diff --git a/app/build.gradle b/app/build.gradle index 83e493745..3d5f79ca0 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -78,7 +78,7 @@ task exportDex { android { compileSdkVersion 32 - buildToolsVersion '33.0.0' + buildToolsVersion '32.0.0' defaultConfig { applicationId "ru.vtosters.lite.utils.lite" diff --git a/app/src/main/java/com/vk/core/drawable/RecoloredDrawable.java b/app/src/main/java/com/vk/core/drawable/RecoloredDrawable.java new file mode 100644 index 000000000..bd60ee6b6 --- /dev/null +++ b/app/src/main/java/com/vk/core/drawable/RecoloredDrawable.java @@ -0,0 +1,132 @@ +package com.vk.core.drawable; + +import android.content.res.ColorStateList; +import android.graphics.Canvas; +import android.graphics.ColorFilter; +import android.graphics.PorterDuff; +import android.graphics.drawable.Drawable; +import androidx.annotation.NonNull; +import ru.vtosters.lite.themes.utils.RecolorUtils; + +public class RecoloredDrawable extends Drawable implements Drawable.Callback { + private Drawable drawable; + private ColorStateList colorStateList; + private int c; + private int d; + + public RecoloredDrawable(Drawable drawable, ColorStateList colorStateList) { + this.c = 255; + this.d = 255; + try { + this.drawable = drawable.mutate(); + } catch (Exception e) { + e.printStackTrace(); + } + this.drawable.setCallback(this); + this.colorStateList = RecolorUtils.themeCSL(colorStateList); + onStateChange(new int[0]); + } + + public void a(int i) { + a(new ColorStateList(new int[][]{new int[0]}, new int[]{i})); + } + + @Override + public void draw(@NonNull Canvas canvas) { + this.drawable.draw(canvas); + } + + @Override + public int getIntrinsicHeight() { + return this.drawable.getIntrinsicHeight(); + } + + @Override + public int getIntrinsicWidth() { + return this.drawable.getIntrinsicWidth(); + } + + @Override + public int getOpacity() { + return this.drawable.getOpacity(); + } + + @Override + public void invalidateDrawable(@NonNull Drawable drawable) { + invalidateSelf(); + } + + @Override + public boolean isStateful() { + return this.colorStateList.isStateful(); + } + + @Override + protected boolean onStateChange(int[] iArr) { + super.onStateChange(iArr); + ColorStateList colorStateList = this.colorStateList; + this.drawable.setColorFilter(colorStateList.getColorForState(iArr, colorStateList.getDefaultColor()), PorterDuff.Mode.SRC_IN); + int length = iArr.length; + boolean z = false; + int i = 0; + while (true) { + if (i >= length) { + break; + } else if (iArr[i] == 0x010100a1) { + z = true; + break; + } else { + i++; + } + } + this.drawable.setState(iArr); + this.drawable.setAlpha(z ? this.c : this.d); + return true; + } + + @Override + public void scheduleDrawable(@NonNull Drawable drawable, @NonNull Runnable runnable, long j) { + scheduleSelf(runnable, j); + } + + @Override + public void setAlpha(int i) { + this.c = i; + this.d = i; + this.drawable.setAlpha(i); + } + + @Override + public void setBounds(int i, int i2, int i3, int i4) { + super.setBounds(i, i2, i3, i4); + this.drawable.setBounds(i, i2, i3, i4); + } + + @Override + public void setColorFilter(ColorFilter colorFilter) { + } + + @Override + public void unscheduleDrawable(@NonNull Drawable drawable, @NonNull Runnable runnable) { + unscheduleSelf(runnable); + } + + public void a(ColorStateList colorStateList) { + this.colorStateList = colorStateList; + onStateChange(getState()); + invalidateSelf(); + } + + public Drawable a() { + return this.drawable; + } + + public RecoloredDrawable(Drawable drawable, int i) { + this(drawable, new ColorStateList(new int[][]{new int[0]}, new int[]{i})); + } + + public RecoloredDrawable() { + this.c = 255; + this.d = 255; + } +} \ No newline at end of file diff --git a/app/src/main/java/com/vtosters/lite/ui/bottomnavigation/BottomNavigationItemView.java b/app/src/main/java/com/vtosters/lite/ui/bottomnavigation/BottomNavigationItemView.java index 4cbde195e..59ee7f61b 100644 --- a/app/src/main/java/com/vtosters/lite/ui/bottomnavigation/BottomNavigationItemView.java +++ b/app/src/main/java/com/vtosters/lite/ui/bottomnavigation/BottomNavigationItemView.java @@ -71,12 +71,11 @@ public class BottomNavigationItemView extends FrameLayout implements MenuView.It this.mIcon.getLayoutParams().width = V.a(28.0F); this.mIcon.getLayoutParams().height = V.a(28.0F); - var colorStateList = getCSTDock(); this.mSmallLabel = this.findViewById(R.id.smallLabel); - mSmallLabel.setTextColor(colorStateList); + mSmallLabel.setTextColor(getCSTDock()); this.mLargeLabel = this.findViewById(R.id.largeLabel); - mLargeLabel.setTextColor(colorStateList); + mLargeLabel.setTextColor(getCSTDock()); LayoutInflater.from(this.getContext()).inflate(R.layout.navigation_bottom_counter, this, true); this.mCounterContainer = this.findViewById(R.id.counter_container); @@ -326,6 +325,8 @@ public class BottomNavigationItemView extends FrameLayout implements MenuView.It } public void setTextColor(ColorStateList colorStateList) { + this.mSmallLabel.setTextColor(colorStateList); + this.mLargeLabel.setTextColor(colorStateList); } @SuppressLint("RestrictedApi") diff --git a/app/src/main/java/ru/vtosters/lite/downloaders/AudioDownloader.java b/app/src/main/java/ru/vtosters/lite/downloaders/AudioDownloader.java index c2ee0ed99..ab854a1f9 100644 --- a/app/src/main/java/ru/vtosters/lite/downloaders/AudioDownloader.java +++ b/app/src/main/java/ru/vtosters/lite/downloaders/AudioDownloader.java @@ -23,6 +23,7 @@ import ru.vtosters.lite.music.downloader.PlaylistDownloader; import ru.vtosters.lite.music.downloader.TrackDownloader; import ru.vtosters.lite.music.notification.MusicNotificationBuilder; import ru.vtosters.lite.utils.AccountManagerUtils; +import ru.vtosters.lite.utils.AndroidUtils; import ru.vtosters.lite.utils.IOUtils; /** @@ -63,6 +64,7 @@ public class AudioDownloader { if (CacheDatabaseDelegate.isCached(trackId)) { CacheDatabaseDelegate.removeTrackFromCache(LibVKXClient.asId(track)); + AndroidUtils.sendToast("Трек удален из кеша"); return; } diff --git a/app/src/main/java/ru/vtosters/lite/downloaders/OTADownloader.java b/app/src/main/java/ru/vtosters/lite/downloaders/OTADownloader.java index ee6ca8eb8..c90c64d3d 100644 --- a/app/src/main/java/ru/vtosters/lite/downloaders/OTADownloader.java +++ b/app/src/main/java/ru/vtosters/lite/downloaders/OTADownloader.java @@ -57,7 +57,7 @@ public class OTADownloader { var request = new DownloadManager.Request(uri); request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED); - request.setTitle("Скачивание обновления"); + request.setTitle(AndroidUtils.getString("downloading_update")); request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, "VTLite-" + commitSHA + ".apk"); var manager = (DownloadManager) AndroidUtils.getGlobalContext().getSystemService(Context.DOWNLOAD_SERVICE); diff --git a/app/src/main/java/ru/vtosters/lite/hooks/DockBarInjector.java b/app/src/main/java/ru/vtosters/lite/hooks/DockBarInjector.java index b1614f61b..a004f91db 100644 --- a/app/src/main/java/ru/vtosters/lite/hooks/DockBarInjector.java +++ b/app/src/main/java/ru/vtosters/lite/hooks/DockBarInjector.java @@ -102,6 +102,7 @@ public class DockBarInjector { item.setStaticMode(true); item.setIconsMode(false); item.setShiftingMode(false); + item.setTextColor(getCSTDock()); } } } diff --git a/app/src/main/java/ru/vtosters/lite/hooks/GcmHook.java b/app/src/main/java/ru/vtosters/lite/hooks/GcmHook.java index 24467c1d4..643c03f8b 100644 --- a/app/src/main/java/ru/vtosters/lite/hooks/GcmHook.java +++ b/app/src/main/java/ru/vtosters/lite/hooks/GcmHook.java @@ -41,11 +41,11 @@ public class GcmHook { } public static String requestTokenV2(String orig) { - return isValidSignature() ? "eyJhbGciOiAibm9uZSJ9eyJub25jZSI6ICJudWxsIn0=" : "e251bGx9"; + return isValidSignature() ? "eyJhbGciOiAibm9uZSJ9.eyJub25jZSI6ICJ0ZXN0PT0ifQ." : "e251bGx9"; } public static String requestToken(String orig) { - return requestToken(); + return "yssp9o9p9pamz5t-nvmq8spgwtin3e0=="; } public static String requestToken() { diff --git a/app/src/main/java/ru/vtosters/lite/hooks/PhotoViewer.java b/app/src/main/java/ru/vtosters/lite/hooks/PhotoViewer.java index 12872dea8..12714ed3f 100644 --- a/app/src/main/java/ru/vtosters/lite/hooks/PhotoViewer.java +++ b/app/src/main/java/ru/vtosters/lite/hooks/PhotoViewer.java @@ -97,9 +97,8 @@ public class PhotoViewer { @SuppressLint("UseCompatLoadingForDrawables") public static void addMenuItems(AttachmentWithMedia attachment, ActionsPopup.b actionPopup, int i, boolean z) { actionPopup.a(R.string.search_photo_content, - ThemesUtils.isDarkTheme() - ? AndroidUtils.getGlobalContext().getDrawable(R.drawable.ic_menu_search_outline_28) - : new RecoloredDrawable(AndroidUtils.getGlobalContext().getDrawable(R.drawable.ic_menu_search_outline_28), ThemesUtils.getAccentColor()), + new RecoloredDrawable(AndroidUtils.getGlobalContext().getDrawable(R.drawable.ic_menu_search_outline_28), + ThemesUtils.isDarkTheme() ? Color.WHITE : ThemesUtils.getAccentColor()), false, () -> { if (attachment instanceof PhotoAttachment) { @@ -119,9 +118,8 @@ public class PhotoViewer { } ); actionPopup.a(R.string.copy_photo_url_content, - !ThemesUtils.isDarkTheme() - ? new RecoloredDrawable(AndroidUtils.getGlobalContext().getDrawable(R.drawable.ic_copy_outline_28), ThemesUtils.getAccentColor()) - : new RecoloredDrawable(AndroidUtils.getGlobalContext().getDrawable(R.drawable.ic_copy_outline_28), Color.WHITE), + new RecoloredDrawable(AndroidUtils.getGlobalContext().getDrawable(R.drawable.ic_copy_outline_28), + ThemesUtils.isDarkTheme() ? Color.WHITE : ThemesUtils.getAccentColor()), false, () -> { if (attachment instanceof PhotoAttachment) { @@ -141,10 +139,8 @@ public class PhotoViewer { } ); actionPopup.a(R.string.open_original_photo_content, - ThemesUtils.isDarkTheme() - ? AndroidUtils.getGlobalContext().getDrawable(R.drawable.ic_link_outline_28) - : new RecoloredDrawable(AndroidUtils.getGlobalContext().getDrawable(R.drawable.ic_link_outline_28), - ThemesUtils.getAccentColor()), + new RecoloredDrawable(AndroidUtils.getGlobalContext().getDrawable(R.drawable.ic_link_outline_28), + ThemesUtils.isDarkTheme() ? Color.WHITE : ThemesUtils.getAccentColor()), false, () -> { if (attachment instanceof PhotoAttachment) { diff --git a/app/src/main/java/ru/vtosters/lite/hooks/TogglesHook.java b/app/src/main/java/ru/vtosters/lite/hooks/TogglesHook.java index 4ee6b4556..7e1e092b2 100644 --- a/app/src/main/java/ru/vtosters/lite/hooks/TogglesHook.java +++ b/app/src/main/java/ru/vtosters/lite/hooks/TogglesHook.java @@ -110,8 +110,6 @@ public class TogglesHook { case FEATURE_VK_APPS_SEARCH: case FEATURE_VOTES_BALANCE: case FEATURE_WEBVIEW_TOKEN_ACTIVE: - case FEATURE_WISHLIST_ENTRY_POINT: - case FEATURE_WISHLIST_MY_PROFILE: case FEATURE_MILKSHAKE_FORCE_DISABLED: case FEATURE_MILKSHAKE_ACTIVATION_DISABLED: case EXPERIMENT_NEWS_DISABLE_CACHE: diff --git a/app/src/main/java/ru/vtosters/lite/music/hook/MusicBottomSheetHook.java b/app/src/main/java/ru/vtosters/lite/music/hook/MusicBottomSheetHook.java index 69bc65d48..4923b23e7 100644 --- a/app/src/main/java/ru/vtosters/lite/music/hook/MusicBottomSheetHook.java +++ b/app/src/main/java/ru/vtosters/lite/music/hook/MusicBottomSheetHook.java @@ -22,6 +22,8 @@ import java.util.ArrayList; import bruhcollective.itaysonlab.libvkx.client.LibVKXClientImpl; import ru.vtosters.lite.downloaders.AudioDownloader; +import ru.vtosters.lite.music.cache.CacheDatabaseDelegate; +import ru.vtosters.lite.utils.AndroidUtils; public class MusicBottomSheetHook { public static ArrayList hook(ArrayList actions, MusicTrack musicTrack) { @@ -36,9 +38,15 @@ public class MusicBottomSheetHook { if (isIntegrationEnabled()) { if (isVkxCached(trackid)) { actions.add(getRemoveCacheTrackVkxAction()); - } else { + } else if (isNetworkConnected()){ actions.add(addToCacheTrackVkxAction()); } + } else { + if (isCached(trackid)) { + actions.add(getRemoveCacheTrackAction()); + } else if (isNetworkConnected()){ + actions.add(addToCacheTrackAction()); + } } if (isNetworkConnected()) { @@ -85,10 +93,10 @@ public class MusicBottomSheetHook { if (isIntegrationEnabled()) { if (isVkxCached(playlist.a, playlist.b)) { actions.add(getRemoveCacheTrackVkxAction()); - } else { + } else if (isNetworkConnected()){ actions.add(addToCacheTrackVkxAction()); } - } else { + } else if (isNetworkConnected()){ actions.add(addToCacheTrackAction()); } @@ -121,6 +129,15 @@ public class MusicBottomSheetHook { return true; } + if (actionId == R.id.remove_from_cache) { + CacheDatabaseDelegate.removeTrackFromCache(asId(track)); + AndroidUtils.sendToast("Трек удален из кеша"); + return true; + } else if (actionId == R.id.add_to_cache) { + AudioDownloader.cacheTrack(track); + return true; + } + if (actionId == R.id.download_mp3) { if (isIntegrationEnabled()) { getInstance().runOnService(service -> { diff --git a/app/src/main/java/ru/vtosters/lite/themes/ColorReferences.java b/app/src/main/java/ru/vtosters/lite/themes/ColorReferences.java new file mode 100644 index 000000000..2348c1f51 --- /dev/null +++ b/app/src/main/java/ru/vtosters/lite/themes/ColorReferences.java @@ -0,0 +1,157 @@ +package ru.vtosters.lite.themes; + +import android.content.res.ColorStateList; +import android.graphics.Color; + +import java.util.Arrays; +import java.util.List; + +import static com.vtosters.lite.R.color.*; + +public class ColorReferences { + public static List accentColors = Arrays.asList( + Color.parseColor("#3f8ae0"), // azure_300 (light accent) + Color.parseColor("#4986cc"), // azure_a400 + Color.parseColor("#528bcc"), // another light accent + Color.parseColor("#71aaeb"), // vk_sky_300 (dark accent) + Color.parseColor("#5181b8"), // header_blue + Color.parseColor("#5a9eff"), + Color.parseColor("#5692d7"), + Color.parseColor("#5c9ce6"), + Color.parseColor("#518bcc"), + Color.parseColor("#74a2d6") + ); + + public static List mutedAccentColors = Arrays.asList( + Color.parseColor("#663f8ae0"), + Color.parseColor("#19528bcc"), + Color.parseColor("#66528bcc"), + Color.parseColor("#1971aaeb"), + Color.parseColor("#665181b8"), + Color.parseColor("#1a003973"), + Color.parseColor("#a800244d"), + Color.parseColor("#14001c3d"), + Color.parseColor("#3d001c3d"), + Color.parseColor("#67a5eb"), + Color.parseColor("#45678f"), + Color.parseColor("#6645678f"), + Color.parseColor("#0099cc"), + Color.parseColor("#664986cc") + ); + + public static List accents = Arrays.asList( + viewer_retry_button_text_color, + azure_300, + picker_camera_button, + music_check_button_bg_pressed, + notification_color, + music_text_counter, + music_follow_button_bg_pressed, + music_blue_button_normal, + music_check_button_bg_normal, + vk_terms_link, + vk_blue_200, + accent_blue, + azure_A400, + vk_azure_A400, + blue, + blue_200, + vk_blue_300, + vk_blue_400, + blue_300, + blue_400, + cool_blue, + cornflower_blue, + cornflower_blue_two, + dot_unread, + fave_promo_btn_pressed, + header_blue, + colorAccent, + live_emoji_butt_hide, + music_action_button_blue, + name, + picker_blue, + picker_blue_pressed, + picker_tab_bg_selected, + picker_tab_text_selected, + sharing_blue_btn_normal, + sharing_blue_btn_pressed, + vk_sky_300, + vk_blue_A400, + blue_A400, + sky_300, + text_blue, + tip_background, + tw__blue_default, + tw__blue_pressed, + vkim_msg_sending_ic, + vkim_playing_drawable_rect, + vk_white_blue32, + date_picker_selector, + post_suggest_blue, + list_dialog_blue, + music_tab_bg_normal, + toolbar_blue_background, + toolbar_blue_statusBarColorBack + ); + + public static List mutedAccents = Arrays.asList( + blue_200_muted, + vk_blue_200_muted, + white_blue32, + vk_white_blue32, + header_blue_opacity16, + black_blue45_alpha10, + music_check_button_bg_checked, + vk_black_blue45_alpha10, + black_blue30_alpha66, + vk_black_blue30_alpha66, + attachpicker_item_background, + black_blue24_alpha8, + music_placeholder_artist_bg, + black_blue24_alpha24, + vk_black_blue24_alpha24, + azure_100_muted, + vk_azure_100_muted, + muted_blue, + blue_600, + light_blue, + vk_blue_600, + muted_blue_opacity40, + muted_blue_old, + darker_blue, + header_blue_opacity40 + ); + + public static boolean isAccentedColor(ColorStateList target) { + return target != null && isAccentedColor(target.getDefaultColor()); + } + + public static boolean isAccentedColor(int target) { + return accentColors.contains(target); + } + + public static boolean isMutedAccentedColor(ColorStateList target) { + return target != null && isMutedAccentedColor(target.getDefaultColor()); + } + + public static boolean isMutedAccentedColor(int target) { + return mutedAccentColors.contains(target); + } + + public static boolean isColorRefAccented(int target) { + return accents.contains(target); + } + + public static boolean isColorRefMutedAccented(int target) { + return mutedAccents.contains(target); + } + + public static boolean isCslNeedToBeThemed(ColorStateList csl) { + int unsel = csl.getColorForState(new int[]{-android.R.attr.state_selected}, Color.BLACK); + int sel = csl.getColorForState(new int[]{android.R.attr.state_selected}, Color.BLACK); + boolean isUnselAccent = isAccentedColor(unsel); + boolean isSelAccent = isAccentedColor(sel); + return ThemesCore.isCachedAccents() && (isUnselAccent || isSelAccent); + } +} \ No newline at end of file diff --git a/app/src/main/java/ru/vtosters/lite/themes/ThemesCore.java b/app/src/main/java/ru/vtosters/lite/themes/ThemesCore.java new file mode 100644 index 000000000..99e6c1e1d --- /dev/null +++ b/app/src/main/java/ru/vtosters/lite/themes/ThemesCore.java @@ -0,0 +1,166 @@ +package ru.vtosters.lite.themes; + +import android.content.Context; +import android.util.SparseBooleanArray; +import android.util.SparseIntArray; + +import androidx.annotation.IdRes; + +import ru.vtosters.lite.utils.ThemesUtils; + + +public class ThemesCore { + private static final String TAG = "ThemesCore"; + + public static SparseIntArray themedColors = new SparseIntArray(); + public static SparseBooleanArray ACCENT_THEME_ONLY_LIGHT = new SparseBooleanArray(); + public static SparseBooleanArray ACCENT_THEME_ONLY_NOMILK_LIGHT = new SparseBooleanArray(); + public static SparseBooleanArray ACCENT_THEME_ONLY_NOMILK = new SparseBooleanArray(); + public static SparseBooleanArray ACCENT_THEME_ONLY_MILK_LIGHT = new SparseBooleanArray(); + public static SparseBooleanArray ACCENT_THEME_ONLY_MILK_DARK = new SparseBooleanArray(); + + private static boolean cachedAccents = false; + private static int wallLightColor; + + static { + setExceptions(); + setThemedColors(ThemesUtils.getAccentColor()); + } + + public static void setExceptions() { + ACCENT_THEME_ONLY_LIGHT.clear(); + ACCENT_THEME_ONLY_NOMILK_LIGHT.clear(); + ACCENT_THEME_ONLY_NOMILK.clear(); + ACCENT_THEME_ONLY_MILK_LIGHT.clear(); + ACCENT_THEME_ONLY_MILK_DARK.clear(); + + ACCENT_THEME_ONLY_LIGHT.put(com.vtosters.lite.R.attr.button_primary_background, false); + ACCENT_THEME_ONLY_LIGHT.put(com.vtosters.lite.R.attr.button_secondary_foreground, false); + ACCENT_THEME_ONLY_LIGHT.put(com.vtosters.lite.R.attr.button_tertiary_foreground, false); + ACCENT_THEME_ONLY_LIGHT.put(com.vtosters.lite.R.attr.button_muted_foreground, false); + ACCENT_THEME_ONLY_LIGHT.put(com.vtosters.lite.R.attr.button_outline_border, false); + ACCENT_THEME_ONLY_LIGHT.put(com.vtosters.lite.R.attr.text_name, false); + ACCENT_THEME_ONLY_LIGHT.put(com.vtosters.lite.R.attr.newsfeed_post_title_color, false); + ACCENT_THEME_ONLY_LIGHT.put(com.vtosters.lite.R.attr.attach_picker_tab_active_background, false); + ACCENT_THEME_ONLY_LIGHT.put(com.vtosters.lite.R.attr.attach_picker_tab_active_text, false); + ACCENT_THEME_ONLY_LIGHT.put(com.vtosters.lite.R.attr.newsfeed_action_color, false); + ACCENT_THEME_ONLY_LIGHT.put(com.vtosters.lite.R.attr.counter_primary_background, false); + ACCENT_THEME_ONLY_LIGHT.put(com.vtosters.lite.R.attr.action_sheet_action_foreground, false); + + ACCENT_THEME_ONLY_NOMILK_LIGHT.put(com.vtosters.lite.R.attr.header_background, false); + + ACCENT_THEME_ONLY_MILK_LIGHT.put(com.vtosters.lite.R.attr.header_tint, false); + ACCENT_THEME_ONLY_MILK_LIGHT.put(com.vtosters.lite.R.attr.icon_name, false); + ACCENT_THEME_ONLY_MILK_LIGHT.put(com.vtosters.lite.R.attr.header_tint_alternate, false); + ACCENT_THEME_ONLY_MILK_LIGHT.put(com.vtosters.lite.R.attr.toolbarIconsColor, false); + ACCENT_THEME_ONLY_MILK_LIGHT.put(com.vtosters.lite.R.attr.header_tab_active_indicator, false); + ACCENT_THEME_ONLY_MILK_LIGHT.put(com.vtosters.lite.R.attr.header_alternate_tab_active_indicator, false); + ACCENT_THEME_ONLY_MILK_LIGHT.put(com.vtosters.lite.R.attr.im_dropdown_arrow_tint, false); + + ACCENT_THEME_ONLY_MILK_LIGHT.put(com.vtosters.lite.R.attr.im_bubble_wallpaper_outgoing, false); + ACCENT_THEME_ONLY_MILK_LIGHT.put(com.vtosters.lite.R.attr.im_bubble_outgoing, false); + ACCENT_THEME_ONLY_MILK_LIGHT.put(com.vtosters.lite.R.attr.im_bubble_outgoing_highlighted, false); + + ACCENT_THEME_ONLY_NOMILK.put(com.vtosters.lite.R.attr.im_dropdown_icon_color, false); + } + + public static void setThemedColors(int accentColor) { + int mutedAccentColor = ThemesUtils.getMutedColor(accentColor); + + cachedAccents = true; + themedColors.clear(); + + themedColors.put(com.vtosters.lite.R.attr.text_link, accentColor); + themedColors.put(com.vtosters.lite.R.attr.accent, accentColor); + themedColors.put(com.vtosters.lite.R.attr.newsfeed_dropdown_color, accentColor); + themedColors.put(com.vtosters.lite.R.attr.icon_name, accentColor); + + themedColors.put(com.vtosters.lite.R.attr.vk_accent, accentColor); + themedColors.put(com.vtosters.lite.R.attr.accentColor, accentColor); + themedColors.put(com.vtosters.lite.R.attr.text_name, accentColor); + themedColors.put(com.vtosters.lite.R.attr.tabbar_active_icon, accentColor); + //themedColors.put(com.vtosters.lite.R.attr.header_background, accentColor); + themedColors.put(com.vtosters.lite.R.attr.header_tint, accentColor); + themedColors.put(com.vtosters.lite.R.attr.header_tint_alternate, accentColor); + themedColors.put(com.vtosters.lite.R.attr.activity_indicator_tint, accentColor); + themedColors.put(com.vtosters.lite.R.attr.toolbarIconsColor, accentColor); + + themedColors.put(com.vtosters.lite.R.attr.button_primary_background, accentColor); + themedColors.put(com.vtosters.lite.R.attr.button_secondary_foreground, accentColor); + themedColors.put(com.vtosters.lite.R.attr.button_tertiary_foreground, accentColor); + themedColors.put(com.vtosters.lite.R.attr.button_outline_border, accentColor); + themedColors.put(com.vtosters.lite.R.attr.button_muted_foreground, accentColor); + themedColors.put(com.vtosters.lite.R.attr.header_tab_active_indicator, accentColor); + themedColors.put(com.vtosters.lite.R.attr.header_alternate_tab_active_indicator, accentColor); + + themedColors.put(com.vtosters.lite.R.attr.button_primary_background_disabled, mutedAccentColor); + themedColors.put(com.vtosters.lite.R.attr.button_secondary_foreground_disabled, mutedAccentColor); + themedColors.put(com.vtosters.lite.R.attr.button_tertiary_foreground_disabled, mutedAccentColor); + themedColors.put(com.vtosters.lite.R.attr.button_outline_border_disabled, mutedAccentColor); + themedColors.put(com.vtosters.lite.R.attr.button_muted_foreground_disabled, mutedAccentColor); + + themedColors.put(com.vtosters.lite.R.attr.im_dropdown_icon_color, accentColor); + themedColors.put(com.vtosters.lite.R.attr.im_dropdown_arrow_tint, accentColor); + + themedColors.put(com.vtosters.lite.R.attr.im_attach_tint, accentColor); + themedColors.put(com.vtosters.lite.R.attr.im_forward_line_tint, accentColor); + themedColors.put(com.vtosters.lite.R.attr.link_alternate, accentColor); + themedColors.put(com.vtosters.lite.R.attr.newsfeed_post_title_color, accentColor); + + themedColors.put(com.vtosters.lite.R.attr.attach_picker_tab_active_background, accentColor); + themedColors.put(com.vtosters.lite.R.attr.attach_picker_tab_active_text, accentColor); + themedColors.put(com.vtosters.lite.R.attr.newsfeed_action_color, accentColor); + themedColors.put(com.vtosters.lite.R.attr.counter_primary_background, accentColor); + + themedColors.put(com.vtosters.lite.R.attr.dynamic_blue, accentColor); + + themedColors.put(com.vtosters.lite.R.attr.action_sheet_action_foreground, accentColor); + + // messages + themedColors.put(com.vtosters.lite.R.attr.im_reply_separator, accentColor); + themedColors.put(com.vtosters.lite.R.attr.im_text_name, accentColor); + + wallLightColor = ThemesUtils.lighten(accentColor, 0.67f); + + themedColors.put(com.vtosters.lite.R.attr.im_ic_send_msg, accentColor); + themedColors.put(com.vtosters.lite.R.attr.im_bubble_wallpaper_outgoing, accentColor); + themedColors.put(com.vtosters.lite.R.attr.im_bubble_outgoing, accentColor); + themedColors.put(com.vtosters.lite.R.attr.im_bubble_outgoing_highlighted, accentColor); + } + + public static int getThemedAttr(Context context, @IdRes int attr) { + if (attr == com.vtosters.lite.R.attr.im_bubble_wallpaper_outgoing || attr == com.vtosters.lite.R.attr.im_bubble_outgoing || attr == com.vtosters.lite.R.attr.im_bubble_outgoing_highlighted) { + return wallLightColor; + } + + return themedColors.get(attr); + } + + public static boolean hasThemedAttr(Context context, int attrID) { +// try { +// Log.d(TAG, "Requesting color by attr " + context.getResources().getResourceName(attrID)); +// } catch (Exception e) { +// } + + if (isCachedAccents()) { + if (!ThemesUtils.isDarkTheme()) { + return (themedColors.get(attrID) != 0 + && ACCENT_THEME_ONLY_MILK_DARK.get(attrID, true) + && ACCENT_THEME_ONLY_NOMILK_LIGHT.get(attrID, true)); + } else { + return (themedColors.get(attrID) != 0 + && ACCENT_THEME_ONLY_MILK_LIGHT.get(attrID, true) + && ACCENT_THEME_ONLY_NOMILK_LIGHT.get(attrID, true)); + } + } else return themedColors.get(attrID) != 0; + } + + public static void clear() { + cachedAccents = false; + themedColors.clear(); + } + + public static boolean isCachedAccents() { + return cachedAccents; + } +} \ No newline at end of file diff --git a/app/src/main/java/ru/vtosters/lite/themes/ThemesHacks.java b/app/src/main/java/ru/vtosters/lite/themes/ThemesHacks.java new file mode 100644 index 000000000..31be18a8e --- /dev/null +++ b/app/src/main/java/ru/vtosters/lite/themes/ThemesHacks.java @@ -0,0 +1,56 @@ +package ru.vtosters.lite.themes; + +import android.content.Context; +import android.graphics.drawable.*; +import android.os.Build; +import android.view.View; +import android.widget.TextView; +import androidx.annotation.ColorRes; +import androidx.annotation.NonNull; +import com.vtosters.lite.R; +import ru.vtosters.lite.themes.utils.RecolorUtils; +import ru.vtosters.lite.utils.ThemesUtils; + +public class ThemesHacks { + // Фиксит селектор (все/свои/архив) в профиле + public static void fixProfileSelector(View view) { + if (!ThemesUtils.isMilkshake()) return; + var id = view.getId(); + + if (id == R.id.profile_wall_owner_posts || id == R.id.profile_wall_all_posts || id == R.id.profile_wall_archived_posts) { + StateListDrawable states = (StateListDrawable) ((LayerDrawable) view.getBackground()).getDrawable(0); + LayerDrawable selected = (LayerDrawable) ((DrawableContainer.DrawableContainerState) states.getConstantState()).getChildren()[0]; + ((ColorDrawable) selected.getDrawable(0)).setColor(ThemesUtils.getAccentColor()); + } + } + + public static void fixThemedFeed(TextView textView, int i) { + if (i != R.layout.themed_feed_tab_2) { + return; + } + textView.setTextColor(RecolorUtils.recolorCSL(textView.getTextColors())); + ((InsetDrawable) ((DrawableContainer.DrawableContainerState) textView.getBackground().getConstantState()).getChildren()[0]).getDrawable().setTint(ThemesUtils.lighten(ThemesUtils.getAccentColor(), 0.15f)); + } + + public static void fixDropdown(Drawable drawable) { + if (!ThemesUtils.isDarkTheme() && ThemesUtils.isMilkshake() && ThemesCore.isCachedAccents()) { + StateListDrawable stateListDrawable = (StateListDrawable) drawable; + ((DrawableContainer.DrawableContainerState) stateListDrawable.getConstantState()).getChildren()[0].setTint(ThemesUtils.getAccentColor()); + ((DrawableContainer.DrawableContainerState) stateListDrawable.getConstantState()).getChildren()[1].setTint(ThemesUtils.halfAlpha(ThemesUtils.getAccentColor())); + } + } + + public static int getHackedColor(@NonNull Context context, @ColorRes int color) { + if (ThemesCore.isCachedAccents() && ColorReferences.isAccentedColor(context.getColor(color))) { + return ThemesUtils.getAccentColor(); + } + + if (ThemesCore.isCachedAccents() && ColorReferences.isMutedAccentedColor(context.getColor(color))) { + return ThemesUtils.getMutedAccentColor(); + } + + if (Build.VERSION.SDK_INT > 23) { + return context.getColor(color); + } else return context.getResources().getColor(color); + } +} \ No newline at end of file diff --git a/app/src/main/java/ru/vtosters/lite/themes/VTLResources.java b/app/src/main/java/ru/vtosters/lite/themes/VTLResources.java new file mode 100644 index 000000000..32ddc7b48 --- /dev/null +++ b/app/src/main/java/ru/vtosters/lite/themes/VTLResources.java @@ -0,0 +1,92 @@ +package ru.vtosters.lite.themes; + +import android.content.Context; +import android.content.res.Resources; +import android.content.res.TypedArray; +import android.graphics.drawable.Drawable; +import android.util.AttributeSet; +import android.util.Log; +import android.util.TypedValue; + +import androidx.annotation.Nullable; + +import java.lang.reflect.Field; +import java.util.ArrayList; +import java.util.List; + +import ru.vtosters.lite.utils.ThemesUtils; + +public class VTLResources extends Resources { + private static final String TAG = "VTLResources"; + private final Context context; + private static Field typedArrayField; + + private static final List attributesToTheme = new ArrayList<>(); + + static { + try { + typedArrayField = TypedArray.class.getDeclaredField("mData"); + typedArrayField.setAccessible(true); + } catch (NoSuchFieldException e) { + e.printStackTrace(); + } + + attributesToTheme.add(16843041); + attributesToTheme.add(android.R.attr.backgroundTint); + attributesToTheme.add(16843173); + } + + public VTLResources(Context context, Resources parent) { + super(parent.getAssets(), parent.getDisplayMetrics(), parent.getConfiguration()); + this.context = context; +// Log.d(TAG, "VTLResources: init"); + } + + @Override + public TypedArray obtainAttributes(AttributeSet set, int[] attrs) { + var typedArray = super.obtainAttributes(set, attrs); + var data = getArrayData(typedArray); + for (int i = 0; i < attrs.length; i++) { + try { + int attrID = attrs[i]; + if (attributesToTheme.contains(attrID)) { + int type = data[i*6]; + int cnt = data[(i*6)+1]; + + if (type == TypedValue.TYPE_ATTRIBUTE && isAttrThemeable(cnt)) { + data[i*6] = TypedValue.TYPE_INT_COLOR_RGB8; + data[(i*6)+1] = ThemesUtils.getAccentColor(); + data[(i*6)+2] = 0; // clear reference content + } + } + } catch (Exception e) { + Log.e(TAG, "TAVzlom failed! (obtainAttributes)"); + e.printStackTrace(); + } + } + return typedArray; + } + + @Override + public Drawable getDrawable(int id, @Nullable Theme theme) throws NotFoundException { + var drawable = super.getDrawable(id, theme); + if (id == com.vtosters.lite.R.drawable.newsfeed_tab_dropdown_16) { + ThemesHacks.fixDropdown(drawable); + } + return drawable; + } + + private static boolean isAttrThemeable(int attrID) { + return !ThemesUtils.isDarkTheme() && attrID == com.vtosters.lite.R.attr.button_primary_background; + } + + private static int[] getArrayData(TypedArray arr) { + try { + return (int[]) typedArrayField.get(arr); + } catch (IllegalAccessException e) { + Log.e(TAG, "getArrayData: ", e); + e.printStackTrace(); + return new int[0]; + } + } +} \ No newline at end of file diff --git a/app/src/main/java/ru/vtosters/lite/themes/ViewInjector.java b/app/src/main/java/ru/vtosters/lite/themes/ViewInjector.java new file mode 100644 index 000000000..f3c2ae118 --- /dev/null +++ b/app/src/main/java/ru/vtosters/lite/themes/ViewInjector.java @@ -0,0 +1,43 @@ +package ru.vtosters.lite.themes; + +import android.view.View; +import android.view.ViewGroup; + +import java.util.ArrayList; + +import ru.vtosters.lite.themes.hooks.BaseHook; +import ru.vtosters.lite.themes.hooks.ButtonHook; +import ru.vtosters.lite.themes.hooks.ImageViewHook; +import ru.vtosters.lite.themes.hooks.ProgressWheelHook; +import ru.vtosters.lite.themes.hooks.TabLayoutHook; +import ru.vtosters.lite.themes.hooks.TextViewHook; +import ru.vtosters.lite.themes.hooks.ToolbarHook; +import ru.vtosters.lite.themes.hooks.VKImageViewHook; + +public class ViewInjector { + public static ArrayList hooks = new ArrayList<>(); + + static { + hooks.add(new ButtonHook()); + hooks.add(new ImageViewHook()); + hooks.add(new TabLayoutHook()); + hooks.add(new TextViewHook()); + hooks.add(new ToolbarHook()); + hooks.add(new VKImageViewHook()); + hooks.add(new ProgressWheelHook()); + } + + public static View inject(View view, int i, boolean z) { + for (BaseHook hook : hooks) { + hook.inject(view, i, z); + } + if (view instanceof ViewGroup) { + var viewGroup = (ViewGroup) view; + for (int i2 = 0; i2 < viewGroup.getChildCount(); i2++) { + inject(viewGroup.getChildAt(i2), i, false); + } + } + + return view; + } +} \ No newline at end of file diff --git a/app/src/main/java/ru/vtosters/lite/themes/hooks/BaseHook.java b/app/src/main/java/ru/vtosters/lite/themes/hooks/BaseHook.java new file mode 100644 index 000000000..d56a91414 --- /dev/null +++ b/app/src/main/java/ru/vtosters/lite/themes/hooks/BaseHook.java @@ -0,0 +1,7 @@ +package ru.vtosters.lite.themes.hooks; + +import android.view.View; + +public interface BaseHook { + void inject(View view, int i, boolean z); +} diff --git a/app/src/main/java/ru/vtosters/lite/themes/hooks/ButtonHook.java b/app/src/main/java/ru/vtosters/lite/themes/hooks/ButtonHook.java new file mode 100644 index 000000000..1dec07232 --- /dev/null +++ b/app/src/main/java/ru/vtosters/lite/themes/hooks/ButtonHook.java @@ -0,0 +1,29 @@ +package ru.vtosters.lite.themes.hooks; + +import android.content.res.ColorStateList; +import android.view.View; +import android.widget.Button; + +import ru.vtosters.lite.themes.ColorReferences; +import ru.vtosters.lite.utils.ThemesUtils; + +public class ButtonHook implements BaseHook { + @Override + public void inject(View view, int i, boolean z) { + if (view instanceof Button) { + var button = (Button) view; + if (button.getBackgroundTintList() != null && ColorReferences.isMutedAccentedColor(button.getBackgroundTintList())) { + button.setBackgroundTintList(ColorStateList.valueOf(ThemesUtils.getMutedAccentColor())); + } + + if (button.getBackgroundTintList() != null && ColorReferences.isAccentedColor(button.getBackgroundTintList())) { + button.setBackgroundTintList(ColorStateList.valueOf(ThemesUtils.getAccentColor())); + } + + if (TextViewHook.isPositiveButton(button) || TextViewHook.isVkUiButton(view)) { + button.setBackgroundTintList(ColorStateList.valueOf(ThemesUtils.getAccentColor())); + } + } + } +} + diff --git a/app/src/main/java/ru/vtosters/lite/themes/hooks/ImageViewHook.java b/app/src/main/java/ru/vtosters/lite/themes/hooks/ImageViewHook.java new file mode 100644 index 000000000..b9b88ef8a --- /dev/null +++ b/app/src/main/java/ru/vtosters/lite/themes/hooks/ImageViewHook.java @@ -0,0 +1,24 @@ +package ru.vtosters.lite.themes.hooks; + +import android.content.res.ColorStateList; +import android.view.View; +import android.widget.ImageView; + +import ru.vtosters.lite.themes.ColorReferences; +import ru.vtosters.lite.themes.ThemesCore; +import ru.vtosters.lite.utils.ThemesUtils; + +public class ImageViewHook implements BaseHook { + @Override + public void inject(View view, int i, boolean z) { + if (view instanceof ImageView) { + if (ThemesCore.isCachedAccents()) { + var imageView = (ImageView) view; + if (imageView.getImageTintList() == null) return; + if (ColorReferences.isCslNeedToBeThemed(imageView.getImageTintList())) { + imageView.setImageTintList(ColorStateList.valueOf(ThemesUtils.getAccentColor())); + } + } + } + } +} diff --git a/app/src/main/java/ru/vtosters/lite/themes/hooks/ProgressWheelHook.java b/app/src/main/java/ru/vtosters/lite/themes/hooks/ProgressWheelHook.java new file mode 100644 index 000000000..01da24ac2 --- /dev/null +++ b/app/src/main/java/ru/vtosters/lite/themes/hooks/ProgressWheelHook.java @@ -0,0 +1,21 @@ +package ru.vtosters.lite.themes.hooks; + +import android.view.View; + +import com.pnikosis.materialishprogress.ProgressWheel; + +import ru.vtosters.lite.themes.ThemesCore; +import ru.vtosters.lite.utils.ThemesUtils; + +public class ProgressWheelHook implements BaseHook { + @Override + public void inject(View view, int i, boolean z) { + if (view instanceof ProgressWheel) { + if (ThemesCore.isCachedAccents()) { + var progressWheel = (ProgressWheel) view; + progressWheel.setBarColor(ThemesUtils.getAccentColor()); + } + } + } +} + diff --git a/app/src/main/java/ru/vtosters/lite/themes/hooks/TabLayoutHook.java b/app/src/main/java/ru/vtosters/lite/themes/hooks/TabLayoutHook.java new file mode 100644 index 000000000..c85402c26 --- /dev/null +++ b/app/src/main/java/ru/vtosters/lite/themes/hooks/TabLayoutHook.java @@ -0,0 +1,21 @@ +package ru.vtosters.lite.themes.hooks; + +import android.content.res.ColorStateList; +import android.view.View; + +import com.vk.core.view.VKTabLayout; + +import ru.vtosters.lite.utils.ThemesUtils; + + +public class TabLayoutHook implements BaseHook { + @Override + public void inject(View view, int i, boolean z) { + if (view instanceof VKTabLayout) { + var tabLayout = (VKTabLayout) view; + tabLayout.setSelectedTabIndicatorColor(ThemesUtils.getAccentColor()); + tabLayout.setTabRippleColor(ColorStateList.valueOf(ThemesUtils.getAccentColor())); + } + } +} + diff --git a/app/src/main/java/ru/vtosters/lite/themes/hooks/TextViewHook.java b/app/src/main/java/ru/vtosters/lite/themes/hooks/TextViewHook.java new file mode 100644 index 000000000..da8e65948 --- /dev/null +++ b/app/src/main/java/ru/vtosters/lite/themes/hooks/TextViewHook.java @@ -0,0 +1,136 @@ +package ru.vtosters.lite.themes.hooks; + +import android.annotation.SuppressLint; +import android.content.res.ColorStateList; +import android.os.Build; +import android.view.View; +import android.widget.EditText; +import android.widget.TextView; + +import androidx.appcompat.widget.AppCompatCheckedTextView; + +import com.vk.core.extensions.EditTextExt; +import com.vk.core.view.OverlayTextView; +import com.vk.core.view.TintTextView; +import com.vk.core.view.links.LinkedTextView; +import com.vtosters.lite.R; + +import ru.vtosters.lite.themes.ColorReferences; +import ru.vtosters.lite.themes.ThemesHacks; +import ru.vtosters.lite.themes.utils.VkUiThemer; +import ru.vtosters.lite.utils.ThemesUtils; + +public class TextViewHook implements BaseHook { + + private static final String TAG = "TextViewHook"; + + @SuppressLint("RestrictedApi") + @Override + public void inject(View view, int i, boolean z) { + if (view instanceof TextView) { + var textView = (TextView) view; + + if (ColorReferences.isAccentedColor(textView.getCurrentTextColor())) { + textView.setTextColor(ThemesUtils.getAccentColor()); + } + + if (ColorReferences.isMutedAccentedColor(textView.getCurrentTextColor())) { + textView.setTextColor(ThemesUtils.getMutedAccentColor()); + } + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && textView.getCompoundDrawableTintList() != null) { + if (ColorReferences.isAccentedColor(textView.getCompoundDrawableTintList())) { + textView.setCompoundDrawableTintList(ColorStateList.valueOf(ThemesUtils.getAccentColor())); + } + + if (ColorReferences.isMutedAccentedColor(textView.getCompoundDrawableTintList())) { + textView.setCompoundDrawableTintList(ColorStateList.valueOf(ThemesUtils.getMutedAccentColor())); + } + } + + if (textView.getLinkTextColors() != null && ColorReferences.isAccentedColor(textView.getLinkTextColors())) { + textView.setLinkTextColor(ThemesUtils.getAccentColor()); + } + + if (textView.getLinkTextColors() != null && ColorReferences.isMutedAccentedColor(textView.getLinkTextColors())) { + textView.setLinkTextColor(ThemesUtils.getMutedAccentColor()); + } + + if (isPositiveButton(textView) || isVkUiButton(textView)) { + view.setBackgroundTintList(ColorStateList.valueOf(ThemesUtils.getAccentColor())); + } + + if (view instanceof OverlayTextView) { + if (view.getId() == android.R.id.button1) { + view.setBackground(ThemesUtils.recolorDrawable(view.getBackground())); + } + if (ColorReferences.isAccentedColor(((OverlayTextView) view).getTextColors().getDefaultColor())) { + ((OverlayTextView) view).setTextColor(ThemesUtils.getAccentColor()); + } + } + + if (view instanceof TintTextView) { + if (eligibleForStartTinting((TintTextView) view)) { + ((TintTextView) view).setDrawableStartTint(ThemesUtils.getAccentColor()); + } + + if (eligibleForStartTintingMuted((TintTextView) view)) { + ((TintTextView) view).setDrawableStartTint(ThemesUtils.getMutedAccentColor()); + } + + if (eligibleForTinting(view.getId())) { + ((TintTextView) view).setDrawableTint(ThemesUtils.getAccentColor()); + } + + if (eligibleForTinting(view.getId())) { + ((TintTextView) view).setDrawableStartTint(ThemesUtils.getAccentColor()); + } + } + + if (view instanceof LinkedTextView) { + ((LinkedTextView) view).setLinkTextColor(ThemesUtils.getAccentColor()); + } + + if (view instanceof AppCompatCheckedTextView) { + var check = (AppCompatCheckedTextView) view; + if (ColorReferences.isAccentedColor(check.getCheckMarkTintList())) { + check.setCheckMarkTintList(ColorStateList.valueOf(ThemesUtils.getAccentColor())); + } + + if (ColorReferences.isMutedAccentedColor(check.getCheckMarkTintList())) { + check.setCheckMarkTintList(ColorStateList.valueOf(ThemesUtils.getMutedAccentColor())); + } + } + + if (view instanceof EditText) { + ThemesUtils.setCursorColor((EditText) view); + } + + ThemesUtils.colorHandles(textView); + VkUiThemer.autoThemeVkuiButtons(textView); + ThemesHacks.fixProfileSelector(textView); + ThemesHacks.fixThemedFeed(textView, i); + } + } + + public static boolean eligibleForStartTinting(TintTextView view) { + return ColorReferences.isAccentedColor(view.getTextColors()) || view.getTextColors().getDefaultColor() == ThemesUtils.getAccentColor(); + } + + public static boolean eligibleForStartTintingMuted(TintTextView view) { + return ColorReferences.isMutedAccentedColor(view.getTextColors()) || view.getTextColors().getDefaultColor() == ThemesUtils.getMutedAccentColor(); + } + + public static boolean eligibleForTinting(int id) { + return !ThemesUtils.isDarkTheme() && (id == R.id.attach_title || id == R.id.post_retweet_name); + } + + public static boolean isPositiveButton(View view) { + return !ThemesUtils.isDarkTheme() && (view.getId() == R.id.positive || view.getId() == R.id.positive_button); + } + + public static boolean isVkUiButton(View view) { + return !ThemesUtils.isDarkTheme() && (view.getId() == R.id.empty_button || view.getId() == R.id.button); + } +} + diff --git a/app/src/main/java/ru/vtosters/lite/themes/hooks/ToolbarHook.java b/app/src/main/java/ru/vtosters/lite/themes/hooks/ToolbarHook.java new file mode 100644 index 000000000..38c5097da --- /dev/null +++ b/app/src/main/java/ru/vtosters/lite/themes/hooks/ToolbarHook.java @@ -0,0 +1,29 @@ +package ru.vtosters.lite.themes.hooks; + +import android.view.View; +import androidx.appcompat.widget.Toolbar; +import com.vk.core.drawable.RecoloredDrawable; +import ru.vtosters.lite.utils.ThemesUtils; + +public class ToolbarHook implements BaseHook { + @Override + public void inject(View view, int i, boolean z) { + if (view instanceof Toolbar) { + var color = (ThemesUtils.isMilkshake() && !ThemesUtils.isDarkTheme()) ? ThemesUtils.getAccentColor() : ThemesUtils.getHeaderText(); + var menu = ((Toolbar) view).getMenu(); + for (int j = 0; j < menu.size(); ++j) { + var item = menu.getItem(j); + var icon = item.getIcon(); + if (icon != null) { + if (icon instanceof RecoloredDrawable) + ((RecoloredDrawable) icon).a(color); + else + icon = new RecoloredDrawable(icon, color); + item.setIcon(icon); + } + } + + } + } +} + diff --git a/app/src/main/java/ru/vtosters/lite/themes/hooks/VKImageViewHook.java b/app/src/main/java/ru/vtosters/lite/themes/hooks/VKImageViewHook.java new file mode 100644 index 000000000..eb3133a7e --- /dev/null +++ b/app/src/main/java/ru/vtosters/lite/themes/hooks/VKImageViewHook.java @@ -0,0 +1,30 @@ +package ru.vtosters.lite.themes.hooks; + +import android.graphics.Paint; +import android.graphics.PorterDuff; +import android.graphics.PorterDuffColorFilter; +import android.view.View; + +import com.vk.imageloader.view.VKImageView; + +import ru.vtosters.lite.themes.utils.RecolorUtils; +import ru.vtosters.lite.utils.ThemesUtils; + +public class VKImageViewHook implements BaseHook { + private static Paint paint = new Paint(); + static { + paint.setColorFilter(new PorterDuffColorFilter(ThemesUtils.getAccentColor(), PorterDuff.Mode.SRC_IN)); + } + + @Override + public void inject(View view, int i, boolean z) { + if (view instanceof VKImageView) { + var imageView = (VKImageView) view; + if (imageView.getImageTintList() != null) { + imageView.setImageTintList(RecolorUtils.recolorCSL(imageView.getImageTintList())); + imageView.setColorFilter(ThemesUtils.getAccentColor(), PorterDuff.Mode.SRC_IN); + } + } + } +} + diff --git a/app/src/main/java/ru/vtosters/lite/themes/items/VTLColor.java b/app/src/main/java/ru/vtosters/lite/themes/items/VTLColor.java new file mode 100644 index 000000000..1c086ee17 --- /dev/null +++ b/app/src/main/java/ru/vtosters/lite/themes/items/VTLColor.java @@ -0,0 +1,26 @@ +package ru.vtosters.lite.themes.items; + +public class VTLColor { + + public String resName; + public int id; + public int color; + + public VTLColor(int id, int color) { + this.id = id; + this.color = color; + } + public VTLColor(String resName, int id, int color) { + this.resName = resName; + this.id = id; + this.color = color; + } + + public static VTLColor create(int id, int color) { + return new VTLColor(id, color); + } + + public static VTLColor create(String resName, int id, int color) { + return new VTLColor(resName, id, color); + } +} diff --git a/app/src/main/java/ru/vtosters/lite/themes/items/VTLPalette.java b/app/src/main/java/ru/vtosters/lite/themes/items/VTLPalette.java new file mode 100644 index 000000000..19d723329 --- /dev/null +++ b/app/src/main/java/ru/vtosters/lite/themes/items/VTLPalette.java @@ -0,0 +1,94 @@ +package ru.vtosters.lite.themes.items; + +import android.graphics.Color; + +import org.json.JSONException; +import org.json.JSONObject; + +import java.util.ArrayList; +import java.util.List; + +public class VTLPalette { + public String id; + public String name; + public String author; + public List colors = new ArrayList<>(); + + public VTLPalette() { + + } + + public VTLPalette(String id, String name, String author, List colors) { + this.id = id; + this.name = name; + this.author = author; + this.colors = colors; + } + + public VTLPalette setId(String id) { + this.id = id; + return this; + } + + public VTLPalette setName(String name) { + this.name = name; + return this; + } + + public VTLPalette setAuthor(String author) { + this.author = author; + return this; + } + + public VTLPalette setColors(List colors) { + this.colors = colors; + return this; + } + + public VTLPalette setColor(String name, int color) { + this.colors.add(new VTLColor(name, 0, color)); + return this; + } + + public int getColor(String name) { + for (var item : colors) + if (name.equals(item.resName)) + return item.color; + return -1; + } + + public static VTLPalette fromJson(JSONObject json) throws JSONException { + var palette = new VTLPalette() + .setId(json.optString("palette_id")) + .setName(json.optString("name")) + .setAuthor(json.optString("author")); + var paletteNode = json.getJSONArray("palette"); + for (int i = 0; i < paletteNode.length(); i++) { + var colorNode = paletteNode.getJSONObject(i); + var name = colorNode.getString("name"); + if (colorNode.has("colors")) { + var colorsNode = colorNode.getJSONArray("colors"); + for (int j = 0; j < colorsNode.length(); j++) { + var subColorNode = colorsNode.getJSONObject(j); + var index = subColorNode.getString("index"); + var subColor = subColorNode.getString("color"); + if (!subColor.startsWith("#")) subColor = "#" + subColor; + palette.setColor(name + " " + index, Color.parseColor(subColor)); + } + } else { + var color = colorNode.getString("color"); + if (!color.startsWith("#")) color = "#" + color; + palette.setColor(name, Color.parseColor(color)); + } + } + return palette; + } + + public static VTLPalette valuesOf(String id, String name, String author, List colors) { + return new VTLPalette() + .setId(id) + .setName(name) + .setAuthor(author) + .setColors(colors); + } +} diff --git a/app/src/main/java/ru/vtosters/lite/themes/palettes/PalettesManager.java b/app/src/main/java/ru/vtosters/lite/themes/palettes/PalettesManager.java new file mode 100644 index 000000000..5e6184374 --- /dev/null +++ b/app/src/main/java/ru/vtosters/lite/themes/palettes/PalettesManager.java @@ -0,0 +1,98 @@ +package ru.vtosters.lite.themes.palettes; + +import android.os.Environment; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import org.json.JSONException; +import org.json.JSONObject; + +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +import ru.vtosters.lite.themes.items.VTLPalette; +import ru.vtosters.lite.utils.AndroidUtils; +import ru.vtosters.lite.utils.IOUtils; + +public class PalettesManager { + + private final static File PALETTES_DIR = new File(Environment.getExternalStorageDirectory(), "VTL/palettes"); + private final static String ASSETS_DIR = "vtl_themes/palettes/"; + + private static PalettesManager sInstance; + + private final List mPalettes = new ArrayList<>(); + + public static PalettesManager getInstance() { + if (sInstance == null) + sInstance = new PalettesManager(); + return sInstance; + } + + public PalettesManager() { + load(); + } + + public void load() { + mPalettes.clear(); + if (!PALETTES_DIR.exists()) + PALETTES_DIR.mkdirs(); + final var palettes = PALETTES_DIR.listFiles((dir, name) -> name.endsWith(".json")); + if (palettes == null || palettes.length == 0) + copyPaletteFromAssets(); + parsePalettes(); + } + + private boolean copyPaletteFromAssets() { + try { + final var manager = AndroidUtils.getGlobalContext().getAssets(); + final var assets = manager.list(ASSETS_DIR); + if (assets == null || assets.length == 0) return false; + for (var asset : assets) { + try { + IOUtils.copyFile(manager.open(ASSETS_DIR + asset), new File(PALETTES_DIR, asset)); + } catch (IOException e) { + e.printStackTrace(); + } + } + return true; + } catch (IOException e) { + e.printStackTrace(); + } + return false; + } + + private void parsePalettes() { + var arr = PALETTES_DIR.listFiles((dir, name) -> name.endsWith(".json")); + if (arr == null || arr.length == 0) + throw new RuntimeException("Can't load palettes"); + for (var file : arr) { + try { + var json = new JSONObject(IOUtils.readAllLines(file)); + mPalettes.add(VTLPalette.fromJson(json)); + } catch (IOException | JSONException e) { + e.printStackTrace(); + } + } + } + + @Nullable + public VTLPalette getPalette(String id) { + for (var palette : mPalettes) + if (id.equals(palette.id)) + return palette; + return null; + } + + @NonNull + public VTLPalette getPalette(int i) { + return mPalettes.get(i); + } + + public int getPalettesCount() { + return mPalettes.size(); + } +} diff --git a/app/src/main/java/ru/vtosters/lite/themes/utils/RecolorUtils.java b/app/src/main/java/ru/vtosters/lite/themes/utils/RecolorUtils.java new file mode 100644 index 000000000..f0236b9d4 --- /dev/null +++ b/app/src/main/java/ru/vtosters/lite/themes/utils/RecolorUtils.java @@ -0,0 +1,94 @@ +package ru.vtosters.lite.themes.utils; + +import android.annotation.SuppressLint; +import android.content.Context; +import android.content.res.ColorStateList; +import android.graphics.Color; +import android.graphics.drawable.Drawable; +import android.os.Build; +import com.vk.core.drawable.RecoloredDrawable; +import ru.vtosters.lite.themes.ColorReferences; +import ru.vtosters.lite.utils.AndroidUtils; +import ru.vtosters.lite.utils.ThemesUtils; + +public class RecolorUtils { + public static Drawable recolorDrawableToolbar(Drawable drawable) { + if (drawable == null) return null; + + return new RecoloredDrawable(drawable, ThemesUtils.getHeaderText()); + } // Recolor toolbar drawable to accent color + + @SuppressLint("UseCompatLoadingForDrawables") + public static Drawable recolorDrawableInt(int drawable) { + + @SuppressLint("UseCompatLoadingForDrawables") Drawable res = AndroidUtils.getResources().getDrawable(drawable); + return new RecoloredDrawable(res, ThemesUtils.getAccentColor()); + } // Get res drawable via id and coloring to accent + + public static int recolorHexColor(int i){ + var accented = ColorReferences.isAccentedColor(i); + var mutedaccented = ColorReferences.isMutedAccentedColor(i); + return (accented || mutedaccented) ? (accented ? ThemesUtils.getAccentColor() : ThemesUtils.getMutedAccentColor()) : i; + } + + public static ColorStateList recolorCSL(ColorStateList colorStateList) { + if (colorStateList == null) return null; + + return ColorStateList.valueOf(ThemesUtils.getAccentColor()); + } // Recolor ColorStateList to accent color + + @SuppressLint("UseCompatLoadingForColorStateLists") + public static ColorStateList themeCSL(Context context, int color) { + if (ColorReferences.isColorRefAccented(color)) { + return ColorStateList.valueOf(ThemesUtils.getAccentColor()); + } else if (ColorReferences.isColorRefMutedAccented(color)) { + return ColorStateList.valueOf(ThemesUtils.getMutedAccentColor()); + } + + ColorStateList csl; + + if (Build.VERSION.SDK_INT >= 23) { + csl = context.getColorStateList(color); + } else { + csl = context.getResources().getColorStateList(color); + } + + return themeCSL(csl); + } // Recolor ColorStateList + + public static ColorStateList themeCSL(ColorStateList csl){ + try { + int unsel = csl.getColorForState(new int[]{-android.R.attr.state_selected}, Color.BLACK); + int sel = csl.getColorForState(new int[]{android.R.attr.state_selected}, Color.BLACK); + int enabled = csl.getColorForState(new int[]{android.R.attr.state_enabled}, Color.BLACK); + int disabled = csl.getColorForState(new int[]{-android.R.attr.state_enabled}, Color.BLACK); + + boolean isUnselAccent = ColorReferences.isAccentedColor(unsel); + boolean isSelAccent = ColorReferences.isAccentedColor(sel); + boolean isEnabledAccent = ColorReferences.isAccentedColor(enabled); + boolean isDisabledAccent = ColorReferences.isAccentedColor(disabled); + + boolean isUnselMutedAccent = ColorReferences.isMutedAccentedColor(unsel); + boolean isSelMutedAccent = ColorReferences.isMutedAccentedColor(sel); + boolean isEnabledMutedAccent = ColorReferences.isMutedAccentedColor(enabled); + boolean isDisabledMutedAccent = ColorReferences.isMutedAccentedColor(disabled); + + if (isUnselAccent || isSelAccent || isUnselMutedAccent || isSelMutedAccent) { + return new ColorStateList(new int[][]{ + new int[]{android.R.attr.state_selected}, new int[]{-android.R.attr.state_selected} + }, new int[]{(isSelAccent || isSelMutedAccent) ? (isSelAccent ? ThemesUtils.getAccentColor() : ThemesUtils.getMutedAccentColor()) : sel, (isUnselAccent || isUnselMutedAccent) ? (isUnselAccent ? ThemesUtils.getAccentColor() : ThemesUtils.getMutedAccentColor()) : unsel}); + } + + if (isDisabledAccent || isEnabledAccent || isEnabledMutedAccent || isDisabledMutedAccent) { + return new ColorStateList(new int[][]{ + new int[]{android.R.attr.state_enabled}, new int[]{-android.R.attr.state_enabled} + }, new int[]{(isEnabledAccent || isEnabledMutedAccent) ? (isEnabledAccent ? ThemesUtils.getAccentColor() : ThemesUtils.getMutedAccentColor()) : enabled, (isDisabledAccent || isDisabledMutedAccent) ? (isDisabledAccent ? ThemesUtils.getAccentColor() : ThemesUtils.getMutedAccentColor()) : disabled}); + } + + return csl; + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } +} diff --git a/app/src/main/java/ru/vtosters/lite/themes/utils/VkUiThemer.java b/app/src/main/java/ru/vtosters/lite/themes/utils/VkUiThemer.java new file mode 100644 index 000000000..d471fe84a --- /dev/null +++ b/app/src/main/java/ru/vtosters/lite/themes/utils/VkUiThemer.java @@ -0,0 +1,85 @@ +package ru.vtosters.lite.themes.utils; + +import android.content.res.ColorStateList; +import android.graphics.drawable.Drawable; +import android.graphics.drawable.DrawableContainer; +import android.graphics.drawable.GradientDrawable; +import android.graphics.drawable.RippleDrawable; +import android.graphics.drawable.StateListDrawable; +import android.os.Build; +import android.widget.TextView; + +import ru.vtosters.lite.themes.ColorReferences; +import ru.vtosters.lite.utils.ThemesUtils; + +public class VkUiThemer { + public static void autoThemeVkuiButtons(TextView view) { + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) return; + if (ThemesUtils.isDarkTheme()) + return; // no need to theme b/w buttons, well it should skip, but I do it for extra performance + + try { + if (!(view.getBackground() instanceof StateListDrawable)) return; + + StateListDrawable states = ((StateListDrawable) view.getBackground()); + if (states.getConstantState() == null) return; + DrawableContainer.DrawableContainerState dStates = (DrawableContainer.DrawableContainerState) states.getConstantState(); + + if (dStates.getChildCount() == 2) { + Drawable target = dStates.getChildren()[0]; + if (!(target instanceof RippleDrawable)) return; + + RippleDrawable ripple = (RippleDrawable) target; + for (int i = 0; i < ripple.getNumberOfLayers(); i++) { + if (ripple.getId(i) == android.R.id.mask) continue; + + Drawable currentTarget = ripple.getDrawable(i); + + if (!(currentTarget instanceof GradientDrawable)) continue; + + //if (TSColorRefs.TS_DEBUG_MODE) Log.d("TSCore", "[tsh] finally, obamium = ["+currentTarget.toString()+"]"); + + GradientDrawable spd = (GradientDrawable) currentTarget; + if (spd.getShape() != GradientDrawable.RECTANGLE) continue; + +// Log.d("TSCore", "[tsh] got a color!"); + + ColorStateList csl = spd.getColor(); +// if (csl != null) { +// Log.d("TSCore", "[tsh] csl2 | " + csl); +// } + + if (ColorReferences.isAccentedColor(spd.getColor())) { +// Log.d("TSCore", "[tsh] theming CSL"); + spd.setTint(ThemesUtils.getAccentColor()); + } + } + + Drawable draw2 = dStates.getChildren()[0]; + if (!(draw2 instanceof GradientDrawable)) return; + GradientDrawable spd = (GradientDrawable) draw2; + if (spd.getShape() != GradientDrawable.RECTANGLE) return; + +// Log.d("TSCore", "[tsh:disabled] got a color!"); + + ColorStateList csl = spd.getColor(); +// if (csl != null) { +// Log.d("TSCore", "[tsh:disabled] csl2 | " + csl); +// } + + if (ColorReferences.isAccentedColor(spd.getColor())) { +// Log.d("TSCore", "[tsh:disabled] theming CSL"); + spd.setTint(ThemesUtils.getAccentColor()); + } + + if (ColorReferences.isMutedAccentedColor(spd.getColor())) { +// Log.d("TSCore", "[tsh:disabled] theming CSL"); + spd.setTint(ThemesUtils.getMutedAccentColor()); + } + } + } catch (Exception e) { + // This must go wrong, so we ignore any exceptions that may occur + e.printStackTrace(); // REMOVE THIS! + } + } +} \ No newline at end of file diff --git a/app/src/main/java/ru/vtosters/lite/ui/PreferencesUtil.java b/app/src/main/java/ru/vtosters/lite/ui/PreferencesUtil.java index 54f140044..65986e0ed 100644 --- a/app/src/main/java/ru/vtosters/lite/ui/PreferencesUtil.java +++ b/app/src/main/java/ru/vtosters/lite/ui/PreferencesUtil.java @@ -1,30 +1,23 @@ package ru.vtosters.lite.ui; -import static ru.vtosters.lite.utils.AndroidUtils.dp2px; -import static ru.vtosters.lite.utils.AndroidUtils.getGlobalContext; -import static ru.vtosters.lite.utils.ImageUtils.setTint; -import static ru.vtosters.lite.utils.ThemesUtils.getAccentColor; -import static ru.vtosters.lite.utils.ThemesUtils.getSTextAttr; -import static ru.vtosters.lite.utils.ThemesUtils.getTextAttr; - import android.content.Context; -import android.content.res.ColorStateList; import android.graphics.drawable.Drawable; import android.preference.PreferenceManager; import android.util.TypedValue; import android.view.ViewGroup; import android.widget.EditText; import android.widget.LinearLayout; - import androidx.annotation.Nullable; import androidx.core.content.ContextCompat; import androidx.preference.ListPreference; import androidx.preference.Preference; import androidx.preference.PreferenceCategory; - import com.vk.core.dialogs.alert.VkAlertDialog; import com.vtosters.lite.general.fragments.MaterialPreferenceToolbarFragment; import com.vtosters.lite.ui.MaterialSwitchPreference; +import ru.vtosters.lite.utils.AndroidUtils; +import ru.vtosters.lite.utils.ImageUtils; +import ru.vtosters.lite.utils.ThemesUtils; public class PreferencesUtil { @@ -36,7 +29,7 @@ public class PreferencesUtil { CharSequence[] entries, CharSequence[] entriesValue ) { - ListPreference preference = new ListPreference(getGlobalContext()); + ListPreference preference = new ListPreference(fragment.requireContext()); preference.setEntries(entries); preference.setEntryValues(entriesValue); preference.setTitle(title); // setTitle @@ -57,7 +50,7 @@ public class PreferencesUtil { CharSequence[] entriesValue, Preference.OnPreferenceChangeListener listener ) { - ListPreference preference = new ListPreference(getGlobalContext()); + ListPreference preference = new ListPreference(fragment.requireContext()); preference.setEntries(entries); preference.setEntryValues(entriesValue); preference.setSummary(summary); // setSummary @@ -69,7 +62,7 @@ public class PreferencesUtil { preference.setOnPreferenceChangeListener(listener); if (iconRes != 0) - preference.setIcon(setTint(getGlobalContext(), getDrawable(getGlobalContext(), iconRes))); // preference.setIcon + preference.setIcon(ImageUtils.setTint(fragment.requireContext(), getDrawable(fragment.requireContext(), iconRes))); // preference.setIcon fragment.getPreferenceScreen().addPreference(preference); // fragment.getPreferenceScreen().addPreference(preference) } @@ -80,7 +73,7 @@ public class PreferencesUtil { CharSequence summary, boolean defValue ) { - MaterialSwitchPreference materialSwitchPreference = new MaterialSwitchPreference(getGlobalContext()); + MaterialSwitchPreference materialSwitchPreference = new MaterialSwitchPreference(materialPreferenceToolbarFragment.requireContext()); materialSwitchPreference.setTitle(title); // setTitle materialSwitchPreference.setSummary(summary); // setSummary materialSwitchPreference.setKey(key); // setKey @@ -98,7 +91,7 @@ public class PreferencesUtil { // boolean defValue, // Preference.OnPreferenceChangeListener listener // ) { -// MaterialSwitchPreference materialSwitchPreference = new MaterialSwitchPreference(getGlobalContext()); +// MaterialSwitchPreference materialSwitchPreference = new MaterialSwitchPreference(fragment.requireContext()); // materialSwitchPreference.setTitle(title); // setTitle // materialSwitchPreference.setSummary(summary); // setSummary // materialSwitchPreference.setKey(key); // setKey @@ -106,7 +99,7 @@ public class PreferencesUtil { // materialSwitchPreference.setOnPreferenceChangeListener(listener); // setOnPreferenceClickListener // // if (iconRes != 0) -// materialSwitchPreference.setIcon(setTint(getGlobalContext(), Objects.requireNonNull(ContextCompat.getDrawable(getGlobalContext(), iconRes)))); // preference.setIcon +// materialSwitchPreference.setIcon(setTint(fragment.requireContext(), Objects.requireNonNull(ContextCompat.getDrawable(fragment.requireContext(), iconRes)))); // preference.setIcon // // fragment.getPreferenceScreen().addPreference(materialSwitchPreference); // fragment.getPreferenceScreen().addPreference(preference) // } @@ -120,7 +113,7 @@ public class PreferencesUtil { boolean defValue, Preference.OnPreferenceChangeListener listener ) { - MaterialSwitchPreference materialSwitchPreference = new MaterialSwitchPreference(getGlobalContext()); + MaterialSwitchPreference materialSwitchPreference = new MaterialSwitchPreference(fragment.requireContext()); materialSwitchPreference.setTitle(title); // setTitle materialSwitchPreference.setSummary(summary); // setSummary materialSwitchPreference.setKey(key); // setKey @@ -128,7 +121,7 @@ public class PreferencesUtil { fragment.getPreferenceScreen().addPreference(materialSwitchPreference); // materialPreferenceToolbarFragment.getPreferenceScreen().addPreference(preference) if (iconRes != 0) - materialSwitchPreference.setIcon(setTint(getGlobalContext(), getDrawable(getGlobalContext(), iconRes))); // preference.setIcon + materialSwitchPreference.setIcon(ImageUtils.setTint(fragment.requireContext(), getDrawable(fragment.requireContext(), iconRes))); // preference.setIcon materialSwitchPreference.setOnPreferenceChangeListener(listener); // setOnPreferenceClickListener(listener) fragment.getPreferenceScreen().addPreference(materialSwitchPreference); // fragment.getPreferenceScreen().addPreference(preference) @@ -140,7 +133,7 @@ public class PreferencesUtil { CharSequence title, CharSequence summary ) { - Preference preference = new Preference(getGlobalContext()); + Preference preference = new Preference(fragment.requireContext()); preference.setSummary(summary); // setSummary preference.setTitle(title); // setTitle preference.setKey(key); // setKey @@ -155,12 +148,12 @@ public class PreferencesUtil { int iconRes, Preference.OnPreferenceClickListener listener ) { - Preference preference = new Preference(getGlobalContext()); + Preference preference = new Preference(fragment.requireContext()); preference.setSummary(summary); // setSummary preference.setTitle(title); // setTitle if (iconRes != 0) - preference.setIcon(setTint(getGlobalContext(), getDrawable(getGlobalContext(), iconRes))); // preference.setIcon + preference.setIcon(ImageUtils.setTint(fragment.requireContext(), getDrawable(fragment.requireContext(), iconRes))); // preference.setIcon preference.setOnPreferenceClickListener(listener); // preference.setOnPreferenceClickListener(listener) fragment.getPreferenceScreen().addPreference(preference); // fragment.getPreferenceScreen().addPreference(preference) @@ -173,13 +166,13 @@ public class PreferencesUtil { CharSequence summary, int iconRes, Preference.OnPreferenceClickListener listener) { - Preference preference = new Preference(getGlobalContext()); + Preference preference = new Preference(fragment.requireContext()); preference.setSummary(summary); // setSummary preference.setTitle(title); // setTitle preference.setKey(key); // setKey if (iconRes != 0) - preference.setIcon(setTint(getGlobalContext(), getDrawable(getGlobalContext(), iconRes))); // preference.setIcon + preference.setIcon(ImageUtils.setTint(fragment.requireContext(), getDrawable(fragment.requireContext(), iconRes))); // preference.setIcon preference.setOnPreferenceClickListener(listener); // preference.setOnPreferenceClickListener(listener) fragment.getPreferenceScreen().addPreference(preference); // fragment.getPreferenceScreen().addPreference(preference) @@ -193,7 +186,7 @@ public class PreferencesUtil { @Nullable Drawable icon, Preference.OnPreferenceClickListener listener ) { - Preference preference = new Preference(getGlobalContext()); + Preference preference = new Preference(fragment.requireContext()); preference.setSummary(summary); // setSummary preference.setTitle(title); // setTitle preference.setKey(key); // setKey @@ -206,37 +199,37 @@ public class PreferencesUtil { } public static void addPreferenceCategory(MaterialPreferenceToolbarFragment fragment, CharSequence title) { - PreferenceCategory preference = new PreferenceCategory(getGlobalContext(), null); + PreferenceCategory preference = new PreferenceCategory(fragment.requireContext(), null); preference.setTitle(title); // setTitle fragment.getPreferenceScreen().addPreference(preference); // fragment.getPreferenceScreen().addPreference(preference) } public static void addPreferenceCategory(MaterialPreferenceToolbarFragment fragment, CharSequence title, int collapsedSize) { - PreferenceCategory preference = new PreferenceCategory(getGlobalContext(), null); + PreferenceCategory preference = new PreferenceCategory(fragment.requireContext(), null); preference.setTitle(title); // setTitle fragment.getPreferenceScreen().addPreference(preference); // fragment.getPreferenceScreen().addPreference(preference) } public static void addEditTextPreference(MaterialPreferenceToolbarFragment fragment, String key, CharSequence title, EditTextPrefChangeListener editTextPrefChangeListener) { - Preference preference = new Preference(getGlobalContext()); + Preference preference = new Preference(fragment.requireContext()); preference.setTitle(title); // setTitle preference.setKey(key); // setKey preference.setOnPreferenceClickListener(preference1 -> { - LinearLayout linearLayout = new LinearLayout(getGlobalContext()); + LinearLayout linearLayout = new LinearLayout(fragment.requireContext()); - final EditText editText = new EditText(getGlobalContext()); - editText.setText(PreferenceManager.getDefaultSharedPreferences(getGlobalContext()).getString(key, "")); + final EditText editText = new EditText(fragment.requireContext()); + editText.setText(PreferenceManager.getDefaultSharedPreferences(fragment.requireContext()).getString(key, "")); editText.setHint(title); - editText.setTextColor(getTextAttr()); - editText.setHintTextColor(getSTextAttr()); + editText.setTextColor(ThemesUtils.getTextAttr()); + editText.setHintTextColor(ThemesUtils.getSTextAttr()); - editText.setBackgroundTintList(ColorStateList.valueOf(getAccentColor())); + editText.setBackgroundTintList(ThemesUtils.getAccenedColorStateList()); linearLayout.addView(editText); editText.getLayoutParams().width = ViewGroup.LayoutParams.MATCH_PARENT; ViewGroup.MarginLayoutParams margin = ((ViewGroup.MarginLayoutParams) editText.getLayoutParams()); - margin.setMargins(dp2px(20f), 0, dp2px(20f), 0); + margin.setMargins(AndroidUtils.dp2px(20f), 0, AndroidUtils.dp2px(20f), 0); editText.setLayoutParams(margin); new VkAlertDialog.Builder(fragment.getContext()) @@ -247,7 +240,7 @@ public class PreferencesUtil { if (!change) return; - PreferenceManager.getDefaultSharedPreferences(getGlobalContext()) + PreferenceManager.getDefaultSharedPreferences(fragment.requireContext()) .edit() .putString(key, editText.getText().toString()) .apply(); @@ -261,13 +254,13 @@ public class PreferencesUtil { public static int getTextColor(Context ctx) { TypedValue typedValue = new TypedValue(); - ctx.getTheme().resolveAttribute(getTextAttr(), typedValue, true); + ctx.getTheme().resolveAttribute(ThemesUtils.getTextAttr(), typedValue, true); return typedValue.data; } public static int getSTextColor(Context ctx) { TypedValue typedValue = new TypedValue(); - ctx.getTheme().resolveAttribute(getSTextAttr(), typedValue, true); + ctx.getTheme().resolveAttribute(ThemesUtils.getSTextAttr(), typedValue, true); return typedValue.data; } diff --git a/app/src/main/java/ru/vtosters/lite/ui/adapters/ColorPickerAdapter.java b/app/src/main/java/ru/vtosters/lite/ui/adapters/ColorPickerAdapter.java new file mode 100644 index 000000000..38239838f --- /dev/null +++ b/app/src/main/java/ru/vtosters/lite/ui/adapters/ColorPickerAdapter.java @@ -0,0 +1,81 @@ +package ru.vtosters.lite.ui.adapters; + +import android.graphics.Color; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.FrameLayout; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.recyclerview.widget.RecyclerView; + +import com.vk.core.drawable.BorderDrawable; +import com.vk.core.util.Screen; +import com.vk.stories.view.StoryCircleImageView; + +import java.util.List; + +import ru.vtosters.lite.themes.items.VTLColor; +import ru.vtosters.lite.utils.AndroidUtils; +import ru.vtosters.lite.utils.ThemesUtils; + +public class ColorPickerAdapter extends RecyclerView.Adapter { + + private List mColors; + private OnColorSelectListener mSelectListener; + + public ColorPickerAdapter(List colors, OnColorSelectListener selectListener) { + this.mColors = colors; + this.mSelectListener = selectListener; + } + + @NonNull + @Override + public ColorPickerViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { + var container = LayoutInflater.from(parent.getContext()) + .inflate(AndroidUtils.getIdentifier("color_picker_item", "layout"), parent, false); + return new ColorPickerViewHolder(container); + } + + @Override + public void onBindViewHolder(@NonNull ColorPickerViewHolder holder, int pos) { + holder.bind(mColors.get(pos)); + } + + @Override + public int getItemCount() { + return mColors.size(); + } + + public class ColorPickerViewHolder extends RecyclerView.ViewHolder { + private View mContainer; + private FrameLayout mColorPreviewBorder; + private StoryCircleImageView mColorPreview; + private TextView mColorName; + private TextView mColorValue; + + public ColorPickerViewHolder(@NonNull View view) { + super(view); + + mContainer = view; + mColorPreviewBorder = view.findViewById(AndroidUtils.getIdentifier("color_preview_border", "id")); + mColorPreview = view.findViewById(AndroidUtils.getIdentifier("color_preview", "id")); + mColorName = view.findViewById(AndroidUtils.getIdentifier("color_name", "id")); + mColorValue = view.findViewById(AndroidUtils.getIdentifier("color_value", "id")); + } + + public void bind(VTLColor item) { + mContainer.setOnClickListener(v -> mSelectListener.onColorSelected(ColorPickerAdapter.this, item)); + mColorPreviewBorder.setBackground(new BorderDrawable(ThemesUtils.isDarkTheme() ? Color.WHITE : Color.BLACK, Screen.c(24.0f), Screen.c(1.0f))); + mColorPreview.setPlaceholderColor(item.color); + mColorName.setText(item.resName); + mColorValue.setText("#" + Integer.toHexString(item.color).toUpperCase()); + } + } + + public interface OnColorSelectListener { + + void onColorSelected(ColorPickerAdapter adapter, VTLColor vtlcolor); + } +} diff --git a/app/src/main/java/ru/vtosters/lite/ui/adapters/MessagesPreviewAdapter.java b/app/src/main/java/ru/vtosters/lite/ui/adapters/MessagesPreviewAdapter.java index 8431b108d..ee01a6fab 100644 --- a/app/src/main/java/ru/vtosters/lite/ui/adapters/MessagesPreviewAdapter.java +++ b/app/src/main/java/ru/vtosters/lite/ui/adapters/MessagesPreviewAdapter.java @@ -1,39 +1,41 @@ package ru.vtosters.lite.ui.adapters; -import static ru.vtosters.lite.utils.ThemesUtils.getTextAttr; - import android.content.Context; -import android.util.TypedValue; +import android.graphics.ColorFilter; +import android.graphics.ColorMatrixColorFilter; +import android.graphics.PorterDuff; import android.view.Gravity; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; -import android.widget.TextView; import androidx.annotation.NonNull; import androidx.recyclerview.widget.RecyclerView; import com.vk.core.widget.BubbleFluidLayout; +import com.vk.im.ui.components.viewcontrollers.msg_list.entry.MsgTextBuilder; +import com.vk.im.ui.views.msg.MsgPartTextView; +import com.vk.im.ui.views.msg.bubble.MsgBubbleDrawable; +import com.vk.im.ui.views.msg.bubble.MsgBubblePart; +import com.vk.im.ui.views.msg.bubble.MsgBubbleStyle; import com.vk.im.ui.views.msg.bubble.MsgBubbleView; import com.vtosters.lite.R; +import com.vtosters.lite.m0.ToolbarHelper; import ru.vtosters.lite.utils.AndroidUtils; +import ru.vtosters.lite.utils.ThemesUtils; public class MessagesPreviewAdapter extends RecyclerView.Adapter { - private static final int ME = 0x0; - private static final int ANONYMOUS = -0x1; - private final String[] mMessages = AndroidUtils.getArray(R.array.wallpaper_change_dialog); + private final String[] mMessages; - private static int getColorFromAttribute(Context context, int attrId) { - TypedValue typedValue = new TypedValue(); - context.getTheme().resolveAttribute(attrId, typedValue, true); - return typedValue.data; + public MessagesPreviewAdapter(String... messages) { + mMessages = messages; } @Override public int getItemViewType(int i) { - return i % 2 == 0 ? ANONYMOUS : ME; + return i % 2 == 0 ? Gravity.START : Gravity.END; } @NonNull @@ -41,7 +43,12 @@ public class MessagesPreviewAdapter extends RecyclerView.Adapter { - // Toast.makeText(mActivity, "Обновления найдены", Toast.LENGTH_SHORT).show(); - new ModalBottomSheetWrapper(mActivity) - .setTitle(mActivity.getString(R.string.newversion) + " " + mHelper.getNewVersionName()) - .setUpdateInfoView(mHelper.getUpdateDescription()) - .setPositiveButton(mActivity.getString(R.string.updateanddownload), () -> { - OTADownloader.downloadBuild(mHelper.getDownloadUrl(), mHelper.getCommitSHA()); - }) - .show(); - }); +// mActivity.runOnUiThread(() -> { +// // Toast.makeText(mActivity, "Обновления найдены", Toast.LENGTH_SHORT).show(); +// new ModalBottomSheetWrapper(mActivity) +// .setTitle(mActivity.getString(R.string.newversion) + " " + mHelper.getNewVersionName()) +// .setUpdateInfoView(mHelper.getUpdateDescription()) +// .setPositiveButton(mActivity.getString(R.string.updateanddownload), () -> { +// OTADownloader.downloadBuild(mHelper.getDownloadUrl(), mHelper.getCommitSHA()); +// }) +// .show(); +// }); } @Override public void onUpdateCanceled() { - mActivity.runOnUiThread(() -> { - // Toast.makeText(mActivity, "Обновлений не найдено", Toast.LENGTH_SHORT).show(); - }); +// mActivity.runOnUiThread(() -> { +// // Toast.makeText(mActivity, "Обновлений не найдено", Toast.LENGTH_SHORT).show(); +// }); } } diff --git a/app/src/main/java/ru/vtosters/lite/ui/dialogs/PalettesBottomSheetDialog.java b/app/src/main/java/ru/vtosters/lite/ui/dialogs/PalettesBottomSheetDialog.java new file mode 100644 index 000000000..9f2fb0b6f --- /dev/null +++ b/app/src/main/java/ru/vtosters/lite/ui/dialogs/PalettesBottomSheetDialog.java @@ -0,0 +1,22 @@ +package ru.vtosters.lite.ui.dialogs; + +import android.app.Activity; + +import ru.vtosters.lite.themes.items.VTLPalette; +import ru.vtosters.lite.ui.adapters.ColorPickerAdapter; + +public class PalettesBottomSheetDialog { + + private static final String TAG = "palettes_copy_color"; + + public static void create(Activity activity, VTLPalette palette, ColorPickerAdapter.OnColorSelectListener action) { + var instance = new VTColorPickerBottomSheetDialog(activity); + var colorPickerAdapter = new ColorPickerAdapter(palette.colors, (adapter, vtlcolor) -> { + action.onColorSelected(adapter, vtlcolor); + instance.dismiss(); + }); + instance.setTitle(palette.name) + .setAdapter(colorPickerAdapter, true) + .show(TAG, true); + } +} diff --git a/app/src/main/java/ru/vtosters/lite/ui/dialogs/VTColorPickerBottomSheetDialog.java b/app/src/main/java/ru/vtosters/lite/ui/dialogs/VTColorPickerBottomSheetDialog.java new file mode 100644 index 000000000..8444ca3d1 --- /dev/null +++ b/app/src/main/java/ru/vtosters/lite/ui/dialogs/VTColorPickerBottomSheetDialog.java @@ -0,0 +1,41 @@ +package ru.vtosters.lite.ui.dialogs; + +import android.app.Activity; +import android.widget.LinearLayout; + +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + +import ru.vtosters.lite.ui.adapters.ColorPickerAdapter; +import ru.vtosters.lite.ui.vkui.ModalBottomSheetWrapper; +import ru.vtosters.lite.utils.LayoutUtils; + +public class VTColorPickerBottomSheetDialog extends ModalBottomSheetWrapper { + + private Activity mActivity; + private LinearLayout mContainer; + + public VTColorPickerBottomSheetDialog(Activity activity) { + super(activity); + this.mActivity = activity; + mContainer = new LinearLayout(mActivity); + mContainer.setLayoutParams(LayoutUtils.createLinear(-1, -1)); + mContainer.setOrientation(LinearLayout.VERTICAL); + } + + public VTColorPickerBottomSheetDialog setAdapter(ColorPickerAdapter adapter, boolean searchMode) { + var recyclerView = new RecyclerView(mActivity); + recyclerView.setAdapter(adapter); + recyclerView.setHasFixedSize(true); + recyclerView.setLayoutManager(new LinearLayoutManager(mActivity)); + var recyclerViewParams = LayoutUtils.createLinear(-1, -1); + mContainer.addView(recyclerView, recyclerViewParams); + + mBuilder.a(mContainer); + return setView(mContainer); + } + + public LinearLayout getContainer() { + return mContainer; + } +} diff --git a/app/src/main/java/ru/vtosters/lite/ui/fragments/BaseToolbarFragment.java b/app/src/main/java/ru/vtosters/lite/ui/fragments/BaseToolbarFragment.java index 308cc39c2..1a1e5f905 100644 --- a/app/src/main/java/ru/vtosters/lite/ui/fragments/BaseToolbarFragment.java +++ b/app/src/main/java/ru/vtosters/lite/ui/fragments/BaseToolbarFragment.java @@ -25,7 +25,7 @@ public abstract class BaseToolbarFragment extends FragmentImpl { private Toolbar mToolbar; private FrameLayout mContentLayout; - @CallSuper + protected void onCreateMenu(Menu menu) { if (menu.size() > 0) for (int i = 0; i < menu.size(); i++) @@ -63,6 +63,10 @@ public abstract class BaseToolbarFragment extends FragmentImpl { return mRootView; } + public Toolbar getToolbar() { + return mToolbar; + } + public abstract View onCreateContent(@NonNull LayoutInflater inflater, @Nullable Bundle bundle); private void initToolbar() { diff --git a/app/src/main/java/ru/vtosters/lite/ui/fragments/DockBarEditorFragment.java b/app/src/main/java/ru/vtosters/lite/ui/fragments/DockBarEditorFragment.java index e714b76cd..09b008417 100644 --- a/app/src/main/java/ru/vtosters/lite/ui/fragments/DockBarEditorFragment.java +++ b/app/src/main/java/ru/vtosters/lite/ui/fragments/DockBarEditorFragment.java @@ -21,6 +21,7 @@ import androidx.recyclerview.widget.RecyclerView; import com.vtosters.lite.R; +import ru.vtosters.lite.themes.hooks.TextViewHook; import ru.vtosters.lite.ui.adapters.CategorizedAdapter; import ru.vtosters.lite.ui.components.DockBarEditorManager; import ru.vtosters.lite.ui.components.ItemMovingCallback; @@ -54,6 +55,8 @@ public class DockBarEditorFragment extends BaseToolbarFragment { restartApplication(); }); + new TextViewHook().inject(save, 0, false); + LinearLayout.LayoutParams saveParams = new LinearLayout.LayoutParams(0, -2); saveParams.weight = 1.0f; buttonsContainer.addView(save, saveParams); @@ -68,6 +71,8 @@ public class DockBarEditorFragment extends BaseToolbarFragment { restartApplication(); }); + new TextViewHook().inject(reset, 0, false); + LinearLayout.LayoutParams resetParams = new LinearLayout.LayoutParams(0, -2); resetParams.weight = 1.0f; buttonsContainer.addView(reset, resetParams); diff --git a/app/src/main/java/ru/vtosters/lite/ui/fragments/MediaFragment.java b/app/src/main/java/ru/vtosters/lite/ui/fragments/MediaFragment.java index c744ca629..7d0b53441 100644 --- a/app/src/main/java/ru/vtosters/lite/ui/fragments/MediaFragment.java +++ b/app/src/main/java/ru/vtosters/lite/ui/fragments/MediaFragment.java @@ -50,6 +50,7 @@ import ru.vtosters.lite.music.LastFMScrobbler; import ru.vtosters.lite.music.cache.CacheDatabaseDelegate; import ru.vtosters.lite.ui.adapters.ImagineArrayAdapter; import ru.vtosters.lite.utils.AndroidUtils; +import ru.vtosters.lite.utils.ThemesUtils; public class MediaFragment extends MaterialPreferenceToolbarFragment { private static final ExecutorService executor = Executors.newCachedThreadPool(); @@ -57,7 +58,7 @@ public class MediaFragment extends MaterialPreferenceToolbarFragment { public static void download(Context ctx) { final EditText input = new EditText(ctx); input.setTextColor(getTextAttr()); - input.setBackgroundTintList(ColorStateList.valueOf(getAccentColor())); + input.setBackgroundTintList(ThemesUtils.getAccenedColorStateList()); var lp = new FrameLayout.LayoutParams(-1, -2); lp.leftMargin = AndroidUtils.dp2px(16); @@ -175,7 +176,7 @@ public class MediaFragment extends MaterialPreferenceToolbarFragment { fn.setHint(R.string.lastfm_login); fn.setTextColor(getTextAttr()); fn.setHintTextColor(getSTextAttr()); - fn.setBackgroundTintList(ColorStateList.valueOf(getAccentColor())); + fn.setBackgroundTintList(ThemesUtils.getAccenedColorStateList()); linearLayout.addView(fn); fn.getLayoutParams().width = ViewGroup.LayoutParams.MATCH_PARENT; ViewGroup.MarginLayoutParams margin = ((ViewGroup.MarginLayoutParams) fn.getLayoutParams()); @@ -186,7 +187,7 @@ public class MediaFragment extends MaterialPreferenceToolbarFragment { ln.setHint(R.string.lastfm_password); ln.setTextColor(getTextAttr()); ln.setHintTextColor(getSTextAttr()); - ln.setBackgroundTintList(ColorStateList.valueOf(getAccentColor())); + ln.setBackgroundTintList(ThemesUtils.getAccenedColorStateList()); linearLayout.addView(ln); ln.getLayoutParams().width = ViewGroup.LayoutParams.MATCH_PARENT; ln.setLayoutParams(margin); diff --git a/app/src/main/java/ru/vtosters/lite/ui/fragments/SuperAppEditorFragment.java b/app/src/main/java/ru/vtosters/lite/ui/fragments/SuperAppEditorFragment.java index c511fd8dc..c901d3b87 100644 --- a/app/src/main/java/ru/vtosters/lite/ui/fragments/SuperAppEditorFragment.java +++ b/app/src/main/java/ru/vtosters/lite/ui/fragments/SuperAppEditorFragment.java @@ -22,6 +22,7 @@ import androidx.recyclerview.widget.RecyclerView; import com.vtosters.lite.R; +import ru.vtosters.lite.themes.hooks.TextViewHook; import ru.vtosters.lite.ui.adapters.CategorizedAdapter; import ru.vtosters.lite.ui.components.ItemMovingCallback; import ru.vtosters.lite.ui.components.SuperAppEditorManager; @@ -70,6 +71,8 @@ public class SuperAppEditorFragment extends BaseToolbarFragment { restartApplication(); }); + new TextViewHook().inject(save, 0, false); + LinearLayout.LayoutParams saveParams = new LinearLayout.LayoutParams(0, -2); saveParams.weight = 1.0f; buttonsContainer.addView(save, saveParams); @@ -84,6 +87,8 @@ public class SuperAppEditorFragment extends BaseToolbarFragment { restartApplication(); }); + new TextViewHook().inject(reset, 0, false); + LinearLayout.LayoutParams resetParams = new LinearLayout.LayoutParams(0, -2); resetParams.weight = 1.0f; buttonsContainer.addView(reset, resetParams); diff --git a/app/src/main/java/ru/vtosters/lite/ui/fragments/ThemesFragment.java b/app/src/main/java/ru/vtosters/lite/ui/fragments/ThemesFragment.java index fbc0ffa5e..8949a57f0 100644 --- a/app/src/main/java/ru/vtosters/lite/ui/fragments/ThemesFragment.java +++ b/app/src/main/java/ru/vtosters/lite/ui/fragments/ThemesFragment.java @@ -1,20 +1,27 @@ package ru.vtosters.lite.ui.fragments; -import static ru.vtosters.lite.utils.AndroidUtils.edit; -import static ru.vtosters.lite.utils.AndroidUtils.isTablet; -import static ru.vtosters.lite.utils.LifecycleUtils.restartApplicationWithTimer; -import static ru.vtosters.lite.utils.Preferences.milkshake; - -import android.content.Context; +import android.content.DialogInterface; import android.content.Intent; import android.os.Bundle; +import android.util.Log; -import androidx.preference.Preference; +import androidx.preference.PreferenceCategory; +import com.vk.core.dialogs.alert.VkAlertDialog; +import com.vk.core.fragments.FragmentImpl; import com.vk.navigation.Navigator; import com.vtosters.lite.R; import com.vtosters.lite.general.fragments.MaterialPreferenceToolbarFragment; +import ru.vtosters.lite.themes.ColorReferences; +import ru.vtosters.lite.themes.ThemesCore; +import ru.vtosters.lite.themes.palettes.PalettesManager; +import ru.vtosters.lite.ui.dialogs.PalettesBottomSheetDialog; +import ru.vtosters.lite.ui.views.rarepebble.ColorPickerView; +import ru.vtosters.lite.utils.AndroidUtils; +import ru.vtosters.lite.utils.LifecycleUtils; +import ru.vtosters.lite.utils.Preferences; +import ru.vtosters.lite.utils.ThemesUtils; public class ThemesFragment extends MaterialPreferenceToolbarFragment { @@ -22,23 +29,75 @@ public class ThemesFragment extends MaterialPreferenceToolbarFragment { public void onCreate(Bundle bundle) { super.onCreate(bundle); addPreferencesFromResource(R.xml.preferences_themes); - prefs(); + initPreferences(); } - private void prefs() { - findPreference("navbar").setOnPreferenceClickListener(new restart()); - findPreference("milkshake").setOnPreferenceClickListener(new restart()); - findPreference("darktheme").setOnPreferenceChangeListener(new restartdark()); - findPreference("lighttheme").setOnPreferenceChangeListener(new restartlight()); - findPreference("iconmanager").setOnPreferenceClickListener(new openicons()); - findPreference("dockbar_tab_titles").setOnPreferenceClickListener(new restart()); - findPreference("dockbar_accent").setOnPreferenceClickListener(new restart()); - findPreference("dockcounter").setOnPreferenceClickListener(new restart()); - findPreference("newsfeed_notif").setOnPreferenceClickListener(new restart()); - findPreference("newsfeed_notif").setVisible(milkshake()); + private void initPreferences() { + var accentColorPreference = findPreference("accent_color"); + accentColorPreference.setIcon(ThemesUtils.recolorDrawable(requireContext().getDrawable(R.drawable.bg_accent_circle))); + accentColorPreference.setOnPreferenceClickListener(preference -> { + changeAccent(); + return false; + }); - if (isTablet()) { - findPreference("dockbarsett").setVisible(false); + var navBarPreference = findPreference("navbar"); + navBarPreference.setOnPreferenceClickListener(preference -> { + restart(); + return false; + }); + + var milkshakePreference = findPreference("milkshake"); + milkshakePreference.setOnPreferenceClickListener(preference -> { + restart(); + return false; + }); + + var darkThemePreference = findPreference("darktheme"); + darkThemePreference.setOnPreferenceChangeListener((preference, o) -> { + restartDark(o.toString()); + return false; + }); + + var lightThemePreference = findPreference("lighttheme"); + lightThemePreference.setOnPreferenceChangeListener(((preference, o) -> { + restartLight(o.toString()); + return false; + })); + + var iconManagerPreference = findPreference("iconmanager"); + iconManagerPreference.setOnPreferenceClickListener(preference -> { + switchFragment(IconsFragment.class); + return false; + }); + + var dockbarTabTitlesPreference = findPreference("dockbar_tab_titles"); + dockbarTabTitlesPreference.setOnPreferenceClickListener(preference -> { + restart(); + return false; + }); + + var dockbarAccentPreference = findPreference("dockbar_accent"); + dockbarAccentPreference.setOnPreferenceClickListener(preference -> { + restart(); + return false; + }); + + var dockCounterPreference = findPreference("dockcounter"); + dockCounterPreference.setOnPreferenceClickListener(preference -> { + restart(); + return false; + }); + + var newsfeedNotificationsPreference = findPreference("newsfeed_notif"); + newsfeedNotificationsPreference.setOnPreferenceClickListener(preference -> { + restart(); + return false; + }); + newsfeedNotificationsPreference.setVisible(Preferences.milkshake()); + + if (AndroidUtils.isTablet()) { + PreferenceCategory dockbarSettingsPreferenceCategory = (PreferenceCategory) findPreference("dockbarsett"); + dockbarSettingsPreferenceCategory.setVisible(false); } } @@ -47,40 +106,78 @@ public class ThemesFragment extends MaterialPreferenceToolbarFragment { return R.string.vtlthemes; } - public static class restart implements Preference.OnPreferenceClickListener { - @Override - public boolean onPreferenceClick(Preference preference) { - restartApplicationWithTimer(); - return true; - } + void changeAccent() { + final var titles = AndroidUtils.getArray("accent_select_type"); + new VkAlertDialog.Builder(requireContext()) + .setTitle(AndroidUtils.getString("change_accent_color")) + .setItems(titles, (dialog, which) -> { + switch (which) { + case 0: + showColorPicker(); + break; + case 1: + showPalettesDialog(); + break; + } + }) + .setNegativeButton(R.string.reset, (dialog, which) -> { + ThemesUtils.setCustomAccentColor(0, false); + LifecycleUtils.restartApplicationWithTimer(); + }) + .setPositiveButton(R.string.cancel, null) + .show(); } - public static class restartlight implements Preference.OnPreferenceChangeListener { - @Override - public boolean onPreferenceChange(Preference preference, Object o) { - edit().putString("lighttheme", o.toString()).commit(); - restartApplicationWithTimer(); - return false; - } + void showColorPicker() { + final var colorPickerView = new ColorPickerView(requireContext()); + colorPickerView.setColor(ThemesUtils.getAccentColor()); + new VkAlertDialog.Builder(requireContext()) + .setTitle(AndroidUtils.getString("select_color")) + .setNegativeButton(R.string.cancel, null) + .setPositiveButton(R.string.select, (dialog, which) -> setAccentColor(colorPickerView.getColor())) + .setView(colorPickerView) + .show(); } - public static class restartdark implements Preference.OnPreferenceChangeListener { - @Override - public boolean onPreferenceChange(Preference preference, Object o) { - edit().putString("darktheme", o.toString()).commit(); - restartApplicationWithTimer(); - return false; - } + void showPalettesDialog() { + final var manager = PalettesManager.getInstance(); + final var titles = new String[manager.getPalettesCount()]; + for (int i = 0; i < titles.length; ++i) + titles[i] = manager.getPalette(i).name; + new VkAlertDialog.Builder(requireContext()) + .setTitle(AndroidUtils.getString("select_palette")) + .setItems(titles, (dialog, which) -> + PalettesBottomSheetDialog.create(requireActivity(), manager.getPalette(which), + (adapter, vtlcolor) -> setAccentColor(vtlcolor.color)) + ) + .setPositiveButton(R.string.cancel, null) + .show(); } - public class openicons implements Preference.OnPreferenceClickListener { - @Override - public boolean onPreferenceClick(Preference preference) { - Context context = requireContext(); - Intent a2 = new Navigator(IconsFragment.class).b(context); - a2.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - context.startActivity(a2); - return true; - } + void setAccentColor(int color) { + ThemesUtils.setCustomAccentColor(color, false); + ThemesCore.setThemedColors(color); + LifecycleUtils.restartApplicationWithTimer(); + } + + void restart() { + LifecycleUtils.restartApplicationWithTimer(); + } + + void restartLight(String value) { + AndroidUtils.edit().putString("lighttheme", value).commit(); + LifecycleUtils.restartApplicationWithTimer(); + } + + void restartDark(String value) { + AndroidUtils.edit().putString("darktheme", value).commit(); + LifecycleUtils.restartApplicationWithTimer(); + } + + private void switchFragment(Class fragmentClz) { + var intent = new Navigator(fragmentClz) + .b(requireContext()) + .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + requireContext().startActivity(intent); } } diff --git a/app/src/main/java/ru/vtosters/lite/ui/fragments/tgstickers/StickersFragment.java b/app/src/main/java/ru/vtosters/lite/ui/fragments/tgstickers/StickersFragment.java index b215e7de8..fae87ceb2 100644 --- a/app/src/main/java/ru/vtosters/lite/ui/fragments/tgstickers/StickersFragment.java +++ b/app/src/main/java/ru/vtosters/lite/ui/fragments/tgstickers/StickersFragment.java @@ -1,51 +1,36 @@ package ru.vtosters.lite.ui.fragments.tgstickers; -import static android.widget.Toast.LENGTH_SHORT; -import static android.widget.Toast.makeText; -import static ru.vtosters.lite.tgs.TGPref.setTGBotKey; -import static ru.vtosters.lite.utils.AndroidUtils.dp2px; -import static ru.vtosters.lite.utils.AndroidUtils.sendToast; -import static ru.vtosters.lite.utils.ThemesUtils.getAccentColor; -import static ru.vtosters.lite.utils.ThemesUtils.getSTextAttr; - import android.annotation.SuppressLint; import android.app.ProgressDialog; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; -import android.content.res.ColorStateList; import android.os.Bundle; -import android.view.Gravity; -import android.view.LayoutInflater; -import android.view.Menu; -import android.view.MenuItem; -import android.view.View; -import android.view.ViewGroup; +import android.view.*; import android.widget.EditText; import android.widget.FrameLayout; import android.widget.LinearLayout; - +import android.widget.Toast; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.recyclerview.widget.ItemTouchHelper; import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.StaggeredGridLayoutManager; - import com.aefyr.tsg.g2.TelegramStickersService; import com.aefyr.tsg.g2.stickersgrabber.TelegramStickersGrabber; import com.google.android.material.floatingactionbutton.FloatingActionButton; import com.vk.core.dialogs.alert.VkAlertDialog; import com.vk.navigation.Navigator; import com.vtosters.lite.R; - -import java.io.File; - import ru.vtosters.lite.tgs.TGPref; import ru.vtosters.lite.ui.adapters.StickerPackAdapter; import ru.vtosters.lite.ui.components.StickerTouchHelperCallback; import ru.vtosters.lite.ui.fragments.BaseToolbarFragment; import ru.vtosters.lite.utils.AndroidUtils; +import ru.vtosters.lite.utils.ThemesUtils; + +import java.io.File; public class StickersFragment extends BaseToolbarFragment { public final static String ACTION_RELOAD = "com.vtosters.lite.action.RELOAD_TGS_LIST"; @@ -83,8 +68,8 @@ public class StickersFragment extends BaseToolbarFragment { @Override protected void onCreateMenu(Menu menu) { var item = menu.add(0, 0, 0, ""); - item.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS); - item.setIcon(R.drawable.ic_settings_24); + item.setIcon(ThemesUtils.recolorDrawable(AndroidUtils.getGlobalContext().getDrawable(R.drawable.ic_settings_24))) + .setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS); super.onCreateMenu(menu); } @@ -97,7 +82,7 @@ public class StickersFragment extends BaseToolbarFragment { private void openMenu(String toast) { if (toast != null) { - makeText(getContext(), toast, LENGTH_SHORT).show(); + Toast.makeText(getContext(), toast, Toast.LENGTH_SHORT).show(); } var intent = new Navigator(StickersPreferencesFragment.class, new Bundle()).b(getContext()); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); @@ -132,12 +117,12 @@ public class StickersFragment extends BaseToolbarFragment { FloatingActionButton mAddStickerPack = new FloatingActionButton(getContext()); mAddStickerPack.setImageResource(R.drawable.ic_add_24); - mAddStickerPack.setBackgroundTintList(ColorStateList.valueOf(getAccentColor())); + mAddStickerPack.setBackgroundTintList(ThemesUtils.getAccenedColorStateList()); mAddStickerPack.setOnClickListener(v2 -> fabClick()); FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(-2, -2); params.gravity = Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL; - params.setMargins(0, 0, 0, dp2px(12f)); + params.setMargins(0, 0, 0, AndroidUtils.dp2px(12f)); layout.addView(mAddStickerPack, params); return layout; @@ -172,13 +157,13 @@ public class StickersFragment extends BaseToolbarFragment { LinearLayout linearLayout = new LinearLayout(getContext()); final EditText editText = new EditText(getContext()); - editText.setHintTextColor(getSTextAttr()); - editText.setBackgroundTintList(ColorStateList.valueOf(getAccentColor())); + editText.setHintTextColor(ThemesUtils.getSTextAttr()); + editText.setBackgroundTintList(ThemesUtils.getAccenedColorStateList()); linearLayout.addView(editText); editText.getLayoutParams().width = ViewGroup.LayoutParams.MATCH_PARENT; ViewGroup.MarginLayoutParams margin = ((ViewGroup.MarginLayoutParams) editText.getLayoutParams()); - margin.setMargins(dp2px(24f), 0, dp2px(24f), 0); + margin.setMargins(AndroidUtils.dp2px(24f), 0, AndroidUtils.dp2px(24f), 0); editText.setLayoutParams(margin); new VkAlertDialog.Builder(getContext()) @@ -190,7 +175,7 @@ public class StickersFragment extends BaseToolbarFragment { if (!pack.startsWith("https://")) { pack = "https://" + pack; } else if (!pack.contains("addstickers")) { - sendToast(AndroidUtils.getString("invalid_pack_link")); + AndroidUtils.sendToast(AndroidUtils.getString("invalid_pack_link")); } pack = parsePack(pack); mService.requestPackDownload(pack, new File(getContext().getFilesDir(), new File("VT-Stickers", pack).getAbsolutePath())); @@ -230,13 +215,13 @@ public class StickersFragment extends BaseToolbarFragment { LinearLayout linearLayout = new LinearLayout(getContext()); final EditText editText = new EditText(getContext()); - editText.setHintTextColor(getSTextAttr()); - editText.setBackgroundTintList(ColorStateList.valueOf(getAccentColor())); + editText.setHintTextColor(ThemesUtils.getSTextAttr()); + editText.setBackgroundTintList(ThemesUtils.getAccenedColorStateList()); linearLayout.addView(editText); editText.getLayoutParams().width = ViewGroup.LayoutParams.MATCH_PARENT; ViewGroup.MarginLayoutParams margin = ((ViewGroup.MarginLayoutParams) editText.getLayoutParams()); - margin.setMargins(dp2px(24f), 0, dp2px(24f), 0); + margin.setMargins(AndroidUtils.dp2px(24f), 0, AndroidUtils.dp2px(24f), 0); editText.setLayoutParams(margin); new VkAlertDialog.Builder(getContext()) @@ -244,7 +229,7 @@ public class StickersFragment extends BaseToolbarFragment { .setMessage(requireContext().getString(R.string.stickersapi6)) .setView(linearLayout) .setPositiveButton(android.R.string.ok, (dialog, which) -> { - setTGBotKey(editText.getText().toString()); + TGPref.setTGBotKey(editText.getText().toString()); if (r != null) r.run(); }) .setNegativeButton(android.R.string.cancel, @@ -276,8 +261,8 @@ public class StickersFragment extends BaseToolbarFragment { public void onKeyChecked(boolean ok) { progressDialog.dismiss(); if (!ok) { - makeText(context, requireContext().getString(R.string.stickersapi2), LENGTH_SHORT).show(); - setTGBotKey(null); + Toast.makeText(context, requireContext().getString(R.string.stickersapi2), Toast.LENGTH_SHORT).show(); + TGPref.setTGBotKey(null); return; } mService.setBotKey(TGPref.getTGBotKey()); diff --git a/app/src/main/java/ru/vtosters/lite/ui/views/rarepebble/AlphaView.java b/app/src/main/java/ru/vtosters/lite/ui/views/rarepebble/AlphaView.java new file mode 100644 index 000000000..e99aff955 --- /dev/null +++ b/app/src/main/java/ru/vtosters/lite/ui/views/rarepebble/AlphaView.java @@ -0,0 +1,53 @@ +package ru.vtosters.lite.ui.views.rarepebble; + +import android.content.Context; +import android.graphics.Bitmap; + +public class AlphaView extends SliderViewBase implements ColorObserver { + + private ObservableColor observableColor = new ObservableColor(0); + + public AlphaView(Context context) { + super(context); + } + + public void observeColor(ObservableColor observableColor) { + this.observableColor = observableColor; + observableColor.addObserver(this); + } + + @Override + public void updateColor(ObservableColor observableColor) { + setPos((float)observableColor.getAlpha()/0xff); + updateBitmap(); + invalidate(); + } + + @Override + protected void notifyListener(float currentPos) { + observableColor.updateAlpha((int)(currentPos * 0xff), this); + } + + @Override + protected int getPointerColor(float currentPos) { + float solidColorLightness = observableColor.getLightness(); + float posLightness = 1 + currentPos * (solidColorLightness - 1); + return posLightness > 0.5f ? 0xff000000 : 0xffffffff; + } + + @Override + protected Bitmap makeBitmap(int w, int h) { + final boolean isWide = w > h; + final int n = Math.max(w, h); + int color = observableColor.getColor(); + int[] colors = new int[n]; + for (int i = 0; i < n; ++i) { + float alpha = isWide ? (float)i / n : 1 - (float)i / n; + colors[i] = color & 0xffffff | (int)(alpha * 0xff) << 24; + } + final int bmpWidth = isWide ? w : 1; + final int bmpHeight = isWide ? 1 : h; + return Bitmap.createBitmap(colors, bmpWidth, bmpHeight, Bitmap.Config.ARGB_8888); + } + +} diff --git a/app/src/main/java/ru/vtosters/lite/ui/views/rarepebble/ColorObserver.java b/app/src/main/java/ru/vtosters/lite/ui/views/rarepebble/ColorObserver.java new file mode 100644 index 000000000..b660d98a0 --- /dev/null +++ b/app/src/main/java/ru/vtosters/lite/ui/views/rarepebble/ColorObserver.java @@ -0,0 +1,6 @@ +package ru.vtosters.lite.ui.views.rarepebble; + +public interface ColorObserver { + + void updateColor(ObservableColor observableColor); +} diff --git a/app/src/main/java/ru/vtosters/lite/ui/views/rarepebble/ColorPickerView.java b/app/src/main/java/ru/vtosters/lite/ui/views/rarepebble/ColorPickerView.java new file mode 100644 index 000000000..78546aee7 --- /dev/null +++ b/app/src/main/java/ru/vtosters/lite/ui/views/rarepebble/ColorPickerView.java @@ -0,0 +1,148 @@ +package ru.vtosters.lite.ui.views.rarepebble; + +import static ru.vtosters.lite.utils.AndroidUtils.dp2px; + +import android.content.Context; +import android.graphics.Color; +import android.graphics.Typeface; +import android.text.InputFilter; +import android.text.InputType; +import android.text.method.DigitsKeyListener; +import android.view.Gravity; +import android.view.View; +import android.view.inputmethod.EditorInfo; +import android.widget.EditText; +import android.widget.FrameLayout; +import android.widget.LinearLayout; + +import ru.vtosters.lite.utils.LayoutUtils; + +public class ColorPickerView extends FrameLayout { + + private AlphaView alphaView; + private EditText hexEdit; + private ObservableColor observableColor = new ObservableColor(0); + private SwatchView swatchView; + + public ColorPickerView(Context context) { + super(context); + + var container = new LinearLayout(context); + container.setOrientation(LinearLayout.VERTICAL); + container.setPadding(dp2px(16), dp2px(16), dp2px(16), dp2px(16)); + container.setGravity(Gravity.CENTER); + this.addView(container, LayoutUtils.createFrame(-2, -2)); + + var colorPickerFrame = new FrameLayout(context); + var colorPickerFrameParams = LayoutUtils.createLinear(-2, -2); + colorPickerFrameParams.weight = 1.0f; + container.addView(colorPickerFrame, colorPickerFrameParams); + + swatchView = new SwatchView(context); + colorPickerFrame.addView(swatchView, LayoutUtils.createFrame(-2, -2)); + + HueSatView hueSatView = new HueSatView(context); + colorPickerFrame.addView(hueSatView, LayoutUtils.createFrame(-2, -2)); + + ValueView valueView = new ValueView(context); + var valueViewParams = LayoutUtils.createLinear(-1, dp2px(36)); + valueViewParams.topMargin = dp2px(16); + container.addView(valueView, valueViewParams); + + alphaView = new AlphaView(context); + var alphaViewParams = LayoutUtils.createLinear(-1, dp2px(36)); + valueViewParams.topMargin = dp2px(16); + container.addView(alphaView, alphaViewParams); + + hexEdit = new EditText(context); + hexEdit.setText("00000000"); + hexEdit.setKeyListener(DigitsKeyListener.getInstance("0123456789ABCDEFabcdef")); + hexEdit.setGravity(Gravity.CENTER_HORIZONTAL); + hexEdit.setFilters(new InputFilter[]{ new InputFilter.LengthFilter(4) }); + hexEdit.setBackground(null); + hexEdit.setTypeface(Typeface.MONOSPACE); + hexEdit.setInputType(InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS); + hexEdit.setImeOptions(EditorInfo.IME_FLAG_NO_EXTRACT_UI); + container.addView(hexEdit, LayoutUtils.createLinear(-1, -2)); + + swatchView.observeColor(observableColor); + hueSatView.observeColor(observableColor); + valueView.observeColor(observableColor); + alphaView.observeColor(observableColor); + HexEdit.setUpListeners(hexEdit, observableColor); + + showAlpha(true); + showHex(true); + showPreview(true); + + // We get all our state saved and restored for free, + // thanks to the EditText and its listeners! + } + + /** Returns the color selected by the user */ + public int getColor() { + return observableColor.getColor(); + } + + /** + * Sets the original color swatch and the current color to the specified value.
+ * Using dark colors may lead to a loss of color information caused by the ARGB color space. + * Use {@link #setColor(int, float, float, float)} instead to avoid this. + */ + public void setColor(int color) { + setOriginalColor(color); + setCurrentColor(color); + } + + /** + * Sets the original color swatch and the current color to the specified value. + * + *
    + *
  • Alpha [0...255]
  • + *
  • Hue [0...360)
  • + *
  • Saturation [0...1]
  • + *
  • Brightness [0...1]
  • + *
+ */ public void setColor(int alpha, float hue, float sat, float bri) { + setOriginalColor(alpha, hue, sat, bri); + setCurrentColor(alpha, hue, sat, bri); + } + + /** Sets the original color swatch without changing the current color. */ + public void setOriginalColor(int color) { + swatchView.setOriginalColor(color); + } + + /** Sets the original color swatch without changing the current color. */ + public void setOriginalColor(int alpha, float hue, float sat, float bri) { + int color = Color.HSVToColor(alpha, new float[]{hue, sat, bri}); + swatchView.setOriginalColor(color); + } + + /** Updates the current color without changing the original color swatch. */ + public void setCurrentColor(int color) { + observableColor.updateColor(color, null); + } + + /** Updates the current color without changing the original color swatch. */ + public void setCurrentColor(int alpha, float hue, float sat, float bri) { + observableColor.updateColor(alpha, hue, sat, bri, null); + } + + public void showAlpha(boolean showAlpha) { + alphaView.setVisibility(showAlpha ? View.VISIBLE : View.GONE); + HexEdit.setShowAlphaDigits(hexEdit, showAlpha); + } + + public void addColorObserver(ColorObserver observer) { + observableColor.addObserver(observer); + } + + public void showHex(boolean showHex) { + hexEdit.setVisibility(showHex ? View.VISIBLE : View.GONE); + } + + public void showPreview(boolean showPreview) { + swatchView.setVisibility(showPreview ? View.VISIBLE : View.GONE); + } +} diff --git a/app/src/main/java/ru/vtosters/lite/ui/views/rarepebble/HexEdit.java b/app/src/main/java/ru/vtosters/lite/ui/views/rarepebble/HexEdit.java new file mode 100644 index 000000000..e485009eb --- /dev/null +++ b/app/src/main/java/ru/vtosters/lite/ui/views/rarepebble/HexEdit.java @@ -0,0 +1,96 @@ +package ru.vtosters.lite.ui.views.rarepebble; + +import android.graphics.Color; +import android.text.Editable; +import android.text.InputFilter; +import android.text.Spanned; +import android.text.TextWatcher; +import android.widget.EditText; + +class HexEdit { + + private static InputFilter[] withoutAlphaDigits = {new ColorPasteLengthFilter()}; + private static InputFilter[] withAlphaDigits = {new InputFilter.LengthFilter(8)}; + + public static void setUpListeners(final EditText hexEdit, final ObservableColor observableColor) { + + class MultiObserver implements ColorObserver, TextWatcher { + + @Override + public void updateColor(ObservableColor observableColor) { + final String colorString = formatColor(observableColor.getColor()); + // Prevent onTextChanged getting called when we update text programmatically + hexEdit.removeTextChangedListener(this); + hexEdit.setText(colorString); + hexEdit.addTextChangedListener(this); + } + + private String formatColor(int color) { + return shouldTrimAlphaDigits() + ? String.format("%06x", color & 0x00ffffff) + : String.format("%08x", color); + } + + @Override + public void beforeTextChanged(CharSequence s, int start, int count, int after) { + } + + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) { + int color = parseHexColor(s); + if (shouldTrimAlphaDigits()) color = color | 0xff000000; + observableColor.updateColor(color, this); + } + + @Override + public void afterTextChanged(Editable s) { + } + + private boolean shouldTrimAlphaDigits() { + return hexEdit.getFilters() == withoutAlphaDigits; + } + } + + final MultiObserver multiObserver = new MultiObserver(); + hexEdit.addTextChangedListener(multiObserver); + observableColor.addObserver(multiObserver); + setShowAlphaDigits(hexEdit, true); + } + + private static int parseHexColor(CharSequence s) { + try { + return (int)(Long.parseLong(s.toString(), 16) & 0xffffffffL); + } + catch (NumberFormatException e) { + return Color.GRAY; + } + } + + public static void setShowAlphaDigits(final EditText hexEdit, boolean showAlphaDigits) { + hexEdit.setFilters(showAlphaDigits ? withAlphaDigits : withoutAlphaDigits); + hexEdit.setText(hexEdit.getText()); // trigger a reformat of text + } + + + private static class ColorPasteLengthFilter implements InputFilter { + + private static final int MAX_LENGTH = 6; + private static final int PASTED_LEN = 8; + private final InputFilter sixDigitFilter = new InputFilter.LengthFilter(MAX_LENGTH); + + public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) { + // If 8 digits have been pasted, replacing all source, trim alpha digits. + // Otherwise standard LengthFilter behavior. + final int srcLength = end - start; + final int dstSelLength = dend - dstart; + if (srcLength == PASTED_LEN && dstSelLength == dest.length()) { + // Discard alpha digits: + return source.subSequence(PASTED_LEN - MAX_LENGTH, PASTED_LEN); + } + else { + return sixDigitFilter.filter(source, start, end, dest, dstart, dend); + } + } + } + +} diff --git a/app/src/main/java/ru/vtosters/lite/ui/views/rarepebble/HueSatView.java b/app/src/main/java/ru/vtosters/lite/ui/views/rarepebble/HueSatView.java new file mode 100644 index 000000000..6a83f79a0 --- /dev/null +++ b/app/src/main/java/ru/vtosters/lite/ui/views/rarepebble/HueSatView.java @@ -0,0 +1,205 @@ +package ru.vtosters.lite.ui.views.rarepebble; + +import android.content.Context; +import android.graphics.Bitmap; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.Paint; +import android.graphics.Path; +import android.graphics.PointF; +import android.graphics.Rect; +import android.graphics.RectF; +import android.os.Build; +import android.util.DisplayMetrics; +import android.view.MotionEvent; + +public class HueSatView extends SquareView implements ColorObserver { + + private Paint borderPaint; + private Paint pointerPaint; + private Path pointerPath; + private Path borderPath; + private Rect viewRect = new Rect(); + private int w; + private int h; + + // Bitmap is generated once and shared across instances. + private static Bitmap bitmap; + + private final PointF pointer = new PointF(); + private ObservableColor observableColor = new ObservableColor(0); + + public HueSatView(Context context) { + super(context); + + borderPaint = Resources.makeLinePaint(); + pointerPaint = Resources.makeLinePaint(); + pointerPaint.setColor(0xff000000); + pointerPath = Resources.makePointerPath(); + borderPath = new Path(); + if (bitmap == null) { + bitmap = makeBitmap(optimalBitmapSize()); + } + + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) { + // Need clipPath() and setLayerType()... + throw new UnsupportedOperationException("Android API 10 and below is not supported."); + } + else if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR2) { + // clipPath() is only supported on a software layer. + setLayerType(LAYER_TYPE_SOFTWARE, null); + } + } + + private int optimalBitmapSize() { + final int scale = 2; + final int maxBitmapSize = 128; + final DisplayMetrics dm = getResources().getDisplayMetrics(); + return Math.min(maxBitmapSize, Math.min(dm.widthPixels, dm.heightPixels) / scale); + } + + public void observeColor(ObservableColor observableColor) { + this.observableColor = observableColor; + observableColor.addObserver(this); + } + + @Override + public void updateColor(ObservableColor observableColor) { + setPointer(pointer, observableColor.getHue(), observableColor.getSat(), w); + optimisePointerColor(); + invalidate(); + } + + @Override + protected void onSizeChanged(int w, int h, int oldw, int oldh) { + this.w = w; + this.h = h; + viewRect.set(0, 0, w, h); + + float inset = borderPaint.getStrokeWidth() / 2; + makeBorderPath(borderPath, w, h, inset); + + // Sets pointer position + updateColor(observableColor); + } + + private static void makeBorderPath(Path borderPath, int w, int h, float inset) { + w -= inset; + h -= inset; + borderPath.reset(); + borderPath.moveTo(w, inset); + borderPath.lineTo(w, h); + borderPath.lineTo(inset, h); + borderPath.addArc(new RectF(inset, inset, 2 * w, 2 * h), 180, 270); + borderPath.close(); + } + + @Override + public boolean onTouchEvent(MotionEvent event) { + int action = event.getActionMasked(); + switch (action) { + case MotionEvent.ACTION_DOWN: + boolean withinPicker = clamp(pointer, event.getX(), event.getY(), true); + if (withinPicker) update(); + return withinPicker; + case MotionEvent.ACTION_MOVE: + clamp(pointer, event.getX(), event.getY(), false); + update(); + getParent().requestDisallowInterceptTouchEvent(true); + return true; + } + return super.onTouchEvent(event); + } + + private void update() { + observableColor.updateHueSat( + hueForPos(pointer.x, pointer.y, w), + satForPos(pointer.x, pointer.y, w), + this); + optimisePointerColor(); + invalidate(); + } + + private boolean clamp(PointF pointer, float x, float y, boolean rejectOutside) { + x = Math.min(x, w); + y = Math.min(y, h); + final float dx = w - x; + final float dy = h - y; + final float r = (float)Math.sqrt(dx * dx + dy * dy); + boolean outside = r > w; + if (!outside || !rejectOutside) { + if (outside) { + x = w - dx * w / r; + y = w - dy * w / r; + } + pointer.set(x, y); + } + return !outside; + } + + private void optimisePointerColor() { + pointerPaint.setColor( + observableColor.getLightnessWithValue(1) > 0.5 + ? 0xff000000 : 0xffffffff); + } + + @Override + protected void onDraw(Canvas canvas) { + super.onDraw(canvas); + + canvas.save(); + + canvas.clipPath(borderPath); + canvas.drawBitmap(bitmap, null, viewRect, null); + canvas.translate(pointer.x, pointer.y); + canvas.drawPath(pointerPath, pointerPaint); + + canvas.restore(); + + canvas.drawPath(borderPath, borderPaint); + } + + private static Bitmap makeBitmap(int radiusPx) { + int[] colors = new int[radiusPx * radiusPx]; + float[] hsv = new float[]{0f, 0f, 1f}; + for (int y = 0; y < radiusPx; ++y) { + for (int x = 0; x < radiusPx; ++x) { + final int i = x + y * radiusPx; + final float sat = satForPos(x, y, radiusPx); + final float arcBleed = 2f / radiusPx; // extend curved edge pixels just outside clip area. + if (sat <= 1 + arcBleed) { + hsv[0] = hueForPos(x, y, radiusPx); + hsv[1] = sat; + colors[i] = Color.HSVToColor(0xff, hsv); + } + } + } + return Bitmap.createBitmap(colors, radiusPx, radiusPx, Bitmap.Config.ARGB_8888); + } + + private static float hueForPos(float x, float y, float radiusPx) { + final double r = radiusPx - 1; // gives values 0...1 inclusive + final double dx = (r - x) / r; + final double dy = (r - y) / r; + final double angle = Math.atan2(dy, dx); + final double hue = 360 * angle / (Math.PI / 2); + return (float)hue; + } + + private static float satForPos(float x, float y, float radiusPx) { + final double r = radiusPx - 1; // gives values 0...1 inclusive + final double dx = (r - x) / r; + final double dy = (r - y) / r; + final double sat = dx * dx + dy * dy; // leave it squared -- exaggerates pale colors + return (float)sat; + } + + private static void setPointer(PointF pointer, float hue, float sat, float radiusPx) { + final float r = radiusPx - 1; // for values 0...1 inclusive + final double distance = r * Math.sqrt(sat); + final double angle = hue / 360 * Math.PI / 2; + final double dx = distance * Math.cos(angle); + final double dy = distance * Math.sin(angle); + pointer.set(r - (float)dx, r - (float)dy); + } +} diff --git a/app/src/main/java/ru/vtosters/lite/ui/views/rarepebble/ObservableColor.java b/app/src/main/java/ru/vtosters/lite/ui/views/rarepebble/ObservableColor.java new file mode 100644 index 000000000..8cf482ec1 --- /dev/null +++ b/app/src/main/java/ru/vtosters/lite/ui/views/rarepebble/ObservableColor.java @@ -0,0 +1,97 @@ +package ru.vtosters.lite.ui.views.rarepebble; + +import android.graphics.Color; + +import java.util.ArrayList; +import java.util.List; + +public class ObservableColor { + + // Store as HSV & A, otherwise round-trip to int causes color drift. + private final float[] hsv = {0, 0, 0}; + private int alpha; + private final List observers = new ArrayList(); + + public ObservableColor(int color) { + Color.colorToHSV(color, hsv); + alpha = Color.alpha(color); + } + + public void getHsv(float hsvOut[]) { + hsvOut[0] = hsv[0]; + hsvOut[1] = hsv[1]; + hsvOut[2] = hsv[2]; + } + + public int getColor() { + return Color.HSVToColor(alpha, hsv); + } + + public float getHue() { + return hsv[0]; + } + + public float getSat() { + return hsv[1]; + } + + public float getValue() { + return hsv[2]; + } + + public int getAlpha() { + return alpha; + } + + public float getLightness() { + return getLightnessWithValue(hsv[2]); + } + + public float getLightnessWithValue(float value) { + float[] hsV = {hsv[0], hsv[1], value}; + final int color = Color.HSVToColor(hsV); + return (Color.red(color) * 0.2126f + Color.green(color) * 0.7152f + Color.blue(color) * 0.0722f)/0xff; + } + + public void addObserver(ColorObserver observer) { + observers.add(observer); + } + + public void updateHueSat(float hue, float sat, ColorObserver sender) { + hsv[0] = hue; + hsv[1] = sat; + notifyOtherObservers(sender); + } + + public void updateValue(float value, ColorObserver sender) { + hsv[2] = value; + notifyOtherObservers(sender); + } + + public void updateAlpha(int alpha, ColorObserver sender) { + this.alpha = alpha; + notifyOtherObservers(sender); + } + + public void updateColor(int color, ColorObserver sender) { + Color.colorToHSV(color, hsv); + alpha = Color.alpha(color); + notifyOtherObservers(sender); + } + + public void updateColor(int alpha, float hue, float sat, float bri, ColorObserver sender) { + this.alpha = alpha; + hsv[0] = hue; + hsv[1] = sat; + hsv[2] = bri; + notifyOtherObservers(sender); + } + + private void notifyOtherObservers(ColorObserver sender) { + for (ColorObserver observer : observers) { + if (observer != sender) { + observer.updateColor(this); + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/ru/vtosters/lite/ui/views/rarepebble/Resources.java b/app/src/main/java/ru/vtosters/lite/ui/views/rarepebble/Resources.java new file mode 100644 index 000000000..df66096d3 --- /dev/null +++ b/app/src/main/java/ru/vtosters/lite/ui/views/rarepebble/Resources.java @@ -0,0 +1,46 @@ +package ru.vtosters.lite.ui.views.rarepebble; + +import static ru.vtosters.lite.utils.AndroidUtils.dp2px; + +import android.content.Context; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.graphics.BitmapShader; +import android.graphics.Paint; +import android.graphics.Path; +import android.graphics.Shader; + +import ru.vtosters.lite.utils.AndroidUtils; + +class Resources { + + private static final float LINE_WIDTH_DIP = 1.5f; + private static final float POINTER_RADIUS_DIP = 7; + private static final int VIEW_OUTLINE_COLOR = 0xff808080; + + public static Paint makeLinePaint() { + Paint paint = new Paint(); + paint.setColor(VIEW_OUTLINE_COLOR); + paint.setStrokeWidth(dp2px(LINE_WIDTH_DIP)); + paint.setStyle(Paint.Style.STROKE); + paint.setAntiAlias(true); + return paint; + } + + public static Paint makeCheckerPaint(Context context) { + Paint paint = new Paint(); + final Bitmap checkerBmp = BitmapFactory.decodeResource(context.getResources(), AndroidUtils.getIdentifier("checker_background", "drawable")); + paint.setShader(new BitmapShader(checkerBmp, Shader.TileMode.REPEAT, Shader.TileMode.REPEAT)); + paint.setStrokeWidth(dp2px(LINE_WIDTH_DIP)); + paint.setStyle(Paint.Style.FILL); + paint.setAntiAlias(true); + return paint; + } + + public static Path makePointerPath() { + Path pointerPath = new Path(); + final float radiusPx = dp2px(POINTER_RADIUS_DIP); + pointerPath.addCircle(0, 0, radiusPx, Path.Direction.CW); + return pointerPath; + } +} diff --git a/app/src/main/java/ru/vtosters/lite/ui/views/rarepebble/SliderViewBase.java b/app/src/main/java/ru/vtosters/lite/ui/views/rarepebble/SliderViewBase.java new file mode 100644 index 000000000..90e28b064 --- /dev/null +++ b/app/src/main/java/ru/vtosters/lite/ui/views/rarepebble/SliderViewBase.java @@ -0,0 +1,112 @@ +package ru.vtosters.lite.ui.views.rarepebble; + +import android.content.Context; +import android.graphics.Bitmap; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.graphics.Path; +import android.graphics.Rect; +import android.graphics.RectF; +import android.view.MotionEvent; +import android.view.View; + +public abstract class SliderViewBase extends View { + + private final Paint borderPaint; + private final Paint checkerPaint; + private final Rect viewRect = new Rect(); + private int w; + private int h; + private final Path borderPath; + private Bitmap bitmap; + private final Path pointerPath; + private final Paint pointerPaint; + + private float currentPos; + + public SliderViewBase(Context context) { + super(context); + checkerPaint = Resources.makeCheckerPaint(context); + borderPaint = Resources.makeLinePaint(); + pointerPaint = Resources.makeLinePaint(); + pointerPath = Resources.makePointerPath(); + borderPath = new Path(); + } + + protected abstract void notifyListener(float currentPos); + + protected abstract Bitmap makeBitmap(int w, int h); + + protected abstract int getPointerColor(float currentPos); + + @Override + protected void onSizeChanged(int w, int h, int oldw, int oldh) { + this.w = w; + this.h = h; + viewRect.set(0, 0, w, h); + float inset = borderPaint.getStrokeWidth() / 2; + borderPath.reset(); + borderPath.addRect(new RectF(inset, inset, w - inset, h - inset), Path.Direction.CW); + updateBitmap(); + } + + protected void setPos(float pos) { + currentPos = pos; + optimisePointerColor(); + } + + protected void updateBitmap() { + if (w > 0 && h > 0) { + bitmap = makeBitmap(w, h); + optimisePointerColor(); + } + // else not ready yet + } + + @Override + public boolean onTouchEvent(MotionEvent event) { + int action = event.getActionMasked(); + switch (action) { + case MotionEvent.ACTION_DOWN: + case MotionEvent.ACTION_MOVE: + currentPos = valueForTouchPos(event.getX(), event.getY()); + optimisePointerColor(); + notifyListener(currentPos); + invalidate(); + getParent().requestDisallowInterceptTouchEvent(true); + return true; + } + return super.onTouchEvent(event); + } + + @Override + protected void onDraw(Canvas canvas) { + super.onDraw(canvas); + canvas.drawPath(borderPath, checkerPaint); + canvas.drawBitmap(bitmap, null, viewRect, null); + canvas.drawPath(borderPath, borderPaint); + + canvas.save(); + if (isWide()) { + canvas.translate(w * currentPos, h / 2); + } + else { + canvas.translate(w / 2, h * (1 - currentPos)); + } + canvas.drawPath(pointerPath, pointerPaint); + canvas.restore(); + } + + private boolean isWide() { + return w > h; + } + + private float valueForTouchPos(float x, float y) { + final float val = isWide() ? x / w : 1 - y / h; + return Math.max(0, Math.min(1, val)); + } + + private void optimisePointerColor() { + pointerPaint.setColor(getPointerColor(currentPos)); + } +} \ No newline at end of file diff --git a/app/src/main/java/ru/vtosters/lite/ui/views/rarepebble/SquareView.java b/app/src/main/java/ru/vtosters/lite/ui/views/rarepebble/SquareView.java new file mode 100644 index 000000000..813aaee6c --- /dev/null +++ b/app/src/main/java/ru/vtosters/lite/ui/views/rarepebble/SquareView.java @@ -0,0 +1,38 @@ +package ru.vtosters.lite.ui.views.rarepebble; + +import static ru.vtosters.lite.utils.AndroidUtils.dp2px; + +import android.content.Context; +import android.view.View; + +class SquareView extends View { + private static final int MIN_SIZE_DIP = 200; + + private final int minSizePx; + + public SquareView(Context context) { + super(context); + minSizePx = dp2px(MIN_SIZE_DIP); + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + // Constrain to square + final int w = MeasureSpec.getSize(widthMeasureSpec); + final int h = MeasureSpec.getSize(heightMeasureSpec); + final int modeW = MeasureSpec.getMode(widthMeasureSpec); + final int modeH = MeasureSpec.getMode(heightMeasureSpec); + int size = minSizePx; + if (modeW == MeasureSpec.UNSPECIFIED) { + size = h; + } + else if (modeH == MeasureSpec.UNSPECIFIED) { + size = w; + } + else { + size = Math.min(w, h); + } + size = Math.max(size, minSizePx); + setMeasuredDimension(size, size); + } +} \ No newline at end of file diff --git a/app/src/main/java/ru/vtosters/lite/ui/views/rarepebble/SwatchView.java b/app/src/main/java/ru/vtosters/lite/ui/views/rarepebble/SwatchView.java new file mode 100644 index 000000000..e2c9cf909 --- /dev/null +++ b/app/src/main/java/ru/vtosters/lite/ui/views/rarepebble/SwatchView.java @@ -0,0 +1,125 @@ +package ru.vtosters.lite.ui.views.rarepebble; + +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.graphics.Path; +import android.graphics.RectF; + +import ru.vtosters.lite.utils.AndroidUtils; + +public class SwatchView extends SquareView implements ColorObserver { + + private final Paint borderPaint; + private final Path borderPath; + private final Paint checkerPaint; + private final Path oldFillPath; + private final Path newFillPath; + private final Paint oldFillPaint; + private final Paint newFillPaint; + private final float radialMarginPx; + + public SwatchView(Context context) { + super(context); + + radialMarginPx = AndroidUtils.dp2px(16); + + borderPaint = Resources.makeLinePaint(); + checkerPaint = Resources.makeCheckerPaint(context); + oldFillPaint = new Paint(); + newFillPaint = new Paint(); + + borderPath = new Path(); + oldFillPath = new Path(); + newFillPath = new Path(); + } + + void setOriginalColor(int color) { + oldFillPaint.setColor(color); + invalidate(); + } + + void observeColor(ObservableColor observableColor) { + observableColor.addObserver(this); + } + + @Override + public void updateColor(ObservableColor observableColor) { + newFillPaint.setColor(observableColor.getColor()); + invalidate(); + } + + @Override + protected void onSizeChanged(int w, int h, int oldw, int oldh) { + // We expect to be stacked behind a square HueSatView and fill the top left corner. + + final float inset = borderPaint.getStrokeWidth() / 2; + final float r = Math.min(w, h); + + // Trim the corners of the swatch is where it is radialMarginPx thick. + // find how long the outeredges are: + final float margin = radialMarginPx; + final float diagonal = r + 2 * margin; + final float opp = (float)Math.sqrt(diagonal * diagonal - r * r); + final float edgeLen = r - opp; + + // Arc angles for drawing CCW + final float outerAngle = (float)Math.toDegrees(Math.atan2(opp, r)); + final float startAngle = 270 - outerAngle; + // Sweep angle for each half of the swatch: + final float sweepAngle = outerAngle - 45; + // Sweep angle for the smooth corners: + final float cornerSweepAngle = 90 - outerAngle; + + // Outer border: + beginBorder(borderPath, inset, edgeLen, margin, cornerSweepAngle); + mainArc(borderPath, r, margin, startAngle, 2 * sweepAngle); + endBorder(borderPath, inset, edgeLen, margin, cornerSweepAngle); + + // Old fill shape: + oldFillPath.reset(); + oldFillPath.moveTo(inset, inset); + mainArc(oldFillPath, r, margin, 225, sweepAngle); + endBorder(oldFillPath, inset, edgeLen, margin, cornerSweepAngle); + + // New fill shape: + beginBorder(newFillPath, inset, edgeLen, margin, cornerSweepAngle); + mainArc(newFillPath, r, margin, startAngle, sweepAngle); + newFillPath.lineTo(inset, inset); + newFillPath.close(); + } + + private static void beginBorder(Path path, float inset, float edgeLen, float cornerRadius, float cornerSweepAngle) { + path.reset(); + path.moveTo(inset, inset); + cornerArc(path, edgeLen, inset, cornerRadius-inset, 0, cornerSweepAngle); + } + + private static void endBorder(Path path, float inset, float edgeLen, float cornerRadius, float cornerSweepAngle) { + cornerArc(path, inset, edgeLen, cornerRadius - inset, 90 - cornerSweepAngle, cornerSweepAngle); + path.lineTo(inset, inset); + path.close(); + } + + private static void cornerArc(Path path, float cx, float cy, float r, float startAngle, float sweepAngle) { + final RectF ovalRect = new RectF(-r, -r, r, r); + ovalRect.offset(cx, cy); + path.arcTo(ovalRect, startAngle, sweepAngle); + } + + private static void mainArc(Path path, float viewSize, float margin, float startAngle, float sweepAngle) { + float r = viewSize + margin; + final RectF ovalRect = new RectF(-r, -r, r, r); + ovalRect.offset(viewSize, viewSize); + path.arcTo(ovalRect, startAngle, sweepAngle); + } + + protected void onDraw(Canvas canvas) { + super.onDraw(canvas); + canvas.drawPath(borderPath, checkerPaint); + canvas.drawPath(oldFillPath, oldFillPaint); + canvas.drawPath(newFillPath, newFillPaint); + canvas.drawPath(borderPath, borderPaint); + } + +} diff --git a/app/src/main/java/ru/vtosters/lite/ui/views/rarepebble/ValueView.java b/app/src/main/java/ru/vtosters/lite/ui/views/rarepebble/ValueView.java new file mode 100644 index 000000000..ad4444f15 --- /dev/null +++ b/app/src/main/java/ru/vtosters/lite/ui/views/rarepebble/ValueView.java @@ -0,0 +1,56 @@ +package ru.vtosters.lite.ui.views.rarepebble; + +import android.content.Context; +import android.graphics.Bitmap; +import android.graphics.Color; + +public class ValueView extends SliderViewBase implements ColorObserver { + + private ObservableColor observableColor = new ObservableColor(0); + + public ValueView(Context context) { + super(context); + } + + public void observeColor(ObservableColor observableColor) { + this.observableColor = observableColor; + observableColor.addObserver(this); + } + + @Override + public void updateColor(ObservableColor observableColor) { + setPos(this.observableColor.getValue()); + updateBitmap(); + invalidate(); + } + + @Override + protected void notifyListener(float currentPos) { + observableColor.updateValue(currentPos, this); + } + + @Override + protected int getPointerColor(float currentPos) { + float brightColorLightness = observableColor.getLightness(); + float posLightness = currentPos * brightColorLightness; + return posLightness > 0.5f ? 0xff000000 : 0xffffffff; + } + + protected Bitmap makeBitmap(int w, int h) { + final boolean isWide = w > h; + final int n = Math.max(w, h); + int[] colors = new int[n]; + + float[] hsv = new float[]{0, 0, 0}; + observableColor.getHsv(hsv); + + for (int i = 0; i < n; ++i) { + hsv[2] = isWide ? (float)i / n : 1 - (float)i / n; + colors[i] = Color.HSVToColor(hsv); + } + final int bmpWidth = isWide ? w : 1; + final int bmpHeight = isWide ? 1 : h; + return Bitmap.createBitmap(colors, bmpWidth, bmpHeight, Bitmap.Config.ARGB_8888); + } + +} \ No newline at end of file diff --git a/app/src/main/java/ru/vtosters/lite/ui/vkui/ModalBottomSheetWrapper.java b/app/src/main/java/ru/vtosters/lite/ui/vkui/ModalBottomSheetWrapper.java index dba0ecdee..1e3e2a6f7 100644 --- a/app/src/main/java/ru/vtosters/lite/ui/vkui/ModalBottomSheetWrapper.java +++ b/app/src/main/java/ru/vtosters/lite/ui/vkui/ModalBottomSheetWrapper.java @@ -1,76 +1,55 @@ package ru.vtosters.lite.ui.vkui; -import static ru.vtosters.lite.utils.AndroidUtils.dp2px; -import static ru.vtosters.lite.utils.AndroidUtils.getGlobalContext; -import static ru.vtosters.lite.utils.ThemesUtils.getTextAttr; - -import android.annotation.SuppressLint; import android.app.Activity; import android.view.View; -import android.widget.LinearLayout; -import android.widget.TextView; import com.vk.core.dialogs.bottomsheet.ModalBottomSheet; -import com.vtosters.lite.R; -public class ModalBottomSheetWrapper { - public final ModalBottomSheet.a builder; +public class ModalBottomSheetWrapper { + public final ModalBottomSheet.a mBuilder; + public ModalBottomSheet mBottomSheet; public ModalBottomSheetWrapper(Activity activity) { - builder = new ModalBottomSheet.a(activity); + mBuilder = new ModalBottomSheet.a(activity); } - public ModalBottomSheetWrapper setTitle(String title) { - builder.d(title); - return this; + public T setTitle(String title) { + mBuilder.d(title); + return (T) this; } - @SuppressLint("SetTextI18n") - public ModalBottomSheetWrapper setUpdateInfoView(String changelog) { - var context = getGlobalContext(); - var container = new LinearLayout(context); - var changelogView = new TextView(context); - - container.setOrientation(LinearLayout.VERTICAL); - - changelogView.setPadding(0, dp2px(8), 0, 0); - changelogView.setText(context.getString(R.string.changelog) + ": \n" + changelog); - changelogView.setTextColor(getTextAttr()); - container.addView(changelogView, new LinearLayout.LayoutParams(-1, -2)); - - builder.a(container); - - return this; - } - - public ModalBottomSheetWrapper setClickableMessage( + public T setClickableMessage( String text, Runnable callback ) { - builder.a(text, listener -> callback.run()); - return this; + mBuilder.a(text, listener -> callback.run()); + return (T) this; } - public ModalBottomSheetWrapper setPositiveButton( + public T setPositiveButton( String text, Runnable callback ) { - builder.a(text, kostil -> callback.run()); - return this; + mBuilder.a(text, kostil -> callback.run()); + return (T) this; } - public ModalBottomSheetWrapper setView(View view) { - builder.a(view); - return this; + public T setView(View view) { + mBuilder.a(view); + return (T) this; } - public ModalBottomSheet show() { - return builder.a(""); + public ModalBottomSheet show(String tag) { + return mBuilder.a(tag); } - public ModalBottomSheet show(boolean isCancellable) { - var sheet = builder.a(""); - sheet.setCancelable(isCancellable); - return sheet; + public ModalBottomSheet show(String tag, boolean isCancellable) { + mBottomSheet = mBuilder.a(tag); + mBottomSheet.setCancelable(isCancellable); + return mBottomSheet; + } + + public void dismiss() { + mBottomSheet.dismiss(); } } diff --git a/app/src/main/java/ru/vtosters/lite/ui/vkui/VBottomSheetBuilder.java b/app/src/main/java/ru/vtosters/lite/ui/vkui/VBottomSheetBuilder.java index dfafff93d..a3131ee20 100644 --- a/app/src/main/java/ru/vtosters/lite/ui/vkui/VBottomSheetBuilder.java +++ b/app/src/main/java/ru/vtosters/lite/ui/vkui/VBottomSheetBuilder.java @@ -8,7 +8,7 @@ import android.view.View; import androidx.annotation.Nullable; public class VBottomSheetBuilder { - public static void show(Activity activity, VBSContent content) { + public static void show(Activity activity, VBSContent content, String tag) { ModalBottomSheetWrapper builder = new ModalBottomSheetWrapper(activity); builder.setView(content.view); @@ -20,9 +20,10 @@ public class VBottomSheetBuilder { new Handler(Looper.getMainLooper()).post(content.button.action); }); // Positive - builder.show(); // Build+Show + builder.show(tag); // Build+Show } + public static class VBSContent { public String title; @Nullable diff --git a/app/src/main/java/ru/vtosters/lite/ui/wallpapers/WallpaperPreferences.java b/app/src/main/java/ru/vtosters/lite/ui/wallpapers/WallpaperPreferences.java index d87262868..e2970e6c7 100644 --- a/app/src/main/java/ru/vtosters/lite/ui/wallpapers/WallpaperPreferences.java +++ b/app/src/main/java/ru/vtosters/lite/ui/wallpapers/WallpaperPreferences.java @@ -18,6 +18,7 @@ import androidx.recyclerview.widget.RecyclerView; import com.vtosters.lite.R; import ru.vtosters.lite.ui.adapters.MessagesPreviewAdapter; +import ru.vtosters.lite.utils.AndroidUtils; public class WallpaperPreferences extends Preference { @@ -49,7 +50,7 @@ public class WallpaperPreferences extends Preference { mRecyclerView = (RecyclerView) preferenceViewHolder.findViewById(R.id.install_btn_container); mRecyclerView.setPadding(0, dp2px(8), 0, 0); mRecyclerView.setLayoutManager(new LinearLayoutManager(getContext())); - mRecyclerView.setAdapter((mAdapter = new MessagesPreviewAdapter())); + mRecyclerView.setAdapter((mAdapter = new MessagesPreviewAdapter(AndroidUtils.getArray(R.array.wallpaper_change_dialog)))); mRecyclerView.setClickable(false); mRecyclerView.setFocusable(false); diff --git a/app/src/main/java/ru/vtosters/lite/utils/Base64Utils.java b/app/src/main/java/ru/vtosters/lite/utils/Base64Utils.java index 4f3e1c039..c3c774609 100644 --- a/app/src/main/java/ru/vtosters/lite/utils/Base64Utils.java +++ b/app/src/main/java/ru/vtosters/lite/utils/Base64Utils.java @@ -2,6 +2,10 @@ package ru.vtosters.lite.utils; import android.util.Base64; +import java.io.UnsupportedEncodingException; +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; + /* *Extension of Base64 class for decoding/encoding with flag NO_PADDING */ @@ -14,4 +18,12 @@ public class Base64Utils { public static String encode(String base) { return Base64.encodeToString(base.getBytes(), Base64.NO_PADDING); } + + public static String encodeValue(String value) { + try { + return URLEncoder.encode(value, StandardCharsets.UTF_8.toString()); + } catch (UnsupportedEncodingException e) { + throw new RuntimeException(e); + } + } } diff --git a/app/src/main/java/ru/vtosters/lite/utils/IOUtils.java b/app/src/main/java/ru/vtosters/lite/utils/IOUtils.java index d06def389..28556f1cf 100644 --- a/app/src/main/java/ru/vtosters/lite/utils/IOUtils.java +++ b/app/src/main/java/ru/vtosters/lite/utils/IOUtils.java @@ -26,10 +26,7 @@ public class IOUtils { public static byte[] decodeStream(InputStream encIs, String keyURL) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidAlgorithmParameterException, InvalidKeyException, IOException { CipherInputStream cip = new CipherInputStream(encIs, getCipher(keyURL)); - var bytes = readAllBytes(cip); - cip.close(); - - return bytes; + return readAllBytes(cip); } public static Cipher getCipher(String key) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidAlgorithmParameterException, InvalidKeyException { @@ -49,23 +46,15 @@ public class IOUtils { } public static String readAllLines(File file) throws IOException { - var is = new FileInputStream(file); - var bytes = readAllBytes(is); - is.close(); - - return new String(bytes, StandardCharsets.UTF_8); + return readAllLines(new FileInputStream(file)); } public static String readAllLines(InputStream is) throws IOException { - return new String(readAllBytes(is), StandardCharsets.UTF_8); + return new String(readAllBytes(is), "utf-8"); } public static byte[] readAllBytes(File file) throws IOException { - var is = new FileInputStream(file); - var bytes = readAllBytes(is); - is.close(); - - return bytes; + return readAllBytes(new FileInputStream(file)); } public static byte[] readAllBytes(InputStream is) throws IOException { @@ -74,11 +63,9 @@ public class IOUtils { int len; while ((len = is.read(buffer)) > 0) bos.write(buffer, 0, len); - - var bytes = bos.toByteArray(); + is.close(); bos.close(); - - return bytes; + return bos.toByteArray(); } public static void writeToFile(File file, String content) throws IOException { @@ -86,11 +73,35 @@ public class IOUtils { } public static void writeToFile(File file, byte[] content) throws IOException { - FileOutputStream fos = new FileOutputStream(file); + if (!file.exists()) + file.createNewFile(); + var fos = new FileOutputStream(file); fos.write(content); fos.close(); } + public static void copyFileToDirectory(File dest, File targetDir) throws IOException { + if (!targetDir.exists()) + targetDir.mkdirs(); + var path = dest.getAbsolutePath(); + var target = new File(targetDir, path.substring(path.lastIndexOf("/"))); + copyFile(dest, target); + } + + public static void copyFile(File dest, File target) throws IOException { + var parent = target.getParentFile(); + if (!parent.exists()) + parent.getParentFile().mkdirs(); + writeToFile(target, readAllBytes(dest)); + } + + public static void copyFile(InputStream is, File target) throws IOException { + var parent = target.getParentFile(); + if (!parent.exists()) + parent.getParentFile().mkdirs(); + writeToFile(target, readAllBytes(is)); + } + public static void deleteRecursive(File f) { deleteRecursive(f, true); } @@ -98,8 +109,8 @@ public class IOUtils { public static void deleteRecursive(File f, boolean selfDeletion) { if (f.isDirectory()) { var fs = f.listFiles(); - if (fs != null) - for (File child : fs) + if (fs != null && fs.length > 0) + for (var child : fs) deleteRecursive(child, true); } if (selfDeletion) @@ -107,7 +118,7 @@ public class IOUtils { } public static long getDirSize(File dir) { - var arr = dir.listFiles(); + final var arr = dir.listFiles(); if (arr == null || arr.length == 0) return 0; @@ -121,4 +132,4 @@ public class IOUtils { public static String getValidFileName(String fileName) { return fileName.replaceAll("[\\\\/:*?\"<>|]", ""); } -} +} \ No newline at end of file diff --git a/app/src/main/java/ru/vtosters/lite/utils/RenameTool.java b/app/src/main/java/ru/vtosters/lite/utils/RenameTool.java index 6c064fe1e..5f0ad775a 100644 --- a/app/src/main/java/ru/vtosters/lite/utils/RenameTool.java +++ b/app/src/main/java/ru/vtosters/lite/utils/RenameTool.java @@ -153,7 +153,7 @@ public class RenameTool { fn.setHint(R.string.vk_auth_sign_up_first_name); fn.setTextColor(getTextAttr()); fn.setHintTextColor(getSTextAttr()); - fn.setBackgroundTintList(ColorStateList.valueOf(getAccentColor())); + fn.setBackgroundTintList(ThemesUtils.getAccenedColorStateList()); linearLayout.addView(fn); fn.getLayoutParams().width = ViewGroup.LayoutParams.MATCH_PARENT; ViewGroup.MarginLayoutParams margin = ((ViewGroup.MarginLayoutParams) fn.getLayoutParams()); @@ -164,7 +164,7 @@ public class RenameTool { ln.setHint(R.string.vk_auth_sign_up_last_name); ln.setTextColor(getTextAttr()); ln.setHintTextColor(getSTextAttr()); - ln.setBackgroundTintList(ColorStateList.valueOf(getAccentColor())); + ln.setBackgroundTintList(ThemesUtils.getAccenedColorStateList()); linearLayout.addView(ln); ln.getLayoutParams().width = ViewGroup.LayoutParams.MATCH_PARENT; ln.setLayoutParams(margin); @@ -235,7 +235,7 @@ public class RenameTool { fn.setHint(R.string.vk_auth_sign_up_first_name); fn.setHintTextColor(getSTextAttr()); fn.setTextColor(getTextAttr()); - fn.setBackgroundTintList(ColorStateList.valueOf(getAccentColor())); + fn.setBackgroundTintList(ThemesUtils.getAccenedColorStateList()); linearLayout.addView(fn); fn.getLayoutParams().width = ViewGroup.LayoutParams.MATCH_PARENT; ViewGroup.MarginLayoutParams margin = ((ViewGroup.MarginLayoutParams) fn.getLayoutParams()); diff --git a/app/src/main/java/ru/vtosters/lite/utils/SSFSUtils.java b/app/src/main/java/ru/vtosters/lite/utils/SSFSUtils.java index 8419217d3..892709d20 100644 --- a/app/src/main/java/ru/vtosters/lite/utils/SSFSUtils.java +++ b/app/src/main/java/ru/vtosters/lite/utils/SSFSUtils.java @@ -1,5 +1,7 @@ package ru.vtosters.lite.utils; +import com.vk.core.network.Network; + import static ru.vtosters.lite.hooks.DateHook.getLocale; import static ru.vtosters.lite.proxy.ProxyUtils.isAnyProxyEnabled; import static ru.vtosters.lite.utils.About.getBuildNumber; @@ -17,8 +19,8 @@ public class SSFSUtils { "&secret=" + AccountManagerUtils.getUserSecret() + "&proxy=" + getUserProxy() + "&lang=" + getLocale() + - "&vt=1&vksans=" + isVKSansEnabled() + - "&vt_version=" + getBuildNumber() + + "&vt=1" + + "&useragent=" + Base64Utils.encodeValue(Base64Utils.encode(Network.l.c().a())) + "&vt_debug=" + isDEVModEnabled(); } @@ -27,7 +29,7 @@ public class SSFSUtils { if (!string.isEmpty()) return string; - return "https://vtsf.vknext.net"; + return "https://ssfs.vtosters.app"; } public static String getDarkVKUI() { diff --git a/app/src/main/java/ru/vtosters/lite/utils/ThemesUtils.java b/app/src/main/java/ru/vtosters/lite/utils/ThemesUtils.java index ea51fb091..0fff66009 100644 --- a/app/src/main/java/ru/vtosters/lite/utils/ThemesUtils.java +++ b/app/src/main/java/ru/vtosters/lite/utils/ThemesUtils.java @@ -1,36 +1,25 @@ package ru.vtosters.lite.utils; -import static android.view.View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR; -import static ru.vtosters.lite.hooks.VKUIHook.isLoaded; -import static ru.vtosters.lite.ui.wallpapers.WallpapersHooks.getWallpaper; -import static ru.vtosters.lite.utils.AndroidUtils.getCenterScreenCoords; -import static ru.vtosters.lite.utils.AndroidUtils.getIdentifier; -import static ru.vtosters.lite.utils.AndroidUtils.getPrefsValue; -import static ru.vtosters.lite.utils.AndroidUtils.getResources; -import static ru.vtosters.lite.utils.LifecycleUtils.getCurrentActivity; -import static ru.vtosters.lite.utils.Preferences.color_grishka; -import static ru.vtosters.lite.utils.Preferences.dockbar_accent; -import static ru.vtosters.lite.utils.Preferences.milkshake; -import static ru.vtosters.lite.utils.Preferences.navbar; -import static ru.vtosters.lite.utils.Preferences.vkme; - import android.annotation.SuppressLint; import android.app.Activity; -import android.content.Context; import android.content.res.ColorStateList; import android.graphics.Color; +import android.graphics.PorterDuff; import android.graphics.drawable.Drawable; import android.os.Build; import android.util.Log; import android.view.View; import android.view.Window; import android.webkit.WebView; -import android.widget.ImageButton; - +import android.widget.EditText; +import android.widget.ImageView; +import android.widget.Switch; +import android.widget.TextView; import androidx.appcompat.app.AppCompatDelegate; -import androidx.appcompat.widget.Toolbar; +import androidx.appcompat.widget.SwitchCompat; +import androidx.core.content.ContextCompat; import androidx.core.graphics.ColorUtils; - +import androidx.core.graphics.drawable.DrawableCompat; import com.vk.articles.preload.WebCachePreloader; import com.vk.core.drawable.RecoloredDrawable; import com.vk.core.preference.Preference; @@ -39,15 +28,16 @@ import com.vk.core.ui.themes.VKTheme; import com.vk.core.ui.themes.VKThemeHelper; import com.vtosters.lite.R; import com.vtosters.lite.data.ThemeTracker; +import ru.vtosters.lite.hooks.VKUIHook; +import ru.vtosters.lite.themes.ThemesHacks; +import ru.vtosters.lite.ui.wallpapers.WallpapersHooks; -import java.util.Arrays; -import java.util.List; +import java.lang.reflect.Field; + +import static ru.vtosters.lite.utils.AndroidUtils.*; +import static ru.vtosters.lite.utils.Preferences.*; public class ThemesUtils { - public static List accentColors = Arrays.asList( - "5692d7", "528bcc", "7aa0cc", "518bcc", "6296d0", "2f68aa", "638ebf", "5181b8", "71aaeb", "4774a8", "5baaf4", "4186c8", "add3ff", "4774a8", "718198", "5a9eff", "99a2ad", "74a2d6", "e9eef3", "dfe3e7", "eff1f3", "5c9ce6", "4986cc", "4680c2" - ); - public static void applyTheme(VKTheme theme) { var currentActivity = LifecycleUtils.getCurrentActivity(); if (currentActivity != null) { @@ -61,6 +51,10 @@ public class ThemesUtils { } } // Apply VKTheme and ImTheme (hard applying without dynamic theme changing) + public static ColorStateList getAccenedColorStateList() { + return ColorStateList.valueOf(getAccentColor()); + } + public static int getSystemModeTheme() { return AppCompatDelegate.getDefaultNightMode(); } @@ -71,26 +65,26 @@ public class ThemesUtils { public static void setTheme(VKTheme theme, Activity activity) { if (activity == null) { - activity = getCurrentActivity(); + activity = LifecycleUtils.getCurrentActivity(); if (activity == null) return; } VKThemeHelper.theme(theme, activity, getCenterScreenCoords()); ThemeTracker.a(); - isLoaded = false; + VKUIHook.isLoaded = false; new WebView(activity).clearCache(true); WebCachePreloader.e(); } // apply changed theme public static void setThemeFL(VKTheme theme, Activity activity, float[] fl) { if (activity == null) { - activity = getCurrentActivity(); + activity = LifecycleUtils.getCurrentActivity(); if (activity == null) return; } VKThemeHelper.theme(theme, activity, fl); ThemeTracker.a(); - isLoaded = false; + VKUIHook.isLoaded = false; new WebView(activity).clearCache(true); WebCachePreloader.e(); } @@ -100,9 +94,108 @@ public class ThemesUtils { } public static int getAccentColor() { - return getColorFromAttr(R.attr.accent); + var accent = AndroidUtils.getPreferences().getInt("accent_color", getColorFromAttr(R.attr.accent)); + return accent == 0 ? getColorFromAttr(R.attr.accent) : accent; } // Color accent + public static int getMutedAccentColor() { + return getMutedColor(getAccentColor()); + } + + @SuppressLint("DiscouragedPrivateApi") + public static void setCursorColor(EditText view) { + try { + view.setHighlightColor(ThemesUtils.getMutedAccentColor()); + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { + view.getTextCursorDrawable().setColorFilter(ThemesUtils.getAccentColor(), PorterDuff.Mode.SRC_IN); + } else { + Field field = TextView.class.getDeclaredField("mCursorDrawableRes"); + field.setAccessible(true); + int drawableResId = field.getInt(view); + + field = TextView.class.getDeclaredField("mEditor"); + field.setAccessible(true); + Object editor = field.get(view); + + if (editor != null) { + Drawable drawable = ContextCompat.getDrawable(view.getContext(), drawableResId); + drawable.setColorFilter(getAccentColor(), PorterDuff.Mode.SRC_IN); + Drawable[] drawables = {drawable, drawable}; + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { + field = editor.getClass().getDeclaredField("mCursorDrawable"); + } else { + field = editor.getClass().getDeclaredField("mDrawableForCursor"); + } + field.setAccessible(true); + field.set(editor, drawables); + } + } + } catch (Exception ignored) { + } + } + @SuppressLint("DiscouragedPrivateApi") + public static void colorHandles(TextView view) { + try { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { + view.getTextSelectHandle().setColorFilter(ThemesUtils.getAccentColor(), PorterDuff.Mode.SRC_IN); + view.getTextSelectHandleRight().setColorFilter(ThemesUtils.getAccentColor(), PorterDuff.Mode.SRC_IN); + view.getTextSelectHandleLeft().setColorFilter(ThemesUtils.getAccentColor(), PorterDuff.Mode.SRC_IN); + } else { + Field editorField = TextView.class.getDeclaredField("mEditor"); + + if (!editorField.isAccessible()) editorField.setAccessible(true); + + Object editor = editorField.get(view); + + if (editor != null) { + Class editorClass; + + editorClass = editor.getClass(); + + String[] handleNames = {"mSelectHandleLeft", "mSelectHandleRight", "mSelectHandleCenter"}; + String[] resNames = {"mTextSelectHandleLeftRes", "mTextSelectHandleRightRes", "mTextSelectHandleRes"}; + + for (int i = 0; i < handleNames.length; i++) { + Field handleField = editorClass.getDeclaredField(handleNames[i]); + if (!handleField.isAccessible()) { + handleField.setAccessible(true); + } + + Drawable handleDrawable = (Drawable) handleField.get(editor); + + if (handleDrawable == null) { + Field resField = TextView.class.getDeclaredField(resNames[i]); + if (!resField.isAccessible()) { + resField.setAccessible(true); + } + int resId = resField.getInt(view); + handleDrawable = view.getResources().getDrawable(resId); + } + + if (handleDrawable != null) { + Drawable drawable = handleDrawable.mutate(); + drawable.setColorFilter(getAccentColor(), PorterDuff.Mode.SRC_IN); + handleField.set(editor, drawable); + } + } + } + } + } catch (Exception ignored) { + } + } + + public static int getMutedColor(int color) { + return ColorUtils.blendARGB(color, (isDarkTheme() ? Color.BLACK : Color.WHITE), 0.5f); + } + + public static void setCustomAccentColor(int newColor, boolean async) { + var editor = AndroidUtils.edit().putInt("accent_color", newColor); + if (async) editor.apply(); + else editor.commit(); + } + public static int getTextAttr() { return getColorFromAttr(R.attr.text_primary); } // Text Primary color @@ -131,38 +224,12 @@ public class ThemesUtils { return getColorFromAttr(R.attr.header_text); } // Header/Toolbar color text - public static int getAmoledTheme() { - return getIdentifier("BaseAmoledStyle", "style"); - } // Get Amoled theme id - - public static int picFix() { - return getIdentifier("ActionBarThemeFix", "style"); - } // Fix tabbar color in photo viewer - - public static int getAmoledImTheme() { - return getIdentifier("VkIm.Theme.VkApp.Amoled", "style"); - } // Get Amoled theme id for messages - - public static int getAmoledMeTheme() { - return getIdentifier("VkIm.Theme.VkMe.Amoled", "style"); - } // Get Amoled theme id for messages with rounded msg - public static int getAttrId(String attr) { return getIdentifier(attr, "attr"); } - public static void setBarTheme(View getview) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { - getview.setSystemUiVisibility(getNeededColorNavbar() | getNeededColorStatusbar()); - } - } // Set white/dark statusbar/navbar icons - - public static int getNeededColorStatusbar() { - return !isDarkTheme() && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S ? 8192 : 0; - } - public static int getNeededColorNavbar() { - return Build.VERSION.SDK_INT >= Build.VERSION_CODES.O ? isDarkTheme() ? SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR : 0 : 0; + return Build.VERSION.SDK_INT >= Build.VERSION_CODES.O ? isDarkTheme() ? View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR : 0 : 0; } public static int getDarkThemeRes() { @@ -197,16 +264,35 @@ public class ThemesUtils { return MilkshakeHelper.e(); } - public static boolean isColorRefAccented(int color) { - for (int accent : new int[]{R.color.accent_blue, R.color.azure_A400, R.color.blue, R.color.blue_200, R.color.blue_200_muted, R.color.blue_300, R.color.blue_400, R.color.cool_blue, R.color.cornflower_blue, R.color.cornflower_blue_two, R.color.dot_unread, R.color.fave_promo_btn_pressed, R.color.header_blue, R.color.vkim_ripple_dark, R.color.colorAccent, R.color.light_blue, R.color.light_blue_gray, R.color.live_emoji_butt_hide, R.color.music_action_button_blue, R.color.name, R.color.picker_blue, R.color.picker_blue_pressed, R.color.picker_tab_bg_selected, R.color.picker_tab_text_selected, R.color.sharing_blue_btn_normal, R.color.sharing_blue_btn_pressed, R.color.sky_300, R.color.text_blue, R.color.tip_background, R.color.tw__blue_default, R.color.tw__blue_pressed, R.color.vkim_msg_sending_ic, R.color.vkim_playing_drawable_rect, R.color.white_blue32}) { - if (color == accent) return true; - } - return false; - } // Accent colors + private static int[] p() { + int[] iArr = new int[4]; + iArr[0] = getColor(isDarkTheme() ? R.color.gray_800 : R.color.white); + iArr[1] = getColor(isDarkTheme() ? R.color.switch_disabled_on_dark : R.color.switch_disabled_on_light); + iArr[2] = getColor(R.color.gray_20); + iArr[3] = getAccentColor(); + return iArr; + } - public static void themeMonetToolbar(ImageButton imageButton, Toolbar toolbar) { - imageButton.setImageTintList(ColorStateList.valueOf(getHeaderText())); - toolbar.setElevation(0.0f); + private static int[][] f() { + return new int[][]{new int[]{-16842910, -16842912}, new int[]{-16842910, 16842912}, new int[]{-16842912}, new int[]{16842912}}; + } + + private static int[] q() { + return new int[]{VKThemeHelper.d(R.attr.loader_track_fill), getMutedAccentColor(), VKThemeHelper.d(R.attr.loader_track_fill), getMutedAccentColor()}; + } + + public static void setSwitch(SwitchCompat switchCompat) { + DrawableCompat.setTintList(DrawableCompat.wrap(switchCompat.getThumbDrawable()), new ColorStateList(f(), p())); + DrawableCompat.setTintList(DrawableCompat.wrap(switchCompat.getTrackDrawable()), new ColorStateList(f(), q())); + } + + public static void setSwitch(Switch aSwitch) { + DrawableCompat.setTintList(DrawableCompat.wrap(aSwitch.getThumbDrawable()), new ColorStateList(f(), p())); + DrawableCompat.setTintList(DrawableCompat.wrap(aSwitch.getTrackDrawable()), new ColorStateList(f(), q())); + } + + public static void setImageViewColored(ImageView view){ + view.setColorFilter(ThemesUtils.getAccentColor(), PorterDuff.Mode.MULTIPLY); } public static Drawable recolorDrawable(Drawable drawable) { @@ -214,76 +300,18 @@ public class ThemesUtils { return new RecoloredDrawable(drawable, getAccentColor()); } // Recolor drawable to accent color - public static Drawable recolorVKIconMenu(Drawable drawable) { - int accent = getHeaderText(); - + public static Drawable recolorToolbarDrawable(Drawable drawable) { if (drawable == null) return null; + return new RecoloredDrawable(drawable, (ThemesUtils.isMilkshake() && !ThemesUtils.isDarkTheme()) ? ThemesUtils.getAccentColor() : ThemesUtils.getHeaderText()); + } - if (isAndroidMonet() || isDarkTheme()) accent = getAccentColor(); + public static void recolorTextView(TextView tw) { + tw.getBackground().setColorFilter(ThemesUtils.getAccentColor(), PorterDuff.Mode.SRC_OVER); + } - return new RecoloredDrawable(drawable, accent); - } // Recolor vk icon to accent color - - - public static Drawable recolorDrawableToolbar(Drawable drawable) { - if (drawable == null) return null; - - if (!isAndroidMonet()) return drawable; - - return new RecoloredDrawable(drawable, getHeaderText()); - } // Recolor toolbar drawable to accent color - - @SuppressLint("UseCompatLoadingForDrawables") - public static Drawable recolorDrawableInt(int drawable) { - if (!isAndroidMonet()) return getResources().getDrawable(drawable); - - @SuppressLint("UseCompatLoadingForDrawables") Drawable res = getResources().getDrawable(drawable); - return new RecoloredDrawable(res, getAccentColor()); - } // Get res drawable via id and coloring to accent - - public static ColorStateList recolorCSL(ColorStateList colorStateList) { - if (colorStateList == null) return null; - - if (!isAndroidMonet()) return colorStateList; - - return ColorStateList.valueOf(getAccentColor()); - } // Recolor ColorStateList to accent color - - @SuppressLint("UseCompatLoadingForColorStateLists") - public static ColorStateList themeCSL(Context context, int color) { - if (isColorRefAccented(color) && isAndroidMonet()) { - return ColorStateList.valueOf(getAccentColor()); - } - - ColorStateList csl; - - if (Build.VERSION.SDK_INT >= 23) { - csl = context.getColorStateList(color); - } else { - csl = context.getResources().getColorStateList(color); - } - - try { - int unsel = csl.getColorForState(new int[]{-android.R.attr.state_selected}, Color.BLACK); - int sel = csl.getColorForState(new int[]{android.R.attr.state_selected}, Color.BLACK); - - boolean isUnselAccent = isAccentedColor(unsel); - boolean isSelAccent = isAccentedColor(sel); - - if (isUnselAccent || isSelAccent) { - - return new ColorStateList(new int[][]{ - new int[]{android.R.attr.state_selected}, new int[]{-android.R.attr.state_selected} - }, new int[]{isSelAccent ? getAccentColor() : sel, isUnselAccent ? getAccentColor() : unsel}); - } - - return csl; - } catch (Exception e) { - - e.printStackTrace(); - return null; - } - } // Recolor ColorStateList + public static void recolorBGView(View view) { + view.getBackground().setColorFilter(ThemesUtils.getAccentColor(), PorterDuff.Mode.SRC_OVER); + } public static int darken(int color, float by) { float[] hsl = new float[3]; @@ -311,30 +339,8 @@ public class ThemesUtils { return ColorUtils.setAlphaComponent(src, 169); } - public static boolean isAccentedColor(ColorStateList target) { - return target != null && isAccentedColor(target.getDefaultColor()); - } - - public static boolean isAccentedColor(int target) { - return accentColors.contains(hex(target).toLowerCase()); - } - - public static int getColor(Context context, int i) { - if (isColorRefAccented(i) && isAndroidMonet()) { - return getAccentColor(); - } - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { - return context.getColor(i); - } else { - return context.getResources().getColor(i); - } - } // Android Support color injector + accent color checker - - public static int getColor2(int i) { - if (isColorRefAccented(i) && isAndroidMonet()) { - return getAccentColor(); - } - return getResources().getColor(i); + public static int getColor(int i) { + return ThemesHacks.getHackedColor(getGlobalContext(), i); } // Android Support color injector + accent color checker public static int getAlertStyle() { @@ -342,7 +348,7 @@ public class ThemesUtils { } public static String getBackgroundStickers() { - if (getWallpaper() != null) { + if (WallpapersHooks.getWallpaper() != null) { return "images_with_background"; } return "images"; @@ -384,6 +390,11 @@ public class ThemesUtils { return String.format("#%06X", i & 16777215); } // Get color as hex string + // hex, but without # at the beginning + public static String hexx(int i) { + return String.format("%06X", i & 16777215); + } + public static int getNavigationHeight(int Default) { int VKME = R.dimen.design_bottom_sheet_peek_height_min; diff --git a/smali/assets/StandartFilter.txt b/smali/assets/StandartFilter.txt index eb1973b86..78e972ef6 100644 --- a/smali/assets/StandartFilter.txt +++ b/smali/assets/StandartFilter.txt @@ -94,4 +94,6 @@ cкорее подписывайся Подписывайтесь👇 Подписывайся👇 ссылка в комментариях -в комментариях👇 \ No newline at end of file +в комментариях👇 +👉https:// +👉http:// \ No newline at end of file diff --git a/smali/assets/vtl_themes/palettes/html_w3c.json b/smali/assets/vtl_themes/palettes/html_w3c.json new file mode 100644 index 000000000..e74e4028b --- /dev/null +++ b/smali/assets/vtl_themes/palettes/html_w3c.json @@ -0,0 +1,2387 @@ +{ + "palette_id": "html_w3c", + "name": "HTML W3C Palette", + "author": "Vologhat", + "palette": [ + { + "name": "Black (W3C)", + "color": "000000" + }, + { + "name": "Night", + "color": "0C090A" + }, + { + "name": "Charcoal", + "color": "34282C" + }, + { + "name": "Oil", + "color": "3B3131" + }, + { + "name": "Dark Gray", + "color": "3A3B3C" + }, + { + "name": "Light Black", + "color": "454545" + }, + { + "name": "Black Cat", + "color": "413839" + }, + { + "name": "Iridium", + "color": "3D3C3A" + }, + { + "name": "Black Eel", + "color": "463E3F" + }, + { + "name": "Black Cow", + "color": "4C4646" + }, + { + "name": "Gray Wolf", + "color": "504A4B" + }, + { + "name": "Vampire Gray", + "color": "565051" + }, + { + "name": "Iron Gray", + "color": "52595D" + }, + { + "name": "Gray Dolphin", + "color": "5C5858" + }, + { + "name": "Carbon Gray", + "color": "625D5D" + }, + { + "name": "Ash Gray", + "color": "666362" + }, + { + "name": "DimGray or DimGrey (W3C)", + "color": "696969" + }, + { + "name": "Nardo Gray", + "color": "686A6C" + }, + { + "name": "Cloudy Gray", + "color": "6D6968" + }, + { + "name": "Smokey Gray", + "color": "726E6D" + }, + { + "name": "Alien Gray", + "color": "736F6E" + }, + { + "name": "Sonic Silver", + "color": "757575" + }, + { + "name": "Platinum Gray", + "color": "797979" + }, + { + "name": "Granite", + "color": "837E7C" + }, + { + "name": "Gray or Grey (W3C)", + "color": "808080" + }, + { + "name": "Battleship Gray", + "color": "848482" + }, + { + "name": "Gunmetal Gray", + "color": "8D918D" + }, + { + "name": "DarkGray or DarkGrey (W3C)", + "color": "A9A9A9" + }, + { + "name": "Gray Cloud", + "color": "B6B6B4" + }, + { + "name": "Silver (W3C)", + "color": "C0C0C0" + }, + { + "name": "Pale Silver", + "color": "C9C0BB" + }, + { + "name": "Gray Goose", + "color": "D1D0CE" + }, + { + "name": "Platinum Silver", + "color": "CECECE" + }, + { + "name": "LightGray or LightGrey (W3C)", + "color": "D3D3D3" + }, + { + "name": "Gainsboro (W3C)", + "color": "DCDCDC" + }, + { + "name": "Platinum", + "color": "E5E4E2" + }, + { + "name": "Metallic Silver", + "color": "BCC6CC" + }, + { + "name": "Blue Gray", + "color": "98AFC7" + }, + { + "name": "Roman Silver", + "color": "838996" + }, + { + "name": "LightSlateGray or LightSlateGrey (W3C)", + "color": "778899" + }, + { + "name": "SlateGray or SlateGrey (W3C)", + "color": "708090" + }, + { + "name": "Rat Gray", + "color": "6D7B8D" + }, + { + "name": "Slate Granite Gray", + "color": "657383" + }, + { + "name": "Jet Gray", + "color": "616D7E" + }, + { + "name": "Mist Blue", + "color": "646D7E" + }, + { + "name": "Marble Blue", + "color": "566D7E" + }, + { + "name": "Slate Blue Grey", + "color": "737CA1" + }, + { + "name": "Light Purple Blue", + "color": "728FCE" + }, + { + "name": "Azure Blue", + "color": "4863A0" + }, + { + "name": "Blue Jay", + "color": "2B547E" + }, + { + "name": "Charcoal Blue", + "color": "36454F" + }, + { + "name": "Dark Blue Grey", + "color": "29465B" + }, + { + "name": "Dark Slate", + "color": "2B3856" + }, + { + "name": "Deep-Sea Blue", + "color": "123456" + }, + { + "name": "Night Blue", + "color": "151B54" + }, + { + "name": "MidnightBlue (W3C)", + "color": "191970" + }, + { + "name": "Navy (W3C)", + "color": "000080" + }, + { + "name": "Denim Dark Blue", + "color": "151B8D" + }, + { + "name": "DarkBlue (W3C)", + "color": "00008B" + }, + { + "name": "Lapis Blue", + "color": "15317E" + }, + { + "name": "New Midnight Blue", + "color": "0000A0" + }, + { + "name": "Earth Blue", + "color": "0000A5" + }, + { + "name": "Cobalt Blue", + "color": "0020C2" + }, + { + "name": "MediumBlue (W3C)", + "color": "0000CD" + }, + { + "name": "Blueberry Blue", + "color": "0041C2" + }, + { + "name": "Canary Blue", + "color": "2916F5" + }, + { + "name": "Blue (W3C)", + "color": "0000FF" + }, + { + "name": "Bright Blue", + "color": "0909FF" + }, + { + "name": "Blue Orchid", + "color": "1F45FC" + }, + { + "name": "Sapphire Blue", + "color": "2554C7" + }, + { + "name": "Blue Eyes", + "color": "1569C7" + }, + { + "name": "Bright Navy Blue", + "color": "1974D2" + }, + { + "name": "Balloon Blue", + "color": "2B60DE" + }, + { + "name": "RoyalBlue (W3C)", + "color": "4169E1" + }, + { + "name": "Ocean Blue", + "color": "2B65EC" + }, + { + "name": "Blue Ribbon", + "color": "306EFF" + }, + { + "name": "Blue Dress", + "color": "157DEC" + }, + { + "name": "Neon Blue", + "color": "1589FF" + }, + { + "name": "DodgerBlue (W3C)", + "color": "1E90FF" + }, + { + "name": "Glacial Blue Ice", + "color": "368BC1" + }, + { + "name": "SteelBlue (W3C)", + "color": "4682B4" + }, + { + "name": "Silk Blue", + "color": "488AC7" + }, + { + "name": "Windows Blue", + "color": "357EC7" + }, + { + "name": "Blue Ivy", + "color": "3090C7" + }, + { + "name": "Blue Koi", + "color": "659EC7" + }, + { + "name": "Columbia Blue", + "color": "87AFC7" + }, + { + "name": "Baby Blue", + "color": "95B9C7" + }, + { + "name": "CornflowerBlue (W3C)", + "color": "6495ED" + }, + { + "name": "Sky Blue Dress", + "color": "6698FF" + }, + { + "name": "Iceberg", + "color": "56A5EC" + }, + { + "name": "Butterfly Blue", + "color": "38ACEC" + }, + { + "name": "DeepSkyBlue (W3C)", + "color": "00BFFF" + }, + { + "name": "Midday Blue", + "color": "3BB9FF" + }, + { + "name": "Crystal Blue", + "color": "5CB3FF" + }, + { + "name": "Denim Blue", + "color": "79BAEC" + }, + { + "name": "Day Sky Blue", + "color": "82CAFF" + }, + { + "name": "LightSkyBlue (W3C)", + "color": "87CEFA" + }, + { + "name": "SkyBlue (W3C)", + "color": "87CEEB" + }, + { + "name": "Jeans Blue", + "color": "A0CFEC" + }, + { + "name": "Blue Angel", + "color": "B7CEEC" + }, + { + "name": "Pastel Blue", + "color": "B4CFEC" + }, + { + "name": "Light Day Blue", + "color": "ADDFFF" + }, + { + "name": "Sea Blue", + "color": "C2DFFF" + }, + { + "name": "Heavenly Blue", + "color": "C6DEFF" + }, + { + "name": "Robin Egg Blue", + "color": "BDEDFF" + }, + { + "name": "PowderBlue (W3C)", + "color": "B0E0E6" + }, + { + "name": "Coral Blue", + "color": "AFDCEC" + }, + { + "name": "LightBlue (W3C)", + "color": "ADD8E6" + }, + { + "name": "LightSteelBlue (W3C)", + "color": "B0CFDE" + }, + { + "name": "Gulf Blue", + "color": "C9DFEC" + }, + { + "name": "Pastel Light Blue", + "color": "D5D6EA" + }, + { + "name": "Lavender Blue", + "color": "E3E4FA" + }, + { + "name": "Lavender (W3C)", + "color": "E6E6FA" + }, + { + "name": "Water", + "color": "EBF4FA" + }, + { + "name": "AliceBlue (W3C)", + "color": "F0F8FF" + }, + { + "name": "GhostWhite (W3C)", + "color": "F8F8FF" + }, + { + "name": "Azure (W3C)", + "color": "F0FFFF" + }, + { + "name": "LightCyan (W3C)", + "color": "E0FFFF" + }, + { + "name": "Light Slate", + "color": "CCFFFF" + }, + { + "name": "Electric Blue", + "color": "9AFEFF" + }, + { + "name": "Tron Blue", + "color": "7DFDFE" + }, + { + "name": "Blue Zircon", + "color": "57FEFF" + }, + { + "name": "Aqua or Cyan (W3C)", + "color": "00FFFF" + }, + { + "name": "Bright Cyan", + "color": "0AFFFF" + }, + { + "name": "Celeste", + "color": "50EBEC" + }, + { + "name": "Blue Diamond", + "color": "4EE2EC" + }, + { + "name": "Bright Turquoise", + "color": "16E2F5" + }, + { + "name": "Blue Lagoon", + "color": "8EEBEC" + }, + { + "name": "PaleTurquoise (W3C)", + "color": "AFEEEE" + }, + { + "name": "Pale Blue Lily", + "color": "CFECEC" + }, + { + "name": "Tiffany Blue", + "color": "81D8D0" + }, + { + "name": "Blue Hosta", + "color": "77BFC7" + }, + { + "name": "Cyan Opaque", + "color": "92C7C7" + }, + { + "name": "Northern Lights Blue", + "color": "78C7C7" + }, + { + "name": "Blue Green", + "color": "7BCCB5" + }, + { + "name": "MediumAquaMarine (W3C)", + "color": "66CDAA" + }, + { + "name": "Magic Mint", + "color": "AAF0D1" + }, + { + "name": "Aquamarine (W3C)", + "color": "7FFFD4" + }, + { + "name": "Light Aquamarine", + "color": "93FFE8" + }, + { + "name": "Turquoise (W3C)", + "color": "40E0D0" + }, + { + "name": "MediumTurquoise (W3C)", + "color": "48D1CC" + }, + { + "name": "Deep Turquoise", + "color": "48CCCD" + }, + { + "name": "Jellyfish", + "color": "46C7C7" + }, + { + "name": "Blue Turquoise", + "color": "43C6DB" + }, + { + "name": "DarkTurquoise (W3C)", + "color": "00CED1" + }, + { + "name": "Macaw Blue Green", + "color": "43BFC7" + }, + { + "name": "LightSeaGreen (W3C)", + "color": "20B2AA" + }, + { + "name": "Seafoam Green", + "color": "3EA99F" + }, + { + "name": "CadetBlue (W3C)", + "color": "5F9EA0" + }, + { + "name": "Deep-Sea", + "color": "3B9C9C" + }, + { + "name": "DarkCyan (W3C)", + "color": "008B8B" + }, + { + "name": "Teal (W3C)", + "color": "008080" + }, + { + "name": "Medium Teal", + "color": "045F5F" + }, + { + "name": "Deep Teal", + "color": "033E3E" + }, + { + "name": "DarkSlateGray or DarkSlateGrey (W3C)", + "color": "25383C" + }, + { + "name": "Gunmetal", + "color": "2C3539" + }, + { + "name": "Blue Moss Green", + "color": "3C565B" + }, + { + "name": "Beetle Green", + "color": "4C787E" + }, + { + "name": "Grayish Turquoise", + "color": "5E7D7E" + }, + { + "name": "Greenish Blue", + "color": "307D7E" + }, + { + "name": "Aquamarine Stone", + "color": "348781" + }, + { + "name": "Sea Turtle Green", + "color": "438D80" + }, + { + "name": "Dull-Sea Green", + "color": "4E8975" + }, + { + "name": "Deep-Sea Green", + "color": "306754" + }, + { + "name": "SeaGreen (W3C)", + "color": "2E8B57" + }, + { + "name": "Dark Mint", + "color": "31906E" + }, + { + "name": "Jade", + "color": "00A36C" + }, + { + "name": "Earth Green", + "color": "34A56F" + }, + { + "name": "Emerald", + "color": "50C878" + }, + { + "name": "Mint", + "color": "3EB489" + }, + { + "name": "MediumSeaGreen (W3C)", + "color": "3CB371" + }, + { + "name": "Camouflage Green", + "color": "78866B" + }, + { + "name": "Sage Green", + "color": "848B79" + }, + { + "name": "Hazel Green", + "color": "617C58" + }, + { + "name": "Venom Green", + "color": "728C00" + }, + { + "name": "OliveDrab (W3C)", + "color": "6B8E23" + }, + { + "name": "Olive (W3C)", + "color": "808000" + }, + { + "name": "DarkOliveGreen (W3C)", + "color": "556B2F" + }, + { + "name": "Army Green", + "color": "4B5320" + }, + { + "name": "Fern Green", + "color": "667C26" + }, + { + "name": "Fall Forest Green", + "color": "4E9258" + }, + { + "name": "Pine Green", + "color": "387C44" + }, + { + "name": "Medium Forest Green", + "color": "347235" + }, + { + "name": "Jungle Green", + "color": "347C2C" + }, + { + "name": "ForestGreen (W3C)", + "color": "228B22" + }, + { + "name": "Green (W3C)", + "color": "008000" + }, + { + "name": "DarkGreen (W3C)", + "color": "006400" + }, + { + "name": "Deep Emerald Green", + "color": "046307" + }, + { + "name": "Dark Forest Green", + "color": "254117" + }, + { + "name": "Seaweed Green", + "color": "437C17" + }, + { + "name": "Shamrock Green", + "color": "347C17" + }, + { + "name": "Green Onion", + "color": "6AA121" + }, + { + "name": "Green Pepper", + "color": "4AA02C" + }, + { + "name": "Dark Lime Green", + "color": "41A317" + }, + { + "name": "Parrot Green", + "color": "12AD2B" + }, + { + "name": "Clover Green", + "color": "3EA055" + }, + { + "name": "Dinosaur Green", + "color": "73A16C" + }, + { + "name": "Green Snake", + "color": "6CBB3C" + }, + { + "name": "Alien Green", + "color": "6CC417" + }, + { + "name": "Green Apple", + "color": "4CC417" + }, + { + "name": "LimeGreen (W3C)", + "color": "32CD32" + }, + { + "name": "Pea Green", + "color": "52D017" + }, + { + "name": "Kelly Green", + "color": "4CC552" + }, + { + "name": "Zombie Green", + "color": "54C571" + }, + { + "name": "Frog Green", + "color": "99C68E" + }, + { + "name": "DarkSeaGreen (W3C)", + "color": "8FBC8F" + }, + { + "name": "Green Peas", + "color": "89C35C" + }, + { + "name": "Dollar Bill Green", + "color": "85BB65" + }, + { + "name": "Iguana Green", + "color": "9CB071" + }, + { + "name": "Acid Green", + "color": "B0BF1A" + }, + { + "name": "Avocado Green", + "color": "B2C248" + }, + { + "name": "Pistachio Green", + "color": "9DC209" + }, + { + "name": "Salad Green", + "color": "A1C935" + }, + { + "name": "YellowGreen (W3C)", + "color": "9ACD32" + }, + { + "name": "Pastel Green", + "color": "77DD77" + }, + { + "name": "Hummingbird Green", + "color": "7FE817" + }, + { + "name": "Nebula Green", + "color": "59E817" + }, + { + "name": "Stoplight Go Green", + "color": "57E964" + }, + { + "name": "Neon Green", + "color": "16F529" + }, + { + "name": "Jade Green", + "color": "5EFB6E" + }, + { + "name": "Lime Mint Green", + "color": "36F57F" + }, + { + "name": "SpringGreen (W3C)", + "color": "00FF7F" + }, + { + "name": "MediumSpringGreen (W3C)", + "color": "00FA9A" + }, + { + "name": "Emerald Green", + "color": "5FFB17" + }, + { + "name": "Lime (W3C)", + "color": "00FF00" + }, + { + "name": "LawnGreen (W3C)", + "color": "7CFC00" + }, + { + "name": "Bright Green", + "color": "66FF00" + }, + { + "name": "Chartreuse (W3C)", + "color": "7FFF00" + }, + { + "name": "Yellow Lawn Green", + "color": "87F717" + }, + { + "name": "Aloe Vera Green", + "color": "98F516" + }, + { + "name": "Dull Green Yellow", + "color": "B1FB17" + }, + { + "name": "GreenYellow (W3C)", + "color": "ADFF2F" + }, + { + "name": "Chameleon Green", + "color": "BDF516" + }, + { + "name": "Neon Yellow Green", + "color": "DAEE01" + }, + { + "name": "Yellow Green Grosbeak", + "color": "E2F516" + }, + { + "name": "Tea Green", + "color": "CCFB5D" + }, + { + "name": "Slime Green", + "color": "BCE954" + }, + { + "name": "Algae Green", + "color": "64E986" + }, + { + "name": "LightGreen (W3C)", + "color": "90EE90" + }, + { + "name": "Dragon Green", + "color": "6AFB92" + }, + { + "name": "PaleGreen (W3C)", + "color": "98FB98" + }, + { + "name": "Mint Green", + "color": "98FF98" + }, + { + "name": "Green Thumb", + "color": "B5EAAA" + }, + { + "name": "Organic Brown", + "color": "E3F9A6" + }, + { + "name": "Light Jade", + "color": "C3FDB8" + }, + { + "name": "Light Rose Green", + "color": "DBF9DB" + }, + { + "name": "HoneyDew (W3C)", + "color": "F0FFF0" + }, + { + "name": "MintCream (W3C)", + "color": "F5FFFA" + }, + { + "name": "LemonChiffon (W3C)", + "color": "FFFACD" + }, + { + "name": "Parchment", + "color": "FFFFC2" + }, + { + "name": "Cream", + "color": "FFFFCC" + }, + { + "name": "Cream White", + "color": "FFFDD0" + }, + { + "name": "LightGoldenRodYellow (W3C)", + "color": "FAFAD2" + }, + { + "name": "LightYellow (W3C)", + "color": "FFFFE0" + }, + { + "name": "Beige (W3C)", + "color": "F5F5DC" + }, + { + "name": "Cornsilk (W3C)", + "color": "FFF8DC" + }, + { + "name": "Blonde", + "color": "FBF6D9" + }, + { + "name": "Champagne", + "color": "F7E7CE" + }, + { + "name": "AntiqueWhite (W3C)", + "color": "FAEBD7" + }, + { + "name": "PapayaWhip (W3C)", + "color": "FFEFD5" + }, + { + "name": "BlanchedAlmond (W3C)", + "color": "FFEBCD" + }, + { + "name": "Bisque (W3C)", + "color": "FFE4C4" + }, + { + "name": "Wheat (W3C)", + "color": "F5DEB3" + }, + { + "name": "Moccasin (W3C)", + "color": "FFE4B5" + }, + { + "name": "Peach", + "color": "FFE5B4" + }, + { + "name": "Light Orange", + "color": "FED8B1" + }, + { + "name": "PeachPuff (W3C)", + "color": "FFDAB9" + }, + { + "name": "NavajoWhite (W3C)", + "color": "FFDEAD" + }, + { + "name": "Golden Blonde", + "color": "FBE7A1" + }, + { + "name": "Golden Silk", + "color": "F3E3C3" + }, + { + "name": "Dark Blonde", + "color": "F0E2B6" + }, + { + "name": "Light Gold", + "color": "F1E5AC" + }, + { + "name": "Vanilla", + "color": "F3E5AB" + }, + { + "name": "Tan Brown", + "color": "ECE5B6" + }, + { + "name": "Dirty White", + "color": "E8E4C9" + }, + { + "name": "PaleGoldenRod (W3C)", + "color": "EEE8AA" + }, + { + "name": "Khaki (W3C)", + "color": "F0E68C" + }, + { + "name": "Cardboard Brown", + "color": "EDDA74" + }, + { + "name": "Harvest Gold", + "color": "EDE275" + }, + { + "name": "Sun Yellow", + "color": "FFE87C" + }, + { + "name": "Corn Yellow", + "color": "FFF380" + }, + { + "name": "Pastel Yellow", + "color": "FAF884" + }, + { + "name": "Neon Yellow", + "color": "FFFF33" + }, + { + "name": "Yellow (W3C)", + "color": "FFFF00" + }, + { + "name": "Canary Yellow", + "color": "FFEF00" + }, + { + "name": "Banana Yellow", + "color": "F5E216" + }, + { + "name": "Mustard Yellow", + "color": "FFDB58" + }, + { + "name": "Golden Yellow", + "color": "FFDF00" + }, + { + "name": "Bold Yellow", + "color": "F9DB24" + }, + { + "name": "Rubber Ducky Yellow", + "color": "FFD801" + }, + { + "name": "Gold (W3C)", + "color": "FFD700" + }, + { + "name": "Bright Gold", + "color": "FDD017" + }, + { + "name": "Chrome Gold", + "color": "FFCE44" + }, + { + "name": "Golden Brown", + "color": "EAC117" + }, + { + "name": "Deep Yellow", + "color": "F6BE00" + }, + { + "name": "Macaroni and Cheese", + "color": "F2BB66" + }, + { + "name": "Saffron", + "color": "FBB917" + }, + { + "name": "Beer", + "color": "FBB117" + }, + { + "name": "Yellow Orange or Orange Yellow", + "color": "FFAE42" + }, + { + "name": "Cantaloupe", + "color": "FFA62F" + }, + { + "name": "Orange (W3C)", + "color": "FFA500" + }, + { + "name": "Brown Sand", + "color": "EE9A4D" + }, + { + "name": "SandyBrown (W3C)", + "color": "F4A460" + }, + { + "name": "Brown Sugar", + "color": "E2A76F" + }, + { + "name": "Camel Brown", + "color": "C19A6B" + }, + { + "name": "Deer Brown", + "color": "E6BF83" + }, + { + "name": "BurlyWood (W3C)", + "color": "DEB887" + }, + { + "name": "Tan (W3C)", + "color": "D2B48C" + }, + { + "name": "Light French Beige", + "color": "C8AD7F" + }, + { + "name": "Sand", + "color": "C2B280" + }, + { + "name": "Sage", + "color": "BCB88A" + }, + { + "name": "Fall Leaf Brown", + "color": "C8B560" + }, + { + "name": "Ginger Brown", + "color": "C9BE62" + }, + { + "name": "DarkKhaki (W3C)", + "color": "BDB76B" + }, + { + "name": "Olive Green", + "color": "BAB86C" + }, + { + "name": "Brass", + "color": "B5A642" + }, + { + "name": "Cookie Brown", + "color": "C7A317" + }, + { + "name": "Metallic Gold", + "color": "D4AF37" + }, + { + "name": "Bee Yellow", + "color": "E9AB17" + }, + { + "name": "School Bus Yellow", + "color": "E8A317" + }, + { + "name": "GoldenRod (W3C)", + "color": "DAA520" + }, + { + "name": "Orange Gold", + "color": "D4A017" + }, + { + "name": "Caramel", + "color": "C68E17" + }, + { + "name": "DarkGoldenRod (W3C)", + "color": "B8860B" + }, + { + "name": "Cinnamon", + "color": "C58917" + }, + { + "name": "Peru (W3C)", + "color": "CD853F" + }, + { + "name": "Bronze", + "color": "CD7F32" + }, + { + "name": "Tiger Orange", + "color": "C88141" + }, + { + "name": "Copper", + "color": "B87333" + }, + { + "name": "Dark Gold", + "color": "AA6C39" + }, + { + "name": "Dark Almond", + "color": "AB784E" + }, + { + "name": "Wood", + "color": "966F33" + }, + { + "name": "Oak Brown", + "color": "806517" + }, + { + "name": "Antique Bronze", + "color": "665D1E" + }, + { + "name": "Hazel", + "color": "8E7618" + }, + { + "name": "Dark Yellow", + "color": "8B8000" + }, + { + "name": "Dark Moccasin", + "color": "827839" + }, + { + "name": "Khaki Green", + "color": "8A865D" + }, + { + "name": "Bullet Shell", + "color": "AF9B60" + }, + { + "name": "Army Brown", + "color": "827B60" + }, + { + "name": "Sandstone", + "color": "786D5F" + }, + { + "name": "Taupe", + "color": "483C32" + }, + { + "name": "Mocha", + "color": "493D26" + }, + { + "name": "Milk Chocolate", + "color": "513B1C" + }, + { + "name": "Gray Brown", + "color": "3D3635" + }, + { + "name": "Dark Coffee", + "color": "3B2F2F" + }, + { + "name": "Old Burgundy", + "color": "43302E" + }, + { + "name": "Western Charcoal", + "color": "49413F" + }, + { + "name": "Bakers Brown", + "color": "5C3317" + }, + { + "name": "Dark Brown", + "color": "654321" + }, + { + "name": "Sepia Brown", + "color": "704214" + }, + { + "name": "Dark Bronze", + "color": "804A00" + }, + { + "name": "Coffee", + "color": "6F4E37" + }, + { + "name": "Brown Bear", + "color": "835C3B" + }, + { + "name": "Red Dirt", + "color": "7F5217" + }, + { + "name": "Sepia", + "color": "7F462C" + }, + { + "name": "Sienna (W3C)", + "color": "A0522D" + }, + { + "name": "SaddleBrown (W3C)", + "color": "8B4513" + }, + { + "name": "Dark Sienna", + "color": "8A4117" + }, + { + "name": "Sangria", + "color": "7E3817" + }, + { + "name": "Blood Red", + "color": "7E3517" + }, + { + "name": "Chestnut", + "color": "954535" + }, + { + "name": "Chestnut Red", + "color": "C34A2C" + }, + { + "name": "Mahogany", + "color": "C04000" + }, + { + "name": "Red Fox", + "color": "C35817" + }, + { + "name": "Dark Bisque", + "color": "B86500" + }, + { + "name": "Light Brown", + "color": "B5651D" + }, + { + "name": "Petra Gold", + "color": "B76734" + }, + { + "name": "Rust", + "color": "C36241" + }, + { + "name": "Copper Red", + "color": "CB6D51" + }, + { + "name": "Orange Salmon", + "color": "C47451" + }, + { + "name": "Chocolate (W3C)", + "color": "D2691E" + }, + { + "name": "Sedona", + "color": "CC6600" + }, + { + "name": "Papaya Orange", + "color": "E56717" + }, + { + "name": "Halloween Orange", + "color": "E66C2C" + }, + { + "name": "Neon Orange", + "color": "FF6700" + }, + { + "name": "Bright Orange", + "color": "FF5F1F" + }, + { + "name": "Pumpkin Orange", + "color": "F87217" + }, + { + "name": "Carrot Orange", + "color": "F88017" + }, + { + "name": "DarkOrange (W3C)", + "color": "FF8C00" + }, + { + "name": "Construction Cone Orange", + "color": "F87431" + }, + { + "name": "Indian Saffron", + "color": "FF7722" + }, + { + "name": "Sunrise Orange", + "color": "E67451" + }, + { + "name": "Mango Orange", + "color": "FF8040" + }, + { + "name": "Coral (W3C)", + "color": "FF7F50" + }, + { + "name": "Basket Ball Orange", + "color": "F88158" + }, + { + "name": "Light Salmon Rose", + "color": "F9966B" + }, + { + "name": "LightSalmon (W3C)", + "color": "FFA07A" + }, + { + "name": "DarkSalmon (W3C)", + "color": "E9967A" + }, + { + "name": "Tangerine", + "color": "E78A61" + }, + { + "name": "Light Copper", + "color": "DA8A67" + }, + { + "name": "Salmon (W3C)", + "color": "FA8072" + }, + { + "name": "LightCoral (W3C)", + "color": "F08080" + }, + { + "name": "Pastel Red", + "color": "F67280" + }, + { + "name": "Pink Coral", + "color": "E77471" + }, + { + "name": "Bean Red", + "color": "F75D59" + }, + { + "name": "Valentine Red", + "color": "E55451" + }, + { + "name": "IndianRed (W3C)", + "color": "CD5C5C" + }, + { + "name": "Tomato (W3C)", + "color": "FF6347" + }, + { + "name": "Shocking Orange", + "color": "E55B3C" + }, + { + "name": "OrangeRed (W3C)", + "color": "FF4500" + }, + { + "name": "Red (W3C)", + "color": "FF0000" + }, + { + "name": "Neon Red", + "color": "FD1C03" + }, + { + "name": "Scarlet", + "color": "FF2400" + }, + { + "name": "Ruby Red", + "color": "F62217" + }, + { + "name": "Ferrari Red", + "color": "F70D1A" + }, + { + "name": "Fire Engine Red", + "color": "F62817" + }, + { + "name": "Lava Red", + "color": "E42217" + }, + { + "name": "Love Red", + "color": "E41B17" + }, + { + "name": "Grapefruit", + "color": "DC381F" + }, + { + "name": "Cherry Red", + "color": "C24641" + }, + { + "name": "Chilli Pepper", + "color": "C11B17" + }, + { + "name": "FireBrick (W3C)", + "color": "B22222" + }, + { + "name": "Tomato Sauce Red", + "color": "B21807" + }, + { + "name": "Brown (W3C)", + "color": "A52A2A" + }, + { + "name": "Carbon Red", + "color": "A70D2A" + }, + { + "name": "Cranberry", + "color": "9F000F" + }, + { + "name": "Saffron Red", + "color": "931314" + }, + { + "name": "Crimson Red", + "color": "990000" + }, + { + "name": "Red Wine or Wine Red", + "color": "990012" + }, + { + "name": "DarkRed (W3C)", + "color": "8B0000" + }, + { + "name": "Maroon (W3C)", + "color": "800000" + }, + { + "name": "Burgundy", + "color": "8C001A" + }, + { + "name": "Vermilion", + "color": "7E191B" + }, + { + "name": "Deep Red", + "color": "800517" + }, + { + "name": "Red Blood", + "color": "660000" + }, + { + "name": "Blood Night", + "color": "551606" + }, + { + "name": "Dark Scarlet", + "color": "560319" + }, + { + "name": "Black Bean", + "color": "3D0C02" + }, + { + "name": "Chocolate Brown", + "color": "3F000F" + }, + { + "name": "Midnight", + "color": "2B1B17" + }, + { + "name": "Purple Lily", + "color": "550A35" + }, + { + "name": "Purple Maroon", + "color": "810541" + }, + { + "name": "Plum Pie", + "color": "7D0541" + }, + { + "name": "Plum Velvet", + "color": "7D0552" + }, + { + "name": "Dark Raspberry", + "color": "872657" + }, + { + "name": "Velvet Maroon", + "color": "7E354D" + }, + { + "name": "Rosy-Finch", + "color": "7F4E52" + }, + { + "name": "Dull Purple", + "color": "7F525D" + }, + { + "name": "Puce", + "color": "7F5A58" + }, + { + "name": "Rose Dust", + "color": "997070" + }, + { + "name": "Rosy Pink", + "color": "B38481" + }, + { + "name": "RosyBrown (W3C)", + "color": "BC8F8F" + }, + { + "name": "Khaki Rose", + "color": "C5908E" + }, + { + "name": "Lipstick Pink", + "color": "C48793" + }, + { + "name": "Pink Brown", + "color": "C48189" + }, + { + "name": "Pink Daisy", + "color": "E799A3" + }, + { + "name": "Dusty Pink", + "color": "D58A94" + }, + { + "name": "Rose", + "color": "E8ADAA" + }, + { + "name": "Silver Pink", + "color": "C4AEAD" + }, + { + "name": "Rose Gold", + "color": "ECC5C0" + }, + { + "name": "Deep Peach", + "color": "FFCBA4" + }, + { + "name": "Pastel Orange", + "color": "F8B88B" + }, + { + "name": "Desert Sand", + "color": "EDC9AF" + }, + { + "name": "Unbleached Silk", + "color": "FFDDCA" + }, + { + "name": "Pig Pink", + "color": "FDD7E4" + }, + { + "name": "Blush", + "color": "FFE6E8" + }, + { + "name": "MistyRose (W3C)", + "color": "FFE4E1" + }, + { + "name": "Pink Bubble Gum", + "color": "FFDFDD" + }, + { + "name": "Light Red", + "color": "FFCCCB" + }, + { + "name": "Light Rose", + "color": "FBCFCD" + }, + { + "name": "Deep Rose", + "color": "FBBBB9" + }, + { + "name": "Pink (W3C)", + "color": "FFC0CB" + }, + { + "name": "LightPink (W3C)", + "color": "FFB6C1" + }, + { + "name": "Donut Pink", + "color": "FAAFBE" + }, + { + "name": "Baby Pink", + "color": "FAAFBA" + }, + { + "name": "Flamingo Pink", + "color": "F9A7B0" + }, + { + "name": "Pastel Pink", + "color": "FEA3AA" + }, + { + "name": "Rose Pink or Pink Rose", + "color": "E7A1B0" + }, + { + "name": "Cadillac Pink", + "color": "E38AAE" + }, + { + "name": "Carnation Pink", + "color": "F778A1" + }, + { + "name": "Blush Red", + "color": "E56E94" + }, + { + "name": "PaleVioletRed (W3C)", + "color": "DB7093" + }, + { + "name": "Purple Pink", + "color": "D16587" + }, + { + "name": "Tulip Pink", + "color": "C25A7C" + }, + { + "name": "Bashful Pink", + "color": "C25283" + }, + { + "name": "Dark Pink", + "color": "E75480" + }, + { + "name": "Dark Hot Pink", + "color": "F660AB" + }, + { + "name": "HotPink (W3C)", + "color": "FF69B4" + }, + { + "name": "Watermelon Pink", + "color": "FC6C85" + }, + { + "name": "Violet Red", + "color": "F6358A" + }, + { + "name": "Hot Deep Pink", + "color": "F52887" + }, + { + "name": "DeepPink (W3C)", + "color": "FF1493" + }, + { + "name": "Neon Pink", + "color": "F535AA" + }, + { + "name": "Neon Hot Pink", + "color": "FD349C" + }, + { + "name": "Pink Cupcake", + "color": "E45E9D" + }, + { + "name": "Dimorphotheca Magenta", + "color": "E3319D" + }, + { + "name": "Pink Lemonade", + "color": "E4287C" + }, + { + "name": "Raspberry", + "color": "E30B5D" + }, + { + "name": "Crimson (W3C)", + "color": "DC143C" + }, + { + "name": "Bright Maroon", + "color": "C32148" + }, + { + "name": "Rose Red", + "color": "C21E56" + }, + { + "name": "Rogue Pink", + "color": "C12869" + }, + { + "name": "Burnt Pink", + "color": "C12267" + }, + { + "name": "Pink Violet", + "color": "CA226B" + }, + { + "name": "MediumVioletRed (W3C)", + "color": "C71585" + }, + { + "name": "Dark Carnation Pink", + "color": "C12283" + }, + { + "name": "Raspberry Purple", + "color": "B3446C" + }, + { + "name": "Pink Plum", + "color": "B93B8F" + }, + { + "name": "Orchid (W3C)", + "color": "DA70D6" + }, + { + "name": "Deep Mauve", + "color": "DF73D4" + }, + { + "name": "Violet (W3C)", + "color": "EE82EE" + }, + { + "name": "Bright Neon Pink", + "color": "F433FF" + }, + { + "name": "Fuchsia or Magenta (W3C)", + "color": "FF00FF" + }, + { + "name": "Crimson Purple", + "color": "E238EC" + }, + { + "name": "Heliotrope Purple", + "color": "D462FF" + }, + { + "name": "Tyrian Purple", + "color": "C45AEC" + }, + { + "name": "MediumOrchid (W3C)", + "color": "BA55D3" + }, + { + "name": "Purple Flower", + "color": "A74AC7" + }, + { + "name": "Orchid Purple", + "color": "B048B5" + }, + { + "name": "Pastel Violet", + "color": "D291BC" + }, + { + "name": "Mauve Taupe", + "color": "915F6D" + }, + { + "name": "Viola Purple", + "color": "7E587E" + }, + { + "name": "Eggplant", + "color": "614051" + }, + { + "name": "Plum Purple", + "color": "583759" + }, + { + "name": "Grape", + "color": "5E5A80" + }, + { + "name": "Purple Navy", + "color": "4E5180" + }, + { + "name": "SlateBlue (W3C)", + "color": "6A5ACD" + }, + { + "name": "Blue Lotus", + "color": "6960EC" + }, + { + "name": "Light Slate Blue", + "color": "736AFF" + }, + { + "name": "MediumSlateBlue (W3C)", + "color": "7B68EE" + }, + { + "name": "Periwinkle Purple", + "color": "7575CF" + }, + { + "name": "Very Peri", + "color": "6667AB" + }, + { + "name": "Bright Grape", + "color": "6F2DA8" + }, + { + "name": "Purple Amethyst", + "color": "6C2DC7" + }, + { + "name": "Bright Purple", + "color": "6A0DAD" + }, + { + "name": "Deep Periwinkle", + "color": "5453A6" + }, + { + "name": "DarkSlateBlue (W3C)", + "color": "483D8B" + }, + { + "name": "Purple Haze", + "color": "4E387E" + }, + { + "name": "Purple Iris", + "color": "571B7E" + }, + { + "name": "Dark Purple", + "color": "4B0150" + }, + { + "name": "Deep Purple", + "color": "36013F" + }, + { + "name": "Purple Monster", + "color": "461B7E" + }, + { + "name": "Indigo (W3C)", + "color": "4B0082" + }, + { + "name": "Blue Whale", + "color": "342D7E" + }, + { + "name": "RebeccaPurple (W3C)", + "color": "663399" + }, + { + "name": "Purple Jam", + "color": "6A287E" + }, + { + "name": "DarkMagenta (W3C)", + "color": "8B008B" + }, + { + "name": "Purple (W3C)", + "color": "800080" + }, + { + "name": "French Lilac", + "color": "86608E" + }, + { + "name": "DarkOrchid (W3C)", + "color": "9932CC" + }, + { + "name": "DarkViolet (W3C)", + "color": "9400D3" + }, + { + "name": "Purple Violet", + "color": "8D38C9" + }, + { + "name": "Jasmine Purple", + "color": "A23BEC" + }, + { + "name": "Purple Daffodil", + "color": "B041FF" + }, + { + "name": "Clematis Violet", + "color": "842DCE" + }, + { + "name": "BlueViolet (W3C)", + "color": "8A2BE2" + }, + { + "name": "Purple Sage Bush", + "color": "7A5DC7" + }, + { + "name": "Lovely Purple", + "color": "7F38EC" + }, + { + "name": "Neon Purple", + "color": "9D00FF" + }, + { + "name": "Purple Plum", + "color": "8E35EF" + }, + { + "name": "Aztech Purple", + "color": "893BFF" + }, + { + "name": "Lavender Purple", + "color": "967BB6" + }, + { + "name": "MediumPurple (W3C)", + "color": "9370DB" + }, + { + "name": "Light Purple", + "color": "8467D7" + }, + { + "name": "Crocus Purple", + "color": "9172EC" + }, + { + "name": "Purple Mimosa", + "color": "9E7BFF" + }, + { + "name": "Periwinkle", + "color": "CCCCFF" + }, + { + "name": "Pale Lilac", + "color": "DCD0FF" + }, + { + "name": "Mauve", + "color": "E0B0FF" + }, + { + "name": "Bright Lilac", + "color": "D891EF" + }, + { + "name": "Rich Lilac", + "color": "B666D2" + }, + { + "name": "Purple Dragon", + "color": "C38EC7" + }, + { + "name": "Lilac", + "color": "C8A2C8" + }, + { + "name": "Plum (W3C)", + "color": "DDA0DD" + }, + { + "name": "Blush Pink", + "color": "E6A9EC" + }, + { + "name": "Pastel Purple", + "color": "F2A2E8" + }, + { + "name": "Blossom Pink", + "color": "F9B7FF" + }, + { + "name": "Wisteria Purple", + "color": "C6AEC7" + }, + { + "name": "Purple Thistle", + "color": "D2B9D3" + }, + { + "name": "Thistle (W3C)", + "color": "D8BFD8" + }, + { + "name": "Periwinkle Pink", + "color": "E9CFEC" + }, + { + "name": "Cotton Candy", + "color": "FCDFFF" + }, + { + "name": "Lavender Pinocchio", + "color": "EBDDE2" + }, + { + "name": "Dark White", + "color": "E1D9D1" + }, + { + "name": "Ash White", + "color": "E9E4D4" + }, + { + "name": "White Chocolate", + "color": "EDE6D6" + }, + { + "name": "Soft Ivory", + "color": "FAF0DD" + }, + { + "name": "Off White", + "color": "F8F0E3" + }, + { + "name": "Pearl White", + "color": "F8F6F0" + }, + { + "name": "LavenderBlush (W3C)", + "color": "FFF0F5" + }, + { + "name": "Pearl", + "color": "FDEEF4" + }, + { + "name": "Egg Shell", + "color": "FFF9E3" + }, + { + "name": "OldLace (W3C)", + "color": "FDF5E6" + }, + { + "name": "Linen (W3C)", + "color": "FAF0E6" + }, + { + "name": "SeaShell (W3C)", + "color": "FFF5EE" + }, + { + "name": "Rice", + "color": "FAF5EF" + }, + { + "name": "FloralWhite (W3C)", + "color": "FFFAF0" + }, + { + "name": "Ivory (W3C)", + "color": "FFFFF0" + }, + { + "name": "Light White", + "color": "FFFFF7" + }, + { + "name": "WhiteSmoke (W3C)", + "color": "F5F5F5" + }, + { + "name": "Cotton", + "color": "FBFBF9" + }, + { + "name": "Snow (W3C)", + "color": "FFFAFA" + }, + { + "name": "Milk White", + "color": "FEFCFF" + }, + { + "name": "White (W3C)", + "color": "FFFFFF" + } + ] +} \ No newline at end of file diff --git a/smali/assets/vtl_themes/palettes/material.json b/smali/assets/vtl_themes/palettes/material.json new file mode 100644 index 000000000..410a548a5 --- /dev/null +++ b/smali/assets/vtl_themes/palettes/material.json @@ -0,0 +1,1118 @@ +{ + "palette_id": "material", + "name": "Material Palette", + "author": "Vologhat", + "palette": [ + { + "name": "Red", + "colors": [ + { + "index": "50", + "color": "FFEBEE" + }, + { + "index": "100", + "color": "FFCDD2" + }, + { + "index": "200", + "color": "EF9A9A" + }, + { + "index": "300", + "color": "E57373" + }, + { + "index": "400", + "color": "EF5350" + }, + { + "index": "500", + "color": "F44336" + }, + { + "index": "600", + "color": "E53935" + }, + { + "index": "700", + "color": "D32F2F" + }, + { + "index": "800", + "color": "C62828" + }, + { + "index": "900", + "color": "B71C1C" + }, + { + "index": "A700", + "color": "D50000" + }, + { + "index": "A100", + "color": "FF8A80" + }, + { + "index": "A200", + "color": "FF5252" + }, + { + "index": "A400", + "color": "FF1744" + } + ] + }, + { + "name": "Pink", + "colors": [ + { + "index": "50", + "color": "FCE4EC" + }, + { + "index": "100", + "color": "F8BBD0" + }, + { + "index": "200", + "color": "F48FB1" + }, + { + "index": "300", + "color": "F06292" + }, + { + "index": "400", + "color": "EC407A" + }, + { + "index": "500", + "color": "E91E63" + }, + { + "index": "600", + "color": "D81B60" + }, + { + "index": "700", + "color": "C2185B" + }, + { + "index": "800", + "color": "AD1457" + }, + { + "index": "900", + "color": "880E4F" + }, + { + "index": "A700", + "color": "C51162" + }, + { + "index": "A100", + "color": "FF80AB" + }, + { + "index": "A200", + "color": "FF4081" + }, + { + "index": "A400", + "color": "F50057" + } + ] + }, + { + "name": "Purple", + "colors": [ + { + "index": "50", + "color": "F3E5F5" + }, + { + "index": "100", + "color": "E1BEE7" + }, + { + "index": "200", + "color": "CE93D8" + }, + { + "index": "300", + "color": "BA68C8" + }, + { + "index": "400", + "color": "AB47BC" + }, + { + "index": "500", + "color": "9C27B0" + }, + { + "index": "600", + "color": "8E24AA" + }, + { + "index": "700", + "color": "7B1FA2" + }, + { + "index": "800", + "color": "6A1B9A" + }, + { + "index": "900", + "color": "4A148C" + }, + { + "index": "A700", + "color": "AA00FF" + }, + { + "index": "A100", + "color": "EA80FC" + }, + { + "index": "A200", + "color": "E040FB" + }, + { + "index": "A400", + "color": "D500F9" + } + ] + }, + { + "name": "Deep Purple", + "colors": [ + { + "index": "50", + "color": "EDE7F6" + }, + { + "index": "100", + "color": "D1C4E9" + }, + { + "index": "200", + "color": "B39DDB" + }, + { + "index": "300", + "color": "9575CD" + }, + { + "index": "400", + "color": "7E57C2" + }, + { + "index": "500", + "color": "673AB7" + }, + { + "index": "600", + "color": "5E35B1" + }, + { + "index": "700", + "color": "512DA8" + }, + { + "index": "800", + "color": "4527A0" + }, + { + "index": "900", + "color": "311B92" + }, + { + "index": "A700", + "color": "6200EA" + }, + { + "index": "A100", + "color": "B388FF" + }, + { + "index": "A200", + "color": "7C4DFF" + }, + { + "index": "A400", + "color": "651FFF" + } + ] + }, + { + "name": "Indigo", + "colors": [ + { + "index": "50", + "color": "E8EAF6" + }, + { + "index": "100", + "color": "C5CAE9" + }, + { + "index": "200", + "color": "9FA8DA" + }, + { + "index": "300", + "color": "7986CB" + }, + { + "index": "400", + "color": "5C6BC0" + }, + { + "index": "500", + "color": "3F51B5" + }, + { + "index": "600", + "color": "3949AB" + }, + { + "index": "700", + "color": "303F9F" + }, + { + "index": "800", + "color": "283593" + }, + { + "index": "900", + "color": "1A237E" + }, + { + "index": "A700", + "color": "304FFE" + }, + { + "index": "A100", + "color": "8C9EFF" + }, + { + "index": "A200", + "color": "536DFE" + }, + { + "index": "A400", + "color": "3D5AFE" + } + ] + }, + { + "name": "Blue", + "colors": [ + { + "index": "50", + "color": "E3F2FD" + }, + { + "index": "100", + "color": "BBDEFB" + }, + { + "index": "200", + "color": "90CAF9" + }, + { + "index": "300", + "color": "64B5F6" + }, + { + "index": "400", + "color": "42A5F5" + }, + { + "index": "500", + "color": "2196F3" + }, + { + "index": "600", + "color": "1E88E5" + }, + { + "index": "700", + "color": "1976D2" + }, + { + "index": "800", + "color": "1565C0" + }, + { + "index": "900", + "color": "0D47A1" + }, + { + "index": "A700", + "color": "2962FF" + }, + { + "index": "A100", + "color": "82B1FF" + }, + { + "index": "A200", + "color": "448AFF" + }, + { + "index": "A400", + "color": "2979FF" + } + ] + }, + { + "name": "Light Blue", + "colors": [ + { + "index": "50", + "color": "E1F5FE" + }, + { + "index": "100", + "color": "B3E5FC" + }, + { + "index": "200", + "color": "81D4FA" + }, + { + "index": "300", + "color": "4FC3F7" + }, + { + "index": "400", + "color": "29B6F6" + }, + { + "index": "500", + "color": "03A9F4" + }, + { + "index": "600", + "color": "039BE5" + }, + { + "index": "700", + "color": "0288D1" + }, + { + "index": "800", + "color": "0277BD" + }, + { + "index": "900", + "color": "01579B" + }, + { + "index": "A700", + "color": "0091EA" + }, + { + "index": "A100", + "color": "80D8FF" + }, + { + "index": "A200", + "color": "40C4FF" + }, + { + "index": "A400", + "color": "00B0FF" + } + ] + }, + { + "name": "Cyan", + "colors": [ + { + "index": "50", + "color": "E0F7FA" + }, + { + "index": "100", + "color": "B2EBF2" + }, + { + "index": "200", + "color": "80DEEA" + }, + { + "index": "300", + "color": "4DD0E1" + }, + { + "index": "400", + "color": "26C6DA" + }, + { + "index": "500", + "color": "00BCD4" + }, + { + "index": "600", + "color": "00ACC1" + }, + { + "index": "700", + "color": "0097A7" + }, + { + "index": "800", + "color": "00838F" + }, + { + "index": "900", + "color": "006064" + }, + { + "index": "A700", + "color": "00B8D4" + }, + { + "index": "A100", + "color": "84FFFF" + }, + { + "index": "A200", + "color": "18FFFF" + }, + { + "index": "A400", + "color": "00E5FF" + } + ] + }, + { + "name": "Teal", + "colors": [ + { + "index": "50", + "color": "E0F2F1" + }, + { + "index": "100", + "color": "B2DFDB" + }, + { + "index": "200", + "color": "80CBC4" + }, + { + "index": "300", + "color": "4DB6AC" + }, + { + "index": "400", + "color": "26A69A" + }, + { + "index": "500", + "color": "009688" + }, + { + "index": "600", + "color": "00897B" + }, + { + "index": "700", + "color": "00796B" + }, + { + "index": "800", + "color": "00695C" + }, + { + "index": "900", + "color": "004D40" + }, + { + "index": "A700", + "color": "00BFA5" + }, + { + "index": "A100", + "color": "A7FFEB" + }, + { + "index": "A200", + "color": "64FFDA" + }, + { + "index": "A400", + "color": "1DE9B6" + } + ] + }, + { + "name": "Green", + "colors": [ + { + "index": "50", + "color": "E8F5E9" + }, + { + "index": "100", + "color": "C8E6C9" + }, + { + "index": "200", + "color": "A5D6A7" + }, + { + "index": "300", + "color": "81C784" + }, + { + "index": "400", + "color": "66BB6A" + }, + { + "index": "500", + "color": "4CAF50" + }, + { + "index": "600", + "color": "43A047" + }, + { + "index": "700", + "color": "388E3C" + }, + { + "index": "800", + "color": "2E7D32" + }, + { + "index": "900", + "color": "1B5E20" + }, + { + "index": "A700", + "color": "00C853" + }, + { + "index": "A100", + "color": "B9F6CA" + }, + { + "index": "A200", + "color": "69F0AE" + }, + { + "index": "A400", + "color": "00E676" + } + ] + }, + { + "name": "Light Green", + "colors": [ + { + "index": "50", + "color": "F1F8E9" + }, + { + "index": "100", + "color": "DCEDC8" + }, + { + "index": "200", + "color": "C5E1A5" + }, + { + "index": "300", + "color": "AED581" + }, + { + "index": "400", + "color": "9CCC65" + }, + { + "index": "500", + "color": "8BC34A" + }, + { + "index": "600", + "color": "7CB342" + }, + { + "index": "700", + "color": "689F38" + }, + { + "index": "800", + "color": "558B2F" + }, + { + "index": "900", + "color": "33691E" + }, + { + "index": "A700", + "color": "64DD17" + }, + { + "index": "A100", + "color": "CCFF90" + }, + { + "index": "A200", + "color": "B2FF59" + }, + { + "index": "A400", + "color": "76FF03" + } + ] + }, + { + "name": "Lime", + "colors": [ + { + "index": "50", + "color": "F9FBE7" + }, + { + "index": "100", + "color": "F0F4C3" + }, + { + "index": "200", + "color": "E6EE9C" + }, + { + "index": "300", + "color": "DCE775" + }, + { + "index": "400", + "color": "D4E157" + }, + { + "index": "500", + "color": "CDDC39" + }, + { + "index": "600", + "color": "C0CA33" + }, + { + "index": "700", + "color": "AFB42B" + }, + { + "index": "800", + "color": "9E9D24" + }, + { + "index": "900", + "color": "827717" + }, + { + "index": "A700", + "color": "AEEA00" + }, + { + "index": "A100", + "color": "F4FF81" + }, + { + "index": "A200", + "color": "EEFF41" + }, + { + "index": "A400", + "color": "C6FF00" + } + ] + }, + { + "name": "Yellow", + "colors": [ + { + "index": "50", + "color": "FFFDE7" + }, + { + "index": "100", + "color": "FFF9C4" + }, + { + "index": "200", + "color": "FFF59D" + }, + { + "index": "300", + "color": "FFF176" + }, + { + "index": "400", + "color": "FFEE58" + }, + { + "index": "500", + "color": "FFEB3B" + }, + { + "index": "600", + "color": "FDD835" + }, + { + "index": "700", + "color": "FBC02D" + }, + { + "index": "800", + "color": "F9A825" + }, + { + "index": "900", + "color": "F57F17" + }, + { + "index": "A700", + "color": "FFD600" + }, + { + "index": "A100", + "color": "FFFF8D" + }, + { + "index": "A200", + "color": "FFFF00" + }, + { + "index": "A400", + "color": "FFEA00" + } + ] + }, + { + "name": "Amber", + "colors": [ + { + "index": "50", + "color": "FFF8E1" + }, + { + "index": "100", + "color": "FFECB3" + }, + { + "index": "200", + "color": "FFE082" + }, + { + "index": "300", + "color": "FFD54F" + }, + { + "index": "400", + "color": "FFCA28" + }, + { + "index": "500", + "color": "FFC107" + }, + { + "index": "600", + "color": "FFB300" + }, + { + "index": "700", + "color": "FFA000" + }, + { + "index": "800", + "color": "FF8F00" + }, + { + "index": "900", + "color": "FF6F00" + }, + { + "index": "A700", + "color": "FFAB00" + }, + { + "index": "A100", + "color": "FFE57F" + }, + { + "index": "A200", + "color": "FFD740" + }, + { + "index": "A400", + "color": "FFC400" + } + ] + }, + { + "name": "Orange", + "colors": [ + { + "index": "50", + "color": "FFF3E0" + }, + { + "index": "100", + "color": "FFE0B2" + }, + { + "index": "200", + "color": "FFCC80" + }, + { + "index": "300", + "color": "FFB74D" + }, + { + "index": "400", + "color": "FFA726" + }, + { + "index": "500", + "color": "FF9800" + }, + { + "index": "600", + "color": "FB8C00" + }, + { + "index": "700", + "color": "F57C00" + }, + { + "index": "800", + "color": "EF6C00" + }, + { + "index": "900", + "color": "E65100" + }, + { + "index": "A700", + "color": "FF6D00" + }, + { + "index": "A100", + "color": "FFD180" + }, + { + "index": "A200", + "color": "FFAB40" + }, + { + "index": "A400", + "color": "FF9100" + } + ] + }, + { + "name": "Deep Orange", + "colors": [ + { + "index": "50", + "color": "FBE9E7" + }, + { + "index": "100", + "color": "FFCCBC" + }, + { + "index": "200", + "color": "FFAB91" + }, + { + "index": "300", + "color": "FF8A65" + }, + { + "index": "400", + "color": "FF7043" + }, + { + "index": "500", + "color": "FF5722" + }, + { + "index": "600", + "color": "F4511E" + }, + { + "index": "700", + "color": "E64A19" + }, + { + "index": "800", + "color": "D84315" + }, + { + "index": "900", + "color": "BF360C" + }, + { + "index": "A700", + "color": "DD2C00" + }, + { + "index": "A100", + "color": "FF9E80" + }, + { + "index": "A200", + "color": "FF6E40" + }, + { + "index": "A400", + "color": "FF3D00" + } + ] + }, + { + "name": "Brown", + "colors": [ + { + "index": "50", + "color": "EFEBE9" + }, + { + "index": "100", + "color": "D7CCC8" + }, + { + "index": "200", + "color": "BCAAA4" + }, + { + "index": "300", + "color": "A1887F" + }, + { + "index": "400", + "color": "8D6E63" + }, + { + "index": "500", + "color": "795548" + }, + { + "index": "600", + "color": "6D4C41" + }, + { + "index": "700", + "color": "5D4037" + }, + { + "index": "800", + "color": "4E342E" + }, + { + "index": "900", + "color": "3E2723" + } + ] + }, + { + "name": "Grey", + "colors": [ + { + "index": "50", + "color": "FAFAFA" + }, + { + "index": "100", + "color": "F5F5F5" + }, + { + "index": "200", + "color": "EEEEEE" + }, + { + "index": "300", + "color": "E0E0E0" + }, + { + "index": "400", + "color": "BDBDBD" + }, + { + "index": "500", + "color": "9E9E9E" + }, + { + "index": "600", + "color": "757575" + }, + { + "index": "700", + "color": "616161" + }, + { + "index": "800", + "color": "424242" + }, + { + "index": "900", + "color": "212121" + } + ] + }, + { + "name": "Blue Grey", + "colors": [ + { + "index": "50", + "color": "ECEFF1" + }, + { + "index": "100", + "color": "CFD8DC" + }, + { + "index": "200", + "color": "B0BEC5" + }, + { + "index": "300", + "color": "90A4AE" + }, + { + "index": "400", + "color": "78909C" + }, + { + "index": "500", + "color": "607D8B" + }, + { + "index": "600", + "color": "546E7A" + }, + { + "index": "700", + "color": "455A64" + }, + { + "index": "800", + "color": "37474F" + }, + { + "index": "900", + "color": "263238" + } + ] + } + ] +} \ No newline at end of file diff --git a/smali/res/color/date_picker_selector.xml b/smali/res/color/date_picker_selector.xml index 8098bf4c3..50dd18041 100644 --- a/smali/res/color/date_picker_selector.xml +++ b/smali/res/color/date_picker_selector.xml @@ -1,6 +1,6 @@ - - + + \ No newline at end of file diff --git a/smali/res/color/newpost_button.xml b/smali/res/color/newpost_button.xml index b3477f219..cae72f5da 100644 --- a/smali/res/color/newpost_button.xml +++ b/smali/res/color/newpost_button.xml @@ -1,5 +1,5 @@ - + \ No newline at end of file diff --git a/smali/res/drawable/$notification_receive_28_60fps__0.xml b/smali/res/drawable/$notification_receive_28_60fps__0.xml index 83cbb505c..0fffece6c 100644 --- a/smali/res/drawable/$notification_receive_28_60fps__0.xml +++ b/smali/res/drawable/$notification_receive_28_60fps__0.xml @@ -22,7 +22,7 @@ @@ -36,7 +36,7 @@ diff --git a/smali/res/drawable/bg_button_posting_settings_active.xml b/smali/res/drawable/bg_button_posting_settings_active.xml index 0e5c7b20c..58f8f89ec 100644 --- a/smali/res/drawable/bg_button_posting_settings_active.xml +++ b/smali/res/drawable/bg_button_posting_settings_active.xml @@ -3,7 +3,7 @@ - + diff --git a/smali/res/drawable/bg_qr_promo.xml b/smali/res/drawable/bg_qr_promo.xml index 09450bdd4..9c1cb8be7 100644 --- a/smali/res/drawable/bg_qr_promo.xml +++ b/smali/res/drawable/bg_qr_promo.xml @@ -3,6 +3,6 @@ android:shape="rectangle"> \ No newline at end of file diff --git a/smali/res/drawable/bg_replies_new_count_badge.xml b/smali/res/drawable/bg_replies_new_count_badge.xml index 0d35fd2d6..4e9fa0d62 100644 --- a/smali/res/drawable/bg_replies_new_count_badge.xml +++ b/smali/res/drawable/bg_replies_new_count_badge.xml @@ -1,7 +1,7 @@ - + - + @@ -12,7 +12,7 @@ - + diff --git a/smali/res/drawable/checker_background.png b/smali/res/drawable/checker_background.png new file mode 100644 index 000000000..284f90695 Binary files /dev/null and b/smali/res/drawable/checker_background.png differ diff --git a/smali/res/drawable/ic_phone_56.xml b/smali/res/drawable/ic_phone_56.xml index ce0e4abcc..cd75d09d8 100644 --- a/smali/res/drawable/ic_phone_56.xml +++ b/smali/res/drawable/ic_phone_56.xml @@ -5,7 +5,7 @@ android:viewportWidth="56.0" android:viewportHeight="56.0"> \ No newline at end of file diff --git a/smali/res/drawable/inline_comments_reply_marker.xml b/smali/res/drawable/inline_comments_reply_marker.xml index f7b2821ae..6b3e71ee0 100644 --- a/smali/res/drawable/inline_comments_reply_marker.xml +++ b/smali/res/drawable/inline_comments_reply_marker.xml @@ -2,7 +2,7 @@ - + diff --git a/smali/res/drawable/picker_btn_light_blue_circle.xml b/smali/res/drawable/picker_btn_light_blue_circle.xml index 1bac39a0d..ba150ce9d 100644 --- a/smali/res/drawable/picker_btn_light_blue_circle.xml +++ b/smali/res/drawable/picker_btn_light_blue_circle.xml @@ -1,5 +1,5 @@ - + \ No newline at end of file diff --git a/smali/res/drawable/picker_cursor_sticker_text.xml b/smali/res/drawable/picker_cursor_sticker_text.xml index edfb1fa83..fc5492fe9 100644 --- a/smali/res/drawable/picker_cursor_sticker_text.xml +++ b/smali/res/drawable/picker_cursor_sticker_text.xml @@ -2,6 +2,6 @@ - + \ No newline at end of file diff --git a/smali/res/drawable/poll_select_photo_bg.xml b/smali/res/drawable/poll_select_photo_bg.xml index 7b40b96f7..402b7926a 100644 --- a/smali/res/drawable/poll_select_photo_bg.xml +++ b/smali/res/drawable/poll_select_photo_bg.xml @@ -13,7 +13,7 @@ diff --git a/smali/res/drawable/progress_video.xml b/smali/res/drawable/progress_video.xml index e1c60ac92..501efecc5 100644 --- a/smali/res/drawable/progress_video.xml +++ b/smali/res/drawable/progress_video.xml @@ -18,7 +18,7 @@ - + diff --git a/smali/res/drawable/progress_video_feed.xml b/smali/res/drawable/progress_video_feed.xml index 6964eb303..5ca70ebe5 100644 --- a/smali/res/drawable/progress_video_feed.xml +++ b/smali/res/drawable/progress_video_feed.xml @@ -9,7 +9,7 @@ - + diff --git a/smali/res/drawable/ripple_poster_item.xml b/smali/res/drawable/ripple_poster_item.xml index fc734f127..246e78c9d 100644 --- a/smali/res/drawable/ripple_poster_item.xml +++ b/smali/res/drawable/ripple_poster_item.xml @@ -1,3 +1,3 @@ \ No newline at end of file + android:color="@color/blue_200" /> \ No newline at end of file diff --git a/smali/res/drawable/video_progress_seekbar.xml b/smali/res/drawable/video_progress_seekbar.xml index 91d7c141e..501efecc5 100644 --- a/smali/res/drawable/video_progress_seekbar.xml +++ b/smali/res/drawable/video_progress_seekbar.xml @@ -18,7 +18,7 @@ - + diff --git a/smali/res/drawable/vk_auth_bg_circle_avatar_btn.xml b/smali/res/drawable/vk_auth_bg_circle_avatar_btn.xml index 5fd47b1c9..3eabcd8a3 100644 --- a/smali/res/drawable/vk_auth_bg_circle_avatar_btn.xml +++ b/smali/res/drawable/vk_auth_bg_circle_avatar_btn.xml @@ -3,7 +3,7 @@ - + diff --git a/smali/res/drawable/vkim_bg_dialog_bar_button_primary.xml b/smali/res/drawable/vkim_bg_dialog_bar_button_primary.xml index 1305fe313..e59a88bf6 100644 --- a/smali/res/drawable/vkim_bg_dialog_bar_button_primary.xml +++ b/smali/res/drawable/vkim_bg_dialog_bar_button_primary.xml @@ -1,6 +1,6 @@ - + \ No newline at end of file diff --git a/smali/res/drawable/vkim_fastscroll_thumb_pressed.xml b/smali/res/drawable/vkim_fastscroll_thumb_pressed.xml index 6e04b210d..5f7e6305c 100644 --- a/smali/res/drawable/vkim_fastscroll_thumb_pressed.xml +++ b/smali/res/drawable/vkim_fastscroll_thumb_pressed.xml @@ -5,7 +5,7 @@ android:right="10.0dip" android:top="8.0dip"> - + diff --git a/smali/res/drawable/vkim_msg_part_audio_progress.xml b/smali/res/drawable/vkim_msg_part_audio_progress.xml index 1472f1505..de4f3cc81 100644 --- a/smali/res/drawable/vkim_msg_part_audio_progress.xml +++ b/smali/res/drawable/vkim_msg_part_audio_progress.xml @@ -23,7 +23,7 @@ + android:color="@color/header_blue" /> diff --git a/smali/res/drawable/vkim_msg_part_audio_thumb.xml b/smali/res/drawable/vkim_msg_part_audio_thumb.xml index 82069ffaf..908759384 100644 --- a/smali/res/drawable/vkim_msg_part_audio_thumb.xml +++ b/smali/res/drawable/vkim_msg_part_audio_thumb.xml @@ -1,7 +1,7 @@ - + diff --git a/smali/res/drawable/vkui_bg_default_active_cell.xml b/smali/res/drawable/vkui_bg_default_active_cell.xml index ce7641fe5..5534687cb 100644 --- a/smali/res/drawable/vkui_bg_default_active_cell.xml +++ b/smali/res/drawable/vkui_bg_default_active_cell.xml @@ -5,5 +5,5 @@ + android:color="?accent" /> \ No newline at end of file diff --git a/smali/res/drawable/vkui_btn_circle_avatar.xml b/smali/res/drawable/vkui_btn_circle_avatar.xml index 9a7b2e0b9..7a94b25bc 100644 --- a/smali/res/drawable/vkui_btn_circle_avatar.xml +++ b/smali/res/drawable/vkui_btn_circle_avatar.xml @@ -3,7 +3,7 @@ - + diff --git a/smali/res/drawable/voip_button_send_normal.xml b/smali/res/drawable/voip_button_send_normal.xml index e012fb9dd..ba150ce9d 100644 --- a/smali/res/drawable/voip_button_send_normal.xml +++ b/smali/res/drawable/voip_button_send_normal.xml @@ -1,5 +1,5 @@ - + \ No newline at end of file diff --git a/smali/res/layout/color_picker_item.xml b/smali/res/layout/color_picker_item.xml new file mode 100644 index 000000000..c8e98abef --- /dev/null +++ b/smali/res/layout/color_picker_item.xml @@ -0,0 +1,48 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/smali/res/layout/gift_send_add.xml b/smali/res/layout/gift_send_add.xml index 0a7f0a635..0daded13f 100644 --- a/smali/res/layout/gift_send_add.xml +++ b/smali/res/layout/gift_send_add.xml @@ -8,5 +8,5 @@ android:paddingLeft="28.0dip" android:paddingRight="16.0dip" android:text="@string/gifts_add_recipient" - android:textColor="#ff5181b8" + android:textColor="@color/header_blue" android:textSize="16.0dip" /> \ No newline at end of file diff --git a/smali/res/layout/group_edit_manager.xml b/smali/res/layout/group_edit_manager.xml index 4aee6669e..c744bf171 100644 --- a/smali/res/layout/group_edit_manager.xml +++ b/smali/res/layout/group_edit_manager.xml @@ -258,7 +258,7 @@ android:paddingRight="@dimen/post_side_padding" android:text="@string/group_remove_manager" android:textAllCaps="true" - android:textColor="#ff5181b8" + android:textColor="@color/header_blue" android:textSize="14.0dip" app:overlay="@drawable/highlight_post" /> diff --git a/smali/res/layout/layout_story_view.xml b/smali/res/layout/layout_story_view.xml index ace625b65..d8e38cc8e 100644 --- a/smali/res/layout/layout_story_view.xml +++ b/smali/res/layout/layout_story_view.xml @@ -304,7 +304,7 @@ android:singleLine="true" android:text="@string/story_retry" android:textAllCaps="true" - android:textColor="#ff74a2d6" + android:textColor="@color/blue_200_muted" android:textSize="14.0sp" /> diff --git a/smali/res/layout/picker_layout_text_sticker_dialog.xml b/smali/res/layout/picker_layout_text_sticker_dialog.xml index b77eb9eb6..3955cfcbb 100644 --- a/smali/res/layout/picker_layout_text_sticker_dialog.xml +++ b/smali/res/layout/picker_layout_text_sticker_dialog.xml @@ -30,7 +30,7 @@ android:paddingEnd="32.0dip" android:paddingBottom="100.0dip" android:textColor="#ffffffff" - android:textColorHighlight="#665c9ce6" + android:textColorHighlight="@color/blue_200" android:textCursorDrawable="@drawable/picker_cursor_sticker_text" android:textSize="40.0sp" /> diff --git a/smali/res/layout/poll_edit.xml b/smali/res/layout/poll_edit.xml index daace2883..5b2977584 100644 --- a/smali/res/layout/poll_edit.xml +++ b/smali/res/layout/poll_edit.xml @@ -66,7 +66,7 @@ android:paddingRight="16.0dip" android:paddingBottom="16.0dip" android:text="@string/poll_options_header" - android:textColor="#ff5181b8" + android:textColor="@color/header_blue" android:textSize="14.0dip" app:typeface="Medium" /> @@ -80,7 +80,7 @@ android:paddingRight="16.0dip" android:text="@string/poll_add_option" android:textAllCaps="true" - android:textColor="#ff5181b8" + android:textColor="@color/header_blue" android:textSize="14.0dip" app:typeface="Medium" /> @@ -105,7 +105,7 @@ android:paddingRight="16.0dip" android:paddingBottom="16.0dip" android:text="@string/poll_settings" - android:textColor="#ff5181b8" + android:textColor="@color/header_blue" android:textSize="14.0dip" app:typeface="Medium" /> diff --git a/smali/res/layout/profile_edit.xml b/smali/res/layout/profile_edit.xml index 93f0430c8..68a26c921 100644 --- a/smali/res/layout/profile_edit.xml +++ b/smali/res/layout/profile_edit.xml @@ -64,7 +64,7 @@ android:padding="8.0dip" android:text="@string/add_photo" android:textAllCaps="true" - android:textColor="#ff5181b8" + android:textColor="@color/header_blue" android:textSize="12.0dip" /> diff --git a/smali/res/layout/recover_search.xml b/smali/res/layout/recover_search.xml index 8d9d91b7a..81729273a 100644 --- a/smali/res/layout/recover_search.xml +++ b/smali/res/layout/recover_search.xml @@ -50,7 +50,7 @@ android:layout_gravity="center_vertical" android:scaleType="centerInside" android:src="@drawable/ic_search_params_24" - android:tint="#ff528bcc" /> + android:tint="@color/accent_blue" /> \ No newline at end of file diff --git a/smali/res/layout/vkim_offline_list_item_for_peers.xml b/smali/res/layout/vkim_offline_list_item_for_peers.xml index 144af712e..9293cc1b5 100644 --- a/smali/res/layout/vkim_offline_list_item_for_peers.xml +++ b/smali/res/layout/vkim_offline_list_item_for_peers.xml @@ -41,7 +41,7 @@ android:fontFamily="sans-serif-medium" android:gravity="end" android:text="@string/vkim_search_try_again" - android:textColor="#ff528bcc" + android:textColor="@color/accent_blue" android:textSize="14.0sp" android:textStyle="normal" /> \ No newline at end of file diff --git a/smali/res/values-ru/arrays.xml b/smali/res/values-ru/arrays.xml index 5c4555874..fc4d750c8 100644 --- a/smali/res/values-ru/arrays.xml +++ b/smali/res/values-ru/arrays.xml @@ -689,4 +689,8 @@ Темная тема Светлая тема + + Выбрать вручную + Предустановленные цвета + diff --git a/smali/res/values-ru/strings.xml b/smali/res/values-ru/strings.xml index 6413d57c7..3313f3f93 100644 --- a/smali/res/values-ru/strings.xml +++ b/smali/res/values-ru/strings.xml @@ -6319,4 +6319,13 @@ Не получать промостикеры Использовать старый дизайн Работает \"как есть\". Могут быть ошибки + + Скачивание обновления + Источники + Отключить бизнес-уведомления + Цвет акцента + Цвет акцента в приложении + Выберите цвет акцента + Выберите палитру цветов + Выберите цвет \ No newline at end of file diff --git a/smali/res/values-v31/styles.xml b/smali/res/values-v31/styles.xml new file mode 100644 index 000000000..2fca6bb3b --- /dev/null +++ b/smali/res/values-v31/styles.xml @@ -0,0 +1,2126 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/smali/res/values/arrays.xml b/smali/res/values/arrays.xml index bf64b72bf..e200a0223 100644 --- a/smali/res/values/arrays.xml +++ b/smali/res/values/arrays.xml @@ -889,4 +889,8 @@ Dark theme Light theme + + Color Picker + From Palettes + diff --git a/smali/res/values/public.xml b/smali/res/values/public.xml index ad152e46d..056c40213 100644 --- a/smali/res/values/public.xml +++ b/smali/res/values/public.xml @@ -6867,6 +6867,10 @@ + + + + diff --git a/smali/res/values/strings.xml b/smali/res/values/strings.xml index 7eb4f573e..0d7016a34 100644 --- a/smali/res/values/strings.xml +++ b/smali/res/values/strings.xml @@ -6457,4 +6457,13 @@ May look like a fake leaving the online" Don\'t receive promoted stickers Use old music catalog Works \"as is\". There may be errors + + Downloading update + Sources + Disable business notifications + Accent color + Accent color in app + Change accent color + Select palette + Select color diff --git a/smali/res/values/styles.xml b/smali/res/values/styles.xml index 123775232..ef80fd093 100644 --- a/smali/res/values/styles.xml +++ b/smali/res/values/styles.xml @@ -9209,8 +9209,6 @@ @menu/bottom_navigation_milkshake - - -