mirror of https://github.com/tasks/tasks
Add theme manager, widget themes
parent
81d9b3fb3b
commit
142a9b3229
@ -0,0 +1,15 @@
|
|||||||
|
package org.tasks.widget;
|
||||||
|
|
||||||
|
import org.tasks.injection.ActivityComponent;
|
||||||
|
|
||||||
|
public class WidgetConfigActivity extends BaseWidgetConfigActivity {
|
||||||
|
@Override
|
||||||
|
public void inject(ActivityComponent component) {
|
||||||
|
component.inject(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void initiateThemePurchase() {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,23 @@
|
|||||||
|
package org.tasks.widget;
|
||||||
|
|
||||||
|
import org.tasks.R;
|
||||||
|
import org.tasks.injection.ActivityComponent;
|
||||||
|
import org.tasks.preferences.Preferences;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
|
||||||
|
public class WidgetConfigActivity extends BaseWidgetConfigActivity {
|
||||||
|
|
||||||
|
@Inject Preferences preferences;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void inject(ActivityComponent component) {
|
||||||
|
component.inject(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void initiateThemePurchase() {
|
||||||
|
preferences.setBoolean(R.string.p_purchased_themes, true);
|
||||||
|
showThemeSelection();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,52 @@
|
|||||||
|
package org.tasks.widget;
|
||||||
|
|
||||||
|
import android.content.Intent;
|
||||||
|
|
||||||
|
import org.tasks.R;
|
||||||
|
import org.tasks.billing.PurchaseHelper;
|
||||||
|
import org.tasks.billing.PurchaseHelperCallback;
|
||||||
|
import org.tasks.injection.ActivityComponent;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
|
||||||
|
import timber.log.Timber;
|
||||||
|
|
||||||
|
public class WidgetConfigActivity extends BaseWidgetConfigActivity implements PurchaseHelperCallback {
|
||||||
|
|
||||||
|
private static final int REQUEST_PURCHASE = 10109;
|
||||||
|
|
||||||
|
@Inject PurchaseHelper purchaseHelper;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void initiateThemePurchase() {
|
||||||
|
purchaseHelper.purchase(dialogBuilder, this, getString(R.string.sku_themes), getString(R.string.p_purchased_themes), REQUEST_PURCHASE, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void purchaseCompleted(boolean success, final String sku) {
|
||||||
|
runOnUiThread(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
if (getString(R.string.sku_themes).equals(sku)) {
|
||||||
|
showThemeSelection();
|
||||||
|
} else {
|
||||||
|
Timber.d("Unhandled sku: %s", sku);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void inject(ActivityComponent component) {
|
||||||
|
component.inject(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||||
|
if (requestCode == REQUEST_PURCHASE) {
|
||||||
|
purchaseHelper.handleActivityResult(this, requestCode, resultCode, data);
|
||||||
|
} else {
|
||||||
|
super.onActivityResult(requestCode, resultCode, data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,19 @@
|
|||||||
|
package org.tasks.injection;
|
||||||
|
|
||||||
|
import android.os.Bundle;
|
||||||
|
|
||||||
|
import org.tasks.preferences.ThemeApplicator;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
|
||||||
|
public abstract class ThemedInjectingAppCompatActivity extends InjectingAppCompatActivity {
|
||||||
|
|
||||||
|
@Inject ThemeApplicator themeApplicator;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
|
||||||
|
themeApplicator.applyThemeAndStatusBarColor();
|
||||||
|
}
|
||||||
|
}
|
@ -1,137 +0,0 @@
|
|||||||
package org.tasks.preferences;
|
|
||||||
|
|
||||||
import android.app.Activity;
|
|
||||||
import android.content.Context;
|
|
||||||
import android.graphics.PixelFormat;
|
|
||||||
import android.util.TypedValue;
|
|
||||||
import android.view.ContextThemeWrapper;
|
|
||||||
|
|
||||||
import org.tasks.R;
|
|
||||||
|
|
||||||
import javax.inject.Inject;
|
|
||||||
import javax.inject.Singleton;
|
|
||||||
|
|
||||||
import static com.todoroo.andlib.utility.AndroidUtilities.atLeastLollipop;
|
|
||||||
|
|
||||||
@Singleton
|
|
||||||
public class ActivityPreferences extends Preferences {
|
|
||||||
|
|
||||||
private final Activity activity;
|
|
||||||
|
|
||||||
@Inject
|
|
||||||
public ActivityPreferences(Activity activity, PermissionChecker permissionChecker) {
|
|
||||||
super(activity, permissionChecker);
|
|
||||||
this.activity = activity;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void applyThemeAndStatusBarColor() {
|
|
||||||
applyTheme();
|
|
||||||
applyStatusBarColor();
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getThemeName() {
|
|
||||||
int themeIndex = getInt(R.string.p_theme, 0);
|
|
||||||
String[] themeNames = activity.getResources().getStringArray(R.array.themes);
|
|
||||||
return themeNames[themeIndex];
|
|
||||||
}
|
|
||||||
|
|
||||||
public void applyTheme() {
|
|
||||||
applyTheme(getTheme());
|
|
||||||
}
|
|
||||||
|
|
||||||
public void applyDialogTheme() {
|
|
||||||
applyTheme(getDialogTheme());
|
|
||||||
}
|
|
||||||
|
|
||||||
private void applyTheme(int theme) {
|
|
||||||
activity.setTheme(theme);
|
|
||||||
activity.getWindow().setFormat(PixelFormat.RGBA_8888);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void applyStatusBarColor() {
|
|
||||||
if (atLeastLollipop()) {
|
|
||||||
activity.getWindow().setStatusBarColor(getPrimaryDarkColor());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getTheme() {
|
|
||||||
return getTheme(getInt(R.string.p_theme, -1));
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getDialogTheme() {
|
|
||||||
Context contextThemeWrapper = new ContextThemeWrapper(activity, getTheme());
|
|
||||||
TypedValue typedValue = new TypedValue();
|
|
||||||
contextThemeWrapper.getTheme().resolveAttribute(R.attr.alertDialogTheme, typedValue, true);
|
|
||||||
return typedValue.data;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getDateTimePickerAccent() {
|
|
||||||
Context contextThemeWrapper = new ContextThemeWrapper(activity, getTheme());
|
|
||||||
TypedValue typedValue = new TypedValue();
|
|
||||||
contextThemeWrapper.getTheme().resolveAttribute(R.attr.asDateTimePickerAccent, typedValue, true);
|
|
||||||
return typedValue.data;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getPrimaryDarkColor() {
|
|
||||||
return getColorAttribute(R.attr.colorPrimaryDark);
|
|
||||||
}
|
|
||||||
|
|
||||||
private int getColorAttribute(int attribute) {
|
|
||||||
TypedValue typedValue = new TypedValue();
|
|
||||||
activity.getTheme().resolveAttribute(attribute, typedValue, true);
|
|
||||||
return typedValue.data;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getPrimaryColor(int themeIndex) {
|
|
||||||
Context contextThemeWrapper = new ContextThemeWrapper(activity, getTheme(themeIndex));
|
|
||||||
TypedValue typedValue = new TypedValue();
|
|
||||||
contextThemeWrapper.getTheme().resolveAttribute(R.attr.colorPrimary, typedValue, true);
|
|
||||||
return typedValue.data;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getTheme(int index) {
|
|
||||||
switch (index) {
|
|
||||||
case 1:
|
|
||||||
return R.style.Black;
|
|
||||||
case 2:
|
|
||||||
return R.style.Red;
|
|
||||||
case 3:
|
|
||||||
return R.style.Pink;
|
|
||||||
case 4:
|
|
||||||
return R.style.Purple;
|
|
||||||
case 5:
|
|
||||||
return R.style.DeepPurple;
|
|
||||||
case 6:
|
|
||||||
return R.style.Indigo;
|
|
||||||
case 7:
|
|
||||||
return R.style.Blue;
|
|
||||||
case 8:
|
|
||||||
return R.style.LightBlue;
|
|
||||||
case 9:
|
|
||||||
return R.style.Cyan;
|
|
||||||
case 10:
|
|
||||||
return R.style.Teal;
|
|
||||||
case 11:
|
|
||||||
return R.style.Green;
|
|
||||||
case 12:
|
|
||||||
return R.style.LightGreen;
|
|
||||||
case 13:
|
|
||||||
return R.style.Lime;
|
|
||||||
case 14:
|
|
||||||
return R.style.Yellow;
|
|
||||||
case 15:
|
|
||||||
return R.style.Amber;
|
|
||||||
case 16:
|
|
||||||
return R.style.Orange;
|
|
||||||
case 17:
|
|
||||||
return R.style.DeepOrange;
|
|
||||||
case 18:
|
|
||||||
return R.style.Brown;
|
|
||||||
case 19:
|
|
||||||
return R.style.Grey;
|
|
||||||
case 0:
|
|
||||||
default:
|
|
||||||
return R.style.BlueGrey;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -0,0 +1,72 @@
|
|||||||
|
package org.tasks.preferences;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.util.TypedValue;
|
||||||
|
import android.view.ContextThemeWrapper;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
|
||||||
|
import org.tasks.R;
|
||||||
|
|
||||||
|
public class Theme {
|
||||||
|
private final Context context;
|
||||||
|
private final int themeRes;
|
||||||
|
private final int themeIndex;
|
||||||
|
private final String name;
|
||||||
|
|
||||||
|
public Theme(Context context, int themeIndex, int themeRes, String name) {
|
||||||
|
this.themeIndex = themeIndex;
|
||||||
|
this.name = name;
|
||||||
|
this.context = new ContextThemeWrapper(context, themeRes);
|
||||||
|
this.themeRes = themeRes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public LayoutInflater getThemedLayoutInflater() {
|
||||||
|
return (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isDark() {
|
||||||
|
return themeIndex == 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getThemeIndex() {
|
||||||
|
return themeIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getPrimaryColor() {
|
||||||
|
return resolveAttribute(R.attr.colorPrimary);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getContentBackground() {
|
||||||
|
return resolveAttribute(R.attr.asContentBackground);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getPrimaryDarkColor() {
|
||||||
|
return resolveAttribute(R.attr.colorPrimaryDark);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getTextColor() {
|
||||||
|
return resolveAttribute(R.attr.asTextColor);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getDateTimePickerAccent() {
|
||||||
|
return resolveAttribute(R.attr.asDateTimePickerAccent);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getAppThemeResId() {
|
||||||
|
return themeRes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getDialogThemeResId() {
|
||||||
|
return resolveAttribute(R.attr.alertDialogTheme);
|
||||||
|
}
|
||||||
|
|
||||||
|
private int resolveAttribute(int attribute) {
|
||||||
|
TypedValue typedValue = new TypedValue();
|
||||||
|
context.getTheme().resolveAttribute(attribute, typedValue, true);
|
||||||
|
return typedValue.data;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,46 @@
|
|||||||
|
package org.tasks.preferences;
|
||||||
|
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.graphics.PixelFormat;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
|
||||||
|
import static com.todoroo.andlib.utility.AndroidUtilities.atLeastLollipop;
|
||||||
|
|
||||||
|
public class ThemeApplicator {
|
||||||
|
private final Activity activity;
|
||||||
|
private final ThemeManager themeManager;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
public ThemeApplicator(Activity activity, ThemeManager themeManager) {
|
||||||
|
this.activity = activity;
|
||||||
|
this.themeManager = themeManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void applyThemeAndStatusBarColor() {
|
||||||
|
applyTheme();
|
||||||
|
applyStatusBarColor();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void applyTheme() {
|
||||||
|
Theme appTheme = themeManager.getAppTheme();
|
||||||
|
applyTheme(appTheme.getAppThemeResId());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void applyDialogTheme() {
|
||||||
|
Theme appTheme = themeManager.getAppTheme();
|
||||||
|
applyTheme(appTheme.getDialogThemeResId());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void applyTheme(int theme) {
|
||||||
|
activity.setTheme(theme);
|
||||||
|
activity.getWindow().setFormat(PixelFormat.RGBA_8888);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void applyStatusBarColor() {
|
||||||
|
if (atLeastLollipop()) {
|
||||||
|
Theme appTheme = themeManager.getAppTheme();
|
||||||
|
activity.getWindow().setStatusBarColor(appTheme.getPrimaryDarkColor());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,88 @@
|
|||||||
|
package org.tasks.preferences;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
|
||||||
|
import org.tasks.R;
|
||||||
|
import org.tasks.injection.ForApplication;
|
||||||
|
import org.tasks.widget.WidgetConfigActivity;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
|
@Singleton
|
||||||
|
public class ThemeManager {
|
||||||
|
|
||||||
|
private final Context context;
|
||||||
|
private final Preferences preferences;
|
||||||
|
private final String[] themeNames;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
public ThemeManager(@ForApplication Context context, Preferences preferences) {
|
||||||
|
this.context = context;
|
||||||
|
this.preferences = preferences;
|
||||||
|
themeNames = context.getResources().getStringArray(R.array.themes);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Theme getAppTheme() {
|
||||||
|
return getTheme(preferences.getInt(R.string.p_theme, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
public Theme getTheme(int themeIndex) {
|
||||||
|
return new Theme(context, themeIndex, getStyle(themeIndex), themeNames[themeIndex]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Theme getWidgetTheme(int widgetId) {
|
||||||
|
int defaultTheme = preferences.useDarkWidgetTheme(widgetId) ? 1 : 0;
|
||||||
|
return getTheme(preferences.getInt(WidgetConfigActivity.PREF_THEME + widgetId, defaultTheme));
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getDialogThemeResId() {
|
||||||
|
return getAppTheme().getDialogThemeResId();
|
||||||
|
}
|
||||||
|
|
||||||
|
private int getStyle(int index) {
|
||||||
|
switch (index) {
|
||||||
|
case 1:
|
||||||
|
return R.style.Black;
|
||||||
|
case 2:
|
||||||
|
return R.style.Red;
|
||||||
|
case 3:
|
||||||
|
return R.style.Pink;
|
||||||
|
case 4:
|
||||||
|
return R.style.Purple;
|
||||||
|
case 5:
|
||||||
|
return R.style.DeepPurple;
|
||||||
|
case 6:
|
||||||
|
return R.style.Indigo;
|
||||||
|
case 7:
|
||||||
|
return R.style.Blue;
|
||||||
|
case 8:
|
||||||
|
return R.style.LightBlue;
|
||||||
|
case 9:
|
||||||
|
return R.style.Cyan;
|
||||||
|
case 10:
|
||||||
|
return R.style.Teal;
|
||||||
|
case 11:
|
||||||
|
return R.style.Green;
|
||||||
|
case 12:
|
||||||
|
return R.style.LightGreen;
|
||||||
|
case 13:
|
||||||
|
return R.style.Lime;
|
||||||
|
case 14:
|
||||||
|
return R.style.Yellow;
|
||||||
|
case 15:
|
||||||
|
return R.style.Amber;
|
||||||
|
case 16:
|
||||||
|
return R.style.Orange;
|
||||||
|
case 17:
|
||||||
|
return R.style.DeepOrange;
|
||||||
|
case 18:
|
||||||
|
return R.style.Brown;
|
||||||
|
case 19:
|
||||||
|
return R.style.Grey;
|
||||||
|
case 0:
|
||||||
|
default:
|
||||||
|
return R.style.BlueGrey;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue