package ml.docilealligator.infinityforreddit.activities; import android.content.Intent; import android.content.SharedPreferences; import android.net.Uri; import android.os.Build; import android.os.Bundle; import android.text.Spanned; import android.view.MenuItem; import android.view.View; import android.view.Window; import android.view.WindowManager; import android.widget.TextView; import androidx.annotation.NonNull; import com.bumptech.glide.Glide; import com.bumptech.glide.RequestManager; import org.greenrobot.eventbus.EventBus; import org.greenrobot.eventbus.Subscribe; import org.json.JSONException; import org.json.JSONObject; import javax.inject.Inject; import javax.inject.Named; import io.noties.markwon.AbstractMarkwonPlugin; import io.noties.markwon.Markwon; import io.noties.markwon.MarkwonConfiguration; import io.noties.markwon.MarkwonPlugin; import io.noties.markwon.core.MarkwonTheme; import io.noties.markwon.recycler.MarkwonAdapter; import ml.docilealligator.infinityforreddit.Infinity; import ml.docilealligator.infinityforreddit.R; import ml.docilealligator.infinityforreddit.apis.RedditAPI; import ml.docilealligator.infinityforreddit.bottomsheetfragments.UrlMenuBottomSheetFragment; import ml.docilealligator.infinityforreddit.customtheme.CustomThemeWrapper; import ml.docilealligator.infinityforreddit.customviews.LinearLayoutManagerBugFixed; import ml.docilealligator.infinityforreddit.customviews.SwipeLockInterface; import ml.docilealligator.infinityforreddit.customviews.SwipeLockLinearLayoutManager; import ml.docilealligator.infinityforreddit.customviews.slidr.Slidr; import ml.docilealligator.infinityforreddit.databinding.ActivityWikiBinding; import ml.docilealligator.infinityforreddit.events.ChangeNetworkStatusEvent; import ml.docilealligator.infinityforreddit.events.SwitchAccountEvent; import ml.docilealligator.infinityforreddit.markdown.EmoteCloseBracketInlineProcessor; import ml.docilealligator.infinityforreddit.markdown.EmotePlugin; import ml.docilealligator.infinityforreddit.markdown.EvenBetterLinkMovementMethod; import ml.docilealligator.infinityforreddit.markdown.ImageAndGifEntry; import ml.docilealligator.infinityforreddit.markdown.ImageAndGifPlugin; import ml.docilealligator.infinityforreddit.markdown.MarkdownUtils; import ml.docilealligator.infinityforreddit.utils.JSONUtils; import ml.docilealligator.infinityforreddit.utils.SharedPreferencesUtils; import ml.docilealligator.infinityforreddit.utils.Utils; import retrofit2.Call; import retrofit2.Callback; import retrofit2.Response; import retrofit2.Retrofit; public class WikiActivity extends BaseActivity { public static final String EXTRA_SUBREDDIT_NAME = "ESN"; public static final String EXTRA_WIKI_PATH = "EWP"; private static final String WIKI_MARKDOWN_STATE = "WMS"; @Inject @Named("no_oauth") Retrofit mRetrofit; @Inject @Named("default") SharedPreferences mSharedPreferences; @Inject @Named("current_account") SharedPreferences mCurrentAccountSharedPreferences; @Inject CustomThemeWrapper mCustomThemeWrapper; private String wikiMarkdown; private String mSubredditName; private EmoteCloseBracketInlineProcessor emoteCloseBracketInlineProcessor; private EmotePlugin emotePlugin; private ImageAndGifPlugin imageAndGifPlugin; private ImageAndGifEntry imageAndGifEntry; private Markwon markwon; private MarkwonAdapter markwonAdapter; private boolean isRefreshing = false; private RequestManager mGlide; private ActivityWikiBinding binding; @Override protected void onCreate(Bundle savedInstanceState) { ((Infinity) getApplication()).getAppComponent().inject(this); super.onCreate(savedInstanceState); binding = ActivityWikiBinding.inflate(getLayoutInflater()); setContentView(binding.getRoot()); EventBus.getDefault().register(this); applyCustomTheme(); setSupportActionBar(binding.toolbarCommentWikiActivity); getSupportActionBar().setDisplayHomeAsUpEnabled(true); if (mSharedPreferences.getBoolean(SharedPreferencesUtils.SWIPE_RIGHT_TO_GO_BACK, true)) { mSliderPanel = Slidr.attach(this); } if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { Window window = getWindow(); if (isChangeStatusBarIconColor()) { addOnOffsetChangedListener(binding.appbarLayoutCommentWikiActivity); } if (isImmersiveInterface()) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { window.setDecorFitsSystemWindows(false); } else { window.setFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS, WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS); } adjustToolbar(binding.toolbarCommentWikiActivity); binding.contentMarkdownViewCommentWikiActivity.setPadding(binding.contentMarkdownViewCommentWikiActivity.getPaddingLeft(), 0, binding.contentMarkdownViewCommentWikiActivity.getPaddingRight(), getNavBarHeight()); } } mGlide = Glide.with(this); mSubredditName = getIntent().getStringExtra(EXTRA_SUBREDDIT_NAME); binding.swipeRefreshLayoutWikiActivity.setEnabled(mSharedPreferences.getBoolean(SharedPreferencesUtils.PULL_TO_REFRESH, true)); binding.swipeRefreshLayoutWikiActivity.setOnRefreshListener(this::loadWiki); int markdownColor = mCustomThemeWrapper.getPrimaryTextColor(); int spoilerBackgroundColor = markdownColor | 0xFF000000; int linkColor = mCustomThemeWrapper.getLinkColor(); MarkwonPlugin miscPlugin = new AbstractMarkwonPlugin() { @Override public void beforeSetText(@NonNull TextView textView, @NonNull Spanned markdown) { if (contentTypeface != null) { textView.setTypeface(contentTypeface); } textView.setTextColor(markdownColor); } @Override public void configureConfiguration(@NonNull MarkwonConfiguration.Builder builder) { builder.linkResolver((view, link) -> { Intent intent = new Intent(WikiActivity.this, LinkResolverActivity.class); Uri uri = Uri.parse(link); intent.setData(uri); startActivity(intent); }); } @Override public void configureTheme(@NonNull MarkwonTheme.Builder builder) { builder.linkColor(linkColor); } }; EvenBetterLinkMovementMethod.OnLinkLongClickListener onLinkLongClickListener = (textView, url) -> { UrlMenuBottomSheetFragment urlMenuBottomSheetFragment = UrlMenuBottomSheetFragment.newInstance(url); urlMenuBottomSheetFragment.show(getSupportFragmentManager(), null); return true; }; emoteCloseBracketInlineProcessor = new EmoteCloseBracketInlineProcessor(); emotePlugin = EmotePlugin.create(this, SharedPreferencesUtils.EMBEDDED_MEDIA_ALL, mediaMetadata -> { Intent intent = new Intent(this, ViewImageOrGifActivity.class); if (mediaMetadata.isGIF) { intent.putExtra(ViewImageOrGifActivity.EXTRA_GIF_URL_KEY, mediaMetadata.original.url); } else { intent.putExtra(ViewImageOrGifActivity.EXTRA_IMAGE_URL_KEY, mediaMetadata.original.url); } intent.putExtra(ViewImageOrGifActivity.EXTRA_SUBREDDIT_OR_USERNAME_KEY, mSubredditName); intent.putExtra(ViewImageOrGifActivity.EXTRA_FILE_NAME_KEY, mediaMetadata.fileName); }); imageAndGifPlugin = new ImageAndGifPlugin(); imageAndGifEntry = new ImageAndGifEntry(this, mGlide, SharedPreferencesUtils.EMBEDDED_MEDIA_ALL, mediaMetadata -> { Intent intent = new Intent(this, ViewImageOrGifActivity.class); if (mediaMetadata.isGIF) { intent.putExtra(ViewImageOrGifActivity.EXTRA_GIF_URL_KEY, mediaMetadata.original.url); } else { intent.putExtra(ViewImageOrGifActivity.EXTRA_IMAGE_URL_KEY, mediaMetadata.original.url); } intent.putExtra(ViewImageOrGifActivity.EXTRA_SUBREDDIT_OR_USERNAME_KEY, mSubredditName); intent.putExtra(ViewImageOrGifActivity.EXTRA_FILE_NAME_KEY, mediaMetadata.fileName); }); markwon = MarkdownUtils.createFullRedditMarkwon(this, miscPlugin, emoteCloseBracketInlineProcessor, emotePlugin, imageAndGifPlugin, markdownColor, spoilerBackgroundColor, onLinkLongClickListener); markwonAdapter = MarkdownUtils.createCustomTablesAndImagesAdapter(this, imageAndGifEntry); LinearLayoutManagerBugFixed linearLayoutManager = new SwipeLockLinearLayoutManager(this, new SwipeLockInterface() { @Override public void lockSwipe() { if (mSliderPanel != null) { mSliderPanel.lock(); } } @Override public void unlockSwipe() { if (mSliderPanel != null) { mSliderPanel.unlock(); } } }); binding.contentMarkdownViewCommentWikiActivity.setLayoutManager(linearLayoutManager); binding.contentMarkdownViewCommentWikiActivity.setAdapter(markwonAdapter); if (savedInstanceState != null) { wikiMarkdown = savedInstanceState.getString(WIKI_MARKDOWN_STATE); } if (wikiMarkdown == null) { loadWiki(); } else { markwonAdapter.setMarkdown(markwon, wikiMarkdown); // noinspection NotifyDataSetChanged markwonAdapter.notifyDataSetChanged(); } } private void loadWiki() { if (isRefreshing) { return; } isRefreshing = true; binding.swipeRefreshLayoutWikiActivity.setRefreshing(true); Glide.with(this).clear(binding.fetchWikiImageViewWikiActivity); binding.fetchWikiLinearLayoutWikiActivity.setVisibility(View.GONE); mRetrofit.create(RedditAPI.class).getWikiPage(mSubredditName, getIntent().getStringExtra(EXTRA_WIKI_PATH)).enqueue(new Callback<>() { @Override public void onResponse(@NonNull Call call, @NonNull Response response) { if (response.isSuccessful()) { try { String markdown = new JSONObject(response.body()) .getJSONObject(JSONUtils.DATA_KEY).getString(JSONUtils.CONTENT_MD_KEY); markwonAdapter.setMarkdown(markwon, Utils.modifyMarkdown(markdown)); // noinspection NotifyDataSetChanged markwonAdapter.notifyDataSetChanged(); } catch (JSONException e) { e.printStackTrace(); showErrorView(R.string.error_loading_wiki); } } else { if (response.code() == 404 || response.code() == 403) { showErrorView(R.string.no_wiki); } else { showErrorView(R.string.error_loading_wiki); } } isRefreshing = false; binding.swipeRefreshLayoutWikiActivity.setRefreshing(false); } @Override public void onFailure(@NonNull Call call, @NonNull Throwable t) { showErrorView(R.string.error_loading_wiki); isRefreshing = false; binding.swipeRefreshLayoutWikiActivity.setRefreshing(false); } }); } private void showErrorView(int stringResId) { binding.swipeRefreshLayoutWikiActivity.setRefreshing(false); binding.fetchWikiLinearLayoutWikiActivity.setVisibility(View.VISIBLE); binding.fetchWikiTextViewWikiActivity.setText(stringResId); mGlide.load(R.drawable.error_image).into(binding.fetchWikiImageViewWikiActivity); } @Override public boolean onOptionsItemSelected(@NonNull MenuItem item) { if (item.getItemId() == android.R.id.home) { finish(); return true; } return false; } @Override protected void onSaveInstanceState(@NonNull Bundle outState) { super.onSaveInstanceState(outState); outState.putString(WIKI_MARKDOWN_STATE, wikiMarkdown); } @Override protected void onDestroy() { super.onDestroy(); EventBus.getDefault().unregister(this); } @Override public SharedPreferences getDefaultSharedPreferences() { return mSharedPreferences; } @Override public SharedPreferences getCurrentAccountSharedPreferences() { return mCurrentAccountSharedPreferences; } @Override public CustomThemeWrapper getCustomThemeWrapper() { return mCustomThemeWrapper; } @Override protected void applyCustomTheme() { binding.getRoot().setBackgroundColor(mCustomThemeWrapper.getBackgroundColor()); applyAppBarLayoutAndCollapsingToolbarLayoutAndToolbarTheme(binding.appbarLayoutCommentWikiActivity, binding.collapsingToolbarLayoutWikiActivity, binding.toolbarCommentWikiActivity); binding.swipeRefreshLayoutWikiActivity.setProgressBackgroundColorSchemeColor(mCustomThemeWrapper.getCircularProgressBarBackground()); binding.swipeRefreshLayoutWikiActivity.setColorSchemeColors(mCustomThemeWrapper.getColorAccent()); binding.fetchWikiTextViewWikiActivity.setTextColor(mCustomThemeWrapper.getSecondaryTextColor()); if (typeface != null) { binding.fetchWikiTextViewWikiActivity.setTypeface(typeface); } } @Subscribe public void onAccountSwitchEvent(SwitchAccountEvent event) { if (!getClass().getName().equals(event.excludeActivityClassName)) { finish(); } } @Subscribe public void onChangeNetworkStatusEvent(ChangeNetworkStatusEvent changeNetworkStatusEvent) { String dataSavingMode = mSharedPreferences.getString(SharedPreferencesUtils.DATA_SAVING_MODE, SharedPreferencesUtils.DATA_SAVING_MODE_OFF); if (dataSavingMode.equals(SharedPreferencesUtils.DATA_SAVING_MODE_ONLY_ON_CELLULAR_DATA)) { if (emotePlugin != null) { emotePlugin.setDataSavingMode(changeNetworkStatusEvent.connectedNetwork == Utils.NETWORK_TYPE_CELLULAR); } if (imageAndGifEntry != null) { imageAndGifEntry.setDataSavingMode(changeNetworkStatusEvent.connectedNetwork == Utils.NETWORK_TYPE_CELLULAR); } } } }