package org.joinmastodon.android; import static org.joinmastodon.android.api.MastodonAPIController.gson; import static org.joinmastodon.android.api.session.AccountLocalPreferences.ColorPreference.MATERIAL3; import android.content.Context; import android.content.SharedPreferences; import android.util.Log; import com.google.gson.JsonSyntaxException; import com.google.gson.reflect.TypeToken; import org.joinmastodon.android.api.session.AccountLocalPreferences; import org.joinmastodon.android.api.session.AccountLocalPreferences.ColorPreference; import org.joinmastodon.android.api.session.AccountSession; import org.joinmastodon.android.api.session.AccountSessionManager; import org.joinmastodon.android.model.ContentType; import org.joinmastodon.android.model.Instance; import org.joinmastodon.android.model.TimelineDefinition; import java.lang.reflect.Type; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; public class GlobalUserPreferences{ private static final String TAG="GlobalUserPreferences"; public static boolean playGifs; public static boolean useCustomTabs; public static boolean altTextReminders, confirmUnfollow, confirmBoost, confirmDeletePost; public static ThemePreference theme; // MEGALODON public static boolean trueBlackTheme; public static boolean loadNewPosts; public static boolean showNewPostsButton; public static boolean toolbarMarquee; public static boolean disableSwipe; public static boolean voteButtonForSingleChoice; public static boolean enableDeleteNotifications; public static boolean translateButtonOpenedOnly; public static boolean uniformNotificationIcon; public static boolean reduceMotion; public static boolean showAltIndicator; public static boolean showNoAltIndicator; public static boolean enablePreReleases; public static PrefixRepliesMode prefixReplies; public static boolean collapseLongPosts; public static boolean spectatorMode; public static boolean autoHideFab; public static boolean allowRemoteLoading; public static boolean forwardReportDefault; public static AutoRevealMode autoRevealEqualSpoilers; public static boolean disableM3PillActiveIndicator; public static boolean showNavigationLabels; public static boolean displayPronounsInTimelines, displayPronounsInThreads, displayPronounsInUserListings; public static boolean overlayMedia; public static boolean showSuicideHelp; public static boolean underlinedLinks; public static ColorPreference color; public static boolean likeIcon; private static SharedPreferences getPrefs(){ return MastodonApp.context.getSharedPreferences("global", Context.MODE_PRIVATE); } public static T fromJson(String json, Type type, T orElse){ if(json==null) return orElse; try{ T value=gson.fromJson(json, type); return value==null ? orElse : value; }catch(JsonSyntaxException ignored){ return orElse; } } public static > T enumValue(Class enumType, String name) { try { return Enum.valueOf(enumType, name); } catch (NullPointerException npe) { return null; } } public static void load(){ SharedPreferences prefs=getPrefs(); playGifs=prefs.getBoolean("playGifs", true); useCustomTabs=prefs.getBoolean("useCustomTabs", true); theme=ThemePreference.values()[prefs.getInt("theme", 0)]; altTextReminders=prefs.getBoolean("altTextReminders", true); confirmUnfollow=prefs.getBoolean("confirmUnfollow", true); confirmBoost=prefs.getBoolean("confirmBoost", false); confirmDeletePost=prefs.getBoolean("confirmDeletePost", true); // MEGALODON trueBlackTheme=prefs.getBoolean("trueBlackTheme", false); loadNewPosts=prefs.getBoolean("loadNewPosts", true); showNewPostsButton=prefs.getBoolean("showNewPostsButton", true); toolbarMarquee=prefs.getBoolean("toolbarMarquee", true); disableSwipe=prefs.getBoolean("disableSwipe", false); voteButtonForSingleChoice=prefs.getBoolean("voteButtonForSingleChoice", true); enableDeleteNotifications=prefs.getBoolean("enableDeleteNotifications", false); translateButtonOpenedOnly=prefs.getBoolean("translateButtonOpenedOnly", false); uniformNotificationIcon=prefs.getBoolean("uniformNotificationIcon", false); reduceMotion=prefs.getBoolean("reduceMotion", false); showAltIndicator=prefs.getBoolean("showAltIndicator", true); showNoAltIndicator=prefs.getBoolean("showNoAltIndicator", true); enablePreReleases=prefs.getBoolean("enablePreReleases", false); prefixReplies=PrefixRepliesMode.valueOf(prefs.getString("prefixReplies", PrefixRepliesMode.NEVER.name())); collapseLongPosts=prefs.getBoolean("collapseLongPosts", true); spectatorMode=prefs.getBoolean("spectatorMode", false); autoHideFab=prefs.getBoolean("autoHideFab", true); allowRemoteLoading=prefs.getBoolean("allowRemoteLoading", true); autoRevealEqualSpoilers=AutoRevealMode.valueOf(prefs.getString("autoRevealEqualSpoilers", AutoRevealMode.THREADS.name())); forwardReportDefault=prefs.getBoolean("forwardReportDefault", true); disableM3PillActiveIndicator=prefs.getBoolean("disableM3PillActiveIndicator", false); showNavigationLabels=prefs.getBoolean("showNavigationLabels", true); displayPronounsInTimelines=prefs.getBoolean("displayPronounsInTimelines", true); displayPronounsInThreads=prefs.getBoolean("displayPronounsInThreads", true); displayPronounsInUserListings=prefs.getBoolean("displayPronounsInUserListings", true); overlayMedia=prefs.getBoolean("overlayMedia", false); showSuicideHelp=prefs.getBoolean("showSuicideHelp", true); underlinedLinks=prefs.getBoolean("underlinedLinks", true); color=ColorPreference.valueOf(prefs.getString("color", MATERIAL3.name())); likeIcon=prefs.getBoolean("likeIcon", false); if (prefs.contains("prefixRepliesWithRe")) { prefixReplies = prefs.getBoolean("prefixRepliesWithRe", false) ? PrefixRepliesMode.TO_OTHERS : PrefixRepliesMode.NEVER; prefs.edit() .putString("prefixReplies", prefixReplies.name()) .remove("prefixRepliesWithRe") .apply(); } int migrationLevel=prefs.getInt("migrationLevel", BuildConfig.VERSION_CODE); if(migrationLevel < 61) migrateToUpstreamVersion61(); if(migrationLevel < BuildConfig.VERSION_CODE) prefs.edit().putInt("migrationLevel", BuildConfig.VERSION_CODE).apply(); } public static void save(){ getPrefs().edit() .putBoolean("playGifs", playGifs) .putBoolean("useCustomTabs", useCustomTabs) .putInt("theme", theme.ordinal()) .putBoolean("altTextReminders", altTextReminders) .putBoolean("confirmUnfollow", confirmUnfollow) .putBoolean("confirmBoost", confirmBoost) .putBoolean("confirmDeletePost", confirmDeletePost) // MEGALODON .putBoolean("loadNewPosts", loadNewPosts) .putBoolean("showNewPostsButton", showNewPostsButton) .putBoolean("trueBlackTheme", trueBlackTheme) .putBoolean("toolbarMarquee", toolbarMarquee) .putBoolean("disableSwipe", disableSwipe) .putBoolean("enableDeleteNotifications", enableDeleteNotifications) .putBoolean("translateButtonOpenedOnly", translateButtonOpenedOnly) .putBoolean("uniformNotificationIcon", uniformNotificationIcon) .putBoolean("reduceMotion", reduceMotion) .putBoolean("showAltIndicator", showAltIndicator) .putBoolean("showNoAltIndicator", showNoAltIndicator) .putBoolean("enablePreReleases", enablePreReleases) .putString("prefixReplies", prefixReplies.name()) .putBoolean("collapseLongPosts", collapseLongPosts) .putBoolean("spectatorMode", spectatorMode) .putBoolean("autoHideFab", autoHideFab) .putBoolean("allowRemoteLoading", allowRemoteLoading) .putString("autoRevealEqualSpoilers", autoRevealEqualSpoilers.name()) .putBoolean("forwardReportDefault", forwardReportDefault) .putBoolean("disableM3PillActiveIndicator", disableM3PillActiveIndicator) .putBoolean("showNavigationLabels", showNavigationLabels) .putBoolean("displayPronounsInTimelines", displayPronounsInTimelines) .putBoolean("displayPronounsInThreads", displayPronounsInThreads) .putBoolean("displayPronounsInUserListings", displayPronounsInUserListings) .putBoolean("overlayMedia", overlayMedia) .putBoolean("showSuicideHelp", showSuicideHelp) .putBoolean("underlinedLinks", underlinedLinks) .putString("color", color.name()) .putBoolean("likeIcon", likeIcon) .apply(); } public enum ThemePreference{ AUTO, LIGHT, DARK } public enum AutoRevealMode { NEVER, THREADS, DISCUSSIONS } public enum PrefixRepliesMode { NEVER, ALWAYS, TO_OTHERS } //region preferences migrations private static void migrateToUpstreamVersion61(){ Log.d(TAG, "Migrating preferences to upstream version 61!!"); Type accountsDefaultContentTypesType = new TypeToken>() {}.getType(); Type pinnedTimelinesType = new TypeToken>>() {}.getType(); Type recentLanguagesType = new TypeToken>>() {}.getType(); // migrate global preferences SharedPreferences prefs=getPrefs(); altTextReminders=!prefs.getBoolean("disableAltTextReminder", false); confirmBoost=prefs.getBoolean("confirmBeforeReblog", false); toolbarMarquee=!prefs.getBoolean("disableMarquee", false); save(); // migrate local preferences AccountSessionManager asm=AccountSessionManager.getInstance(); // reset: Set accountsWithContentTypesEnabled=prefs.getStringSet("accountsWithContentTypesEnabled", new HashSet<>()); Map accountsDefaultContentTypes=fromJson(prefs.getString("accountsDefaultContentTypes", null), accountsDefaultContentTypesType, new HashMap<>()); Map> pinnedTimelines=fromJson(prefs.getString("pinnedTimelines", null), pinnedTimelinesType, new HashMap<>()); Set accountsWithLocalOnlySupport=prefs.getStringSet("accountsWithLocalOnlySupport", new HashSet<>()); Set accountsInGlitchMode=prefs.getStringSet("accountsInGlitchMode", new HashSet<>()); Map> recentLanguages=fromJson(prefs.getString("recentLanguages", null), recentLanguagesType, new HashMap<>()); for(AccountSession session : asm.getLoggedInAccounts()){ String accountID=session.getID(); AccountLocalPreferences localPrefs=session.getLocalPreferences(); localPrefs.revealCWs=prefs.getBoolean("alwaysExpandContentWarnings", false); localPrefs.recentLanguages=recentLanguages.get(accountID); // reset: localPrefs.contentTypesEnabled=accountsWithContentTypesEnabled.contains(accountID); localPrefs.defaultContentType=accountsDefaultContentTypes.getOrDefault(accountID, ContentType.PLAIN); localPrefs.showInteractionCounts=prefs.getBoolean("showInteractionCounts", false); localPrefs.timelines=pinnedTimelines.getOrDefault(accountID, TimelineDefinition.getDefaultTimelines(accountID)); localPrefs.localOnlySupported=accountsWithLocalOnlySupport.contains(accountID); localPrefs.glitchInstance=accountsInGlitchMode.contains(accountID); localPrefs.publishButtonText=prefs.getString("publishButtonText", null); localPrefs.keepOnlyLatestNotification=prefs.getBoolean("keepOnlyLatestNotification", false); localPrefs.showReplies=prefs.getBoolean("showReplies", true); localPrefs.showBoosts=prefs.getBoolean("showBoosts", true); if(session.getInstance().map(Instance::isAkkoma).orElse(false)){ localPrefs.timelineReplyVisibility=prefs.getString("replyVisibility", null); } localPrefs.save(); } } //endregion }