Introduce ThemeManager to group theme-related logic

This commit is contained in:
cketti 2019-05-22 13:44:12 +02:00
parent 6257efa007
commit be124ec896
10 changed files with 116 additions and 67 deletions

View file

@ -326,10 +326,6 @@ object K9 : KoinComponent {
val k9MessageViewTheme: Theme
get() = if (k9MessageViewThemeSetting == Theme.USE_GLOBAL) k9Theme else k9MessageViewThemeSetting
@JvmStatic
val k9ComposerTheme: Theme
get() = if (k9ComposerThemeSetting == Theme.USE_GLOBAL) k9Theme else k9ComposerThemeSetting
val isQuietTime: Boolean
get() {
if (!isQuietTimeEnabled) {

View file

@ -16,6 +16,7 @@ import android.view.View;
import com.fsck.k9.activity.K9ActivityCommon.K9ActivityMagic;
import com.fsck.k9.activity.misc.SwipeGestureDetector.OnSwipeGestureListener;
import com.fsck.k9.ui.R;
import com.fsck.k9.ui.ThemeManager;
import com.fsck.k9.ui.permissions.PermissionRationaleDialogFragment;
import timber.log.Timber;
@ -28,6 +29,9 @@ public abstract class K9Activity extends AppCompatActivity implements K9Activity
private final K9ActivityCommon base = new K9ActivityCommon(this, ThemeType.DEFAULT);
public ThemeManager getThemeManager() {
return base.getThemeManager();
}
@Override
public void onCreate(Bundle savedInstanceState) {

View file

@ -1,18 +1,17 @@
package com.fsck.k9.activity
import java.util.Locale
import android.app.Activity
import android.content.res.Resources
import android.text.TextUtils
import android.view.GestureDetector
import android.view.MotionEvent
import com.fsck.k9.K9
import com.fsck.k9.K9.Theme
import com.fsck.k9.activity.misc.SwipeGestureDetector
import com.fsck.k9.activity.misc.SwipeGestureDetector.OnSwipeGestureListener
import com.fsck.k9.ui.R
import com.fsck.k9.ui.ThemeManager
import org.koin.standalone.KoinComponent
import org.koin.standalone.inject
import java.util.Locale
/**
@ -27,6 +26,9 @@ class K9ActivityCommon(
) {
private var gestureDetector: GestureDetector? = null
val themeManager = Companion.themeManager
/**
* Call this before calling `super.onCreate(Bundle)`.
*/
@ -34,9 +36,9 @@ class K9ActivityCommon(
setLanguage(K9.k9Language)
val theme = when (themeType) {
ThemeType.DEFAULT -> k9ThemeResourceId
ThemeType.ACTION_BAR -> k9ActionBarThemeResourceId
ThemeType.DIALOG -> translucentDialogThemeResourceId
ThemeType.DEFAULT -> themeManager.appThemeResourceId
ThemeType.ACTION_BAR -> themeManager.appActionBarThemeResourceId
ThemeType.DIALOG -> themeManager.translucentDialogThemeResourceId
}
activity.setTheme(theme)
}
@ -74,28 +76,8 @@ class K9ActivityCommon(
}
companion object {
@JvmStatic
fun getK9ThemeResourceId(themeId: Theme): Int {
return if (themeId === Theme.LIGHT) R.style.Theme_K9_Light else R.style.Theme_K9_Dark
}
@JvmStatic
val k9ActionBarThemeResourceId: Int
get() = if (k9ThemeResourceId == R.style.Theme_K9_Light)
R.style.Theme_K9_Light_ActionBar
else
R.style.Theme_K9_Dark_ActionBar
@JvmStatic
val k9ThemeResourceId: Int
get() = getK9ThemeResourceId(K9.k9Theme)
private val translucentDialogThemeResourceId: Int
get() = if (k9ThemeResourceId == R.style.Theme_K9_Light)
R.style.Theme_K9_Dialog_Translucent_Light
else
R.style.Theme_K9_Dialog_Translucent_Dark
companion object : KoinComponent {
private val themeManager: ThemeManager by inject()
}
/**

View file

@ -100,6 +100,7 @@ import com.fsck.k9.message.SimpleMessageFormat;
import com.fsck.k9.search.LocalSearch;
import com.fsck.k9.ui.EolConvertingEditText;
import com.fsck.k9.ui.R;
import com.fsck.k9.ui.ThemeManager;
import com.fsck.k9.ui.compose.QuotedMessageMvpView;
import com.fsck.k9.ui.compose.QuotedMessagePresenter;
import org.openintents.openpgp.OpenPgpApiManager;
@ -232,10 +233,11 @@ public class MessageCompose extends K9Activity implements OnClickListener,
}
requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
if (K9.getK9ComposerThemeSetting() != K9.Theme.USE_GLOBAL) {
ThemeManager themeManager = getThemeManager();
if (themeManager.getMessageComposeTheme() != themeManager.getAppTheme()) {
// theme the whole content according to the theme (except the action bar)
ContextThemeWrapper themeContext = new ContextThemeWrapper(this,
K9ActivityCommon.getK9ThemeResourceId(K9.getK9ComposerTheme()));
int messageComposeThemeResourceId = themeManager.getMessageComposeThemeResourceId();
ContextThemeWrapper themeContext = new ContextThemeWrapper(this, messageComposeThemeResourceId);
@SuppressLint("InflateParams") // this is the top level activity element, it has no root
View v = LayoutInflater.from(themeContext).inflate(R.layout.message_compose, null);
TypedValue outValue = new TypedValue();
@ -1127,10 +1129,8 @@ public class MessageCompose extends K9Activity implements OnClickListener,
})
.create();
case DIALOG_CHOOSE_IDENTITY:
Context context = new ContextThemeWrapper(this,
(K9.getK9Theme() == K9.Theme.LIGHT) ?
R.style.Theme_K9_Dialog_Light :
R.style.Theme_K9_Dialog_Dark);
int dialogThemeResourceId = getThemeManager().getDialogThemeResourceId();
Context context = new ContextThemeWrapper(this, dialogThemeResourceId);
Builder builder = new AlertDialog.Builder(context);
builder.setTitle(R.string.send_as);
final IdentityAdapter adapter = new IdentityAdapter(context);

View file

@ -47,7 +47,6 @@ import com.fsck.k9.helper.ParcelableUtil;
import com.fsck.k9.mailstore.SearchStatusManager;
import com.fsck.k9.mailstore.StorageManager;
import com.fsck.k9.notification.NotificationChannelManager;
import com.fsck.k9.preferences.StorageEditor;
import com.fsck.k9.search.LocalSearch;
import com.fsck.k9.search.SearchAccount;
import com.fsck.k9.search.SearchSpecification;
@ -56,6 +55,7 @@ import com.fsck.k9.search.SearchSpecification.SearchCondition;
import com.fsck.k9.search.SearchSpecification.SearchField;
import com.fsck.k9.ui.K9Drawer;
import com.fsck.k9.ui.R;
import com.fsck.k9.ui.Theme;
import com.fsck.k9.ui.messageview.MessageViewFragment;
import com.fsck.k9.ui.messageview.MessageViewFragment.MessageViewFragmentListener;
import com.fsck.k9.ui.settings.SettingsActivity;
@ -1075,7 +1075,7 @@ public class MessageList extends K9Activity implements MessageListFragmentListen
toggleTheme.setVisible(false);
} else {
// Set title of menu item to switch to dark/light theme
if (K9.getK9MessageViewTheme() == K9.Theme.DARK) {
if (getThemeManager().getMessageViewTheme() == Theme.DARK) {
toggleTheme.setTitle(R.string.message_view_theme_action_light);
} else {
toggleTheme.setTitle(R.string.message_view_theme_action_dark);
@ -1564,21 +1564,7 @@ public class MessageList extends K9Activity implements MessageListFragmentListen
}
private void onToggleTheme() {
if (K9.getK9MessageViewTheme() == K9.Theme.DARK) {
K9.setK9MessageViewThemeSetting(K9.Theme.LIGHT);
} else {
K9.setK9MessageViewThemeSetting(K9.Theme.DARK);
}
new Thread(new Runnable() {
@Override
public void run() {
StorageEditor editor = preferences.createStorageEditor();
K9.save(editor);
editor.commit();
}
}).start();
getThemeManager().toggleMessageViewTheme();
recreate();
}

View file

@ -4,17 +4,17 @@ import android.content.Context
import android.util.TypedValue
import android.view.ContextThemeWrapper
import com.fsck.k9.K9
import com.fsck.k9.activity.K9ActivityCommon
import com.fsck.k9.ui.R
import com.fsck.k9.ui.ThemeManager
class ContactLetterBitmapConfig(context: Context) {
class ContactLetterBitmapConfig(context: Context, themeManager: ThemeManager) {
val hasDefaultBackgroundColor: Boolean = !K9.isColorizeMissingContactPictures
val defaultBackgroundColor: Int
init {
defaultBackgroundColor = if (hasDefaultBackgroundColor) {
val outValue = TypedValue()
val themedContext = ContextThemeWrapper(context, K9ActivityCommon.k9ThemeResourceId)
val themedContext = ContextThemeWrapper(context, themeManager.appThemeResourceId)
themedContext.theme.resolveAttribute(R.attr.contactPictureFallbackDefaultBackgroundColor, outValue, true)
outValue.data
} else {

View file

@ -4,7 +4,7 @@ import org.koin.dsl.module.applicationContext
val contactsModule = applicationContext {
bean { ContactLetterExtractor() }
factory { ContactLetterBitmapConfig(get()) }
factory { ContactLetterBitmapConfig(get(), get()) }
factory { ContactLetterBitmapCreator(get(), get()) }
factory { ContactPictureLoader(get(), get()) }
}

View file

@ -7,4 +7,5 @@ import org.koin.dsl.module.applicationContext
val uiModule = applicationContext {
bean { FolderNameFormatter(get()) }
bean { HtmlToSpanned() }
bean { ThemeManager() }
}

View file

@ -0,0 +1,78 @@
package com.fsck.k9.ui
import androidx.annotation.StyleRes
import com.fsck.k9.K9
class ThemeManager {
val appTheme: Theme
get() = when (K9.k9Theme) {
K9.Theme.LIGHT -> Theme.LIGHT
K9.Theme.DARK -> Theme.DARK
K9.Theme.USE_GLOBAL -> error("App theme must be either LIGHT or DARK")
}
val messageViewTheme: Theme
get() = resolveTheme(K9.k9MessageViewThemeSetting)
val messageComposeTheme: Theme
get() = resolveTheme(K9.k9ComposerThemeSetting)
@get:StyleRes
val appThemeResourceId: Int
get() = getThemeResourceId(appTheme)
@get:StyleRes
val appActionBarThemeResourceId: Int
get() = when (appTheme) {
Theme.LIGHT -> R.style.Theme_K9_Light_ActionBar
Theme.DARK -> R.style.Theme_K9_Dark_ActionBar
}
@get:StyleRes
val messageViewThemeResourceId: Int
get() = getThemeResourceId(messageViewTheme)
@get:StyleRes
val messageComposeThemeResourceId: Int
get() = getThemeResourceId(messageComposeTheme)
@get:StyleRes
val dialogThemeResourceId: Int
get() = when (appTheme) {
Theme.LIGHT -> R.style.Theme_K9_Dialog_Light
Theme.DARK -> R.style.Theme_K9_Dialog_Dark
}
@get:StyleRes
val translucentDialogThemeResourceId: Int
get() = when (appTheme) {
Theme.LIGHT -> R.style.Theme_K9_Dialog_Translucent_Light
Theme.DARK -> R.style.Theme_K9_Dialog_Translucent_Dark
}
fun toggleMessageViewTheme() {
if (messageViewTheme === Theme.DARK) {
K9.k9MessageViewThemeSetting = K9.Theme.LIGHT
} else {
K9.k9MessageViewThemeSetting = K9.Theme.DARK
}
K9.saveSettingsAsync()
}
private fun getThemeResourceId(theme: Theme): Int = when (theme) {
Theme.LIGHT -> R.style.Theme_K9_Light
Theme.DARK -> R.style.Theme_K9_Dark
}
private fun resolveTheme(theme: K9.Theme): Theme = when (theme) {
K9.Theme.LIGHT -> Theme.LIGHT
K9.Theme.DARK -> Theme.DARK
K9.Theme.USE_GLOBAL -> appTheme
}
}
enum class Theme {
LIGHT,
DARK
}

View file

@ -30,10 +30,10 @@ import android.view.inputmethod.InputMethodManager;
import android.widget.Toast;
import com.fsck.k9.Account;
import com.fsck.k9.DI;
import com.fsck.k9.K9;
import com.fsck.k9.Preferences;
import com.fsck.k9.activity.ChooseFolder;
import com.fsck.k9.activity.K9ActivityCommon;
import com.fsck.k9.activity.MessageLoaderHelper;
import com.fsck.k9.activity.MessageLoaderHelper.MessageLoaderCallbacks;
import com.fsck.k9.controller.MessageReference;
@ -46,6 +46,7 @@ import com.fsck.k9.mailstore.AttachmentViewInfo;
import com.fsck.k9.mailstore.LocalMessage;
import com.fsck.k9.mailstore.MessageViewInfo;
import com.fsck.k9.ui.R;
import com.fsck.k9.ui.ThemeManager;
import com.fsck.k9.ui.messageview.CryptoInfoDialog.OnClickShowCryptoKeyListener;
import com.fsck.k9.ui.messageview.MessageCryptoPresenter.MessageCryptoMvpView;
import com.fsck.k9.ui.settings.account.AccountSettingsActivity;
@ -77,6 +78,8 @@ public class MessageViewFragment extends Fragment implements ConfirmationDialogF
return fragment;
}
private final ThemeManager themeManager = DI.get(ThemeManager.class);
private MessageTopView mMessageView;
private Account mAccount;
@ -159,10 +162,9 @@ public class MessageViewFragment extends Fragment implements ConfirmationDialogF
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
Context context = new ContextThemeWrapper(inflater.getContext(),
K9ActivityCommon.getK9ThemeResourceId(K9.getK9MessageViewTheme()));
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
int messageViewThemeResourceId = themeManager.getMessageViewThemeResourceId();
Context context = new ContextThemeWrapper(inflater.getContext(), messageViewThemeResourceId);
LayoutInflater layoutInflater = LayoutInflater.from(context);
View view = layoutInflater.inflate(R.layout.message, container, false);