diff options
39 files changed, 593 insertions, 530 deletions
diff --git a/app/build.gradle b/app/build.gradle index 86e49619..63dec2b3 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -6,8 +6,8 @@ android { applicationId "ml.docilealligator.infinityforreddit" minSdkVersion 21 targetSdkVersion 30 - versionCode 84 - versionName "5.1.0" + versionCode 85 + versionName "5.1.1" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" javaCompileOptions { annotationProcessorOptions { diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 1a7707e6..6852e8a5 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -25,7 +25,7 @@ <uses-permission android:name="android.permission.WAKE_LOCK" /> <application - android:name=".Infinity" + android:name="ml.docilealligator.infinityforreddit.Infinity" android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/application_name" diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/SaveMemoryCenterInisdeDownsampleStrategy.java b/app/src/main/java/ml/docilealligator/infinityforreddit/SaveMemoryCenterInisdeDownsampleStrategy.java new file mode 100644 index 00000000..8516c53e --- /dev/null +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/SaveMemoryCenterInisdeDownsampleStrategy.java @@ -0,0 +1,29 @@ +package ml.docilealligator.infinityforreddit; + +import com.bumptech.glide.load.resource.bitmap.DownsampleStrategy; + +public class SaveMemoryCenterInisdeDownsampleStrategy extends DownsampleStrategy { + + @Override + public float getScaleFactor(int sourceWidth, int sourceHeight, int requestedWidth, int requestedHeight) { + int originalSourceWidth = sourceWidth; + int originalSourceHeight = sourceHeight; + if (sourceWidth * sourceHeight > 5_000_000) { + int divisor = 2; + do { + sourceWidth /= divisor; + sourceHeight /= divisor; + } while (sourceWidth * sourceHeight > 5_000_000); + } + + float widthPercentage = (float) requestedWidth / (float) sourceWidth; + float heightPercentage = (float) requestedHeight / (float) sourceHeight; + + return Math.min((float) sourceWidth / (float) originalSourceWidth, (float) sourceHeight / (float) originalSourceHeight) * Math.min(1.f, Math.min(widthPercentage, heightPercentage)); + } + + @Override + public SampleSizeRounding getSampleSizeRounding(int sourceWidth, int sourceHeight, int requestedWidth, int requestedHeight) { + return SampleSizeRounding.MEMORY; + } +} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/activities/BaseActivity.java b/app/src/main/java/ml/docilealligator/infinityforreddit/activities/BaseActivity.java index 13f40f63..ad840efa 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/activities/BaseActivity.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/activities/BaseActivity.java @@ -129,10 +129,10 @@ public abstract class BaseActivity extends AppCompatActivity { } } - boolean userDefinedChangeSatusBarIconColorInImmersiveInterface = + boolean userDefinedChangeStatusBarIconColorInImmersiveInterface = customThemeWrapper.isChangeStatusBarIconColorAfterToolbarCollapsedInImmersiveInterface(); if (immersiveInterface && isImmersiveInterfaceApplicable) { - changeStatusBarIconColor = userDefinedChangeSatusBarIconColorInImmersiveInterface; + changeStatusBarIconColor = userDefinedChangeStatusBarIconColorInImmersiveInterface; } else { changeStatusBarIconColor = false; } diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/activities/CommentActivity.java b/app/src/main/java/ml/docilealligator/infinityforreddit/activities/CommentActivity.java index ffb9173b..7680f2fd 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/activities/CommentActivity.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/activities/CommentActivity.java @@ -72,7 +72,7 @@ import ml.docilealligator.infinityforreddit.customtheme.CustomThemeWrapper; import ml.docilealligator.infinityforreddit.customviews.LinearLayoutManagerBugFixed; import ml.docilealligator.infinityforreddit.events.SwitchAccountEvent; import ml.docilealligator.infinityforreddit.utils.SharedPreferencesUtils; -import ml.docilealligator.infinityforreddit.utils.SuperscriptInlineProcessor; +import ml.docilealligator.infinityforreddit.markdown.SuperscriptInlineProcessor; import ml.docilealligator.infinityforreddit.utils.Utils; import retrofit2.Retrofit; diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/activities/EditCommentActivity.java b/app/src/main/java/ml/docilealligator/infinityforreddit/activities/EditCommentActivity.java index cb03370b..4f4b81ec 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/activities/EditCommentActivity.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/activities/EditCommentActivity.java @@ -132,7 +132,7 @@ public class EditCommentActivity extends BaseActivity implements UploadImageEnab mFullName = getIntent().getStringExtra(EXTRA_FULLNAME); mAccessToken = mCurrentAccountSharedPreferences.getString(SharedPreferencesUtils.ACCESS_TOKEN, null); - mCommentContent = getIntent().getStringExtra(EXTRA_CONTENT).replaceAll(">",">"); + mCommentContent = getIntent().getStringExtra(EXTRA_CONTENT); contentEditText.setText(mCommentContent); if (savedInstanceState != null) { diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/activities/EditPostActivity.java b/app/src/main/java/ml/docilealligator/infinityforreddit/activities/EditPostActivity.java index 16e91ebc..0d22d9b3 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/activities/EditPostActivity.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/activities/EditPostActivity.java @@ -141,7 +141,7 @@ public class EditPostActivity extends BaseActivity implements UploadImageEnabled mFullName = getIntent().getStringExtra(EXTRA_FULLNAME); mAccessToken = mCurrentAccountSharedPreferences.getString(SharedPreferencesUtils.ACCESS_TOKEN, null); titleTextView.setText(getIntent().getStringExtra(EXTRA_TITLE)); - mPostContent = getIntent().getStringExtra(EXTRA_CONTENT).replaceAll(">",">");; + mPostContent = getIntent().getStringExtra(EXTRA_CONTENT); contentEditText.setText(mPostContent); if (savedInstanceState != null) { diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/activities/FullMarkdownActivity.java b/app/src/main/java/ml/docilealligator/infinityforreddit/activities/FullMarkdownActivity.java index 32a5f452..acd1713c 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/activities/FullMarkdownActivity.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/activities/FullMarkdownActivity.java @@ -61,8 +61,10 @@ import ml.docilealligator.infinityforreddit.customtheme.CustomThemeWrapper; import ml.docilealligator.infinityforreddit.customviews.LinearLayoutManagerBugFixed; import ml.docilealligator.infinityforreddit.customviews.MarkwonLinearLayoutManager; import ml.docilealligator.infinityforreddit.events.SwitchAccountEvent; +import ml.docilealligator.infinityforreddit.markdown.SpoilerParserPlugin; +import ml.docilealligator.infinityforreddit.markdown.SpoilerSpan; import ml.docilealligator.infinityforreddit.utils.SharedPreferencesUtils; -import ml.docilealligator.infinityforreddit.utils.SuperscriptInlineProcessor; +import ml.docilealligator.infinityforreddit.markdown.SuperscriptInlineProcessor; import ml.docilealligator.infinityforreddit.utils.Utils; public class FullMarkdownActivity extends BaseActivity { @@ -150,51 +152,6 @@ public class FullMarkdownActivity extends BaseActivity { public String processMarkdown(@NonNull String markdown) { return super.processMarkdown(Utils.fixSuperScript(markdown)); } - - @Override - public void afterSetText(@NonNull TextView textView) { - textView.setHighlightColor(Color.TRANSPARENT); - SpannableStringBuilder markdownStringBuilder = new SpannableStringBuilder(textView.getText()); - Pattern spoilerPattern = Pattern.compile(">![\\S\\s]+?!<"); - Matcher matcher = spoilerPattern.matcher(markdownStringBuilder); - int start = 0; - boolean find = false; - while (matcher.find(start)) { - if (markdownStringBuilder.length() < 4 - || matcher.start() < 0 - || matcher.end() > markdownStringBuilder.length()) { - break; - } - find = true; - markdownStringBuilder.delete(matcher.end() - 2, matcher.end()); - markdownStringBuilder.delete(matcher.start(), matcher.start() + 2); - ClickableSpan clickableSpan = new ClickableSpan() { - private boolean isShowing = false; - @Override - public void updateDrawState(@NonNull TextPaint ds) { - if (isShowing) { - super.updateDrawState(ds); - ds.setColor(markdownColor); - } else { - ds.bgColor = spoilerBackgroundColor; - ds.setColor(markdownColor); - } - ds.setUnderlineText(false); - } - - @Override - public void onClick(@NonNull View view) { - isShowing = !isShowing; - view.invalidate(); - } - }; - markdownStringBuilder.setSpan(clickableSpan, matcher.start(), matcher.end() - 4, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); - start = matcher.end() - 4; - } - if (find) { - textView.setText(markdownStringBuilder); - } - } @Override public void beforeSetText(@NonNull TextView textView, @NonNull Spanned markdown) { @@ -217,6 +174,7 @@ public class FullMarkdownActivity extends BaseActivity { builder.linkColor(linkColor); } }) + .usePlugin(SpoilerParserPlugin.create(markdownColor, spoilerBackgroundColor)) .usePlugin(StrikethroughPlugin.create()) .usePlugin(LinkifyPlugin.create(Linkify.WEB_URLS)) .usePlugin(TableEntryPlugin.create(this)) diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/activities/MainActivity.java b/app/src/main/java/ml/docilealligator/infinityforreddit/activities/MainActivity.java index 30d134fe..990fbe83 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/activities/MainActivity.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/activities/MainActivity.java @@ -38,7 +38,6 @@ import androidx.drawerlayout.widget.DrawerLayout; import androidx.fragment.app.Fragment; import androidx.fragment.app.FragmentActivity; import androidx.fragment.app.FragmentManager; -import androidx.lifecycle.Observer; import androidx.lifecycle.ViewModelProvider; import androidx.recyclerview.widget.RecyclerView; import androidx.viewpager2.adapter.FragmentStateAdapter; @@ -270,9 +269,6 @@ public class MainActivity extends BaseActivity implements SortTypeSelectionCallb if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { drawer.setFitsSystemWindows(false); getWindow().setDecorFitsSystemWindows(false); - /*drawer.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE | - View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | - View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION);*/ } else { window.setFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS, WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS); } @@ -855,51 +851,37 @@ public class MainActivity extends BaseActivity implements SortTypeSelectionCallb tabLayout.setTabMode(TabLayout.MODE_FIXED); } new TabLayoutMediator(tabLayout, viewPager2, (tab, position) -> { - if (mAccessToken == null) { - switch (position) { - case 0: - tab.setText(R.string.home); - break; - case 1: - tab.setText(R.string.popular); - break; - case 2: - tab.setText(R.string.all); - break; - } - } else { - switch (position) { - case 0: - tab.setText(mMainActivityTabsSharedPreferences.getString((mAccountName == null ? "" : mAccountName) + SharedPreferencesUtils.MAIN_PAGE_TAB_1_TITLE, getString(R.string.home))); - break; - case 1: - tab.setText(mMainActivityTabsSharedPreferences.getString((mAccountName == null ? "" : mAccountName) + SharedPreferencesUtils.MAIN_PAGE_TAB_2_TITLE, getString(R.string.popular))); - break; - case 2: - tab.setText(mMainActivityTabsSharedPreferences.getString((mAccountName == null ? "" : mAccountName) + SharedPreferencesUtils.MAIN_PAGE_TAB_3_TITLE, getString(R.string.all))); - break; - } - if (position >= tabCount && (mShowFavoriteMultiReddits || mShowMultiReddits || - mShowFavoriteSubscribedSubreddits || mShowSubscribedSubreddits) - && sectionsPagerAdapter != null) { - if (position - tabCount < sectionsPagerAdapter.favoriteMultiReddits.size()) { - tab.setText(sectionsPagerAdapter.favoriteMultiReddits.get(position - tabCount).getName()); - } else if (position - tabCount - sectionsPagerAdapter.favoriteMultiReddits.size() < sectionsPagerAdapter.multiReddits.size()) { - tab.setText(sectionsPagerAdapter.multiReddits.get(position - tabCount - - sectionsPagerAdapter.favoriteMultiReddits.size()).getName()); - } else if (position - tabCount - sectionsPagerAdapter.favoriteMultiReddits.size() - - sectionsPagerAdapter.multiReddits.size() < sectionsPagerAdapter.favoriteSubscribedSubreddits.size()) { - tab.setText(sectionsPagerAdapter.favoriteSubscribedSubreddits.get(position - tabCount - - sectionsPagerAdapter.favoriteMultiReddits.size() - - sectionsPagerAdapter.multiReddits.size()).getName()); - } else if (position - tabCount - sectionsPagerAdapter.favoriteMultiReddits.size() + switch (position) { + case 0: + tab.setText(mMainActivityTabsSharedPreferences.getString((mAccountName == null ? "" : mAccountName) + SharedPreferencesUtils.MAIN_PAGE_TAB_1_TITLE, getString(R.string.home))); + break; + case 1: + tab.setText(mMainActivityTabsSharedPreferences.getString((mAccountName == null ? "" : mAccountName) + SharedPreferencesUtils.MAIN_PAGE_TAB_2_TITLE, getString(R.string.popular))); + break; + case 2: + tab.setText(mMainActivityTabsSharedPreferences.getString((mAccountName == null ? "" : mAccountName) + SharedPreferencesUtils.MAIN_PAGE_TAB_3_TITLE, getString(R.string.all))); + break; + } + if (position >= tabCount && (mShowFavoriteMultiReddits || mShowMultiReddits || + mShowFavoriteSubscribedSubreddits || mShowSubscribedSubreddits) + && sectionsPagerAdapter != null) { + if (position - tabCount < sectionsPagerAdapter.favoriteMultiReddits.size()) { + tab.setText(sectionsPagerAdapter.favoriteMultiReddits.get(position - tabCount).getName()); + } else if (position - tabCount - sectionsPagerAdapter.favoriteMultiReddits.size() < sectionsPagerAdapter.multiReddits.size()) { + tab.setText(sectionsPagerAdapter.multiReddits.get(position - tabCount + - sectionsPagerAdapter.favoriteMultiReddits.size()).getName()); + } else if (position - tabCount - sectionsPagerAdapter.favoriteMultiReddits.size() + - sectionsPagerAdapter.multiReddits.size() < sectionsPagerAdapter.favoriteSubscribedSubreddits.size()) { + tab.setText(sectionsPagerAdapter.favoriteSubscribedSubreddits.get(position - tabCount + - sectionsPagerAdapter.favoriteMultiReddits.size() + - sectionsPagerAdapter.multiReddits.size()).getName()); + } else if (position - tabCount - sectionsPagerAdapter.favoriteMultiReddits.size() + - sectionsPagerAdapter.multiReddits.size() + - sectionsPagerAdapter.favoriteSubscribedSubreddits.size() < sectionsPagerAdapter.subscribedSubreddits.size()) { + tab.setText(sectionsPagerAdapter.subscribedSubreddits.get(position - tabCount + - sectionsPagerAdapter.favoriteMultiReddits.size() - sectionsPagerAdapter.multiReddits.size() - - sectionsPagerAdapter.favoriteSubscribedSubreddits.size() < sectionsPagerAdapter.subscribedSubreddits.size()) { - tab.setText(sectionsPagerAdapter.subscribedSubreddits.get(position - tabCount - - sectionsPagerAdapter.favoriteMultiReddits.size() - - sectionsPagerAdapter.multiReddits.size() - - sectionsPagerAdapter.favoriteSubscribedSubreddits.size()).getName()); - } + - sectionsPagerAdapter.favoriteSubscribedSubreddits.size()).getName()); } } }).attach(); @@ -925,7 +907,7 @@ public class MainActivity extends BaseActivity implements SortTypeSelectionCallb loadSubscriptions(); multiRedditViewModel = new ViewModelProvider(this, new MultiRedditViewModel.Factory(getApplication(), - mRedditDataRoomDatabase, mAccountName)) + mRedditDataRoomDatabase, mAccountName == null ? "-" : mAccountName)) .get(MultiRedditViewModel.class); multiRedditViewModel.getAllFavoriteMultiReddits().observe(this, multiReddits -> { @@ -934,17 +916,14 @@ public class MainActivity extends BaseActivity implements SortTypeSelectionCallb } }); - multiRedditViewModel.getAllMultiReddits().observe(this, new Observer<List<MultiReddit>>() { - @Override - public void onChanged(List<MultiReddit> multiReddits) { - if (mShowMultiReddits && sectionsPagerAdapter != null) { - sectionsPagerAdapter.setMultiReddits(multiReddits); - } + multiRedditViewModel.getAllMultiReddits().observe(this, multiReddits -> { + if (mShowMultiReddits && sectionsPagerAdapter != null) { + sectionsPagerAdapter.setMultiReddits(multiReddits); } }); subscribedSubredditViewModel = new ViewModelProvider(this, - new SubscribedSubredditViewModel.Factory(getApplication(), mRedditDataRoomDatabase, mAccountName)) + new SubscribedSubredditViewModel.Factory(getApplication(), mRedditDataRoomDatabase, mAccountName == null ? "-" : mAccountName)) .get(SubscribedSubredditViewModel.class); subscribedSubredditViewModel.getAllSubscribedSubreddits().observe(this, subscribedSubredditData -> { @@ -1696,9 +1675,6 @@ public class MainActivity extends BaseActivity implements SortTypeSelectionCallb @Override public int getItemCount() { - if (mAccessToken == null) { - return 3; - } return tabCount + favoriteMultiReddits.size() + multiReddits.size() + favoriteSubscribedSubreddits.size() + subscribedSubreddits.size(); } diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/activities/TrendingActivity.java b/app/src/main/java/ml/docilealligator/infinityforreddit/activities/TrendingActivity.java index 7057b1ad..039688fb 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/activities/TrendingActivity.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/activities/TrendingActivity.java @@ -22,6 +22,7 @@ import androidx.recyclerview.widget.RecyclerView; import androidx.swiperefreshlayout.widget.SwipeRefreshLayout; import com.bumptech.glide.Glide; +import com.bumptech.glide.RequestManager; import com.google.android.material.appbar.AppBarLayout; import com.google.android.material.appbar.CollapsingToolbarLayout; import com.r0adkll.slidr.Slidr; @@ -100,10 +101,10 @@ public class TrendingActivity extends BaseActivity { @Inject Executor mExecutor; private String mAccessToken; - private String mAccountName; private boolean isRefreshing = false; private ArrayList<TrendingSearch> trendingSearches; private TrendingSearchRecyclerViewAdapter adapter; + private RequestManager mGlide; @Override protected void onCreate(Bundle savedInstanceState) { @@ -151,7 +152,8 @@ public class TrendingActivity extends BaseActivity { setToolbarGoToTop(toolbar); mAccessToken = mCurrentAccountSharedPreferences.getString(SharedPreferencesUtils.ACCESS_TOKEN, null); - mAccountName = mCurrentAccountSharedPreferences.getString(SharedPreferencesUtils.ACCOUNT_NAME, null); + + mGlide = Glide.with(this); DisplayMetrics displayMetrics = new DisplayMetrics(); getWindowManager().getDefaultDisplay().getMetrics(displayMetrics); @@ -277,7 +279,7 @@ public class TrendingActivity extends BaseActivity { private void showErrorView(int stringId) { errorLinearLayout.setVisibility(View.VISIBLE); - Glide.with(this).load(R.drawable.error_image).into(errorImageView); + mGlide.load(R.drawable.error_image).into(errorImageView); errorTextView.setText(stringId); } diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/activities/ViewVideoActivity.java b/app/src/main/java/ml/docilealligator/infinityforreddit/activities/ViewVideoActivity.java index 548e7c53..d70aaa68 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/activities/ViewVideoActivity.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/activities/ViewVideoActivity.java @@ -1,6 +1,12 @@ package ml.docilealligator.infinityforreddit.activities; +import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_AUTO_BATTERY; +import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM; +import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_NO; +import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_YES; + import android.Manifest; +import android.app.AlertDialog; import android.content.Intent; import android.content.SharedPreferences; import android.content.pm.ActivityInfo; @@ -32,6 +38,7 @@ import android.widget.Toast; import androidx.annotation.NonNull; import androidx.appcompat.app.ActionBar; import androidx.appcompat.app.AppCompatActivity; +import androidx.appcompat.app.AppCompatDelegate; import androidx.coordinatorlayout.widget.CoordinatorLayout; import androidx.core.app.ActivityCompat; import androidx.core.content.ContextCompat; @@ -79,6 +86,7 @@ import ml.docilealligator.infinityforreddit.Infinity; import ml.docilealligator.infinityforreddit.R; import ml.docilealligator.infinityforreddit.apis.VReddIt; import ml.docilealligator.infinityforreddit.bottomsheetfragments.PlaybackSpeedBottomSheetFragment; +import ml.docilealligator.infinityforreddit.customtheme.CustomThemeWrapper; import ml.docilealligator.infinityforreddit.font.ContentFontFamily; import ml.docilealligator.infinityforreddit.font.ContentFontStyle; import ml.docilealligator.infinityforreddit.font.FontFamily; @@ -150,6 +158,8 @@ public class ViewVideoActivity extends AppCompatActivity { TextView titleTextView; @BindView(R.id.download_image_view_exo_playback_control_view) ImageView downloadImageView; + @BindView(R.id.playback_speed_image_view_exo_playback_control_view) + ImageView playbackSpeedImageView; @BindView(R.id.lockable_nested_scroll_view_view_video_activity) LockableNestedScrollView nestedScrollView; @@ -195,6 +205,9 @@ public class ViewVideoActivity extends AppCompatActivity { SharedPreferences mSharedPreferences; @Inject + CustomThemeWrapper mCustomThemeWrapper; + + @Inject Executor mExecutor; @Inject @@ -206,7 +219,37 @@ public class ViewVideoActivity extends AppCompatActivity { ((Infinity) getApplication()).getAppComponent().inject(this); - getTheme().applyStyle(R.style.Theme_Normal, true); + boolean systemDefault = Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q; + int systemThemeType = Integer.parseInt(mSharedPreferences.getString(SharedPreferencesUtils.THEME_KEY, "2")); + switch (systemThemeType) { + case 0: + AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_NO); + getTheme().applyStyle(R.style.Theme_Normal, true); + break; + case 1: + AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_YES); + if(mSharedPreferences.getBoolean(SharedPreferencesUtils.AMOLED_DARK_KEY, false)) { + getTheme().applyStyle(R.style.Theme_Normal_AmoledDark, true); + } else { + getTheme().applyStyle(R.style.Theme_Normal_NormalDark, true); + } + break; + case 2: + if (systemDefault) { + AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_FOLLOW_SYSTEM); + } else { + AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_AUTO_BATTERY); + } + if((getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK) == Configuration.UI_MODE_NIGHT_NO) { + getTheme().applyStyle(R.style.Theme_Normal, true); + } else { + if(mSharedPreferences.getBoolean(SharedPreferencesUtils.AMOLED_DARK_KEY, false)) { + getTheme().applyStyle(R.style.Theme_Normal_AmoledDark, true); + } else { + getTheme().applyStyle(R.style.Theme_Normal_NormalDark, true); + } + } + } getTheme().applyStyle(FontStyle.valueOf(mSharedPreferences .getString(SharedPreferencesUtils.FONT_SIZE_KEY, FontStyle.Normal.name())).getResId(), true); @@ -250,6 +293,14 @@ public class ViewVideoActivity extends AppCompatActivity { isDownloading = true; requestPermissionAndDownload(); }); + + playbackSpeedImageView.setOnClickListener(view -> { + PlaybackSpeedBottomSheetFragment playbackSpeedBottomSheetFragment = new PlaybackSpeedBottomSheetFragment(); + Bundle bundle = new Bundle(); + bundle.putInt(PlaybackSpeedBottomSheetFragment.EXTRA_PLAYBACK_SPEED, playbackSpeed); + playbackSpeedBottomSheetFragment.setArguments(bundle); + playbackSpeedBottomSheetFragment.show(getSupportFragmentManager(), playbackSpeedBottomSheetFragment.getTag()); + }); } else { ActionBar actionBar = getSupportActionBar(); Drawable upArrow = resources.getDrawable(R.drawable.ic_arrow_back_white_24dp); @@ -520,10 +571,13 @@ public class ViewVideoActivity extends AppCompatActivity { hdButton.setVisibility(View.VISIBLE); hdButton.setOnClickListener(view -> { - TrackSelectionDialogBuilder build = new TrackSelectionDialogBuilder(ViewVideoActivity.this, getString(R.string.select_video_quality), trackSelector, 0); - build.setShowDisableOption(true); - build.setAllowAdaptiveSelections(false); - build.build().show(); + TrackSelectionDialogBuilder builder = new TrackSelectionDialogBuilder(ViewVideoActivity.this, getString(R.string.select_video_quality), trackSelector, 0); + builder.setShowDisableOption(true); + builder.setAllowAdaptiveSelections(false); + AlertDialog alertDialog = builder.build(); + alertDialog.show(); + alertDialog.getButton(AlertDialog.BUTTON_POSITIVE).setTextColor(mCustomThemeWrapper.getPrimaryTextColor()); + alertDialog.getButton(AlertDialog.BUTTON_NEGATIVE).setTextColor(mCustomThemeWrapper.getPrimaryTextColor()); }); } diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/activities/WikiActivity.java b/app/src/main/java/ml/docilealligator/infinityforreddit/activities/WikiActivity.java index 1a353a7f..4568cfe5 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/activities/WikiActivity.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/activities/WikiActivity.java @@ -26,6 +26,7 @@ import androidx.recyclerview.widget.RecyclerView; import androidx.swiperefreshlayout.widget.SwipeRefreshLayout; import com.bumptech.glide.Glide; +import com.bumptech.glide.RequestManager; import com.google.android.material.appbar.AppBarLayout; import com.google.android.material.appbar.CollapsingToolbarLayout; import com.r0adkll.slidr.Slidr; @@ -66,9 +67,11 @@ import ml.docilealligator.infinityforreddit.customtheme.CustomThemeWrapper; import ml.docilealligator.infinityforreddit.customviews.LinearLayoutManagerBugFixed; import ml.docilealligator.infinityforreddit.customviews.MarkwonLinearLayoutManager; import ml.docilealligator.infinityforreddit.events.SwitchAccountEvent; +import ml.docilealligator.infinityforreddit.markdown.SpoilerParserPlugin; +import ml.docilealligator.infinityforreddit.markdown.SpoilerSpan; import ml.docilealligator.infinityforreddit.utils.JSONUtils; import ml.docilealligator.infinityforreddit.utils.SharedPreferencesUtils; -import ml.docilealligator.infinityforreddit.utils.SuperscriptInlineProcessor; +import ml.docilealligator.infinityforreddit.markdown.SuperscriptInlineProcessor; import ml.docilealligator.infinityforreddit.utils.Utils; import retrofit2.Call; import retrofit2.Callback; @@ -113,6 +116,7 @@ public class WikiActivity extends BaseActivity { private Markwon markwon; private MarkwonAdapter markwonAdapter; private boolean isRefreshing = false; + private RequestManager mGlide; @Override protected void onCreate(Bundle savedInstanceState) { @@ -154,6 +158,8 @@ public class WikiActivity extends BaseActivity { } } + mGlide = Glide.with(this); + swipeRefreshLayout.setEnabled(mSharedPreferences.getBoolean(SharedPreferencesUtils.PULL_TO_REFRESH, true)); swipeRefreshLayout.setOnRefreshListener(this::loadWiki); @@ -177,51 +183,6 @@ public class WikiActivity extends BaseActivity { } @Override - public void afterSetText(@NonNull TextView textView) { - textView.setHighlightColor(Color.TRANSPARENT); - SpannableStringBuilder markdownStringBuilder = new SpannableStringBuilder(textView.getText()); - Pattern spoilerPattern = Pattern.compile(">![\\S\\s]+?!<"); - Matcher matcher = spoilerPattern.matcher(markdownStringBuilder); - int start = 0; - boolean find = false; - while (matcher.find(start)) { - if (markdownStringBuilder.length() < 4 - || matcher.start() < 0 - || matcher.end() > markdownStringBuilder.length()) { - break; - } - find = true; - markdownStringBuilder.delete(matcher.end() - 2, matcher.end()); - markdownStringBuilder.delete(matcher.start(), matcher.start() + 2); - ClickableSpan clickableSpan = new ClickableSpan() { - private boolean isShowing = false; - @Override - public void updateDrawState(@NonNull TextPaint ds) { - if (isShowing) { - super.updateDrawState(ds); - ds.setColor(markdownColor); - } else { - ds.bgColor = spoilerBackgroundColor; - ds.setColor(markdownColor); - } - ds.setUnderlineText(false); - } - - @Override - public void onClick(@NonNull View view) { - isShowing = !isShowing; - view.invalidate(); - } - }; - markdownStringBuilder.setSpan(clickableSpan, matcher.start(), matcher.end() - 4, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); - start = matcher.end() - 4; - } - if (find) { - textView.setText(markdownStringBuilder); - } - } - - @Override public void beforeSetText(@NonNull TextView textView, @NonNull Spanned markdown) { textView.setTextColor(markdownColor); } @@ -241,6 +202,7 @@ public class WikiActivity extends BaseActivity { builder.linkColor(linkColor); } }) + .usePlugin(SpoilerParserPlugin.create(markdownColor, spoilerBackgroundColor)) .usePlugin(StrikethroughPlugin.create()) .usePlugin(LinkifyPlugin.create(Linkify.WEB_URLS)) .usePlugin(TableEntryPlugin.create(this)) @@ -328,7 +290,7 @@ public class WikiActivity extends BaseActivity { swipeRefreshLayout.setRefreshing(false); mFetchWikiInfoLinearLayout.setVisibility(View.VISIBLE); mFetchWikiInfoTextView.setText(stringResId); - Glide.with(this).load(R.drawable.error_image).into(mFetchWikiInfoImageView); + mGlide.load(R.drawable.error_image).into(mFetchWikiInfoImageView); } @Override diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/adapters/CommentsListingRecyclerViewAdapter.java b/app/src/main/java/ml/docilealligator/infinityforreddit/adapters/CommentsListingRecyclerViewAdapter.java index 616b9c1b..40bce0d6 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/adapters/CommentsListingRecyclerViewAdapter.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/adapters/CommentsListingRecyclerViewAdapter.java @@ -63,9 +63,11 @@ import ml.docilealligator.infinityforreddit.comment.Comment; import ml.docilealligator.infinityforreddit.customtheme.CustomThemeWrapper; import ml.docilealligator.infinityforreddit.customviews.CommentIndentationView; import ml.docilealligator.infinityforreddit.customviews.SpoilerOnClickTextView; +import ml.docilealligator.infinityforreddit.markdown.SpoilerParserPlugin; +import ml.docilealligator.infinityforreddit.markdown.SpoilerSpan; import ml.docilealligator.infinityforreddit.utils.APIUtils; import ml.docilealligator.infinityforreddit.utils.SharedPreferencesUtils; -import ml.docilealligator.infinityforreddit.utils.SuperscriptInlineProcessor; +import ml.docilealligator.infinityforreddit.markdown.SuperscriptInlineProcessor; import ml.docilealligator.infinityforreddit.utils.Utils; import retrofit2.Retrofit; @@ -137,56 +139,6 @@ public class CommentsListingRecyclerViewAdapter extends PagedListAdapter<Comment } @Override - public void afterSetText(@NonNull TextView textView) { - textView.setHighlightColor(Color.TRANSPARENT); - SpannableStringBuilder markdownStringBuilder = new SpannableStringBuilder(textView.getText()); - Pattern spoilerPattern = Pattern.compile(">![\\S\\s]+?!<"); - Matcher matcher = spoilerPattern.matcher(markdownStringBuilder); - int start = 0; - boolean find = false; - while (matcher.find(start)) { - if (markdownStringBuilder.length() < 4 - || matcher.start() < 0 - || matcher.end() > markdownStringBuilder.length()) { - break; - } - find = true; - markdownStringBuilder.delete(matcher.end() - 2, matcher.end()); - markdownStringBuilder.delete(matcher.start(), matcher.start() + 2); - int matcherStart = matcher.start(); - int matcherEnd = matcher.end(); - ClickableSpan clickableSpan = new ClickableSpan() { - private boolean isShowing = false; - @Override - public void updateDrawState(@NonNull TextPaint ds) { - if (isShowing) { - super.updateDrawState(ds); - ds.setColor(mCommentColor); - } else { - ds.bgColor = commentSpoilerBackgroundColor; - ds.setColor(mCommentColor); - } - ds.setUnderlineText(false); - } - - @Override - public void onClick(@NonNull View view) { - if (textView instanceof SpoilerOnClickTextView) { - ((SpoilerOnClickTextView) textView).setSpoilerOnClick(true); - } - isShowing = !isShowing; - view.invalidate(); - } - }; - markdownStringBuilder.setSpan(clickableSpan, matcherStart, matcherEnd - 4, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); - start = matcherEnd - 4; - } - if (find) { - textView.setText(markdownStringBuilder); - } - } - - @Override public void configureTheme(@NonNull MarkwonTheme.Builder builder) { builder.linkColor(customThemeWrapper.getLinkColor()); } @@ -202,6 +154,7 @@ public class CommentsListingRecyclerViewAdapter extends PagedListAdapter<Comment } }) + .usePlugin(SpoilerParserPlugin.create(mCommentColor, commentSpoilerBackgroundColor)) .usePlugin(LinkifyPlugin.create(Linkify.WEB_URLS)) .usePlugin(StrikethroughPlugin.create()) .build(); diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/adapters/CommentsRecyclerViewAdapter.java b/app/src/main/java/ml/docilealligator/infinityforreddit/adapters/CommentsRecyclerViewAdapter.java index 5bd116ee..6e6d18d5 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/adapters/CommentsRecyclerViewAdapter.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/adapters/CommentsRecyclerViewAdapter.java @@ -9,10 +9,6 @@ import android.graphics.drawable.Drawable; import android.net.Uri; import android.os.Bundle; import android.os.Handler; -import android.text.SpannableStringBuilder; -import android.text.Spanned; -import android.text.TextPaint; -import android.text.style.ClickableSpan; import android.text.util.Linkify; import android.view.LayoutInflater; import android.view.View; @@ -38,8 +34,6 @@ import com.lsjwzh.widget.materialloadingprogressbar.CircleProgressBar; import java.util.ArrayList; import java.util.Locale; import java.util.concurrent.Executor; -import java.util.regex.Matcher; -import java.util.regex.Pattern; import butterknife.BindView; import butterknife.ButterKnife; @@ -50,6 +44,7 @@ import io.noties.markwon.core.MarkwonTheme; import io.noties.markwon.ext.strikethrough.StrikethroughPlugin; import io.noties.markwon.html.HtmlPlugin; import io.noties.markwon.html.tag.SuperScriptHandler; +import io.noties.markwon.inlineparser.BackslashInlineProcessor; import io.noties.markwon.inlineparser.BangInlineProcessor; import io.noties.markwon.inlineparser.HtmlInlineProcessor; import io.noties.markwon.inlineparser.MarkwonInlineParserPlugin; @@ -71,10 +66,11 @@ import ml.docilealligator.infinityforreddit.customtheme.CustomThemeWrapper; import ml.docilealligator.infinityforreddit.customviews.CommentIndentationView; import ml.docilealligator.infinityforreddit.customviews.SpoilerOnClickTextView; import ml.docilealligator.infinityforreddit.fragments.ViewPostDetailFragment; +import ml.docilealligator.infinityforreddit.markdown.SpoilerParserPlugin; +import ml.docilealligator.infinityforreddit.markdown.SuperscriptInlineProcessor; import ml.docilealligator.infinityforreddit.post.Post; import ml.docilealligator.infinityforreddit.utils.APIUtils; import ml.docilealligator.infinityforreddit.utils.SharedPreferencesUtils; -import ml.docilealligator.infinityforreddit.utils.SuperscriptInlineProcessor; import ml.docilealligator.infinityforreddit.utils.Utils; import retrofit2.Retrofit; @@ -182,52 +178,6 @@ public class CommentsRecyclerViewAdapter extends RecyclerView.Adapter<RecyclerVi } @Override - public void afterSetText(@NonNull TextView textView) { - SpannableStringBuilder markdownStringBuilder = new SpannableStringBuilder(textView.getText()); - Pattern spoilerPattern = Pattern.compile(">![\\S\\s]+?!<"); - Matcher matcher = spoilerPattern.matcher(markdownStringBuilder); - int start = 0; - boolean find = false; - while (matcher.find(start)) { - if (markdownStringBuilder.length() < 4 - || matcher.start() < 0 - || matcher.end() > markdownStringBuilder.length()) { - break; - } - find = true; - markdownStringBuilder.delete(matcher.end() - 2, matcher.end()); - markdownStringBuilder.delete(matcher.start(), matcher.start() + 2); - ClickableSpan clickableSpan = new ClickableSpan() { - private boolean isShowing = false; - @Override - public void updateDrawState(@NonNull TextPaint ds) { - if (isShowing) { - super.updateDrawState(ds); - } else { - ds.bgColor = commentSpoilerBackgroundColor; - } - ds.setColor(mCommentTextColor); - ds.setUnderlineText(false); - } - - @Override - public void onClick(@NonNull View view) { - if (textView instanceof SpoilerOnClickTextView) { - ((SpoilerOnClickTextView) textView).setSpoilerOnClick(true); - } - isShowing = !isShowing; - view.invalidate(); - } - }; - markdownStringBuilder.setSpan(clickableSpan, matcher.start(), matcher.end() - 4, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); - start = matcher.end() - 4; - } - if (find) { - textView.setText(markdownStringBuilder); - } - } - - @Override public void configureConfiguration(@NonNull MarkwonConfiguration.Builder builder) { builder.linkResolver((view, link) -> { Intent intent = new Intent(mActivity, LinkResolverActivity.class); @@ -243,6 +193,7 @@ public class CommentsRecyclerViewAdapter extends RecyclerView.Adapter<RecyclerVi builder.linkColor(linkColor); } }) + .usePlugin(SpoilerParserPlugin.create(mCommentTextColor, commentSpoilerBackgroundColor)) .usePlugin(StrikethroughPlugin.create()) .usePlugin(MovementMethodPlugin.create(BetterLinkMovementMethod.newInstance().setOnLinkLongClickListener((textView, url) -> { if (!activity.isDestroyed() && !activity.isFinishing()) { diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/adapters/MessageRecyclerViewAdapter.java b/app/src/main/java/ml/docilealligator/infinityforreddit/adapters/MessageRecyclerViewAdapter.java index 095a36f7..7560aab4 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/adapters/MessageRecyclerViewAdapter.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/adapters/MessageRecyclerViewAdapter.java @@ -46,10 +46,12 @@ import ml.docilealligator.infinityforreddit.activities.LinkResolverActivity; import ml.docilealligator.infinityforreddit.activities.ViewPrivateMessagesActivity; import ml.docilealligator.infinityforreddit.activities.ViewUserDetailActivity; import ml.docilealligator.infinityforreddit.customtheme.CustomThemeWrapper; +import ml.docilealligator.infinityforreddit.markdown.SpoilerParserPlugin; +import ml.docilealligator.infinityforreddit.markdown.SpoilerSpan; import ml.docilealligator.infinityforreddit.message.FetchMessage; import ml.docilealligator.infinityforreddit.message.Message; import ml.docilealligator.infinityforreddit.message.ReadMessage; -import ml.docilealligator.infinityforreddit.utils.SuperscriptInlineProcessor; +import ml.docilealligator.infinityforreddit.markdown.SuperscriptInlineProcessor; import ml.docilealligator.infinityforreddit.utils.Utils; import retrofit2.Retrofit; @@ -121,53 +123,6 @@ public class MessageRecyclerViewAdapter extends PagedListAdapter<Message, Recycl } @Override - public void afterSetText(@NonNull TextView textView) { - textView.setHighlightColor(Color.TRANSPARENT); - SpannableStringBuilder markdownStringBuilder = new SpannableStringBuilder(textView.getText()); - Pattern spoilerPattern = Pattern.compile(">![\\S\\s]+?!<"); - Matcher matcher = spoilerPattern.matcher(markdownStringBuilder); - int start = 0; - boolean find = false; - while (matcher.find(start)) { - if (markdownStringBuilder.length() < 4 - || matcher.start() < 0 - || matcher.end() > markdownStringBuilder.length()) { - break; - } - find = true; - markdownStringBuilder.delete(matcher.end() - 2, matcher.end()); - markdownStringBuilder.delete(matcher.start(), matcher.start() + 2); - int matcherStart = matcher.start(); - int matcherEnd = matcher.end(); - ClickableSpan clickableSpan = new ClickableSpan() { - private boolean isShowing = false; - @Override - public void updateDrawState(@NonNull TextPaint ds) { - if (isShowing) { - super.updateDrawState(ds); - ds.setColor(mSecondaryTextColor); - } else { - ds.bgColor = spoilerBackgroundColor; - ds.setColor(mSecondaryTextColor); - } - ds.setUnderlineText(false); - } - - @Override - public void onClick(@NonNull View view) { - isShowing = !isShowing; - view.invalidate(); - } - }; - markdownStringBuilder.setSpan(clickableSpan, matcherStart, matcherEnd - 4, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); - start = matcherEnd - 4; - } - if (find) { - textView.setText(markdownStringBuilder); - } - } - - @Override public void configureConfiguration(@NonNull MarkwonConfiguration.Builder builder) { builder.linkResolver((view, link) -> { Intent intent = new Intent(mContext, LinkResolverActivity.class); @@ -182,6 +137,7 @@ public class MessageRecyclerViewAdapter extends PagedListAdapter<Message, Recycl builder.linkColor(customThemeWrapper.getLinkColor()); } }) + .usePlugin(SpoilerParserPlugin.create(mSecondaryTextColor, spoilerBackgroundColor)) .usePlugin(StrikethroughPlugin.create()) .usePlugin(LinkifyPlugin.create(Linkify.WEB_URLS)) .build(); diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/adapters/PostDetailRecyclerViewAdapter.java b/app/src/main/java/ml/docilealligator/infinityforreddit/adapters/PostDetailRecyclerViewAdapter.java index 0b2c7f94..1fa45219 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/adapters/PostDetailRecyclerViewAdapter.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/adapters/PostDetailRecyclerViewAdapter.java @@ -87,6 +87,7 @@ import jp.wasabeef.glide.transformations.BlurTransformation; import jp.wasabeef.glide.transformations.RoundedCornersTransformation; import me.saket.bettermovementmethod.BetterLinkMovementMethod; import ml.docilealligator.infinityforreddit.FetchGfycatOrRedgifsVideoLinks; +import ml.docilealligator.infinityforreddit.SaveMemoryCenterInisdeDownsampleStrategy; import ml.docilealligator.infinityforreddit.R; import ml.docilealligator.infinityforreddit.RedditDataRoomDatabase; import ml.docilealligator.infinityforreddit.SaveThing; @@ -110,11 +111,13 @@ import ml.docilealligator.infinityforreddit.customviews.AspectRatioGifImageView; import ml.docilealligator.infinityforreddit.customviews.LinearLayoutManagerBugFixed; import ml.docilealligator.infinityforreddit.customviews.MarkwonLinearLayoutManager; import ml.docilealligator.infinityforreddit.fragments.ViewPostDetailFragment; +import ml.docilealligator.infinityforreddit.markdown.SpoilerParserPlugin; +import ml.docilealligator.infinityforreddit.markdown.SpoilerSpan; import ml.docilealligator.infinityforreddit.post.Post; import ml.docilealligator.infinityforreddit.post.PostPagingSource; import ml.docilealligator.infinityforreddit.utils.APIUtils; import ml.docilealligator.infinityforreddit.utils.SharedPreferencesUtils; -import ml.docilealligator.infinityforreddit.utils.SuperscriptInlineProcessor; +import ml.docilealligator.infinityforreddit.markdown.SuperscriptInlineProcessor; import ml.docilealligator.infinityforreddit.utils.Utils; import pl.droidsonroids.gif.GifImageView; import retrofit2.Retrofit; @@ -140,7 +143,6 @@ public class PostDetailRecyclerViewAdapter extends RecyclerView.Adapter<Recycler private RequestManager mGlide; private Markwon mPostDetailMarkwon; private final MarkwonAdapter mMarkwonAdapter; - private int mImageViewWidth; private String mAccessToken; private String mAccountName; private Post mPost; @@ -209,7 +211,7 @@ public class PostDetailRecyclerViewAdapter extends RecyclerView.Adapter<Recycler Executor executor, CustomThemeWrapper customThemeWrapper, Retrofit retrofit, Retrofit oauthRetrofit, Retrofit gfycatRetrofit, Retrofit redgifsRetrofit, RedditDataRoomDatabase redditDataRoomDatabase, - RequestManager glide, int imageViewWidth, + RequestManager glide, boolean separatePostAndComments, String accessToken, String accountName, Post post, Locale locale, SharedPreferences sharedPreferences, @@ -247,51 +249,6 @@ public class PostDetailRecyclerViewAdapter extends RecyclerView.Adapter<Recycler } @Override - public void afterSetText(@NonNull TextView textView) { - textView.setHighlightColor(Color.TRANSPARENT); - SpannableStringBuilder markdownStringBuilder = new SpannableStringBuilder(textView.getText()); - Pattern spoilerPattern = Pattern.compile(">![\\S\\s]+?!<"); - Matcher matcher = spoilerPattern.matcher(markdownStringBuilder); - int start = 0; - boolean find = false; - while (matcher.find(start)) { - if (markdownStringBuilder.length() < 4 - || matcher.start() < 0 - || matcher.end() > markdownStringBuilder.length()) { - break; - } - find = true; - markdownStringBuilder.delete(matcher.end() - 2, matcher.end()); - markdownStringBuilder.delete(matcher.start(), matcher.start() + 2); - ClickableSpan clickableSpan = new ClickableSpan() { - private boolean isShowing = false; - @Override - public void updateDrawState(@NonNull TextPaint ds) { - if (isShowing) { - super.updateDrawState(ds); - ds.setColor(markdownColor); - } else { - ds.bgColor = postSpoilerBackgroundColor; - ds.setColor(markdownColor); - } - ds.setUnderlineText(false); - } - - @Override - public void onClick(@NonNull View view) { - isShowing = !isShowing; - view.invalidate(); - } - }; - markdownStringBuilder.setSpan(clickableSpan, matcher.start(), matcher.end() - 4, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); - start = matcher.end() - 4; - } - if (find) { - textView.setText(markdownStringBuilder); - } - } - - @Override public void beforeSetText(@NonNull TextView textView, @NonNull Spanned markdown) { textView.setTextColor(markdownColor); textView.setOnLongClickListener(view -> { @@ -323,6 +280,7 @@ public class PostDetailRecyclerViewAdapter extends RecyclerView.Adapter<Recycler builder.linkColor(linkColor); } }) + .usePlugin(SpoilerParserPlugin.create(markdownColor, postSpoilerBackgroundColor)) .usePlugin(StrikethroughPlugin.create()) .usePlugin(MovementMethodPlugin.create(BetterLinkMovementMethod.linkify(Linkify.WEB_URLS, activity).setOnLinkLongClickListener((textView, url) -> { if (activity != null && !activity.isDestroyed() && !activity.isFinishing()) { @@ -342,7 +300,6 @@ public class PostDetailRecyclerViewAdapter extends RecyclerView.Adapter<Recycler .tableLayout(R.layout.adapter_table_block, R.id.table_layout) .textLayoutIsRoot(R.layout.view_table_entry_cell))) .build(); - mImageViewWidth = imageViewWidth; mSeparatePostAndComments = separatePostAndComments; mLegacyAutoplayVideoControllerUI = sharedPreferences.getBoolean(SharedPreferencesUtils.LEGACY_AUTOPLAY_VIDEO_CONTROLLER_UI, false); mAccessToken = accessToken; @@ -676,11 +633,7 @@ public class PostDetailRecyclerViewAdapter extends RecyclerView.Adapter<Recycler Post.Preview preview = getSuitablePreview(mPost.getPreviews()); if (preview != null) { ((PostDetailVideoAutoplayViewHolder) holder).aspectRatioFrameLayout.setAspectRatio((float) preview.getPreviewWidth() / preview.getPreviewHeight()); - if (mImageViewWidth > preview.getPreviewWidth()) { - mGlide.load(preview.getPreviewUrl()).override(preview.getPreviewWidth(), preview.getPreviewHeight()).into(((PostDetailVideoAutoplayViewHolder) holder).previewImageView); - } else { - mGlide.load(preview.getPreviewUrl()).into(((PostDetailVideoAutoplayViewHolder) holder).previewImageView); - } + mGlide.load(preview.getPreviewUrl()).centerInside().downsample(new SaveMemoryCenterInisdeDownsampleStrategy()).into(((PostDetailVideoAutoplayViewHolder) holder).previewImageView); } else { ((PostDetailVideoAutoplayViewHolder) holder).aspectRatioFrameLayout.setAspectRatio(1); } @@ -736,8 +689,6 @@ public class PostDetailRecyclerViewAdapter extends RecyclerView.Adapter<Recycler int height = (int) (400 * mScale); ((PostDetailImageAndGifAutoplayViewHolder) holder).mImageView.setScaleType(ImageView.ScaleType.CENTER_CROP); ((PostDetailImageAndGifAutoplayViewHolder) holder).mImageView.getLayoutParams().height = height; - preview.setPreviewWidth(mImageViewWidth); - preview.setPreviewHeight(height); } else { ((PostDetailImageAndGifAutoplayViewHolder) holder).mImageView.setRatio((float) preview.getPreviewHeight() / (float) preview.getPreviewWidth()); } @@ -854,31 +805,15 @@ public class PostDetailRecyclerViewAdapter extends RecyclerView.Adapter<Recycler previewIndex = 0; } preview = previews.get(previewIndex); - if (preview.getPreviewWidth() * preview.getPreviewHeight() > 10_000_000) { + if (preview.getPreviewWidth() * preview.getPreviewHeight() > 5_000_000) { for (int i = previews.size() - 1; i >= 1; i--) { preview = previews.get(i); - if (mImageViewWidth >= preview.getPreviewWidth()) { - if (preview.getPreviewWidth() * preview.getPreviewHeight() <= 10_000_000) { - return preview; - } - } else { - int height = mImageViewWidth / preview.getPreviewWidth() * preview.getPreviewHeight(); - if (mImageViewWidth * height <= 10_000_000) { - return preview; - } + if (preview.getPreviewWidth() * preview.getPreviewHeight() <= 5_000_000) { + return preview; } } } - if (preview.getPreviewWidth() * preview.getPreviewHeight() > 10_000_000) { - int divisor = 2; - do { - preview.setPreviewWidth(preview.getPreviewWidth() / divisor); - preview.setPreviewHeight(preview.getPreviewHeight() / divisor); - divisor *= 2; - } while (preview.getPreviewWidth() * preview.getPreviewHeight() > 10_000_000); - } - return preview; } @@ -890,7 +825,7 @@ public class PostDetailRecyclerViewAdapter extends RecyclerView.Adapter<Recycler boolean blurImage = (mPost.isNSFW() && mNeedBlurNsfw && !(mDoNotBlurNsfwInNsfwSubreddits && mFragment != null && mFragment.getIsNsfwSubreddit()) && !(mPost.getPostType() == Post.GIF_TYPE && mAutoplayNsfwVideos)) || (mPost.isSpoiler() && mNeedBlurSpoiler); String url = mPost.getPostType() == Post.IMAGE_TYPE || blurImage ? preview.getPreviewUrl() : mPost.getUrl(); RequestBuilder<Drawable> imageRequestBuilder = mGlide.load(url) - .listener(new RequestListener<Drawable>() { + .listener(new RequestListener<>() { @Override public boolean onLoadFailed(@Nullable GlideException e, Object model, Target<Drawable> target, boolean isFirstResource) { ((PostDetailImageAndGifAutoplayViewHolder) holder).mLoadImageProgressBar.setVisibility(View.GONE); @@ -913,15 +848,11 @@ public class PostDetailRecyclerViewAdapter extends RecyclerView.Adapter<Recycler if (blurImage) { imageRequestBuilder.apply(RequestOptions.bitmapTransform(new BlurTransformation(50, 10))).into(((PostDetailImageAndGifAutoplayViewHolder) holder).mImageView); } else { - if (mImageViewWidth > preview.getPreviewWidth()) { - imageRequestBuilder.override(preview.getPreviewWidth(), preview.getPreviewHeight()).into(((PostDetailImageAndGifAutoplayViewHolder) holder).mImageView); - } else { - imageRequestBuilder.into(((PostDetailImageAndGifAutoplayViewHolder) holder).mImageView); - } + imageRequestBuilder.centerInside().downsample(new SaveMemoryCenterInisdeDownsampleStrategy()).into(((PostDetailImageAndGifAutoplayViewHolder) holder).mImageView); } } else if (holder instanceof PostDetailVideoAndGifPreviewHolder) { RequestBuilder<Drawable> imageRequestBuilder = mGlide.load(preview.getPreviewUrl()) - .listener(new RequestListener<Drawable>() { + .listener(new RequestListener<>() { @Override public boolean onLoadFailed(@Nullable GlideException e, Object model, Target<Drawable> target, boolean isFirstResource) { ((PostDetailVideoAndGifPreviewHolder) holder).mLoadImageProgressBar.setVisibility(View.GONE); @@ -945,15 +876,11 @@ public class PostDetailRecyclerViewAdapter extends RecyclerView.Adapter<Recycler imageRequestBuilder.apply(RequestOptions.bitmapTransform(new BlurTransformation(50, 10))) .into(((PostDetailVideoAndGifPreviewHolder) holder).mImageView); } else { - if (mImageViewWidth > preview.getPreviewWidth()) { - imageRequestBuilder.override(preview.getPreviewWidth(), preview.getPreviewHeight()).into(((PostDetailVideoAndGifPreviewHolder) holder).mImageView); - } else { - imageRequestBuilder.into(((PostDetailVideoAndGifPreviewHolder) holder).mImageView); - } + imageRequestBuilder.centerInside().downsample(new SaveMemoryCenterInisdeDownsampleStrategy()).into(((PostDetailVideoAndGifPreviewHolder) holder).mImageView); } } else if (holder instanceof PostDetailLinkViewHolder) { RequestBuilder<Drawable> imageRequestBuilder = mGlide.load(preview.getPreviewUrl()) - .listener(new RequestListener<Drawable>() { + .listener(new RequestListener<>() { @Override public boolean onLoadFailed(@Nullable GlideException e, Object model, Target<Drawable> target, boolean isFirstResource) { ((PostDetailLinkViewHolder) holder).mLoadImageProgressBar.setVisibility(View.GONE); @@ -977,15 +904,11 @@ public class PostDetailRecyclerViewAdapter extends RecyclerView.Adapter<Recycler imageRequestBuilder.apply(RequestOptions.bitmapTransform(new BlurTransformation(50, 10))) .into(((PostDetailLinkViewHolder) holder).mImageView); } else { - if (mImageViewWidth > preview.getPreviewWidth()) { - imageRequestBuilder.override(preview.getPreviewWidth(), preview.getPreviewHeight()).into(((PostDetailLinkViewHolder) holder).mImageView); - } else { - imageRequestBuilder.into(((PostDetailLinkViewHolder) holder).mImageView); - } + imageRequestBuilder.centerInside().downsample(new SaveMemoryCenterInisdeDownsampleStrategy()).into(((PostDetailLinkViewHolder) holder).mImageView); } } else if (holder instanceof PostDetailGalleryViewHolder) { RequestBuilder<Drawable> imageRequestBuilder = mGlide.load(preview.getPreviewUrl()) - .listener(new RequestListener<Drawable>() { + .listener(new RequestListener<>() { @Override public boolean onLoadFailed(@Nullable GlideException e, Object model, Target<Drawable> target, boolean isFirstResource) { ((PostDetailGalleryViewHolder) holder).mLoadImageProgressBar.setVisibility(View.GONE); @@ -1008,11 +931,7 @@ public class PostDetailRecyclerViewAdapter extends RecyclerView.Adapter<Recycler if ((mPost.isNSFW() && mNeedBlurNsfw && !(mDoNotBlurNsfwInNsfwSubreddits && mFragment != null && mFragment.getIsNsfwSubreddit()) && !(mPost.getPostType() == Post.GIF_TYPE && mAutoplayNsfwVideos)) || (mPost.isSpoiler() && mNeedBlurSpoiler)) { imageRequestBuilder.apply(RequestOptions.bitmapTransform(new BlurTransformation(50, 10))).into(((PostDetailGalleryViewHolder) holder).mImageView); } else { - if (mImageViewWidth > preview.getPreviewWidth()) { - imageRequestBuilder.override(preview.getPreviewWidth(), preview.getPreviewHeight()).into(((PostDetailGalleryViewHolder) holder).mImageView); - } else { - imageRequestBuilder.into(((PostDetailGalleryViewHolder) holder).mImageView); - } + imageRequestBuilder.centerInside().downsample(new SaveMemoryCenterInisdeDownsampleStrategy()).into(((PostDetailGalleryViewHolder) holder).mImageView); } } } diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/adapters/PostRecyclerViewAdapter.java b/app/src/main/java/ml/docilealligator/infinityforreddit/adapters/PostRecyclerViewAdapter.java index 2c23649e..a8cf40d2 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/adapters/PostRecyclerViewAdapter.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/adapters/PostRecyclerViewAdapter.java @@ -69,6 +69,7 @@ import jp.wasabeef.glide.transformations.BlurTransformation; import jp.wasabeef.glide.transformations.RoundedCornersTransformation; import ml.docilealligator.infinityforreddit.FetchGfycatOrRedgifsVideoLinks; import ml.docilealligator.infinityforreddit.MarkPostAsReadInterface; +import ml.docilealligator.infinityforreddit.SaveMemoryCenterInisdeDownsampleStrategy; import ml.docilealligator.infinityforreddit.R; import ml.docilealligator.infinityforreddit.SaveThing; import ml.docilealligator.infinityforreddit.VoteThing; @@ -126,7 +127,6 @@ public class PostRecyclerViewAdapter extends PagingDataAdapter<Post, RecyclerVie private Retrofit mOauthRetrofit; private Retrofit mGfycatRetrofit; private Retrofit mRedgifsRetrofit; - private int mImageViewWidth; private String mAccessToken; private RequestManager mGlide; private Locale mLocale; @@ -206,7 +206,7 @@ public class PostRecyclerViewAdapter extends PagingDataAdapter<Post, RecyclerVie public PostRecyclerViewAdapter(AppCompatActivity activity, PostFragment fragment, Executor executor, Retrofit oauthRetrofit, Retrofit gfycatRetrofit, Retrofit redgifsRetrofit, - CustomThemeWrapper customThemeWrapper, Locale locale, int imageViewWidth, + CustomThemeWrapper customThemeWrapper, Locale locale, String accessToken, String accountName, int postType, int postLayout, boolean displaySubredditName, SharedPreferences sharedPreferences, SharedPreferences nsfwAndSpoilerSharedPreferences, SharedPreferences postHistorySharedPreferences, @@ -220,7 +220,6 @@ public class PostRecyclerViewAdapter extends PagingDataAdapter<Post, RecyclerVie mOauthRetrofit = oauthRetrofit; mGfycatRetrofit = gfycatRetrofit; mRedgifsRetrofit = redgifsRetrofit; - mImageViewWidth = imageViewWidth; mAccessToken = accessToken; mPostType = postType; mDisplaySubredditName = displaySubredditName; @@ -676,11 +675,7 @@ public class PostRecyclerViewAdapter extends PagingDataAdapter<Post, RecyclerVie Post.Preview preview = getSuitablePreview(post.getPreviews()); if (preview != null) { ((PostVideoAutoplayViewHolder) holder).aspectRatioFrameLayout.setAspectRatio((float) preview.getPreviewWidth() / preview.getPreviewHeight()); - if (mImageViewWidth > preview.getPreviewWidth()) { - mGlide.load(preview.getPreviewUrl()).override(Target.SIZE_ORIGINAL).into(((PostVideoAutoplayViewHolder) holder).previewImageView); - } else { - mGlide.load(preview.getPreviewUrl()).into(((PostVideoAutoplayViewHolder) holder).previewImageView); - } + mGlide.load(preview.getPreviewUrl()).centerInside().downsample(new SaveMemoryCenterInisdeDownsampleStrategy()).into(((PostVideoAutoplayViewHolder) holder).previewImageView); } else { ((PostVideoAutoplayViewHolder) holder).aspectRatioFrameLayout.setAspectRatio(1); } @@ -774,8 +769,6 @@ public class PostRecyclerViewAdapter extends PagingDataAdapter<Post, RecyclerVie int height = (int) (400 * mScale); ((PostWithPreviewTypeViewHolder) holder).imageView.setScaleType(ImageView.ScaleType.CENTER_CROP); ((PostWithPreviewTypeViewHolder) holder).imageView.getLayoutParams().height = height; - preview.setPreviewWidth(mImageViewWidth); - preview.setPreviewHeight(height); } else { ((PostWithPreviewTypeViewHolder) holder).imageView .setRatio((float) preview.getPreviewHeight() / preview.getPreviewWidth()); @@ -809,11 +802,7 @@ public class PostRecyclerViewAdapter extends PagingDataAdapter<Post, RecyclerVie Post.Preview preview = getSuitablePreview(post.getPreviews()); if (preview != null) { ((PostCard2VideoAutoplayViewHolder) holder).aspectRatioFrameLayout.setAspectRatio((float) preview.getPreviewWidth() / preview.getPreviewHeight()); - if (mImageViewWidth > preview.getPreviewWidth()) { - mGlide.load(preview.getPreviewUrl()).override(Target.SIZE_ORIGINAL).into(((PostCard2VideoAutoplayViewHolder) holder).previewImageView); - } else { - mGlide.load(preview.getPreviewUrl()).into(((PostCard2VideoAutoplayViewHolder) holder).previewImageView); - } + mGlide.load(preview.getPreviewUrl()).centerInside().downsample(new SaveMemoryCenterInisdeDownsampleStrategy()).into(((PostCard2VideoAutoplayViewHolder) holder).previewImageView); } else { ((PostCard2VideoAutoplayViewHolder) holder).aspectRatioFrameLayout.setAspectRatio(1); } @@ -909,8 +898,6 @@ public class PostRecyclerViewAdapter extends PagingDataAdapter<Post, RecyclerVie int height = (int) (400 * mScale); ((PostCard2WithPreviewViewHolder) holder).imageView.setScaleType(ImageView.ScaleType.CENTER_CROP); ((PostCard2WithPreviewViewHolder) holder).imageView.getLayoutParams().height = height; - preview.setPreviewWidth(mImageViewWidth); - preview.setPreviewHeight(height); } else { ((PostCard2WithPreviewViewHolder) holder).imageView .setRatio((float) preview.getPreviewHeight() / preview.getPreviewWidth()); @@ -1291,8 +1278,6 @@ public class PostRecyclerViewAdapter extends PagingDataAdapter<Post, RecyclerVie int height = (int) (400 * mScale); ((PostGalleryViewHolder) holder).imageView.setScaleType(ImageView.ScaleType.CENTER_CROP); ((PostGalleryViewHolder) holder).imageView.getLayoutParams().height = height; - preview.setPreviewWidth(mImageViewWidth); - preview.setPreviewHeight(height); } else { ((PostGalleryViewHolder) holder).imageView .setRatio((float) preview.getPreviewHeight() / preview.getPreviewWidth()); @@ -1327,8 +1312,6 @@ public class PostRecyclerViewAdapter extends PagingDataAdapter<Post, RecyclerVie int height = (int) (400 * mScale); ((PostGalleryViewHolder) holder).imageView.setScaleType(ImageView.ScaleType.CENTER_CROP); ((PostGalleryViewHolder) holder).imageView.getLayoutParams().height = height; - preview.setPreviewWidth(mImageViewWidth); - preview.setPreviewHeight(height); } else { ((PostGalleryViewHolder) holder).imageView .setRatio((float) preview.getPreviewHeight() / preview.getPreviewWidth()); @@ -1353,8 +1336,6 @@ public class PostRecyclerViewAdapter extends PagingDataAdapter<Post, RecyclerVie int height = (int) (400 * mScale); ((PostGalleryViewHolder) holder).imageView.setScaleType(ImageView.ScaleType.CENTER_CROP); ((PostGalleryViewHolder) holder).imageView.getLayoutParams().height = height; - preview.setPreviewWidth(mImageViewWidth); - preview.setPreviewHeight(height); } else { ((PostGalleryViewHolder) holder).imageView .setRatio((float) preview.getPreviewHeight() / preview.getPreviewWidth()); @@ -1379,8 +1360,6 @@ public class PostRecyclerViewAdapter extends PagingDataAdapter<Post, RecyclerVie int height = (int) (400 * mScale); ((PostGalleryViewHolder) holder).imageView.setScaleType(ImageView.ScaleType.CENTER_CROP); ((PostGalleryViewHolder) holder).imageView.getLayoutParams().height = height; - preview.setPreviewWidth(mImageViewWidth); - preview.setPreviewHeight(height); } else { ((PostGalleryViewHolder) holder).imageView .setRatio((float) preview.getPreviewHeight() / preview.getPreviewWidth()); @@ -1415,8 +1394,6 @@ public class PostRecyclerViewAdapter extends PagingDataAdapter<Post, RecyclerVie int height = (int) (400 * mScale); ((PostGalleryViewHolder) holder).imageView.setScaleType(ImageView.ScaleType.CENTER_CROP); ((PostGalleryViewHolder) holder).imageView.getLayoutParams().height = height; - preview.setPreviewWidth(mImageViewWidth); - preview.setPreviewHeight(height); } else { ((PostGalleryViewHolder) holder).imageView .setRatio((float) preview.getPreviewHeight() / preview.getPreviewWidth()); @@ -1447,29 +1424,11 @@ public class PostRecyclerViewAdapter extends PagingDataAdapter<Post, RecyclerVie if (preview.getPreviewWidth() * preview.getPreviewHeight() > 5_000_000) { for (int i = previews.size() - 1; i >= 1; i--) { preview = previews.get(i); - if (mImageViewWidth >= preview.getPreviewWidth()) { - if (preview.getPreviewWidth() * preview.getPreviewHeight() <= 5_000_000) { - return preview; - } - } else { - int height = mImageViewWidth / preview.getPreviewWidth() * preview.getPreviewHeight(); - if (mImageViewWidth * height <= 5_000_000) { - preview.setPreviewWidth(mImageViewWidth); - preview.setPreviewHeight(height); - return preview; - } + if (preview.getPreviewWidth() * preview.getPreviewHeight() <= 5_000_000) { + return preview; } } } - - if (preview.getPreviewWidth() * preview.getPreviewHeight() > 5_000_000) { - int divisor = 2; - do { - preview.setPreviewWidth(preview.getPreviewWidth() / divisor); - preview.setPreviewHeight(preview.getPreviewHeight() / divisor); - divisor *= 2; - } while (preview.getPreviewWidth() * preview.getPreviewHeight() > 5_000_000); - } return preview; } @@ -1494,7 +1453,7 @@ public class PostRecyclerViewAdapter extends PagingDataAdapter<Post, RecyclerVie imageRequestBuilder.apply(RequestOptions.bitmapTransform(new BlurTransformation(50, 10))) .into(((PostWithPreviewTypeViewHolder) holder).imageView); } else { - imageRequestBuilder.override(preview.getPreviewWidth(), preview.getPreviewHeight()).centerInside().into(((PostWithPreviewTypeViewHolder) holder).imageView); + imageRequestBuilder.centerInside().downsample(new SaveMemoryCenterInisdeDownsampleStrategy()).into(((PostWithPreviewTypeViewHolder) holder).imageView); } } } else if (holder instanceof PostCompactBaseViewHolder) { @@ -1534,11 +1493,7 @@ public class PostRecyclerViewAdapter extends PagingDataAdapter<Post, RecyclerVie imageRequestBuilder.apply(RequestOptions.bitmapTransform(new BlurTransformation(50, 10))) .into(((PostGalleryViewHolder) holder).imageView); } else { - if (mImageViewWidth > preview.getPreviewWidth()) { - imageRequestBuilder.override(preview.getPreviewWidth(), preview.getPreviewHeight()).into(((PostGalleryViewHolder) holder).imageView); - } else { - imageRequestBuilder.into(((PostGalleryViewHolder) holder).imageView); - } + imageRequestBuilder.centerInside().downsample(new SaveMemoryCenterInisdeDownsampleStrategy()).into(((PostGalleryViewHolder) holder).imageView); } } } else if (holder instanceof PostCard2WithPreviewViewHolder) { @@ -1558,11 +1513,7 @@ public class PostRecyclerViewAdapter extends PagingDataAdapter<Post, RecyclerVie imageRequestBuilder.apply(RequestOptions.bitmapTransform(new BlurTransformation(50, 10))) .into(((PostCard2WithPreviewViewHolder) holder).imageView); } else { - if (mImageViewWidth > preview.getPreviewWidth()) { - imageRequestBuilder.override(preview.getPreviewWidth(), preview.getPreviewHeight()).into(((PostCard2WithPreviewViewHolder) holder).imageView); - } else { - imageRequestBuilder.into(((PostCard2WithPreviewViewHolder) holder).imageView); - } + imageRequestBuilder.centerInside().downsample(new SaveMemoryCenterInisdeDownsampleStrategy()).into(((PostCard2WithPreviewViewHolder) holder).imageView); } } } @@ -1916,12 +1867,15 @@ public class PostRecyclerViewAdapter extends PagingDataAdapter<Post, RecyclerVie } private void openViewPostDetailActivity(Post post, int position) { - Intent intent = new Intent(mActivity, ViewPostDetailActivity.class); - intent.putExtra(ViewPostDetailActivity.EXTRA_POST_DATA, post); - intent.putExtra(ViewPostDetailActivity.EXTRA_POST_LIST_POSITION, position); - intent.putExtra(ViewPostDetailActivity.EXTRA_POST_FRAGMENT_ID, mFragment.getPostFragmentId()); - intent.putExtra(ViewPostDetailActivity.EXTRA_IS_NSFW_SUBREDDIT, mFragment.getIsNsfwSubreddit()); - mActivity.startActivity(intent); + if (canStartActivity) { + canStartActivity = false; + Intent intent = new Intent(mActivity, ViewPostDetailActivity.class); + intent.putExtra(ViewPostDetailActivity.EXTRA_POST_DATA, post); + intent.putExtra(ViewPostDetailActivity.EXTRA_POST_LIST_POSITION, position); + intent.putExtra(ViewPostDetailActivity.EXTRA_POST_FRAGMENT_ID, mFragment.getPostFragmentId()); + intent.putExtra(ViewPostDetailActivity.EXTRA_IS_NSFW_SUBREDDIT, mFragment.getIsNsfwSubreddit()); + mActivity.startActivity(intent); + } } private void openMedia(Post post) { @@ -2113,7 +2067,6 @@ public class PostRecyclerViewAdapter extends PagingDataAdapter<Post, RecyclerVie Post post = getItem(position); if (post != null) { markPostRead(post, true); - canStartActivity = false; openViewPostDetailActivity(post, getBindingAdapterPosition()); } @@ -3160,8 +3113,6 @@ public class PostRecyclerViewAdapter extends PagingDataAdapter<Post, RecyclerVie Post post = getItem(position); if (post != null && canStartActivity) { markPostRead(post, true); - canStartActivity = false; - openViewPostDetailActivity(post, getBindingAdapterPosition()); } }); @@ -3750,7 +3701,6 @@ public class PostRecyclerViewAdapter extends PagingDataAdapter<Post, RecyclerVie Post post = getItem(position); if (post != null) { markPostRead(post, true); - canStartActivity = false; if (post.getPostType() == Post.TEXT_TYPE || !mSharedPreferences.getBoolean(SharedPreferencesUtils.CLICK_TO_SHOW_MEDIA_IN_GALLERY_LAYOUT, false)) { openViewPostDetailActivity(post, getBindingAdapterPosition()); @@ -3767,7 +3717,6 @@ public class PostRecyclerViewAdapter extends PagingDataAdapter<Post, RecyclerVie Post post = getItem(position); if (post != null) { markPostRead(post, true); - canStartActivity = false; if (post.getPostType() == Post.TEXT_TYPE || mSharedPreferences.getBoolean(SharedPreferencesUtils.CLICK_TO_SHOW_MEDIA_IN_GALLERY_LAYOUT, false)) { openViewPostDetailActivity(post, getBindingAdapterPosition()); diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/adapters/PrivateMessagesDetailRecyclerViewAdapter.java b/app/src/main/java/ml/docilealligator/infinityforreddit/adapters/PrivateMessagesDetailRecyclerViewAdapter.java index e357771b..180b74be 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/adapters/PrivateMessagesDetailRecyclerViewAdapter.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/adapters/PrivateMessagesDetailRecyclerViewAdapter.java @@ -41,7 +41,7 @@ import ml.docilealligator.infinityforreddit.activities.ViewUserDetailActivity; import ml.docilealligator.infinityforreddit.customtheme.CustomThemeWrapper; import ml.docilealligator.infinityforreddit.message.Message; import ml.docilealligator.infinityforreddit.utils.SharedPreferencesUtils; -import ml.docilealligator.infinityforreddit.utils.SuperscriptInlineProcessor; +import ml.docilealligator.infinityforreddit.markdown.SuperscriptInlineProcessor; import ml.docilealligator.infinityforreddit.utils.Utils; public class PrivateMessagesDetailRecyclerViewAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> { diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/adapters/RulesRecyclerViewAdapter.java b/app/src/main/java/ml/docilealligator/infinityforreddit/adapters/RulesRecyclerViewAdapter.java index 294733a1..d82fcf8d 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/adapters/RulesRecyclerViewAdapter.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/adapters/RulesRecyclerViewAdapter.java @@ -35,7 +35,7 @@ import ml.docilealligator.infinityforreddit.Rule; import ml.docilealligator.infinityforreddit.activities.LinkResolverActivity; import ml.docilealligator.infinityforreddit.bottomsheetfragments.UrlMenuBottomSheetFragment; import ml.docilealligator.infinityforreddit.customtheme.CustomThemeWrapper; -import ml.docilealligator.infinityforreddit.utils.SuperscriptInlineProcessor; +import ml.docilealligator.infinityforreddit.markdown.SuperscriptInlineProcessor; import ml.docilealligator.infinityforreddit.utils.Utils; public class RulesRecyclerViewAdapter extends RecyclerView.Adapter<RulesRecyclerViewAdapter.RuleViewHolder> { diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/bottomsheetfragments/CopyTextBottomSheetFragment.java b/app/src/main/java/ml/docilealligator/infinityforreddit/bottomsheetfragments/CopyTextBottomSheetFragment.java index 4264f36a..e30156dc 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/bottomsheetfragments/CopyTextBottomSheetFragment.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/bottomsheetfragments/CopyTextBottomSheetFragment.java @@ -74,7 +74,6 @@ public class CopyTextBottomSheetFragment extends LandscapeExpandedRoundedBottomS if (markdownText != null) { //markdownText = markdownText.replaceAll("<sup>", "^").replaceAll("</sup>", ""); - markdownText = markdownText.replaceAll(">", ">"); copyMarkdownTextView.setOnClickListener(view -> { showCopyDialog(markdownText); dismiss(); diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/fragments/PostFragment.java b/app/src/main/java/ml/docilealligator/infinityforreddit/fragments/PostFragment.java index 4a9703f7..257f604e 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/fragments/PostFragment.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/fragments/PostFragment.java @@ -17,7 +17,6 @@ import android.os.Build; import android.os.Bundle; import android.os.CountDownTimer; import android.os.Handler; -import android.util.DisplayMetrics; import android.view.HapticFeedbackConstants; import android.view.KeyEvent; import android.view.LayoutInflater; @@ -338,10 +337,6 @@ public class PostFragment extends Fragment implements FragmentCommunicator { } } - DisplayMetrics displayMetrics = new DisplayMetrics(); - activity.getWindowManager().getDefaultDisplay().getMetrics(displayMetrics); - int windowWidth = displayMetrics.widthPixels; - mGlide = Glide.with(activity); lazyModeRunnable = new LazyModeRunnable() { @@ -452,7 +447,7 @@ public class PostFragment extends Fragment implements FragmentCommunicator { mAdapter = new PostRecyclerViewAdapter(activity, this, mExecutor, mOauthRetrofit, mGfycatRetrofit, mRedgifsRetrofit, mCustomThemeWrapper, locale, - windowWidth, accessToken, accountName, postType, postLayout, true, + accessToken, accountName, postType, postLayout, true, mSharedPreferences, mNsfwAndSpoilerSharedPreferences, mPostHistorySharedPreferences, mExoCreator, new PostRecyclerViewAdapter.Callback() { @Override @@ -529,7 +524,7 @@ public class PostFragment extends Fragment implements FragmentCommunicator { mAdapter = new PostRecyclerViewAdapter(activity, this, mExecutor, mOauthRetrofit, mGfycatRetrofit, mRedgifsRetrofit, mCustomThemeWrapper, locale, - windowWidth, accessToken, accountName, postType, postLayout, displaySubredditName, + accessToken, accountName, postType, postLayout, displaySubredditName, mSharedPreferences, mNsfwAndSpoilerSharedPreferences, mPostHistorySharedPreferences, mExoCreator, new PostRecyclerViewAdapter.Callback() { @Override @@ -600,7 +595,7 @@ public class PostFragment extends Fragment implements FragmentCommunicator { mAdapter = new PostRecyclerViewAdapter(activity, this, mExecutor, mOauthRetrofit, mGfycatRetrofit, mRedgifsRetrofit, mCustomThemeWrapper, locale, - windowWidth, accessToken, accountName, postType, postLayout, true, + accessToken, accountName, postType, postLayout, true, mSharedPreferences, mNsfwAndSpoilerSharedPreferences, mPostHistorySharedPreferences, mExoCreator, new PostRecyclerViewAdapter.Callback() { @Override @@ -665,7 +660,7 @@ public class PostFragment extends Fragment implements FragmentCommunicator { mAdapter = new PostRecyclerViewAdapter(activity, this, mExecutor, mOauthRetrofit, mGfycatRetrofit, mRedgifsRetrofit, mCustomThemeWrapper, locale, - windowWidth, accessToken, accountName, postType, postLayout, true, + accessToken, accountName, postType, postLayout, true, mSharedPreferences, mNsfwAndSpoilerSharedPreferences, mPostHistorySharedPreferences, mExoCreator, new PostRecyclerViewAdapter.Callback() { @Override @@ -726,7 +721,7 @@ public class PostFragment extends Fragment implements FragmentCommunicator { mAdapter = new PostRecyclerViewAdapter(activity, this, mExecutor, mOauthRetrofit, mGfycatRetrofit, mRedgifsRetrofit, mCustomThemeWrapper, locale, - windowWidth, accessToken, accountName, postType, postLayout, true, + accessToken, accountName, postType, postLayout, true, mSharedPreferences, mNsfwAndSpoilerSharedPreferences, mPostHistorySharedPreferences, mExoCreator, new PostRecyclerViewAdapter.Callback() { @Override @@ -786,7 +781,7 @@ public class PostFragment extends Fragment implements FragmentCommunicator { mAdapter = new PostRecyclerViewAdapter(activity, this, mExecutor, mOauthRetrofit, mGfycatRetrofit, mRedgifsRetrofit, mCustomThemeWrapper, locale, - windowWidth, accessToken, accountName, postType, postLayout, true, + accessToken, accountName, postType, postLayout, true, mSharedPreferences, mNsfwAndSpoilerSharedPreferences, mPostHistorySharedPreferences, mExoCreator, new PostRecyclerViewAdapter.Callback() { @Override @@ -840,7 +835,7 @@ public class PostFragment extends Fragment implements FragmentCommunicator { mAdapter = new PostRecyclerViewAdapter(activity, this, mExecutor, mOauthRetrofit, mGfycatRetrofit, mRedgifsRetrofit, mCustomThemeWrapper, locale, - windowWidth, accessToken, accountName, postType, postLayout, true, + accessToken, accountName, postType, postLayout, true, mSharedPreferences, mNsfwAndSpoilerSharedPreferences, mPostHistorySharedPreferences, mExoCreator, new PostRecyclerViewAdapter.Callback() { @Override @@ -891,7 +886,6 @@ public class PostFragment extends Fragment implements FragmentCommunicator { StaggeredGridLayoutManagerItemOffsetDecoration itemDecoration = new StaggeredGridLayoutManagerItemOffsetDecoration(activity, R.dimen.staggeredLayoutManagerItemOffset, nColumns); mPostRecyclerView.addItemDecoration(itemDecoration); - windowWidth /= 2; } if (recyclerViewPosition > 0) { diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/fragments/SidebarFragment.java b/app/src/main/java/ml/docilealligator/infinityforreddit/fragments/SidebarFragment.java index 3f22a64e..bea0c4ed 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/fragments/SidebarFragment.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/fragments/SidebarFragment.java @@ -58,7 +58,7 @@ import ml.docilealligator.infinityforreddit.customviews.LinearLayoutManagerBugFi import ml.docilealligator.infinityforreddit.subreddit.FetchSubredditData; import ml.docilealligator.infinityforreddit.subreddit.SubredditData; import ml.docilealligator.infinityforreddit.subreddit.SubredditViewModel; -import ml.docilealligator.infinityforreddit.utils.SuperscriptInlineProcessor; +import ml.docilealligator.infinityforreddit.markdown.SuperscriptInlineProcessor; import ml.docilealligator.infinityforreddit.utils.Utils; import retrofit2.Retrofit; diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/fragments/ViewPostDetailFragment.java b/app/src/main/java/ml/docilealligator/infinityforreddit/fragments/ViewPostDetailFragment.java index 5e4d8c3e..0a2ec296 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/fragments/ViewPostDetailFragment.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/fragments/ViewPostDetailFragment.java @@ -16,7 +16,6 @@ import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.Drawable; import android.os.Bundle; import android.os.Handler; -import android.util.DisplayMetrics; import android.view.HapticFeedbackConstants; import android.view.LayoutInflater; import android.view.Menu; @@ -225,7 +224,6 @@ public class ViewPostDetailFragment extends Fragment implements FragmentCommunic private boolean mExpandChildren; private boolean mSeparatePostAndComments = false; private boolean mMarkPostsAsRead; - private int mWindowWidth; private ConcatAdapter mConcatAdapter; private PostDetailRecyclerViewAdapter mPostAdapter; private CommentsRecyclerViewAdapter mCommentsAdapter; @@ -291,10 +289,6 @@ public class ViewPostDetailFragment extends Fragment implements FragmentCommunic showToast = true; } - DisplayMetrics displayMetrics = new DisplayMetrics(); - activity.getWindowManager().getDefaultDisplay().getMetrics(displayMetrics); - mWindowWidth = displayMetrics.widthPixels; - mLockFab = mSharedPreferences.getBoolean(SharedPreferencesUtils.LOCK_JUMP_TO_NEXT_TOP_LEVEL_COMMENT_BUTTON, false); mSwipeUpToHideFab = mSharedPreferences.getBoolean(SharedPreferencesUtils.SWIPE_UP_TO_HIDE_JUMP_TO_NEXT_TOP_LEVEL_COMMENT_BUTTON, false); mExpandChildren = !mSharedPreferences.getBoolean(SharedPreferencesUtils.SHOW_TOP_LEVEL_COMMENTS_FIRST, false); @@ -551,7 +545,7 @@ public class ViewPostDetailFragment extends Fragment implements FragmentCommunic mPostAdapter = new PostDetailRecyclerViewAdapter(activity, this, mExecutor, mCustomThemeWrapper, mRetrofit, mOauthRetrofit, mGfycatRetrofit, mRedgifsRetrofit, mRedditDataRoomDatabase, mGlide, - mWindowWidth, mSeparatePostAndComments, mAccessToken, mAccountName, mPost, mLocale, + mSeparatePostAndComments, mAccessToken, mAccountName, mPost, mLocale, mSharedPreferences, mNsfwAndSpoilerSharedPreferences, mPostDetailsSharedPreferences, mExoCreator, post -> EventBus.getDefault().post(new PostUpdateEventToPostList(mPost, postListPosition))); mCommentsAdapter = new CommentsRecyclerViewAdapter(activity, @@ -1196,7 +1190,7 @@ public class ViewPostDetailFragment extends Fragment implements FragmentCommunic mPostAdapter = new PostDetailRecyclerViewAdapter(activity, ViewPostDetailFragment.this, mExecutor, mCustomThemeWrapper, mRetrofit, mOauthRetrofit, mGfycatRetrofit, mRedgifsRetrofit, - mRedditDataRoomDatabase, mGlide, mWindowWidth, mSeparatePostAndComments, + mRedditDataRoomDatabase, mGlide, mSeparatePostAndComments, mAccessToken, mAccountName, mPost, mLocale, mSharedPreferences, mNsfwAndSpoilerSharedPreferences, mPostDetailsSharedPreferences, mExoCreator, diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/fragments/ViewRPANBroadcastFragment.java b/app/src/main/java/ml/docilealligator/infinityforreddit/fragments/ViewRPANBroadcastFragment.java index 66921637..5b7dcb2c 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/fragments/ViewRPANBroadcastFragment.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/fragments/ViewRPANBroadcastFragment.java @@ -1,5 +1,6 @@ package ml.docilealligator.infinityforreddit.fragments; +import android.app.AlertDialog; import android.content.Context; import android.content.SharedPreferences; import android.content.res.Configuration; @@ -207,11 +208,14 @@ public class ViewRPANBroadcastFragment extends Fragment { hdButton.setVisibility(View.VISIBLE); hdButton.setOnClickListener(view -> { - TrackSelectionDialogBuilder build = new TrackSelectionDialogBuilder(mActivity, + TrackSelectionDialogBuilder builder = new TrackSelectionDialogBuilder(mActivity, getString(R.string.select_video_quality), trackSelector, 0); - build.setShowDisableOption(true); - build.setAllowAdaptiveSelections(false); - build.build().show(); + builder.setShowDisableOption(true); + builder.setAllowAdaptiveSelections(false); + AlertDialog alertDialog = builder.build(); + alertDialog.show(); + alertDialog.getButton(AlertDialog.BUTTON_POSITIVE).setTextColor(mCustomThemeWrapper.getPrimaryTextColor()); + alertDialog.getButton(AlertDialog.BUTTON_NEGATIVE).setTextColor(mCustomThemeWrapper.getPrimaryTextColor()); }); for (int i = 0; i < trackGroups.length; i++) { diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/fragments/ViewRedditGalleryImageOrGifFragment.java b/app/src/main/java/ml/docilealligator/infinityforreddit/fragments/ViewRedditGalleryImageOrGifFragment.java index 05f0ab7a..494d6b44 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/fragments/ViewRedditGalleryImageOrGifFragment.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/fragments/ViewRedditGalleryImageOrGifFragment.java @@ -427,7 +427,7 @@ public class ViewRedditGalleryImageOrGifFragment extends Fragment { @Override public void onDestroyView() { super.onDestroyView(); - BigImageViewer.imageLoader().cancelAll(); + imageView.cancel(); SubsamplingScaleImageView subsamplingScaleImageView = imageView.getSSIV(); if (subsamplingScaleImageView != null) { subsamplingScaleImageView.recycle(); diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/markdown/BlockQuoteWithExceptionParser.java b/app/src/main/java/ml/docilealligator/infinityforreddit/markdown/BlockQuoteWithExceptionParser.java new file mode 100644 index 00000000..f500bb93 --- /dev/null +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/markdown/BlockQuoteWithExceptionParser.java @@ -0,0 +1,85 @@ +package ml.docilealligator.infinityforreddit.markdown; + +import org.commonmark.internal.util.Parsing; +import org.commonmark.node.Block; +import org.commonmark.node.BlockQuote; +import org.commonmark.parser.block.AbstractBlockParser; +import org.commonmark.parser.block.AbstractBlockParserFactory; +import org.commonmark.parser.block.BlockContinue; +import org.commonmark.parser.block.BlockStart; +import org.commonmark.parser.block.MatchedBlockParser; +import org.commonmark.parser.block.ParserState; + +// Parse and consume a block quote except when it's a spoiler opening +public class BlockQuoteWithExceptionParser extends AbstractBlockParser { + private final BlockQuote block = new BlockQuote(); + + private static boolean isMarker(ParserState state, int index) { + CharSequence line = state.getLine(); + return state.getIndent() < Parsing.CODE_BLOCK_INDENT && index < line.length() && line.charAt(index) == '>'; + } + + private static boolean isMarkerSpoiler(ParserState state, int index) { + CharSequence line = state.getLine(); + int length = line.length(); + try { + return state.getIndent() < Parsing.CODE_BLOCK_INDENT && index < length && line.charAt(index) == '>' && (index + 1) < length && line.charAt(index + 1) == '!'; + } catch (IndexOutOfBoundsException e) { + e.printStackTrace(); + return false; + } + } + + @Override + public boolean isContainer() { + return true; + } + + @Override + public boolean canContain(Block block) { + return true; + } + + @Override + public BlockQuote getBlock() { + return block; + } + + @Override + public BlockContinue tryContinue(ParserState state) { + int nextNonSpace = state.getNextNonSpaceIndex(); + if (isMarker(state, nextNonSpace)) { + int newColumn = state.getColumn() + state.getIndent() + 1; + // optional following space or tab + if (Parsing.isSpaceOrTab(state.getLine(), nextNonSpace + 1)) { + newColumn++; + } + return BlockContinue.atColumn(newColumn); + } else { + return BlockContinue.none(); + } + } + + public static class Factory extends AbstractBlockParserFactory { + public BlockStart tryStart(ParserState state, MatchedBlockParser matchedBlockParser) { + int nextNonSpace = state.getNextNonSpaceIndex(); + // Potential for a spoiler opening + // We don't check for spoiler closing, neither does Reddit + if (isMarkerSpoiler(state, nextNonSpace)) { + // It might be a spoiler, don't consume + return BlockStart.none(); + } + // Not a spoiler then + else if (isMarker(state, nextNonSpace)) { + int newColumn = state.getColumn() + state.getIndent() + 1; + // optional following space or tab + if (Parsing.isSpaceOrTab(state.getLine(), nextNonSpace + 1)) { + newColumn++; + } + return BlockStart.of(new BlockQuoteWithExceptionParser()).atColumn(newColumn); + } else { + return BlockStart.none(); + } + } + } +} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/markdown/SpoilerParserPlugin.java b/app/src/main/java/ml/docilealligator/infinityforreddit/markdown/SpoilerParserPlugin.java new file mode 100644 index 00000000..1cca0cfe --- /dev/null +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/markdown/SpoilerParserPlugin.java @@ -0,0 +1,202 @@ +package ml.docilealligator.infinityforreddit.markdown; + +import android.graphics.Color; +import android.text.SpannableStringBuilder; +import android.text.Spanned; +import android.widget.TextView; + +import androidx.annotation.NonNull; + +import org.commonmark.node.Block; +import org.commonmark.node.BlockQuote; +import org.commonmark.node.HtmlBlock; +import org.commonmark.node.HtmlInline; +import org.commonmark.parser.Parser; + +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.Set; +import java.util.Stack; + +import io.noties.markwon.AbstractMarkwonPlugin; +import io.noties.markwon.core.CorePlugin; +import io.noties.markwon.core.spans.CodeBlockSpan; +import io.noties.markwon.core.spans.CodeSpan; + +public class SpoilerParserPlugin extends AbstractMarkwonPlugin { + private final int textColor; + private final int backgroundColor; + + SpoilerParserPlugin(int textColor, int backgroundColor) { + this.textColor = textColor; + this.backgroundColor = backgroundColor; + } + + public static SpoilerParserPlugin create(@NonNull int textColor, @NonNull int backgroundColor) { + return new SpoilerParserPlugin(textColor, backgroundColor); + } + + @Override + public void configureParser(@NonNull Parser.Builder builder) { + builder.customBlockParserFactory(new BlockQuoteWithExceptionParser.Factory()); + + Set<Class<? extends Block>> blocks = CorePlugin.enabledBlockTypes(); + blocks.remove(HtmlBlock.class); + blocks.remove(HtmlInline.class); + blocks.remove(BlockQuote.class); + + builder.enabledBlockTypes(blocks); + } + + @Override + public void afterSetText(@NonNull TextView textView) { + textView.setHighlightColor(Color.TRANSPARENT); + + if(textView.getText().length() < 5) { + return; + } + + SpannableStringBuilder markdownStringBuilder = new SpannableStringBuilder(textView.getText()); + + LinkedHashMap<Integer, Integer> spoilers = parse(markdownStringBuilder); + if(spoilers.size() == 0) { + return; + } + int offset = 2; + + for (Map.Entry<Integer, Integer> entry : spoilers.entrySet()) { + int spoilerStart = entry.getKey() - offset; + int spoilerEnd = entry.getValue() - offset; + + // Try not to set a spoiler span if it's inside a CodeSpan + CodeSpan[] codeSpans = markdownStringBuilder.getSpans(spoilerStart, spoilerEnd, CodeSpan.class); + CodeBlockSpan[] codeBlockSpans = markdownStringBuilder.getSpans(spoilerStart, spoilerEnd, CodeBlockSpan.class); + + if (codeSpans.length == 0 && codeBlockSpans.length == 0) { + markdownStringBuilder.delete(spoilerStart, spoilerStart + 2); + markdownStringBuilder.delete(spoilerEnd, spoilerEnd + 2); + SpoilerSpan spoilerSpan = new SpoilerSpan(textColor, backgroundColor); + markdownStringBuilder.setSpan(spoilerSpan, spoilerStart, spoilerEnd, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + offset += 4; + } + + for (CodeSpan codeSpan : codeSpans) { + int spanBeginning = markdownStringBuilder.getSpanStart(codeSpan); + int spanEnd = markdownStringBuilder.getSpanEnd(codeSpan); + if (spoilerStart + 2 <= spanBeginning && spanEnd <= spoilerEnd + 2) { + markdownStringBuilder.delete(spoilerStart, spoilerStart + 2); + markdownStringBuilder.delete(spoilerEnd, spoilerEnd + 2); + SpoilerSpan spoilerSpan = new SpoilerSpan(textColor, backgroundColor); + markdownStringBuilder.setSpan(spoilerSpan, spoilerStart, spoilerEnd, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + offset += 4; + } else { + break; + } + } + + for (CodeBlockSpan codeBlockSpan : codeBlockSpans) { + int spanBeginning = markdownStringBuilder.getSpanStart(codeBlockSpan); + int spanEnd = markdownStringBuilder.getSpanEnd(codeBlockSpan); + if (spoilerStart + 2 <= spanBeginning && spanEnd <= spoilerEnd + 2) { + markdownStringBuilder.delete(spoilerStart, spoilerStart + 2); + markdownStringBuilder.delete(spoilerEnd, spoilerEnd + 2); + SpoilerSpan spoilerSpan = new SpoilerSpan(textColor, backgroundColor); + markdownStringBuilder.setSpan(spoilerSpan, spoilerStart, spoilerEnd, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + offset += 4; + } else { + break; + } + } + } + if(offset > 2) { + textView.setText(markdownStringBuilder); + } + } + + // Very naive implementation, needs to be improved for efficiency and edge cases + // Don't allow more than one new line after every non-blank line + // Try not to care about recursing spoilers, we just want the outermost spoiler because + // spoiler revealing-hiding breaks with recursing spoilers + private LinkedHashMap<Integer, Integer> parse(SpannableStringBuilder markdown) { + final int MAX_NEW_LINE = 1; + var openSpoilerStack = new Stack<Integer>(); + var closedSpoilerMap = new LinkedHashMap<Integer, Integer>(); + int variable_max_depth = calculateBalance(0, markdown) + 1; + int new_lines = 0; + int depth = 0; + for (int i = 0; i < markdown.length(); i++) { + if (markdown.charAt(i) == '\u2000' || markdown.charAt(i) == '\t') { + continue; + } else if (markdown.charAt(i) == '>' && (i + 1) < markdown.length() && markdown.charAt(i + 1) == '!') { + openSpoilerStack.push(i + 1); + depth++; + } else if (openSpoilerStack.size() > 0 + && markdown.charAt(i) == '!' && (i + 1) < markdown.length() + && markdown.charAt(i + 1) == '<') { + var pos = i + 1; + for (int j = 0; j < depth; j++) { + if (!openSpoilerStack.isEmpty()) pos = openSpoilerStack.peek(); + if (pos + 1 <= i) { + if (!openSpoilerStack.isEmpty()) pos = openSpoilerStack.peek(); + break; + } else { + if (!openSpoilerStack.isEmpty()) pos = openSpoilerStack.pop(); + } + } + if (depth <= variable_max_depth && pos + 1 <= i) //Spoiler content cannot be zero or less length + { + openSpoilerStack.clear(); + closedSpoilerMap.put(pos + 1, i); + } + depth--; + } else if (markdown.charAt(i) == '\n') { + new_lines++; + if (openSpoilerStack.size() >= 1 && new_lines > MAX_NEW_LINE) { + openSpoilerStack.clear(); + new_lines = 0; + depth = 0; + variable_max_depth = calculateBalance(i, markdown) + 1; + } + } else { + new_lines = 0; + } + + if (openSpoilerStack.size() >= 32) // No + { + openSpoilerStack.clear(); + closedSpoilerMap.clear(); + continue; + } + } + return closedSpoilerMap; + } + + private int calculateBalance(int index, SpannableStringBuilder line) { + final int MAX_NEW_LINE = 1; + int new_lines = 0; + int opening = 0; + int closing = 0; + for (int i = index; i < line.length(); i++) { + if (line.charAt(i) == '\u0020' || line.charAt(i) == '\t') { + continue; + } else if (line.charAt(i) == '>' + && (i + 1) < line.length() + && line.charAt(i + 1) == '!') { + opening++; + } else if (line.charAt(i) == '!' && (i + 1) < line.length() + && line.charAt(i + 1) == '<') { + closing++; + } else if (line.charAt(i) == '\n') { + new_lines++; + if (new_lines > MAX_NEW_LINE) { + break; + } + } else { + new_lines = 0; + continue; + } + } + return Math.abs(opening - closing); + } + +} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/markdown/SpoilerSpan.java b/app/src/main/java/ml/docilealligator/infinityforreddit/markdown/SpoilerSpan.java new file mode 100644 index 00000000..2264449c --- /dev/null +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/markdown/SpoilerSpan.java @@ -0,0 +1,64 @@ +package ml.docilealligator.infinityforreddit.markdown; + +import android.text.Layout; +import android.text.Spannable; +import android.text.TextPaint; +import android.text.style.ClickableSpan; +import android.view.View; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.transition.AutoTransition; +import androidx.transition.TransitionManager; + +import ml.docilealligator.infinityforreddit.customviews.SpoilerOnClickTextView; + +public class SpoilerSpan extends ClickableSpan { + final int textColor; + final int backgroundColor; + private boolean isShowing = false; + + public SpoilerSpan(@NonNull int textColor, @NonNull int backgroundColor) { + this.textColor = textColor; + this.backgroundColor = backgroundColor; + } + + @Override + public void onClick(@NonNull View widget) { + if (!(widget instanceof TextView)) { + return; + } + + final TextView textView = (TextView) widget; + final Spannable spannable = (Spannable) textView.getText(); + + final int end = spannable.getSpanEnd(this); + + if (end < 0) { + return; + } + + final Layout layout = textView.getLayout(); + if (layout == null) { + return; + } + + if (widget instanceof SpoilerOnClickTextView) { + ((SpoilerOnClickTextView) textView).setSpoilerOnClick(true); + } + isShowing = !isShowing; + widget.invalidate(); + } + + @Override + public void updateDrawState(@NonNull TextPaint ds) { + if (isShowing) { + ds.bgColor = backgroundColor & 0x0D000000; //Slightly darker background color for revealed spoiler + super.updateDrawState(ds); + } else { + ds.bgColor = backgroundColor; + } + ds.setColor(textColor); + ds.setUnderlineText(false); + } +}
\ No newline at end of file diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/utils/SuperscriptInlineProcessor.java b/app/src/main/java/ml/docilealligator/infinityforreddit/markdown/SuperscriptInlineProcessor.java index 136a69d4..27f4d1e4 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/utils/SuperscriptInlineProcessor.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/markdown/SuperscriptInlineProcessor.java @@ -1,4 +1,4 @@ -package ml.docilealligator.infinityforreddit.utils; +package ml.docilealligator.infinityforreddit.markdown; import androidx.annotation.Nullable; diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/settings/CustomizeMainPageTabsFragment.java b/app/src/main/java/ml/docilealligator/infinityforreddit/settings/CustomizeMainPageTabsFragment.java index dddbda85..44f45eef 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/settings/CustomizeMainPageTabsFragment.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/settings/CustomizeMainPageTabsFragment.java @@ -492,26 +492,26 @@ public class CustomizeMainPageTabsFragment extends Fragment { tab3AddImageView.setOnClickListener(view -> selectName(2)); - showMultiredditsSwitchMaterial.setChecked(mainActivityTabsSharedPreferences.getBoolean(accountName + SharedPreferencesUtils.MAIN_PAGE_SHOW_MULTIREDDITS, false)); - showMultiredditsSwitchMaterial.setOnCheckedChangeListener((compoundButton, b) -> mainActivityTabsSharedPreferences.edit().putBoolean(accountName + SharedPreferencesUtils.MAIN_PAGE_SHOW_MULTIREDDITS, b).apply()); + showMultiredditsSwitchMaterial.setChecked(mainActivityTabsSharedPreferences.getBoolean((accountName == null ? "" : accountName) + SharedPreferencesUtils.MAIN_PAGE_SHOW_MULTIREDDITS, false)); + showMultiredditsSwitchMaterial.setOnCheckedChangeListener((compoundButton, b) -> mainActivityTabsSharedPreferences.edit().putBoolean((accountName == null ? "" : accountName) + SharedPreferencesUtils.MAIN_PAGE_SHOW_MULTIREDDITS, b).apply()); showMultiredditsLinearLayout.setOnClickListener(view -> { showMultiredditsSwitchMaterial.performClick(); }); - showFavoriteMultiredditsSwitchMaterial.setChecked(mainActivityTabsSharedPreferences.getBoolean(accountName + SharedPreferencesUtils.MAIN_PAGE_SHOW_FAVORITE_MULTIREDDITS, false)); - showFavoriteMultiredditsSwitchMaterial.setOnCheckedChangeListener((compoundButton, b) -> mainActivityTabsSharedPreferences.edit().putBoolean(accountName + SharedPreferencesUtils.MAIN_PAGE_SHOW_FAVORITE_MULTIREDDITS, b).apply()); + showFavoriteMultiredditsSwitchMaterial.setChecked(mainActivityTabsSharedPreferences.getBoolean((accountName == null ? "" : accountName) + SharedPreferencesUtils.MAIN_PAGE_SHOW_FAVORITE_MULTIREDDITS, false)); + showFavoriteMultiredditsSwitchMaterial.setOnCheckedChangeListener((compoundButton, b) -> mainActivityTabsSharedPreferences.edit().putBoolean((accountName == null ? "" : accountName) + SharedPreferencesUtils.MAIN_PAGE_SHOW_FAVORITE_MULTIREDDITS, b).apply()); showFavoriteMultiredditsLinearLayout.setOnClickListener(view -> { showFavoriteMultiredditsSwitchMaterial.performClick(); }); - showSubscribedSubredditsSwitchMaterial.setChecked(mainActivityTabsSharedPreferences.getBoolean(accountName + SharedPreferencesUtils.MAIN_PAGE_SHOW_SUBSCRIBED_SUBREDDITS, false)); - showSubscribedSubredditsSwitchMaterial.setOnCheckedChangeListener((compoundButton, b) -> mainActivityTabsSharedPreferences.edit().putBoolean(accountName + SharedPreferencesUtils.MAIN_PAGE_SHOW_SUBSCRIBED_SUBREDDITS, b).apply()); + showSubscribedSubredditsSwitchMaterial.setChecked(mainActivityTabsSharedPreferences.getBoolean((accountName == null ? "" : accountName) + SharedPreferencesUtils.MAIN_PAGE_SHOW_SUBSCRIBED_SUBREDDITS, false)); + showSubscribedSubredditsSwitchMaterial.setOnCheckedChangeListener((compoundButton, b) -> mainActivityTabsSharedPreferences.edit().putBoolean((accountName == null ? "" : accountName) + SharedPreferencesUtils.MAIN_PAGE_SHOW_SUBSCRIBED_SUBREDDITS, b).apply()); showSubscribedSubredditsLinearLayout.setOnClickListener(view -> { showSubscribedSubredditsSwitchMaterial.performClick(); }); - showFavoriteSubscribedSubredditsSwitchMaterial.setChecked(mainActivityTabsSharedPreferences.getBoolean(accountName + SharedPreferencesUtils.MAIN_PAGE_SHOW_FAVORITE_SUBSCRIBED_SUBREDDITS, false)); - showFavoriteSubscribedSubredditsSwitchMaterial.setOnCheckedChangeListener((compoundButton, b) -> mainActivityTabsSharedPreferences.edit().putBoolean(accountName + SharedPreferencesUtils.MAIN_PAGE_SHOW_FAVORITE_SUBSCRIBED_SUBREDDITS, b).apply()); + showFavoriteSubscribedSubredditsSwitchMaterial.setChecked(mainActivityTabsSharedPreferences.getBoolean((accountName == null ? "" : accountName) + SharedPreferencesUtils.MAIN_PAGE_SHOW_FAVORITE_SUBSCRIBED_SUBREDDITS, false)); + showFavoriteSubscribedSubredditsSwitchMaterial.setOnCheckedChangeListener((compoundButton, b) -> mainActivityTabsSharedPreferences.edit().putBoolean((accountName == null ? "" : accountName) + SharedPreferencesUtils.MAIN_PAGE_SHOW_FAVORITE_SUBSCRIBED_SUBREDDITS, b).apply()); showFavoriteSubscribedSubredditsLinearLayout.setOnClickListener(view -> { showFavoriteSubscribedSubredditsSwitchMaterial.performClick(); }); diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/utils/Utils.java b/app/src/main/java/ml/docilealligator/infinityforreddit/utils/Utils.java index 15bcefa0..f292088d 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/utils/Utils.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/utils/Utils.java @@ -65,7 +65,6 @@ public class Utils { .replaceAll("((?<=[\\s])|^)/[rRuU]/[\\w-]+/{0,1}", "[$0](https://www.reddit.com$0)") .replaceAll("((?<=[\\s])|^)[rRuU]/[\\w-]+/{0,1}", "[$0](https://www.reddit.com/$0)") .replaceAll("\\^{2,}", "^") - .replaceAll(">!(\\n?(?:[\\S\\h]+?(?:\\n?[\\S\\h]+?)?)\\n?)!<", ">!$1!<") // html entity remains escaped inside an inline block .replaceAll("(^|^ *|\\n *)#(?!($|\\s|#))", "$0 ") .replaceAll("(^|^ *|\\n *)##(?!($|\\s|#))", "$0 ") .replaceAll("(^|^ *|\\n *)###(?!($|\\s|#))", "$0 ") diff --git a/app/src/main/res/layout/exo_playback_control_view.xml b/app/src/main/res/layout/exo_playback_control_view.xml index b81b5026..28ee2d9a 100644 --- a/app/src/main/res/layout/exo_playback_control_view.xml +++ b/app/src/main/res/layout/exo_playback_control_view.xml @@ -119,6 +119,14 @@ android:src="@drawable/ic_file_download_toolbar_white_24dp" android:background="?attr/selectableItemBackgroundBorderless" /> + <ImageView + android:id="@+id/playback_speed_image_view_exo_playback_control_view" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:padding="16dp" + android:src="@drawable/ic_playback_speed_toolbar_24dp" + android:background="?attr/selectableItemBackgroundBorderless" /> + </LinearLayout> </com.google.android.material.bottomappbar.BottomAppBar> diff --git a/app/src/main/res/layout/item_post_card_2_video_autoplay.xml b/app/src/main/res/layout/item_post_card_2_video_autoplay.xml index 62f68bb2..3f3cf37c 100644 --- a/app/src/main/res/layout/item_post_card_2_video_autoplay.xml +++ b/app/src/main/res/layout/item_post_card_2_video_autoplay.xml @@ -31,6 +31,7 @@ android:layout_width="match_parent" android:layout_height="match_parent" app:show_timeout="1500" + app:auto_show="false" app:controller_layout_id="@layout/exo_autoplay_playback_control_view" /> <pl.droidsonroids.gif.GifImageView diff --git a/app/src/main/res/layout/item_post_card_2_video_autoplay_legacy_controller.xml b/app/src/main/res/layout/item_post_card_2_video_autoplay_legacy_controller.xml index 458630ef..002afb56 100644 --- a/app/src/main/res/layout/item_post_card_2_video_autoplay_legacy_controller.xml +++ b/app/src/main/res/layout/item_post_card_2_video_autoplay_legacy_controller.xml @@ -31,6 +31,7 @@ android:layout_width="match_parent" android:layout_height="match_parent" app:show_timeout="1500" + app:auto_show="false" app:controller_layout_id="@layout/exo_autoplay_playback_control_view_legacy" /> <pl.droidsonroids.gif.GifImageView diff --git a/app/src/main/res/layout/item_post_detail_video_autoplay.xml b/app/src/main/res/layout/item_post_detail_video_autoplay.xml index ff03dacc..aa3a3662 100644 --- a/app/src/main/res/layout/item_post_detail_video_autoplay.xml +++ b/app/src/main/res/layout/item_post_detail_video_autoplay.xml @@ -214,6 +214,7 @@ android:layout_width="match_parent" android:layout_height="match_parent" app:show_timeout="1500" + app:auto_show="false" app:controller_layout_id="@layout/exo_autoplay_playback_control_view" /> <pl.droidsonroids.gif.GifImageView diff --git a/app/src/main/res/layout/item_post_detail_video_autoplay_legacy_controller.xml b/app/src/main/res/layout/item_post_detail_video_autoplay_legacy_controller.xml index 56784af0..8e1b67ac 100644 --- a/app/src/main/res/layout/item_post_detail_video_autoplay_legacy_controller.xml +++ b/app/src/main/res/layout/item_post_detail_video_autoplay_legacy_controller.xml @@ -214,6 +214,7 @@ android:layout_width="match_parent" android:layout_height="match_parent" app:show_timeout="1500" + app:auto_show="false" app:controller_layout_id="@layout/exo_autoplay_playback_control_view_legacy" /> <pl.droidsonroids.gif.GifImageView diff --git a/app/src/main/res/layout/item_post_video_type_autoplay.xml b/app/src/main/res/layout/item_post_video_type_autoplay.xml index 3ea2d41a..b63b608e 100644 --- a/app/src/main/res/layout/item_post_video_type_autoplay.xml +++ b/app/src/main/res/layout/item_post_video_type_autoplay.xml @@ -208,6 +208,7 @@ android:layout_width="match_parent" android:layout_height="match_parent" app:show_timeout="1500" + app:auto_show="false" app:controller_layout_id="@layout/exo_autoplay_playback_control_view" /> <pl.droidsonroids.gif.GifImageView diff --git a/app/src/main/res/layout/item_post_video_type_autoplay_legacy_controller.xml b/app/src/main/res/layout/item_post_video_type_autoplay_legacy_controller.xml index 12369cd3..6dc38374 100644 --- a/app/src/main/res/layout/item_post_video_type_autoplay_legacy_controller.xml +++ b/app/src/main/res/layout/item_post_video_type_autoplay_legacy_controller.xml @@ -208,6 +208,7 @@ android:layout_width="match_parent" android:layout_height="match_parent" app:show_timeout="1500" + app:auto_show="false" app:controller_layout_id="@layout/exo_autoplay_playback_control_view_legacy" /> <pl.droidsonroids.gif.GifImageView diff --git a/app/src/main/res/layout/item_post_with_preview.xml b/app/src/main/res/layout/item_post_with_preview.xml index 91014578..e0162b1c 100644 --- a/app/src/main/res/layout/item_post_with_preview.xml +++ b/app/src/main/res/layout/item_post_with_preview.xml @@ -216,8 +216,7 @@ android:id="@+id/image_view_item_post_with_preview" android:layout_width="match_parent" android:layout_height="wrap_content" - android:adjustViewBounds="true" - android:scaleType="fitStart" /> + android:adjustViewBounds="true" /> <ImageView android:id="@+id/video_or_gif_indicator_image_view_item_post_with_preview" |