mirror of
				https://github.com/KokaKiwi/BarInsta
				synced 2025-10-31 11:35:34 +00:00 
			
		
		
		
	Merge branch 'master' into dm-notifications-enhancements
This commit is contained in:
		
						commit
						605f15ee3a
					
				| @ -42,6 +42,15 @@ | ||||
|         "bug" | ||||
|       ] | ||||
|     }, | ||||
|     { | ||||
|       "login": "MeLlamoPablo", | ||||
|       "name": "Pablo Rodríguez", | ||||
|       "avatar_url": "https://avatars.githubusercontent.com/u/11708035?v=4", | ||||
|       "profile": "https://github.com/MeLlamoPablo", | ||||
|       "contributions": [ | ||||
|         "code" | ||||
|       ] | ||||
|     }, | ||||
|     { | ||||
|       "login": "AwaisKing", | ||||
|       "name": "AWAiS", | ||||
| @ -55,7 +64,7 @@ | ||||
|       "login": "snajdovski", | ||||
|       "name": "Stefan Najdovski", | ||||
|       "avatar_url": "https://avatars2.githubusercontent.com/u/42580385?v=4", | ||||
|       "profile": "https://stefannajdovski.com/", | ||||
|       "profile": "https://snajdovski.github.io", | ||||
|       "contributions": [ | ||||
|         "design", | ||||
|         "translation" | ||||
|  | ||||
							
								
								
									
										19
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										19
									
								
								README.md
									
									
									
									
									
								
							| @ -9,7 +9,7 @@ | ||||
| [](http://makeapullrequest.com) | ||||
| [](./LICENSE) | ||||
| [](https://GitHub.com/austinhuang0131/barinsta/stargazers/)<!-- ALL-CONTRIBUTORS-BADGE:START - Do not remove or modify this section --> | ||||
| [](#contributors) | ||||
| [](#contributors) | ||||
| <!-- ALL-CONTRIBUTORS-BADGE:END --> | ||||
| 
 | ||||
| Instagram client; previously known as InstaGrabber. | ||||
| @ -57,51 +57,52 @@ Prominent contributors are listed here in the [all-contributors](https://allcont | ||||
|     <td align="center"><a href="https://austinhuang.me"><img src="https://avatars1.githubusercontent.com/u/16656689?s=100" width="100px;" alt=""/><br /><sub><b>Austin Huang</b></sub></a><br /><a href="https://github.com/austinhuang0131/barinsta/commits?author=austinhuang0131" title="Code">💻</a> <a href="https://github.com/austinhuang0131/barinsta/commits?author=austinhuang0131" title="Documentation">📖</a> <a href="#question-austinhuang0131" title="Answering Questions">💬</a> <a href="https://crowdin.com/project/instagrabber" title="Translation">🌍</a> <a href="#ideas-austinhuang0131" title="Ideas, Planning, & Feedback">🤔</a></td> | ||||
|     <td align="center"><a href="https://github.com/ammargitham"><img src="https://avatars0.githubusercontent.com/u/8017365?s=100" width="100px;" alt=""/><br /><sub><b>Ammar Githam</b></sub></a><br /><a href="https://github.com/austinhuang0131/barinsta/commits?author=ammargitham" title="Code">💻</a> <a href="#design-ammargitham" title="Design">🎨</a> <a href="#ideas-ammargitham" title="Ideas, Planning, & Feedback">🤔</a> <a href="#maintenance-ammargitham" title="Maintenance">🚧</a> <a href="#question-ammargitham" title="Answering Questions">💬</a></td> | ||||
|     <td align="center"><a href="https://github.com/andersonvom"><img src="https://avatars3.githubusercontent.com/u/69922?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Anderson Mesquita</b></sub></a><br /><a href="https://github.com/austinhuang0131/barinsta/commits?author=andersonvom" title="Code">💻</a> <a href="https://github.com/austinhuang0131/barinsta/issues?q=author%3Aandersonvom" title="Bug reports">🐛</a></td> | ||||
|     <td align="center"><a href="https://github.com/MeLlamoPablo"><img src="https://avatars.githubusercontent.com/u/11708035?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Pablo Rodríguez</b></sub></a><br /><a href="https://github.com/austinhuang0131/barinsta/commits?author=MeLlamoPablo" title="Code">💻</a></td> | ||||
|     <td align="center"><a href="http://rerolledgeek.blogspot.com/"><img src="https://avatars3.githubusercontent.com/u/5278488?s=100" width="100px;" alt=""/><br /><sub><b>AWAiS</b></sub></a><br /><a href="https://github.com/austinhuang0131/barinsta/commits?author=AwaisKing" title="Code">💻</a></td> | ||||
|     <td align="center"><a href="https://stefannajdovski.com/"><img src="https://avatars2.githubusercontent.com/u/42580385?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Stefan Najdovski</b></sub></a><br /><a href="#design-snajdovski" title="Design">🎨</a> <a href="https://crowdin.com/project/instagrabber" title="Translation">🌍</a></td> | ||||
|     <td align="center"><a href="https://github.com/CrazyMarvin"><img src="https://avatars3.githubusercontent.com/u/15004217?v=4?s=100" width="100px;" alt=""/><br /><sub><b>CrazyMarvin</b></sub></a><br /><a href="#financial-CrazyMarvin" title="Financial">💵</a></td> | ||||
|     <td align="center"><a href="https://snajdovski.github.io"><img src="https://avatars2.githubusercontent.com/u/42580385?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Stefan Najdovski</b></sub></a><br /><a href="#design-snajdovski" title="Design">🎨</a> <a href="https://crowdin.com/project/instagrabber" title="Translation">🌍</a></td> | ||||
|   </tr> | ||||
|   <tr> | ||||
|     <td align="center"><a href="https://github.com/CrazyMarvin"><img src="https://avatars3.githubusercontent.com/u/15004217?v=4?s=100" width="100px;" alt=""/><br /><sub><b>CrazyMarvin</b></sub></a><br /><a href="#financial-CrazyMarvin" title="Financial">💵</a></td> | ||||
|     <td align="center"><a href="http://kevinthomas.dev"><img src="https://avatars2.githubusercontent.com/u/15370181?s=100" width="100px;" alt=""/><br /><sub><b>Kevin Thomas</b></sub></a><br /><a href="#financial-KevinNThomas" title="Financial">💵</a></td> | ||||
|     <td align="center"><a href="https://github.com/Shadowspear123"><img src="https://avatars1.githubusercontent.com/u/50462281?s=100" width="100px;" alt=""/><br /><sub><b>Shadowspear123</b></sub></a><br /><a href="#blog-Shadowspear123" title="Blogposts">📝</a> <a href="https://github.com/austinhuang0131/barinsta/issues?q=author%3AShadowspear123" title="Bug reports">🐛</a> <a href="#ideas-Shadowspear123" title="Ideas, Planning, & Feedback">🤔</a> <a href="#question-Shadowspear123" title="Answering Questions">💬</a></td> | ||||
|     <td align="center"><a href="https://github.com/RickyM7"><img src="https://avatars3.githubusercontent.com/u/24703825?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Ricardo</b></sub></a><br /><a href="https://github.com/austinhuang0131/barinsta/issues?q=author%3ARickyM7" title="Bug reports">🐛</a> <a href="https://crowdin.com/project/instagrabber" title="Translation">🌍</a></td> | ||||
|     <td align="center"><a href="https://airikr.me/"><img src="https://avatars0.githubusercontent.com/u/53869451?s=100" width="100px;" alt=""/><br /><sub><b>Airikr</b></sub></a><br /><a href="#ideas-e-edgren" title="Ideas, Planning, & Feedback">🤔</a> <a href="#question-e-edgren" title="Answering Questions">💬</a></td> | ||||
|     <td align="center"><a href="https://github.com/Akrai"><img src="https://avatars1.githubusercontent.com/u/5624597?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Akrai</b></sub></a><br /><a href="#ideas-Akrai" title="Ideas, Planning, & Feedback">🤔</a> <a href="https://crowdin.com/project/instagrabber" title="Translation">🌍</a></td> | ||||
|     <td align="center"><a href="https://github.com/avtkal"><img src="https://avatars.githubusercontent.com/u/63205014?v=4?s=100" width="100px;" alt=""/><br /><sub><b>avtkal</b></sub></a><br /><a href="https://crowdin.com/project/instagrabber" title="Translation">🌍</a></td> | ||||
|   </tr> | ||||
|   <tr> | ||||
|     <td align="center"><a href="https://github.com/avtkal"><img src="https://avatars.githubusercontent.com/u/63205014?v=4?s=100" width="100px;" alt=""/><br /><sub><b>avtkal</b></sub></a><br /><a href="https://crowdin.com/project/instagrabber" title="Translation">🌍</a></td> | ||||
|     <td align="center"><a href="https://github.com/cizordj"><img src="https://avatars2.githubusercontent.com/u/32869222?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Cézar Augusto</b></sub></a><br /><a href="https://crowdin.com/project/instagrabber" title="Translation">🌍</a></td> | ||||
|     <td align="center"><a href="https://github.com/dimitrist19"><img src="https://avatars.githubusercontent.com/u/56406468?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Dimitris T</b></sub></a><br /><a href="https://crowdin.com/project/instagrabber" title="Translation">🌍</a></td> | ||||
|     <td align="center"><a href="https://github.com/farzadx"><img src="https://avatars2.githubusercontent.com/u/70059397?v=4?s=100" width="100px;" alt=""/><br /><sub><b>farzadx</b></sub></a><br /><a href="https://crowdin.com/project/instagrabber" title="Translation">🌍</a></td> | ||||
|     <td align="center"><a href="https://github.com/faydin"><img src="https://avatars2.githubusercontent.com/u/22706676?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Fatih Aydın</b></sub></a><br /><a href="https://crowdin.com/project/instagrabber" title="Translation">🌍</a></td> | ||||
|     <td align="center"><a href="https://github.com/fouze555"><img src="https://avatars3.githubusercontent.com/u/71935341?v=4?s=100" width="100px;" alt=""/><br /><sub><b>fouze555</b></sub></a><br /><a href="https://crowdin.com/project/instagrabber" title="Translation">🌍</a></td> | ||||
|     <td align="center"><a href="https://github.com/Galang23"><img src="https://avatars3.githubusercontent.com/u/13700948?s=100" width="100px;" alt=""/><br /><sub><b>Galang23</b></sub></a><br /><a href="https://crowdin.com/project/instagrabber" title="Translation">🌍</a></td> | ||||
|   </tr> | ||||
|   <tr> | ||||
|     <td align="center"><a href="https://github.com/Galang23"><img src="https://avatars3.githubusercontent.com/u/13700948?s=100" width="100px;" alt=""/><br /><sub><b>Galang23</b></sub></a><br /><a href="https://crowdin.com/project/instagrabber" title="Translation">🌍</a></td> | ||||
|     <td align="center"><a href="https://github.com/initdebugs"><img src="https://avatars0.githubusercontent.com/u/75781464?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Initdebugs</b></sub></a><br /><a href="https://crowdin.com/project/instagrabber" title="Translation">🌍</a></td> | ||||
|     <td align="center"><a href="https://janek.xyz/"><img src="https://avatars3.githubusercontent.com/u/8365659?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Jakub Janek</b></sub></a><br /><a href="https://crowdin.com/project/instagrabber" title="Translation">🌍</a></td> | ||||
|     <td align="center"><a href="https://github.com/GenosseFlosse"><img src="https://avatars.githubusercontent.com/u/59205524?v=4?s=100" width="100px;" alt=""/><br /><sub><b>GenosseFlosse</b></sub></a><br /><a href="https://crowdin.com/project/instagrabber" title="Translation">🌍</a></td> | ||||
|     <td align="center"><a href="https://becauseofprog.fr/"><img src="https://avatars3.githubusercontent.com/u/24623168?s=100" width="100px;" alt=""/><br /><sub><b>kernoeb</b></sub></a><br /><a href="https://crowdin.com/project/instagrabber" title="Translation">🌍</a></td> | ||||
|     <td align="center"><a href="https://github.com/MoaufmKlo"><img src="https://avatars1.githubusercontent.com/u/45636897?s=100" width="100px;" alt=""/><br /><sub><b>MoaufmKlo</b></sub></a><br /><a href="https://crowdin.com/project/instagrabber" title="Translation">🌍</a></td> | ||||
|     <td align="center"><a href="https://github.com/nalinalini"><img src="https://avatars0.githubusercontent.com/u/65640431?v=4?s=100" width="100px;" alt=""/><br /><sub><b>nalinalini</b></sub></a><br /><a href="https://crowdin.com/project/instagrabber" title="Translation">🌍</a></td> | ||||
|   </tr> | ||||
|   <tr> | ||||
|     <td align="center"><a href="https://github.com/nalinalini"><img src="https://avatars0.githubusercontent.com/u/65640431?v=4?s=100" width="100px;" alt=""/><br /><sub><b>nalinalini</b></sub></a><br /><a href="https://crowdin.com/project/instagrabber" title="Translation">🌍</a></td> | ||||
|     <td align="center"><a href="https://github.com/peterge1998"><img src="https://avatars2.githubusercontent.com/u/47355238?s=100" width="100px;" alt=""/><br /><sub><b>peterge1998</b></sub></a><br /><a href="https://crowdin.com/project/instagrabber" title="Translation">🌍</a></td> | ||||
|     <td align="center"><a href="https://github.com/PierreM0"><img src="https://avatars3.githubusercontent.com/u/71077853?v=4?s=100" width="100px;" alt=""/><br /><sub><b>PierreM0</b></sub></a><br /><a href="https://crowdin.com/project/instagrabber" title="Translation">🌍</a></td> | ||||
|     <td align="center"><a href="https://github.com/RAMAR-RAR"><img src="https://avatars3.githubusercontent.com/u/47423745?s=100" width="100px;" alt=""/><br /><sub><b>RAMAR-RAR</b></sub></a><br /><a href="https://crowdin.com/project/instagrabber" title="Translation">🌍</a></td> | ||||
|     <td align="center"><a href="https://github.com/rohang02"><img src="https://avatars3.githubusercontent.com/u/47921164?v=4?s=100" width="100px;" alt=""/><br /><sub><b>rohang02</b></sub></a><br /><a href="https://crowdin.com/project/instagrabber" title="Translation">🌍</a></td> | ||||
|     <td align="center"><a href="https://github.com/retiolus"><img src="https://avatars1.githubusercontent.com/u/65604466?v=4?s=100" width="100px;" alt=""/><br /><sub><b>retiolus</b></sub></a><br /><a href="https://crowdin.com/project/instagrabber" title="Translation">🌍</a></td> | ||||
|     <td align="center"><a href="https://github.com/rikishi0071"><img src="https://avatars3.githubusercontent.com/u/18183855?v=4?s=100" width="100px;" alt=""/><br /><sub><b>rikishi0071</b></sub></a><br /><a href="https://crowdin.com/project/instagrabber" title="Translation">🌍</a></td> | ||||
|   </tr> | ||||
|   <tr> | ||||
|     <td align="center"><a href="https://github.com/rikishi0071"><img src="https://avatars3.githubusercontent.com/u/18183855?v=4?s=100" width="100px;" alt=""/><br /><sub><b>rikishi0071</b></sub></a><br /><a href="https://crowdin.com/project/instagrabber" title="Translation">🌍</a></td> | ||||
|     <td align="center"><a href="https://gitlab.com/sandboiii"><img src="https://avatars.githubusercontent.com/u/17468894?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Alexey Peschany</b></sub></a><br /><a href="https://crowdin.com/project/instagrabber" title="Translation">🌍</a></td> | ||||
|     <td align="center"><a href="https://stillu.cc/"><img src="https://avatars2.githubusercontent.com/u/5843208?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Still Hsu</b></sub></a><br /><a href="https://crowdin.com/project/instagrabber" title="Translation">🌍</a></td> | ||||
|     <td align="center"><a href="https://github.com/Lego8486"><img src="https://avatars1.githubusercontent.com/u/47414485?s=100" width="100px;" alt=""/><br /><sub><b>Ten_Lego</b></sub></a><br /><a href="https://crowdin.com/project/instagrabber" title="Translation">🌍</a></td> | ||||
|     <td align="center"><a href="https://github.com/wagnim"><img src="https://avatars0.githubusercontent.com/u/30241419?s=100" width="100px;" alt=""/><br /><sub><b>wagnim</b></sub></a><br /><a href="https://crowdin.com/project/instagrabber" title="Translation">🌍</a></td> | ||||
|     <td align="center"><a href="https://github.com/wokija"><img src="https://avatars.githubusercontent.com/u/14982166?v=4?s=100" width="100px;" alt=""/><br /><sub><b>wokija</b></sub></a><br /><a href="https://crowdin.com/project/instagrabber" title="Translation">🌍</a></td> | ||||
|     <td align="center"><a href="https://github.com/ysakamoto"><img src="https://avatars3.githubusercontent.com/u/1331642?v=4?s=100" width="100px;" alt=""/><br /><sub><b>ysakamoto</b></sub></a><br /><a href="https://crowdin.com/project/instagrabber" title="Translation">🌍</a></td> | ||||
|   </tr> | ||||
|   <tr> | ||||
|     <td align="center"><a href="https://github.com/ysakamoto"><img src="https://avatars3.githubusercontent.com/u/1331642?v=4?s=100" width="100px;" alt=""/><br /><sub><b>ysakamoto</b></sub></a><br /><a href="https://crowdin.com/project/instagrabber" title="Translation">🌍</a></td> | ||||
|     <td align="center"><a href="https://github.com/ZDVokoun"><img src="https://avatars.githubusercontent.com/u/76393152?v=4?s=100" width="100px;" alt=""/><br /><sub><b>ZDVokoun</b></sub></a><br /><a href="https://crowdin.com/project/instagrabber" title="Translation">🌍</a></td> | ||||
|   </tr> | ||||
| </table> | ||||
| @ -131,7 +132,7 @@ This app's predecessor, InstaGrabber, was originally made by [@AwaisKing](https: | ||||
|     You should have received a copy of the GNU General Public License | ||||
|     along with this program.  If not, see <https://www.gnu.org/licenses/>. | ||||
| 
 | ||||
| Logo by [Stefan Najdovski](https://stefannajdovski.com/). Used under license. | ||||
| Logo by [Stefan Najdovski](https://snajdovski.github.io/). Used under license. | ||||
| 
 | ||||
| [](https://snyk.io/test/github/austinhuang0131/barinsta) | ||||
| [](https://lgtm.com/projects/g/austinhuang0131/barinsta) | ||||
|  | ||||
| @ -10,8 +10,8 @@ android { | ||||
|         minSdkVersion 21 | ||||
|         targetSdkVersion 29 | ||||
| 
 | ||||
|         versionCode 58 | ||||
|         versionName '19.1.0-a1' | ||||
|         versionCode 59 | ||||
|         versionName '19.1.0-a2' | ||||
| 
 | ||||
|         multiDexEnabled true | ||||
| 
 | ||||
|  | ||||
| @ -14,13 +14,11 @@ import java.util.List; | ||||
| 
 | ||||
| import awais.instagrabber.adapters.viewholder.NotificationViewHolder; | ||||
| import awais.instagrabber.databinding.ItemNotificationBinding; | ||||
| import awais.instagrabber.interfaces.MentionClickListener; | ||||
| import awais.instagrabber.models.NotificationModel; | ||||
| import awais.instagrabber.models.enums.NotificationType; | ||||
| 
 | ||||
| public final class NotificationsAdapter extends ListAdapter<NotificationModel, NotificationViewHolder> { | ||||
|     private final OnNotificationClickListener notificationClickListener; | ||||
|     private final MentionClickListener mentionClickListener; | ||||
| 
 | ||||
|     private static final DiffUtil.ItemCallback<NotificationModel> DIFF_CALLBACK = new DiffUtil.ItemCallback<NotificationModel>() { | ||||
|         @Override | ||||
| @ -34,11 +32,9 @@ public final class NotificationsAdapter extends ListAdapter<NotificationModel, N | ||||
|         } | ||||
|     }; | ||||
| 
 | ||||
|     public NotificationsAdapter(final OnNotificationClickListener notificationClickListener, | ||||
|                                 final MentionClickListener mentionClickListener) { | ||||
|     public NotificationsAdapter(final OnNotificationClickListener notificationClickListener) { | ||||
|         super(DIFF_CALLBACK); | ||||
|         this.notificationClickListener = notificationClickListener; | ||||
|         this.mentionClickListener = mentionClickListener; | ||||
|     } | ||||
| 
 | ||||
|     @NonNull | ||||
|  | ||||
| @ -32,7 +32,7 @@ public final class NotificationViewHolder extends RecyclerView.ViewHolder { | ||||
|                 text = R.string.comment_notif; | ||||
|                 subtext = model.getText(); | ||||
|                 break; | ||||
|             case MENTION: | ||||
|             case COMMENT_MENTION: | ||||
|                 text = R.string.mention_notif; | ||||
|                 subtext = model.getText(); | ||||
|                 break; | ||||
|  | ||||
| @ -1,205 +0,0 @@ | ||||
| package awais.instagrabber.customviews; | ||||
| 
 | ||||
| import android.annotation.SuppressLint; | ||||
| import android.content.Context; | ||||
| import android.graphics.RectF; | ||||
| import android.os.Handler; | ||||
| import android.text.Layout; | ||||
| import android.text.Selection; | ||||
| import android.text.Spannable; | ||||
| import android.text.SpannableString; | ||||
| import android.text.SpannableStringBuilder; | ||||
| import android.text.Spanned; | ||||
| import android.text.style.BackgroundColorSpan; | ||||
| import android.text.style.ClickableSpan; | ||||
| import android.text.style.URLSpan; | ||||
| import android.util.AttributeSet; | ||||
| import android.view.MotionEvent; | ||||
| import android.view.ViewConfiguration; | ||||
| import android.widget.TextView; | ||||
| 
 | ||||
| import androidx.annotation.NonNull; | ||||
| import androidx.annotation.Nullable; | ||||
| import androidx.appcompat.widget.AppCompatTextView; | ||||
| 
 | ||||
| import awais.instagrabber.R; | ||||
| import awais.instagrabber.interfaces.MentionClickListener; | ||||
| import awais.instagrabber.utils.TextUtils; | ||||
| 
 | ||||
| @Deprecated | ||||
| public final class RamboTextView extends AppCompatTextView { | ||||
|     private static final String TAG = "RamboTextView"; | ||||
|     private static final int highlightBackgroundSpanKey = R.id.tvComment; | ||||
|     private static final RectF touchedLineBounds = new RectF(); | ||||
|     private ClickableSpan clickableSpanUnderTouchOnActionDown; | ||||
|     private MentionClickListener mentionClickListener; | ||||
|     private boolean isUrlHighlighted; | ||||
|     private boolean isExpanded; | ||||
|     private OnLongClickListener longClickListener; | ||||
| 
 | ||||
|     private final Handler handler = new Handler(); | ||||
|     private final Runnable longPressRunnable = () -> { | ||||
|         if (longClickListener != null) longClickListener.onLongClick(this); | ||||
|     }; | ||||
| 
 | ||||
|     public RamboTextView(final Context context) { | ||||
|         super(context); | ||||
|     } | ||||
| 
 | ||||
|     public RamboTextView(final Context context, final AttributeSet attrs) { | ||||
|         super(context, attrs); | ||||
|     } | ||||
| 
 | ||||
|     public RamboTextView(final Context context, final AttributeSet attrs, final int defStyleAttr) { | ||||
|         super(context, attrs, defStyleAttr); | ||||
|     } | ||||
| 
 | ||||
|     public void setMentionClickListener(final MentionClickListener mentionClickListener) { | ||||
|         this.mentionClickListener = mentionClickListener; | ||||
|     } | ||||
| 
 | ||||
|     // public void setCaptionIsExpandable(final boolean isExpandable) { | ||||
|     //     this.isExpandable = isExpandable; | ||||
|     // } | ||||
| 
 | ||||
|     // public void setCaptionIsExpanded(final boolean isExpanded) { | ||||
|     //     this.isExpanded = isExpanded; | ||||
|     // } | ||||
| 
 | ||||
|     @Override | ||||
|     public void setOnLongClickListener(@Nullable final OnLongClickListener l) { | ||||
|         if (l == null) return; | ||||
|         this.longClickListener = l; | ||||
|     } | ||||
| 
 | ||||
|     @SuppressLint("ClickableViewAccessibility") | ||||
|     @Override | ||||
|     public boolean onTouchEvent(final MotionEvent event) { | ||||
|         final CharSequence text = getText(); | ||||
|         if (text instanceof SpannableString || text instanceof SpannableStringBuilder) { | ||||
|             final Spannable spanText = (Spannable) text; | ||||
|             final ClickableSpan clickableSpanUnderTouch = findClickableSpanUnderTouch(this, spanText, event); | ||||
| 
 | ||||
|             final int action = event.getAction(); | ||||
| 
 | ||||
|             if (action == MotionEvent.ACTION_DOWN) clickableSpanUnderTouchOnActionDown = clickableSpanUnderTouch; | ||||
|             final boolean touchStartedOverAClickableSpan = clickableSpanUnderTouchOnActionDown != null; | ||||
|             final boolean isURLSpan = clickableSpanUnderTouch instanceof URLSpan; | ||||
| 
 | ||||
|             // feed view caption hacks | ||||
|             // if (isExpandable && !touchStartedOverAClickableSpan) | ||||
|             //     return !isExpanded | super.onTouchEvent(event); // short operator, because we want two shits to work | ||||
| 
 | ||||
|             // final Object tag = getTag(); | ||||
|             // final FeedModel feedModel = tag instanceof FeedModel ? (FeedModel) tag : null; | ||||
| 
 | ||||
|             switch (action) { | ||||
|                 case MotionEvent.ACTION_DOWN: | ||||
|                     final int longPressTimeout = ViewConfiguration.getLongPressTimeout(); | ||||
|                     handler.postDelayed(longPressRunnable, longPressTimeout); | ||||
|                     // if (feedModel != null) feedModel.setMentionClicked(false); | ||||
|                     if (clickableSpanUnderTouch != null) { | ||||
|                         highlightUrl(clickableSpanUnderTouch, spanText); | ||||
|                     } | ||||
|                     return super.onTouchEvent(event); | ||||
|                 case MotionEvent.ACTION_UP: | ||||
|                     handler.removeCallbacks(longPressRunnable); | ||||
|                     if (touchStartedOverAClickableSpan && clickableSpanUnderTouch == clickableSpanUnderTouchOnActionDown) { | ||||
|                         dispatchUrlClick(spanText, clickableSpanUnderTouch); | ||||
|                         // if (feedModel != null) feedModel.setMentionClicked(true); | ||||
|                     } | ||||
|                     cleanupOnTouchUp(spanText); | ||||
|                     return super.onTouchEvent(event); | ||||
|                 case MotionEvent.ACTION_MOVE: | ||||
|                     // handler.removeCallbacks(longPressRunnable); | ||||
|                     // if (feedModel != null) feedModel.setMentionClicked(false); | ||||
|                     if (clickableSpanUnderTouch != null) highlightUrl(clickableSpanUnderTouch, spanText); | ||||
|                     else removeUrlHighlightColor(spanText); | ||||
|                     return super.onTouchEvent(event); | ||||
|                 case MotionEvent.ACTION_CANCEL: | ||||
|                     handler.removeCallbacks(longPressRunnable); | ||||
|                     // if (feedModel != null) feedModel.setMentionClicked(false); | ||||
|                     cleanupOnTouchUp(spanText); | ||||
|                     return super.onTouchEvent(event); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         return super.onTouchEvent(event); | ||||
|     } | ||||
| 
 | ||||
|     protected void dispatchUrlClick(final Spanned s, final ClickableSpan clickableSpan) { | ||||
|         if (mentionClickListener != null) { | ||||
|             final int spanStart = s.getSpanStart(clickableSpan); | ||||
|             final boolean ishHashtag = s.charAt(spanStart) == '#'; | ||||
| 
 | ||||
|             final int start = ishHashtag || s.charAt(spanStart) != '@' ? spanStart : spanStart + 1; | ||||
| 
 | ||||
|             CharSequence subSequence = s.subSequence(start, s.getSpanEnd(clickableSpan)); | ||||
| 
 | ||||
|             // for feed ellipsize | ||||
|             final int indexOfEllipsize = TextUtils.indexOfChar(subSequence, '…', 0); | ||||
|             if (indexOfEllipsize != -1) | ||||
|                 subSequence = subSequence.subSequence(0, indexOfEllipsize - 1); | ||||
| 
 | ||||
|             mentionClickListener.onClick(this, subSequence.toString(), ishHashtag, false); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     protected void highlightUrl(final ClickableSpan clickableSpan, final Spannable text) { | ||||
|         if (!isUrlHighlighted) { | ||||
|             isUrlHighlighted = true; | ||||
| 
 | ||||
|             final int spanStart = text.getSpanStart(clickableSpan); | ||||
|             final int spanEnd = text.getSpanEnd(clickableSpan); | ||||
|             final BackgroundColorSpan highlightSpan = new BackgroundColorSpan(getHighlightColor()); | ||||
|             text.setSpan(highlightSpan, spanStart, spanEnd, Spannable.SPAN_INCLUSIVE_INCLUSIVE); | ||||
|             setTag(highlightBackgroundSpanKey, highlightSpan); | ||||
|             Selection.setSelection(text, spanStart, spanEnd); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     protected void removeUrlHighlightColor(final Spannable text) { | ||||
|         if (isUrlHighlighted) { | ||||
|             isUrlHighlighted = false; | ||||
| 
 | ||||
|             final BackgroundColorSpan highlightSpan = (BackgroundColorSpan) getTag(highlightBackgroundSpanKey); | ||||
|             text.removeSpan(highlightSpan); | ||||
| 
 | ||||
|             Selection.removeSelection(text); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     private void cleanupOnTouchUp(final Spannable text) { | ||||
|         clickableSpanUnderTouchOnActionDown = null; | ||||
|         removeUrlHighlightColor(text); | ||||
|     } | ||||
| 
 | ||||
|     @Nullable | ||||
|     private static ClickableSpan findClickableSpanUnderTouch(@NonNull final TextView textView, | ||||
|                                                              final Spanned text, | ||||
|                                                              @NonNull final MotionEvent event) { | ||||
|         final int touchX = (int) (event.getX() - textView.getTotalPaddingLeft() + textView.getScrollX()); | ||||
|         final int touchY = (int) (event.getY() - textView.getTotalPaddingTop() + textView.getScrollY()); | ||||
| 
 | ||||
|         final Layout layout = textView.getLayout(); | ||||
|         final int touchedLine = layout.getLineForVertical(touchY); | ||||
|         final int touchOffset = layout.getOffsetForHorizontal(touchedLine, touchX); | ||||
| 
 | ||||
|         touchedLineBounds.left = layout.getLineLeft(touchedLine); | ||||
|         touchedLineBounds.top = layout.getLineTop(touchedLine); | ||||
|         touchedLineBounds.right = layout.getLineWidth(touchedLine) + touchedLineBounds.left; | ||||
|         touchedLineBounds.bottom = layout.getLineBottom(touchedLine); | ||||
| 
 | ||||
|         if (touchedLineBounds.contains(touchX, touchY)) { | ||||
|             final Object[] spans = text.getSpans(touchOffset, touchOffset, ClickableSpan.class); | ||||
|             for (final Object span : spans) | ||||
|                 if (span instanceof ClickableSpan) return (ClickableSpan) span; | ||||
|         } | ||||
| 
 | ||||
|         return null; | ||||
|     } | ||||
| 
 | ||||
|     public boolean isCaptionExpanded() { | ||||
|         return isExpanded; | ||||
|     } | ||||
| } | ||||
| @ -33,7 +33,6 @@ import awais.instagrabber.asyncs.NotificationsFetcher; | ||||
| import awais.instagrabber.databinding.FragmentNotificationsViewerBinding; | ||||
| import awais.instagrabber.fragments.settings.MorePreferencesFragmentDirections; | ||||
| import awais.instagrabber.interfaces.FetchListener; | ||||
| import awais.instagrabber.interfaces.MentionClickListener; | ||||
| import awais.instagrabber.models.NotificationModel; | ||||
| import awais.instagrabber.models.enums.NotificationType; | ||||
| import awais.instagrabber.repositories.requests.StoryViewerOptions; | ||||
| @ -145,33 +144,8 @@ public final class NotificationsViewerFragment extends Fragment implements Swipe | ||||
|                                     } | ||||
|                                 }); | ||||
|                                 return; | ||||
|                             } else if (model.getType() == NotificationType.RESPONDED_STORY) { | ||||
|                                 final NavDirections action = NotificationsViewerFragmentDirections | ||||
|                                         .actionNotificationsViewerFragmentToStoryViewerFragment(StoryViewerOptions.forStory(model.getPostId(), | ||||
|                                                                                                                             model.getUsername())); | ||||
|                                 NavHostFragment.findNavController(NotificationsViewerFragment.this).navigate(action); | ||||
|                                 return; | ||||
|                             } | ||||
|                             final AlertDialog alertDialog = new AlertDialog.Builder(context) | ||||
|                                     .setCancelable(false) | ||||
|                                     .setView(R.layout.dialog_opening_post) | ||||
|                                     .create(); | ||||
|                             alertDialog.show(); | ||||
|                             mediaService.fetch(model.getPostId(), new ServiceCallback<Media>() { | ||||
|                                 @Override | ||||
|                                 public void onSuccess(final Media feedModel) { | ||||
|                                     final PostViewV2Fragment fragment = PostViewV2Fragment | ||||
|                                             .builder(feedModel) | ||||
|                                             .build(); | ||||
|                                     fragment.setOnShowListener(dialog1 -> alertDialog.dismiss()); | ||||
|                                     fragment.show(getChildFragmentManager(), "post_view"); | ||||
|                                 } | ||||
| 
 | ||||
|                                 @Override | ||||
|                                 public void onFailure(final Throwable t) { | ||||
|                                     Toast.makeText(context, R.string.downloader_unknown_error, Toast.LENGTH_SHORT).show(); | ||||
|                                 } | ||||
|                             }); | ||||
|                             clickListener.onPreviewClick(model); | ||||
|                             break; | ||||
|                         case 2: | ||||
|                             friendshipService.ignore(model.getUserId(), new ServiceCallback<FriendshipChangeResponse>() { | ||||
| @ -196,16 +170,6 @@ public final class NotificationsViewerFragment extends Fragment implements Swipe | ||||
|             } | ||||
|         } | ||||
|     }; | ||||
|     private final MentionClickListener mentionClickListener = (view, text, isHashtag, isLocation) -> { | ||||
|         if (getContext() == null) return; | ||||
|         new AlertDialog.Builder(getContext()) | ||||
|                 .setTitle(text) | ||||
|                 .setMessage(isHashtag ? R.string.comment_view_mention_hash_search | ||||
|                                       : R.string.comment_view_mention_user_search) | ||||
|                 .setNegativeButton(R.string.cancel, null) | ||||
|                 .setPositiveButton(R.string.ok, (dialog, which) -> openProfile(text)) | ||||
|                 .show(); | ||||
|     }; | ||||
| 
 | ||||
|     @Override | ||||
|     public void onCreate(@Nullable final Bundle savedInstanceState) { | ||||
| @ -250,7 +214,7 @@ public final class NotificationsViewerFragment extends Fragment implements Swipe | ||||
|         CookieUtils.setupCookies(settingsHelper.getString(Constants.COOKIE)); | ||||
|         binding.swipeRefreshLayout.setOnRefreshListener(this); | ||||
|         notificationViewModel = new ViewModelProvider(this).get(NotificationViewModel.class); | ||||
|         final NotificationsAdapter adapter = new NotificationsAdapter(clickListener, mentionClickListener); | ||||
|         final NotificationsAdapter adapter = new NotificationsAdapter(clickListener); | ||||
|         binding.rvComments.setLayoutManager(new LinearLayoutManager(context)); | ||||
|         binding.rvComments.setAdapter(adapter); | ||||
|         notificationViewModel.getList().observe(getViewLifecycleOwner(), adapter::submitList); | ||||
|  | ||||
| @ -817,7 +817,7 @@ public class PostViewV2Fragment extends SharedElementTransitionDialogFragment im | ||||
|     } | ||||
| 
 | ||||
|     private void setupCaption(final Caption caption) { | ||||
|         if (caption == null) { | ||||
|         if (caption == null || TextUtils.isEmpty(caption.getText())) { | ||||
|             binding.caption.setVisibility(View.GONE); | ||||
|             binding.translate.setVisibility(View.GONE); | ||||
|             binding.captionToggle.setVisibility(View.GONE); | ||||
|  | ||||
| @ -709,7 +709,7 @@ public class ProfileFragment extends Fragment implements SwipeRefreshLayout.OnRe | ||||
|                                                                                                                            .trim())); | ||||
|             profileDetailsBinding.mainBiography | ||||
|                     .addOnURLClickListener(autoLinkItem -> Utils.openURL(getContext(), autoLinkItem.getOriginalText().trim())); | ||||
|             profileDetailsBinding.mainBiography.setOnClickListener(v -> { | ||||
|             profileDetailsBinding.mainBiography.setOnLongClickListener(v -> { | ||||
|                 String[] commentDialogList; | ||||
|                 if (!TextUtils.isEmpty(cookie)) { | ||||
|                     commentDialogList = new String[]{ | ||||
| @ -753,9 +753,6 @@ public class ProfileFragment extends Fragment implements SwipeRefreshLayout.OnRe | ||||
|                         }) | ||||
|                         .setNegativeButton(R.string.cancel, null) | ||||
|                         .show(); | ||||
|             }); | ||||
|             profileDetailsBinding.mainBiography.setOnLongClickListener(v -> { | ||||
|                 Utils.copyText(context, biography); | ||||
|                 return true; | ||||
|             }); | ||||
|         } | ||||
|  | ||||
| @ -1,11 +0,0 @@ | ||||
| package awais.instagrabber.interfaces; | ||||
| 
 | ||||
| import awais.instagrabber.customviews.RamboTextView; | ||||
| 
 | ||||
| @Deprecated | ||||
| public interface MentionClickListener { | ||||
|     void onClick(final RamboTextView view, | ||||
|                  final String text, | ||||
|                  final boolean isHashtag, | ||||
|                  final boolean isLocation); | ||||
| } | ||||
| @ -9,7 +9,7 @@ public enum NotificationType implements Serializable { | ||||
|     LIKE("GraphLikeAggregatedStory"), | ||||
|     FOLLOW("GraphFollowAggregatedStory"), | ||||
|     COMMENT("GraphCommentMediaStory"), | ||||
|     MENTION("GraphMentionStory"), | ||||
|     COMMENT_MENTION("GraphMentionStory"), | ||||
|     TAGGED("GraphUserTaggedStory"), | ||||
|     // app story_type | ||||
|     COMMENT_LIKE("13"), | ||||
|  | ||||
| @ -17,7 +17,7 @@ public class StoryReplyBroadcastOptions extends BroadcastOptions { | ||||
|                                       final String reelId) | ||||
|             throws UnsupportedEncodingException { | ||||
|         super(clientContext, threadIdOrUserIds, BroadcastItemType.REELSHARE); | ||||
|         this.text = TextUtils.encode(text); | ||||
|         this.text = text; | ||||
|         this.mediaId = mediaId; | ||||
|         this.reelId = reelId; // or user id, usually same | ||||
|     } | ||||
|  | ||||
| @ -104,18 +104,6 @@ public final class TextUtils { | ||||
|         return (int) ((d2 - d1) / DateUtils.DAY_IN_MILLIS); | ||||
|     } | ||||
| 
 | ||||
|     @NonNull | ||||
|     public static String encode(final String text) throws UnsupportedEncodingException { | ||||
|         return URLEncoder.encode(text, "UTF-8") | ||||
|                          .replaceAll("\\+", "%20") | ||||
|                          .replaceAll("%21", "!") | ||||
|                          .replaceAll("%27", "'") | ||||
|                          .replaceAll("%28", "(") | ||||
|                          .replaceAll("%29", ")") | ||||
|                          .replaceAll("%7E", "~") | ||||
|                          .replaceAll("%0A", "\n"); | ||||
|     } | ||||
| 
 | ||||
|     public static List<String> extractUrls(final String text) { | ||||
|         if (isEmpty(text)) return Collections.emptyList(); | ||||
|         final Matcher matcher = Patterns.WEB_URL.matcher(text); | ||||
|  | ||||
| @ -18,8 +18,8 @@ public class UserAgentUtils { | ||||
|             "Mozilla/5.0 (Macintosh; Intel Mac OS X 11_1) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0.2 Safari/605.1.15" | ||||
|     }; | ||||
|     // use APKpure, assume x86 | ||||
|     private static final String igVersion = "175.1.0.25.119"; | ||||
|     private static final String igVersionCode = "273907115"; | ||||
|     private static final String igVersion = "177.0.0.30.119"; | ||||
|     private static final String igVersionCode = "276028050"; | ||||
|     // only pick the ones that has width 1440 for maximum download quality | ||||
|     public static final String[] devices = { | ||||
|             // https://github.com/dilame/instagram-private-api/blob/master/src/samples/devices.json | ||||
|  | ||||
| @ -131,7 +131,7 @@ public class NewsService extends BaseService { | ||||
|                                     user.getLong("id"), | ||||
|                                     user.getString("username"), | ||||
|                                     user.getString("profile_pic_url"), | ||||
|                                     data.has("media") ? data.getJSONObject("media").getLong("id") : 0, | ||||
|                                     !data.isNull("media") ? Long.valueOf(data.getJSONObject("media").getString("id").split("_")[0]) : 0, | ||||
|                                     data.has("media") ? data.getJSONObject("media").getString("thumbnail_src") : null, | ||||
|                                     notificationType)); | ||||
|                         } | ||||
|  | ||||
| @ -45,11 +45,11 @@ | ||||
|         app:layout_constraintTop_toTopOf="parent" | ||||
|         tools:text="username" /> | ||||
| 
 | ||||
|     <awais.instagrabber.customviews.RamboTextView | ||||
|     <androidx.appcompat.widget.AppCompatTextView | ||||
|         android:id="@+id/tvComment" | ||||
|         android:layout_width="0dp" | ||||
|         android:layout_height="wrap_content" | ||||
|         android:linksClickable="true" | ||||
|         android:linksClickable="false" | ||||
|         android:paddingStart="16dp" | ||||
|         android:paddingLeft="16dp" | ||||
|         android:paddingEnd="16dp" | ||||
| @ -62,13 +62,13 @@ | ||||
|         app:layout_constraintTop_toBottomOf="@id/tvUsername" | ||||
|         tools:text="comment comment comment comment comment comment comment comment comment comment comment comment comment " /> | ||||
| 
 | ||||
|     <awais.instagrabber.customviews.RamboTextView | ||||
|     <androidx.appcompat.widget.AppCompatTextView | ||||
|         android:id="@+id/tvSubComment" | ||||
|         android:layout_width="0dp" | ||||
|         android:layout_height="wrap_content" | ||||
|         android:autoLink="web|email" | ||||
|         android:ellipsize="end" | ||||
|         android:linksClickable="true" | ||||
|         android:linksClickable="false" | ||||
|         android:paddingStart="16dp" | ||||
|         android:paddingLeft="16dp" | ||||
|         android:paddingEnd="8dp" | ||||
|  | ||||
| @ -96,16 +96,13 @@ | ||||
|         app:layout_constraintTop_toBottomOf="@id/locationFullName" | ||||
|         tools:text="IN THE MIDDLE OF OUR STREET" /> | ||||
| 
 | ||||
|     <awais.instagrabber.customviews.RamboTextView | ||||
|     <awais.instagrabber.customviews.RamboTextViewV2 | ||||
|         android:id="@+id/locationUrl" | ||||
|         android:layout_width="0dp" | ||||
|         android:layout_width="match_parent" | ||||
|         android:layout_height="wrap_content" | ||||
|         android:layout_below="@id/locationBiography" | ||||
|         android:layout_below="@id/mainBiography" | ||||
|         android:ellipsize="marquee" | ||||
|         android:paddingStart="8dp" | ||||
|         android:paddingLeft="8dp" | ||||
|         android:paddingEnd="8dp" | ||||
|         android:paddingRight="8dp" | ||||
|         android:padding="8dp" | ||||
|         android:textAppearance="@style/TextAppearance.AppCompat.Body1" | ||||
|         android:visibility="gone" | ||||
|         app:layout_constraintBottom_toBottomOf="parent" | ||||
| @ -113,5 +110,7 @@ | ||||
|         app:layout_constraintStart_toStartOf="parent" | ||||
|         app:layout_constraintTop_toBottomOf="@id/locationBiography" | ||||
|         tools:text="https://austinhuang.me/" | ||||
|         tools:textColor="@android:color/holo_blue_dark" | ||||
|         tools:visibility="visible" /> | ||||
| 
 | ||||
| </androidx.constraintlayout.widget.ConstraintLayout> | ||||
| @ -12,8 +12,7 @@ | ||||
|     <string name="clipboard_error">Error copying text</string> | ||||
|     <string name="clipboard_copied">Copied to clipboard!</string> | ||||
|     <string name="report">Report</string> | ||||
|     <string name="password">Password (Max 32 chars)</string> | ||||
|     <string name="set_password">Set a password (max 32 chars)</string> | ||||
|     <string name="set_password">Protect file with password</string> | ||||
|     <string name="password_no_max">Password</string> | ||||
|     <string name="ok">OK</string> | ||||
|     <string name="yes">Yes</string> | ||||
| @ -319,9 +318,9 @@ | ||||
|     <string name="locations">Locations</string> | ||||
|     <string name="unknown">Unknown</string> | ||||
|     <string name="removed_from_favs">Removed from Favourites</string> | ||||
|     <string name="backup_and_restore">Backup & Restore User Settings</string> | ||||
|     <string name="backup_summary">Back up app settings, account login information, and/or favorites data to a plain text or encrypted backup file for later restoration.</string> | ||||
|     <string name="backup_warning">If you\'re backing up login info, treat the file as confidential: Keep them somewhere safe!</string> | ||||
|     <string name="backup_and_restore">Backup & Restore</string> | ||||
|     <string name="backup_summary">Backup Barinsta app settings, account login data, and/or favorites to a plain text or encrypted backup file for later restoration.</string> | ||||
|     <string name="backup_warning">If you\'re backing up account login data, treat the file as confidential and keep it somewhere safe!</string> | ||||
|     <string name="create_backup">Create new backup file</string> | ||||
|     <string name="restore_backup">Restore from existing backup file</string> | ||||
|     <string name="file_chosen_label">File:</string> | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user