package com.moez.QKSMS.ui;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ArgbEvaluator;
import android.animation.ValueAnimator;
import android.annotation.TargetApi;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.graphics.Color;
import android.graphics.PorterDuff;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.preference.PreferenceManager;
import android.support.annotation.ColorInt;
import android.support.annotation.DrawableRes;
import android.support.v4.content.ContextCompat;
import android.support.v4.view.ViewPager;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.animation.DecelerateInterpolator;
import android.view.inputmethod.EditorInfo;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.SeekBar;
import butterknife.Bind;
import butterknife.ButterKnife;
import com.moez.QKSMS.R;
import com.moez.QKSMS.common.AnalyticsManager;
import com.moez.QKSMS.common.CIELChEvaluator;
import com.moez.QKSMS.common.ConversationPrefsHelper;
import com.moez.QKSMS.common.LiveViewManager;
import com.moez.QKSMS.common.utils.ColorUtils;
import com.moez.QKSMS.common.utils.KeyboardUtils;
import com.moez.QKSMS.common.utils.Units;
import com.moez.QKSMS.enums.QKPreference;
import com.moez.QKSMS.receiver.IconColorReceiver;
import com.moez.QKSMS.theme.IconAdapter;
import com.moez.QKSMS.ui.base.QKActivity;
import com.moez.QKSMS.ui.dialog.ColorPickerPagerAdapter;
import com.moez.QKSMS.ui.dialog.QKDialog;
import com.moez.QKSMS.ui.settings.SettingsFragment;
import com.moez.QKSMS.ui.view.QKEditText;
import com.moez.QKSMS.ui.view.QKTextView;
import com.moez.QKSMS.ui.view.colorpicker.ColorPickerPalette;
import com.moez.QKSMS.ui.widget.WidgetProvider;
public class ThemeManager {
private final static String TAG = "ThemeManager";
public static final int DEFAULT_COLOR = 0xff009688;
public static final int TRANSITION_LENGTH = 500;
public enum Theme {
LIGHT,
DARK,
BLACK;
public static final String PREF_OFFWHITE = "light";
public static final String PREF_GREY = "grey";
public static final String PREF_BLACK = "black";
public static Theme fromString(String color) {
switch (color) {
case PREF_OFFWHITE:
return LIGHT;
case PREF_GREY:
return DARK;
case PREF_BLACK:
return BLACK;
default:
Log.w(TAG, "Tried to set theme with invalid string: " + color);
return LIGHT;
}
}
}
// Colors copied from http://www.google.com/design/spec/style/color.html#color-ui-color-palette
private static final int[][] COLORS = {{
// Red
0xfffde0dc, 0xfff9bdbb, 0xfff69988, 0xfff36c60,
0xffe84e40, 0xffe51c23, 0xffdd191d, 0xffd01716,
0xffc41411, 0xffb0120a
}, { // Pink
0xfffce4ec, 0xfff8bbd0, 0xfff48fb1, 0xfff06292,
0xffec407a, 0xffe91e63, 0xffd81b60, 0xffc2185b,
0xffad1457, 0xff880e4f
}, { // Purple
0xfff3e5f5, 0xffe1bee7, 0xffce93d8, 0xffba68c8,
0xffab47bc, 0xff9c27b0, 0xff8e24aa, 0xff7b1fa2,
0xff6a1b9a, 0xff4a148c
}, { // Deep Purple
0xffede7f6, 0xffd1c4e9, 0xffb39ddb, 0xff9575cd,
0xff7e57c2, 0xff673ab7, 0xff5e35b1, 0xff512da8,
0xff4527a0, 0xff311b92
}, { // Indigo
0xffe8eaf6, 0xffc5cae9, 0xff9fa8da, 0xff7986cb,
0xff5c6bc0, 0xff3f51b5, 0xff3949ab, 0xff303f9f,
0xff283593, 0xff1a237e
}, { // Blue
0xffe7e9fd, 0xffd0d9ff, 0xffafbfff, 0xff91a7ff,
0xff738ffe, 0xff5677fc, 0xff4e6cef, 0xff455ede,
0xff3b50ce, 0xff2a36b1
}, { // Light Blue
0xffe1f5fe, 0xffb3e5fc, 0xff81d4fa, 0xff4fc3f7,
0xff29b6f6, 0xff03a9f4, 0xff039be5, 0xff0288d1,
0xff0277bd, 0xff01579b
}, { // Cyan
0xffe0f7fa, 0xffb2ebf2, 0xff80deea, 0xff4dd0e1,
0xff26c6da, 0xff00bcd4, 0xff00acc1, 0xff0097a7,
0xff00838f, 0xff006064
}, { // Teal
0xffe0f2f1, 0xffb2dfdb, 0xff80cbc4, 0xff4db6ac,
0xff26a69a, 0xff009688, 0xff00897b, 0xff00796b,
0xff00695c, 0xff004d40
}, { // Green
0xffd0f8ce, 0xffa3e9a4, 0xff72d572, 0xff42bd41,
0xff2baf2b, 0xff259b24, 0xff0a8f08, 0xff0a7e07,
0xff056f00, 0xff0d5302
}, { // Light Green
0xfff1f8e9, 0xffdcedc8, 0xffc5e1a5, 0xffaed581,
0xff9ccc65, 0xff8bc34a, 0xff7cb342, 0xff689f38,
0xff558b2f, 0xff33691e
}, { // Lime
0xfff9fbe7, 0xfff0f4c3, 0xffe6ee9c, 0xffdce775,
0xffd4e157, 0xffcddc39, 0xffc0ca33, 0xffafb42b,
0xff9e9d24, 0xff827717
}, { // Yellow
0xfffffde7, 0xfffff9c4, 0xfffff59d, 0xfffff176,
0xffffee58, 0xffffeb3b, 0xfffdd835, 0xfffbc02d,
0xfff9a825, 0xfff57f17
}, { // Amber
0xfffff8e1, 0xffffecb3, 0xffffe082, 0xffffd54f,
0xffffca28, 0xffffc107, 0xffffb300, 0xffffa000,
0xffff8f00, 0xffff6f00
}, { // Orange
0xfffff3e0, 0xffffe0b2, 0xffffcc80, 0xffffb74d,
0xffffa726, 0xffff9800, 0xfffb8c00, 0xfff57c00,
0xffef6c00, 0xffe65100
}, { // Deep Orange
0xfffbe9e7, 0xffffccbc, 0xffffab91, 0xffff8a65,
0xffff7043, 0xffff5722, 0xfff4511e, 0xffe64a19,
0xffd84315, 0xffbf360c
}, { // Brown
0xffefebe9, 0xffd7ccc8, 0xffbcaaa4, 0xffa1887f,
0xff8d6e63, 0xff795548, 0xff6d4c41, 0xff5d4037,
0xff4e342e, 0xff3e2723
}, { // Grey
0xfffafafa, 0xfff5f5f5, 0xffeeeeee, 0xffe0e0e0,
0xffbdbdbd, 0xff9e9e9e, 0xff757575, 0xff616161,
0xff424242, 0xff212121, 0xff000000, 0xffffffff
}, { // Blue Grey
0xffeceff1, 0xffeceff1, 0xffb0bec5, 0xff90a4ae,
0xff78909c, 0xff607d8b, 0xff546e7a, 0xff455a64,
0xff37474f, 0xff263238
}};
/**
* These are the colors that go in the initial palette.
*/
public static final int[] PALETTE = {
COLORS[0][5], // Red
COLORS[1][5], // Pink
COLORS[2][5], // Purple
COLORS[3][5], // Deep purple
COLORS[4][5], // Indigo
COLORS[5][5], // Blue
COLORS[6][5], // Light Blue
COLORS[7][5], // Cyan
COLORS[8][5], // Teal
COLORS[9][5], // Green
COLORS[10][5], // Light Green
COLORS[11][5], // Lime
COLORS[12][5], // Yellow
COLORS[13][5], // Amber
COLORS[14][5], // Orange
COLORS[15][5], // Deep Orange
COLORS[16][5], // Brown
COLORS[17][5], // Grey
COLORS[18][5] // Blue Grey
};
/**
* This configures whether the text is black (0) or white (1) for each color above.
*/
private static final int[][] TEXT_MODE = {{
// Red
0, 0, 1, 1, 1, 1, 1, 1, 1, 1
}, { // Pink
0, 0, 1, 1, 1, 1, 1, 1, 1, 1
}, { // Purple
0, 0, 1, 1, 1, 1, 1, 1, 1, 1
}, { // Deep Purple
0, 0, 1, 1, 1, 1, 1, 1, 1, 1
}, { // Indigo
0, 0, 1, 1, 1, 1, 1, 1, 1, 1
}, { // Blue
0, 0, 0, 1, 1, 1, 1, 1, 1, 1
}, { // Light Blue
0, 0, 0, 1, 1, 1, 1, 1, 1, 1
}, { // Cyan
0, 0, 0, 1, 1, 1, 1, 1, 1, 1
}, { // Teal
0, 0, 0, 1, 1, 1, 1, 1, 1, 1
}, { // Green
0, 0, 1, 1, 1, 1, 1, 1, 1, 1
}, { // Light Green
0, 0, 0, 0, 1, 1, 1, 1, 1, 1
}, { // Lime
0, 0, 0, 0, 0, 0, 1, 1, 1, 1
}, { // Yellow
0, 0, 0, 0, 0, 0, 0, 1, 1, 1
}, { // Amber
0, 0, 0, 0, 0, 1, 1, 1, 1, 1
}, { // Orange
0, 0, 0, 1, 1, 1, 1, 1, 1, 1
}, { // Deep Orange
0, 0, 1, 1, 1, 1, 1, 1, 1, 1
}, { // Brown
0, 0, 1, 1, 1, 1, 1, 1, 1, 1
}, { // Grey
0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0
}, { // Blue Grey
0, 0, 0, 1, 1, 1, 1, 1, 1, 1
}};
private static int mColor;
private static int mActiveColor;
private static int mBackgroundColor;
private static Theme mTheme;
private static int mTextOnColorPrimary;
private static int mTextOnColorSecondary;
private static int mTextOnBackgroundPrimary;
private static int mtextOnBackgroundSecondary;
private static int mSentBubbleRes;
private static int mSentBubbleAltRes;
private static boolean mSentBubbleColored;
private static int mReceivedBubbleRes;
private static int mReceivedBubbleAltRes;
private static boolean mReceivedBubbleColored;
private static int mRippleBackgroundRes;
private static Resources mResources;
private static SharedPreferences mPrefs;
private static Context mContext;
public static void init(Context context) {
mContext = context;
mPrefs = PreferenceManager.getDefaultSharedPreferences(context);
mResources = context.getResources();
mColor = Integer.parseInt(mPrefs.getString(SettingsFragment.THEME, "" + DEFAULT_COLOR));
mActiveColor = mColor;
initializeTheme(Theme.fromString(mPrefs.getString(SettingsFragment.BACKGROUND, "offwhite")));
}
public static void setTheme(Theme theme) {
final int startColor = mBackgroundColor;
initializeTheme(theme);
final int endColor = mBackgroundColor;
if (startColor != endColor) {
ValueAnimator backgroundAnimation = ValueAnimator.ofObject(new ArgbEvaluator(), startColor, endColor);
backgroundAnimation.setDuration(TRANSITION_LENGTH);
backgroundAnimation.addUpdateListener(animation -> {
mBackgroundColor = (Integer) animation.getAnimatedValue();
LiveViewManager.refreshViews(QKPreference.BACKGROUND);
});
backgroundAnimation.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
mBackgroundColor = endColor;
LiveViewManager.refreshViews(QKPreference.BACKGROUND);
WidgetProvider.notifyThemeChanged(mContext);
}
});
backgroundAnimation.start();
} else {
LiveViewManager.refreshViews(QKPreference.BACKGROUND);
WidgetProvider.notifyThemeChanged(mContext);
}
}
public static void initializeTheme(Theme theme) {
mTheme = theme;
switch (theme) {
case LIGHT:
mBackgroundColor = mResources.getColor(R.color.grey_light_mega_ultra);
mTextOnBackgroundPrimary = mResources.getColor(R.color.theme_light_text_primary);
mtextOnBackgroundSecondary = mResources.getColor(R.color.theme_light_text_secondary);
mRippleBackgroundRes = R.drawable.ripple;
break;
case DARK:
mBackgroundColor = mResources.getColor(R.color.grey_material);
mTextOnBackgroundPrimary = mResources.getColor(R.color.theme_dark_text_primary);
mtextOnBackgroundSecondary = mResources.getColor(R.color.theme_dark_text_secondary);
mRippleBackgroundRes = R.drawable.ripple_light;
break;
case BLACK:
mBackgroundColor = mResources.getColor(R.color.black);
mTextOnBackgroundPrimary = mResources.getColor(R.color.theme_dark_text_primary);
mtextOnBackgroundSecondary = mResources.getColor(R.color.theme_dark_text_secondary);
mRippleBackgroundRes = R.drawable.ripple_light;
break;
}
mTextOnColorPrimary = mResources.getColor(isColorDarkEnough(mColor) ?
R.color.theme_dark_text_primary : R.color.theme_light_text_primary);
mTextOnColorSecondary = mResources.getColor(isColorDarkEnough(mColor) ?
R.color.theme_dark_text_secondary : R.color.theme_light_text_secondary);
setSentBubbleColored(mPrefs.getBoolean(SettingsFragment.COLOR_SENT, true));
setReceivedBubbleColored(mPrefs.getBoolean(SettingsFragment.COLOR_RECEIVED, false));
setBubbleStyleNew(mPrefs.getBoolean(SettingsFragment.BUBBLES_NEW, true));
LiveViewManager.refreshViews(QKPreference.BACKGROUND);
}
public static void setIcon(final QKActivity context) {
String[] colors = {
"Default", "Dark", "Red", "Pink", "Purple", "DeepPurple",
"Indigo", "Blue", "LightBlue", "Cyan", "Teal", "Green",
"LightGreen", "Lime", "Yellow", "Amber", "Orange", "DeepOrange",
"Brown", "Grey", "BlueGrey"
};
RecyclerView recyclerView = new RecyclerView(context);
recyclerView.setLayoutParams(new LinearLayout.LayoutParams(-1, Units.dpToPx(context, 200)));
recyclerView.setLayoutManager(new GridLayoutManager(context, 4));
recyclerView.setAdapter(new IconAdapter(context, (parent, view, position, id) -> {
PackageManager packageManager = context.getPackageManager();
// Disable all of the color aliases, except for the alias with the current
// color.
String enabledComponent = null;
for (int i = 0; i < colors.length; i++) {
String componentClassName = String.format("com.moez.QKSMS.ui.MainActivity-%s", colors[i]);
// Save the enabled component so we can kill the app with this one when
// it's all done.
if (i == position) {
enabledComponent = componentClassName;
} else {
packageManager.setComponentEnabledSetting(
new ComponentName(context, componentClassName),
PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
// Don't kill the app while we're in the loop! This will
// prevent the other component enabled settings from
// changing, i.e. they will all be disabled and the app
// won't show up to the user.
PackageManager.DONT_KILL_APP
);
}
}
// Broadcast an intent to a receiver that will:
// 1) enable the last component; and
// 2) relaunch QKSMS with the new component name.
Intent intent = new Intent(IconColorReceiver.ACTION_ICON_COLOR_CHANGED);
intent.putExtra(IconColorReceiver.EXTRA_COMPONENT_NAME, enabledComponent);
context.sendBroadcast(intent);
}));
new QKDialog()
.setContext(context)
.setTitle(R.string.update_icon_title)
.setMessage(R.string.update_icon_message)
.setCustomView(recyclerView)
.setNegativeButton(R.string.cancel, null)
.show();
}
@ColorInt
public static int getBackgroundColor() {
return mBackgroundColor;
}
@ColorInt
public static int getTextOnColorPrimary() {
return mTextOnColorPrimary;
}
@ColorInt
public static int getTextOnColorSecondary() {
return mTextOnColorSecondary;
}
@ColorInt
public static int getTextOnBackgroundPrimary() {
return mTextOnBackgroundPrimary;
}
@ColorInt
public static int getTextOnBackgroundSecondary() {
return mtextOnBackgroundSecondary;
}
@DrawableRes
public static int getSentBubbleRes() {
return mSentBubbleRes;
}
@DrawableRes
public static int getSentBubbleAltRes() {
return mSentBubbleAltRes;
}
@ColorInt
public static int getSentBubbleColor() {
return mSentBubbleColored ? mActiveColor : getNeutralBubbleColor();
}
@DrawableRes
public static int getReceivedBubbleRes() {
return mReceivedBubbleRes;
}
@DrawableRes
public static int getReceivedBubbleAltRes() {
return mReceivedBubbleAltRes;
}
@ColorInt
public static int getReceivedBubbleColor() {
return mReceivedBubbleColored ? mActiveColor : getNeutralBubbleColor();
}
public static void setBubbleStyleNew(boolean styleNew) {
mSentBubbleRes = styleNew ? R.drawable.message_sent_2 : R.drawable.message_sent;
mSentBubbleAltRes = styleNew ? R.drawable.message_sent_alt_2 : R.drawable.message_sent_alt;
mReceivedBubbleRes = styleNew ? R.drawable.message_received_2 : R.drawable.message_received;
mReceivedBubbleAltRes = styleNew ? R.drawable.message_received_alt_2 : R.drawable.message_received_alt;
}
public static void setSentBubbleColored(boolean colored) {
mSentBubbleColored = colored;
}
public static void setReceivedBubbleColored(boolean colored) {
mReceivedBubbleColored = colored;
}
@ColorInt
public static int getNeutralBubbleColor() {
if (mTheme == null) {
return 0xeeeeee;
}
switch (mTheme) {
case DARK:
return mResources.getColor(R.color.grey_dark);
case BLACK:
return mResources.getColor(R.color.grey_material);
default:
return mResources.getColor(R.color.white_pure);
}
}
public static Drawable getRippleBackground() {
return mResources.getDrawable(mRippleBackgroundRes);
}
@ColorInt
public static int getColor() {
return mActiveColor;
}
@ColorInt
public static int getThemeColor() {
return mColor;
}
public static Theme getTheme() {
return mTheme;
}
public static boolean isNightMode() {
return mTheme == Theme.DARK || mTheme == Theme.BLACK;
}
public static void showColorPickerDialog(final QKActivity context) {
showColorPicker(context, v -> setColor(context, getColor()));
}
public static void showColorPickerDialogForConversation(final QKActivity context, ConversationPrefsHelper prefs) {
showColorPicker(context, v -> {
prefs.putString(QKPreference.THEME.getKey(), "" + getColor());
LiveViewManager.refreshViews(QKPreference.CONVERSATION_THEME);
});
}
private static void showColorPicker(QKActivity context, View.OnClickListener saveListener) {
final QKDialog dialog = new QKDialog();
View view = LayoutInflater.from(mContext).inflate(R.layout.dialog_color_picker, null, false);
ColorPickerViewHolder holder = new ColorPickerViewHolder(view);
holder.mTab1.setBackgroundDrawable(getRippleBackground());
holder.mTab2.setBackgroundDrawable(getRippleBackground());
holder.mTab1.setOnClickListener(v -> holder.mPager.setCurrentItem(0));
holder.mTab2.setOnClickListener(v -> holder.mPager.setCurrentItem(1));
ColorPickerPagerAdapter adapter = new ColorPickerPagerAdapter(context);
holder.mPager.setAdapter(adapter);
holder.mPager.setOffscreenPageLimit(1);
holder.mPager.addOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
@Override
public void onPageSelected(int position) {
super.onPageSelected(position);
holder.mTab1.setTextColor(position == 0 ? getColor() : getTextOnBackgroundPrimary());
holder.mTab2.setTextColor(position == 1 ? getColor() : getTextOnBackgroundPrimary());
}
});
int swatchColor = getSwatchColor(getColor());
holder.mPalette.init(19, 4, color -> {
holder.mPalette.init(getSwatch(color).length, 4, color2 -> {
setActiveColor(color2);
saveListener.onClick(null);
dialog.dismiss();
});
holder.mPalette.drawPalette(getSwatch(color), getColor());
});
holder.mPalette.drawPalette(PALETTE, swatchColor);
if (swatchColor == getColor()) { // If the current theme was set from the RGB picker, show that page instead
holder.mPager.setCurrentItem(1);
}
SeekBar.OnSeekBarChangeListener seekListener = new SeekBar.OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
int color = getColor();
color = Color.rgb(seekBar == holder.mRed ? progress : Color.red(color),
seekBar == holder.mGreen ? progress : Color.green(color),
seekBar == holder.mBlue ? progress : Color.blue(color));
if (seekBar == holder.mRed) holder.mRedValue.setText(String.valueOf(progress));
if (seekBar == holder.mGreen) holder.mGreenValue.setText(String.valueOf(progress));
if (seekBar == holder.mBlue) holder.mBlueValue.setText(String.valueOf(progress));
setActiveColor(color);
String colorString = Integer.toHexString(color);
holder.mHex.setTextChangedListenerEnabled(false);
holder.mHex.setText(colorString.substring(colorString.length() > 6 ? colorString.length() - 6 : 0));
holder.mHex.setTextChangedListenerEnabled(true);
holder.mError.setVisibility(View.INVISIBLE);
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
};
Drawable thumbRed = ContextCompat.getDrawable(mContext, R.drawable.seek_thumb);
Drawable thumbGreen = ContextCompat.getDrawable(mContext, R.drawable.seek_thumb);
Drawable thumbBlue = ContextCompat.getDrawable(mContext, R.drawable.seek_thumb);
LiveViewManager.registerView(QKPreference.THEME, holder.mPreview, key -> {
holder.mPreview.setBackgroundColor(getColor());
holder.mRed.getProgressDrawable().setColorFilter(getColor(), PorterDuff.Mode.MULTIPLY);
holder.mGreen.getProgressDrawable().setColorFilter(getColor(), PorterDuff.Mode.MULTIPLY);
holder.mBlue.getProgressDrawable().setColorFilter(getColor(), PorterDuff.Mode.MULTIPLY);
if (holder.mPager.getCurrentItem() == 0) {
holder.mTab1.setTextColor(getColor());
} else {
holder.mTab2.setTextColor(getColor());
}
});
LiveViewManager.registerView(QKPreference.BACKGROUND, holder.mHex, key -> {
holder.mHex.getBackground().setColorFilter(0x22888888, PorterDuff.Mode.MULTIPLY);
holder.mError.setColorFilter(getTextOnBackgroundSecondary(), PorterDuff.Mode.SRC_ATOP);
});
holder.mRed.setThumb(thumbRed);
holder.mRed.setOnSeekBarChangeListener(seekListener);
holder.mGreen.setThumb(thumbGreen);
holder.mGreen.setOnSeekBarChangeListener(seekListener);
holder.mBlue.setThumb(thumbBlue);
holder.mBlue.setOnSeekBarChangeListener(seekListener);
holder.mRed.setProgress(Color.red(getColor()));
holder.mGreen.setProgress(Color.green(getColor()));
holder.mBlue.setProgress(Color.blue(getColor()));
String colorString = Integer.toHexString(getColor());
holder.mHex.setText(colorString.substring(colorString.length() > 6 ? colorString.length() - 6 : 0));
holder.mHex.setOnEditorActionListener((v, actionId, event) -> {
if (actionId == EditorInfo.IME_ACTION_DONE) {
holder.mHex.clearFocus();
KeyboardUtils.hide(mContext, holder.mHex);
}
return false;
});
holder.mHex.setTextChangedListener(s -> {
if (s.length() == 6) {
int color = Color.parseColor("#" + s.toString());
holder.mError.setVisibility(View.INVISIBLE);
if (color != getColor()) {
holder.mRed.setProgress(Color.red(color));
holder.mGreen.setProgress(Color.green(color));
holder.mBlue.setProgress(Color.blue(color));
}
} else {
holder.mError.setVisibility(View.VISIBLE);
}
});
dialog.setContext(context)
.setCustomView(view)
.setNegativeButton(R.string.cancel, v -> setActiveColor(getThemeColor()))
.setPositiveButton(R.string.save, saveListener)
.show();
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public static void setStatusBarTintEnabled(QKActivity activity, boolean enabled) {
int colorFrom = enabled ? mResources.getColor(R.color.black) : mColor;
int colorTo = enabled ? mColor : mResources.getColor(R.color.black);
ValueAnimator colorAnimation = ValueAnimator.ofObject(new ArgbEvaluator(), colorFrom, colorTo);
colorAnimation.setDuration(TRANSITION_LENGTH);
colorAnimation.addUpdateListener(animation -> {
activity.getWindow().setStatusBarColor(ColorUtils.darken((Integer) animation.getAnimatedValue()));
});
colorAnimation.start();
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public static void setNavigationBarTintEnabled(QKActivity activity, boolean enabled) {
int colorFrom = enabled ? mResources.getColor(R.color.black) : mColor;
int colorTo = enabled ? mColor : mResources.getColor(R.color.black);
ValueAnimator colorAnimation = ValueAnimator.ofObject(new ArgbEvaluator(), colorFrom, colorTo);
colorAnimation.setDuration(TRANSITION_LENGTH);
colorAnimation.addUpdateListener(animation -> {
activity.getWindow().setNavigationBarColor(ColorUtils.darken((Integer) animation.getAnimatedValue()));
});
colorAnimation.start();
}
public static String getColorString(int color) {
return String.format("#%08x", color).toUpperCase();
}
public static void setColor(QKActivity activity, int color) {
AnalyticsManager.getInstance().sendEvent(
AnalyticsManager.CATEGORY_PREFERENCE_CHANGE,
SettingsFragment.CATEGORY_THEME,
getColorString(color)
);
int colorFrom = mActiveColor;
mColor = color;
mActiveColor = color;
mPrefs.edit().putString(SettingsFragment.THEME, "" + color).apply();
setSentBubbleColored(mPrefs.getBoolean(SettingsFragment.COLOR_SENT, true));
setReceivedBubbleColored(mPrefs.getBoolean(SettingsFragment.COLOR_RECEIVED, false));
mTextOnColorPrimary = mResources.getColor(isColorDarkEnough(mColor) ?
R.color.theme_dark_text_primary : R.color.theme_light_text_primary);
mTextOnColorSecondary = mResources.getColor(isColorDarkEnough(mColor) ?
R.color.theme_dark_text_secondary : R.color.theme_light_text_secondary);
ValueAnimator colorAnimation = ValueAnimator.ofObject(new CIELChEvaluator(colorFrom, color), 0);
colorAnimation.setDuration(TRANSITION_LENGTH);
colorAnimation.setInterpolator(new DecelerateInterpolator());
colorAnimation.addUpdateListener(animation -> {
setActiveColor((Integer) animation.getAnimatedValue());
});
colorAnimation.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
WidgetProvider.notifyThemeChanged(mContext);
}
});
colorAnimation.start();
if (activity.findViewById(R.id.toolbar_title) != null) {
//final Toolbar toolbar = (Toolbar) mActivity.findViewById(R.id.title);
final QKTextView title = (QKTextView) activity.findViewById(R.id.toolbar_title);
if (title.getCurrentTextColor() != mTextOnColorPrimary) {
ValueAnimator titleColorAnimation = ValueAnimator.ofObject(new ArgbEvaluator(), title.getCurrentTextColor(), mTextOnColorPrimary);
titleColorAnimation.setDuration(TRANSITION_LENGTH);
titleColorAnimation.setInterpolator(new DecelerateInterpolator());
titleColorAnimation.addUpdateListener(animation -> {
int color1 = (Integer) animation.getAnimatedValue();
title.setTextColor(color1);
activity.colorMenuIcons(activity.getMenu(), color1);
});
titleColorAnimation.start();
}
}
}
public static void setActiveColor(int color) {
if (mActiveColor != color) {
mActiveColor = color;
LiveViewManager.refreshViews(QKPreference.THEME);
}
}
private static boolean isColorDarkEnough(int color) {
for (int i = 0; i < COLORS.length; i++) {
for (int j = 0; j < COLORS[i].length; j++) {
if (color == COLORS[i][j]) {
return TEXT_MODE[i][j] == 1;
}
}
}
return true;
}
public static int getSwatchColor(int color) {
for (int i = 0; i < COLORS.length; i++) {
for (int j = 0; j < COLORS[i].length; j++) {
if (color == COLORS[i][j]) {
return PALETTE[i];
}
}
}
return color;
}
private static int[] getSwatch(int color) {
for (int[] swatch : COLORS) {
for (int swatchColor : swatch) {
if (color == swatchColor) {
return swatch;
}
}
}
return PALETTE;
}
static class ColorPickerViewHolder {
@Bind(R.id.tab_1) QKTextView mTab1;
@Bind(R.id.tab_2) QKTextView mTab2;
@Bind(R.id.pager) ViewPager mPager;
@Bind(R.id.palette) ColorPickerPalette mPalette;
@Bind(R.id.preview) View mPreview;
@Bind(R.id.red) SeekBar mRed;
@Bind(R.id.red_value) QKTextView mRedValue;
@Bind(R.id.green) SeekBar mGreen;
@Bind(R.id.green_value) QKTextView mGreenValue;
@Bind(R.id.blue) SeekBar mBlue;
@Bind(R.id.blue_value) QKTextView mBlueValue;
@Bind(R.id.hex) QKEditText mHex;
@Bind(R.id.error) ImageView mError;
public ColorPickerViewHolder(View view) {
ButterKnife.bind(this, view);
}
}
}