Merge pull request #183 from FineFindus/feat/settings-redesign
feat(settings): refactor and redesign
This commit is contained in:
commit
e49e485ba3
|
@ -31,14 +31,13 @@ public class GlobalUserPreferences{
|
||||||
public static boolean alwaysExpandContentWarnings;
|
public static boolean alwaysExpandContentWarnings;
|
||||||
public static boolean disableMarquee;
|
public static boolean disableMarquee;
|
||||||
public static boolean disableSwipe;
|
public static boolean disableSwipe;
|
||||||
public static boolean disableDividers;
|
public static boolean showDividers;
|
||||||
public static boolean voteButtonForSingleChoice;
|
public static boolean voteButtonForSingleChoice;
|
||||||
public static boolean uniformNotificationIcon;
|
public static boolean uniformNotificationIcon;
|
||||||
public static boolean enableDeleteNotifications;
|
public static boolean enableDeleteNotifications;
|
||||||
public static boolean relocatePublishButton;
|
public static boolean relocatePublishButton;
|
||||||
public static boolean reduceMotion;
|
public static boolean reduceMotion;
|
||||||
public static boolean keepOnlyLatestNotification;
|
public static boolean keepOnlyLatestNotification;
|
||||||
public static boolean enableFabAutoHide;
|
|
||||||
public static boolean disableAltTextReminder;
|
public static boolean disableAltTextReminder;
|
||||||
public static boolean showAltIndicator;
|
public static boolean showAltIndicator;
|
||||||
public static boolean showNoAltIndicator;
|
public static boolean showNoAltIndicator;
|
||||||
|
@ -49,7 +48,7 @@ public class GlobalUserPreferences{
|
||||||
public static boolean spectatorMode;
|
public static boolean spectatorMode;
|
||||||
public static boolean autoHideFab;
|
public static boolean autoHideFab;
|
||||||
public static boolean defaultToUnlistedReplies;
|
public static boolean defaultToUnlistedReplies;
|
||||||
public static boolean disableDoubleTapToSwipe;
|
public static boolean doubleTapToSwipe;
|
||||||
public static boolean compactReblogReplyLine;
|
public static boolean compactReblogReplyLine;
|
||||||
public static boolean confirmBeforeReblog;
|
public static boolean confirmBeforeReblog;
|
||||||
public static boolean replyLineAboveHeader;
|
public static boolean replyLineAboveHeader;
|
||||||
|
@ -103,13 +102,12 @@ public class GlobalUserPreferences{
|
||||||
alwaysExpandContentWarnings=prefs.getBoolean("alwaysExpandContentWarnings", false);
|
alwaysExpandContentWarnings=prefs.getBoolean("alwaysExpandContentWarnings", false);
|
||||||
disableMarquee=prefs.getBoolean("disableMarquee", false);
|
disableMarquee=prefs.getBoolean("disableMarquee", false);
|
||||||
disableSwipe=prefs.getBoolean("disableSwipe", false);
|
disableSwipe=prefs.getBoolean("disableSwipe", false);
|
||||||
disableDividers=prefs.getBoolean("disableDividers", true);
|
showDividers =prefs.getBoolean("showDividers", false);
|
||||||
relocatePublishButton=prefs.getBoolean("relocatePublishButton", true);
|
relocatePublishButton=prefs.getBoolean("relocatePublishButton", true);
|
||||||
voteButtonForSingleChoice=prefs.getBoolean("voteButtonForSingleChoice", true);
|
voteButtonForSingleChoice=prefs.getBoolean("voteButtonForSingleChoice", true);
|
||||||
enableDeleteNotifications=prefs.getBoolean("enableDeleteNotifications", false);
|
enableDeleteNotifications=prefs.getBoolean("enableDeleteNotifications", false);
|
||||||
reduceMotion=prefs.getBoolean("reduceMotion", false);
|
reduceMotion=prefs.getBoolean("reduceMotion", false);
|
||||||
keepOnlyLatestNotification=prefs.getBoolean("keepOnlyLatestNotification", false);
|
keepOnlyLatestNotification=prefs.getBoolean("keepOnlyLatestNotification", false);
|
||||||
enableFabAutoHide=prefs.getBoolean("enableFabAutoHide", true);
|
|
||||||
disableAltTextReminder=prefs.getBoolean("disableAltTextReminder", false);
|
disableAltTextReminder=prefs.getBoolean("disableAltTextReminder", false);
|
||||||
showAltIndicator=prefs.getBoolean("showAltIndicator", true);
|
showAltIndicator=prefs.getBoolean("showAltIndicator", true);
|
||||||
showNoAltIndicator=prefs.getBoolean("showNoAltIndicator", true);
|
showNoAltIndicator=prefs.getBoolean("showNoAltIndicator", true);
|
||||||
|
@ -121,7 +119,7 @@ public class GlobalUserPreferences{
|
||||||
autoHideFab=prefs.getBoolean("autoHideFab", true);
|
autoHideFab=prefs.getBoolean("autoHideFab", true);
|
||||||
compactReblogReplyLine=prefs.getBoolean("compactReblogReplyLine", true);
|
compactReblogReplyLine=prefs.getBoolean("compactReblogReplyLine", true);
|
||||||
defaultToUnlistedReplies=prefs.getBoolean("defaultToUnlistedReplies", false);
|
defaultToUnlistedReplies=prefs.getBoolean("defaultToUnlistedReplies", false);
|
||||||
disableDoubleTapToSwipe=prefs.getBoolean("disableDoubleTapToSwipe", false);
|
doubleTapToSwipe =prefs.getBoolean("doubleTapToSwipe", true);
|
||||||
replyLineAboveHeader=prefs.getBoolean("replyLineAboveHeader", true);
|
replyLineAboveHeader=prefs.getBoolean("replyLineAboveHeader", true);
|
||||||
compactReblogReplyLine=prefs.getBoolean("compactReblogReplyLine", true);
|
compactReblogReplyLine=prefs.getBoolean("compactReblogReplyLine", true);
|
||||||
confirmBeforeReblog=prefs.getBoolean("confirmBeforeReblog", false);
|
confirmBeforeReblog=prefs.getBoolean("confirmBeforeReblog", false);
|
||||||
|
@ -165,13 +163,12 @@ public class GlobalUserPreferences{
|
||||||
.putBoolean("alwaysExpandContentWarnings", alwaysExpandContentWarnings)
|
.putBoolean("alwaysExpandContentWarnings", alwaysExpandContentWarnings)
|
||||||
.putBoolean("disableMarquee", disableMarquee)
|
.putBoolean("disableMarquee", disableMarquee)
|
||||||
.putBoolean("disableSwipe", disableSwipe)
|
.putBoolean("disableSwipe", disableSwipe)
|
||||||
.putBoolean("disableDividers", disableDividers)
|
.putBoolean("showDividers", showDividers)
|
||||||
.putBoolean("relocatePublishButton", relocatePublishButton)
|
.putBoolean("relocatePublishButton", relocatePublishButton)
|
||||||
.putBoolean("uniformNotificationIcon", uniformNotificationIcon)
|
.putBoolean("uniformNotificationIcon", uniformNotificationIcon)
|
||||||
.putBoolean("enableDeleteNotifications", enableDeleteNotifications)
|
.putBoolean("enableDeleteNotifications", enableDeleteNotifications)
|
||||||
.putBoolean("reduceMotion", reduceMotion)
|
.putBoolean("reduceMotion", reduceMotion)
|
||||||
.putBoolean("keepOnlyLatestNotification", keepOnlyLatestNotification)
|
.putBoolean("keepOnlyLatestNotification", keepOnlyLatestNotification)
|
||||||
.putBoolean("enableFabAutoHide", enableFabAutoHide)
|
|
||||||
.putBoolean("disableAltTextReminder", disableAltTextReminder)
|
.putBoolean("disableAltTextReminder", disableAltTextReminder)
|
||||||
.putBoolean("showAltIndicator", showAltIndicator)
|
.putBoolean("showAltIndicator", showAltIndicator)
|
||||||
.putBoolean("showNoAltIndicator", showNoAltIndicator)
|
.putBoolean("showNoAltIndicator", showNoAltIndicator)
|
||||||
|
@ -183,7 +180,7 @@ public class GlobalUserPreferences{
|
||||||
.putString("publishButtonText", publishButtonText)
|
.putString("publishButtonText", publishButtonText)
|
||||||
.putBoolean("bottomEncoding", bottomEncoding)
|
.putBoolean("bottomEncoding", bottomEncoding)
|
||||||
.putBoolean("defaultToUnlistedReplies", defaultToUnlistedReplies)
|
.putBoolean("defaultToUnlistedReplies", defaultToUnlistedReplies)
|
||||||
.putBoolean("disableDoubleTapToSwipe", disableDoubleTapToSwipe)
|
.putBoolean("doubleTapToSwipe", doubleTapToSwipe)
|
||||||
.putBoolean("compactReblogReplyLine", compactReblogReplyLine)
|
.putBoolean("compactReblogReplyLine", compactReblogReplyLine)
|
||||||
.putBoolean("replyLineAboveHeader", replyLineAboveHeader)
|
.putBoolean("replyLineAboveHeader", replyLineAboveHeader)
|
||||||
.putBoolean("confirmBeforeReblog", confirmBeforeReblog)
|
.putBoolean("confirmBeforeReblog", confirmBeforeReblog)
|
||||||
|
|
|
@ -13,7 +13,6 @@ import android.text.Layout;
|
||||||
import android.text.StaticLayout;
|
import android.text.StaticLayout;
|
||||||
import android.text.TextPaint;
|
import android.text.TextPaint;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.view.LayoutInflater;
|
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.view.WindowInsets;
|
import android.view.WindowInsets;
|
||||||
|
@ -21,14 +20,15 @@ import android.view.animation.TranslateAnimation;
|
||||||
import android.widget.ImageButton;
|
import android.widget.ImageButton;
|
||||||
import android.widget.Toolbar;
|
import android.widget.Toolbar;
|
||||||
|
|
||||||
import org.joinmastodon.android.DomainManager;
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
|
||||||
import org.joinmastodon.android.E;
|
import org.joinmastodon.android.E;
|
||||||
import org.joinmastodon.android.GlobalUserPreferences;
|
import org.joinmastodon.android.GlobalUserPreferences;
|
||||||
import org.joinmastodon.android.MainActivity;
|
|
||||||
import org.joinmastodon.android.R;
|
import org.joinmastodon.android.R;
|
||||||
import org.joinmastodon.android.api.requests.accounts.GetAccountRelationships;
|
import org.joinmastodon.android.api.requests.accounts.GetAccountRelationships;
|
||||||
import org.joinmastodon.android.api.requests.polls.SubmitPollVote;
|
import org.joinmastodon.android.api.requests.polls.SubmitPollVote;
|
||||||
import org.joinmastodon.android.api.session.AccountSessionManager;
|
|
||||||
import org.joinmastodon.android.events.PollUpdatedEvent;
|
import org.joinmastodon.android.events.PollUpdatedEvent;
|
||||||
import org.joinmastodon.android.model.Account;
|
import org.joinmastodon.android.model.Account;
|
||||||
import org.joinmastodon.android.model.DisplayItemsParent;
|
import org.joinmastodon.android.model.DisplayItemsParent;
|
||||||
|
@ -58,10 +58,6 @@ import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
import androidx.annotation.Nullable;
|
|
||||||
import androidx.recyclerview.widget.RecyclerView;
|
|
||||||
|
|
||||||
import me.grishka.appkit.Nav;
|
import me.grishka.appkit.Nav;
|
||||||
import me.grishka.appkit.api.Callback;
|
import me.grishka.appkit.api.Callback;
|
||||||
import me.grishka.appkit.api.ErrorResponse;
|
import me.grishka.appkit.api.ErrorResponse;
|
||||||
|
@ -317,7 +313,7 @@ public abstract class BaseStatusListFragment<T extends DisplayItemsParent> exten
|
||||||
currentPhotoViewer.offsetView(-dx, -dy);
|
currentPhotoViewer.offsetView(-dx, -dy);
|
||||||
|
|
||||||
View fab = getFab();
|
View fab = getFab();
|
||||||
if (fab!=null && GlobalUserPreferences.enableFabAutoHide) {
|
if (fab!=null && GlobalUserPreferences.autoHideFab) {
|
||||||
if (dy > 0 && fab.getVisibility() == View.VISIBLE) {
|
if (dy > 0 && fab.getVisibility() == View.VISIBLE) {
|
||||||
animateFab(false);
|
animateFab(false);
|
||||||
} else if (dy < 0 && fab.getVisibility() != View.VISIBLE) {
|
} else if (dy < 0 && fab.getVisibility() != View.VISIBLE) {
|
||||||
|
@ -763,7 +759,7 @@ public abstract class BaseStatusListFragment<T extends DisplayItemsParent> exten
|
||||||
private int currentMediaHiddenLayoutsWidth=0;
|
private int currentMediaHiddenLayoutsWidth=0;
|
||||||
|
|
||||||
{
|
{
|
||||||
dividerPaint.setColor(UiUtils.getThemeColor(getActivity(), GlobalUserPreferences.disableDividers ? R.attr.colorWindowBackground : R.attr.colorPollVoted));
|
dividerPaint.setColor(UiUtils.getThemeColor(getActivity(), GlobalUserPreferences.showDividers ? R.attr.colorPollVoted : R.attr.colorWindowBackground));
|
||||||
dividerPaint.setStyle(Paint.Style.STROKE);
|
dividerPaint.setStyle(Paint.Style.STROKE);
|
||||||
dividerPaint.setStrokeWidth(V.dp(1));
|
dividerPaint.setStrokeWidth(V.dp(1));
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
package org.joinmastodon.android.fragments;
|
package org.joinmastodon.android.fragments;
|
||||||
|
|
||||||
import static org.joinmastodon.android.GlobalUserPreferences.reduceMotion;
|
import static org.joinmastodon.android.GlobalUserPreferences.reduceMotion;
|
||||||
import static org.joinmastodon.android.GlobalUserPreferences.showNewPostsButton;
|
|
||||||
|
|
||||||
import android.animation.Animator;
|
import android.animation.Animator;
|
||||||
import android.animation.AnimatorListenerAdapter;
|
import android.animation.AnimatorListenerAdapter;
|
||||||
|
@ -48,6 +47,7 @@ import org.joinmastodon.android.events.HashtagUpdatedEvent;
|
||||||
import org.joinmastodon.android.events.ListDeletedEvent;
|
import org.joinmastodon.android.events.ListDeletedEvent;
|
||||||
import org.joinmastodon.android.events.ListUpdatedCreatedEvent;
|
import org.joinmastodon.android.events.ListUpdatedCreatedEvent;
|
||||||
import org.joinmastodon.android.events.SelfUpdateStateChangedEvent;
|
import org.joinmastodon.android.events.SelfUpdateStateChangedEvent;
|
||||||
|
import org.joinmastodon.android.fragments.settings.SettingsMainFragment;
|
||||||
import org.joinmastodon.android.model.Announcement;
|
import org.joinmastodon.android.model.Announcement;
|
||||||
import org.joinmastodon.android.model.Hashtag;
|
import org.joinmastodon.android.model.Hashtag;
|
||||||
import org.joinmastodon.android.model.HeaderPaginationList;
|
import org.joinmastodon.android.model.HeaderPaginationList;
|
||||||
|
@ -484,7 +484,7 @@ public class HomeTabFragment extends MastodonToolbarFragment implements Scrollab
|
||||||
getToolbar().post(() -> overflowPopup.show());
|
getToolbar().post(() -> overflowPopup.show());
|
||||||
return true;
|
return true;
|
||||||
} else if (id == R.id.settings || id == R.id.settings_action) {
|
} else if (id == R.id.settings || id == R.id.settings_action) {
|
||||||
Nav.go(getActivity(), SettingsFragment.class, args);
|
Nav.go(getActivity(), SettingsMainFragment.class, args);
|
||||||
} else if (id == R.id.announcements || id == R.id.announcements_action) {
|
} else if (id == R.id.announcements || id == R.id.announcements_action) {
|
||||||
Nav.goForResult(getActivity(), AnnouncementsFragment.class, args, ANNOUNCEMENTS_RESULT, this);
|
Nav.goForResult(getActivity(), AnnouncementsFragment.class, args, ANNOUNCEMENTS_RESULT, this);
|
||||||
} else if (id == R.id.edit_timelines) {
|
} else if (id == R.id.edit_timelines) {
|
||||||
|
@ -505,7 +505,7 @@ public class HomeTabFragment extends MastodonToolbarFragment implements Scrollab
|
||||||
@Override
|
@Override
|
||||||
public void scrollToTop(){
|
public void scrollToTop(){
|
||||||
if (((ScrollableToTop) fragments[pager.getCurrentItem()]).isScrolledToTop() &&
|
if (((ScrollableToTop) fragments[pager.getCurrentItem()]).isScrolledToTop() &&
|
||||||
!GlobalUserPreferences.disableDoubleTapToSwipe && !newPostsBtnShown) {
|
GlobalUserPreferences.doubleTapToSwipe && !newPostsBtnShown) {
|
||||||
int nextPage = (pager.getCurrentItem() + 1) % count;
|
int nextPage = (pager.getCurrentItem() + 1) % count;
|
||||||
navigateTo(nextPage);
|
navigateTo(nextPage);
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -205,7 +205,7 @@ public class NotificationsFragment extends MastodonToolbarFragment implements Sc
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void scrollToTop(){
|
public void scrollToTop(){
|
||||||
if (getFragmentForPage(pager.getCurrentItem()).isScrolledToTop() && !GlobalUserPreferences.disableDoubleTapToSwipe) {
|
if (getFragmentForPage(pager.getCurrentItem()).isScrolledToTop() && GlobalUserPreferences.doubleTapToSwipe) {
|
||||||
int nextPage = (pager.getCurrentItem() + 1) % tabViews.length;
|
int nextPage = (pager.getCurrentItem() + 1) % tabViews.length;
|
||||||
pager.setCurrentItem(nextPage, true);
|
pager.setCurrentItem(nextPage, true);
|
||||||
return;
|
return;
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -23,8 +23,7 @@ import org.joinmastodon.android.api.requests.accounts.UpdateAccountCredentials;
|
||||||
import org.joinmastodon.android.api.session.AccountActivationInfo;
|
import org.joinmastodon.android.api.session.AccountActivationInfo;
|
||||||
import org.joinmastodon.android.api.session.AccountSession;
|
import org.joinmastodon.android.api.session.AccountSession;
|
||||||
import org.joinmastodon.android.api.session.AccountSessionManager;
|
import org.joinmastodon.android.api.session.AccountSessionManager;
|
||||||
import org.joinmastodon.android.fragments.HomeFragment;
|
import org.joinmastodon.android.fragments.settings.SettingsMainFragment;
|
||||||
import org.joinmastodon.android.fragments.SettingsFragment;
|
|
||||||
import org.joinmastodon.android.model.Account;
|
import org.joinmastodon.android.model.Account;
|
||||||
import org.joinmastodon.android.ui.AccountSwitcherSheet;
|
import org.joinmastodon.android.ui.AccountSwitcherSheet;
|
||||||
import org.joinmastodon.android.ui.utils.UiUtils;
|
import org.joinmastodon.android.ui.utils.UiUtils;
|
||||||
|
@ -70,7 +69,7 @@ public class AccountActivationFragment extends ToolbarFragment{
|
||||||
openEmailBtn.setOnLongClickListener(v->{
|
openEmailBtn.setOnLongClickListener(v->{
|
||||||
Bundle args=new Bundle();
|
Bundle args=new Bundle();
|
||||||
args.putString("account", accountID);
|
args.putString("account", accountID);
|
||||||
Nav.go(getActivity(), SettingsFragment.class, args);
|
Nav.go(getActivity(), SettingsMainFragment.class, args);
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
resendBtn=view.findViewById(R.id.btn_resend);
|
resendBtn=view.findViewById(R.id.btn_resend);
|
||||||
|
|
|
@ -0,0 +1,123 @@
|
||||||
|
package org.joinmastodon.android.fragments.settings;
|
||||||
|
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.net.Uri;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.provider.Settings;
|
||||||
|
import android.text.TextUtils;
|
||||||
|
import android.util.LruCache;
|
||||||
|
import android.widget.Toast;
|
||||||
|
|
||||||
|
import org.joinmastodon.android.BuildConfig;
|
||||||
|
import org.joinmastodon.android.GlobalUserPreferences;
|
||||||
|
import org.joinmastodon.android.MainActivity;
|
||||||
|
import org.joinmastodon.android.R;
|
||||||
|
import org.joinmastodon.android.api.MastodonAPIController;
|
||||||
|
import org.joinmastodon.android.api.requests.oauth.RevokeOauthToken;
|
||||||
|
import org.joinmastodon.android.api.session.AccountActivationInfo;
|
||||||
|
import org.joinmastodon.android.api.session.AccountSession;
|
||||||
|
import org.joinmastodon.android.api.session.AccountSessionManager;
|
||||||
|
import org.joinmastodon.android.fragments.onboarding.AccountActivationFragment;
|
||||||
|
import org.joinmastodon.android.fragments.onboarding.InstanceRulesFragment;
|
||||||
|
import org.joinmastodon.android.ui.M3AlertDialogBuilder;
|
||||||
|
import org.joinmastodon.android.ui.utils.UiUtils;
|
||||||
|
import org.joinmastodon.android.updater.GithubSelfUpdater;
|
||||||
|
import org.parceler.Parcels;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
import me.grishka.appkit.Nav;
|
||||||
|
import me.grishka.appkit.api.Callback;
|
||||||
|
import me.grishka.appkit.api.ErrorResponse;
|
||||||
|
import me.grishka.appkit.imageloader.ImageCache;
|
||||||
|
|
||||||
|
public class AboutFragment extends SettingsBaseFragment{
|
||||||
|
|
||||||
|
private TextItem clearImageCacheItem;
|
||||||
|
private ImageCache imageCache;
|
||||||
|
@Override
|
||||||
|
public void addItems(ArrayList<Item> items) {
|
||||||
|
|
||||||
|
imageCache = ImageCache.getInstance(getActivity());
|
||||||
|
|
||||||
|
items.add(new TextItem(R.string.mo_settings_contribute, ()->UiUtils.launchWebBrowser(getActivity(), "https://github.com/LucasGGamerM/moshidon"), R.drawable.ic_fluent_open_24_regular));
|
||||||
|
items.add(new TextItem(R.string.sk_settings_donate, ()->UiUtils.launchWebBrowser(getActivity(), "https://github.com/sponsors/LucasGGamerM"), R.drawable.ic_fluent_heart_24_regular));
|
||||||
|
|
||||||
|
if (GithubSelfUpdater.needSelfUpdating()) {
|
||||||
|
TextItem checkForUpdateItem = new TextItem(R.string.sk_check_for_update, GithubSelfUpdater.getInstance()::checkForUpdates);
|
||||||
|
items.add(checkForUpdateItem);
|
||||||
|
items.add(new SwitchItem(R.string.sk_updater_enable_pre_releases, 0, GlobalUserPreferences.enablePreReleases, i->{
|
||||||
|
GlobalUserPreferences.enablePreReleases=i.checked;
|
||||||
|
GlobalUserPreferences.save();
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
LruCache<?, ?> cache = imageCache == null ? null : imageCache.getLruCache();
|
||||||
|
clearImageCacheItem = new TextItem(R.string.settings_clear_cache, UiUtils.formatFileSize(getContext(), cache != null ? cache.size() : 0, true), this::clearImageCache, 0);
|
||||||
|
items.add(clearImageCacheItem);
|
||||||
|
items.add(new TextItem(R.string.sk_clear_recent_languages, ()->UiUtils.showConfirmationAlert(getActivity(), R.string.sk_clear_recent_languages, R.string.sk_confirm_clear_recent_languages, R.string.clear, ()->{
|
||||||
|
GlobalUserPreferences.recentLanguages.remove(accountID);
|
||||||
|
GlobalUserPreferences.save();
|
||||||
|
})));
|
||||||
|
|
||||||
|
items.add(new TextItem(R.string.mo_clear_recent_emoji, ()-> {
|
||||||
|
GlobalUserPreferences.recentEmojis.clear();
|
||||||
|
GlobalUserPreferences.save();
|
||||||
|
}));
|
||||||
|
|
||||||
|
if(BuildConfig.DEBUG){
|
||||||
|
items.add(new RedHeaderItem("Debug options"));
|
||||||
|
|
||||||
|
items.add(new TextItem("Test E-Mail confirmation flow", ()->{
|
||||||
|
AccountSession sess=AccountSessionManager.getInstance().getAccount(accountID);
|
||||||
|
sess.activated=false;
|
||||||
|
sess.activationInfo=new AccountActivationInfo("test@email", System.currentTimeMillis());
|
||||||
|
Bundle args=new Bundle();
|
||||||
|
args.putString("account", accountID);
|
||||||
|
args.putBoolean("debug", true);
|
||||||
|
Nav.goClearingStack(getActivity(), AccountActivationFragment.class, args);
|
||||||
|
}));
|
||||||
|
|
||||||
|
items.add(new TextItem("Copy preferences", ()->{
|
||||||
|
StringBuilder prefBuilder = new StringBuilder();
|
||||||
|
GlobalUserPreferences.load();
|
||||||
|
GlobalUserPreferences.getPrefs().getAll().forEach((key, value) -> prefBuilder.append(key).append(": ").append(value).append('\n'));
|
||||||
|
UiUtils.copyText(view, prefBuilder.toString());
|
||||||
|
}));
|
||||||
|
|
||||||
|
items.add(new TextItem("Reset preferences", ()->{
|
||||||
|
GlobalUserPreferences.load();
|
||||||
|
GlobalUserPreferences.getPrefs().edit().clear().commit();
|
||||||
|
UiUtils.restartApp();
|
||||||
|
}, R.drawable.ic_fluent_warning_24_regular));
|
||||||
|
|
||||||
|
items.add(new TextItem("Open App Info", () ->
|
||||||
|
getContext().startActivity(new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS)
|
||||||
|
.setData(Uri.fromParts("package", getContext().getPackageName(), null))),
|
||||||
|
R.drawable.ic_fluent_open_24_regular
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
items.add(new TextItem("Open developer settings",
|
||||||
|
()-> getContext().startActivity(new Intent(Settings.ACTION_APPLICATION_DEVELOPMENT_SETTINGS)),
|
||||||
|
R.drawable.ic_fluent_open_24_regular)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
String version = getContext().getString(R.string.mo_settings_app_version, BuildConfig.VERSION_NAME, BuildConfig.VERSION_CODE);
|
||||||
|
items.add(new FooterItem(version, () -> UiUtils.copyText(view, version)));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void clearImageCache(){
|
||||||
|
MastodonAPIController.runInBackground(()->{
|
||||||
|
Activity activity=getActivity();
|
||||||
|
imageCache.clear();
|
||||||
|
Toast.makeText(activity, R.string.media_cache_cleared, Toast.LENGTH_SHORT).show();
|
||||||
|
});
|
||||||
|
if (list.findViewHolderForAdapterPosition(items.indexOf(clearImageCacheItem)) instanceof TextViewHolder tvh) {
|
||||||
|
clearImageCacheItem.secondaryText = UiUtils.formatFileSize(getContext(), 0, true);
|
||||||
|
tvh.rebind();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,181 @@
|
||||||
|
package org.joinmastodon.android.fragments.settings;
|
||||||
|
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.text.TextUtils;
|
||||||
|
import android.view.Gravity;
|
||||||
|
import android.view.Menu;
|
||||||
|
import android.view.MenuItem;
|
||||||
|
import android.widget.Button;
|
||||||
|
import android.widget.PopupMenu;
|
||||||
|
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
import androidx.annotation.StringRes;
|
||||||
|
|
||||||
|
import org.joinmastodon.android.GlobalUserPreferences;
|
||||||
|
import org.joinmastodon.android.MainActivity;
|
||||||
|
import org.joinmastodon.android.R;
|
||||||
|
import org.joinmastodon.android.api.requests.oauth.RevokeOauthToken;
|
||||||
|
import org.joinmastodon.android.api.session.AccountSession;
|
||||||
|
import org.joinmastodon.android.api.session.AccountSessionManager;
|
||||||
|
import org.joinmastodon.android.fragments.onboarding.InstanceRulesFragment;
|
||||||
|
import org.joinmastodon.android.model.ContentType;
|
||||||
|
import org.joinmastodon.android.ui.M3AlertDialogBuilder;
|
||||||
|
import org.joinmastodon.android.ui.utils.UiUtils;
|
||||||
|
import org.parceler.Parcels;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
import me.grishka.appkit.Nav;
|
||||||
|
import me.grishka.appkit.api.Callback;
|
||||||
|
import me.grishka.appkit.api.ErrorResponse;
|
||||||
|
|
||||||
|
public class AccountFragment extends SettingsBaseFragment{
|
||||||
|
|
||||||
|
|
||||||
|
private SwitchItem glitchModeItem;
|
||||||
|
private ButtonItem defaultContentTypeButtonItem;
|
||||||
|
private Menu contentTypeMenu;
|
||||||
|
@Override
|
||||||
|
public void addItems(ArrayList<Item> items) {
|
||||||
|
items.add(new HeaderItem(R.string.settings_account));
|
||||||
|
items.add(new TextItem(R.string.sk_settings_profile, ()-> UiUtils.launchWebBrowser(getActivity(), "https://"+session.domain+"/settings/profile"), R.drawable.ic_fluent_open_24_regular));
|
||||||
|
items.add(new TextItem(R.string.sk_settings_posting, ()->UiUtils.launchWebBrowser(getActivity(), "https://"+session.domain+"/settings/preferences/other"), R.drawable.ic_fluent_open_24_regular));
|
||||||
|
items.add(new TextItem(R.string.sk_settings_filters, ()->UiUtils.launchWebBrowser(getActivity(), "https://"+session.domain+"/filters"), R.drawable.ic_fluent_open_24_regular));
|
||||||
|
items.add(new TextItem(R.string.sk_settings_auth, ()->UiUtils.launchWebBrowser(getActivity(), "https://"+session.domain+"/auth/edit"), R.drawable.ic_fluent_open_24_regular));
|
||||||
|
|
||||||
|
items.add(new HeaderItem(getInstanceName()));
|
||||||
|
items.add(new TextItem(R.string.sk_settings_rules, ()->{
|
||||||
|
Bundle args=new Bundle();
|
||||||
|
args.putParcelable("instance", Parcels.wrap(getInstance()));
|
||||||
|
Nav.go(getActivity(), InstanceRulesFragment.class, args);
|
||||||
|
}, R.drawable.ic_fluent_task_list_ltr_24_regular));
|
||||||
|
items.add(new TextItem(R.string.sk_settings_about_instance , ()->UiUtils.launchWebBrowser(getActivity(), "https://"+session.domain+"/about"), R.drawable.ic_fluent_info_24_regular));
|
||||||
|
items.add(new TextItem(R.string.settings_tos, ()->UiUtils.launchWebBrowser(getActivity(), "https://"+session.domain+"/terms"), R.drawable.ic_fluent_open_24_regular));
|
||||||
|
items.add(new TextItem(R.string.settings_privacy_policy, ()->UiUtils.launchWebBrowser(getActivity(), "https://"+session.domain+"/terms"), R.drawable.ic_fluent_open_24_regular));
|
||||||
|
items.add(new TextItem(R.string.log_out, this::confirmLogOut, R.drawable.ic_fluent_sign_out_24_regular));
|
||||||
|
if (!TextUtils.isEmpty(getInstance().version)) items.add(new SmallTextItem(getString(R.string.sk_settings_server_version, getInstance().version)));
|
||||||
|
|
||||||
|
items.add(new HeaderItem(R.string.sk_instance_features));
|
||||||
|
items.add(new SwitchItem(R.string.sk_settings_content_types, R.string.sk_settings_content_types_explanation, 0, GlobalUserPreferences.accountsWithContentTypesEnabled.contains(accountID), (i)->{
|
||||||
|
if (i.checked) {
|
||||||
|
GlobalUserPreferences.accountsWithContentTypesEnabled.add(accountID);
|
||||||
|
if (GlobalUserPreferences.accountsDefaultContentTypes.get(accountID) == null) {
|
||||||
|
GlobalUserPreferences.accountsDefaultContentTypes.put(accountID, ContentType.PLAIN);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
GlobalUserPreferences.accountsWithContentTypesEnabled.remove(accountID);
|
||||||
|
GlobalUserPreferences.accountsDefaultContentTypes.remove(accountID);
|
||||||
|
}
|
||||||
|
if (list.findViewHolderForAdapterPosition(items.indexOf(defaultContentTypeButtonItem))
|
||||||
|
instanceof ButtonViewHolder bvh) bvh.rebind();
|
||||||
|
GlobalUserPreferences.save();
|
||||||
|
}));
|
||||||
|
items.add(defaultContentTypeButtonItem = new ButtonItem(R.string.sk_settings_default_content_type, R.string.sk_settings_default_content_type_explanation, 0, b->{
|
||||||
|
PopupMenu popupMenu=new PopupMenu(getActivity(), b, Gravity.CENTER_HORIZONTAL);
|
||||||
|
popupMenu.inflate(R.menu.compose_content_type);
|
||||||
|
popupMenu.setOnMenuItemClickListener(item -> this.onContentTypeChanged(item, b));
|
||||||
|
b.setOnTouchListener(popupMenu.getDragToOpenListener());
|
||||||
|
b.setOnClickListener(v->popupMenu.show());
|
||||||
|
ContentType contentType = GlobalUserPreferences.accountsDefaultContentTypes.get(accountID);
|
||||||
|
b.setText(getContentTypeString(contentType));
|
||||||
|
contentTypeMenu = popupMenu.getMenu();
|
||||||
|
contentTypeMenu.findItem(ContentType.getContentTypeRes(contentType)).setChecked(true);
|
||||||
|
ContentType.adaptMenuToInstance(contentTypeMenu, getInstance());
|
||||||
|
contentTypeMenu.findItem(R.id.content_type_null).setVisible(
|
||||||
|
!GlobalUserPreferences.accountsWithContentTypesEnabled.contains(accountID));
|
||||||
|
}));
|
||||||
|
items.add(new SwitchItem(R.string.sk_settings_support_local_only, R.string.sk_settings_local_only_explanation, 0, GlobalUserPreferences.accountsWithLocalOnlySupport.contains(accountID), i->{
|
||||||
|
glitchModeItem.enabled = i.checked;
|
||||||
|
if (i.checked) {
|
||||||
|
GlobalUserPreferences.accountsWithLocalOnlySupport.add(accountID);
|
||||||
|
if (getInstance().pleroma == null) GlobalUserPreferences.accountsInGlitchMode.add(accountID);
|
||||||
|
} else {
|
||||||
|
GlobalUserPreferences.accountsWithLocalOnlySupport.remove(accountID);
|
||||||
|
GlobalUserPreferences.accountsInGlitchMode.remove(accountID);
|
||||||
|
}
|
||||||
|
glitchModeItem.checked = GlobalUserPreferences.accountsInGlitchMode.contains(accountID);
|
||||||
|
if (list.findViewHolderForAdapterPosition(items.indexOf(glitchModeItem)) instanceof SwitchViewHolder svh) svh.rebind();
|
||||||
|
GlobalUserPreferences.save();
|
||||||
|
}));
|
||||||
|
items.add(glitchModeItem = new SwitchItem(R.string.sk_settings_glitch_instance, R.string.sk_settings_glitch_mode_explanation, 0, GlobalUserPreferences.accountsInGlitchMode.contains(accountID), i->{
|
||||||
|
if (i.checked) {
|
||||||
|
GlobalUserPreferences.accountsInGlitchMode.add(accountID);
|
||||||
|
} else {
|
||||||
|
GlobalUserPreferences.accountsInGlitchMode.remove(accountID);
|
||||||
|
}
|
||||||
|
GlobalUserPreferences.save();
|
||||||
|
}));
|
||||||
|
glitchModeItem.enabled = GlobalUserPreferences.accountsWithLocalOnlySupport.contains(accountID);
|
||||||
|
|
||||||
|
|
||||||
|
boolean translationAvailable = getInstance().v2 != null && getInstance().v2.configuration.translation != null && getInstance().v2.configuration.translation.enabled;
|
||||||
|
items.add(new SmallTextItem(getString(translationAvailable ?
|
||||||
|
R.string.sk_settings_translation_availability_note_available :
|
||||||
|
R.string.sk_settings_translation_availability_note_unavailable, getInstance().title)));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private void confirmLogOut(){
|
||||||
|
new M3AlertDialogBuilder(getActivity())
|
||||||
|
.setTitle(R.string.log_out)
|
||||||
|
.setMessage(R.string.confirm_log_out)
|
||||||
|
.setPositiveButton(R.string.log_out, (dialog, which) -> logOut())
|
||||||
|
.setNegativeButton(R.string.cancel, null)
|
||||||
|
.show();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void logOut(){
|
||||||
|
AccountSession session= AccountSessionManager.getInstance().getAccount(accountID);
|
||||||
|
new RevokeOauthToken(session.app.clientId, session.app.clientSecret, session.token.accessToken)
|
||||||
|
.setCallback(new Callback<>(){
|
||||||
|
@Override
|
||||||
|
public void onSuccess(Object result){
|
||||||
|
onLoggedOut();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onError(ErrorResponse error){
|
||||||
|
onLoggedOut();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.wrapProgress(getActivity(), R.string.loading, false)
|
||||||
|
.exec(accountID);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void onLoggedOut(){
|
||||||
|
if (getActivity() == null) return;
|
||||||
|
AccountSessionManager.getInstance().removeAccount(accountID);
|
||||||
|
getActivity().finish();
|
||||||
|
Intent intent=new Intent(getActivity(), MainActivity.class);
|
||||||
|
startActivity(intent);
|
||||||
|
}
|
||||||
|
|
||||||
|
private @StringRes int getContentTypeString(@Nullable ContentType contentType) {
|
||||||
|
if (contentType == null) return R.string.sk_content_type_unspecified;
|
||||||
|
return switch (contentType) {
|
||||||
|
case PLAIN -> R.string.sk_content_type_plain;
|
||||||
|
case HTML -> R.string.sk_content_type_html;
|
||||||
|
case MARKDOWN -> R.string.sk_content_type_markdown;
|
||||||
|
case BBCODE -> R.string.sk_content_type_bbcode;
|
||||||
|
case MISSKEY_MARKDOWN -> R.string.sk_content_type_mfm;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean onContentTypeChanged(MenuItem item, Button btn){
|
||||||
|
int id = item.getItemId();
|
||||||
|
ContentType contentType = switch (id) {
|
||||||
|
case R.id.content_type_plain -> ContentType.PLAIN;
|
||||||
|
case R.id.content_type_html -> ContentType.HTML;
|
||||||
|
case R.id.content_type_markdown -> ContentType.MARKDOWN;
|
||||||
|
case R.id.content_type_bbcode -> ContentType.BBCODE;
|
||||||
|
case R.id.content_type_misskey_markdown -> ContentType.MISSKEY_MARKDOWN;
|
||||||
|
default -> null;
|
||||||
|
};
|
||||||
|
GlobalUserPreferences.accountsDefaultContentTypes.put(accountID, contentType);
|
||||||
|
GlobalUserPreferences.save();
|
||||||
|
btn.setText(getContentTypeString(contentType));
|
||||||
|
item.setChecked(true);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,73 @@
|
||||||
|
package org.joinmastodon.android.fragments.settings;
|
||||||
|
|
||||||
|
import android.os.Build;
|
||||||
|
import android.view.Gravity;
|
||||||
|
import android.view.MenuItem;
|
||||||
|
import android.widget.PopupMenu;
|
||||||
|
|
||||||
|
import org.joinmastodon.android.GlobalUserPreferences;
|
||||||
|
import org.joinmastodon.android.R;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
public class AppearanceFragment extends SettingsBaseFragment {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addItems(ArrayList<Item> items) {
|
||||||
|
themeItem = new ThemeItem();
|
||||||
|
items.add(themeItem);
|
||||||
|
items.add(new ButtonItem(R.string.sk_settings_color_palette, R.drawable.ic_fluent_color_24_regular, b -> {
|
||||||
|
PopupMenu popupMenu = new PopupMenu(getActivity(), b, Gravity.CENTER_HORIZONTAL);
|
||||||
|
popupMenu.inflate(R.menu.color_palettes);
|
||||||
|
popupMenu.getMenu().findItem(R.id.m3_color).setVisible(Build.VERSION.SDK_INT >= Build.VERSION_CODES.S);
|
||||||
|
popupMenu.setOnMenuItemClickListener(this::onColorPreferenceClick);
|
||||||
|
b.setOnTouchListener(popupMenu.getDragToOpenListener());
|
||||||
|
b.setOnClickListener(v -> popupMenu.show());
|
||||||
|
b.setText(switch (GlobalUserPreferences.color) {
|
||||||
|
case MATERIAL3 -> R.string.sk_color_palette_material3;
|
||||||
|
case PINK -> R.string.sk_color_palette_pink;
|
||||||
|
case PURPLE -> R.string.sk_color_palette_purple;
|
||||||
|
case GREEN -> R.string.sk_color_palette_green;
|
||||||
|
case BLUE -> R.string.sk_color_palette_blue;
|
||||||
|
case BROWN -> R.string.sk_color_palette_brown;
|
||||||
|
case RED -> R.string.sk_color_palette_red;
|
||||||
|
case YELLOW -> R.string.sk_color_palette_yellow;
|
||||||
|
case NORD -> R.string.mo_color_palette_nord;
|
||||||
|
});
|
||||||
|
}));
|
||||||
|
items.add(new SwitchItem(R.string.theme_true_black, R.string.mo_setting_true_black_summary, R.drawable.ic_fluent_dark_theme_24_regular, GlobalUserPreferences.trueBlackTheme, this::onTrueBlackThemeChanged));
|
||||||
|
items.add(new SwitchItem(R.string.sk_disable_marquee, R.drawable.ic_fluent_text_more_24_regular, GlobalUserPreferences.disableMarquee, i -> {
|
||||||
|
GlobalUserPreferences.disableMarquee = i.checked;
|
||||||
|
GlobalUserPreferences.save();
|
||||||
|
needAppRestart = true;
|
||||||
|
}));
|
||||||
|
items.add(new SwitchItem(R.string.sk_settings_reduce_motion, R.string.mo_setting_reduced_motion_summary, R.drawable.ic_fluent_star_emphasis_24_regular, GlobalUserPreferences.reduceMotion, i -> {
|
||||||
|
GlobalUserPreferences.reduceMotion = i.checked;
|
||||||
|
GlobalUserPreferences.save();
|
||||||
|
needAppRestart = true;
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean onColorPreferenceClick(MenuItem item) {
|
||||||
|
GlobalUserPreferences.ColorPreference pref = null;
|
||||||
|
int id = item.getItemId();
|
||||||
|
|
||||||
|
if (id == R.id.m3_color) pref = GlobalUserPreferences.ColorPreference.MATERIAL3;
|
||||||
|
else if (id == R.id.pink_color) pref = GlobalUserPreferences.ColorPreference.PINK;
|
||||||
|
else if (id == R.id.purple_color) pref = GlobalUserPreferences.ColorPreference.PURPLE;
|
||||||
|
else if (id == R.id.green_color) pref = GlobalUserPreferences.ColorPreference.GREEN;
|
||||||
|
else if (id == R.id.blue_color) pref = GlobalUserPreferences.ColorPreference.BLUE;
|
||||||
|
else if (id == R.id.brown_color) pref = GlobalUserPreferences.ColorPreference.BROWN;
|
||||||
|
else if (id == R.id.red_color) pref = GlobalUserPreferences.ColorPreference.RED;
|
||||||
|
else if (id == R.id.yellow_color) pref = GlobalUserPreferences.ColorPreference.YELLOW;
|
||||||
|
else if (id == R.id.nord_color) pref = GlobalUserPreferences.ColorPreference.NORD;
|
||||||
|
|
||||||
|
if (pref == null) return false;
|
||||||
|
|
||||||
|
GlobalUserPreferences.color=pref;
|
||||||
|
GlobalUserPreferences.save();
|
||||||
|
restartActivityToApplyNewTheme();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,115 @@
|
||||||
|
package org.joinmastodon.android.fragments.settings;
|
||||||
|
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.Button;
|
||||||
|
import android.widget.EditText;
|
||||||
|
import android.widget.FrameLayout;
|
||||||
|
import android.widget.Toast;
|
||||||
|
|
||||||
|
import org.joinmastodon.android.GlobalUserPreferences;
|
||||||
|
import org.joinmastodon.android.R;
|
||||||
|
import org.joinmastodon.android.ui.M3AlertDialogBuilder;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
import me.grishka.appkit.utils.V;
|
||||||
|
|
||||||
|
public class BehaviourFragment extends SettingsBaseFragment{
|
||||||
|
@Override
|
||||||
|
public void addItems(ArrayList<Item> items) {
|
||||||
|
items.add(new HeaderItem(R.string.settings_behavior));
|
||||||
|
items.add(new SwitchItem(R.string.settings_gif, R.string.mo_setting_play_gif_summary, R.drawable.ic_fluent_gif_24_regular, GlobalUserPreferences.playGifs, i->{
|
||||||
|
GlobalUserPreferences.playGifs=i.checked;
|
||||||
|
GlobalUserPreferences.save();
|
||||||
|
}));
|
||||||
|
items.add(new SwitchItem(R.string.settings_custom_tabs, R.drawable.ic_fluent_link_24_regular, GlobalUserPreferences.useCustomTabs, i->{
|
||||||
|
GlobalUserPreferences.useCustomTabs=i.checked;
|
||||||
|
GlobalUserPreferences.save();
|
||||||
|
}));
|
||||||
|
items.add(new SwitchItem(R.string.mo_load_remote_followers, R.string.mo_setting_remote_follower_summary, R.drawable.ic_fluent_people_24_regular, GlobalUserPreferences.loadRemoteAccountFollowers, i -> {
|
||||||
|
GlobalUserPreferences.loadRemoteAccountFollowers=i.checked;
|
||||||
|
GlobalUserPreferences.save();
|
||||||
|
}));
|
||||||
|
items.add(new SwitchItem(R.string.sk_settings_always_reveal_content_warnings, R.drawable.ic_fluent_chat_warning_24_regular, GlobalUserPreferences.alwaysExpandContentWarnings, i->{
|
||||||
|
GlobalUserPreferences.alwaysExpandContentWarnings=i.checked;
|
||||||
|
GlobalUserPreferences.save();
|
||||||
|
}));
|
||||||
|
|
||||||
|
items.add(new SwitchItem(R.string.sk_tabs_disable_swipe, R.string.mo_setting_disable_swipe_summary, R.drawable.ic_fluent_swipe_right_24_regular, GlobalUserPreferences.disableSwipe, i->{
|
||||||
|
GlobalUserPreferences.disableSwipe=i.checked;
|
||||||
|
GlobalUserPreferences.save();
|
||||||
|
needAppRestart=true;
|
||||||
|
}));
|
||||||
|
items.add(new SwitchItem(R.string.mo_double_tap_to_swipe_between_tabs, R.drawable.ic_fluent_double_tap_swipe_right_24_regular, GlobalUserPreferences.doubleTapToSwipe, i->{
|
||||||
|
GlobalUserPreferences.doubleTapToSwipe=i.checked;
|
||||||
|
GlobalUserPreferences.save();
|
||||||
|
needAppRestart=true;
|
||||||
|
}));
|
||||||
|
items.add(new SwitchItem(R.string.sk_settings_confirm_before_reblog, R.drawable.ic_fluent_checkmark_circle_24_regular, GlobalUserPreferences.confirmBeforeReblog, i->{
|
||||||
|
GlobalUserPreferences.confirmBeforeReblog=i.checked;
|
||||||
|
GlobalUserPreferences.save();
|
||||||
|
}));
|
||||||
|
|
||||||
|
items.add(new HeaderItem(R.string.mo_composer_behavior));
|
||||||
|
items.add(new ButtonItem(R.string.sk_settings_publish_button_text, R.drawable.ic_fluent_send_24_regular, b-> {
|
||||||
|
updatePublishText(b);
|
||||||
|
b.setOnClickListener(l -> {
|
||||||
|
if(!GlobalUserPreferences.relocatePublishButton) {
|
||||||
|
FrameLayout inputWrap = new FrameLayout(getContext());
|
||||||
|
EditText input = new EditText(getContext());
|
||||||
|
input.setHint(R.string.publish);
|
||||||
|
input.setText(GlobalUserPreferences.publishButtonText.trim());
|
||||||
|
FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
|
||||||
|
params.setMargins(V.dp(16), V.dp(4), V.dp(16), V.dp(16));
|
||||||
|
input.setLayoutParams(params);
|
||||||
|
inputWrap.addView(input);
|
||||||
|
new M3AlertDialogBuilder(getContext()).setTitle(R.string.sk_settings_publish_button_text_title).setView(inputWrap)
|
||||||
|
.setPositiveButton(R.string.save, (d, which) -> {
|
||||||
|
GlobalUserPreferences.publishButtonText = input.getText().toString().trim();
|
||||||
|
GlobalUserPreferences.save();
|
||||||
|
updatePublishText(b);
|
||||||
|
})
|
||||||
|
.setNeutralButton(R.string.clear, (d, which) -> {
|
||||||
|
GlobalUserPreferences.publishButtonText = "";
|
||||||
|
GlobalUserPreferences.save();
|
||||||
|
updatePublishText(b);
|
||||||
|
})
|
||||||
|
.setNegativeButton(R.string.cancel, (d, which) -> {
|
||||||
|
})
|
||||||
|
.show();
|
||||||
|
|
||||||
|
} else {
|
||||||
|
Toast.makeText(getActivity(), R.string.mo_disable_relocate_publish_button_to_enable_customization,
|
||||||
|
Toast.LENGTH_LONG).show();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}));
|
||||||
|
items.add(new SwitchItem(R.string.mo_relocate_publish_button, R.string.mo_setting_relocate_publish_summary, R.drawable.ic_fluent_arrow_autofit_down_24_regular, GlobalUserPreferences.relocatePublishButton, i->{
|
||||||
|
GlobalUserPreferences.relocatePublishButton=i.checked;
|
||||||
|
GlobalUserPreferences.save();
|
||||||
|
}));
|
||||||
|
items.add(new SwitchItem(R.string.mo_change_default_reply_visibility_to_unlisted, R.string.mo_setting_default_reply_privacy_summary, R.drawable.ic_fluent_lock_open_24_regular, GlobalUserPreferences.defaultToUnlistedReplies, i->{
|
||||||
|
GlobalUserPreferences.defaultToUnlistedReplies=i.checked;
|
||||||
|
GlobalUserPreferences.save();
|
||||||
|
}));
|
||||||
|
// TODO find a good icon for this setting
|
||||||
|
items.add(new SwitchItem(R.string.mo_mention_reblogger_automatically, R.drawable.ic_fluent_balloon_24_regular, GlobalUserPreferences.mentionRebloggerAutomatically, i -> {
|
||||||
|
GlobalUserPreferences.mentionRebloggerAutomatically=i.checked;
|
||||||
|
GlobalUserPreferences.save();
|
||||||
|
}));
|
||||||
|
items.add(new SwitchItem(R.string.mo_disable_reminder_to_add_alt_text, R.drawable.ic_fluent_image_alt_text_24_regular, GlobalUserPreferences.disableAltTextReminder, i->{
|
||||||
|
GlobalUserPreferences.disableAltTextReminder=i.checked;
|
||||||
|
GlobalUserPreferences.save();
|
||||||
|
needAppRestart=true;
|
||||||
|
}));
|
||||||
|
items.add(new SwitchItem(R.string.sk_settings_prefix_reply_cw_with_re, R.drawable.ic_fluent_arrow_reply_24_regular, GlobalUserPreferences.prefixRepliesWithRe, i->{
|
||||||
|
GlobalUserPreferences.prefixRepliesWithRe=i.checked;
|
||||||
|
GlobalUserPreferences.save();
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updatePublishText(Button btn) {
|
||||||
|
if (GlobalUserPreferences.publishButtonText.isBlank()) btn.setText(R.string.publish);
|
||||||
|
else btn.setText(GlobalUserPreferences.publishButtonText);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,47 @@
|
||||||
|
package org.joinmastodon.android.fragments.settings;
|
||||||
|
|
||||||
|
import org.joinmastodon.android.GlobalUserPreferences;
|
||||||
|
import org.joinmastodon.android.R;
|
||||||
|
import org.joinmastodon.android.model.PushNotification;
|
||||||
|
import org.joinmastodon.android.model.PushSubscription;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
public class NotificationsFragment extends SettingsBaseFragment {
|
||||||
|
@Override
|
||||||
|
public void addItems(ArrayList<Item> items) {
|
||||||
|
items.add(new HeaderItem(R.string.mo_notification_audience_settings));
|
||||||
|
items.add(notificationPolicyItem = new NotificationPolicyItem());
|
||||||
|
PushSubscription pushSubscription = getPushSubscription();
|
||||||
|
boolean switchEnabled = pushSubscription.policy != PushSubscription.Policy.NONE;
|
||||||
|
|
||||||
|
items.add(new SwitchItem(R.string.notify_favorites, R.drawable.ic_fluent_star_24_regular, pushSubscription.alerts.favourite, i -> onNotificationsChanged(PushNotification.Type.FAVORITE, i.checked), switchEnabled));
|
||||||
|
items.add(new SwitchItem(R.string.notify_follow, R.drawable.ic_fluent_person_add_24_regular, pushSubscription.alerts.follow, i -> onNotificationsChanged(PushNotification.Type.FOLLOW, i.checked), switchEnabled));
|
||||||
|
items.add(new SwitchItem(R.string.notify_reblog, R.drawable.ic_fluent_arrow_repeat_all_24_regular, pushSubscription.alerts.reblog, i -> onNotificationsChanged(PushNotification.Type.REBLOG, i.checked), switchEnabled));
|
||||||
|
items.add(new SwitchItem(R.string.notify_mention, R.drawable.ic_fluent_mention_24_regular, pushSubscription.alerts.mention, i -> onNotificationsChanged(PushNotification.Type.MENTION, i.checked), switchEnabled));
|
||||||
|
items.add(new SwitchItem(R.string.sk_notify_posts, R.drawable.ic_fluent_chat_24_regular, pushSubscription.alerts.status, i -> onNotificationsChanged(PushNotification.Type.STATUS, i.checked), switchEnabled));
|
||||||
|
items.add(new SwitchItem(R.string.sk_notify_update, R.drawable.ic_fluent_history_24_regular, pushSubscription.alerts.update, i -> onNotificationsChanged(PushNotification.Type.UPDATE, i.checked), switchEnabled));
|
||||||
|
items.add(new SwitchItem(R.string.sk_notify_poll_results, R.drawable.ic_fluent_poll_24_regular, pushSubscription.alerts.poll, i -> onNotificationsChanged(PushNotification.Type.POLL, i.checked), switchEnabled));
|
||||||
|
|
||||||
|
items.add(new HeaderItem(R.string.mo_notification_management_settings));
|
||||||
|
items.add(new SwitchItem(R.string.sk_enable_delete_notifications, R.drawable.ic_fluent_mail_inbox_dismiss_24_regular, GlobalUserPreferences.enableDeleteNotifications, i->{
|
||||||
|
GlobalUserPreferences.enableDeleteNotifications=i.checked;
|
||||||
|
GlobalUserPreferences.save();
|
||||||
|
needAppRestart=true;
|
||||||
|
}));
|
||||||
|
items.add(new SwitchItem(R.string.sk_settings_single_notification, R.drawable.ic_fluent_convert_range_24_regular, GlobalUserPreferences.keepOnlyLatestNotification, i->{
|
||||||
|
GlobalUserPreferences.keepOnlyLatestNotification=i.checked;
|
||||||
|
GlobalUserPreferences.save();
|
||||||
|
}));
|
||||||
|
items.add(new SwitchItem(R.string.sk_settings_uniform_icon_for_notifications, R.string.mo_setting_uniform_summary, R.drawable.ic_ntf_logo, GlobalUserPreferences.uniformNotificationIcon, i -> {
|
||||||
|
GlobalUserPreferences.uniformNotificationIcon = i.checked;
|
||||||
|
GlobalUserPreferences.save();
|
||||||
|
}));
|
||||||
|
items.add(new SwitchItem(R.string.mo_swap_bookmark_with_reblog, R.string.mo_swap_bookmark_with_reblog_summary, R.drawable.ic_boost, GlobalUserPreferences.swapBookmarkWithBoostAction, i -> {
|
||||||
|
GlobalUserPreferences.swapBookmarkWithBoostAction=i.checked;
|
||||||
|
GlobalUserPreferences.save();
|
||||||
|
}));
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,925 @@
|
||||||
|
package org.joinmastodon.android.fragments.settings;
|
||||||
|
|
||||||
|
import android.animation.ObjectAnimator;
|
||||||
|
import android.annotation.SuppressLint;
|
||||||
|
import android.app.Fragment;
|
||||||
|
import android.graphics.Bitmap;
|
||||||
|
import android.graphics.Canvas;
|
||||||
|
import android.graphics.Rect;
|
||||||
|
import android.os.Build;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.util.TypedValue;
|
||||||
|
import android.view.Gravity;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.view.WindowInsets;
|
||||||
|
import android.view.WindowManager;
|
||||||
|
import android.view.animation.LinearInterpolator;
|
||||||
|
import android.widget.Button;
|
||||||
|
import android.widget.ImageButton;
|
||||||
|
import android.widget.ImageView;
|
||||||
|
import android.widget.LinearLayout;
|
||||||
|
import android.widget.PopupMenu;
|
||||||
|
import android.widget.ProgressBar;
|
||||||
|
import android.widget.RadioButton;
|
||||||
|
import android.widget.Switch;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import androidx.annotation.DrawableRes;
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.annotation.StringRes;
|
||||||
|
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||||
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
|
||||||
|
import org.joinmastodon.android.DomainManager;
|
||||||
|
import org.joinmastodon.android.GlobalUserPreferences;
|
||||||
|
import org.joinmastodon.android.MastodonApp;
|
||||||
|
import org.joinmastodon.android.R;
|
||||||
|
import org.joinmastodon.android.api.PushSubscriptionManager;
|
||||||
|
import org.joinmastodon.android.api.session.AccountSession;
|
||||||
|
import org.joinmastodon.android.api.session.AccountSessionManager;
|
||||||
|
import org.joinmastodon.android.fragments.DomainDisplay;
|
||||||
|
import org.joinmastodon.android.fragments.MastodonToolbarFragment;
|
||||||
|
import org.joinmastodon.android.model.Instance;
|
||||||
|
import org.joinmastodon.android.model.PushNotification;
|
||||||
|
import org.joinmastodon.android.model.PushSubscription;
|
||||||
|
import org.joinmastodon.android.ui.OutlineProviders;
|
||||||
|
import org.joinmastodon.android.ui.utils.UiUtils;
|
||||||
|
import org.joinmastodon.android.updater.GithubSelfUpdater;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
|
import me.grishka.appkit.Nav;
|
||||||
|
import me.grishka.appkit.utils.BindableViewHolder;
|
||||||
|
import me.grishka.appkit.utils.V;
|
||||||
|
import me.grishka.appkit.views.UsableRecyclerView;
|
||||||
|
|
||||||
|
public abstract class SettingsBaseFragment extends MastodonToolbarFragment implements DomainDisplay {
|
||||||
|
protected View view;
|
||||||
|
protected UsableRecyclerView list;
|
||||||
|
|
||||||
|
protected ImageView themeTransitionWindowView;
|
||||||
|
|
||||||
|
protected ThemeItem themeItem;
|
||||||
|
|
||||||
|
protected boolean needAppRestart;
|
||||||
|
private Instance instance;
|
||||||
|
private String instanceName;
|
||||||
|
|
||||||
|
protected NotificationPolicyItem notificationPolicyItem;
|
||||||
|
|
||||||
|
protected PushSubscription pushSubscription;
|
||||||
|
protected ArrayList<Item> items=new ArrayList<>();
|
||||||
|
protected String accountID;
|
||||||
|
protected AccountSession session;
|
||||||
|
|
||||||
|
protected boolean needUpdateNotificationSettings;
|
||||||
|
|
||||||
|
public abstract void addItems(ArrayList<Item> items);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCreate(Bundle savedInstanceState){
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.N)
|
||||||
|
setRetainInstance(true);
|
||||||
|
setTitle(R.string.settings);
|
||||||
|
|
||||||
|
accountID=getArguments().getString("account");
|
||||||
|
session = AccountSessionManager.getInstance().getAccount(accountID);
|
||||||
|
instance = AccountSessionManager.getInstance().getInstanceInfo(session.domain);
|
||||||
|
instanceName = UiUtils.getInstanceName(accountID);
|
||||||
|
DomainManager.getInstance().setCurrentDomain(session.domain + "/settings");
|
||||||
|
|
||||||
|
addItems(items);
|
||||||
|
String title = getArguments().getString("title", getTitle().toString());
|
||||||
|
items.add(0, new GiantHeaderItem(title));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public View onCreateContentView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState){
|
||||||
|
list=new UsableRecyclerView(getActivity());
|
||||||
|
list.setLayoutManager(new LinearLayoutManager(getActivity()));
|
||||||
|
list.setAdapter(new SettingsAdapter());
|
||||||
|
list.setBackgroundColor(UiUtils.getThemeColor(getActivity(), android.R.attr.windowBackground));
|
||||||
|
list.setPadding(0, V.dp(16), 0, V.dp(12));
|
||||||
|
list.setClipToPadding(false);
|
||||||
|
list.addItemDecoration(new RecyclerView.ItemDecoration(){
|
||||||
|
@Override
|
||||||
|
public void getItemOffsets(@NonNull Rect outRect, @NonNull View view, @NonNull RecyclerView parent, @NonNull RecyclerView.State state){
|
||||||
|
// Add 32dp gaps between sections
|
||||||
|
RecyclerView.ViewHolder holder=parent.getChildViewHolder(view);
|
||||||
|
if((holder instanceof HeaderViewHolder || holder instanceof FooterViewHolder) && holder.getAbsoluteAdapterPosition()>1)
|
||||||
|
outRect.top=V.dp(32);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onApplyWindowInsets(WindowInsets insets){
|
||||||
|
if(Build.VERSION.SDK_INT>=29 && insets.getTappableElementInsets().bottom==0){
|
||||||
|
list.setPadding(0, V.dp(16), 0, V.dp(12)+insets.getSystemWindowInsetBottom());
|
||||||
|
insets=insets.inset(0, 0, 0, insets.getSystemWindowInsetBottom());
|
||||||
|
}
|
||||||
|
super.onApplyWindowInsets(insets);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onViewCreated(View view, Bundle savedInstanceState){
|
||||||
|
super.onViewCreated(view, savedInstanceState);
|
||||||
|
this.view = view;
|
||||||
|
hideToolbar();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void hideToolbar() {
|
||||||
|
getToolbar().setElevation(0f);
|
||||||
|
getToolbar().setTitle("");
|
||||||
|
TypedValue typedValue = new TypedValue();
|
||||||
|
if (getActivity().getTheme().resolveAttribute(android.R.attr.windowBackground, typedValue, true)) {
|
||||||
|
getToolbar().setBackgroundColor(typedValue.data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Instance getInstance() {
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected String getInstanceName() {
|
||||||
|
return instanceName;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static abstract class Item{
|
||||||
|
public abstract int getViewType();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected class HeaderItem extends Item{
|
||||||
|
private String text;
|
||||||
|
|
||||||
|
public HeaderItem(@StringRes int text){
|
||||||
|
this.text=getString(text);
|
||||||
|
}
|
||||||
|
|
||||||
|
public HeaderItem(String text){
|
||||||
|
this.text=text;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getViewType(){
|
||||||
|
return Type.HEADER.ordinal();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected class RedHeaderItem extends HeaderItem {
|
||||||
|
|
||||||
|
public RedHeaderItem(int text){
|
||||||
|
super(text);
|
||||||
|
}
|
||||||
|
|
||||||
|
public RedHeaderItem(String text){
|
||||||
|
super(text);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getViewType(){
|
||||||
|
return Type.RED_HEADER.ordinal();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
protected class SwitchItem extends Item{
|
||||||
|
private String title;
|
||||||
|
private String summary;
|
||||||
|
private int icon;
|
||||||
|
boolean checked;
|
||||||
|
private Consumer<SwitchItem> onChanged;
|
||||||
|
protected boolean enabled=true;
|
||||||
|
|
||||||
|
public SwitchItem(@StringRes int title, @DrawableRes int icon, boolean checked, Consumer<SwitchItem> onChanged){
|
||||||
|
this.title=getString(title);
|
||||||
|
this.icon=icon;
|
||||||
|
this.checked=checked;
|
||||||
|
this.onChanged=onChanged;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SwitchItem(@StringRes int title, @StringRes int summary, @DrawableRes int icon, boolean checked, Consumer<SwitchItem> onChanged){
|
||||||
|
this.title=getString(title);
|
||||||
|
this.summary=getString(summary);
|
||||||
|
this.icon=icon;
|
||||||
|
this.checked=checked;
|
||||||
|
this.onChanged=onChanged;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SwitchItem(@StringRes int title, @DrawableRes int icon, boolean checked, Consumer<SwitchItem> onChanged, boolean enabled){
|
||||||
|
this.title=getString(title);
|
||||||
|
this.icon=icon;
|
||||||
|
this.checked=checked;
|
||||||
|
this.onChanged=onChanged;
|
||||||
|
this.enabled=enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getViewType(){
|
||||||
|
return Type.SWITCH.ordinal();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected class UpdateItem extends Item {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getViewType(){
|
||||||
|
return Type.UPDATER.ordinal();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static class ThemeItem extends Item {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getViewType(){
|
||||||
|
return Type.THEME.ordinal();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static class NotificationPolicyItem extends Item {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getViewType(){
|
||||||
|
return Type.NOTIFICATION_POLICY.ordinal();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
protected class ButtonItem extends Item{
|
||||||
|
private int title;
|
||||||
|
private int summary;
|
||||||
|
private int icon;
|
||||||
|
private Consumer<Button> buttonConsumer;
|
||||||
|
|
||||||
|
public ButtonItem(@StringRes int title, @DrawableRes int icon, Consumer<Button> buttonConsumer) {
|
||||||
|
this.title = title;
|
||||||
|
this.icon = icon;
|
||||||
|
this.buttonConsumer = buttonConsumer;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ButtonItem(@StringRes int title, @StringRes int summary, @DrawableRes int icon, Consumer<Button> buttonConsumer) {
|
||||||
|
this.title = title;
|
||||||
|
this.summary = summary;
|
||||||
|
this.icon = icon;
|
||||||
|
this.buttonConsumer = buttonConsumer;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getViewType(){
|
||||||
|
return Type.BUTTON.ordinal();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected class GiantHeaderItem extends Item {
|
||||||
|
private String text;
|
||||||
|
|
||||||
|
public GiantHeaderItem(String text) {
|
||||||
|
this.text = text;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getViewType() {
|
||||||
|
return Type.GIANT_HEADER.ordinal();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected class SmallTextItem extends Item {
|
||||||
|
private String text;
|
||||||
|
|
||||||
|
public SmallTextItem(String text) {
|
||||||
|
this.text = text;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getViewType() {
|
||||||
|
return Type.SMALL_TEXT.ordinal();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected class TextItem extends Item{
|
||||||
|
private String text;
|
||||||
|
protected String secondaryText;
|
||||||
|
private Runnable onClick;
|
||||||
|
private boolean loading;
|
||||||
|
private int icon;
|
||||||
|
|
||||||
|
public TextItem(@StringRes int text, Runnable onClick) {
|
||||||
|
this(text, null, onClick, false, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public TextItem(@StringRes int text, Runnable onClick, @DrawableRes int icon) {
|
||||||
|
this(text, null, onClick, false, icon);
|
||||||
|
}
|
||||||
|
|
||||||
|
public TextItem(@StringRes int text, String secondaryText, Runnable onClick, @DrawableRes int icon) {
|
||||||
|
this(text, secondaryText, onClick, false, icon);
|
||||||
|
}
|
||||||
|
|
||||||
|
public TextItem(@StringRes int text, String secondaryText, Runnable onClick, boolean loading, @DrawableRes int icon){
|
||||||
|
this.text=getString(text);
|
||||||
|
this.onClick=onClick;
|
||||||
|
this.loading=loading;
|
||||||
|
this.icon=icon;
|
||||||
|
this.secondaryText = secondaryText;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TextItem(String text, Runnable onClick){
|
||||||
|
this.text=text;
|
||||||
|
this.onClick=onClick;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TextItem(String text, Runnable onClick, @DrawableRes int icon){
|
||||||
|
this.text=text;
|
||||||
|
this.onClick=onClick;
|
||||||
|
this.icon=icon;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getViewType(){
|
||||||
|
return Type.TEXT.ordinal();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected class SettingsCategoryItem extends Item{
|
||||||
|
private String text;
|
||||||
|
private int icon;
|
||||||
|
|
||||||
|
private Class<? extends Fragment> fragmentClass;
|
||||||
|
|
||||||
|
public SettingsCategoryItem(@StringRes int text, Class<? extends Fragment> fragmentClass, @DrawableRes int icon) {
|
||||||
|
this.text = getString(text);
|
||||||
|
this.fragmentClass=fragmentClass;
|
||||||
|
this.icon=icon;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SettingsCategoryItem(@StringRes int text, Class<? extends Fragment> fragmentClass) {
|
||||||
|
this(text, fragmentClass, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getViewType(){
|
||||||
|
return Type.SETTINGS_CATEGORY.ordinal();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
protected class FooterItem extends Item{
|
||||||
|
private String text;
|
||||||
|
private Runnable onClick;
|
||||||
|
|
||||||
|
public FooterItem(String text, Runnable onClick){
|
||||||
|
this.text=text;
|
||||||
|
this.onClick=onClick;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getViewType(){
|
||||||
|
return Type.FOOTER.ordinal();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum Type{
|
||||||
|
HEADER,
|
||||||
|
RED_HEADER,
|
||||||
|
GIANT_HEADER,
|
||||||
|
SWITCH,
|
||||||
|
THEME,
|
||||||
|
TEXT,
|
||||||
|
NOTIFICATION_POLICY,
|
||||||
|
FOOTER,
|
||||||
|
BUTTON,
|
||||||
|
SMALL_TEXT,
|
||||||
|
UPDATER,
|
||||||
|
SETTINGS_CATEGORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private class SettingsAdapter extends RecyclerView.Adapter<BindableViewHolder<Item>>{
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
public BindableViewHolder<Item> onCreateViewHolder(@NonNull ViewGroup parent, int viewType){
|
||||||
|
//noinspection unchecked
|
||||||
|
return (BindableViewHolder<Item>) switch(Type.values()[viewType]){
|
||||||
|
case HEADER -> new HeaderViewHolder();
|
||||||
|
case RED_HEADER -> new HeaderViewHolder(true);
|
||||||
|
case GIANT_HEADER -> new GiantHeaderViewHolder();
|
||||||
|
case SWITCH -> new SwitchViewHolder();
|
||||||
|
case THEME -> new ThemeViewHolder();
|
||||||
|
case TEXT -> new TextViewHolder();
|
||||||
|
case NOTIFICATION_POLICY -> new NotificationPolicyViewHolder();
|
||||||
|
case FOOTER -> new FooterViewHolder();
|
||||||
|
case BUTTON -> new ButtonViewHolder();
|
||||||
|
case SMALL_TEXT -> new SmallTextViewHolder();
|
||||||
|
case UPDATER -> new UpdateViewHolder();
|
||||||
|
case SETTINGS_CATEGORY -> new SettingsCategoryViewHolder();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onBindViewHolder(@NonNull BindableViewHolder<Item> holder, int position){
|
||||||
|
holder.bind(items.get(position));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getItemCount(){
|
||||||
|
return items.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getItemViewType(int position){
|
||||||
|
return items.get(position).getViewType();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class HeaderViewHolder extends BindableViewHolder<HeaderItem>{
|
||||||
|
private final TextView text;
|
||||||
|
public HeaderViewHolder(){
|
||||||
|
super(getActivity(), R.layout.item_settings_header, list);
|
||||||
|
text=(TextView) itemView;
|
||||||
|
}
|
||||||
|
|
||||||
|
public HeaderViewHolder(boolean red){
|
||||||
|
super(getActivity(), R.layout.item_settings_header, list);
|
||||||
|
text=(TextView) itemView;
|
||||||
|
if(red)
|
||||||
|
text.setTextColor(getResources().getColor(UiUtils.isDarkTheme() ? R.color.error_400 : R.color.error_700));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onBind(HeaderItem item){
|
||||||
|
text.setText(item.text);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class GiantHeaderViewHolder extends BindableViewHolder<GiantHeaderItem> {
|
||||||
|
private final TextView text;
|
||||||
|
|
||||||
|
public GiantHeaderViewHolder(){
|
||||||
|
super(getActivity(), R.layout.item_settings_text, list);
|
||||||
|
text = itemView.findViewById(R.id.text);
|
||||||
|
text.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT));
|
||||||
|
text.setTextSize(TypedValue.COMPLEX_UNIT_SP, 32);
|
||||||
|
text.setPaddingRelative(text.getPaddingStart(), 0, text.getPaddingEnd(), text.getPaddingBottom());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onBind(GiantHeaderItem item){
|
||||||
|
text.setText(item.text);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
protected void onThemePreferenceClick(GlobalUserPreferences.ThemePreference theme){
|
||||||
|
GlobalUserPreferences.theme=theme;
|
||||||
|
GlobalUserPreferences.save();
|
||||||
|
restartActivityToApplyNewTheme();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void restartActivityToApplyNewTheme(){
|
||||||
|
getActivity().recreate();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDestroy(){
|
||||||
|
super.onDestroy();
|
||||||
|
if(needUpdateNotificationSettings && PushSubscriptionManager.arePushNotificationsAvailable()){
|
||||||
|
AccountSessionManager.getInstance().getAccount(accountID).getPushSubscriptionManager().updatePushSettings(pushSubscription);
|
||||||
|
}
|
||||||
|
if(needAppRestart) UiUtils.restartApp();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
protected void onTrueBlackThemeChanged(SwitchItem item){
|
||||||
|
GlobalUserPreferences.trueBlackTheme=item.checked;
|
||||||
|
GlobalUserPreferences.save();
|
||||||
|
|
||||||
|
RecyclerView.ViewHolder themeHolder=list.findViewHolderForAdapterPosition(items.indexOf(themeItem));
|
||||||
|
if(themeHolder!=null){
|
||||||
|
((ThemeViewHolder)themeHolder).bindSubitems();
|
||||||
|
}else{
|
||||||
|
list.getAdapter().notifyItemChanged(items.indexOf(themeItem));
|
||||||
|
}
|
||||||
|
|
||||||
|
if(UiUtils.isDarkTheme()){
|
||||||
|
restartActivityToApplyNewTheme();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class NotificationPolicyViewHolder extends BindableViewHolder<NotificationPolicyItem>{
|
||||||
|
private final Button button;
|
||||||
|
private final PopupMenu popupMenu;
|
||||||
|
|
||||||
|
@SuppressLint("ClickableViewAccessibility")
|
||||||
|
public NotificationPolicyViewHolder(){
|
||||||
|
super(getActivity(), R.layout.item_settings_notification_policy, list);
|
||||||
|
button=findViewById(R.id.button);
|
||||||
|
popupMenu=new PopupMenu(getActivity(), button, Gravity.CENTER_HORIZONTAL);
|
||||||
|
popupMenu.inflate(R.menu.notification_policy);
|
||||||
|
popupMenu.setOnMenuItemClickListener(item->{
|
||||||
|
PushSubscription.Policy policy;
|
||||||
|
int id=item.getItemId();
|
||||||
|
if(id==R.id.notify_anyone)
|
||||||
|
policy=PushSubscription.Policy.ALL;
|
||||||
|
else if(id==R.id.notify_followed)
|
||||||
|
policy=PushSubscription.Policy.FOLLOWED;
|
||||||
|
else if(id==R.id.notify_follower)
|
||||||
|
policy=PushSubscription.Policy.FOLLOWER;
|
||||||
|
else if(id==R.id.notify_none)
|
||||||
|
policy=PushSubscription.Policy.NONE;
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
onNotificationsPolicyChanged(policy);
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
UiUtils.enablePopupMenuIcons(getActivity(), popupMenu);
|
||||||
|
button.setOnTouchListener(popupMenu.getDragToOpenListener());
|
||||||
|
button.setOnClickListener(v->popupMenu.show());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onBind(NotificationPolicyItem item){
|
||||||
|
button.setText(switch(getPushSubscription().policy){
|
||||||
|
case ALL -> R.string.notify_anyone;
|
||||||
|
case FOLLOWED -> R.string.notify_followed;
|
||||||
|
case FOLLOWER -> R.string.notify_follower;
|
||||||
|
case NONE -> R.string.notify_none;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void onNotificationsPolicyChanged(PushSubscription.Policy policy){
|
||||||
|
PushSubscription subscription=getPushSubscription();
|
||||||
|
PushSubscription.Policy prevPolicy=subscription.policy;
|
||||||
|
if(prevPolicy==policy)
|
||||||
|
return;
|
||||||
|
subscription.policy=policy;
|
||||||
|
int index=items.indexOf(notificationPolicyItem);
|
||||||
|
RecyclerView.ViewHolder policyHolder=list.findViewHolderForAdapterPosition(index);
|
||||||
|
if(policyHolder!=null){
|
||||||
|
((NotificationPolicyViewHolder)policyHolder).rebind();
|
||||||
|
}else{
|
||||||
|
list.getAdapter().notifyItemChanged(index);
|
||||||
|
}
|
||||||
|
if((prevPolicy==PushSubscription.Policy.NONE)!=(policy==PushSubscription.Policy.NONE)){
|
||||||
|
boolean newState=policy!=PushSubscription.Policy.NONE;
|
||||||
|
for(PushNotification.Type value : PushNotification.Type.values()){
|
||||||
|
onNotificationsChanged(value, newState);
|
||||||
|
}
|
||||||
|
index++;
|
||||||
|
while(items.size() > index && items.get(index) instanceof SwitchItem si){
|
||||||
|
si.enabled=si.checked=newState;
|
||||||
|
RecyclerView.ViewHolder holder=list.findViewHolderForAdapterPosition(index);
|
||||||
|
if(holder!=null)
|
||||||
|
((BindableViewHolder<?>)holder).rebind();
|
||||||
|
else
|
||||||
|
list.getAdapter().notifyItemChanged(index);
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
needUpdateNotificationSettings=true;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void onNotificationsChanged(PushNotification.Type type, boolean enabled){
|
||||||
|
PushSubscription subscription=getPushSubscription();
|
||||||
|
switch(type){
|
||||||
|
case FAVORITE -> subscription.alerts.favourite=enabled;
|
||||||
|
case FOLLOW -> subscription.alerts.follow=enabled;
|
||||||
|
case REBLOG -> subscription.alerts.reblog=enabled;
|
||||||
|
case MENTION -> subscription.alerts.mention=enabled;
|
||||||
|
case POLL -> subscription.alerts.poll=enabled;
|
||||||
|
case STATUS -> subscription.alerts.status=enabled;
|
||||||
|
case UPDATE -> subscription.alerts.update=enabled;
|
||||||
|
}
|
||||||
|
needUpdateNotificationSettings=true;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected PushSubscription getPushSubscription(){
|
||||||
|
if(pushSubscription!=null)
|
||||||
|
return pushSubscription;
|
||||||
|
AccountSession session=AccountSessionManager.getInstance().getAccount(accountID);
|
||||||
|
if(session.pushSubscription==null){
|
||||||
|
pushSubscription=new PushSubscription();
|
||||||
|
pushSubscription.alerts=PushSubscription.Alerts.ofAll();
|
||||||
|
}else{
|
||||||
|
pushSubscription=session.pushSubscription.clone();
|
||||||
|
}
|
||||||
|
return pushSubscription;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected class SwitchViewHolder extends BindableViewHolder<SwitchItem> implements UsableRecyclerView.DisableableClickable{
|
||||||
|
private final TextView title;
|
||||||
|
private final TextView summary;
|
||||||
|
private final ImageView icon;
|
||||||
|
private final Switch checkbox;
|
||||||
|
|
||||||
|
public SwitchViewHolder(){
|
||||||
|
super(getActivity(), R.layout.item_settings_switch, list);
|
||||||
|
title=findViewById(R.id.title);
|
||||||
|
summary=findViewById(R.id.summary);
|
||||||
|
icon=findViewById(R.id.icon);
|
||||||
|
checkbox=findViewById(R.id.checkbox);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onBind(SwitchItem item){
|
||||||
|
title.setText(item.title);
|
||||||
|
|
||||||
|
if (item.summary != null) {
|
||||||
|
summary.setText(item.summary);
|
||||||
|
summary.setVisibility(View.VISIBLE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (item.icon == 0) {
|
||||||
|
icon.setVisibility(View.GONE);
|
||||||
|
} else {
|
||||||
|
icon.setVisibility(View.VISIBLE);
|
||||||
|
icon.setImageResource(item.icon);
|
||||||
|
}
|
||||||
|
checkbox.setChecked(item.checked && item.enabled);
|
||||||
|
checkbox.setEnabled(item.enabled);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onClick(){
|
||||||
|
item.checked=!item.checked;
|
||||||
|
checkbox.setChecked(item.checked);
|
||||||
|
item.onChanged.accept(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isEnabled(){
|
||||||
|
return item.enabled;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class ThemeViewHolder extends BindableViewHolder<ThemeItem>{
|
||||||
|
private ThemeViewHolder.SubitemHolder autoHolder, lightHolder, darkHolder;
|
||||||
|
|
||||||
|
public ThemeViewHolder(){
|
||||||
|
super(getActivity(), R.layout.item_settings_theme, list);
|
||||||
|
autoHolder=new ThemeViewHolder.SubitemHolder(findViewById(R.id.theme_auto));
|
||||||
|
lightHolder=new ThemeViewHolder.SubitemHolder(findViewById(R.id.theme_light));
|
||||||
|
darkHolder=new ThemeViewHolder.SubitemHolder(findViewById(R.id.theme_dark));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onBind(ThemeItem item){
|
||||||
|
bindSubitems();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void bindSubitems(){
|
||||||
|
autoHolder.bind(R.string.theme_auto, GlobalUserPreferences.trueBlackTheme ? R.drawable.theme_auto_trueblack : R.drawable.theme_auto, GlobalUserPreferences.theme==GlobalUserPreferences.ThemePreference.AUTO);
|
||||||
|
lightHolder.bind(R.string.theme_light, R.drawable.theme_light, GlobalUserPreferences.theme==GlobalUserPreferences.ThemePreference.LIGHT);
|
||||||
|
darkHolder.bind(R.string.theme_dark, GlobalUserPreferences.trueBlackTheme ? R.drawable.theme_dark_trueblack : R.drawable.theme_dark, GlobalUserPreferences.theme==GlobalUserPreferences.ThemePreference.DARK);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void onSubitemClick(View v){
|
||||||
|
GlobalUserPreferences.ThemePreference pref;
|
||||||
|
if(v.getId()==R.id.theme_auto)
|
||||||
|
pref=GlobalUserPreferences.ThemePreference.AUTO;
|
||||||
|
else if(v.getId()==R.id.theme_light)
|
||||||
|
pref=GlobalUserPreferences.ThemePreference.LIGHT;
|
||||||
|
else if(v.getId()==R.id.theme_dark)
|
||||||
|
pref=GlobalUserPreferences.ThemePreference.DARK;
|
||||||
|
else
|
||||||
|
return;
|
||||||
|
onThemePreferenceClick(pref);
|
||||||
|
}
|
||||||
|
|
||||||
|
private class SubitemHolder{
|
||||||
|
public TextView text;
|
||||||
|
public ImageView icon;
|
||||||
|
public RadioButton checkbox;
|
||||||
|
|
||||||
|
public SubitemHolder(View view){
|
||||||
|
text=view.findViewById(R.id.text);
|
||||||
|
icon=view.findViewById(R.id.icon);
|
||||||
|
checkbox=view.findViewById(R.id.checkbox);
|
||||||
|
view.setOnClickListener(ThemeViewHolder.this::onSubitemClick);
|
||||||
|
|
||||||
|
icon.setClipToOutline(true);
|
||||||
|
icon.setOutlineProvider(OutlineProviders.roundedRect(4));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void bind(int text, int icon, boolean checked){
|
||||||
|
this.text.setText(text);
|
||||||
|
this.icon.setImageResource(icon);
|
||||||
|
checkbox.setChecked(checked);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setChecked(boolean checked){
|
||||||
|
checkbox.setChecked(checked);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class SettingsCategoryViewHolder extends BindableViewHolder<SettingsCategoryItem> implements UsableRecyclerView.Clickable{
|
||||||
|
private final ImageView icon;
|
||||||
|
private final TextView text;
|
||||||
|
|
||||||
|
@SuppressLint("ClickableViewAccessibility")
|
||||||
|
public SettingsCategoryViewHolder(){
|
||||||
|
super(getActivity(), R.layout.item_settings_category, list);
|
||||||
|
text=findViewById(R.id.text);
|
||||||
|
icon=findViewById(R.id.icon);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onBind(SettingsCategoryItem item){
|
||||||
|
text.setText(item.text);
|
||||||
|
icon.setImageResource(item.icon);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onClick() {
|
||||||
|
Bundle args = getArguments();
|
||||||
|
args.putString("title", item.text);
|
||||||
|
Nav.go(getActivity(), item.fragmentClass, args);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected class ButtonViewHolder extends BindableViewHolder<ButtonItem> implements UsableRecyclerView.Clickable{
|
||||||
|
private final Button button;
|
||||||
|
private final ImageView icon;
|
||||||
|
private final TextView title;
|
||||||
|
private final TextView summary;
|
||||||
|
|
||||||
|
@SuppressLint("ClickableViewAccessibility")
|
||||||
|
public ButtonViewHolder(){
|
||||||
|
super(getActivity(), R.layout.item_settings_button, list);
|
||||||
|
title=findViewById(R.id.title);
|
||||||
|
summary=findViewById(R.id.summary);
|
||||||
|
icon=findViewById(R.id.icon);
|
||||||
|
button=findViewById(R.id.button);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onBind(ButtonItem item){
|
||||||
|
title.setText(item.title);
|
||||||
|
|
||||||
|
if (item.summary != 0) {
|
||||||
|
summary.setText(item.summary);
|
||||||
|
summary.setVisibility(View.VISIBLE);
|
||||||
|
}
|
||||||
|
if (item.icon == 0) {
|
||||||
|
icon.setVisibility(View.GONE);
|
||||||
|
} else {
|
||||||
|
icon.setImageResource(item.icon);
|
||||||
|
}
|
||||||
|
item.buttonConsumer.accept(button);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onClick() {
|
||||||
|
button.performClick();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected class TextViewHolder extends BindableViewHolder<TextItem> implements UsableRecyclerView.Clickable{
|
||||||
|
private final TextView text, secondaryText;
|
||||||
|
private final ProgressBar progress;
|
||||||
|
private final ImageView icon;
|
||||||
|
|
||||||
|
public TextViewHolder(){
|
||||||
|
super(getActivity(), R.layout.item_settings_text, list);
|
||||||
|
text = itemView.findViewById(R.id.text);
|
||||||
|
secondaryText = itemView.findViewById(R.id.secondary_text);
|
||||||
|
progress = itemView.findViewById(R.id.progress);
|
||||||
|
icon = itemView.findViewById(R.id.icon);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onBind(TextItem item){
|
||||||
|
icon.setVisibility(item.icon != 0 ? View.VISIBLE : View.GONE);
|
||||||
|
secondaryText.setVisibility(item.secondaryText != null ? View.VISIBLE : View.GONE);
|
||||||
|
|
||||||
|
text.setText(item.text);
|
||||||
|
progress.animate().alpha(item.loading ? 1 : 0);
|
||||||
|
icon.setImageResource(item.icon);
|
||||||
|
secondaryText.setText(item.secondaryText);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onClick(){
|
||||||
|
item.onClick.run();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class SmallTextViewHolder extends BindableViewHolder<SmallTextItem> {
|
||||||
|
private final TextView text;
|
||||||
|
|
||||||
|
public SmallTextViewHolder(){
|
||||||
|
super(getActivity(), R.layout.item_settings_text, list);
|
||||||
|
text = itemView.findViewById(R.id.text);
|
||||||
|
text.setTextColor(UiUtils.getThemeColor(getActivity(), android.R.attr.textColorSecondary));
|
||||||
|
text.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT));
|
||||||
|
text.setTextSize(TypedValue.COMPLEX_UNIT_SP, 14);
|
||||||
|
text.setPaddingRelative(text.getPaddingStart(), 0, text.getPaddingEnd(), text.getPaddingBottom());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onBind(SmallTextItem item){
|
||||||
|
text.setText(item.text);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class FooterViewHolder extends BindableViewHolder<FooterItem> implements UsableRecyclerView.Clickable{
|
||||||
|
private final TextView text;
|
||||||
|
public FooterViewHolder(){
|
||||||
|
super(getActivity(), R.layout.item_settings_footer, list);
|
||||||
|
text=(TextView) itemView;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onBind(FooterItem item){
|
||||||
|
text.setText(item.text);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onClick(){
|
||||||
|
item.onClick.run();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class UpdateViewHolder extends BindableViewHolder<UpdateItem>{
|
||||||
|
|
||||||
|
private final TextView text, changelog;
|
||||||
|
private final Button button;
|
||||||
|
private final ImageButton cancelBtn;
|
||||||
|
private final ProgressBar progress;
|
||||||
|
|
||||||
|
private ObjectAnimator rotationAnimator;
|
||||||
|
private Runnable progressUpdater=this::updateProgress;
|
||||||
|
|
||||||
|
public UpdateViewHolder(){
|
||||||
|
super(getActivity(), R.layout.item_settings_update, list);
|
||||||
|
text=findViewById(R.id.text);
|
||||||
|
changelog=findViewById(R.id.changelog);
|
||||||
|
button=findViewById(R.id.button);
|
||||||
|
cancelBtn=findViewById(R.id.cancel_btn);
|
||||||
|
progress=findViewById(R.id.progress);
|
||||||
|
button.setOnClickListener(v->{
|
||||||
|
GithubSelfUpdater updater=GithubSelfUpdater.getInstance();
|
||||||
|
switch(updater.getState()){
|
||||||
|
case UPDATE_AVAILABLE -> updater.downloadUpdate();
|
||||||
|
case DOWNLOADED -> updater.installUpdate(getActivity());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
cancelBtn.setOnClickListener(v->GithubSelfUpdater.getInstance().cancelDownload());
|
||||||
|
rotationAnimator=ObjectAnimator.ofFloat(progress, View.ROTATION, 0f, 360f);
|
||||||
|
rotationAnimator.setInterpolator(new LinearInterpolator());
|
||||||
|
rotationAnimator.setDuration(1500);
|
||||||
|
rotationAnimator.setRepeatCount(ObjectAnimator.INFINITE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onBind(UpdateItem item){
|
||||||
|
GithubSelfUpdater updater=GithubSelfUpdater.getInstance();
|
||||||
|
GithubSelfUpdater.UpdateState state=updater.getState();
|
||||||
|
if (state == GithubSelfUpdater.UpdateState.CHECKING) return;
|
||||||
|
GithubSelfUpdater.UpdateInfo info=updater.getUpdateInfo();
|
||||||
|
if(state!=GithubSelfUpdater.UpdateState.DOWNLOADED){
|
||||||
|
text.setText(getString(R.string.mo_update_available, info.version));
|
||||||
|
button.setText(getString(R.string.download_update, UiUtils.formatFileSize(getActivity(), info.size, false)));
|
||||||
|
}else{
|
||||||
|
text.setText(getString(R.string.mo_update_ready, info.version));
|
||||||
|
button.setText(R.string.install_update);
|
||||||
|
}
|
||||||
|
if(state==GithubSelfUpdater.UpdateState.DOWNLOADING){
|
||||||
|
rotationAnimator.start();
|
||||||
|
button.setVisibility(View.INVISIBLE);
|
||||||
|
cancelBtn.setVisibility(View.VISIBLE);
|
||||||
|
progress.setVisibility(View.VISIBLE);
|
||||||
|
updateProgress();
|
||||||
|
}else{
|
||||||
|
rotationAnimator.cancel();
|
||||||
|
button.setVisibility(View.VISIBLE);
|
||||||
|
cancelBtn.setVisibility(View.GONE);
|
||||||
|
progress.setVisibility(View.GONE);
|
||||||
|
progress.removeCallbacks(progressUpdater);
|
||||||
|
}
|
||||||
|
changelog.setText(info.changelog);
|
||||||
|
// changelog.setText(getString(R.string.sk_changelog, info.changelog));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateProgress(){
|
||||||
|
GithubSelfUpdater updater=GithubSelfUpdater.getInstance();
|
||||||
|
if(updater.getState()!=GithubSelfUpdater.UpdateState.DOWNLOADING)
|
||||||
|
return;
|
||||||
|
int value=Math.round(progress.getMax()*updater.getDownloadProgress());
|
||||||
|
if(Build.VERSION.SDK_INT>=24)
|
||||||
|
progress.setProgress(value, true);
|
||||||
|
else
|
||||||
|
progress.setProgress(value);
|
||||||
|
progress.postDelayed(progressUpdater, 1000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,47 @@
|
||||||
|
package org.joinmastodon.android.fragments.settings;
|
||||||
|
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.view.View;
|
||||||
|
|
||||||
|
import org.joinmastodon.android.E;
|
||||||
|
import org.joinmastodon.android.R;
|
||||||
|
import org.joinmastodon.android.updater.GithubSelfUpdater;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
public class SettingsMainFragment extends SettingsBaseFragment {
|
||||||
|
@Override
|
||||||
|
public void addItems(ArrayList<Item> items) {
|
||||||
|
|
||||||
|
if (GithubSelfUpdater.needSelfUpdating()) {
|
||||||
|
GithubSelfUpdater updater = GithubSelfUpdater.getInstance();
|
||||||
|
GithubSelfUpdater.UpdateState state = updater.getState();
|
||||||
|
if (state != GithubSelfUpdater.UpdateState.NO_UPDATE && state != GithubSelfUpdater.UpdateState.CHECKING && updater.getUpdateInfo() != null) {
|
||||||
|
items.add(new SettingsBaseFragment.UpdateItem());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
items.add(new SettingsCategoryItem(R.string.settings_theme, AppearanceFragment.class, R.drawable.ic_fluent_color_24_regular));
|
||||||
|
items.add(new SettingsCategoryItem(R.string.settings_behavior, BehaviourFragment.class, R.drawable.ic_fluent_chat_settings_24_regular));
|
||||||
|
items.add(new SettingsCategoryItem(R.string.sk_timelines, TimeLineFragment.class, R.drawable.ic_fluent_timeline_24_regular));
|
||||||
|
items.add(new SettingsCategoryItem(R.string.settings_notifications, NotificationsFragment.class, R.drawable.ic_fluent_alert_28_regular_badged));
|
||||||
|
items.add(new SettingsCategoryItem(R.string.settings_account, AccountFragment.class, R.drawable.ic_fluent_person_28_regular));
|
||||||
|
items.add(new SettingsCategoryItem(R.string.sk_settings_about, AboutFragment.class, R.drawable.ic_fluent_info_24_regular));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onViewCreated(View view, Bundle savedInstanceState) {
|
||||||
|
super.onViewCreated(view, savedInstanceState);
|
||||||
|
if (GithubSelfUpdater.needSelfUpdating()) {
|
||||||
|
E.register(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDestroy() {
|
||||||
|
super.onDestroy();
|
||||||
|
if (GithubSelfUpdater.needSelfUpdating())
|
||||||
|
E.unregister(this);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,125 @@
|
||||||
|
package org.joinmastodon.android.fragments.settings;
|
||||||
|
|
||||||
|
import android.view.Gravity;
|
||||||
|
import android.view.MenuItem;
|
||||||
|
import android.widget.Button;
|
||||||
|
import android.widget.PopupMenu;
|
||||||
|
|
||||||
|
import org.joinmastodon.android.GlobalUserPreferences;
|
||||||
|
import org.joinmastodon.android.R;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
public class TimeLineFragment extends SettingsBaseFragment{
|
||||||
|
|
||||||
|
private SwitchItem showNewPostsItem, compactReblogReplyLineItem;
|
||||||
|
@Override
|
||||||
|
public void addItems(ArrayList<Item> items) {
|
||||||
|
items.add(new SwitchItem(R.string.sk_settings_show_replies, R.drawable.ic_fluent_chat_multiple_24_regular, GlobalUserPreferences.showReplies, i->{
|
||||||
|
GlobalUserPreferences.showReplies=i.checked;
|
||||||
|
GlobalUserPreferences.save();
|
||||||
|
}));
|
||||||
|
if (getInstance().pleroma != null) {
|
||||||
|
items.add(new ButtonItem(R.string.sk_settings_reply_visibility, R.drawable.ic_fluent_chat_24_regular, b->{
|
||||||
|
PopupMenu popupMenu=new PopupMenu(getActivity(), b, Gravity.CENTER_HORIZONTAL);
|
||||||
|
popupMenu.inflate(R.menu.reply_visibility);
|
||||||
|
popupMenu.setOnMenuItemClickListener(item -> this.onReplyVisibilityChanged(item, b));
|
||||||
|
b.setOnTouchListener(popupMenu.getDragToOpenListener());
|
||||||
|
b.setOnClickListener(v->popupMenu.show());
|
||||||
|
b.setText(GlobalUserPreferences.replyVisibility == null ?
|
||||||
|
R.string.sk_settings_reply_visibility_all :
|
||||||
|
switch(GlobalUserPreferences.replyVisibility){
|
||||||
|
case "following" -> R.string.sk_settings_reply_visibility_following;
|
||||||
|
case "self" -> R.string.sk_settings_reply_visibility_self;
|
||||||
|
default -> R.string.sk_settings_reply_visibility_all;
|
||||||
|
});
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
items.add(new SwitchItem(R.string.sk_settings_show_boosts, R.drawable.ic_fluent_arrow_repeat_all_24_regular, GlobalUserPreferences.showBoosts, i->{
|
||||||
|
GlobalUserPreferences.showBoosts=i.checked;
|
||||||
|
GlobalUserPreferences.save();
|
||||||
|
}));
|
||||||
|
items.add(new SwitchItem(R.string.sk_settings_load_new_posts, R.drawable.ic_fluent_arrow_sync_24_regular, GlobalUserPreferences.loadNewPosts, i->{
|
||||||
|
GlobalUserPreferences.loadNewPosts=i.checked;
|
||||||
|
showNewPostsItem.enabled = i.checked;
|
||||||
|
if (!i.checked) {
|
||||||
|
GlobalUserPreferences.showNewPostsButton = false;
|
||||||
|
showNewPostsItem.checked = false;
|
||||||
|
}
|
||||||
|
if (list.findViewHolderForAdapterPosition(items.indexOf(showNewPostsItem)) instanceof SwitchViewHolder svh) svh.rebind();
|
||||||
|
GlobalUserPreferences.save();
|
||||||
|
}));
|
||||||
|
items.add(showNewPostsItem = new SwitchItem(R.string.sk_settings_show_new_posts_button, R.drawable.ic_fluent_arrow_up_24_regular, GlobalUserPreferences.showNewPostsButton, i->{
|
||||||
|
GlobalUserPreferences.showNewPostsButton=i.checked;
|
||||||
|
GlobalUserPreferences.save();
|
||||||
|
}));
|
||||||
|
|
||||||
|
items.add(new SwitchItem(R.string.sk_settings_show_alt_indicator, R.drawable.ic_fluent_scan_text_24_regular, GlobalUserPreferences.showAltIndicator, i->{
|
||||||
|
GlobalUserPreferences.showAltIndicator=i.checked;
|
||||||
|
GlobalUserPreferences.save();
|
||||||
|
needAppRestart=true;
|
||||||
|
}));
|
||||||
|
items.add(new SwitchItem(R.string.sk_settings_show_no_alt_indicator, R.drawable.ic_fluent_important_24_regular, GlobalUserPreferences.showNoAltIndicator, i->{
|
||||||
|
GlobalUserPreferences.showNoAltIndicator=i.checked;
|
||||||
|
GlobalUserPreferences.save();
|
||||||
|
needAppRestart=true;
|
||||||
|
}));
|
||||||
|
items.add(new SwitchItem(R.string.sk_settings_collapse_long_posts, R.drawable.ic_fluent_chevron_down_24_regular, GlobalUserPreferences.collapseLongPosts, i->{
|
||||||
|
GlobalUserPreferences.collapseLongPosts=i.checked;
|
||||||
|
GlobalUserPreferences.save();
|
||||||
|
}));
|
||||||
|
items.add(new SwitchItem(R.string.sk_settings_hide_fab, R.drawable.ic_fluent_edit_24_regular, GlobalUserPreferences.autoHideFab, i->{
|
||||||
|
GlobalUserPreferences.autoHideFab=i.checked;
|
||||||
|
GlobalUserPreferences.save();
|
||||||
|
needAppRestart=true;
|
||||||
|
}));
|
||||||
|
items.add(new SwitchItem(R.string.sk_reply_line_above_avatar, R.drawable.ic_fluent_arrow_reply_24_regular, GlobalUserPreferences.replyLineAboveHeader, i->{
|
||||||
|
GlobalUserPreferences.replyLineAboveHeader=i.checked;
|
||||||
|
GlobalUserPreferences.compactReblogReplyLine=i.checked;
|
||||||
|
compactReblogReplyLineItem.enabled=i.checked;
|
||||||
|
compactReblogReplyLineItem.checked= GlobalUserPreferences.replyLineAboveHeader;
|
||||||
|
if (list.findViewHolderForAdapterPosition(items.indexOf(compactReblogReplyLineItem)) instanceof SwitchViewHolder svh) svh.rebind();
|
||||||
|
GlobalUserPreferences.save();
|
||||||
|
needAppRestart=true;
|
||||||
|
}));
|
||||||
|
items.add(compactReblogReplyLineItem=new SwitchItem(R.string.sk_compact_reblog_reply_line, R.drawable.ic_fluent_re_order_24_regular, GlobalUserPreferences.compactReblogReplyLine, i->{
|
||||||
|
GlobalUserPreferences.compactReblogReplyLine=i.checked;
|
||||||
|
GlobalUserPreferences.save();
|
||||||
|
needAppRestart=true;
|
||||||
|
}));
|
||||||
|
items.add(new SwitchItem(R.string.sk_settings_show_interaction_counts, R.string.mo_setting_interaction_count_summary, R.drawable.ic_fluent_number_row_24_regular, GlobalUserPreferences.showInteractionCounts, i->{
|
||||||
|
GlobalUserPreferences.showInteractionCounts=i.checked;
|
||||||
|
GlobalUserPreferences.save();
|
||||||
|
}));
|
||||||
|
compactReblogReplyLineItem.enabled=GlobalUserPreferences.replyLineAboveHeader;
|
||||||
|
items.add(new SwitchItem(R.string.sk_settings_hide_interaction, R.drawable.ic_fluent_eye_24_regular, GlobalUserPreferences.spectatorMode, i->{
|
||||||
|
GlobalUserPreferences.spectatorMode=i.checked;
|
||||||
|
GlobalUserPreferences.save();
|
||||||
|
needAppRestart=true;
|
||||||
|
}));
|
||||||
|
items.add(new SwitchItem(R.string.mo_enable_dividers, R.drawable.ic_fluent_timeline_24_regular, GlobalUserPreferences.showDividers, i->{
|
||||||
|
GlobalUserPreferences.showDividers =i.checked;
|
||||||
|
GlobalUserPreferences.save();
|
||||||
|
needAppRestart=true;
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean onReplyVisibilityChanged(MenuItem item, Button btn){
|
||||||
|
String pref = null;
|
||||||
|
int id = item.getItemId();
|
||||||
|
|
||||||
|
if (id == R.id.reply_visibility_following) pref = "following";
|
||||||
|
else if (id == R.id.reply_visibility_self) pref = "self";
|
||||||
|
|
||||||
|
GlobalUserPreferences.replyVisibility=pref;
|
||||||
|
GlobalUserPreferences.save();
|
||||||
|
btn.setText(GlobalUserPreferences.replyVisibility == null ?
|
||||||
|
R.string.sk_settings_reply_visibility_all :
|
||||||
|
switch(GlobalUserPreferences.replyVisibility){
|
||||||
|
case "following" -> R.string.sk_settings_reply_visibility_following;
|
||||||
|
case "self" -> R.string.sk_settings_reply_visibility_self;
|
||||||
|
default -> R.string.sk_settings_reply_visibility_all;
|
||||||
|
});
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
|
@ -5,5 +5,5 @@
|
||||||
android:viewportHeight="24">
|
android:viewportHeight="24">
|
||||||
<path
|
<path
|
||||||
android:pathData="M22,12c0,-5.523 -4.477,-10 -10,-10S2,6.477 2,12a9.96,9.96 0,0 0,1.115 4.592l-1.068,3.823a1.25,1.25 0,0 0,1.54 1.54l3.826,-1.067a9.96,9.96 0,0 0,5.368 1.082,6.518 6.518,0 0,1 -1.051,-1.474 8.449,8.449 0,0 1,-3.863 -1.066l-0.27,-0.15 -3.986,1.111 1.113,-3.984 -0.151,-0.27A8.458,8.458 0,0 1,3.5 12a8.5,8.5 0,0 1,16.996 -0.27c0.54,0.281 1.036,0.636 1.474,1.05 0.02,-0.257 0.03,-0.517 0.03,-0.78ZM12.837,16.472a2,2 0,0 0,1.441 -2.496l-0.198,-0.687a5.28,5.28 0,0 1,1.483 -0.912l0.499,0.524a2,2 0,0 0,2.899 0.001l0.493,-0.518a5.28,5.28 0,0 1,1.484 0.921l-0.186,0.631a2,2 0,0 0,1.45 2.51l0.539,0.13a5.732,5.732 0,0 1,0.006 1.808l-0.584,0.144a2,2 0,0 0,-1.44 2.496l0.197,0.686c-0.439,0.383 -0.939,0.693 -1.483,0.913l-0.498,-0.525a2,2 0,0 0,-2.9 0l-0.493,0.519a5.28,5.28 0,0 1,-1.484 -0.922l0.187,-0.631a2,2 0,0 0,-1.45 -2.51l-0.54,-0.13a5.718,5.718 0,0 1,-0.006 -1.808l0.584,-0.144ZM18.95,17.5c0,-0.828 -0.65,-1.5 -1.45,-1.5 -0.8,0 -1.45,0.672 -1.45,1.5S16.7,19 17.5,19c0.8,0 1.45,-0.672 1.45,-1.5Z"
|
android:pathData="M22,12c0,-5.523 -4.477,-10 -10,-10S2,6.477 2,12a9.96,9.96 0,0 0,1.115 4.592l-1.068,3.823a1.25,1.25 0,0 0,1.54 1.54l3.826,-1.067a9.96,9.96 0,0 0,5.368 1.082,6.518 6.518,0 0,1 -1.051,-1.474 8.449,8.449 0,0 1,-3.863 -1.066l-0.27,-0.15 -3.986,1.111 1.113,-3.984 -0.151,-0.27A8.458,8.458 0,0 1,3.5 12a8.5,8.5 0,0 1,16.996 -0.27c0.54,0.281 1.036,0.636 1.474,1.05 0.02,-0.257 0.03,-0.517 0.03,-0.78ZM12.837,16.472a2,2 0,0 0,1.441 -2.496l-0.198,-0.687a5.28,5.28 0,0 1,1.483 -0.912l0.499,0.524a2,2 0,0 0,2.899 0.001l0.493,-0.518a5.28,5.28 0,0 1,1.484 0.921l-0.186,0.631a2,2 0,0 0,1.45 2.51l0.539,0.13a5.732,5.732 0,0 1,0.006 1.808l-0.584,0.144a2,2 0,0 0,-1.44 2.496l0.197,0.686c-0.439,0.383 -0.939,0.693 -1.483,0.913l-0.498,-0.525a2,2 0,0 0,-2.9 0l-0.493,0.519a5.28,5.28 0,0 1,-1.484 -0.922l0.187,-0.631a2,2 0,0 0,-1.45 -2.51l-0.54,-0.13a5.718,5.718 0,0 1,-0.006 -1.808l0.584,-0.144ZM18.95,17.5c0,-0.828 -0.65,-1.5 -1.45,-1.5 -0.8,0 -1.45,0.672 -1.45,1.5S16.7,19 17.5,19c0.8,0 1.45,-0.672 1.45,-1.5Z"
|
||||||
android:fillColor="#212121"/>
|
android:fillColor="@color/fluent_default_icon_tint"/>
|
||||||
</vector>
|
</vector>
|
||||||
|
|
|
@ -13,24 +13,40 @@
|
||||||
android:layout_width="24dp"
|
android:layout_width="24dp"
|
||||||
android:layout_height="24dp"
|
android:layout_height="24dp"
|
||||||
android:layout_marginStart="16dp"
|
android:layout_marginStart="16dp"
|
||||||
android:layout_marginEnd="16dp"
|
android:layout_marginEnd="32dp"
|
||||||
android:importantForAccessibility="no"
|
android:importantForAccessibility="no"
|
||||||
android:tint="?android:textColorPrimary"
|
android:tint="?android:textColorPrimary"
|
||||||
tools:src="@drawable/ic_fluent_color_24_regular"/>
|
tools:src="@drawable/ic_fluent_color_24_regular"/>
|
||||||
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/text"
|
<RelativeLayout
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_weight="1"
|
|
||||||
android:layout_marginStart="16dp"
|
|
||||||
android:layout_marginEnd="8dp"
|
android:layout_marginEnd="8dp"
|
||||||
android:paddingVertical="8dp"
|
android:paddingVertical="8dp"
|
||||||
android:gravity="center_vertical"
|
android:layout_weight="1">
|
||||||
android:textColor="?android:textColorPrimary"
|
|
||||||
android:textSize="16sp" />
|
|
||||||
|
|
||||||
|
<TextView android:id="@+id/title"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:singleLine="true"
|
||||||
|
android:ellipsize="marquee"
|
||||||
|
android:textColor="?android:textColorPrimary"
|
||||||
|
android:textSize="16sp"
|
||||||
|
android:fadingEdge="horizontal"
|
||||||
|
android:text=""/>
|
||||||
|
|
||||||
|
<TextView android:id="@+id/summary"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:textColor="?android:textColorSecondary"
|
||||||
|
android:layout_below="@id/title"
|
||||||
|
android:layout_alignStart="@id/title"
|
||||||
|
android:visibility="gone"
|
||||||
|
android:maxLines="4" />
|
||||||
|
|
||||||
|
</RelativeLayout>
|
||||||
<Button
|
<Button
|
||||||
android:id="@+id/button"
|
android:id="@+id/button"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
|
|
|
@ -0,0 +1,32 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:minHeight="48dp"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:layoutDirection="locale">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/icon"
|
||||||
|
android:layout_width="24dp"
|
||||||
|
android:layout_height="24dp"
|
||||||
|
android:layout_marginStart="16dp"
|
||||||
|
android:layout_marginEnd="32dp"
|
||||||
|
android:importantForAccessibility="no"
|
||||||
|
android:tint="?android:textColorPrimary"
|
||||||
|
tools:src="@drawable/ic_fluent_color_24_regular"/>
|
||||||
|
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/text"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:layout_marginEnd="8dp"
|
||||||
|
android:paddingVertical="8dp"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:textColor="?android:textColorPrimary"
|
||||||
|
android:textSize="16sp" />
|
||||||
|
</LinearLayout>
|
|
@ -17,16 +17,34 @@
|
||||||
android:tint="?android:textColorPrimary"
|
android:tint="?android:textColorPrimary"
|
||||||
tools:src="@drawable/ic_fluent_star_24_regular"/>
|
tools:src="@drawable/ic_fluent_star_24_regular"/>
|
||||||
|
|
||||||
<TextView
|
<RelativeLayout
|
||||||
android:id="@+id/text"
|
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_weight="1"
|
android:layout_marginStart="15dip"
|
||||||
android:layout_marginStart="16dp"
|
android:layout_marginEnd="6dip"
|
||||||
android:paddingVertical="8dp"
|
android:layout_marginTop="6dip"
|
||||||
android:textSize="16sp"
|
android:layout_marginBottom="6dip"
|
||||||
|
android:layout_weight="1">
|
||||||
|
|
||||||
|
<TextView android:id="@+id/title"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:ellipsize="marquee"
|
||||||
android:textColor="?android:textColorPrimary"
|
android:textColor="?android:textColorPrimary"
|
||||||
tools:text="@string/theme_true_black"/>
|
android:textSize="16sp"
|
||||||
|
android:fadingEdge="horizontal"
|
||||||
|
android:text=""/>
|
||||||
|
|
||||||
|
<TextView android:id="@+id/summary"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_below="@id/title"
|
||||||
|
android:textColor="?android:textColorSecondary"
|
||||||
|
android:layout_alignStart="@id/title"
|
||||||
|
android:visibility="gone"
|
||||||
|
android:maxLines="4" />
|
||||||
|
|
||||||
|
</RelativeLayout>
|
||||||
|
|
||||||
<Switch
|
<Switch
|
||||||
android:id="@+id/checkbox"
|
android:id="@+id/checkbox"
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:paddingLeft="16dp"
|
android:paddingLeft="16dp"
|
||||||
android:paddingRight="16dp"
|
android:paddingRight="16dp"
|
||||||
|
android:paddingTop="16dp"
|
||||||
android:paddingBottom="8dp"
|
android:paddingBottom="8dp"
|
||||||
android:clipChildren="false"
|
android:clipChildren="false"
|
||||||
android:clipToPadding="false">
|
android:clipToPadding="false">
|
||||||
|
|
|
@ -6,12 +6,12 @@
|
||||||
|
|
||||||
<string name="mo_color_palette_nord">Nord</string>
|
<string name="mo_color_palette_nord">Nord</string>
|
||||||
<string name="mo_app_username" translatable="false">\@moshidon</string>
|
<string name="mo_app_username" translatable="false">\@moshidon</string>
|
||||||
<string name="mo_disable_dividers">Disable post dividers</string>
|
<string name="mo_enable_dividers">Show post dividers</string>
|
||||||
<string name="mo_relocate_publish_button">Relocate publish button</string>
|
<string name="mo_relocate_publish_button">Relocate publish button</string>
|
||||||
<string name="mo_hide_compose_button_while_scrolling_setting">Hide compose button while scrolling</string>
|
<string name="mo_hide_compose_button_while_scrolling_setting">Hide compose button while scrolling</string>
|
||||||
<string name="mo_welcome_text">To get started, please enter your home instance’s domain name below.</string>
|
<string name="mo_welcome_text">To get started, please enter your home instance’s domain name below.</string>
|
||||||
|
|
||||||
<!-- Setting this as non-translatable as it simply doesnt change with language-->
|
<!-- Setting this as non-translatable as it simply doesn't change with language-->
|
||||||
<string name="mo_settings_app_version" translatable="false">Moshidon v%1$s (%2$d)</string>
|
<string name="mo_settings_app_version" translatable="false">Moshidon v%1$s (%2$d)</string>
|
||||||
|
|
||||||
<string name="mo_personal_note">Add a note about this profile</string>
|
<string name="mo_personal_note">Add a note about this profile</string>
|
||||||
|
@ -29,9 +29,9 @@
|
||||||
<string name="mo_disable_reminder_to_add_alt_text">Disable reminder to add alt text</string>
|
<string name="mo_disable_reminder_to_add_alt_text">Disable reminder to add alt text</string>
|
||||||
<string name="mo_add_custom_server_local_timeline">Add a custom server\'s local timeline</string>
|
<string name="mo_add_custom_server_local_timeline">Add a custom server\'s local timeline</string>
|
||||||
<string name="mo_notification_action_replied">Successfully replied to the post by %s</string>
|
<string name="mo_notification_action_replied">Successfully replied to the post by %s</string>
|
||||||
<string name="mo_change_default_reply_visibility_to_unlisted">Change default reply visibility to unlisted</string>
|
<string name="mo_change_default_reply_visibility_to_unlisted">Reply as \'Unlisted\' by default</string>
|
||||||
<string name="mo_composer_behavior">Composer\'s Behavior</string>
|
<string name="mo_composer_behavior">Composer\'s Behavior</string>
|
||||||
<string name="mo_miscellaneous_settings">Miscellaneous Settings</string>
|
<string name="mo_notification_management_settings">Manage Notifications</string>
|
||||||
|
|
||||||
<!-- accessibility labels-->
|
<!-- accessibility labels-->
|
||||||
<string name="mo_poll_option_add">Add new poll option</string>
|
<string name="mo_poll_option_add">Add new poll option</string>
|
||||||
|
@ -50,8 +50,8 @@
|
||||||
<string name="mo_duration_days_7">7 days</string>
|
<string name="mo_duration_days_7">7 days</string>
|
||||||
|
|
||||||
<string name="mo_share_open_url">Open in App</string>
|
<string name="mo_share_open_url">Open in App</string>
|
||||||
<string name="mo_disable_double_tap_to_swipe_between_tabs">Disable double tap to swipe between tabs</string>
|
<string name="mo_double_tap_to_swipe_between_tabs">Double tap to swipe between tabs</string>
|
||||||
<string name="mo_swap_bookmark_with_reblog">Use reblog action instead of bookmark action on notifications</string>
|
<string name="mo_swap_bookmark_with_reblog">Swap bookmark with reblog action</string>
|
||||||
<string name="mo_download_latest_nightly_release">Download latest nightly release</string>
|
<string name="mo_download_latest_nightly_release">Download latest nightly release</string>
|
||||||
<string name="mo_load_remote_followers">Load remote profile follows and followers</string>
|
<string name="mo_load_remote_followers">Load remote profile follows and followers</string>
|
||||||
<string name="mo_mention_reblogger_automatically">Automatically mention account who reblogged the post in replies</string>
|
<string name="mo_mention_reblogger_automatically">Automatically mention account who reblogged the post in replies</string>
|
||||||
|
@ -69,4 +69,20 @@
|
||||||
<string name="mo_instance_info_moderated_servers">Moderated servers</string>
|
<string name="mo_instance_info_moderated_servers">Moderated servers</string>
|
||||||
<string name="mo_severity_silence">Silenced</string>
|
<string name="mo_severity_silence">Silenced</string>
|
||||||
<string name="mo_severity_suspend">Blocked</string>
|
<string name="mo_severity_suspend">Blocked</string>
|
||||||
|
|
||||||
|
<!-- Settings summaries-->
|
||||||
|
<string name="mo_setting_true_black_summary">Might save power on AMOLED displays</string>
|
||||||
|
<string name="mo_setting_marquee_summary">Disables the ellipsized title scrolling</string>
|
||||||
|
<string name="mo_setting_uniform_summary">Use the app icon for all notifications</string>
|
||||||
|
<string name="mo_setting_reduced_motion_summary">Disable animations of interactions</string>
|
||||||
|
<string name="mo_setting_play_gif_summary">Autoplay GIFs in avatars and emoji</string>
|
||||||
|
<string name="mo_setting_remote_follower_summary">Show followers from other instances</string>
|
||||||
|
<string name="mo_setting_relocate_publish_summary">Move the publish button to the bottom bar</string>
|
||||||
|
<string name="mo_setting_default_reply_privacy_summary">Replies will be opted out of discovery features</string>
|
||||||
|
<string name="mo_setting_interaction_count_summary">Show how many people interacted with a post in the timeline</string>
|
||||||
|
<string name="mo_setting_disable_swipe_summary">Swipe to change viewed timeline</string>
|
||||||
|
<string name="mo_swap_bookmark_with_reblog_summary">Bookmark or reblog posts from the notification</string>
|
||||||
|
|
||||||
|
<!-- Settings -->
|
||||||
|
<string name="mo_notification_audience_settings">Notification Audience</string>
|
||||||
</resources>
|
</resources>
|
|
@ -240,7 +240,7 @@
|
||||||
<string name="sk_settings_show_alt_indicator">Indicator for alt texts</string>
|
<string name="sk_settings_show_alt_indicator">Indicator for alt texts</string>
|
||||||
<string name="sk_settings_show_no_alt_indicator">Indicator for missing alt texts</string>
|
<string name="sk_settings_show_no_alt_indicator">Indicator for missing alt texts</string>
|
||||||
<string name="sk_updater_enable_pre_releases">Enable pre-releases</string>
|
<string name="sk_updater_enable_pre_releases">Enable pre-releases</string>
|
||||||
<string name="sk_settings_see_new_posts_button">“See new posts” button</string>
|
<string name="sk_settings_show_new_posts_button">“Show new posts” button</string>
|
||||||
<string name="sk_inline_local_only">local-only</string>
|
<string name="sk_inline_local_only">local-only</string>
|
||||||
<string name="sk_inline_direct">mentioned-only</string>
|
<string name="sk_inline_direct">mentioned-only</string>
|
||||||
<string name="sk_separator">·</string>
|
<string name="sk_separator">·</string>
|
||||||
|
|
Loading…
Reference in New Issue