From c884a7823515ec305d12d37dd105011c03c54c85 Mon Sep 17 00:00:00 2001 From: DrDisagree Date: Sat, 17 Aug 2024 12:53:40 +0600 Subject: [PATCH 1/7] Revert "Migrate a part to MVVM arch (#93)" This reverts commit 36660010 --- .../ui/fragments/ColorsFragment.java | 229 ++++++++++-------- .../ui/fragments/ThemeFragment.java | 214 ++++++++++++---- .../ui/repositories/ColorRepository.java | 64 ----- .../ui/repositories/ThemeRepository.java | 84 ------- .../ui/viewmodels/ColorsViewModel.java | 69 ------ .../ui/viewmodels/ThemeViewModel.java | 154 ------------ app/src/main/res/layout/fragment_colors.xml | 19 +- 7 files changed, 290 insertions(+), 543 deletions(-) delete mode 100644 app/src/main/java/com/drdisagree/colorblendr/ui/repositories/ColorRepository.java delete mode 100644 app/src/main/java/com/drdisagree/colorblendr/ui/repositories/ThemeRepository.java delete mode 100644 app/src/main/java/com/drdisagree/colorblendr/ui/viewmodels/ColorsViewModel.java delete mode 100644 app/src/main/java/com/drdisagree/colorblendr/ui/viewmodels/ThemeViewModel.java diff --git a/app/src/main/java/com/drdisagree/colorblendr/ui/fragments/ColorsFragment.java b/app/src/main/java/com/drdisagree/colorblendr/ui/fragments/ColorsFragment.java index a52149a..73ecf38 100644 --- a/app/src/main/java/com/drdisagree/colorblendr/ui/fragments/ColorsFragment.java +++ b/app/src/main/java/com/drdisagree/colorblendr/ui/fragments/ColorsFragment.java @@ -1,10 +1,18 @@ package com.drdisagree.colorblendr.ui.fragments; +import static com.drdisagree.colorblendr.common.Const.MONET_LAST_UPDATED; +import static com.drdisagree.colorblendr.common.Const.MONET_SEED_COLOR; +import static com.drdisagree.colorblendr.common.Const.MONET_SEED_COLOR_ENABLED; +import static com.drdisagree.colorblendr.common.Const.WALLPAPER_COLOR_LIST; + import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; +import android.graphics.Color; import android.os.Bundle; +import android.os.Handler; +import android.os.Looper; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -18,12 +26,21 @@ import com.drdisagree.colorblendr.R; import com.drdisagree.colorblendr.common.Const; +import com.drdisagree.colorblendr.config.RPrefs; import com.drdisagree.colorblendr.databinding.FragmentColorsBinding; -import com.drdisagree.colorblendr.ui.viewmodels.ColorsViewModel; +import com.drdisagree.colorblendr.ui.viewmodels.SharedViewModel; import com.drdisagree.colorblendr.ui.views.WallColorPreview; +import com.drdisagree.colorblendr.utils.ColorUtil; import com.drdisagree.colorblendr.utils.MiscUtil; +import com.drdisagree.colorblendr.utils.OverlayManager; +import com.drdisagree.colorblendr.utils.WallpaperColorUtil; +import com.google.gson.reflect.TypeToken; +import java.util.ArrayList; +import java.util.Arrays; import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; import me.jfenn.colorpickerdialog.dialogs.ColorPickerDialog; import me.jfenn.colorpickerdialog.views.picker.ImagePickerView; @@ -31,16 +48,16 @@ @SuppressWarnings("deprecation") public class ColorsFragment extends Fragment { + private static final String TAG = ColorsFragment.class.getSimpleName(); private FragmentColorsBinding binding; - private ColorsViewModel colorsViewModel; - private int monetSeedColor; + private int[] monetSeedColor; + private SharedViewModel sharedViewModel; private final boolean notShizukuMode = Const.getWorkingMethod() != Const.WORK_METHOD.SHIZUKU; - private final BroadcastReceiver wallpaperChangedReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, android.content.Intent intent) { if (binding.colorsToggleGroup.getCheckedButtonId() == R.id.wallpaper_colors_button) { - colorsViewModel.loadWallpaperColors(); + addWallpaperColorItems(); } } }; @@ -49,7 +66,7 @@ public void onReceive(Context context, android.content.Intent intent) { public void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); - colorsViewModel = new ViewModelProvider(requireActivity()).get(ColorsViewModel.class); + sharedViewModel = new ViewModelProvider(requireActivity()).get(SharedViewModel.class); if (!notShizukuMode) { SettingsFragment.clearCustomColors(); @@ -60,57 +77,74 @@ public void onCreate(@Nullable Bundle savedInstanceState) { public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { binding = FragmentColorsBinding.inflate(inflater, container, false); - setupViews(); - observeViewModel(); + MiscUtil.setToolbarTitle(requireContext(), R.string.app_name, false, binding.header.toolbar); + + monetSeedColor = new int[]{RPrefs.getInt( + MONET_SEED_COLOR, + WallpaperColorUtil.getWallpaperColor(requireContext()) + )}; return binding.getRoot(); } - private void setupViews() { - MiscUtil.setToolbarTitle(requireContext(), R.string.app_name, false, binding.header.toolbar); + @Override + public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + + sharedViewModel.getVisibilityStates().observe(getViewLifecycleOwner(), this::updateViewVisibility); - // Color preview container + // Color codes binding.colorsToggleGroup.check( - colorsViewModel.isMonetSeedColorEnabled() ? + RPrefs.getBoolean(MONET_SEED_COLOR_ENABLED, false) ? R.id.basic_colors_button : R.id.wallpaper_colors_button ); binding.colorsToggleGroup.addOnButtonCheckedListener((group, checkedId, isChecked) -> { if (isChecked) { if (checkedId == R.id.wallpaper_colors_button) { - binding.wallpaperColorsContainer.setVisibility(View.VISIBLE); - binding.basicColorsContainer.setVisibility(View.GONE); + addWallpaperColorItems(); } else { - binding.wallpaperColorsContainer.setVisibility(View.GONE); - binding.basicColorsContainer.setVisibility(View.VISIBLE); + addBasicColorItems(); } } }); - if (binding.colorsToggleGroup.getCheckedButtonId() == R.id.wallpaper_colors_button) { - binding.wallpaperColorsContainer.setVisibility(View.VISIBLE); - binding.basicColorsContainer.setVisibility(View.GONE); + if (RPrefs.getBoolean(MONET_SEED_COLOR_ENABLED, false)) { + addBasicColorItems(); } else { - binding.wallpaperColorsContainer.setVisibility(View.GONE); - binding.basicColorsContainer.setVisibility(View.VISIBLE); + addWallpaperColorItems(); } - // Primary color picker + // Primary color + binding.seedColorPicker.setPreviewColor(RPrefs.getInt( + MONET_SEED_COLOR, + monetSeedColor[0] + )); binding.seedColorPicker.setOnClickListener(v -> new ColorPickerDialog() .withCornerRadius(10) - .withColor(monetSeedColor) + .withColor(monetSeedColor[0]) .withAlphaEnabled(false) .withPicker(ImagePickerView.class) .withListener((pickerView, color) -> { - if (monetSeedColor != color) { - monetSeedColor = color; + if (monetSeedColor[0] != color) { + monetSeedColor[0] = color; binding.seedColorPicker.setPreviewColor(color); - colorsViewModel.setMonetSeedColor(color); + RPrefs.putInt(MONET_SEED_COLOR, monetSeedColor[0]); + RPrefs.putLong(MONET_LAST_UPDATED, System.currentTimeMillis()); + new Handler(Looper.getMainLooper()).postDelayed(() -> { + try { + OverlayManager.applyFabricatedColors(requireContext()); + } catch (Exception ignored) { + } + }, 300); } }) .show(getChildFragmentManager(), "seedColorPicker") ); - - reinitSeedColorPickerVisibility(); + binding.seedColorPicker.setVisibility( + RPrefs.getBoolean(MONET_SEED_COLOR_ENABLED, false) ? + View.VISIBLE : + View.GONE + ); // Color palette binding.colorPalette.setOnClickListener(v -> HomeFragment.replaceFragment(new ColorPaletteFragment())); @@ -120,92 +154,85 @@ private void setupViews() { binding.perAppTheme.setEnabled(notShizukuMode); } - private void observeViewModel() { - colorsViewModel.getMonetSeedColorLiveData().observe(getViewLifecycleOwner(), color -> { - monetSeedColor = color; - binding.seedColorPicker.setPreviewColor(color); - }); - - colorsViewModel.getWallpaperColorsLiveData().observe(getViewLifecycleOwner(), this::addWallpaperColorsToContainer); - colorsViewModel.getBasicColorsLiveData().observe(getViewLifecycleOwner(), this::addBasicColorsToContainer); - } - - private void addWallpaperColorsToContainer(List colorList) { - binding.wallpaperColorsContainer.removeAllViews(); - - for (int color : colorList) { - WallColorPreview colorPreview = createWallColorPreview(color, true); - binding.wallpaperColorsContainer.addView(colorPreview); + private void updateViewVisibility(Map visibilityStates) { + Integer seedColorVisibility = visibilityStates.get(MONET_SEED_COLOR_ENABLED); + if (seedColorVisibility != null && binding.seedColorPicker.getVisibility() != seedColorVisibility) { + binding.seedColorPicker.setVisibility(seedColorVisibility); + + String wallpaperColors = RPrefs.getString(WALLPAPER_COLOR_LIST, null); + ArrayList wallpaperColorList = Const.GSON.fromJson( + wallpaperColors, + new TypeToken>() { + }.getType() + ); + + if (seedColorVisibility == View.GONE) { + monetSeedColor = new int[]{wallpaperColorList.get(0)}; + binding.seedColorPicker.setPreviewColor(monetSeedColor[0]); + } else { + monetSeedColor = new int[]{RPrefs.getInt( + MONET_SEED_COLOR, + wallpaperColorList.get(0) + )}; + binding.seedColorPicker.setPreviewColor(monetSeedColor[0]); + } } } - private void addBasicColorsToContainer(List colorList) { - binding.basicColorsContainer.removeAllViews(); + private void addWallpaperColorItems() { + String wallpaperColors = RPrefs.getString(WALLPAPER_COLOR_LIST, null); + ArrayList wallpaperColorList; - for (int color : colorList) { - WallColorPreview colorPreview = createWallColorPreview(color, false); - binding.basicColorsContainer.addView(colorPreview); + if (wallpaperColors != null) { + wallpaperColorList = Const.GSON.fromJson( + wallpaperColors, + new TypeToken>() { + }.getType() + ); + } else { + wallpaperColorList = ColorUtil.getMonetAccentColors(); } + + addColorsToContainer(wallpaperColorList, true); } @SuppressWarnings("all") - private @NonNull WallColorPreview createWallColorPreview(int color, boolean isWallpaperColor) { - WallColorPreview colorPreview = new WallColorPreview(requireContext()); - - int size = (int) (48 * getResources().getDisplayMetrics().density); - int margin = (int) (12 * getResources().getDisplayMetrics().density); - - LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(size, size); - layoutParams.setMargins(margin, margin, margin, margin); - - colorPreview.setLayoutParams(layoutParams); - colorPreview.setMainColor(color); - colorPreview.setTag(color); - colorPreview.setSelected(color == colorsViewModel.getMonetSeedColorLiveData().getValue()); - - colorPreview.setOnClickListener(v -> { - updateColorSelection(color, isWallpaperColor); - binding.seedColorPicker.setPreviewColor(color); - colorsViewModel.setMonetSeedColorEnabled(!isWallpaperColor); - reinitSeedColorPickerVisibility(); - colorsViewModel.setMonetSeedColor(color); - }); + private void addBasicColorItems() { + String[] basicColors = getResources().getStringArray(R.array.basic_color_codes); + List basicColorList = Arrays.stream(basicColors) + .map(Color::parseColor) + .collect(Collectors.toList()); - return colorPreview; + addColorsToContainer(new ArrayList<>(basicColorList), false); } - private void updateColorSelection(int selectedColor, boolean isWallpaperColor) { - ViewGroup parent = isWallpaperColor ? - binding.wallpaperColorsContainer : - binding.basicColorsContainer; - ViewGroup otherParent = isWallpaperColor ? - binding.basicColorsContainer : - binding.wallpaperColorsContainer; - - int count = parent.getChildCount(); - int otherCount = otherParent.getChildCount(); - - for (int i = 0; i < count; i++) { - if (parent.getChildAt(i) instanceof WallColorPreview colorPreview) { - colorPreview.setSelected((Integer) colorPreview.getTag() == selectedColor); - } - } - - for (int i = 0; i < otherCount; i++) { - if (otherParent.getChildAt(i) instanceof WallColorPreview colorPreview) { - colorPreview.setSelected(false); - } + private void addColorsToContainer(ArrayList colorList, boolean isWallpaperColors) { + binding.colorsContainer.removeAllViews(); + + for (int i = 0; i < colorList.size(); i++) { + int size = (int) (48 * getResources().getDisplayMetrics().density); + int margin = (int) (12 * getResources().getDisplayMetrics().density); + + WallColorPreview colorPreview = new WallColorPreview(requireContext()); + LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(size, size); + layoutParams.setMargins(margin, margin, margin, margin); + colorPreview.setLayoutParams(layoutParams); + colorPreview.setMainColor(colorList.get(i)); + colorPreview.setTag(colorList.get(i)); + colorPreview.setSelected(colorList.get(i) == RPrefs.getInt(MONET_SEED_COLOR, Integer.MIN_VALUE)); + + colorPreview.setOnClickListener(v -> { + RPrefs.putInt(MONET_SEED_COLOR, (Integer) colorPreview.getTag()); + RPrefs.putBoolean(MONET_SEED_COLOR_ENABLED, !isWallpaperColors); + binding.seedColorPicker.setPreviewColor((Integer) colorPreview.getTag()); + RPrefs.putLong(MONET_LAST_UPDATED, System.currentTimeMillis()); + OverlayManager.applyFabricatedColors(requireContext()); + }); + + binding.colorsContainer.addView(colorPreview); } } - private void reinitSeedColorPickerVisibility() { - binding.seedColorPicker.setVisibility( - colorsViewModel.isMonetSeedColorEnabled() ? - View.VISIBLE : - View.GONE - ); - } - @Override public void onResume() { super.onResume(); @@ -225,4 +252,4 @@ public void onDestroy() { } super.onDestroy(); } -} +} \ No newline at end of file diff --git a/app/src/main/java/com/drdisagree/colorblendr/ui/fragments/ThemeFragment.java b/app/src/main/java/com/drdisagree/colorblendr/ui/fragments/ThemeFragment.java index e6f42de..33a2f96 100644 --- a/app/src/main/java/com/drdisagree/colorblendr/ui/fragments/ThemeFragment.java +++ b/app/src/main/java/com/drdisagree/colorblendr/ui/fragments/ThemeFragment.java @@ -1,10 +1,17 @@ package com.drdisagree.colorblendr.ui.fragments; import static com.drdisagree.colorblendr.common.Const.MONET_ACCENT_SATURATION; +import static com.drdisagree.colorblendr.common.Const.MONET_ACCURATE_SHADES; import static com.drdisagree.colorblendr.common.Const.MONET_BACKGROUND_LIGHTNESS; import static com.drdisagree.colorblendr.common.Const.MONET_BACKGROUND_SATURATION; +import static com.drdisagree.colorblendr.common.Const.MONET_LAST_UPDATED; +import static com.drdisagree.colorblendr.common.Const.MONET_PITCH_BLACK_THEME; +import static com.drdisagree.colorblendr.common.Const.MONET_STYLE; import android.os.Bundle; +import android.os.Handler; +import android.os.Looper; +import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -13,41 +20,32 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.fragment.app.Fragment; -import androidx.lifecycle.ViewModelProvider; import com.drdisagree.colorblendr.R; +import com.drdisagree.colorblendr.common.Const; import com.drdisagree.colorblendr.config.RPrefs; import com.drdisagree.colorblendr.databinding.FragmentThemeBinding; -import com.drdisagree.colorblendr.ui.viewmodels.ThemeViewModel; -import com.drdisagree.colorblendr.ui.views.ColorPreview; +import com.drdisagree.colorblendr.utils.ColorSchemeUtil; +import com.drdisagree.colorblendr.utils.ColorUtil; import com.drdisagree.colorblendr.utils.MiscUtil; +import com.drdisagree.colorblendr.utils.OverlayManager; import com.drdisagree.colorblendr.utils.SystemUtil; import java.util.ArrayList; public class ThemeFragment extends Fragment { + private static final String TAG = ThemeFragment.class.getSimpleName(); private FragmentThemeBinding binding; - private ThemeViewModel themeViewModel; - - @Override - public void onCreate(@Nullable Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - themeViewModel = new ViewModelProvider(requireActivity()).get(ThemeViewModel.class); - } + private final int[] monetAccentSaturation = new int[]{RPrefs.getInt(MONET_ACCENT_SATURATION, 100)}; + private final int[] monetBackgroundSaturation = new int[]{RPrefs.getInt(MONET_BACKGROUND_SATURATION, 100)}; + private final int[] monetBackgroundLightness = new int[]{RPrefs.getInt(MONET_BACKGROUND_LIGHTNESS, 100)}; + private final boolean notShizukuMode = Const.getWorkingMethod() != Const.WORK_METHOD.SHIZUKU; @Override public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { binding = FragmentThemeBinding.inflate(inflater, container, false); - setupViews(); - observeViewModel(); - - return binding.getRoot(); - } - - private void setupViews() { MiscUtil.setToolbarTitle(requireContext(), R.string.theme, true, binding.header.toolbar); // Color preview titles @@ -63,7 +61,8 @@ private void setupViews() { @Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { binding.accentSaturation.setSelectedProgress(); - themeViewModel.updateAccentSaturation(progress); + monetAccentSaturation[0] = progress; + updatePreviewColors(); } @Override @@ -72,16 +71,33 @@ public void onStartTrackingTouch(SeekBar seekBar) { @Override public void onStopTrackingTouch(SeekBar seekBar) { - themeViewModel.setAccentSaturation(seekBar.getProgress()); + monetAccentSaturation[0] = seekBar.getProgress(); + RPrefs.putInt(MONET_ACCENT_SATURATION, monetAccentSaturation[0]); + RPrefs.putLong(MONET_LAST_UPDATED, System.currentTimeMillis()); + new Handler(Looper.getMainLooper()).postDelayed(() -> { + try { + OverlayManager.applyFabricatedColors(requireContext()); + } catch (Exception ignored) { + } + }, 200); } }); // Long Click Reset binding.accentSaturation.setResetClickListener(v -> { - themeViewModel.resetAccentSaturation(); + monetAccentSaturation[0] = 100; + updatePreviewColors(); + RPrefs.clearPref(MONET_ACCENT_SATURATION); + RPrefs.putLong(MONET_LAST_UPDATED, System.currentTimeMillis()); + new Handler(Looper.getMainLooper()).postDelayed(() -> { + try { + OverlayManager.applyFabricatedColors(requireContext()); + } catch (Exception ignored) { + } + }, 200); return true; }); - binding.accentSaturation.setEnabled(themeViewModel.isNotShizukuMode()); + binding.accentSaturation.setEnabled(notShizukuMode); // Monet background saturation binding.backgroundSaturation.setSeekbarProgress(RPrefs.getInt(MONET_BACKGROUND_SATURATION, 100)); @@ -89,7 +105,8 @@ public void onStopTrackingTouch(SeekBar seekBar) { @Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { binding.backgroundSaturation.setSelectedProgress(); - themeViewModel.updateBackgroundSaturation(progress); + monetBackgroundSaturation[0] = progress; + updatePreviewColors(); } @Override @@ -98,16 +115,33 @@ public void onStartTrackingTouch(SeekBar seekBar) { @Override public void onStopTrackingTouch(@NonNull SeekBar seekBar) { - themeViewModel.setBackgroundSaturation(seekBar.getProgress()); + monetBackgroundSaturation[0] = seekBar.getProgress(); + RPrefs.putInt(MONET_BACKGROUND_SATURATION, monetBackgroundSaturation[0]); + RPrefs.putLong(MONET_LAST_UPDATED, System.currentTimeMillis()); + new Handler(Looper.getMainLooper()).postDelayed(() -> { + try { + OverlayManager.applyFabricatedColors(requireContext()); + } catch (Exception ignored) { + } + }, 200); } }); // Reset button binding.backgroundSaturation.setResetClickListener(v -> { - themeViewModel.resetBackgroundSaturation(); + monetBackgroundSaturation[0] = 100; + updatePreviewColors(); + RPrefs.clearPref(MONET_BACKGROUND_SATURATION); + RPrefs.putLong(MONET_LAST_UPDATED, System.currentTimeMillis()); + new Handler(Looper.getMainLooper()).postDelayed(() -> { + try { + OverlayManager.applyFabricatedColors(requireContext()); + } catch (Exception ignored) { + } + }, 200); return true; }); - binding.backgroundSaturation.setEnabled(themeViewModel.isNotShizukuMode()); + binding.backgroundSaturation.setEnabled(notShizukuMode); // Monet background lightness binding.backgroundLightness.setSeekbarProgress(RPrefs.getInt(MONET_BACKGROUND_LIGHTNESS, 100)); @@ -115,7 +149,8 @@ public void onStopTrackingTouch(@NonNull SeekBar seekBar) { @Override public void onProgressChanged(@NonNull SeekBar seekBar, int progress, boolean fromUser) { binding.backgroundLightness.setSelectedProgress(); - themeViewModel.updateBackgroundLightness(progress); + monetBackgroundLightness[0] = progress; + updatePreviewColors(); } @Override @@ -124,43 +159,116 @@ public void onStartTrackingTouch(@NonNull SeekBar seekBar) { @Override public void onStopTrackingTouch(@NonNull SeekBar seekBar) { - themeViewModel.setBackgroundLightness(seekBar.getProgress()); + monetBackgroundLightness[0] = seekBar.getProgress(); + RPrefs.putInt(MONET_BACKGROUND_LIGHTNESS, monetBackgroundLightness[0]); + RPrefs.putLong(MONET_LAST_UPDATED, System.currentTimeMillis()); + new Handler(Looper.getMainLooper()).postDelayed(() -> { + try { + OverlayManager.applyFabricatedColors(requireContext()); + } catch (Exception ignored) { + } + }, 200); } }); // Long Click Reset binding.backgroundLightness.setResetClickListener(v -> { - themeViewModel.resetBackgroundLightness(); + monetBackgroundLightness[0] = 100; + updatePreviewColors(); + RPrefs.clearPref(MONET_BACKGROUND_LIGHTNESS); + RPrefs.putLong(MONET_LAST_UPDATED, System.currentTimeMillis()); + new Handler(Looper.getMainLooper()).postDelayed(() -> { + try { + OverlayManager.applyFabricatedColors(requireContext()); + } catch (Exception ignored) { + } + }, 200); return true; }); - binding.backgroundLightness.setEnabled(themeViewModel.isNotShizukuMode()); + binding.backgroundLightness.setEnabled(notShizukuMode); + + return binding.getRoot(); } - private void observeViewModel() { - themeViewModel.getColorPaletteLiveData().observe(getViewLifecycleOwner(), this::updatePreviewColors); + @Override + public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + + updatePreviewColors(); + } + + private void updatePreviewColors() { + ArrayList> colorPalette = generateModifiedColors( + monetAccentSaturation[0], + monetBackgroundSaturation[0], + monetBackgroundLightness[0], + RPrefs.getBoolean(MONET_PITCH_BLACK_THEME, false), + RPrefs.getBoolean(MONET_ACCURATE_SHADES, true) + ); + + if (colorPalette != null) { + boolean isDarkMode = SystemUtil.isDarkMode(); + + binding.colorAccent1.colorContainer.setHalfCircleColor(colorPalette.get(0).get(4)); + binding.colorAccent1.colorContainer.setFirstQuarterCircleColor(colorPalette.get(0).get(5)); + binding.colorAccent1.colorContainer.setSecondQuarterCircleColor(colorPalette.get(0).get(6)); + binding.colorAccent1.colorContainer.setSquareColor(colorPalette.get(0).get(!isDarkMode ? 3 : 9)); + binding.colorAccent1.colorContainer.setPadding(8); + binding.colorAccent1.colorContainer.invalidateColors(); + + binding.colorAccent2.colorContainer.setHalfCircleColor(colorPalette.get(1).get(4)); + binding.colorAccent2.colorContainer.setFirstQuarterCircleColor(colorPalette.get(1).get(5)); + binding.colorAccent2.colorContainer.setSecondQuarterCircleColor(colorPalette.get(1).get(6)); + binding.colorAccent2.colorContainer.setSquareColor(colorPalette.get(1).get(!isDarkMode ? 3 : 9)); + binding.colorAccent2.colorContainer.setPadding(8); + binding.colorAccent2.colorContainer.invalidateColors(); + + binding.colorAccent3.colorContainer.setHalfCircleColor(colorPalette.get(2).get(4)); + binding.colorAccent3.colorContainer.setFirstQuarterCircleColor(colorPalette.get(2).get(5)); + binding.colorAccent3.colorContainer.setSecondQuarterCircleColor(colorPalette.get(2).get(6)); + binding.colorAccent3.colorContainer.setSquareColor(colorPalette.get(2).get(!isDarkMode ? 3 : 9)); + binding.colorAccent3.colorContainer.setPadding(8); + binding.colorAccent3.colorContainer.invalidateColors(); + + binding.colorNeutral1.colorContainer.setHalfCircleColor(colorPalette.get(3).get(4)); + binding.colorNeutral1.colorContainer.setFirstQuarterCircleColor(colorPalette.get(3).get(5)); + binding.colorNeutral1.colorContainer.setSecondQuarterCircleColor(colorPalette.get(3).get(6)); + binding.colorNeutral1.colorContainer.setSquareColor(colorPalette.get(3).get(!isDarkMode ? 3 : 9)); + binding.colorNeutral1.colorContainer.setPadding(8); + binding.colorNeutral1.colorContainer.invalidateColors(); + + binding.colorNeutral2.colorContainer.setHalfCircleColor(colorPalette.get(4).get(4)); + binding.colorNeutral2.colorContainer.setFirstQuarterCircleColor(colorPalette.get(4).get(5)); + binding.colorNeutral2.colorContainer.setSecondQuarterCircleColor(colorPalette.get(4).get(6)); + binding.colorNeutral2.colorContainer.setSquareColor(colorPalette.get(4).get(!isDarkMode ? 3 : 9)); + binding.colorNeutral2.colorContainer.setPadding(8); + binding.colorNeutral2.colorContainer.invalidateColors(); + } } - private void updatePreviewColors(ArrayList> colorPalette) { - if (colorPalette == null) return; - - boolean isDarkMode = SystemUtil.isDarkMode(); - - for (int i = 0; i < 5; i++) { - ColorPreview colorContainer = switch (i) { - case 0 -> binding.colorAccent1.colorContainer; - case 1 -> binding.colorAccent2.colorContainer; - case 2 -> binding.colorAccent3.colorContainer; - case 3 -> binding.colorNeutral1.colorContainer; - case 4 -> binding.colorNeutral2.colorContainer; - default -> null; - }; - - colorContainer.setHalfCircleColor(colorPalette.get(i).get(4)); - colorContainer.setFirstQuarterCircleColor(colorPalette.get(i).get(5)); - colorContainer.setSecondQuarterCircleColor(colorPalette.get(i).get(6)); - colorContainer.setSquareColor(colorPalette.get(i).get(isDarkMode ? 9 : 3)); - colorContainer.setPadding(8); - colorContainer.invalidateColors(); + private ArrayList> generateModifiedColors( + int monetAccentSaturation, + int monetBackgroundSaturation, + int monetBackgroundLightness, + boolean pitchBlackTheme, + boolean accurateShades + ) { + try { + return ColorUtil.generateModifiedColors( + requireContext(), + ColorSchemeUtil.stringToEnumMonetStyle( + requireContext(), + RPrefs.getString(MONET_STYLE, getString(R.string.monet_tonalspot)) + ), + monetAccentSaturation, + monetBackgroundSaturation, + monetBackgroundLightness, + pitchBlackTheme, + accurateShades + ); + } catch (Exception e) { + Log.e(TAG, "Error generating modified colors", e); + return null; } } } \ No newline at end of file diff --git a/app/src/main/java/com/drdisagree/colorblendr/ui/repositories/ColorRepository.java b/app/src/main/java/com/drdisagree/colorblendr/ui/repositories/ColorRepository.java deleted file mode 100644 index 7bde64b..0000000 --- a/app/src/main/java/com/drdisagree/colorblendr/ui/repositories/ColorRepository.java +++ /dev/null @@ -1,64 +0,0 @@ -package com.drdisagree.colorblendr.ui.repositories; - -import static com.drdisagree.colorblendr.common.Const.GSON; -import static com.drdisagree.colorblendr.common.Const.MONET_LAST_UPDATED; -import static com.drdisagree.colorblendr.common.Const.MONET_SEED_COLOR; -import static com.drdisagree.colorblendr.common.Const.MONET_SEED_COLOR_ENABLED; -import static com.drdisagree.colorblendr.common.Const.WALLPAPER_COLOR_LIST; - -import android.content.Context; -import android.graphics.Color; - -import com.drdisagree.colorblendr.R; -import com.drdisagree.colorblendr.config.RPrefs; -import com.drdisagree.colorblendr.utils.ColorUtil; -import com.drdisagree.colorblendr.utils.WallpaperColorUtil; -import com.google.gson.reflect.TypeToken; - -import java.util.Arrays; -import java.util.List; -import java.util.stream.Collectors; - -public class ColorRepository { - - private final Context context; - - public ColorRepository(Context context) { - this.context = context; - } - - public int getMonetSeedColor() { - return RPrefs.getInt(MONET_SEED_COLOR, WallpaperColorUtil.getWallpaperColor(context)); - } - - public void setMonetSeedColor(int color) { - RPrefs.putInt(MONET_SEED_COLOR, color); - } - - public boolean isMonetSeedColorEnabled() { - return RPrefs.getBoolean(MONET_SEED_COLOR_ENABLED, false); - } - - public void setMonetSeedColorEnabled(boolean enabled) { - RPrefs.putBoolean(MONET_SEED_COLOR_ENABLED, enabled); - } - - public void setMonetLastUpdated() { - RPrefs.putLong(MONET_LAST_UPDATED, System.currentTimeMillis()); - } - - public List getWallpaperColorList() { - String wallpaperColors = RPrefs.getString(WALLPAPER_COLOR_LIST, null); - if (wallpaperColors != null) { - return GSON.fromJson(wallpaperColors, new TypeToken>() { - }.getType()); - } else { - return ColorUtil.getMonetAccentColors(); - } - } - - public List getBasicColors() { - String[] basicColors = context.getResources().getStringArray(R.array.basic_color_codes); - return Arrays.stream(basicColors).map(Color::parseColor).collect(Collectors.toList()); - } -} diff --git a/app/src/main/java/com/drdisagree/colorblendr/ui/repositories/ThemeRepository.java b/app/src/main/java/com/drdisagree/colorblendr/ui/repositories/ThemeRepository.java deleted file mode 100644 index 4368473..0000000 --- a/app/src/main/java/com/drdisagree/colorblendr/ui/repositories/ThemeRepository.java +++ /dev/null @@ -1,84 +0,0 @@ -package com.drdisagree.colorblendr.ui.repositories; - -import static com.drdisagree.colorblendr.common.Const.MONET_ACCENT_SATURATION; -import static com.drdisagree.colorblendr.common.Const.MONET_ACCURATE_SHADES; -import static com.drdisagree.colorblendr.common.Const.MONET_BACKGROUND_LIGHTNESS; -import static com.drdisagree.colorblendr.common.Const.MONET_BACKGROUND_SATURATION; -import static com.drdisagree.colorblendr.common.Const.MONET_LAST_UPDATED; -import static com.drdisagree.colorblendr.common.Const.MONET_PITCH_BLACK_THEME; -import static com.drdisagree.colorblendr.common.Const.MONET_STYLE; - -import android.content.Context; - -import com.drdisagree.colorblendr.R; -import com.drdisagree.colorblendr.common.Const; -import com.drdisagree.colorblendr.config.RPrefs; -import com.drdisagree.colorblendr.utils.ColorSchemeUtil; - -public class ThemeRepository { - - private final Context context; - - public ThemeRepository(Context context) { - this.context = context; - } - - public int getAccentSaturation() { - return RPrefs.getInt(MONET_ACCENT_SATURATION, 100); - } - - public void setAccentSaturation(int value) { - RPrefs.putInt(MONET_ACCENT_SATURATION, value); - } - - public void resetAccentSaturation() { - RPrefs.clearPref(MONET_ACCENT_SATURATION); - } - - public int getBackgroundSaturation() { - return RPrefs.getInt(MONET_BACKGROUND_SATURATION, 100); - } - - public void setBackgroundSaturation(int value) { - RPrefs.putInt(MONET_BACKGROUND_SATURATION, value); - } - - public void resetBackgroundSaturation() { - RPrefs.clearPref(MONET_BACKGROUND_SATURATION); - } - - public int getBackgroundLightness() { - return RPrefs.getInt(MONET_BACKGROUND_LIGHTNESS, 100); - } - - public void setBackgroundLightness(int value) { - RPrefs.putInt(MONET_BACKGROUND_LIGHTNESS, value); - } - - public void resetBackgroundLightness() { - RPrefs.clearPref(MONET_BACKGROUND_LIGHTNESS); - } - - public boolean getPitchBlackTheme() { - return RPrefs.getBoolean(MONET_PITCH_BLACK_THEME, false); - } - - public boolean getAccurateShades() { - return RPrefs.getBoolean(MONET_ACCURATE_SHADES, true); - } - - public ColorSchemeUtil.MONET getMonetStyle() { - return ColorSchemeUtil.stringToEnumMonetStyle( - context, - RPrefs.getString(MONET_STYLE, context.getString(R.string.monet_tonalspot)) - ); - } - - public void setMonetLastUpdated() { - RPrefs.putLong(MONET_LAST_UPDATED, System.currentTimeMillis()); - } - - public boolean isNotShizukuMode() { - return Const.getWorkingMethod() != Const.WORK_METHOD.SHIZUKU; - } -} diff --git a/app/src/main/java/com/drdisagree/colorblendr/ui/viewmodels/ColorsViewModel.java b/app/src/main/java/com/drdisagree/colorblendr/ui/viewmodels/ColorsViewModel.java deleted file mode 100644 index b02dc0c..0000000 --- a/app/src/main/java/com/drdisagree/colorblendr/ui/viewmodels/ColorsViewModel.java +++ /dev/null @@ -1,69 +0,0 @@ -package com.drdisagree.colorblendr.ui.viewmodels; - -import android.app.Application; - -import androidx.annotation.NonNull; -import androidx.lifecycle.AndroidViewModel; -import androidx.lifecycle.LiveData; -import androidx.lifecycle.MutableLiveData; - -import com.drdisagree.colorblendr.ui.repositories.ColorRepository; -import com.drdisagree.colorblendr.utils.OverlayManager; - -import java.util.List; - -public class ColorsViewModel extends AndroidViewModel { - - private final ColorRepository colorRepository; - private final MutableLiveData> wallpaperColorsLiveData = new MutableLiveData<>(); - private final MutableLiveData> basicColorsLiveData = new MutableLiveData<>(); - private final MutableLiveData monetSeedColorLiveData = new MutableLiveData<>(); - - public ColorsViewModel(@NonNull Application application) { - super(application); - colorRepository = new ColorRepository(application); - loadInitialData(); - } - - private void loadInitialData() { - loadWallpaperColors(); - loadBasicColors(); - monetSeedColorLiveData.setValue(colorRepository.getMonetSeedColor()); - } - - public LiveData> getWallpaperColorsLiveData() { - return wallpaperColorsLiveData; - } - - public LiveData> getBasicColorsLiveData() { - return basicColorsLiveData; - } - - public LiveData getMonetSeedColorLiveData() { - monetSeedColorLiveData.setValue(colorRepository.getMonetSeedColor()); - return monetSeedColorLiveData; - } - - public void loadWallpaperColors() { - wallpaperColorsLiveData.setValue(colorRepository.getWallpaperColorList()); - } - - public void loadBasicColors() { - basicColorsLiveData.setValue(colorRepository.getBasicColors()); - } - - public void setMonetSeedColor(int color) { - colorRepository.setMonetSeedColor(color); - monetSeedColorLiveData.setValue(color); - colorRepository.setMonetLastUpdated(); - OverlayManager.applyFabricatedColors(getApplication().getApplicationContext()); - } - - public void setMonetSeedColorEnabled(boolean enabled) { - colorRepository.setMonetSeedColorEnabled(enabled); - } - - public boolean isMonetSeedColorEnabled() { - return colorRepository.isMonetSeedColorEnabled(); - } -} diff --git a/app/src/main/java/com/drdisagree/colorblendr/ui/viewmodels/ThemeViewModel.java b/app/src/main/java/com/drdisagree/colorblendr/ui/viewmodels/ThemeViewModel.java deleted file mode 100644 index 986ec33..0000000 --- a/app/src/main/java/com/drdisagree/colorblendr/ui/viewmodels/ThemeViewModel.java +++ /dev/null @@ -1,154 +0,0 @@ -package com.drdisagree.colorblendr.ui.viewmodels; - -import android.app.Application; -import android.os.Handler; -import android.os.Looper; -import android.util.Log; - -import androidx.annotation.NonNull; -import androidx.lifecycle.AndroidViewModel; -import androidx.lifecycle.MutableLiveData; - -import com.drdisagree.colorblendr.ui.repositories.ThemeRepository; -import com.drdisagree.colorblendr.utils.ColorUtil; -import com.drdisagree.colorblendr.utils.OverlayManager; - -import java.util.ArrayList; - -public class ThemeViewModel extends AndroidViewModel { - - private final String TAG = ThemeViewModel.class.getSimpleName(); - private final ThemeRepository themeRepository; - private final MutableLiveData accentSaturation = new MutableLiveData<>(); - private final MutableLiveData backgroundSaturation = new MutableLiveData<>(); - private final MutableLiveData backgroundLightness = new MutableLiveData<>(); - private final MutableLiveData>> colorPalette = new MutableLiveData<>(); - - public ThemeViewModel(@NonNull Application application) { - super(application); - themeRepository = new ThemeRepository(application); - loadInitialData(); - } - - private void loadInitialData() { - accentSaturation.setValue(themeRepository.getAccentSaturation()); - backgroundSaturation.setValue(themeRepository.getBackgroundSaturation()); - backgroundLightness.setValue(themeRepository.getBackgroundLightness()); - loadModifiedColors(); - } - - @SuppressWarnings("all") - public int getAccentSaturation() { - return accentSaturation.getValue(); - } - - public void updateAccentSaturation(int value) { - accentSaturation.setValue(value); - loadModifiedColors(); - } - - public void setAccentSaturation(int value) { - themeRepository.setAccentSaturation(value); - updateAccentSaturation(value); - applyFabricatedColors(); - } - - public void resetAccentSaturation() { - themeRepository.resetAccentSaturation(); - updateAccentSaturation(100); - applyFabricatedColors(); - } - - @SuppressWarnings("all") - public int getBackgroundSaturation() { - return backgroundSaturation.getValue(); - } - - public void updateBackgroundSaturation(int value) { - backgroundSaturation.setValue(value); - loadModifiedColors(); - } - - public void setBackgroundSaturation(int value) { - themeRepository.setBackgroundSaturation(value); - updateBackgroundSaturation(value); - applyFabricatedColors(); - } - - public void resetBackgroundSaturation() { - themeRepository.resetBackgroundSaturation(); - updateBackgroundSaturation(100); - applyFabricatedColors(); - } - - @SuppressWarnings("all") - public int getBackgroundLightness() { - return backgroundLightness.getValue(); - } - - public void updateBackgroundLightness(int value) { - backgroundLightness.setValue(value); - loadModifiedColors(); - } - - public void setBackgroundLightness(int value) { - themeRepository.setBackgroundLightness(value); - updateBackgroundLightness(value); - applyFabricatedColors(); - } - - public void resetBackgroundLightness() { - themeRepository.resetBackgroundLightness(); - updateBackgroundLightness(100); - applyFabricatedColors(); - } - - public boolean getPitchBlackTheme() { - return themeRepository.getPitchBlackTheme(); - } - - public boolean getAccurateShades() { - return themeRepository.getAccurateShades(); - } - - public boolean isNotShizukuMode() { - return themeRepository.isNotShizukuMode(); - } - - public void loadModifiedColors() { - colorPalette.setValue(generateModifiedColors()); - } - - public MutableLiveData>> getColorPaletteLiveData() { - return colorPalette; - } - - @SuppressWarnings("all") - private ArrayList> generateModifiedColors() { - try { - return ColorUtil.generateModifiedColors( - getApplication().getApplicationContext(), - themeRepository.getMonetStyle(), - accentSaturation.getValue(), - backgroundSaturation.getValue(), - backgroundLightness.getValue(), - getPitchBlackTheme(), - getAccurateShades() - ); - } catch (Exception e) { - Log.e(TAG, "Error generating modified colors", e); - return null; - } - } - - private void applyFabricatedColors() { - themeRepository.setMonetLastUpdated(); - - new Handler(Looper.getMainLooper()).postDelayed(() -> { - try { - OverlayManager.applyFabricatedColors(getApplication().getApplicationContext()); - } catch (Exception ignored) { - } - }, 200); - } -} \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_colors.xml b/app/src/main/res/layout/fragment_colors.xml index 90f9ca2..738d664 100644 --- a/app/src/main/res/layout/fragment_colors.xml +++ b/app/src/main/res/layout/fragment_colors.xml @@ -70,24 +70,7 @@ - - Date: Sat, 17 Aug 2024 15:23:21 +0600 Subject: [PATCH 2/7] Rename .java to .kt --- .../drdisagree/colorblendr/{ColorBlendr.java => ColorBlendr.kt} | 0 .../com/drdisagree/colorblendr/common/{Const.java => Const.kt} | 0 .../com/drdisagree/colorblendr/config/{RPrefs.java => RPrefs.kt} | 0 .../extension/{MethodInterface.java => MethodInterface.kt} | 0 .../{ThemeOverlayPackage.java => ThemeOverlayPackage.kt} | 0 .../provider/{RemotePrefProvider.java => RemotePrefProvider.kt} | 0 .../{RootConnectionProvider.java => RootConnectionProvider.kt} | 0 ...hizukuConnectionProvider.java => ShizukuConnectionProvider.kt} | 0 .../service/{AutoStartService.java => AutoStartService.kt} | 0 .../service/{BroadcastListener.java => BroadcastListener.kt} | 0 ...{RestartBroadcastReceiver.java => RestartBroadcastReceiver.kt} | 0 .../service/{RootConnection.java => RootConnection.kt} | 0 .../service/{ScheduledJobService.java => ScheduledJobService.kt} | 0 .../service/{ServiceLauncher.java => ServiceLauncher.kt} | 0 .../service/{ShizukuConnection.java => ShizukuConnection.kt} | 0 .../ui/activities/{MainActivity.java => MainActivity.kt} | 0 .../ui/activities/{SplashActivity.java => SplashActivity.kt} | 0 .../ui/adapters/{AppListAdapter.java => AppListAdapter.kt} | 0 .../ui/adapters/{FragmentAdapter.java => FragmentAdapter.kt} | 0 .../ui/adapters/{OnboardingAdapter.java => OnboardingAdapter.kt} | 0 .../ui/fragments/{AboutFragment.java => AboutFragment.kt} | 0 .../{ColorPaletteFragment.java => ColorPaletteFragment.kt} | 0 .../ui/fragments/{ColorsFragment.java => ColorsFragment.kt} | 0 .../ui/fragments/{HomeFragment.java => HomeFragment.kt} | 0 .../fragments/{OnboardingFragment.java => OnboardingFragment.kt} | 0 .../{OnboardingItem1Fragment.java => OnboardingItem1Fragment.kt} | 0 .../{OnboardingItem2Fragment.java => OnboardingItem2Fragment.kt} | 0 .../{OnboardingItem3Fragment.java => OnboardingItem3Fragment.kt} | 0 .../{PerAppThemeFragment.java => PerAppThemeFragment.kt} | 0 .../ui/fragments/{SettingsFragment.java => SettingsFragment.kt} | 0 .../ui/fragments/{StylesFragment.java => StylesFragment.kt} | 0 .../ui/fragments/{ThemeFragment.java => ThemeFragment.kt} | 0 .../colorblendr/ui/models/{AppInfoModel.java => AppInfoModel.kt} | 0 .../ui/viewmodels/{SharedViewModel.java => SharedViewModel.kt} | 0 .../colorblendr/ui/views/{ColorPreview.java => ColorPreview.kt} | 0 .../ui/views/{ResizableSeekbar.java => ResizableSeekbar.kt} | 0 ...ButtonToggleGroup.java => RoundedMaterialButtonToggleGroup.kt} | 0 .../ui/views/{WallColorPreview.java => WallColorPreview.kt} | 0 .../ui/widgets/{ColorPickerWidget.java => ColorPickerWidget.kt} | 0 .../colorblendr/ui/widgets/{MenuWidget.java => MenuWidget.kt} | 0 .../ui/widgets/{ResizableSeekbar.java => ResizableSeekbar.kt} | 0 .../ui/widgets/{SeekbarWidget.java => SeekbarWidget.kt} | 0 .../{SelectableViewWidget.java => SelectableViewWidget.kt} | 0 .../ui/widgets/{StylePreviewWidget.java => StylePreviewWidget.kt} | 0 .../colorblendr/ui/widgets/{SwitchWidget.java => SwitchWidget.kt} | 0 .../com/drdisagree/colorblendr/utils/{AppUtil.java => AppUtil.kt} | 0 .../colorblendr/utils/{ColorModifiers.java => ColorModifiers.kt} | 0 .../utils/{ColorSchemeUtil.java => ColorSchemeUtil.kt} | 0 .../drdisagree/colorblendr/utils/{ColorUtil.java => ColorUtil.kt} | 0 .../colorblendr/utils/{DynamicColors.java => DynamicColors.kt} | 0 .../colorblendr/utils/{FabricatedUtil.java => FabricatedUtil.kt} | 0 .../colorblendr/utils/{FragmentUtil.java => FragmentUtil.kt} | 0 .../drdisagree/colorblendr/utils/{MiscUtil.java => MiscUtil.kt} | 0 .../colorblendr/utils/{OverlayManager.java => OverlayManager.kt} | 0 .../colorblendr/utils/{ShizukuUtil.java => ShizukuUtil.kt} | 0 .../colorblendr/utils/{SystemUtil.java => SystemUtil.kt} | 0 .../utils/{WallpaperColorUtil.java => WallpaperColorUtil.kt} | 0 .../utils/annotations/{TestingOnly.java => TestingOnly.kt} | 0 .../{FabricatedOverlayEntry.java => FabricatedOverlayEntry.kt} | 0 ...abricatedOverlayResource.java => FabricatedOverlayResource.kt} | 0 60 files changed, 0 insertions(+), 0 deletions(-) rename app/src/main/java/com/drdisagree/colorblendr/{ColorBlendr.java => ColorBlendr.kt} (100%) rename app/src/main/java/com/drdisagree/colorblendr/common/{Const.java => Const.kt} (100%) rename app/src/main/java/com/drdisagree/colorblendr/config/{RPrefs.java => RPrefs.kt} (100%) rename app/src/main/java/com/drdisagree/colorblendr/extension/{MethodInterface.java => MethodInterface.kt} (100%) rename app/src/main/java/com/drdisagree/colorblendr/extension/{ThemeOverlayPackage.java => ThemeOverlayPackage.kt} (100%) rename app/src/main/java/com/drdisagree/colorblendr/provider/{RemotePrefProvider.java => RemotePrefProvider.kt} (100%) rename app/src/main/java/com/drdisagree/colorblendr/provider/{RootConnectionProvider.java => RootConnectionProvider.kt} (100%) rename app/src/main/java/com/drdisagree/colorblendr/provider/{ShizukuConnectionProvider.java => ShizukuConnectionProvider.kt} (100%) rename app/src/main/java/com/drdisagree/colorblendr/service/{AutoStartService.java => AutoStartService.kt} (100%) rename app/src/main/java/com/drdisagree/colorblendr/service/{BroadcastListener.java => BroadcastListener.kt} (100%) rename app/src/main/java/com/drdisagree/colorblendr/service/{RestartBroadcastReceiver.java => RestartBroadcastReceiver.kt} (100%) rename app/src/main/java/com/drdisagree/colorblendr/service/{RootConnection.java => RootConnection.kt} (100%) rename app/src/main/java/com/drdisagree/colorblendr/service/{ScheduledJobService.java => ScheduledJobService.kt} (100%) rename app/src/main/java/com/drdisagree/colorblendr/service/{ServiceLauncher.java => ServiceLauncher.kt} (100%) rename app/src/main/java/com/drdisagree/colorblendr/service/{ShizukuConnection.java => ShizukuConnection.kt} (100%) rename app/src/main/java/com/drdisagree/colorblendr/ui/activities/{MainActivity.java => MainActivity.kt} (100%) rename app/src/main/java/com/drdisagree/colorblendr/ui/activities/{SplashActivity.java => SplashActivity.kt} (100%) rename app/src/main/java/com/drdisagree/colorblendr/ui/adapters/{AppListAdapter.java => AppListAdapter.kt} (100%) rename app/src/main/java/com/drdisagree/colorblendr/ui/adapters/{FragmentAdapter.java => FragmentAdapter.kt} (100%) rename app/src/main/java/com/drdisagree/colorblendr/ui/adapters/{OnboardingAdapter.java => OnboardingAdapter.kt} (100%) rename app/src/main/java/com/drdisagree/colorblendr/ui/fragments/{AboutFragment.java => AboutFragment.kt} (100%) rename app/src/main/java/com/drdisagree/colorblendr/ui/fragments/{ColorPaletteFragment.java => ColorPaletteFragment.kt} (100%) rename app/src/main/java/com/drdisagree/colorblendr/ui/fragments/{ColorsFragment.java => ColorsFragment.kt} (100%) rename app/src/main/java/com/drdisagree/colorblendr/ui/fragments/{HomeFragment.java => HomeFragment.kt} (100%) rename app/src/main/java/com/drdisagree/colorblendr/ui/fragments/{OnboardingFragment.java => OnboardingFragment.kt} (100%) rename app/src/main/java/com/drdisagree/colorblendr/ui/fragments/{OnboardingItem1Fragment.java => OnboardingItem1Fragment.kt} (100%) rename app/src/main/java/com/drdisagree/colorblendr/ui/fragments/{OnboardingItem2Fragment.java => OnboardingItem2Fragment.kt} (100%) rename app/src/main/java/com/drdisagree/colorblendr/ui/fragments/{OnboardingItem3Fragment.java => OnboardingItem3Fragment.kt} (100%) rename app/src/main/java/com/drdisagree/colorblendr/ui/fragments/{PerAppThemeFragment.java => PerAppThemeFragment.kt} (100%) rename app/src/main/java/com/drdisagree/colorblendr/ui/fragments/{SettingsFragment.java => SettingsFragment.kt} (100%) rename app/src/main/java/com/drdisagree/colorblendr/ui/fragments/{StylesFragment.java => StylesFragment.kt} (100%) rename app/src/main/java/com/drdisagree/colorblendr/ui/fragments/{ThemeFragment.java => ThemeFragment.kt} (100%) rename app/src/main/java/com/drdisagree/colorblendr/ui/models/{AppInfoModel.java => AppInfoModel.kt} (100%) rename app/src/main/java/com/drdisagree/colorblendr/ui/viewmodels/{SharedViewModel.java => SharedViewModel.kt} (100%) rename app/src/main/java/com/drdisagree/colorblendr/ui/views/{ColorPreview.java => ColorPreview.kt} (100%) rename app/src/main/java/com/drdisagree/colorblendr/ui/views/{ResizableSeekbar.java => ResizableSeekbar.kt} (100%) rename app/src/main/java/com/drdisagree/colorblendr/ui/views/{RoundedMaterialButtonToggleGroup.java => RoundedMaterialButtonToggleGroup.kt} (100%) rename app/src/main/java/com/drdisagree/colorblendr/ui/views/{WallColorPreview.java => WallColorPreview.kt} (100%) rename app/src/main/java/com/drdisagree/colorblendr/ui/widgets/{ColorPickerWidget.java => ColorPickerWidget.kt} (100%) rename app/src/main/java/com/drdisagree/colorblendr/ui/widgets/{MenuWidget.java => MenuWidget.kt} (100%) rename app/src/main/java/com/drdisagree/colorblendr/ui/widgets/{ResizableSeekbar.java => ResizableSeekbar.kt} (100%) rename app/src/main/java/com/drdisagree/colorblendr/ui/widgets/{SeekbarWidget.java => SeekbarWidget.kt} (100%) rename app/src/main/java/com/drdisagree/colorblendr/ui/widgets/{SelectableViewWidget.java => SelectableViewWidget.kt} (100%) rename app/src/main/java/com/drdisagree/colorblendr/ui/widgets/{StylePreviewWidget.java => StylePreviewWidget.kt} (100%) rename app/src/main/java/com/drdisagree/colorblendr/ui/widgets/{SwitchWidget.java => SwitchWidget.kt} (100%) rename app/src/main/java/com/drdisagree/colorblendr/utils/{AppUtil.java => AppUtil.kt} (100%) rename app/src/main/java/com/drdisagree/colorblendr/utils/{ColorModifiers.java => ColorModifiers.kt} (100%) rename app/src/main/java/com/drdisagree/colorblendr/utils/{ColorSchemeUtil.java => ColorSchemeUtil.kt} (100%) rename app/src/main/java/com/drdisagree/colorblendr/utils/{ColorUtil.java => ColorUtil.kt} (100%) rename app/src/main/java/com/drdisagree/colorblendr/utils/{DynamicColors.java => DynamicColors.kt} (100%) rename app/src/main/java/com/drdisagree/colorblendr/utils/{FabricatedUtil.java => FabricatedUtil.kt} (100%) rename app/src/main/java/com/drdisagree/colorblendr/utils/{FragmentUtil.java => FragmentUtil.kt} (100%) rename app/src/main/java/com/drdisagree/colorblendr/utils/{MiscUtil.java => MiscUtil.kt} (100%) rename app/src/main/java/com/drdisagree/colorblendr/utils/{OverlayManager.java => OverlayManager.kt} (100%) rename app/src/main/java/com/drdisagree/colorblendr/utils/{ShizukuUtil.java => ShizukuUtil.kt} (100%) rename app/src/main/java/com/drdisagree/colorblendr/utils/{SystemUtil.java => SystemUtil.kt} (100%) rename app/src/main/java/com/drdisagree/colorblendr/utils/{WallpaperColorUtil.java => WallpaperColorUtil.kt} (100%) rename app/src/main/java/com/drdisagree/colorblendr/utils/annotations/{TestingOnly.java => TestingOnly.kt} (100%) rename app/src/main/java/com/drdisagree/colorblendr/utils/fabricated/{FabricatedOverlayEntry.java => FabricatedOverlayEntry.kt} (100%) rename app/src/main/java/com/drdisagree/colorblendr/utils/fabricated/{FabricatedOverlayResource.java => FabricatedOverlayResource.kt} (100%) diff --git a/app/src/main/java/com/drdisagree/colorblendr/ColorBlendr.java b/app/src/main/java/com/drdisagree/colorblendr/ColorBlendr.kt similarity index 100% rename from app/src/main/java/com/drdisagree/colorblendr/ColorBlendr.java rename to app/src/main/java/com/drdisagree/colorblendr/ColorBlendr.kt diff --git a/app/src/main/java/com/drdisagree/colorblendr/common/Const.java b/app/src/main/java/com/drdisagree/colorblendr/common/Const.kt similarity index 100% rename from app/src/main/java/com/drdisagree/colorblendr/common/Const.java rename to app/src/main/java/com/drdisagree/colorblendr/common/Const.kt diff --git a/app/src/main/java/com/drdisagree/colorblendr/config/RPrefs.java b/app/src/main/java/com/drdisagree/colorblendr/config/RPrefs.kt similarity index 100% rename from app/src/main/java/com/drdisagree/colorblendr/config/RPrefs.java rename to app/src/main/java/com/drdisagree/colorblendr/config/RPrefs.kt diff --git a/app/src/main/java/com/drdisagree/colorblendr/extension/MethodInterface.java b/app/src/main/java/com/drdisagree/colorblendr/extension/MethodInterface.kt similarity index 100% rename from app/src/main/java/com/drdisagree/colorblendr/extension/MethodInterface.java rename to app/src/main/java/com/drdisagree/colorblendr/extension/MethodInterface.kt diff --git a/app/src/main/java/com/drdisagree/colorblendr/extension/ThemeOverlayPackage.java b/app/src/main/java/com/drdisagree/colorblendr/extension/ThemeOverlayPackage.kt similarity index 100% rename from app/src/main/java/com/drdisagree/colorblendr/extension/ThemeOverlayPackage.java rename to app/src/main/java/com/drdisagree/colorblendr/extension/ThemeOverlayPackage.kt diff --git a/app/src/main/java/com/drdisagree/colorblendr/provider/RemotePrefProvider.java b/app/src/main/java/com/drdisagree/colorblendr/provider/RemotePrefProvider.kt similarity index 100% rename from app/src/main/java/com/drdisagree/colorblendr/provider/RemotePrefProvider.java rename to app/src/main/java/com/drdisagree/colorblendr/provider/RemotePrefProvider.kt diff --git a/app/src/main/java/com/drdisagree/colorblendr/provider/RootConnectionProvider.java b/app/src/main/java/com/drdisagree/colorblendr/provider/RootConnectionProvider.kt similarity index 100% rename from app/src/main/java/com/drdisagree/colorblendr/provider/RootConnectionProvider.java rename to app/src/main/java/com/drdisagree/colorblendr/provider/RootConnectionProvider.kt diff --git a/app/src/main/java/com/drdisagree/colorblendr/provider/ShizukuConnectionProvider.java b/app/src/main/java/com/drdisagree/colorblendr/provider/ShizukuConnectionProvider.kt similarity index 100% rename from app/src/main/java/com/drdisagree/colorblendr/provider/ShizukuConnectionProvider.java rename to app/src/main/java/com/drdisagree/colorblendr/provider/ShizukuConnectionProvider.kt diff --git a/app/src/main/java/com/drdisagree/colorblendr/service/AutoStartService.java b/app/src/main/java/com/drdisagree/colorblendr/service/AutoStartService.kt similarity index 100% rename from app/src/main/java/com/drdisagree/colorblendr/service/AutoStartService.java rename to app/src/main/java/com/drdisagree/colorblendr/service/AutoStartService.kt diff --git a/app/src/main/java/com/drdisagree/colorblendr/service/BroadcastListener.java b/app/src/main/java/com/drdisagree/colorblendr/service/BroadcastListener.kt similarity index 100% rename from app/src/main/java/com/drdisagree/colorblendr/service/BroadcastListener.java rename to app/src/main/java/com/drdisagree/colorblendr/service/BroadcastListener.kt diff --git a/app/src/main/java/com/drdisagree/colorblendr/service/RestartBroadcastReceiver.java b/app/src/main/java/com/drdisagree/colorblendr/service/RestartBroadcastReceiver.kt similarity index 100% rename from app/src/main/java/com/drdisagree/colorblendr/service/RestartBroadcastReceiver.java rename to app/src/main/java/com/drdisagree/colorblendr/service/RestartBroadcastReceiver.kt diff --git a/app/src/main/java/com/drdisagree/colorblendr/service/RootConnection.java b/app/src/main/java/com/drdisagree/colorblendr/service/RootConnection.kt similarity index 100% rename from app/src/main/java/com/drdisagree/colorblendr/service/RootConnection.java rename to app/src/main/java/com/drdisagree/colorblendr/service/RootConnection.kt diff --git a/app/src/main/java/com/drdisagree/colorblendr/service/ScheduledJobService.java b/app/src/main/java/com/drdisagree/colorblendr/service/ScheduledJobService.kt similarity index 100% rename from app/src/main/java/com/drdisagree/colorblendr/service/ScheduledJobService.java rename to app/src/main/java/com/drdisagree/colorblendr/service/ScheduledJobService.kt diff --git a/app/src/main/java/com/drdisagree/colorblendr/service/ServiceLauncher.java b/app/src/main/java/com/drdisagree/colorblendr/service/ServiceLauncher.kt similarity index 100% rename from app/src/main/java/com/drdisagree/colorblendr/service/ServiceLauncher.java rename to app/src/main/java/com/drdisagree/colorblendr/service/ServiceLauncher.kt diff --git a/app/src/main/java/com/drdisagree/colorblendr/service/ShizukuConnection.java b/app/src/main/java/com/drdisagree/colorblendr/service/ShizukuConnection.kt similarity index 100% rename from app/src/main/java/com/drdisagree/colorblendr/service/ShizukuConnection.java rename to app/src/main/java/com/drdisagree/colorblendr/service/ShizukuConnection.kt diff --git a/app/src/main/java/com/drdisagree/colorblendr/ui/activities/MainActivity.java b/app/src/main/java/com/drdisagree/colorblendr/ui/activities/MainActivity.kt similarity index 100% rename from app/src/main/java/com/drdisagree/colorblendr/ui/activities/MainActivity.java rename to app/src/main/java/com/drdisagree/colorblendr/ui/activities/MainActivity.kt diff --git a/app/src/main/java/com/drdisagree/colorblendr/ui/activities/SplashActivity.java b/app/src/main/java/com/drdisagree/colorblendr/ui/activities/SplashActivity.kt similarity index 100% rename from app/src/main/java/com/drdisagree/colorblendr/ui/activities/SplashActivity.java rename to app/src/main/java/com/drdisagree/colorblendr/ui/activities/SplashActivity.kt diff --git a/app/src/main/java/com/drdisagree/colorblendr/ui/adapters/AppListAdapter.java b/app/src/main/java/com/drdisagree/colorblendr/ui/adapters/AppListAdapter.kt similarity index 100% rename from app/src/main/java/com/drdisagree/colorblendr/ui/adapters/AppListAdapter.java rename to app/src/main/java/com/drdisagree/colorblendr/ui/adapters/AppListAdapter.kt diff --git a/app/src/main/java/com/drdisagree/colorblendr/ui/adapters/FragmentAdapter.java b/app/src/main/java/com/drdisagree/colorblendr/ui/adapters/FragmentAdapter.kt similarity index 100% rename from app/src/main/java/com/drdisagree/colorblendr/ui/adapters/FragmentAdapter.java rename to app/src/main/java/com/drdisagree/colorblendr/ui/adapters/FragmentAdapter.kt diff --git a/app/src/main/java/com/drdisagree/colorblendr/ui/adapters/OnboardingAdapter.java b/app/src/main/java/com/drdisagree/colorblendr/ui/adapters/OnboardingAdapter.kt similarity index 100% rename from app/src/main/java/com/drdisagree/colorblendr/ui/adapters/OnboardingAdapter.java rename to app/src/main/java/com/drdisagree/colorblendr/ui/adapters/OnboardingAdapter.kt diff --git a/app/src/main/java/com/drdisagree/colorblendr/ui/fragments/AboutFragment.java b/app/src/main/java/com/drdisagree/colorblendr/ui/fragments/AboutFragment.kt similarity index 100% rename from app/src/main/java/com/drdisagree/colorblendr/ui/fragments/AboutFragment.java rename to app/src/main/java/com/drdisagree/colorblendr/ui/fragments/AboutFragment.kt diff --git a/app/src/main/java/com/drdisagree/colorblendr/ui/fragments/ColorPaletteFragment.java b/app/src/main/java/com/drdisagree/colorblendr/ui/fragments/ColorPaletteFragment.kt similarity index 100% rename from app/src/main/java/com/drdisagree/colorblendr/ui/fragments/ColorPaletteFragment.java rename to app/src/main/java/com/drdisagree/colorblendr/ui/fragments/ColorPaletteFragment.kt diff --git a/app/src/main/java/com/drdisagree/colorblendr/ui/fragments/ColorsFragment.java b/app/src/main/java/com/drdisagree/colorblendr/ui/fragments/ColorsFragment.kt similarity index 100% rename from app/src/main/java/com/drdisagree/colorblendr/ui/fragments/ColorsFragment.java rename to app/src/main/java/com/drdisagree/colorblendr/ui/fragments/ColorsFragment.kt diff --git a/app/src/main/java/com/drdisagree/colorblendr/ui/fragments/HomeFragment.java b/app/src/main/java/com/drdisagree/colorblendr/ui/fragments/HomeFragment.kt similarity index 100% rename from app/src/main/java/com/drdisagree/colorblendr/ui/fragments/HomeFragment.java rename to app/src/main/java/com/drdisagree/colorblendr/ui/fragments/HomeFragment.kt diff --git a/app/src/main/java/com/drdisagree/colorblendr/ui/fragments/OnboardingFragment.java b/app/src/main/java/com/drdisagree/colorblendr/ui/fragments/OnboardingFragment.kt similarity index 100% rename from app/src/main/java/com/drdisagree/colorblendr/ui/fragments/OnboardingFragment.java rename to app/src/main/java/com/drdisagree/colorblendr/ui/fragments/OnboardingFragment.kt diff --git a/app/src/main/java/com/drdisagree/colorblendr/ui/fragments/OnboardingItem1Fragment.java b/app/src/main/java/com/drdisagree/colorblendr/ui/fragments/OnboardingItem1Fragment.kt similarity index 100% rename from app/src/main/java/com/drdisagree/colorblendr/ui/fragments/OnboardingItem1Fragment.java rename to app/src/main/java/com/drdisagree/colorblendr/ui/fragments/OnboardingItem1Fragment.kt diff --git a/app/src/main/java/com/drdisagree/colorblendr/ui/fragments/OnboardingItem2Fragment.java b/app/src/main/java/com/drdisagree/colorblendr/ui/fragments/OnboardingItem2Fragment.kt similarity index 100% rename from app/src/main/java/com/drdisagree/colorblendr/ui/fragments/OnboardingItem2Fragment.java rename to app/src/main/java/com/drdisagree/colorblendr/ui/fragments/OnboardingItem2Fragment.kt diff --git a/app/src/main/java/com/drdisagree/colorblendr/ui/fragments/OnboardingItem3Fragment.java b/app/src/main/java/com/drdisagree/colorblendr/ui/fragments/OnboardingItem3Fragment.kt similarity index 100% rename from app/src/main/java/com/drdisagree/colorblendr/ui/fragments/OnboardingItem3Fragment.java rename to app/src/main/java/com/drdisagree/colorblendr/ui/fragments/OnboardingItem3Fragment.kt diff --git a/app/src/main/java/com/drdisagree/colorblendr/ui/fragments/PerAppThemeFragment.java b/app/src/main/java/com/drdisagree/colorblendr/ui/fragments/PerAppThemeFragment.kt similarity index 100% rename from app/src/main/java/com/drdisagree/colorblendr/ui/fragments/PerAppThemeFragment.java rename to app/src/main/java/com/drdisagree/colorblendr/ui/fragments/PerAppThemeFragment.kt diff --git a/app/src/main/java/com/drdisagree/colorblendr/ui/fragments/SettingsFragment.java b/app/src/main/java/com/drdisagree/colorblendr/ui/fragments/SettingsFragment.kt similarity index 100% rename from app/src/main/java/com/drdisagree/colorblendr/ui/fragments/SettingsFragment.java rename to app/src/main/java/com/drdisagree/colorblendr/ui/fragments/SettingsFragment.kt diff --git a/app/src/main/java/com/drdisagree/colorblendr/ui/fragments/StylesFragment.java b/app/src/main/java/com/drdisagree/colorblendr/ui/fragments/StylesFragment.kt similarity index 100% rename from app/src/main/java/com/drdisagree/colorblendr/ui/fragments/StylesFragment.java rename to app/src/main/java/com/drdisagree/colorblendr/ui/fragments/StylesFragment.kt diff --git a/app/src/main/java/com/drdisagree/colorblendr/ui/fragments/ThemeFragment.java b/app/src/main/java/com/drdisagree/colorblendr/ui/fragments/ThemeFragment.kt similarity index 100% rename from app/src/main/java/com/drdisagree/colorblendr/ui/fragments/ThemeFragment.java rename to app/src/main/java/com/drdisagree/colorblendr/ui/fragments/ThemeFragment.kt diff --git a/app/src/main/java/com/drdisagree/colorblendr/ui/models/AppInfoModel.java b/app/src/main/java/com/drdisagree/colorblendr/ui/models/AppInfoModel.kt similarity index 100% rename from app/src/main/java/com/drdisagree/colorblendr/ui/models/AppInfoModel.java rename to app/src/main/java/com/drdisagree/colorblendr/ui/models/AppInfoModel.kt diff --git a/app/src/main/java/com/drdisagree/colorblendr/ui/viewmodels/SharedViewModel.java b/app/src/main/java/com/drdisagree/colorblendr/ui/viewmodels/SharedViewModel.kt similarity index 100% rename from app/src/main/java/com/drdisagree/colorblendr/ui/viewmodels/SharedViewModel.java rename to app/src/main/java/com/drdisagree/colorblendr/ui/viewmodels/SharedViewModel.kt diff --git a/app/src/main/java/com/drdisagree/colorblendr/ui/views/ColorPreview.java b/app/src/main/java/com/drdisagree/colorblendr/ui/views/ColorPreview.kt similarity index 100% rename from app/src/main/java/com/drdisagree/colorblendr/ui/views/ColorPreview.java rename to app/src/main/java/com/drdisagree/colorblendr/ui/views/ColorPreview.kt diff --git a/app/src/main/java/com/drdisagree/colorblendr/ui/views/ResizableSeekbar.java b/app/src/main/java/com/drdisagree/colorblendr/ui/views/ResizableSeekbar.kt similarity index 100% rename from app/src/main/java/com/drdisagree/colorblendr/ui/views/ResizableSeekbar.java rename to app/src/main/java/com/drdisagree/colorblendr/ui/views/ResizableSeekbar.kt diff --git a/app/src/main/java/com/drdisagree/colorblendr/ui/views/RoundedMaterialButtonToggleGroup.java b/app/src/main/java/com/drdisagree/colorblendr/ui/views/RoundedMaterialButtonToggleGroup.kt similarity index 100% rename from app/src/main/java/com/drdisagree/colorblendr/ui/views/RoundedMaterialButtonToggleGroup.java rename to app/src/main/java/com/drdisagree/colorblendr/ui/views/RoundedMaterialButtonToggleGroup.kt diff --git a/app/src/main/java/com/drdisagree/colorblendr/ui/views/WallColorPreview.java b/app/src/main/java/com/drdisagree/colorblendr/ui/views/WallColorPreview.kt similarity index 100% rename from app/src/main/java/com/drdisagree/colorblendr/ui/views/WallColorPreview.java rename to app/src/main/java/com/drdisagree/colorblendr/ui/views/WallColorPreview.kt diff --git a/app/src/main/java/com/drdisagree/colorblendr/ui/widgets/ColorPickerWidget.java b/app/src/main/java/com/drdisagree/colorblendr/ui/widgets/ColorPickerWidget.kt similarity index 100% rename from app/src/main/java/com/drdisagree/colorblendr/ui/widgets/ColorPickerWidget.java rename to app/src/main/java/com/drdisagree/colorblendr/ui/widgets/ColorPickerWidget.kt diff --git a/app/src/main/java/com/drdisagree/colorblendr/ui/widgets/MenuWidget.java b/app/src/main/java/com/drdisagree/colorblendr/ui/widgets/MenuWidget.kt similarity index 100% rename from app/src/main/java/com/drdisagree/colorblendr/ui/widgets/MenuWidget.java rename to app/src/main/java/com/drdisagree/colorblendr/ui/widgets/MenuWidget.kt diff --git a/app/src/main/java/com/drdisagree/colorblendr/ui/widgets/ResizableSeekbar.java b/app/src/main/java/com/drdisagree/colorblendr/ui/widgets/ResizableSeekbar.kt similarity index 100% rename from app/src/main/java/com/drdisagree/colorblendr/ui/widgets/ResizableSeekbar.java rename to app/src/main/java/com/drdisagree/colorblendr/ui/widgets/ResizableSeekbar.kt diff --git a/app/src/main/java/com/drdisagree/colorblendr/ui/widgets/SeekbarWidget.java b/app/src/main/java/com/drdisagree/colorblendr/ui/widgets/SeekbarWidget.kt similarity index 100% rename from app/src/main/java/com/drdisagree/colorblendr/ui/widgets/SeekbarWidget.java rename to app/src/main/java/com/drdisagree/colorblendr/ui/widgets/SeekbarWidget.kt diff --git a/app/src/main/java/com/drdisagree/colorblendr/ui/widgets/SelectableViewWidget.java b/app/src/main/java/com/drdisagree/colorblendr/ui/widgets/SelectableViewWidget.kt similarity index 100% rename from app/src/main/java/com/drdisagree/colorblendr/ui/widgets/SelectableViewWidget.java rename to app/src/main/java/com/drdisagree/colorblendr/ui/widgets/SelectableViewWidget.kt diff --git a/app/src/main/java/com/drdisagree/colorblendr/ui/widgets/StylePreviewWidget.java b/app/src/main/java/com/drdisagree/colorblendr/ui/widgets/StylePreviewWidget.kt similarity index 100% rename from app/src/main/java/com/drdisagree/colorblendr/ui/widgets/StylePreviewWidget.java rename to app/src/main/java/com/drdisagree/colorblendr/ui/widgets/StylePreviewWidget.kt diff --git a/app/src/main/java/com/drdisagree/colorblendr/ui/widgets/SwitchWidget.java b/app/src/main/java/com/drdisagree/colorblendr/ui/widgets/SwitchWidget.kt similarity index 100% rename from app/src/main/java/com/drdisagree/colorblendr/ui/widgets/SwitchWidget.java rename to app/src/main/java/com/drdisagree/colorblendr/ui/widgets/SwitchWidget.kt diff --git a/app/src/main/java/com/drdisagree/colorblendr/utils/AppUtil.java b/app/src/main/java/com/drdisagree/colorblendr/utils/AppUtil.kt similarity index 100% rename from app/src/main/java/com/drdisagree/colorblendr/utils/AppUtil.java rename to app/src/main/java/com/drdisagree/colorblendr/utils/AppUtil.kt diff --git a/app/src/main/java/com/drdisagree/colorblendr/utils/ColorModifiers.java b/app/src/main/java/com/drdisagree/colorblendr/utils/ColorModifiers.kt similarity index 100% rename from app/src/main/java/com/drdisagree/colorblendr/utils/ColorModifiers.java rename to app/src/main/java/com/drdisagree/colorblendr/utils/ColorModifiers.kt diff --git a/app/src/main/java/com/drdisagree/colorblendr/utils/ColorSchemeUtil.java b/app/src/main/java/com/drdisagree/colorblendr/utils/ColorSchemeUtil.kt similarity index 100% rename from app/src/main/java/com/drdisagree/colorblendr/utils/ColorSchemeUtil.java rename to app/src/main/java/com/drdisagree/colorblendr/utils/ColorSchemeUtil.kt diff --git a/app/src/main/java/com/drdisagree/colorblendr/utils/ColorUtil.java b/app/src/main/java/com/drdisagree/colorblendr/utils/ColorUtil.kt similarity index 100% rename from app/src/main/java/com/drdisagree/colorblendr/utils/ColorUtil.java rename to app/src/main/java/com/drdisagree/colorblendr/utils/ColorUtil.kt diff --git a/app/src/main/java/com/drdisagree/colorblendr/utils/DynamicColors.java b/app/src/main/java/com/drdisagree/colorblendr/utils/DynamicColors.kt similarity index 100% rename from app/src/main/java/com/drdisagree/colorblendr/utils/DynamicColors.java rename to app/src/main/java/com/drdisagree/colorblendr/utils/DynamicColors.kt diff --git a/app/src/main/java/com/drdisagree/colorblendr/utils/FabricatedUtil.java b/app/src/main/java/com/drdisagree/colorblendr/utils/FabricatedUtil.kt similarity index 100% rename from app/src/main/java/com/drdisagree/colorblendr/utils/FabricatedUtil.java rename to app/src/main/java/com/drdisagree/colorblendr/utils/FabricatedUtil.kt diff --git a/app/src/main/java/com/drdisagree/colorblendr/utils/FragmentUtil.java b/app/src/main/java/com/drdisagree/colorblendr/utils/FragmentUtil.kt similarity index 100% rename from app/src/main/java/com/drdisagree/colorblendr/utils/FragmentUtil.java rename to app/src/main/java/com/drdisagree/colorblendr/utils/FragmentUtil.kt diff --git a/app/src/main/java/com/drdisagree/colorblendr/utils/MiscUtil.java b/app/src/main/java/com/drdisagree/colorblendr/utils/MiscUtil.kt similarity index 100% rename from app/src/main/java/com/drdisagree/colorblendr/utils/MiscUtil.java rename to app/src/main/java/com/drdisagree/colorblendr/utils/MiscUtil.kt diff --git a/app/src/main/java/com/drdisagree/colorblendr/utils/OverlayManager.java b/app/src/main/java/com/drdisagree/colorblendr/utils/OverlayManager.kt similarity index 100% rename from app/src/main/java/com/drdisagree/colorblendr/utils/OverlayManager.java rename to app/src/main/java/com/drdisagree/colorblendr/utils/OverlayManager.kt diff --git a/app/src/main/java/com/drdisagree/colorblendr/utils/ShizukuUtil.java b/app/src/main/java/com/drdisagree/colorblendr/utils/ShizukuUtil.kt similarity index 100% rename from app/src/main/java/com/drdisagree/colorblendr/utils/ShizukuUtil.java rename to app/src/main/java/com/drdisagree/colorblendr/utils/ShizukuUtil.kt diff --git a/app/src/main/java/com/drdisagree/colorblendr/utils/SystemUtil.java b/app/src/main/java/com/drdisagree/colorblendr/utils/SystemUtil.kt similarity index 100% rename from app/src/main/java/com/drdisagree/colorblendr/utils/SystemUtil.java rename to app/src/main/java/com/drdisagree/colorblendr/utils/SystemUtil.kt diff --git a/app/src/main/java/com/drdisagree/colorblendr/utils/WallpaperColorUtil.java b/app/src/main/java/com/drdisagree/colorblendr/utils/WallpaperColorUtil.kt similarity index 100% rename from app/src/main/java/com/drdisagree/colorblendr/utils/WallpaperColorUtil.java rename to app/src/main/java/com/drdisagree/colorblendr/utils/WallpaperColorUtil.kt diff --git a/app/src/main/java/com/drdisagree/colorblendr/utils/annotations/TestingOnly.java b/app/src/main/java/com/drdisagree/colorblendr/utils/annotations/TestingOnly.kt similarity index 100% rename from app/src/main/java/com/drdisagree/colorblendr/utils/annotations/TestingOnly.java rename to app/src/main/java/com/drdisagree/colorblendr/utils/annotations/TestingOnly.kt diff --git a/app/src/main/java/com/drdisagree/colorblendr/utils/fabricated/FabricatedOverlayEntry.java b/app/src/main/java/com/drdisagree/colorblendr/utils/fabricated/FabricatedOverlayEntry.kt similarity index 100% rename from app/src/main/java/com/drdisagree/colorblendr/utils/fabricated/FabricatedOverlayEntry.java rename to app/src/main/java/com/drdisagree/colorblendr/utils/fabricated/FabricatedOverlayEntry.kt diff --git a/app/src/main/java/com/drdisagree/colorblendr/utils/fabricated/FabricatedOverlayResource.java b/app/src/main/java/com/drdisagree/colorblendr/utils/fabricated/FabricatedOverlayResource.kt similarity index 100% rename from app/src/main/java/com/drdisagree/colorblendr/utils/fabricated/FabricatedOverlayResource.java rename to app/src/main/java/com/drdisagree/colorblendr/utils/fabricated/FabricatedOverlayResource.kt From a0f8bedd08a5b24fbcf94de7a6bbf79ffc8bad4a Mon Sep 17 00:00:00 2001 From: DrDisagree Date: Sat, 17 Aug 2024 15:23:21 +0600 Subject: [PATCH 3/7] Convert project to Kotlin --- .../com/drdisagree/colorblendr/ColorBlendr.kt | 95 +- .../drdisagree/colorblendr/common/Const.kt | 172 ++-- .../drdisagree/colorblendr/config/RPrefs.kt | 249 +++--- .../colorblendr/extension/MethodInterface.kt | 7 +- .../extension/ThemeOverlayPackage.kt | 97 +- .../provider/RemotePrefProvider.kt | 20 +- .../provider/RootConnectionProvider.kt | 221 +++-- .../provider/ShizukuConnectionProvider.kt | 87 +- .../colorblendr/service/AutoStartService.kt | 419 ++++----- .../colorblendr/service/BroadcastListener.kt | 258 +++--- .../service/RestartBroadcastReceiver.kt | 58 +- .../colorblendr/service/RootConnection.kt | 710 ++++++++------- .../service/ScheduledJobService.kt | 47 +- .../colorblendr/service/ServiceLauncher.kt | 38 +- .../colorblendr/service/ShizukuConnection.kt | 116 ++- .../colorblendr/ui/activities/MainActivity.kt | 198 ++-- .../ui/activities/SplashActivity.kt | 158 ++-- .../colorblendr/ui/adapters/AppListAdapter.kt | 221 +++-- .../ui/adapters/FragmentAdapter.kt | 36 +- .../ui/adapters/OnboardingAdapter.kt | 38 +- .../colorblendr/ui/fragments/AboutFragment.kt | 127 ++- .../ui/fragments/ColorPaletteFragment.kt | 488 +++++----- .../ui/fragments/ColorsFragment.kt | 397 ++++---- .../colorblendr/ui/fragments/HomeFragment.kt | 406 +++++---- .../ui/fragments/OnboardingFragment.kt | 356 ++++---- .../ui/fragments/OnboardingItem1Fragment.kt | 32 +- .../ui/fragments/OnboardingItem2Fragment.kt | 233 ++--- .../ui/fragments/OnboardingItem3Fragment.kt | 66 +- .../ui/fragments/PerAppThemeFragment.kt | 484 +++++----- .../ui/fragments/SettingsFragment.kt | 664 +++++++------- .../ui/fragments/StylesFragment.kt | 366 ++++---- .../colorblendr/ui/fragments/ThemeFragment.kt | 436 ++++----- .../colorblendr/ui/models/AppInfoModel.kt | 31 +- .../ui/viewmodels/SharedViewModel.kt | 47 +- .../colorblendr/ui/views/ColorPreview.kt | 191 ++-- .../colorblendr/ui/views/ResizableSeekbar.kt | 36 +- .../views/RoundedMaterialButtonToggleGroup.kt | 67 +- .../colorblendr/ui/views/WallColorPreview.kt | 517 ++++++----- .../ui/widgets/ColorPickerWidget.kt | 357 ++++---- .../colorblendr/ui/widgets/MenuWidget.kt | 239 ++--- .../ui/widgets/ResizableSeekbar.kt | 36 +- .../colorblendr/ui/widgets/SeekbarWidget.kt | 392 ++++---- .../ui/widgets/SelectableViewWidget.kt | 379 ++++---- .../ui/widgets/StylePreviewWidget.kt | 404 +++++---- .../colorblendr/ui/widgets/SwitchWidget.kt | 376 ++++---- .../drdisagree/colorblendr/utils/AppUtil.kt | 92 +- .../colorblendr/utils/ColorModifiers.kt | 174 ++-- .../colorblendr/utils/ColorSchemeUtil.kt | 203 +++-- .../drdisagree/colorblendr/utils/ColorUtil.kt | 845 +++++++++++------- .../colorblendr/utils/DynamicColors.kt | 409 +++++++-- .../colorblendr/utils/FabricatedUtil.kt | 452 +++++----- .../colorblendr/utils/FragmentUtil.kt | 145 +-- .../drdisagree/colorblendr/utils/MiscUtil.kt | 78 +- .../colorblendr/utils/OverlayManager.kt | 567 ++++++------ .../colorblendr/utils/ShizukuUtil.kt | 105 ++- .../colorblendr/utils/SystemUtil.kt | 107 ++- .../colorblendr/utils/WallpaperColorUtil.kt | 406 +++++---- .../utils/annotations/TestingOnly.kt | 21 +- .../fabricated/FabricatedOverlayEntry.kt | 111 +-- .../fabricated/FabricatedOverlayResource.kt | 195 ++-- 60 files changed, 7578 insertions(+), 6704 deletions(-) diff --git a/app/src/main/java/com/drdisagree/colorblendr/ColorBlendr.kt b/app/src/main/java/com/drdisagree/colorblendr/ColorBlendr.kt index 9d332fe..3289a95 100644 --- a/app/src/main/java/com/drdisagree/colorblendr/ColorBlendr.kt +++ b/app/src/main/java/com/drdisagree/colorblendr/ColorBlendr.kt @@ -1,55 +1,58 @@ -package com.drdisagree.colorblendr; - -import android.app.Application; -import android.content.Context; - -import com.drdisagree.colorblendr.provider.RootConnectionProvider; -import com.drdisagree.colorblendr.provider.ShizukuConnectionProvider; -import com.drdisagree.colorblendr.service.IRootConnection; -import com.drdisagree.colorblendr.service.IShizukuConnection; -import com.google.android.material.color.DynamicColors; - -import org.lsposed.hiddenapibypass.HiddenApiBypass; - -import java.lang.ref.WeakReference; - -public class ColorBlendr extends Application { - - private static ColorBlendr instance; - private static WeakReference contextReference; - - public void onCreate() { - super.onCreate(); - instance = this; - contextReference = new WeakReference<>(getApplicationContext()); - DynamicColors.applyToActivitiesIfAvailable(this); +package com.drdisagree.colorblendr + +import android.app.Application +import android.content.Context +import com.drdisagree.colorblendr.provider.RootConnectionProvider +import com.drdisagree.colorblendr.provider.ShizukuConnectionProvider +import com.drdisagree.colorblendr.service.IRootConnection +import com.drdisagree.colorblendr.service.IShizukuConnection +import com.google.android.material.color.DynamicColors +import org.lsposed.hiddenapibypass.HiddenApiBypass +import java.lang.ref.WeakReference + +class ColorBlendr : Application() { + override fun onCreate() { + super.onCreate() + instance = this + contextReference = WeakReference( + applicationContext + ) + DynamicColors.applyToActivitiesIfAvailable(this) } - public static Context getAppContext() { - if (contextReference == null || contextReference.get() == null) { - contextReference = new WeakReference<>(ColorBlendr.getInstance().getApplicationContext()); - } - return contextReference.get(); + override fun attachBaseContext(base: Context) { + super.attachBaseContext(base) + HiddenApiBypass.addHiddenApiExemptions("L") } - private static ColorBlendr getInstance() { - if (instance == null) { - instance = new ColorBlendr(); + companion object { + private lateinit var instance: ColorBlendr + private lateinit var contextReference: WeakReference + + @JvmStatic + val appContext: Context + get() { + if (!this::contextReference.isInitialized || contextReference.get() == null) { + contextReference = WeakReference( + getInstance().applicationContext + ) + } + return contextReference.get()!! + } + + private fun getInstance(): ColorBlendr { + if (!this::instance.isInitialized) { + instance = ColorBlendr() + } + return instance } - return instance; - } - public static IRootConnection getRootConnection() { - return RootConnectionProvider.getServiceProvider(); - } - - public static IShizukuConnection getShizukuConnection() { - return ShizukuConnectionProvider.getServiceProvider(); - } + @JvmStatic + val rootConnection: IRootConnection? + get() = RootConnectionProvider.serviceProvider - @Override - protected void attachBaseContext(Context base) { - super.attachBaseContext(base); - HiddenApiBypass.addHiddenApiExemptions("L"); + @JvmStatic + val shizukuConnection: IShizukuConnection? + get() = ShizukuConnectionProvider.serviceProvider } } \ No newline at end of file diff --git a/app/src/main/java/com/drdisagree/colorblendr/common/Const.kt b/app/src/main/java/com/drdisagree/colorblendr/common/Const.kt index 621945b..0fb58f7 100644 --- a/app/src/main/java/com/drdisagree/colorblendr/common/Const.kt +++ b/app/src/main/java/com/drdisagree/colorblendr/common/Const.kt @@ -1,109 +1,119 @@ -package com.drdisagree.colorblendr.common; +package com.drdisagree.colorblendr.common -import com.drdisagree.colorblendr.BuildConfig; -import com.drdisagree.colorblendr.config.RPrefs; -import com.google.gson.Gson; -import com.google.gson.reflect.TypeToken; - -import java.util.Arrays; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Set; -import java.util.concurrent.atomic.AtomicInteger; - -public class Const { +import com.drdisagree.colorblendr.BuildConfig +import com.drdisagree.colorblendr.config.RPrefs +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken +import java.util.concurrent.atomic.AtomicInteger +object Const { // Preferences file - public static final String SharedPrefs = BuildConfig.APPLICATION_ID + "_preferences"; + const val SHARED_PREFS: String = BuildConfig.APPLICATION_ID + "_preferences" // System packages - public static final String FRAMEWORK_PACKAGE = "android"; - public static final String SYSTEMUI_PACKAGE = "com.android.systemui"; - public static final String SHELL_PACKAGE = "com.android.shell"; + const val FRAMEWORK_PACKAGE: String = "android" + const val SYSTEMUI_PACKAGE: String = "com.android.systemui" + const val SHELL_PACKAGE: String = "com.android.shell" // General preferences - public static final String FIRST_RUN = "firstRun"; - public static final String THEMING_ENABLED = "themingEnabled"; - public static final String MONET_STYLE = "customMonetStyle"; - public static final String MONET_ACCENT_SATURATION = "monetAccentSaturationValue"; - public static final String MONET_BACKGROUND_SATURATION = "monetBackgroundSaturationValue"; - public static final String MONET_BACKGROUND_LIGHTNESS = "monetBackgroundLightnessValue"; - public static final String MONET_ACCURATE_SHADES = "monetAccurateShades"; - public static final String MONET_PITCH_BLACK_THEME = "monetPitchBlackTheme"; - public static final String MONET_SEED_COLOR = "monetSeedColor"; - public static final String MONET_SEED_COLOR_ENABLED = "monetSeedColorEnabled"; - public static final String MANUAL_OVERRIDE_COLORS = "manualOverrideColors"; - public static final String MONET_LAST_UPDATED = "monetLastUpdated"; - public static final String MONET_STYLE_ORIGINAL_NAME = "monetStyleOriginalName"; - public static final String FABRICATED_OVERLAY_SOURCE_PACKAGE = FRAMEWORK_PACKAGE; - public static final String FABRICATED_OVERLAY_NAME_SYSTEM = BuildConfig.APPLICATION_ID + "_dynamic_theme"; - public static final String FABRICATED_OVERLAY_NAME_SYSTEMUI = BuildConfig.APPLICATION_ID + "_dynamic_theme_system"; - public static final String FABRICATED_OVERLAY_NAME_APPS = BuildConfig.APPLICATION_ID + ".%s_dynamic_theme"; - public static final String WALLPAPER_COLOR_LIST = "wallpaperColorList"; - public static final String FABRICATED_OVERLAY_FOR_APPS_STATE = "fabricatedOverlayForAppsState"; - public static final String SHOW_PER_APP_THEME_WARN = "showPerAppThemeWarn"; - public static final String TINT_TEXT_COLOR = "tintTextColor"; - public static final int SHIZUKU_PERMISSION_REQUEST_ID = 100; - public static final String THEME_CUSTOMIZATION_OVERLAY_PACKAGES = "theme_customization_overlay_packages"; - public static final String SHIZUKU_THEMING_ENABLED = "shizukuThemingEnabled"; - public static final String APP_LIST_FILTER_METHOD = "appListFilterMethod"; - public static final AtomicInteger screenOrientation = new AtomicInteger(-1); + const val FIRST_RUN: String = "firstRun" + const val THEMING_ENABLED: String = "themingEnabled" + const val MONET_STYLE: String = "customMonetStyle" + const val MONET_ACCENT_SATURATION: String = "monetAccentSaturationValue" + const val MONET_BACKGROUND_SATURATION: String = "monetBackgroundSaturationValue" + const val MONET_BACKGROUND_LIGHTNESS: String = "monetBackgroundLightnessValue" + const val MONET_ACCURATE_SHADES: String = "monetAccurateShades" + const val MONET_PITCH_BLACK_THEME: String = "monetPitchBlackTheme" + const val MONET_SEED_COLOR: String = "monetSeedColor" + const val MONET_SEED_COLOR_ENABLED: String = "monetSeedColorEnabled" + const val MANUAL_OVERRIDE_COLORS: String = "manualOverrideColors" + const val MONET_LAST_UPDATED: String = "monetLastUpdated" + const val MONET_STYLE_ORIGINAL_NAME: String = "monetStyleOriginalName" + const val FABRICATED_OVERLAY_SOURCE_PACKAGE: String = FRAMEWORK_PACKAGE + const val FABRICATED_OVERLAY_NAME_SYSTEM: String = "${BuildConfig.APPLICATION_ID}_dynamic_theme" + const val FABRICATED_OVERLAY_NAME_SYSTEMUI: String = + "${BuildConfig.APPLICATION_ID}_dynamic_theme_system" + const val FABRICATED_OVERLAY_NAME_APPS: String = + "${BuildConfig.APPLICATION_ID}.%s_dynamic_theme" + const val WALLPAPER_COLOR_LIST: String = "wallpaperColorList" + private const val FABRICATED_OVERLAY_FOR_APPS_STATE: String = "fabricatedOverlayForAppsState" + const val SHOW_PER_APP_THEME_WARN: String = "showPerAppThemeWarn" + const val TINT_TEXT_COLOR: String = "tintTextColor" + const val SHIZUKU_PERMISSION_REQUEST_ID: Int = 100 + const val THEME_CUSTOMIZATION_OVERLAY_PACKAGES: String = "theme_customization_overlay_packages" + const val SHIZUKU_THEMING_ENABLED: String = "shizukuThemingEnabled" + const val APP_LIST_FILTER_METHOD: String = "appListFilterMethod" + val screenOrientation: AtomicInteger = AtomicInteger(-1) // Service preferences - public static final Gson GSON = new Gson(); - public static final String PREF_WORKING_METHOD = "workingMethod"; + val GSON: Gson = Gson() + private const val PREF_WORKING_METHOD: String = "workingMethod" + + var EXCLUDED_PREFS_FROM_BACKUP: Set = HashSet( + listOf( + FIRST_RUN, + PREF_WORKING_METHOD, + MONET_LAST_UPDATED, + THEMING_ENABLED, + SHIZUKU_THEMING_ENABLED, + WALLPAPER_COLOR_LIST + ) + ) + + fun saveSelectedFabricatedApps(selectedApps: HashMap) { + RPrefs.putString(FABRICATED_OVERLAY_FOR_APPS_STATE, GSON.toJson(selectedApps)) + } - public static Set EXCLUDED_PREFS_FROM_BACKUP = new HashSet<>( - Arrays.asList( - FIRST_RUN, - PREF_WORKING_METHOD, - MONET_LAST_UPDATED, - THEMING_ENABLED, - SHIZUKU_THEMING_ENABLED, - WALLPAPER_COLOR_LIST + val selectedFabricatedApps: HashMap + get() { + val selectedApps = RPrefs.getString( + FABRICATED_OVERLAY_FOR_APPS_STATE, + null ) - ); - - public static void saveSelectedFabricatedApps(HashMap selectedApps) { - RPrefs.putString(FABRICATED_OVERLAY_FOR_APPS_STATE, Const.GSON.toJson(selectedApps)); - } + if (selectedApps.isNullOrEmpty()) { + return HashMap() + } - public static HashMap getSelectedFabricatedApps() { - String selectedApps = RPrefs.getString(FABRICATED_OVERLAY_FOR_APPS_STATE, null); - if (selectedApps == null || selectedApps.isEmpty()) { - return new HashMap<>(); + return GSON.fromJson( + selectedApps, + object : + TypeToken?>() { + }.type + ) } - return Const.GSON.fromJson(selectedApps, new TypeToken>() { - }.getType()); + var WORKING_METHOD: WorkMethod = WorkMethod.NULL + + val workingMethod: WorkMethod + get() = WorkMethod.fromString( + RPrefs.getString( + PREF_WORKING_METHOD, + WorkMethod.NULL.toString() + ) + ) + + fun saveWorkingMethod(workMethod: WorkMethod) { + RPrefs.putString(PREF_WORKING_METHOD, workMethod.toString()) } // Working method of app - public enum WORK_METHOD { + enum class WorkMethod { NULL, ROOT, SHIZUKU; - public static WORK_METHOD fromString(String str) { - try { - return valueOf(str); - } catch (Exception e) { - return NULL; + companion object { + fun fromString(str: String?): WorkMethod { + return try { + valueOf(str!!) + } catch (e: Exception) { + NULL + } } } } - public static WORK_METHOD WORKING_METHOD = WORK_METHOD.NULL; - - public static WORK_METHOD getWorkingMethod() { - return WORK_METHOD.fromString(RPrefs.getString(PREF_WORKING_METHOD, WORK_METHOD.NULL.toString())); - } - - public static void saveWorkingMethod(WORK_METHOD workMethod) { - RPrefs.putString(PREF_WORKING_METHOD, workMethod.toString()); - } - - public enum AppType { + enum class AppType { SYSTEM, USER, LAUNCHABLE, diff --git a/app/src/main/java/com/drdisagree/colorblendr/config/RPrefs.kt b/app/src/main/java/com/drdisagree/colorblendr/config/RPrefs.kt index 97bcd17..a5011f9 100644 --- a/app/src/main/java/com/drdisagree/colorblendr/config/RPrefs.kt +++ b/app/src/main/java/com/drdisagree/colorblendr/config/RPrefs.kt @@ -1,182 +1,205 @@ -package com.drdisagree.colorblendr.config; +package com.drdisagree.colorblendr.config -import static android.content.Context.MODE_PRIVATE; -import static com.drdisagree.colorblendr.common.Const.EXCLUDED_PREFS_FROM_BACKUP; -import static com.drdisagree.colorblendr.common.Const.THEMING_ENABLED; +import android.content.Context +import android.content.SharedPreferences +import android.util.Log +import com.drdisagree.colorblendr.ColorBlendr.Companion.appContext +import com.drdisagree.colorblendr.common.Const +import com.drdisagree.colorblendr.common.Const.EXCLUDED_PREFS_FROM_BACKUP +import com.drdisagree.colorblendr.common.Const.THEMING_ENABLED +import java.io.IOException +import java.io.InputStream +import java.io.ObjectInputStream +import java.io.ObjectOutputStream +import java.io.OutputStream -import android.content.SharedPreferences; -import android.util.Log; +@Suppress("unused") +object RPrefs { + private val TAG: String = RPrefs::class.java.simpleName -import androidx.annotation.NonNull; + private var prefs: SharedPreferences = appContext + .createDeviceProtectedStorageContext() + .getSharedPreferences( + Const.SHARED_PREFS, Context.MODE_PRIVATE + ) + private var editor: SharedPreferences.Editor = prefs.edit() -import com.drdisagree.colorblendr.ColorBlendr; -import com.drdisagree.colorblendr.common.Const; - -import java.io.IOException; -import java.io.InputStream; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; -import java.io.OutputStream; -import java.util.HashMap; -import java.util.Map; - -@SuppressWarnings("unused") -public class RPrefs { - - private static final String TAG = RPrefs.class.getSimpleName(); - - public static SharedPreferences prefs = ColorBlendr.getAppContext().createDeviceProtectedStorageContext().getSharedPreferences(Const.SharedPrefs, MODE_PRIVATE); - static SharedPreferences.Editor editor = prefs.edit(); - - public static void putBoolean(String key, boolean val) { - editor.putBoolean(key, val).apply(); + fun putBoolean(key: String, `val`: Boolean) { + editor.putBoolean(key, `val`).apply() } - public static void putInt(String key, int val) { - editor.putInt(key, val).apply(); + fun putInt(key: String, `val`: Int) { + editor.putInt(key, `val`).apply() } - public static void putLong(String key, long val) { - editor.putLong(key, val).apply(); + fun putLong(key: String, `val`: Long) { + editor.putLong(key, `val`).apply() } - public static void putFloat(String key, float val) { - editor.putFloat(key, val).apply(); + fun putFloat(key: String, `val`: Float) { + editor.putFloat(key, `val`).apply() } - public static void putString(String key, String val) { - editor.putString(key, val).apply(); + fun putString(key: String, `val`: String) { + editor.putString(key, `val`).apply() } - public static boolean getBoolean(String key) { - return prefs.getBoolean(key, false); + fun getBoolean(key: String): Boolean { + return prefs.getBoolean(key, false) } - public static boolean getBoolean(String key, Boolean defValue) { - return prefs.getBoolean(key, defValue); + fun getBoolean(key: String, defValue: Boolean): Boolean { + return prefs.getBoolean(key, defValue) } - public static int getInt(String key) { - return prefs.getInt(key, 0); + fun getInt(key: String): Int { + return prefs.getInt(key, 0) } - public static int getInt(String key, int defValue) { - return prefs.getInt(key, defValue); + fun getInt(key: String, defValue: Int): Int { + return prefs.getInt(key, defValue) } - public static long getLong(String key) { - return prefs.getLong(key, 0); + fun getLong(key: String): Long { + return prefs.getLong(key, 0) } - public static long getLong(String key, long defValue) { - return prefs.getLong(key, defValue); + fun getLong(key: String, defValue: Long): Long { + return prefs.getLong(key, defValue) } - public static float getFloat(String key) { - return prefs.getFloat(key, 0); + fun getFloat(key: String): Float { + return prefs.getFloat(key, 0f) } - public static float getFloat(String key, float defValue) { - return prefs.getFloat(key, defValue); + fun getFloat(key: String, defValue: Float): Float { + return prefs.getFloat(key, defValue) } - public static String getString(String key) { - return prefs.getString(key, null); + fun getString(key: String): String? { + return prefs.getString(key, null) } - public static String getString(String key, String defValue) { - return prefs.getString(key, defValue); + fun getString(key: String, defValue: String?): String? { + return prefs.getString(key, defValue) } - public static void clearPref(String key) { - editor.remove(key).apply(); + fun clearPref(key: String) { + editor.remove(key).apply() } - public static void clearPrefs(String... keys) { - for (String key : keys) { - editor.remove(key).apply(); + fun clearPrefs(vararg keys: String) { + for (key in keys) { + editor.remove(key).apply() } } - public static void clearAllPrefs() { - editor.clear().apply(); + fun clearAllPrefs() { + editor.clear().apply() } - public static void backupPrefs(final @NonNull OutputStream outputStream) { - try (outputStream; ObjectOutputStream objectOutputStream = new ObjectOutputStream(outputStream)) { - objectOutputStream.writeObject(prefs.getAll()); - } catch (IOException e) { - Log.e(TAG, "Error serializing preferences", e); + fun backupPrefs(outputStream: OutputStream) { + try { + outputStream.use { + ObjectOutputStream(outputStream).use { objectOutputStream -> + objectOutputStream.writeObject( + prefs.all + ) + } + } + } catch (e: IOException) { + Log.e(TAG, "Error serializing preferences", e) } - try (outputStream; ObjectOutputStream objectOutputStream = new ObjectOutputStream(outputStream)) { - Map allPrefs = prefs.getAll(); - - for (String excludedPref : EXCLUDED_PREFS_FROM_BACKUP) { - allPrefs.remove(excludedPref); + try { + outputStream.use { + ObjectOutputStream(outputStream).use { objectOutputStream -> + val allPrefs = prefs.all + for (excludedPref in EXCLUDED_PREFS_FROM_BACKUP) { + allPrefs.remove(excludedPref) + } + objectOutputStream.writeObject(allPrefs) + } } - - objectOutputStream.writeObject(allPrefs); - } catch (IOException e) { - Log.e(TAG, "Error serializing preferences", e); + } catch (e: IOException) { + Log.e(TAG, "Error serializing preferences", e) } } - @SuppressWarnings("unchecked") - public static void restorePrefs(final @NonNull InputStream inputStream) { - Map map; - try (inputStream; ObjectInputStream objectInputStream = new ObjectInputStream(inputStream)) { - map = (Map) objectInputStream.readObject(); - } catch (ClassNotFoundException | IOException e) { - Log.e(TAG, "Error deserializing preferences", e); - return; + @Suppress("UNCHECKED_CAST") + fun restorePrefs(inputStream: InputStream) { + var map: Map + try { + inputStream.use { + ObjectInputStream(inputStream).use { objectInputStream -> + map = objectInputStream.readObject() as Map + } + } + } catch (e: ClassNotFoundException) { + Log.e(TAG, "Error deserializing preferences", e) + return + } catch (e: IOException) { + Log.e(TAG, "Error deserializing preferences", e) + return } // Retrieve excluded prefs from current prefs - Map excludedPrefs = new HashMap<>(); + val excludedPrefs: MutableMap = HashMap() // Restoring config will enable theming service - excludedPrefs.put(THEMING_ENABLED, true); + excludedPrefs[THEMING_ENABLED] = true - for (String excludedPref : EXCLUDED_PREFS_FROM_BACKUP) { - Object prefValue = prefs.getAll().get(excludedPref); + for (excludedPref in EXCLUDED_PREFS_FROM_BACKUP) { + val prefValue = prefs.all[excludedPref] if (prefValue != null) { - excludedPrefs.put(excludedPref, prefValue); + excludedPrefs[excludedPref] = prefValue } } - editor.clear(); + editor.clear() // Restore excluded prefs - for (Map.Entry entry : excludedPrefs.entrySet()) { - putObject(entry.getKey(), entry.getValue()); + for ((key, value) in excludedPrefs) { + putObject(key, value) } // Restore non-excluded prefs - for (Map.Entry entry : map.entrySet()) { - if (EXCLUDED_PREFS_FROM_BACKUP.contains(entry.getKey())) { - continue; + for ((key, value) in map) { + if (EXCLUDED_PREFS_FROM_BACKUP.contains(key)) { + continue } - putObject(entry.getKey(), entry.getValue()); + putObject(key, value) } - editor.apply(); - } - - private static void putObject(String key, Object value) { - if (value instanceof Boolean) { - editor.putBoolean(key, (Boolean) value); - } else if (value instanceof String) { - editor.putString(key, (String) value); - } else if (value instanceof Integer) { - editor.putInt(key, (Integer) value); - } else if (value instanceof Float) { - editor.putFloat(key, (Float) value); - } else if (value instanceof Long) { - editor.putLong(key, (Long) value); - } else { - throw new IllegalArgumentException("Type " + value.getClass().getName() + " is unknown"); + editor.apply() + } + + private fun putObject(key: String, value: Any) { + when (value) { + is Boolean -> { + editor.putBoolean(key, value) + } + + is String -> { + editor.putString(key, value) + } + + is Int -> { + editor.putInt(key, value) + } + + is Float -> { + editor.putFloat(key, value) + } + + is Long -> { + editor.putLong(key, value) + } + + else -> { + throw IllegalArgumentException("Type " + value.javaClass.name + " is unknown") + } } } } diff --git a/app/src/main/java/com/drdisagree/colorblendr/extension/MethodInterface.kt b/app/src/main/java/com/drdisagree/colorblendr/extension/MethodInterface.kt index 10a6148..056a272 100644 --- a/app/src/main/java/com/drdisagree/colorblendr/extension/MethodInterface.kt +++ b/app/src/main/java/com/drdisagree/colorblendr/extension/MethodInterface.kt @@ -1,6 +1,5 @@ -package com.drdisagree.colorblendr.extension; +package com.drdisagree.colorblendr.extension -public abstract class MethodInterface { - - public abstract void run(); +abstract class MethodInterface { + abstract fun run() } diff --git a/app/src/main/java/com/drdisagree/colorblendr/extension/ThemeOverlayPackage.kt b/app/src/main/java/com/drdisagree/colorblendr/extension/ThemeOverlayPackage.kt index c0c9a75..030922e 100644 --- a/app/src/main/java/com/drdisagree/colorblendr/extension/ThemeOverlayPackage.kt +++ b/app/src/main/java/com/drdisagree/colorblendr/extension/ThemeOverlayPackage.kt @@ -1,51 +1,66 @@ -package com.drdisagree.colorblendr.extension; +package com.drdisagree.colorblendr.extension -import static com.drdisagree.colorblendr.common.Const.MONET_SEED_COLOR; -import static com.drdisagree.colorblendr.common.Const.MONET_STYLE_ORIGINAL_NAME; +import android.graphics.Color +import android.os.Build +import android.util.Log +import com.drdisagree.colorblendr.common.Const.MONET_SEED_COLOR +import com.drdisagree.colorblendr.common.Const.MONET_STYLE_ORIGINAL_NAME +import com.drdisagree.colorblendr.config.RPrefs.getInt +import com.drdisagree.colorblendr.config.RPrefs.getString +import com.drdisagree.colorblendr.utils.ColorUtil.intToHexColorNoHash +import org.json.JSONObject -import android.graphics.Color; -import android.os.Build; -import android.util.Log; +object ThemeOverlayPackage { + private val TAG: String = ThemeOverlayPackage::class.java.simpleName + const val THEME_STYLE: String = "android.theme.customization.theme_style" + const val COLOR_SOURCE: String = "android.theme.customization.color_source" + const val SYSTEM_PALETTE: String = "android.theme.customization.system_palette" + const val ACCENT_COLOR: String = "android.theme.customization.accent_color" + const val COLOR_BOTH: String = "android.theme.customization.color_both" + const val APPLIED_TIMESTAMP: String = "_applied_timestamp" -import com.drdisagree.colorblendr.config.RPrefs; -import com.drdisagree.colorblendr.utils.ColorUtil; + val themeCustomizationOverlayPackages: JSONObject + get() { + val `object` = JSONObject() -import org.json.JSONObject; - -public class ThemeOverlayPackage { - - private static final String TAG = ThemeOverlayPackage.class.getSimpleName(); - public static final String THEME_STYLE = "android.theme.customization.theme_style"; - public static final String COLOR_SOURCE = "android.theme.customization.color_source"; - public static final String SYSTEM_PALETTE = "android.theme.customization.system_palette"; - public static final String ACCENT_COLOR = "android.theme.customization.accent_color"; - public static final String COLOR_BOTH = "android.theme.customization.color_both"; - public static final String APPLIED_TIMESTAMP = "_applied_timestamp"; - - public static JSONObject getThemeCustomizationOverlayPackages() { - JSONObject object = new JSONObject(); - - try { - object.putOpt( + try { + `object`.putOpt( THEME_STYLE, - RPrefs.getString(MONET_STYLE_ORIGINAL_NAME, "TONAL_SPOT") - ); - object.putOpt(COLOR_SOURCE, "preset"); - object.putOpt( + getString(MONET_STYLE_ORIGINAL_NAME, "TONAL_SPOT") + ) + `object`.putOpt(COLOR_SOURCE, "preset") + `object`.putOpt( SYSTEM_PALETTE, - ColorUtil.intToHexColorNoHash(RPrefs.getInt(MONET_SEED_COLOR, Color.BLUE)) - ); - if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.S_V2) { - object.putOpt( + intToHexColorNoHash( + getInt( + MONET_SEED_COLOR, + Color.BLUE + ) + ) + ) + if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.S_V2) { + `object`.putOpt( ACCENT_COLOR, - ColorUtil.intToHexColorNoHash(RPrefs.getInt(MONET_SEED_COLOR, Color.BLUE)) - ); + intToHexColorNoHash( + getInt( + MONET_SEED_COLOR, + Color.BLUE + ) + ) + ) + } + `object`.putOpt( + APPLIED_TIMESTAMP, + System.currentTimeMillis() + ) + } catch (e: Exception) { + Log.e( + TAG, + "getThemeCustomizationOverlayPackages:", + e + ) } - object.putOpt(APPLIED_TIMESTAMP, System.currentTimeMillis()); - } catch (Exception e) { - Log.e(TAG, "getThemeCustomizationOverlayPackages:", e); - } - return object; - } + return `object` + } } diff --git a/app/src/main/java/com/drdisagree/colorblendr/provider/RemotePrefProvider.kt b/app/src/main/java/com/drdisagree/colorblendr/provider/RemotePrefProvider.kt index 2bc357d..4a1f3e9 100644 --- a/app/src/main/java/com/drdisagree/colorblendr/provider/RemotePrefProvider.kt +++ b/app/src/main/java/com/drdisagree/colorblendr/provider/RemotePrefProvider.kt @@ -1,13 +1,11 @@ -package com.drdisagree.colorblendr.provider; +package com.drdisagree.colorblendr.provider -import com.crossbowffs.remotepreferences.RemotePreferenceFile; -import com.crossbowffs.remotepreferences.RemotePreferenceProvider; -import com.drdisagree.colorblendr.BuildConfig; -import com.drdisagree.colorblendr.common.Const; +import com.crossbowffs.remotepreferences.RemotePreferenceFile +import com.crossbowffs.remotepreferences.RemotePreferenceProvider +import com.drdisagree.colorblendr.BuildConfig +import com.drdisagree.colorblendr.common.Const -public class RemotePrefProvider extends RemotePreferenceProvider { - - public RemotePrefProvider() { - super(BuildConfig.APPLICATION_ID, new RemotePreferenceFile[]{new RemotePreferenceFile(Const.SharedPrefs, true)}); - } -} \ No newline at end of file +class RemotePrefProvider : RemotePreferenceProvider( + BuildConfig.APPLICATION_ID, + arrayOf(RemotePreferenceFile(Const.SHARED_PREFS, true)) +) \ No newline at end of file diff --git a/app/src/main/java/com/drdisagree/colorblendr/provider/RootConnectionProvider.kt b/app/src/main/java/com/drdisagree/colorblendr/provider/RootConnectionProvider.kt index e148469..9f0c83d 100644 --- a/app/src/main/java/com/drdisagree/colorblendr/provider/RootConnectionProvider.kt +++ b/app/src/main/java/com/drdisagree/colorblendr/provider/RootConnectionProvider.kt @@ -1,164 +1,145 @@ -package com.drdisagree.colorblendr.provider; - -import android.content.ComponentName; -import android.content.Context; -import android.content.Intent; -import android.content.ServiceConnection; -import android.os.Handler; -import android.os.IBinder; -import android.os.Looper; -import android.util.Log; -import android.widget.Toast; - -import com.drdisagree.colorblendr.ColorBlendr; -import com.drdisagree.colorblendr.R; -import com.drdisagree.colorblendr.common.Const; -import com.drdisagree.colorblendr.extension.MethodInterface; -import com.drdisagree.colorblendr.service.IRootConnection; -import com.drdisagree.colorblendr.service.RootConnection; - -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.TimeUnit; - -public class RootConnectionProvider implements ServiceConnection { - - private static final String TAG = RootConnectionProvider.class.getSimpleName(); - private final Context context; - private static IRootConnection serviceProviderIPC; - private static boolean isServiceConnected = false; - private MethodInterface methodRunOnSuccess; - private MethodInterface methodRunOnFailure; - private static final CountDownLatch mServiceConnectionTimer = new CountDownLatch(1); - - private RootConnectionProvider(Context context) { - this.context = context; - } - - public static Builder builder(Context context) { - return new Builder(context); - } - - public static IRootConnection getServiceProvider() { - return serviceProviderIPC; - } - - public static boolean isNotConnected() { - return !isServiceConnected; - } - - private void bindServiceConnection() { +package com.drdisagree.colorblendr.provider + +import android.content.ComponentName +import android.content.Context +import android.content.Intent +import android.content.ServiceConnection +import android.os.Handler +import android.os.IBinder +import android.os.Looper +import android.util.Log +import android.widget.Toast +import com.drdisagree.colorblendr.ColorBlendr.Companion.appContext +import com.drdisagree.colorblendr.R +import com.drdisagree.colorblendr.common.Const +import com.drdisagree.colorblendr.common.Const.workingMethod +import com.drdisagree.colorblendr.extension.MethodInterface +import com.drdisagree.colorblendr.service.IRootConnection +import com.drdisagree.colorblendr.service.RootConnection +import com.topjohnwu.superuser.ipc.RootService +import java.util.concurrent.CountDownLatch +import java.util.concurrent.TimeUnit + +class RootConnectionProvider private constructor(private val context: Context?) : + ServiceConnection { + + private var methodRunOnSuccess: MethodInterface? = null + private var methodRunOnFailure: MethodInterface? = null + + private fun bindServiceConnection() { if (isServiceConnected) { - mServiceConnectionTimer.countDown(); - return; + mServiceConnectionTimer.countDown() + return } - new Handler(Looper.getMainLooper()).post(() -> RootConnection.bind( - new Intent(context, RootConnection.class), + Handler(Looper.getMainLooper()).post { + RootService.bind( + Intent(context, RootConnection::class.java), this - )); + ) + } } - @Override - public void onServiceConnected(ComponentName name, IBinder binder) { + override fun onServiceConnected(name: ComponentName, binder: IBinder?) { if (binder == null || !binder.pingBinder()) { - Log.w(TAG, "Service binder is null or not alive"); - return; + Log.w(TAG, "Service binder is null or not alive") + return } - serviceProviderIPC = IRootConnection.Stub.asInterface(binder); - isServiceConnected = true; - mServiceConnectionTimer.countDown(); - Log.i(TAG, "Service connected"); + serviceProvider = IRootConnection.Stub.asInterface(binder) + isServiceConnected = true + mServiceConnectionTimer.countDown() + Log.i(TAG, "Service connected") } - @Override - public void onServiceDisconnected(ComponentName name) { - serviceProviderIPC = null; - isServiceConnected = false; - Log.w(TAG, "Service disconnected"); - bindServiceConnection(); + override fun onServiceDisconnected(name: ComponentName) { + serviceProvider = null + isServiceConnected = false + Log.w(TAG, "Service disconnected") + bindServiceConnection() } - public static class ServiceConnectionThread extends Thread { - private final RootConnectionProvider instance; - - public ServiceConnectionThread(RootConnectionProvider instance) { - this.instance = instance; - } - - @Override - public void run() { + class ServiceConnectionThread(private val instance: RootConnectionProvider) : Thread() { + override fun run() { try { - instance.bindServiceConnection(); - boolean success = mServiceConnectionTimer.await(10, TimeUnit.SECONDS); - new Handler(Looper.getMainLooper()).post( - success ? - new SuccessRunnable(instance) : - new FailureRunnable(instance) - ); - } catch (Exception e) { - new Handler(Looper.getMainLooper()).post(() -> Toast.makeText( - ColorBlendr.getAppContext(), + instance.bindServiceConnection() + val success = mServiceConnectionTimer.await(10, TimeUnit.SECONDS) + Handler(Looper.getMainLooper()).post( + if (success) SuccessRunnable(instance) else FailureRunnable(instance) + ) + } catch (e: Exception) { + Handler(Looper.getMainLooper()).post { + Toast.makeText( + appContext, R.string.something_went_wrong, Toast.LENGTH_LONG - ).show()); - Log.e(TAG, "Error starting service connection", e); + ).show() + } + Log.e(TAG, "Error starting service connection", e) } } } - private record SuccessRunnable(RootConnectionProvider instance) implements Runnable { - @Override - public void run() { - new Handler(Looper.getMainLooper()).post(() -> { + private data class SuccessRunnable(val instance: RootConnectionProvider) : Runnable { + override fun run() { + Handler(Looper.getMainLooper()).post { if (instance.methodRunOnSuccess != null) { - instance.methodRunOnSuccess.run(); + instance.methodRunOnSuccess!!.run() } - }); + } } } - private record FailureRunnable(RootConnectionProvider instance) implements Runnable { - @Override - public void run() { - new Handler(Looper.getMainLooper()).post(() -> { + private data class FailureRunnable(val instance: RootConnectionProvider) : Runnable { + override fun run() { + Handler(Looper.getMainLooper()).post { if (instance.methodRunOnFailure != null) { - instance.methodRunOnFailure.run(); + instance.methodRunOnFailure!!.run() } else { - if (Const.getWorkingMethod() == Const.WORK_METHOD.ROOT || - Const.WORKING_METHOD == Const.WORK_METHOD.ROOT + if (workingMethod == Const.WorkMethod.ROOT || + Const.WORKING_METHOD == Const.WorkMethod.ROOT ) { Toast.makeText( - ColorBlendr.getAppContext(), - R.string.root_service_not_found, - Toast.LENGTH_LONG - ).show(); + appContext, + R.string.root_service_not_found, + Toast.LENGTH_LONG + ).show() } } - }); + } } } - @SuppressWarnings("all") - public static class Builder { - private final RootConnectionProvider instance; + class Builder(context: Context?) { + private val instance = RootConnectionProvider(context) - public Builder(Context context) { - instance = new RootConnectionProvider(context); + fun runOnSuccess(method: MethodInterface?): Builder { + instance.methodRunOnSuccess = method + return this } - public Builder runOnSuccess(MethodInterface method) { - instance.methodRunOnSuccess = method; - return this; + fun runOnFailure(method: MethodInterface?): Builder { + instance.methodRunOnFailure = method + return this } - public Builder runOnFailure(MethodInterface method) { - instance.methodRunOnFailure = method; - return this; + fun run() { + ServiceConnectionThread(instance).start() } + } - public void run() { - new ServiceConnectionThread(instance).start(); + companion object { + private val TAG: String = RootConnectionProvider::class.java.simpleName + var serviceProvider: IRootConnection? = null + private var isServiceConnected = false + private val mServiceConnectionTimer = CountDownLatch(1) + + @JvmStatic + fun builder(context: Context?): Builder { + return Builder(context) } + + val isNotConnected: Boolean + get() = !isServiceConnected } } diff --git a/app/src/main/java/com/drdisagree/colorblendr/provider/ShizukuConnectionProvider.kt b/app/src/main/java/com/drdisagree/colorblendr/provider/ShizukuConnectionProvider.kt index bf8f8f0..1bf447a 100644 --- a/app/src/main/java/com/drdisagree/colorblendr/provider/ShizukuConnectionProvider.kt +++ b/app/src/main/java/com/drdisagree/colorblendr/provider/ShizukuConnectionProvider.kt @@ -1,60 +1,55 @@ -package com.drdisagree.colorblendr.provider; - -import android.content.ComponentName; -import android.content.ServiceConnection; -import android.os.Handler; -import android.os.IBinder; -import android.os.Looper; -import android.util.Log; - -import com.drdisagree.colorblendr.service.IShizukuConnection; -import com.drdisagree.colorblendr.service.ShizukuConnection; -import com.drdisagree.colorblendr.utils.ShizukuUtil; - -public class ShizukuConnectionProvider { - - private static final String TAG = ShizukuConnectionProvider.class.getSimpleName(); - private static IShizukuConnection serviceProviderIPC; - private static boolean isServiceConnected = false; - - public static final ServiceConnection serviceConnection = new ServiceConnection() { - @Override - public void onServiceConnected(ComponentName name, IBinder binder) { - if (binder == null || !binder.pingBinder()) { - Log.w(TAG, "Service binder is null or not alive"); - return; +package com.drdisagree.colorblendr.provider + +import android.content.ComponentName +import android.content.ServiceConnection +import android.os.Handler +import android.os.IBinder +import android.os.Looper +import android.util.Log +import com.drdisagree.colorblendr.service.IShizukuConnection +import com.drdisagree.colorblendr.service.ShizukuConnection +import com.drdisagree.colorblendr.utils.ShizukuUtil.bindUserService +import com.drdisagree.colorblendr.utils.ShizukuUtil.getUserServiceArgs + +object ShizukuConnectionProvider { + + private val TAG: String = ShizukuConnectionProvider::class.java.simpleName + var serviceProvider: IShizukuConnection? = null + private var isServiceConnected = false + + val serviceConnection: ServiceConnection = object : ServiceConnection { + override fun onServiceConnected(name: ComponentName, binder: IBinder) { + if (!binder.pingBinder()) { + Log.w(TAG, "Service binder is null or not alive") + return } - serviceProviderIPC = IShizukuConnection.Stub.asInterface(binder); - isServiceConnected = true; - Log.i(TAG, "Service connected"); + serviceProvider = IShizukuConnection.Stub.asInterface(binder) + isServiceConnected = true + Log.i(TAG, "Service connected") } - @Override - public void onServiceDisconnected(ComponentName name) { - serviceProviderIPC = null; - isServiceConnected = false; - Log.w(TAG, "Service disconnected"); - bindServiceConnection(); + override fun onServiceDisconnected(name: ComponentName) { + serviceProvider = null + isServiceConnected = false + Log.w(TAG, "Service disconnected") + bindServiceConnection() } - }; - - public static IShizukuConnection getServiceProvider() { - return serviceProviderIPC; } - public static boolean isNotConnected() { - return !isServiceConnected; - } + val isNotConnected: Boolean + get() = !isServiceConnected - private static void bindServiceConnection() { + private fun bindServiceConnection() { if (isServiceConnected) { - return; + return } - new Handler(Looper.getMainLooper()).post(() -> ShizukuUtil.bindUserService( - ShizukuUtil.getUserServiceArgs(ShizukuConnection.class), + Handler(Looper.getMainLooper()).post { + bindUserService( + getUserServiceArgs(ShizukuConnection::class.java), serviceConnection - )); + ) + } } } diff --git a/app/src/main/java/com/drdisagree/colorblendr/service/AutoStartService.kt b/app/src/main/java/com/drdisagree/colorblendr/service/AutoStartService.kt index bb610f0..eb13d2c 100644 --- a/app/src/main/java/com/drdisagree/colorblendr/service/AutoStartService.kt +++ b/app/src/main/java/com/drdisagree/colorblendr/service/AutoStartService.kt @@ -1,274 +1,281 @@ -package com.drdisagree.colorblendr.service; - -import static com.drdisagree.colorblendr.utils.SystemUtil.sensorEventListener; - -import android.app.Notification; -import android.app.NotificationChannel; -import android.app.NotificationManager; -import android.app.PendingIntent; -import android.app.Service; -import android.content.Context; -import android.content.Intent; -import android.content.IntentFilter; -import android.hardware.Sensor; -import android.hardware.SensorManager; -import android.media.AudioManager; -import android.os.IBinder; -import android.os.RemoteException; -import android.provider.Settings; -import android.util.Log; - -import androidx.annotation.Nullable; -import androidx.core.app.NotificationCompat; -import androidx.localbroadcastmanager.content.LocalBroadcastManager; - -import com.drdisagree.colorblendr.BuildConfig; -import com.drdisagree.colorblendr.ColorBlendr; -import com.drdisagree.colorblendr.R; -import com.drdisagree.colorblendr.utils.annotations.TestingOnly; -import com.drdisagree.colorblendr.common.Const; -import com.drdisagree.colorblendr.extension.MethodInterface; -import com.drdisagree.colorblendr.provider.RootConnectionProvider; -import com.drdisagree.colorblendr.provider.ShizukuConnectionProvider; -import com.drdisagree.colorblendr.utils.ColorUtil; -import com.drdisagree.colorblendr.utils.ShizukuUtil; -import com.drdisagree.colorblendr.utils.SystemUtil; - -import java.util.Timer; -import java.util.TimerTask; - -public class AutoStartService extends Service { - - private static final String TAG = AutoStartService.class.getSimpleName(); - private static boolean isRunning = false; - private static final int NOTIFICATION_ID = 1; - private static final String NOTIFICATION_CHANNEL_ID = "Background Service"; - private static BroadcastListener myReceiver; - private NotificationManager notificationManager; - public static SensorManager sensorManager; - - public AutoStartService() { - isRunning = false; - myReceiver = new BroadcastListener(); +package com.drdisagree.colorblendr.service + +import android.app.NotificationChannel +import android.app.NotificationManager +import android.app.PendingIntent +import android.app.Service +import android.content.Context +import android.content.Intent +import android.content.IntentFilter +import android.hardware.Sensor +import android.hardware.SensorManager +import android.media.AudioManager +import android.os.IBinder +import android.os.RemoteException +import android.provider.Settings +import android.util.Log +import androidx.core.app.NotificationCompat +import androidx.localbroadcastmanager.content.LocalBroadcastManager +import com.drdisagree.colorblendr.BuildConfig +import com.drdisagree.colorblendr.ColorBlendr.Companion.appContext +import com.drdisagree.colorblendr.ColorBlendr.Companion.rootConnection +import com.drdisagree.colorblendr.R +import com.drdisagree.colorblendr.common.Const +import com.drdisagree.colorblendr.common.Const.workingMethod +import com.drdisagree.colorblendr.extension.MethodInterface +import com.drdisagree.colorblendr.provider.RootConnectionProvider +import com.drdisagree.colorblendr.provider.ShizukuConnectionProvider +import com.drdisagree.colorblendr.utils.ColorUtil.getAccentColor +import com.drdisagree.colorblendr.utils.ShizukuUtil.bindUserService +import com.drdisagree.colorblendr.utils.ShizukuUtil.getUserServiceArgs +import com.drdisagree.colorblendr.utils.ShizukuUtil.hasShizukuPermission +import com.drdisagree.colorblendr.utils.ShizukuUtil.isShizukuAvailable +import com.drdisagree.colorblendr.utils.SystemUtil.getScreenRotation +import com.drdisagree.colorblendr.utils.SystemUtil.sensorEventListener +import com.drdisagree.colorblendr.utils.annotations.TestingOnly +import java.util.Timer +import java.util.TimerTask + +class AutoStartService : Service() { + private var notificationManager: NotificationManager? = null + override fun onBind(intent: Intent): IBinder? { + return null } - public static boolean isServiceNotRunning() { - return !isRunning; - } - - @Nullable - @Override - public IBinder onBind(Intent intent) { - return null; - } + override fun onCreate() { + super.onCreate() - @Override - public void onCreate() { - super.onCreate(); + isRunning = true + registerSystemServices() + createNotificationChannel() + showNotification() + registerReceivers() - isRunning = true; - registerSystemServices(); - createNotificationChannel(); - showNotification(); - registerReceivers(); - - if (BroadcastListener.lastOrientation == -1) { - BroadcastListener.lastOrientation = SystemUtil.getScreenRotation(this); + if (BroadcastListener.Companion.lastOrientation == -1) { + BroadcastListener.Companion.lastOrientation = getScreenRotation( + this + ) } } - @Override - public int onStartCommand(Intent intent, int flags, int startId) { - super.onStartCommand(intent, flags, startId); + override fun onStartCommand(intent: Intent, flags: Int, startId: Int): Int { + super.onStartCommand(intent, flags, startId) - setupSystemUIRestartListener(); + setupSystemUIRestartListener() if (isTestingService) { // Testing purposes only - startTimer(this); + startTimer(this) } - return START_STICKY; + return START_STICKY } - @Override - public void onDestroy() { - super.onDestroy(); + override fun onDestroy() { + super.onDestroy() - isRunning = false; - Log.i(TAG, "onDestroy: Service is destroyed :("); + isRunning = false + Log.i(TAG, "onDestroy: Service is destroyed :(") try { - unregisterReceiver(myReceiver); - } catch (Exception ignored) { + unregisterReceiver(myReceiver) + } catch (ignored: Exception) { // Receiver was probably never registered } - Intent broadcastIntent = new Intent(this, RestartBroadcastReceiver.class); - sendBroadcast(broadcastIntent); + val broadcastIntent = Intent( + this, + RestartBroadcastReceiver::class.java + ) + sendBroadcast(broadcastIntent) if (isTestingService) { // Testing purposes only - stopTimer(); + stopTimer() } } - private void registerSystemServices() { + private fun registerSystemServices() { if (notificationManager == null) { - notificationManager = getSystemService(NotificationManager.class); + notificationManager = getSystemService(NotificationManager::class.java) } if (sensorManager == null) { - sensorManager = getSystemService(SensorManager.class); + sensorManager = getSystemService(SensorManager::class.java) if (sensorManager != null) { - sensorManager.registerListener(sensorEventListener, - sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER), - SensorManager.SENSOR_DELAY_UI); + sensorManager!!.registerListener( + sensorEventListener, + sensorManager!!.getDefaultSensor(Sensor.TYPE_ACCELEROMETER), + SensorManager.SENSOR_DELAY_UI + ) } } } - private void createNotificationChannel() { - NotificationChannel channel = new NotificationChannel( - NOTIFICATION_CHANNEL_ID, - getString(R.string.background_service_notification_channel_title), - NotificationManager.IMPORTANCE_DEFAULT - ); - channel.setDescription(getString(R.string.background_service_notification_channel_text)); - notificationManager.createNotificationChannel(channel); + private fun createNotificationChannel() { + val channel = NotificationChannel( + NOTIFICATION_CHANNEL_ID, + getString(R.string.background_service_notification_channel_title), + NotificationManager.IMPORTANCE_DEFAULT + ) + channel.description = getString(R.string.background_service_notification_channel_text) + notificationManager!!.createNotificationChannel(channel) } - private void showNotification() { - Intent notificationIntent = new Intent(); - notificationIntent.setAction(Settings.ACTION_CHANNEL_NOTIFICATION_SETTINGS); - notificationIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - notificationIntent.putExtra(Settings.EXTRA_APP_PACKAGE, getPackageName()); - notificationIntent.putExtra(Settings.EXTRA_CHANNEL_ID, NOTIFICATION_CHANNEL_ID); - - PendingIntent pendingIntent = PendingIntent.getActivity( - this, - 0, - notificationIntent, - PendingIntent.FLAG_IMMUTABLE - ); - - Notification notification = new NotificationCompat.Builder( - this, - NOTIFICATION_CHANNEL_ID + private fun showNotification() { + val notificationIntent = Intent() + notificationIntent.setAction(Settings.ACTION_CHANNEL_NOTIFICATION_SETTINGS) + notificationIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) + notificationIntent.putExtra(Settings.EXTRA_APP_PACKAGE, packageName) + notificationIntent.putExtra(Settings.EXTRA_CHANNEL_ID, NOTIFICATION_CHANNEL_ID) + + val pendingIntent = PendingIntent.getActivity( + this, + 0, + notificationIntent, + PendingIntent.FLAG_IMMUTABLE ) - .setOngoing(true) - .setSmallIcon(R.drawable.ic_launcher_notification) - .setContentTitle(getString(R.string.background_service_notification_title)) - .setContentText(getString(R.string.background_service_notification_text)) - .setContentIntent(pendingIntent) - .setSound(null, AudioManager.STREAM_NOTIFICATION) - .setColor(ColorUtil.getAccentColor(this)) - .build(); - - startForeground(NOTIFICATION_ID, notification); + + val notification = NotificationCompat.Builder( + this, + NOTIFICATION_CHANNEL_ID + ) + .setOngoing(true) + .setSmallIcon(R.drawable.ic_launcher_notification) + .setContentTitle(getString(R.string.background_service_notification_title)) + .setContentText(getString(R.string.background_service_notification_text)) + .setContentIntent(pendingIntent) + .setSound(null, AudioManager.STREAM_NOTIFICATION) + .setColor(getAccentColor(this)) + .build() + + startForeground(NOTIFICATION_ID, notification) } - @SuppressWarnings("all") - private void registerReceivers() { - IntentFilter intentFilterWithoutScheme = new IntentFilter(); - intentFilterWithoutScheme.addAction(Intent.ACTION_WALLPAPER_CHANGED); - intentFilterWithoutScheme.addAction(Intent.ACTION_CONFIGURATION_CHANGED); - intentFilterWithoutScheme.addAction(Intent.ACTION_SCREEN_OFF); - intentFilterWithoutScheme.addAction(Intent.ACTION_MY_PACKAGE_REPLACED); - intentFilterWithoutScheme.addAction(Intent.ACTION_PACKAGE_ADDED); - intentFilterWithoutScheme.addAction(Intent.ACTION_PACKAGE_REMOVED); - intentFilterWithoutScheme.addAction(Intent.ACTION_PACKAGE_REPLACED); - - IntentFilter intentFilterWithScheme = new IntentFilter(); - intentFilterWithScheme.addAction(Intent.ACTION_PACKAGE_ADDED); - intentFilterWithScheme.addAction(Intent.ACTION_PACKAGE_REMOVED); - intentFilterWithScheme.addAction(Intent.ACTION_PACKAGE_REPLACED); - intentFilterWithScheme.addDataScheme("package"); - - registerReceiver(myReceiver, intentFilterWithoutScheme); - registerReceiver(myReceiver, intentFilterWithScheme); + @Suppress("DEPRECATION") + private fun registerReceivers() { + val intentFilterWithoutScheme = IntentFilter() + intentFilterWithoutScheme.addAction(Intent.ACTION_WALLPAPER_CHANGED) + intentFilterWithoutScheme.addAction(Intent.ACTION_CONFIGURATION_CHANGED) + intentFilterWithoutScheme.addAction(Intent.ACTION_SCREEN_OFF) + intentFilterWithoutScheme.addAction(Intent.ACTION_MY_PACKAGE_REPLACED) + intentFilterWithoutScheme.addAction(Intent.ACTION_PACKAGE_ADDED) + intentFilterWithoutScheme.addAction(Intent.ACTION_PACKAGE_REMOVED) + intentFilterWithoutScheme.addAction(Intent.ACTION_PACKAGE_REPLACED) + + val intentFilterWithScheme = IntentFilter() + intentFilterWithScheme.addAction(Intent.ACTION_PACKAGE_ADDED) + intentFilterWithScheme.addAction(Intent.ACTION_PACKAGE_REMOVED) + intentFilterWithScheme.addAction(Intent.ACTION_PACKAGE_REPLACED) + intentFilterWithScheme.addDataScheme("package") + + registerReceiver(myReceiver, intentFilterWithoutScheme) + registerReceiver(myReceiver, intentFilterWithScheme) } - private void setupSystemUIRestartListener() { - if (Const.getWorkingMethod() == Const.WORK_METHOD.ROOT && - RootConnectionProvider.isNotConnected() + private fun setupSystemUIRestartListener() { + if (workingMethod == Const.WorkMethod.ROOT && + RootConnectionProvider.isNotConnected ) { - RootConnectionProvider.builder(ColorBlendr.getAppContext()) - .runOnSuccess(new MethodInterface() { - @Override - public void run() { - initSystemUIRestartListener(); - } - }) - .run(); - } else if (Const.getWorkingMethod() == Const.WORK_METHOD.SHIZUKU && - ShizukuConnectionProvider.isNotConnected() && - ShizukuUtil.isShizukuAvailable() && - ShizukuUtil.hasShizukuPermission(ColorBlendr.getAppContext()) + RootConnectionProvider.builder(appContext) + .runOnSuccess(object : MethodInterface() { + override fun run() { + initSystemUIRestartListener() + } + }) + .run() + } else if (workingMethod == Const.WorkMethod.SHIZUKU && + ShizukuConnectionProvider.isNotConnected && + isShizukuAvailable && + hasShizukuPermission(appContext) ) { - ShizukuUtil.bindUserService( - ShizukuUtil.getUserServiceArgs(ShizukuConnection.class), - ShizukuConnectionProvider.serviceConnection - ); - } else if (Const.getWorkingMethod() == Const.WORK_METHOD.ROOT) { - initSystemUIRestartListener(); + bindUserService( + getUserServiceArgs(ShizukuConnection::class.java), + ShizukuConnectionProvider.serviceConnection + ) + } else if (workingMethod == Const.WorkMethod.ROOT) { + initSystemUIRestartListener() } } - private void initSystemUIRestartListener() { + private fun initSystemUIRestartListener() { try { - ColorBlendr.getRootConnection().setSystemUIRestartListener(); - } catch (RemoteException e) { - Log.e(TAG, "Failed to set SystemUI restart listener", e); + rootConnection?.setSystemUIRestartListener() + } catch (e: RemoteException) { + Log.e(TAG, "Failed to set SystemUI restart listener", e) } } - /* - * The following fields and methods are for testing purposes only - */ - @TestingOnly - private static final String TEST_TAG = AutoStartService.class.getSimpleName() + "_TEST"; - @TestingOnly - private final boolean TEST_BACKGROUND_SERVICE = false; - @TestingOnly - private final boolean isTestingService = BuildConfig.DEBUG && TEST_BACKGROUND_SERVICE; @TestingOnly - public int counter = 0; - @TestingOnly - private Timer timer; - @TestingOnly - private static final String packageName = ColorBlendr.getAppContext().getPackageName(); + private val testBackgroundService = false + @TestingOnly - public static final String ACTION_FOO = packageName + ".FOO"; + private val isTestingService = BuildConfig.DEBUG && testBackgroundService + @TestingOnly - public static final String EXTRA_PARAM_A = packageName + ".PARAM_A"; + var counter: Int = 0 @TestingOnly - public void startTimer(Context context) { - timer = new Timer(); - timer.schedule(new TimerTask() { - @Override - public void run() { - Log.i(TEST_TAG, "Timer is running " + counter++); - broadcastActionTest(context, String.valueOf(counter)); - } - }, 1000, 1000); + private var timer: Timer? = null + + init { + isRunning = false + myReceiver = BroadcastListener() } @TestingOnly - public static void broadcastActionTest(Context context, String param) { - Intent intent = new Intent(ACTION_FOO); - intent.putExtra(EXTRA_PARAM_A, param); - LocalBroadcastManager bm = LocalBroadcastManager.getInstance(context); - bm.sendBroadcast(intent); + fun startTimer(context: Context) { + timer = Timer() + timer!!.schedule(object : TimerTask() { + override fun run() { + Log.i(TEST_TAG, "Timer is running " + counter++) + broadcastActionTest(context, counter.toString()) + } + }, 1000, 1000) } @TestingOnly - public void stopTimer() { + fun stopTimer() { if (timer != null) { - timer.cancel(); - timer = null; + timer!!.cancel() + timer = null + } + } + + companion object { + private val TAG: String = AutoStartService::class.java.simpleName + private var isRunning = false + private const val NOTIFICATION_ID = 1 + private const val NOTIFICATION_CHANNEL_ID = "Background Service" + private lateinit var myReceiver: BroadcastListener + var sensorManager: SensorManager? = null + + @JvmStatic + val isServiceNotRunning: Boolean + get() = !isRunning + + /* + * The following fields and methods are for testing purposes only + */ + @TestingOnly + private val TEST_TAG = AutoStartService::class.java.simpleName + "_TEST" + + @TestingOnly + private val packageName: String = appContext.packageName + + @TestingOnly + val ACTION_FOO: String = "$packageName.FOO" + + @TestingOnly + val EXTRA_PARAM_A: String = "$packageName.PARAM_A" + + @TestingOnly + fun broadcastActionTest(context: Context, param: String?) { + val intent = Intent(ACTION_FOO) + intent.putExtra(EXTRA_PARAM_A, param) + val bm = LocalBroadcastManager.getInstance(context) + bm.sendBroadcast(intent) } } } diff --git a/app/src/main/java/com/drdisagree/colorblendr/service/BroadcastListener.kt b/app/src/main/java/com/drdisagree/colorblendr/service/BroadcastListener.kt index 2977e42..c67d388 100644 --- a/app/src/main/java/com/drdisagree/colorblendr/service/BroadcastListener.kt +++ b/app/src/main/java/com/drdisagree/colorblendr/service/BroadcastListener.kt @@ -1,171 +1,187 @@ -package com.drdisagree.colorblendr.service; - -import static com.drdisagree.colorblendr.common.Const.FABRICATED_OVERLAY_NAME_APPS; -import static com.drdisagree.colorblendr.common.Const.MONET_LAST_UPDATED; -import static com.drdisagree.colorblendr.common.Const.MONET_SEED_COLOR; -import static com.drdisagree.colorblendr.common.Const.MONET_SEED_COLOR_ENABLED; -import static com.drdisagree.colorblendr.common.Const.SHIZUKU_THEMING_ENABLED; -import static com.drdisagree.colorblendr.common.Const.THEMING_ENABLED; -import static com.drdisagree.colorblendr.common.Const.WALLPAPER_COLOR_LIST; - -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; -import android.net.Uri; -import android.os.Handler; -import android.os.Looper; -import android.util.Log; - -import androidx.localbroadcastmanager.content.LocalBroadcastManager; - -import com.drdisagree.colorblendr.common.Const; -import com.drdisagree.colorblendr.config.RPrefs; -import com.drdisagree.colorblendr.extension.MethodInterface; -import com.drdisagree.colorblendr.provider.RootConnectionProvider; -import com.drdisagree.colorblendr.utils.AppUtil; -import com.drdisagree.colorblendr.utils.OverlayManager; -import com.drdisagree.colorblendr.utils.SystemUtil; -import com.drdisagree.colorblendr.utils.WallpaperColorUtil; - -import java.util.ArrayList; -import java.util.HashMap; - -public class BroadcastListener extends BroadcastReceiver { - - private static final String TAG = BroadcastListener.class.getSimpleName(); - public static int lastOrientation = -1; - private static long cooldownTime = 5000; - - @SuppressWarnings("deprecation") - @Override - public void onReceive(Context context, Intent intent) { - Log.d(TAG, "Received intent: " + intent.getAction()); +package com.drdisagree.colorblendr.service + +import android.content.BroadcastReceiver +import android.content.Context +import android.content.Intent +import android.os.Handler +import android.os.Looper +import android.util.Log +import androidx.localbroadcastmanager.content.LocalBroadcastManager +import com.drdisagree.colorblendr.common.Const +import com.drdisagree.colorblendr.common.Const.FABRICATED_OVERLAY_NAME_APPS +import com.drdisagree.colorblendr.common.Const.MONET_LAST_UPDATED +import com.drdisagree.colorblendr.common.Const.MONET_SEED_COLOR +import com.drdisagree.colorblendr.common.Const.MONET_SEED_COLOR_ENABLED +import com.drdisagree.colorblendr.common.Const.SHIZUKU_THEMING_ENABLED +import com.drdisagree.colorblendr.common.Const.THEMING_ENABLED +import com.drdisagree.colorblendr.common.Const.WALLPAPER_COLOR_LIST +import com.drdisagree.colorblendr.common.Const.saveSelectedFabricatedApps +import com.drdisagree.colorblendr.common.Const.selectedFabricatedApps +import com.drdisagree.colorblendr.common.Const.workingMethod +import com.drdisagree.colorblendr.config.RPrefs.getBoolean +import com.drdisagree.colorblendr.config.RPrefs.getLong +import com.drdisagree.colorblendr.config.RPrefs.putInt +import com.drdisagree.colorblendr.config.RPrefs.putLong +import com.drdisagree.colorblendr.config.RPrefs.putString +import com.drdisagree.colorblendr.extension.MethodInterface +import com.drdisagree.colorblendr.provider.RootConnectionProvider +import com.drdisagree.colorblendr.utils.AppUtil.permissionsGranted +import com.drdisagree.colorblendr.utils.OverlayManager.applyFabricatedColors +import com.drdisagree.colorblendr.utils.OverlayManager.applyFabricatedColorsPerApp +import com.drdisagree.colorblendr.utils.OverlayManager.unregisterFabricatedOverlay +import com.drdisagree.colorblendr.utils.SystemUtil.getScreenRotation +import com.drdisagree.colorblendr.utils.WallpaperColorUtil.getWallpaperColors +import kotlin.math.abs + +class BroadcastListener : BroadcastReceiver() { + @Suppress("deprecation") + override fun onReceive(context: Context, intent: Intent) { + Log.d(TAG, "Received intent: " + intent.action) if (lastOrientation == -1) { - lastOrientation = SystemUtil.getScreenRotation(context); + lastOrientation = getScreenRotation(context) } - int currentOrientation = SystemUtil.getScreenRotation(context); + val currentOrientation = getScreenRotation(context) - if (Intent.ACTION_BOOT_COMPLETED.equals(intent.getAction()) || - Intent.ACTION_LOCKED_BOOT_COMPLETED.equals(intent.getAction()) + if (Intent.ACTION_BOOT_COMPLETED == intent.action || + Intent.ACTION_LOCKED_BOOT_COMPLETED == intent.action ) { // Start background service on boot - if (AppUtil.permissionsGranted(context) && AutoStartService.isServiceNotRunning()) { - context.startForegroundService(new Intent(context, AutoStartService.class)); + if (permissionsGranted(context) && AutoStartService.isServiceNotRunning) { + context.startForegroundService(Intent(context, AutoStartService::class.java)) } - validateRootAndUpdateColors(context, new MethodInterface() { - @Override - public void run() { - cooldownTime = 10000; - new Handler(Looper.getMainLooper()).postDelayed(() -> cooldownTime = 5000, 10000); - updateAllColors(context); + validateRootAndUpdateColors(context, object : MethodInterface() { + override fun run() { + cooldownTime = 10000 + Handler(Looper.getMainLooper()).postDelayed({ + cooldownTime = 5000 + }, 10000) + updateAllColors(context) } - }); + }) } // Update wallpaper colors on wallpaper change - if (Intent.ACTION_WALLPAPER_CHANGED.equals(intent.getAction()) && - AppUtil.permissionsGranted(context) + if (Intent.ACTION_WALLPAPER_CHANGED == intent.action && + permissionsGranted(context) ) { - ArrayList wallpaperColors = WallpaperColorUtil.getWallpaperColors(context); - RPrefs.putString(WALLPAPER_COLOR_LIST, Const.GSON.toJson(wallpaperColors)); + val wallpaperColors = getWallpaperColors(context) + putString(WALLPAPER_COLOR_LIST, Const.GSON.toJson(wallpaperColors)) - if (!RPrefs.getBoolean(MONET_SEED_COLOR_ENABLED, false)) { - RPrefs.putInt(MONET_SEED_COLOR, wallpaperColors.get(0)); + if (!getBoolean(MONET_SEED_COLOR_ENABLED, false)) { + putInt(MONET_SEED_COLOR, wallpaperColors[0]) } } // Update fabricated colors on wallpaper change - if (Intent.ACTION_WALLPAPER_CHANGED.equals(intent.getAction()) || - (Intent.ACTION_CONFIGURATION_CHANGED.equals(intent.getAction()) && - lastOrientation == currentOrientation) + if (Intent.ACTION_WALLPAPER_CHANGED == intent.action || + (Intent.ACTION_CONFIGURATION_CHANGED == intent.action && + lastOrientation == currentOrientation) ) { - validateRootAndUpdateColors(context, new MethodInterface() { - @Override - public void run() { - updateAllColors(context); + validateRootAndUpdateColors(context, object : MethodInterface() { + override fun run() { + updateAllColors(context) } - }); + }) } else if (lastOrientation != currentOrientation) { - lastOrientation = currentOrientation; + lastOrientation = currentOrientation } - if (Intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())) { + if (Intent.ACTION_PACKAGE_REMOVED == intent.action) { // Remove fabricated colors for uninstalled apps - Uri data = intent.getData(); + val data = intent.data if (data != null) { - String packageName = data.getSchemeSpecificPart(); - HashMap selectedApps = Const.getSelectedFabricatedApps(); - - if (selectedApps.containsKey(packageName) && Boolean.TRUE.equals(selectedApps.get(packageName))) { - selectedApps.remove(packageName); - Const.saveSelectedFabricatedApps(selectedApps); - - validateRootAndUpdateColors(context, new MethodInterface() { - @Override - public void run() { - OverlayManager.unregisterFabricatedOverlay(String.format(FABRICATED_OVERLAY_NAME_APPS, packageName)); + val packageName = data.schemeSpecificPart + val selectedApps: HashMap = selectedFabricatedApps + + if (selectedApps.containsKey(packageName) && java.lang.Boolean.TRUE == selectedApps[packageName]) { + selectedApps.remove(packageName) + saveSelectedFabricatedApps(selectedApps) + + validateRootAndUpdateColors(context, object : MethodInterface() { + override fun run() { + unregisterFabricatedOverlay( + kotlin.String.format( + FABRICATED_OVERLAY_NAME_APPS, + packageName + ) + ) } - }); + }) } } - } else if (Intent.ACTION_MY_PACKAGE_REPLACED.equals(intent.getAction())) { + } else if (Intent.ACTION_MY_PACKAGE_REPLACED == intent.action) { // Update fabricated colors for updated app - validateRootAndUpdateColors(context, new MethodInterface() { - @Override - public void run() { - updateAllColors(context); + validateRootAndUpdateColors(context, object : MethodInterface() { + override fun run() { + updateAllColors(context) } - }); - } else if (Intent.ACTION_PACKAGE_REPLACED.equals(intent.getAction())) { + }) + } else if (Intent.ACTION_PACKAGE_REPLACED == intent.action) { // Update fabricated colors for updated app - Uri data = intent.getData(); + val data = intent.data if (data != null) { - String packageName = data.getSchemeSpecificPart(); - HashMap selectedApps = Const.getSelectedFabricatedApps(); - - if (selectedApps.containsKey(packageName) && Boolean.TRUE.equals(selectedApps.get(packageName))) { - validateRootAndUpdateColors(context, new MethodInterface() { - @Override - public void run() { - OverlayManager.applyFabricatedColorsPerApp(context, packageName, null); + val packageName = data.schemeSpecificPart + val selectedApps = selectedFabricatedApps + + if (selectedApps.containsKey(packageName) && java.lang.Boolean.TRUE == selectedApps[packageName]) { + validateRootAndUpdateColors(context, object : MethodInterface() { + override fun run() { + applyFabricatedColorsPerApp(context, packageName, null) } - }); + }) } } } - if (Intent.ACTION_PACKAGE_ADDED.equals(intent.getAction()) || - Intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction()) || - Intent.ACTION_WALLPAPER_CHANGED.equals(intent.getAction())) { - LocalBroadcastManager.getInstance(context).sendBroadcast(intent); + if (Intent.ACTION_PACKAGE_ADDED == intent.action || + Intent.ACTION_PACKAGE_REMOVED == intent.action || + Intent.ACTION_WALLPAPER_CHANGED == intent.action + ) { + LocalBroadcastManager.getInstance(context).sendBroadcast(intent) } } - private static void validateRootAndUpdateColors(Context context, MethodInterface method) { - if (Const.getWorkingMethod() == Const.WORK_METHOD.ROOT && - RootConnectionProvider.isNotConnected() - ) { - RootConnectionProvider.builder(context) + companion object { + private val TAG: String = BroadcastListener::class.java.simpleName + var lastOrientation: Int = -1 + private var cooldownTime: Long = 5000 + + private fun validateRootAndUpdateColors(context: Context, method: MethodInterface) { + if (workingMethod == Const.WorkMethod.ROOT && + RootConnectionProvider.isNotConnected + ) { + RootConnectionProvider.builder(context) .runOnSuccess(method) - .run(); - } else { - method.run(); + .run() + } else { + method.run() + } } - } - private static void updateAllColors(Context context) { - if (!RPrefs.getBoolean(THEMING_ENABLED, true) && !RPrefs.getBoolean(SHIZUKU_THEMING_ENABLED, true)) { - return; - } + private fun updateAllColors(context: Context) { + if (!getBoolean(THEMING_ENABLED, true) && !getBoolean(SHIZUKU_THEMING_ENABLED, true)) { + return + } - if (Math.abs(RPrefs.getLong(MONET_LAST_UPDATED, 0) - System.currentTimeMillis()) >= cooldownTime) { - RPrefs.putLong(MONET_LAST_UPDATED, System.currentTimeMillis()); - new Handler(Looper.getMainLooper()).postDelayed(() -> OverlayManager.applyFabricatedColors(context), 500); + if (abs( + (getLong( + MONET_LAST_UPDATED, + 0 + ) - System.currentTimeMillis()).toDouble() + ) >= cooldownTime + ) { + putLong(MONET_LAST_UPDATED, System.currentTimeMillis()) + Handler(Looper.getMainLooper()).postDelayed({ + applyFabricatedColors( + context + ) + }, 500) + } } } } diff --git a/app/src/main/java/com/drdisagree/colorblendr/service/RestartBroadcastReceiver.kt b/app/src/main/java/com/drdisagree/colorblendr/service/RestartBroadcastReceiver.kt index a3481f3..8828c3f 100644 --- a/app/src/main/java/com/drdisagree/colorblendr/service/RestartBroadcastReceiver.kt +++ b/app/src/main/java/com/drdisagree/colorblendr/service/RestartBroadcastReceiver.kt @@ -1,37 +1,37 @@ -package com.drdisagree.colorblendr.service; - -import static android.content.Context.JOB_SCHEDULER_SERVICE; - -import android.app.job.JobInfo; -import android.app.job.JobScheduler; -import android.content.BroadcastReceiver; -import android.content.ComponentName; -import android.content.Context; -import android.content.Intent; -import android.util.Log; - -public class RestartBroadcastReceiver extends BroadcastReceiver { - - private static final String TAG = RestartBroadcastReceiver.class.getSimpleName(); - private static JobScheduler jobScheduler; - - @Override - public void onReceive(Context context, Intent intent) { - Log.i(TAG, "Service Stopped, but this is a never ending service."); - scheduleJob(context); +package com.drdisagree.colorblendr.service + +import android.app.job.JobInfo +import android.app.job.JobScheduler +import android.content.BroadcastReceiver +import android.content.ComponentName +import android.content.Context +import android.content.Intent +import android.util.Log + +class RestartBroadcastReceiver : BroadcastReceiver() { + override fun onReceive(context: Context, intent: Intent) { + Log.i(TAG, "Service Stopped, but this is a never ending service.") + scheduleJob(context) } - public static void scheduleJob(Context context) { - if (jobScheduler == null) { - jobScheduler = (JobScheduler) context.getSystemService(JOB_SCHEDULER_SERVICE); - } + companion object { + private val TAG: String = RestartBroadcastReceiver::class.java.simpleName + private var jobScheduler: JobScheduler? = null - ComponentName componentName = new ComponentName(context, ScheduledJobService.class); + @JvmStatic + fun scheduleJob(context: Context) { + if (jobScheduler == null) { + jobScheduler = + context.getSystemService(Context.JOB_SCHEDULER_SERVICE) as JobScheduler + } - JobInfo jobInfo = new JobInfo.Builder(1, componentName) + val componentName = ComponentName(context, ScheduledJobService::class.java) + + val jobInfo = JobInfo.Builder(1, componentName) .setOverrideDeadline(0) - .setPersisted(true).build(); + .setPersisted(true).build() - jobScheduler.schedule(jobInfo); + jobScheduler!!.schedule(jobInfo) + } } } diff --git a/app/src/main/java/com/drdisagree/colorblendr/service/RootConnection.kt b/app/src/main/java/com/drdisagree/colorblendr/service/RootConnection.kt index c114208..4df7011 100644 --- a/app/src/main/java/com/drdisagree/colorblendr/service/RootConnection.kt +++ b/app/src/main/java/com/drdisagree/colorblendr/service/RootConnection.kt @@ -1,242 +1,139 @@ -package com.drdisagree.colorblendr.service; - -import static com.drdisagree.colorblendr.common.Const.FABRICATED_OVERLAY_NAME_SYSTEM; -import static com.drdisagree.colorblendr.common.Const.FABRICATED_OVERLAY_SOURCE_PACKAGE; -import static com.drdisagree.colorblendr.common.Const.SYSTEMUI_PACKAGE; - -import android.app.IActivityManager; -import android.app.IProcessObserver; -import android.content.Context; -import android.content.Intent; -import android.content.om.IOverlayManager; -import android.content.om.OverlayIdentifier; -import android.content.om.OverlayInfo; -import android.content.om.OverlayManagerTransaction; -import android.content.pm.PackageManager; -import android.os.Build; -import android.os.Handler; -import android.os.IBinder; -import android.os.Looper; -import android.os.Process; -import android.os.RemoteException; -import android.os.UserHandle; -import android.util.Log; - -import androidx.annotation.NonNull; - -import com.drdisagree.colorblendr.extension.MethodInterface; -import com.drdisagree.colorblendr.utils.fabricated.FabricatedOverlayEntry; -import com.drdisagree.colorblendr.utils.fabricated.FabricatedOverlayResource; -import com.topjohnwu.superuser.Shell; -import com.topjohnwu.superuser.internal.Utils; -import com.topjohnwu.superuser.ipc.RootService; - -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.util.Collections; -import java.util.List; -import java.util.Map; - -import rikka.shizuku.SystemServiceHelper; - -@SuppressWarnings({"all"}) -public class RootConnection extends RootService { - - @Override - public IBinder onBind(@NonNull Intent intent) { - return new RootConnectionImpl(); +package com.drdisagree.colorblendr.service + +import android.annotation.SuppressLint +import android.app.IActivityManager +import android.app.IProcessObserver +import android.content.Context +import android.content.Intent +import android.content.om.IOverlayManager +import android.content.om.OverlayIdentifier +import android.content.om.OverlayManagerTransaction +import android.content.pm.PackageManager +import android.os.Build +import android.os.Handler +import android.os.IBinder +import android.os.Looper +import android.os.Process +import android.os.RemoteException +import android.os.UserHandle +import android.util.Log +import com.drdisagree.colorblendr.common.Const.FABRICATED_OVERLAY_NAME_SYSTEM +import com.drdisagree.colorblendr.common.Const.FABRICATED_OVERLAY_SOURCE_PACKAGE +import com.drdisagree.colorblendr.common.Const.SYSTEMUI_PACKAGE +import com.drdisagree.colorblendr.extension.MethodInterface +import com.drdisagree.colorblendr.utils.fabricated.FabricatedOverlayResource +import com.topjohnwu.superuser.Shell +import com.topjohnwu.superuser.internal.Utils +import com.topjohnwu.superuser.ipc.RootService +import rikka.shizuku.SystemServiceHelper +import java.lang.reflect.InvocationTargetException +import java.lang.reflect.Method + +class RootConnection : RootService() { + override fun onBind(intent: Intent): IBinder { + return RootConnectionImpl() } - public static class RootConnectionImpl extends IRootConnection.Stub { - - private static final String TAG = RootConnectionImpl.class.getSimpleName(); - private static Context context = Utils.getContext(); - private static final UserHandle currentUser; - private static final int currentUserId; - private static IOverlayManager mOMS; - private static Class oiClass; - private static Class foClass; - private static Class fobClass; - private static Class omtbClass; - private static int SystemUI_UID = -1; - private static IActivityManager mActivityManager; - private static MethodInterface onSystemUIRestartedListener; - - private IProcessObserver.Stub processListener = new IProcessObserver.Stub() { - @Override - public void onForegroundActivitiesChanged(int pid, int uid, boolean foregroundActivities) throws RemoteException { + class RootConnectionImpl : IRootConnection.Stub() { + private val processListener: IProcessObserver.Stub = object : IProcessObserver.Stub() { + @Throws(RemoteException::class) + override fun onForegroundActivitiesChanged( + pid: Int, + uid: Int, + foregroundActivities: Boolean + ) { // Do nothing } - @Override - public void onForegroundServicesChanged(int pid, int uid, int serviceTypes) throws RemoteException { + @Throws(RemoteException::class) + override fun onForegroundServicesChanged(pid: Int, uid: Int, serviceTypes: Int) { // Do nothing } - @Override - public void onProcessDied(int pid, int uid) { - if (uid == getSystemUI_UID()) { - new Handler(Looper.getMainLooper()).postDelayed(() -> { + override fun onProcessDied(pid: Int, uid: Int) { + if (uid == getSystemUiUID()) { + Handler(Looper.getMainLooper()).postDelayed({ try { - enableOverlayWithIdentifier(Collections.singletonList(FABRICATED_OVERLAY_NAME_SYSTEM)); - } catch (RemoteException ignored) { + enableOverlayWithIdentifier( + listOf( + FABRICATED_OVERLAY_NAME_SYSTEM + ) + ) + } catch (ignored: RemoteException) { // Overlay was never registered } - }, 3000); + }, 3000) } } - }; - - static { - currentUser = getCurrentUser(); - currentUserId = getCurrentUserId(); - - if (mOMS == null) { - mOMS = IOverlayManager.Stub.asInterface(SystemServiceHelper.getSystemService("overlay")); - } - - if (mActivityManager == null) { - mActivityManager = IActivityManager.Stub.asInterface(SystemServiceHelper.getSystemService("activity")); - } - - try { - SystemUI_UID = context.getPackageManager().getPackageUid(SYSTEMUI_PACKAGE, 0); - } catch (PackageManager.NameNotFoundException e) { - Log.e(TAG, "static: ", e); - } - - try { - if (oiClass == null) { - oiClass = Class.forName("android.content.om.OverlayIdentifier"); - } - } catch (ClassNotFoundException e) { - Log.e(TAG, "static: ", e); - } - try { - if (foClass == null) { - foClass = Class.forName("android.content.om.FabricatedOverlay"); - } - } catch (ClassNotFoundException e) { - Log.e(TAG, "static: ", e); - } - try { - if (fobClass == null) { - fobClass = Class.forName("android.content.om.FabricatedOverlay$Builder"); - } - } catch (ClassNotFoundException e) { - Log.e(TAG, "static: ", e); - } - try { - if (omtbClass == null) { - omtbClass = Class.forName("android.content.om.OverlayManagerTransaction$Builder"); - } - } catch (ClassNotFoundException e) { - Log.e(TAG, "static: ", e); - } - } - - private static UserHandle getCurrentUser() { - return Process.myUserHandle(); } - private static Integer getCurrentUserId() { - try { - return (Integer) UserHandle.class.getMethod("getIdentifier").invoke(currentUser); - } catch (NoSuchMethodException | - IllegalAccessException | - InvocationTargetException exception) { - return 0; - } - } - - private static IOverlayManager getOMS() { - if (mOMS == null) { - mOMS = IOverlayManager.Stub.asInterface(SystemServiceHelper.getSystemService("overlay")); - } - return mOMS; - } - - private static IActivityManager getAM() { - if (mActivityManager == null) { - mActivityManager = IActivityManager.Stub.asInterface(SystemServiceHelper.getSystemService("activity")); - } - return mActivityManager; - } - - private static int getSystemUI_UID() { - if (SystemUI_UID == -1) { - try { - SystemUI_UID = context.getPackageManager().getPackageUid(SYSTEMUI_PACKAGE, 0); - } catch (PackageManager.NameNotFoundException e) { - // It's impossible to get here, but just in case - Log.e(TAG, "getSystemUI_UID: ", e); - } - } - return SystemUI_UID; - } - - @Override - public boolean isRooted() throws RemoteException { - return Shell.isAppGrantedRoot(); + @Throws(RemoteException::class) + override fun isRooted(): Boolean { + return Shell.isAppGrantedRoot()!! } /** * Listener to notify when SystemUI restarts. */ - @Override - public void setSystemUIRestartListener() throws RemoteException { - getAM().registerProcessObserver(processListener); + @Throws(RemoteException::class) + override fun setSystemUIRestartListener() { + aM!!.registerProcessObserver(processListener) } /** * Return true if an overlay package is installed. */ - @Override - public boolean isOverlayInstalled(String packageName) throws RemoteException { - return getOMS().getOverlayInfo(packageName, currentUserId) != null; + @Throws(RemoteException::class) + override fun isOverlayInstalled(packageName: String): Boolean { + return oMS!!.getOverlayInfo(packageName, currentUserId) != null } /** * Return true if an overlay package is enabled. */ - @Override - public boolean isOverlayEnabled(String packageName) throws RemoteException { - OverlayInfo overlay = getOMS().getOverlayInfoByIdentifier( - generateOverlayIdentifier(packageName), - currentUserId - ); + @Throws(RemoteException::class) + override fun isOverlayEnabled(packageName: String): Boolean { + val overlay = oMS!!.getOverlayInfoByIdentifier( + generateOverlayIdentifier(packageName), + currentUserId + ) if (overlay == null) { - return false; + return false } try { - Method isEnabled = overlay.getClass().getDeclaredMethod("isEnabled"); - return (boolean) isEnabled.invoke(overlay); - } catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException e) { - e.printStackTrace(); - return false; + val isEnabled = overlay.javaClass.getDeclaredMethod("isEnabled") + return isEnabled.invoke(overlay) as Boolean + } catch (e: NoSuchMethodException) { + e.printStackTrace() + return false + } catch (e: InvocationTargetException) { + e.printStackTrace() + return false + } catch (e: IllegalAccessException) { + e.printStackTrace() + return false } } /** * Request that an overlay package be enabled when possible to do so. */ - @Override - public void enableOverlay(List packages) { - for (String p : packages) { - switchOverlay(p, true); + override fun enableOverlay(packages: List) { + for (p in packages) { + switchOverlay(p, true) } } /** * Request that an overlay package be enabled when possible to do so. */ - @Override - public void enableOverlayWithIdentifier(List packages) throws RemoteException { - for (String p : packages) { - OverlayIdentifier identifier = generateOverlayIdentifier(p); - switchOverlayWithIdentifier(identifier, true); + @Throws(RemoteException::class) + override fun enableOverlayWithIdentifier(packages: List) { + for (p in packages) { + val identifier = generateOverlayIdentifier(p) + switchOverlayWithIdentifier(identifier, true) } } @@ -244,45 +141,46 @@ public class RootConnection extends RootService { * Request that an overlay package is enabled and any other overlay packages with the same * target package are disabled. */ - @Override - public boolean enableOverlayExclusive(String packageName) throws RemoteException { - return getOMS().setEnabledExclusive(packageName, true, currentUserId); + @Throws(RemoteException::class) + override fun enableOverlayExclusive(packageName: String): Boolean { + return oMS!!.setEnabledExclusive(packageName, true, currentUserId) } /** * Request that an overlay package is enabled and any other overlay packages with the same * target package and category are disabled. */ - @Override - public boolean enableOverlayExclusiveInCategory(String packageName) throws RemoteException { - return getOMS().setEnabledExclusiveInCategory(packageName, currentUserId); + @Throws(RemoteException::class) + override fun enableOverlayExclusiveInCategory(packageName: String): Boolean { + return oMS!!.setEnabledExclusiveInCategory(packageName, currentUserId) } /** * Request that an overlay package be disabled when possible to do so. */ - @Override - public void disableOverlay(List packages) throws RemoteException { - for (String p : packages) { - switchOverlay(p, false); + @Throws(RemoteException::class) + override fun disableOverlay(packages: List) { + for (p in packages) { + switchOverlay(p, false) } } /** * Request that an overlay package be disabled when possible to do so. */ - @Override - public void disableOverlayWithIdentifier(List packages) throws RemoteException { - for (String p : packages) { - OverlayIdentifier identifier = generateOverlayIdentifier(p); - switchOverlayWithIdentifier(identifier, false); + @Throws(RemoteException::class) + override fun disableOverlayWithIdentifier(packages: List) { + for (p in packages) { + val identifier = generateOverlayIdentifier(p) + switchOverlayWithIdentifier(identifier, false) } } /** * Registers the fabricated overlay with the overlay manager so it can be enabled and * disabled for any user. - *

+ * + * * The fabricated overlay is initialized in a disabled state. If an overlay is re-registered * the existing overlay will be replaced by the newly registered overlay and the enabled * state of the overlay will be left unchanged if the target package and target overlayable @@ -290,81 +188,80 @@ public class RootConnection extends RootService { * * @param overlay the overlay to register with the overlay manager */ - @Override - public void registerFabricatedOverlay(FabricatedOverlayResource overlay) throws RemoteException { + @Suppress("DEPRECATION") + @Throws(RemoteException::class) + override fun registerFabricatedOverlay(overlay: FabricatedOverlayResource) { try { - Object fobInstance = fobClass.getConstructor( - String.class, - String.class, - String.class + val fobInstance = fobClass!!.getConstructor( + String::class.java, + String::class.java, + String::class.java ).newInstance( - overlay.sourcePackage, - overlay.overlayName, - overlay.targetPackage - ); + overlay.sourcePackage, + overlay.overlayName, + overlay.targetPackage + ) - Method setResourceValueMethod = fobClass.getMethod( - "setResourceValue", - String.class, - int.class, - int.class - ); + val setResourceValueMethod = fobClass!!.getMethod( + "setResourceValue", + String::class.java, + Int::class.javaPrimitiveType, + Int::class.javaPrimitiveType + ) - boolean isA14orHigher = Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE; - Method setResourceValueMethodWithConfig = null; + val isA14orHigher = Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE + var setResourceValueMethodWithConfig: Method? = null if (isA14orHigher) { - setResourceValueMethodWithConfig = fobClass.getMethod( - "setResourceValue", - String.class, - int.class, - int.class, - String.class - ); + setResourceValueMethodWithConfig = fobClass!!.getMethod( + "setResourceValue", + String::class.java, + Int::class.javaPrimitiveType, + Int::class.javaPrimitiveType, + String::class.java + ) } - for (Map.Entry entry : overlay.getEntries().entrySet()) { - FabricatedOverlayEntry overlayEntry = entry.getValue(); - + for ((_, overlayEntry) in overlay.getEntries()) { if (isA14orHigher && overlayEntry.getConfiguration() != null && setResourceValueMethodWithConfig != null) { setResourceValueMethodWithConfig.invoke( - fobInstance, - overlayEntry.getResourceName(), - overlayEntry.getResourceType(), - overlayEntry.getResourceValue(), - overlayEntry.getConfiguration() - ); + fobInstance, + overlayEntry.resourceName, + overlayEntry.resourceType, + overlayEntry.resourceValue, + overlayEntry.getConfiguration() + ) } else { setResourceValueMethod.invoke( - fobInstance, - overlayEntry.getResourceName(), - overlayEntry.getResourceType(), - overlayEntry.getResourceValue() - ); + fobInstance, + overlayEntry.resourceName, + overlayEntry.resourceType, + overlayEntry.resourceValue + ) } } - Object foInstance = fobClass.getMethod( - "build" - ).invoke(fobInstance); + val foInstance = fobClass!!.getMethod( + "build" + ).invoke(fobInstance) - Object omtbInstance = omtbClass.newInstance(); + val omtbInstance = omtbClass!!.newInstance() - omtbClass.getMethod( - "registerFabricatedOverlay", - foClass + omtbClass!!.getMethod( + "registerFabricatedOverlay", + foClass ).invoke( - omtbInstance, - foInstance - ); + omtbInstance, + foInstance + ) - Object omtInstance = omtbClass.getMethod( - "build" - ).invoke(omtbInstance); + val omtInstance = omtbClass!!.getMethod( + "build" + ).invoke(omtbInstance) - commit(omtInstance); - } catch (Exception e) { - Log.e(TAG, "registerFabricatedOverlay: ", e); + commit(omtInstance) + } catch (e: Exception) { + Log.e(TAG, "registerFabricatedOverlay: ", e) } } @@ -373,31 +270,29 @@ public class RootConnection extends RootService { * * @param packageName the package name of the overlay to disable and remove */ - @Override - public void unregisterFabricatedOverlay(String packageName) throws RemoteException { + @Suppress("DEPRECATION") + @Throws(RemoteException::class) + override fun unregisterFabricatedOverlay(packageName: String) { try { - OverlayIdentifier overlay = generateOverlayIdentifier(packageName); - if (overlay == null) { - return; - } + val overlay = generateOverlayIdentifier(packageName) ?: return - Object omtbInstance = omtbClass.newInstance(); + val omtbInstance = omtbClass!!.newInstance() - omtbClass.getMethod( - "unregisterFabricatedOverlay", - oiClass + omtbClass!!.getMethod( + "unregisterFabricatedOverlay", + oiClass ).invoke( - omtbInstance, - overlay - ); + omtbInstance, + overlay + ) - Object omtInstance = omtbClass.getMethod( - "build" - ).invoke(omtbInstance); + val omtInstance = omtbClass!!.getMethod( + "build" + ).invoke(omtbInstance) - commit(omtInstance); - } catch (Exception e) { - Log.e(TAG, "unregisterFabricatedOverlay: ", e); + commit(omtInstance) + } catch (e: Exception) { + Log.e(TAG, "unregisterFabricatedOverlay: ", e) } } @@ -405,105 +300,232 @@ public class RootConnection extends RootService { * Change the priority of the given overlay to the highest priority relative to * the other overlays with the same target and user. */ - @Override - public boolean setHighestPriority(String packageName) throws RemoteException { - return (boolean) getOMS().setHighestPriority(packageName, currentUserId); + @Throws(RemoteException::class) + override fun setHighestPriority(packageName: String): Boolean { + return oMS!!.setHighestPriority( + packageName, + currentUserId + ) } /** * Change the priority of the given overlay to the lowest priority relative to * the other overlays with the same target and user. */ - @Override - public boolean setLowestPriority(String packageName) throws RemoteException { - return (boolean) getOMS().setLowestPriority(packageName, currentUserId); - } - - @Override - public OverlayIdentifier generateOverlayIdentifier(String packageName) throws RemoteException { - return generateOverlayIdentifier(packageName, FABRICATED_OVERLAY_SOURCE_PACKAGE); + @Throws(RemoteException::class) + override fun setLowestPriority(packageName: String): Boolean { + return oMS!!.setLowestPriority( + packageName, + currentUserId + ) } - @Override - public void invalidateCachesForOverlay(String packageName) throws RemoteException { - getOMS().invalidateCachesForOverlay(packageName, currentUserId); + @Throws(RemoteException::class) + override fun generateOverlayIdentifier(packageName: String): OverlayIdentifier? { + return generateOverlayIdentifier(packageName, FABRICATED_OVERLAY_SOURCE_PACKAGE) } - private static OverlayIdentifier generateOverlayIdentifier(String packageName, String sourcePackage) { - try { - return (OverlayIdentifier) oiClass.getConstructor( - String.class, - String.class - ).newInstance( - sourcePackage, - packageName - ); - } catch (Exception e) { - Log.e(TAG, "generateOverlayIdentifier: ", e); - return null; - } + @Throws(RemoteException::class) + override fun invalidateCachesForOverlay(packageName: String) { + oMS!!.invalidateCachesForOverlay(packageName, currentUserId) } - private void switchOverlay(String packageName, boolean enable) { + private fun switchOverlay(packageName: String, enable: Boolean) { try { - getOMS().setEnabled(packageName, enable, currentUserId); - } catch (Exception e) { - e.printStackTrace(); + oMS!!.setEnabled(packageName, enable, currentUserId) + } catch (e: Exception) { + e.printStackTrace() } } - private void switchOverlayWithIdentifier(OverlayIdentifier identifier, boolean enable) { + @Suppress("DEPRECATION") + private fun switchOverlayWithIdentifier(identifier: OverlayIdentifier?, enable: Boolean) { try { - Object omtbInstance = omtbClass.newInstance(); + val omtbInstance = omtbClass!!.newInstance() - omtbClass.getMethod( - "setEnabled", - oiClass, - boolean.class, - int.class + omtbClass!!.getMethod( + "setEnabled", + oiClass, + Boolean::class.javaPrimitiveType, + Int::class.javaPrimitiveType ).invoke( - omtbInstance, - identifier, - enable, - currentUserId - ); - - Object omtInstance = omtbClass.getMethod( - "build" - ).invoke(omtbInstance); - - commit(omtInstance); - } catch (Exception e) { - Log.e(TAG, "switchOverlayWithIdentifier: ", e); + omtbInstance, + identifier, + enable, + currentUserId + ) + + val omtInstance = omtbClass!!.getMethod( + "build" + ).invoke(omtbInstance) + + commit(omtInstance) + } catch (e: Exception) { + Log.e(TAG, "switchOverlayWithIdentifier: ", e) } } /** * Uninstall any overlay updates for the given package name. */ - @Override - public void uninstallOverlayUpdates(String packageName) { - runCommand(Collections.singletonList("pm uninstall " + packageName)); + override fun uninstallOverlayUpdates(packageName: String) { + runCommand(listOf("pm uninstall $packageName")) } /** * Restart systemui immediately. */ - @Override - public void restartSystemUI() throws RemoteException { - runCommand(Collections.singletonList("killall com.android.systemui")); + @Throws(RemoteException::class) + override fun restartSystemUI() { + runCommand(listOf("killall com.android.systemui")) } /** * Run list of commands as root. */ - @Override - public String[] runCommand(List command) { - return Shell.cmd(command.toArray(new String[0])).exec().getOut().toArray(new String[0]); + override fun runCommand(command: List): Array { + return Shell.cmd(*command.toTypedArray()).exec().out.toTypedArray() } - private void commit(Object transaction) throws Exception { - getOMS().commit((OverlayManagerTransaction) transaction); + @SuppressLint("NewApi") + @Throws(Exception::class) + private fun commit(transaction: Any?) { + oMS!!.commit(transaction as OverlayManagerTransaction?) + } + + @SuppressLint("PrivateApi", "NewApi") + companion object { + private val TAG: String = RootConnectionImpl::class.java.simpleName + private val currentUser: UserHandle + private val currentUserId: Int + private var mOMS: IOverlayManager? = null + private var oiClass: Class<*>? = null + private var foClass: Class<*>? = null + private var fobClass: Class<*>? = null + private var omtbClass: Class<*>? = null + private var SystemUI_UID = -1 + private var mActivityManager: IActivityManager? = null + private val onSystemUIRestartedListener: MethodInterface? = null + + @SuppressLint("StaticFieldLeak", "RestrictedApi") + private val context: Context = Utils.getContext() + + init { + currentUser = getCurrentUser() + currentUserId = getCurrentUserId()!! + + if (mOMS == null) { + mOMS = + IOverlayManager.Stub.asInterface(SystemServiceHelper.getSystemService("overlay")) + } + + if (mActivityManager == null) { + mActivityManager = + IActivityManager.Stub.asInterface(SystemServiceHelper.getSystemService("activity")) + } + + try { + SystemUI_UID = context.packageManager.getPackageUid(SYSTEMUI_PACKAGE, 0) + } catch (e: PackageManager.NameNotFoundException) { + Log.e(TAG, "static: ", e) + } + + try { + if (oiClass == null) { + oiClass = Class.forName("android.content.om.OverlayIdentifier") + } + } catch (e: ClassNotFoundException) { + Log.e(TAG, "static: ", e) + } + try { + if (foClass == null) { + foClass = Class.forName("android.content.om.FabricatedOverlay") + } + } catch (e: ClassNotFoundException) { + Log.e(TAG, "static: ", e) + } + try { + if (fobClass == null) { + fobClass = Class.forName("android.content.om.FabricatedOverlay\$Builder") + } + } catch (e: ClassNotFoundException) { + Log.e(TAG, "static: ", e) + } + try { + if (omtbClass == null) { + omtbClass = + Class.forName("android.content.om.OverlayManagerTransaction\$Builder") + } + } catch (e: ClassNotFoundException) { + Log.e(TAG, "static: ", e) + } + } + + private fun getCurrentUser(): UserHandle { + return Process.myUserHandle() + } + + private fun getCurrentUserId(): Int? { + return try { + UserHandle::class.java.getMethod("getIdentifier") + .invoke(currentUser) as Int + } catch (exception: NoSuchMethodException) { + 0 + } catch (exception: IllegalAccessException) { + 0 + } catch (exception: InvocationTargetException) { + 0 + } + } + + private val oMS: IOverlayManager? + get() { + if (mOMS == null) { + mOMS = + IOverlayManager.Stub.asInterface(SystemServiceHelper.getSystemService("overlay")) + } + return mOMS + } + + private val aM: IActivityManager? + get() { + if (mActivityManager == null) { + mActivityManager = + IActivityManager.Stub.asInterface(SystemServiceHelper.getSystemService("activity")) + } + return mActivityManager + } + + private fun getSystemUiUID(): Int { + if (SystemUI_UID == -1) { + try { + SystemUI_UID = context.packageManager.getPackageUid(SYSTEMUI_PACKAGE, 0) + } catch (e: PackageManager.NameNotFoundException) { + // It's impossible to get here, but just in case + Log.e(TAG, "getSystemUI_UID: ", e) + } + } + return SystemUI_UID + } + + @Suppress("SameParameterValue") + private fun generateOverlayIdentifier( + packageName: String, + sourcePackage: String + ): OverlayIdentifier? { + try { + return oiClass!!.getConstructor( + String::class.java, + String::class.java + ).newInstance( + sourcePackage, + packageName + ) as OverlayIdentifier + } catch (e: Exception) { + Log.e(TAG, "generateOverlayIdentifier: ", e) + return null + } + } } } } diff --git a/app/src/main/java/com/drdisagree/colorblendr/service/ScheduledJobService.kt b/app/src/main/java/com/drdisagree/colorblendr/service/ScheduledJobService.kt index 1223ce1..4c49770 100644 --- a/app/src/main/java/com/drdisagree/colorblendr/service/ScheduledJobService.kt +++ b/app/src/main/java/com/drdisagree/colorblendr/service/ScheduledJobService.kt @@ -1,36 +1,35 @@ -package com.drdisagree.colorblendr.service; +package com.drdisagree.colorblendr.service -import android.app.job.JobParameters; -import android.app.job.JobService; -import android.content.Intent; -import android.util.Log; +import android.app.job.JobParameters +import android.app.job.JobService +import android.content.Intent +import android.util.Log +import androidx.work.Configuration -import androidx.work.Configuration; +class ScheduledJobService internal constructor() : JobService() { -public class ScheduledJobService extends JobService { - - private static final String TAG = ScheduledJobService.class.getSimpleName(); - - ScheduledJobService() { - @SuppressWarnings("all") Configuration.Builder builder = new Configuration.Builder(); - builder.setJobSchedulerJobIdRange(0, 1000); + init { + val builder: Configuration.Builder = Configuration.Builder() + builder.setJobSchedulerJobIdRange(0, 1000) } - @Override - public boolean onStartJob(JobParameters jobParameters) { - ServiceLauncher serviceLauncher = new ServiceLauncher(); - serviceLauncher.launchService(this); + override fun onStartJob(jobParameters: JobParameters): Boolean { + val serviceLauncher = ServiceLauncher() + serviceLauncher.launchService(this) - return false; + return false } - @Override - public boolean onStopJob(JobParameters jobParameters) { - Log.i(TAG, "Stopping job..."); + override fun onStopJob(jobParameters: JobParameters): Boolean { + Log.i(TAG, "Stopping job...") - Intent broadcastIntent = new Intent(getApplicationContext().getPackageName()); - sendBroadcast(broadcastIntent); + val broadcastIntent = Intent(applicationContext.packageName) + sendBroadcast(broadcastIntent) + + return false + } - return false; + companion object { + private val TAG: String = ScheduledJobService::class.java.simpleName } } \ No newline at end of file diff --git a/app/src/main/java/com/drdisagree/colorblendr/service/ServiceLauncher.kt b/app/src/main/java/com/drdisagree/colorblendr/service/ServiceLauncher.kt index d6fde72..689ca6e 100644 --- a/app/src/main/java/com/drdisagree/colorblendr/service/ServiceLauncher.kt +++ b/app/src/main/java/com/drdisagree/colorblendr/service/ServiceLauncher.kt @@ -1,30 +1,34 @@ -package com.drdisagree.colorblendr.service; +package com.drdisagree.colorblendr.service -import android.content.Context; -import android.content.Intent; -import android.util.Log; +import android.content.Context +import android.content.Intent +import android.util.Log -public class ServiceLauncher { - - private static final String TAG = ServiceLauncher.class.getSimpleName(); - private static Intent serviceIntent = null; - - private void setServiceIntent(Context context) { +class ServiceLauncher { + private fun setServiceIntent(context: Context) { if (serviceIntent == null) { - serviceIntent = new Intent(context, AutoStartService.class); + serviceIntent = Intent( + context, + AutoStartService::class.java + ) } } - public void launchService(Context context) { + fun launchService(context: Context?) { if (context == null) { - return; + return } - setServiceIntent(context); + setServiceIntent(context) - if (AutoStartService.isServiceNotRunning()) { - Log.d(TAG, "launchService: Service is starting..."); - context.startForegroundService(serviceIntent); + if (AutoStartService.isServiceNotRunning) { + Log.d(TAG, "launchService: Service is starting...") + context.startForegroundService(serviceIntent) } } + + companion object { + private val TAG: String = ServiceLauncher::class.java.simpleName + private var serviceIntent: Intent? = null + } } diff --git a/app/src/main/java/com/drdisagree/colorblendr/service/ShizukuConnection.kt b/app/src/main/java/com/drdisagree/colorblendr/service/ShizukuConnection.kt index 1e068af..a03186f 100644 --- a/app/src/main/java/com/drdisagree/colorblendr/service/ShizukuConnection.kt +++ b/app/src/main/java/com/drdisagree/colorblendr/service/ShizukuConnection.kt @@ -1,86 +1,84 @@ -package com.drdisagree.colorblendr.service; - -import static com.drdisagree.colorblendr.common.Const.THEME_CUSTOMIZATION_OVERLAY_PACKAGES; - -import android.content.Context; -import android.os.Build; -import android.util.Log; - -import androidx.annotation.Keep; -import androidx.annotation.NonNull; - -import com.drdisagree.colorblendr.extension.ThemeOverlayPackage; -import com.topjohnwu.superuser.Shell; - -import org.json.JSONException; -import org.json.JSONObject; - -public class ShizukuConnection extends IShizukuConnection.Stub { - - private static final String TAG = ShizukuConnection.class.getSimpleName(); - - public ShizukuConnection() { - Log.i(TAG, "Constructed with no arguments"); +package com.drdisagree.colorblendr.service + +import android.content.Context +import android.os.Build +import android.util.Log +import androidx.annotation.Keep +import com.drdisagree.colorblendr.common.Const.THEME_CUSTOMIZATION_OVERLAY_PACKAGES +import com.drdisagree.colorblendr.extension.ThemeOverlayPackage +import com.topjohnwu.superuser.Shell +import org.json.JSONException +import org.json.JSONObject +import kotlin.system.exitProcess + +class ShizukuConnection : IShizukuConnection.Stub { + constructor() { + Log.i(TAG, "Constructed with no arguments") } @Keep - public ShizukuConnection(Context context) { - Log.i(TAG, "Constructed with context: " + context.toString()); + constructor(context: Context) { + Log.i(TAG, "Constructed with context: $context") } - @Override - public void destroy() { - System.exit(0); + override fun destroy() { + exitProcess(0) } - @Override - public void exit() { - destroy(); + override fun exit() { + destroy() } - @Override - public void applyFabricatedColors(String jsonString) { - final String mCommand = "settings put secure " + THEME_CUSTOMIZATION_OVERLAY_PACKAGES + " '" + jsonString + "'"; - Shell.cmd(mCommand).exec(); + override fun applyFabricatedColors(jsonString: String) { + val mCommand = + "settings put secure $THEME_CUSTOMIZATION_OVERLAY_PACKAGES '$jsonString'" + Shell.cmd(mCommand).exec() } - @Override - public void removeFabricatedColors() { + override fun removeFabricatedColors() { try { - applyFabricatedColors(getOriginalSettings().toString()); - } catch (Exception e) { - Log.e(TAG, "removeFabricatedColors: ", e); + applyFabricatedColors(originalSettings.toString()) + } catch (e: Exception) { + Log.e(TAG, "removeFabricatedColors: ", e) } } - @Override - public String getCurrentSettings() { - final String mCommand = "settings get secure " + THEME_CUSTOMIZATION_OVERLAY_PACKAGES; - return Shell.cmd(mCommand).exec().getOut().get(0); + override fun getCurrentSettings(): String { + val mCommand = "settings get secure $THEME_CUSTOMIZATION_OVERLAY_PACKAGES" + return Shell.cmd(mCommand).exec().out[0] } - private @NonNull JSONObject getOriginalSettings() throws JSONException { - String currentSettings = getCurrentSettings(); - JSONObject jsonObject = new JSONObject(currentSettings); + @get:Throws(JSONException::class) + private val originalSettings: JSONObject + get() { + val currentSettings = currentSettings + val jsonObject = JSONObject(currentSettings) - String[] keysToRemove = new String[]{ + val keysToRemove = arrayOf( ThemeOverlayPackage.THEME_STYLE, ThemeOverlayPackage.COLOR_SOURCE, ThemeOverlayPackage.SYSTEM_PALETTE - }; + ) - for (String key : keysToRemove) { - jsonObject.remove(key); - } + for (key in keysToRemove) { + jsonObject.remove(key) + } - if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.S_V2) { - jsonObject.remove(ThemeOverlayPackage.ACCENT_COLOR); - } + if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.S_V2) { + jsonObject.remove(ThemeOverlayPackage.ACCENT_COLOR) + } + + jsonObject.putOpt(ThemeOverlayPackage.COLOR_BOTH, "0") + jsonObject.putOpt(ThemeOverlayPackage.COLOR_SOURCE, "home_wallpaper") + jsonObject.putOpt( + ThemeOverlayPackage.APPLIED_TIMESTAMP, + System.currentTimeMillis() + ) - jsonObject.putOpt(ThemeOverlayPackage.COLOR_BOTH, "0"); - jsonObject.putOpt(ThemeOverlayPackage.COLOR_SOURCE, "home_wallpaper"); - jsonObject.putOpt(ThemeOverlayPackage.APPLIED_TIMESTAMP, System.currentTimeMillis()); + return jsonObject + } - return jsonObject; + companion object { + private val TAG: String = ShizukuConnection::class.java.simpleName } } diff --git a/app/src/main/java/com/drdisagree/colorblendr/ui/activities/MainActivity.kt b/app/src/main/java/com/drdisagree/colorblendr/ui/activities/MainActivity.kt index cd8c835..b2e9771 100644 --- a/app/src/main/java/com/drdisagree/colorblendr/ui/activities/MainActivity.kt +++ b/app/src/main/java/com/drdisagree/colorblendr/ui/activities/MainActivity.kt @@ -1,130 +1,124 @@ -package com.drdisagree.colorblendr.ui.activities; - -import static com.drdisagree.colorblendr.common.Const.FIRST_RUN; - -import android.content.res.Configuration; -import android.os.Bundle; -import android.view.MenuItem; -import android.view.ViewGroup; -import android.view.Window; - -import androidx.annotation.NonNull; -import androidx.appcompat.app.AppCompatActivity; -import androidx.core.graphics.Insets; -import androidx.core.view.ViewCompat; -import androidx.core.view.WindowCompat; -import androidx.core.view.WindowInsetsCompat; -import androidx.fragment.app.Fragment; -import androidx.fragment.app.FragmentManager; -import androidx.fragment.app.FragmentTransaction; - -import com.drdisagree.colorblendr.R; -import com.drdisagree.colorblendr.common.Const; -import com.drdisagree.colorblendr.config.RPrefs; -import com.drdisagree.colorblendr.databinding.ActivityMainBinding; -import com.drdisagree.colorblendr.service.RestartBroadcastReceiver; -import com.drdisagree.colorblendr.ui.fragments.HomeFragment; -import com.drdisagree.colorblendr.ui.fragments.OnboardingFragment; -import com.google.android.material.appbar.AppBarLayout; -import com.google.android.material.shape.MaterialShapeDrawable; - -import java.util.Objects; - -public class MainActivity extends AppCompatActivity { - - private ActivityMainBinding binding; - private static FragmentManager fragmentManager; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - binding = ActivityMainBinding.inflate(getLayoutInflater()); - setContentView(binding.getRoot()); - - setupEdgeToEdge(); - - fragmentManager = getSupportFragmentManager(); +package com.drdisagree.colorblendr.ui.activities + +import android.content.res.Configuration +import android.os.Bundle +import android.view.MenuItem +import android.view.View +import android.view.ViewGroup +import android.view.ViewGroup.MarginLayoutParams +import androidx.appcompat.app.AppCompatActivity +import androidx.core.graphics.Insets +import androidx.core.view.ViewCompat +import androidx.core.view.WindowCompat +import androidx.core.view.WindowInsetsCompat +import androidx.fragment.app.Fragment +import androidx.fragment.app.FragmentManager +import androidx.fragment.app.FragmentTransaction +import com.drdisagree.colorblendr.R +import com.drdisagree.colorblendr.common.Const +import com.drdisagree.colorblendr.common.Const.FIRST_RUN +import com.drdisagree.colorblendr.common.Const.workingMethod +import com.drdisagree.colorblendr.config.RPrefs.getBoolean +import com.drdisagree.colorblendr.databinding.ActivityMainBinding +import com.drdisagree.colorblendr.service.RestartBroadcastReceiver.Companion.scheduleJob +import com.drdisagree.colorblendr.ui.fragments.HomeFragment +import com.drdisagree.colorblendr.ui.fragments.OnboardingFragment +import com.google.android.material.appbar.AppBarLayout +import com.google.android.material.shape.MaterialShapeDrawable + +class MainActivity : AppCompatActivity() { + + private lateinit var binding: ActivityMainBinding + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + binding = ActivityMainBinding.inflate(layoutInflater) + setContentView(binding.getRoot()) + + setupEdgeToEdge() + + myFragmentManager = supportFragmentManager if (savedInstanceState == null) { - if (RPrefs.getBoolean(FIRST_RUN, true) || - Const.getWorkingMethod() == Const.WORK_METHOD.NULL || - !getIntent().getBooleanExtra("success", false) + if (getBoolean(FIRST_RUN, true) || workingMethod == Const.WorkMethod.NULL || + !intent.getBooleanExtra("success", false) ) { - replaceFragment(new OnboardingFragment(), false); + replaceFragment(OnboardingFragment(), false) } else { - replaceFragment(new HomeFragment(), false); + replaceFragment(HomeFragment(), false) } } } - private void setupEdgeToEdge() { + private fun setupEdgeToEdge() { try { - ((AppBarLayout) findViewById(R.id.appBarLayout)).setStatusBarForeground(MaterialShapeDrawable.createWithElevationOverlay(getApplicationContext())); - } catch (Exception ignored) { + (findViewById(R.id.appBarLayout) as AppBarLayout).statusBarForeground = + MaterialShapeDrawable.createWithElevationOverlay(applicationContext) + } catch (ignored: Exception) { } - Window window = getWindow(); - WindowCompat.setDecorFitsSystemWindows(window, false); + WindowCompat.setDecorFitsSystemWindows(window, false) - if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) { - ViewGroup viewGroup = getWindow().getDecorView().findViewById(android.R.id.content); - ViewCompat.setOnApplyWindowInsetsListener(viewGroup, (v, windowInsets) -> { - Insets insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars()); - - ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) v.getLayoutParams(); + if (getResources().configuration.orientation == Configuration.ORIENTATION_LANDSCAPE) { + val viewGroup: ViewGroup = window.decorView.findViewById(android.R.id.content) + ViewCompat.setOnApplyWindowInsetsListener(viewGroup) { v: View, windowInsets: WindowInsetsCompat -> + val insets: Insets = + windowInsets.getInsets(WindowInsetsCompat.Type.systemBars()) + val params: MarginLayoutParams = v.layoutParams as MarginLayoutParams v.setPadding( - params.leftMargin + insets.left, - 0, - params.rightMargin + insets.right, - 0 - ); - params.topMargin = 0; - params.bottomMargin = 0; - v.setLayoutParams(params); - - return windowInsets; - }); + params.leftMargin + insets.left, + 0, + params.rightMargin + insets.right, + 0 + ) + params.topMargin = 0 + params.bottomMargin = 0 + v.setLayoutParams(params) + windowInsets + } + } + } + + override fun onOptionsItemSelected(item: MenuItem): Boolean { + if (item.itemId == android.R.id.home) { + onBackPressedDispatcher.onBackPressed() + return true } + return super.onOptionsItemSelected(item) + } + + override fun onResume() { + super.onResume() + scheduleJob(applicationContext) } - public static void replaceFragment(Fragment fragment, boolean animate) { - String tag = fragment.getClass().getSimpleName(); - FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction(); + companion object { + private lateinit var myFragmentManager: FragmentManager - if (animate) { - fragmentTransaction.setCustomAnimations( + fun replaceFragment(fragment: Fragment, animate: Boolean) { + val tag: String = fragment.javaClass.getSimpleName() + val fragmentTransaction: FragmentTransaction = myFragmentManager.beginTransaction() + + if (animate) { + fragmentTransaction.setCustomAnimations( R.anim.slide_in_right, R.anim.slide_out_left, R.anim.slide_in_left, R.anim.slide_out_right - ); - } - fragmentTransaction.replace( + ) + } + fragmentTransaction.replace( R.id.fragmentContainer, fragment - ); + ) - if (Objects.equals(tag, HomeFragment.class.getSimpleName())) { - fragmentManager.popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE); - } else if (!Objects.equals(tag, OnboardingFragment.class.getSimpleName())) { - fragmentTransaction.addToBackStack(tag); - } - - fragmentTransaction.commit(); - } + if (tag == HomeFragment::class.java.simpleName) { + myFragmentManager.popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE) + } else if (tag != OnboardingFragment::class.java.simpleName) { + fragmentTransaction.addToBackStack(tag) + } - @Override - public boolean onOptionsItemSelected(@NonNull MenuItem item) { - if (item.getItemId() == android.R.id.home) { - getOnBackPressedDispatcher().onBackPressed(); - return true; + fragmentTransaction.commit() } - return super.onOptionsItemSelected(item); - } - - @Override - protected void onResume() { - super.onResume(); - RestartBroadcastReceiver.scheduleJob(getApplicationContext()); } } \ No newline at end of file diff --git a/app/src/main/java/com/drdisagree/colorblendr/ui/activities/SplashActivity.kt b/app/src/main/java/com/drdisagree/colorblendr/ui/activities/SplashActivity.kt index 4ba6560..a222adf 100644 --- a/app/src/main/java/com/drdisagree/colorblendr/ui/activities/SplashActivity.kt +++ b/app/src/main/java/com/drdisagree/colorblendr/ui/activities/SplashActivity.kt @@ -1,97 +1,99 @@ -package com.drdisagree.colorblendr.ui.activities; +package com.drdisagree.colorblendr.ui.activities -import static com.drdisagree.colorblendr.common.Const.FIRST_RUN; - -import android.annotation.SuppressLint; -import android.content.Intent; -import android.os.Bundle; - -import androidx.appcompat.app.AppCompatActivity; -import androidx.core.splashscreen.SplashScreen; - -import com.drdisagree.colorblendr.ColorBlendr; -import com.drdisagree.colorblendr.common.Const; -import com.drdisagree.colorblendr.config.RPrefs; -import com.drdisagree.colorblendr.extension.MethodInterface; -import com.drdisagree.colorblendr.provider.RootConnectionProvider; -import com.drdisagree.colorblendr.provider.ShizukuConnectionProvider; -import com.drdisagree.colorblendr.service.ShizukuConnection; -import com.drdisagree.colorblendr.utils.FabricatedUtil; -import com.drdisagree.colorblendr.utils.ShizukuUtil; -import com.drdisagree.colorblendr.utils.WallpaperColorUtil; -import com.google.android.material.color.DynamicColors; - -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.atomic.AtomicBoolean; +import android.annotation.SuppressLint +import android.content.Intent +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import androidx.core.splashscreen.SplashScreen +import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen +import com.drdisagree.colorblendr.ColorBlendr.Companion.appContext +import com.drdisagree.colorblendr.common.Const +import com.drdisagree.colorblendr.common.Const.FIRST_RUN +import com.drdisagree.colorblendr.common.Const.workingMethod +import com.drdisagree.colorblendr.config.RPrefs.getBoolean +import com.drdisagree.colorblendr.extension.MethodInterface +import com.drdisagree.colorblendr.provider.RootConnectionProvider.Companion.builder +import com.drdisagree.colorblendr.provider.ShizukuConnectionProvider +import com.drdisagree.colorblendr.service.ShizukuConnection +import com.drdisagree.colorblendr.utils.FabricatedUtil.getAndSaveSelectedFabricatedApps +import com.drdisagree.colorblendr.utils.ShizukuUtil.bindUserService +import com.drdisagree.colorblendr.utils.ShizukuUtil.getUserServiceArgs +import com.drdisagree.colorblendr.utils.ShizukuUtil.hasShizukuPermission +import com.drdisagree.colorblendr.utils.ShizukuUtil.isShizukuAvailable +import com.drdisagree.colorblendr.utils.WallpaperColorUtil.getAndSaveWallpaperColors +import com.google.android.material.color.DynamicColors +import java.util.concurrent.CountDownLatch +import java.util.concurrent.atomic.AtomicBoolean @SuppressLint("CustomSplashScreen") -public class SplashActivity extends AppCompatActivity { +class SplashActivity : AppCompatActivity() { + + private var keepShowing: Boolean = true - private boolean keepShowing = true; - private final Runnable runnable = () -> { - final AtomicBoolean success = new AtomicBoolean(false); - CountDownLatch countDownLatch = new CountDownLatch(1); + private val runnable: Runnable = Runnable { + val success = AtomicBoolean(false) + val countDownLatch = CountDownLatch(1) - if (!RPrefs.getBoolean(FIRST_RUN, true) && - Const.getWorkingMethod() != Const.WORK_METHOD.NULL + if (!getBoolean(FIRST_RUN, true) && + workingMethod != Const.WorkMethod.NULL ) { - if (Const.getWorkingMethod() == Const.WORK_METHOD.ROOT) { - RootConnectionProvider.builder(ColorBlendr.getAppContext()) - .runOnSuccess(new MethodInterface() { - @Override - public void run() { - WallpaperColorUtil.getAndSaveWallpaperColors(getApplicationContext()); - FabricatedUtil.getAndSaveSelectedFabricatedApps(getApplicationContext()); - success.set(true); - keepShowing = false; - countDownLatch.countDown(); - } - }) - .runOnFailure(new MethodInterface() { - @Override - public void run() { - success.set(false); - keepShowing = false; - countDownLatch.countDown(); - } - }) - .run(); - } else if (Const.getWorkingMethod() == Const.WORK_METHOD.SHIZUKU) { - if (ShizukuUtil.isShizukuAvailable() && ShizukuUtil.hasShizukuPermission(this)) { - ShizukuUtil.bindUserService( - ShizukuUtil.getUserServiceArgs(ShizukuConnection.class), - ShizukuConnectionProvider.serviceConnection - ); - success.set(true); + if (workingMethod == Const.WorkMethod.ROOT) { + builder(appContext) + .runOnSuccess(object : MethodInterface() { + override fun run() { + getAndSaveWallpaperColors(applicationContext) + getAndSaveSelectedFabricatedApps(applicationContext) + success.set(true) + keepShowing = false + countDownLatch.countDown() + } + }) + .runOnFailure(object : MethodInterface() { + override fun run() { + success.set(false) + keepShowing = false + countDownLatch.countDown() + } + }) + .run() + } else if (workingMethod == Const.WorkMethod.SHIZUKU) { + if (isShizukuAvailable && hasShizukuPermission(this)) { + bindUserService( + getUserServiceArgs(ShizukuConnection::class.java), + ShizukuConnectionProvider.serviceConnection + ) + success.set(true) } else { - success.set(false); + success.set(false) } - keepShowing = false; - countDownLatch.countDown(); + keepShowing = false + countDownLatch.countDown() } } else { - keepShowing = false; - countDownLatch.countDown(); + keepShowing = false + countDownLatch.countDown() } try { - countDownLatch.await(); - } catch (InterruptedException ignored) { + countDownLatch.await() + } catch (ignored: InterruptedException) { } - Intent intent = new Intent(SplashActivity.this, MainActivity.class); - intent.putExtra("success", success.get()); - startActivity(intent); - finish(); - }; + val intent = Intent( + this@SplashActivity, + MainActivity::class.java + ) + intent.putExtra("success", success.get()) + startActivity(intent) + finish() + } - @Override - protected void onCreate(Bundle savedInstanceState) { - SplashScreen splashScreen = SplashScreen.installSplashScreen(this); + override fun onCreate(savedInstanceState: Bundle?) { + val splashScreen: SplashScreen = installSplashScreen() - super.onCreate(savedInstanceState); - DynamicColors.applyToActivitiesIfAvailable(getApplication()); - splashScreen.setKeepOnScreenCondition(() -> keepShowing); + super.onCreate(savedInstanceState) + DynamicColors.applyToActivitiesIfAvailable(application) + splashScreen.setKeepOnScreenCondition { keepShowing } - new Thread(runnable).start(); + Thread(runnable).start() } } diff --git a/app/src/main/java/com/drdisagree/colorblendr/ui/adapters/AppListAdapter.kt b/app/src/main/java/com/drdisagree/colorblendr/ui/adapters/AppListAdapter.kt index 7a84a9d..d548b13 100644 --- a/app/src/main/java/com/drdisagree/colorblendr/ui/adapters/AppListAdapter.kt +++ b/app/src/main/java/com/drdisagree/colorblendr/ui/adapters/AppListAdapter.kt @@ -1,149 +1,144 @@ -package com.drdisagree.colorblendr.ui.adapters; - -import static com.drdisagree.colorblendr.common.Const.FABRICATED_OVERLAY_NAME_APPS; -import static com.drdisagree.colorblendr.common.Const.SHIZUKU_THEMING_ENABLED; -import static com.drdisagree.colorblendr.common.Const.THEMING_ENABLED; - -import android.content.Context; -import android.graphics.PorterDuff; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.ImageView; -import android.widget.TextView; - -import androidx.annotation.ColorInt; -import androidx.annotation.NonNull; -import androidx.recyclerview.widget.RecyclerView; - -import com.drdisagree.colorblendr.R; -import com.drdisagree.colorblendr.common.Const; -import com.drdisagree.colorblendr.config.RPrefs; -import com.drdisagree.colorblendr.ui.models.AppInfoModel; -import com.drdisagree.colorblendr.utils.ColorUtil; -import com.drdisagree.colorblendr.utils.OverlayManager; -import com.google.android.material.card.MaterialCardView; - -import java.util.HashMap; -import java.util.List; - -public class AppListAdapter extends RecyclerView.Adapter { - - private Context context; - private final List appList; - private final HashMap selectedApps = new HashMap<>(); - - public AppListAdapter(List appList) { - this.appList = appList; - - if (RPrefs.getBoolean(THEMING_ENABLED, false) || - RPrefs.getBoolean(SHIZUKU_THEMING_ENABLED, false) +package com.drdisagree.colorblendr.ui.adapters + +import android.content.Context +import android.graphics.PorterDuff +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.view.ViewGroup.MarginLayoutParams +import android.widget.ImageView +import android.widget.TextView +import androidx.annotation.ColorInt +import androidx.recyclerview.widget.RecyclerView +import com.drdisagree.colorblendr.R +import com.drdisagree.colorblendr.common.Const.FABRICATED_OVERLAY_NAME_APPS +import com.drdisagree.colorblendr.common.Const.SHIZUKU_THEMING_ENABLED +import com.drdisagree.colorblendr.common.Const.THEMING_ENABLED +import com.drdisagree.colorblendr.common.Const.saveSelectedFabricatedApps +import com.drdisagree.colorblendr.config.RPrefs.getBoolean +import com.drdisagree.colorblendr.ui.models.AppInfoModel +import com.drdisagree.colorblendr.utils.ColorUtil.getColorFromAttribute +import com.drdisagree.colorblendr.utils.OverlayManager.applyFabricatedColorsPerApp +import com.drdisagree.colorblendr.utils.OverlayManager.unregisterFabricatedOverlay +import com.google.android.material.card.MaterialCardView + +class AppListAdapter(private val appList: List) : + RecyclerView.Adapter() { + + private var context: Context? = null + private val selectedApps: HashMap = HashMap() + + init { + if (getBoolean(THEMING_ENABLED, false) || + getBoolean(SHIZUKU_THEMING_ENABLED, false) ) { - for (AppInfoModel appInfo : appList) { - if (appInfo.isSelected()) { - selectedApps.put(appInfo.packageName, appInfo.isSelected()); + for (appInfo: AppInfoModel in appList) { + if (appInfo.isSelected) { + selectedApps[appInfo.packageName] = true } } - Const.saveSelectedFabricatedApps(selectedApps); + saveSelectedFabricatedApps(selectedApps) } } - @NonNull - @Override - public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { - context = parent.getContext(); - View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.view_app_list, parent, false); - return new ViewHolder(view); + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { + context = parent.context + val view: View = + LayoutInflater.from(parent.context).inflate(R.layout.view_app_list, parent, false) + return ViewHolder(view) } - @Override - public void onBindViewHolder(ViewHolder holder, int position) { - AppInfoModel appInfo = appList.get(position); - holder.appIcon.setImageDrawable(appInfo.appIcon); - holder.appName.setText(appInfo.appName); - holder.packageName.setText(appInfo.packageName); + override fun onBindViewHolder(holder: ViewHolder, position: Int) { + val appInfo: AppInfoModel = appList[position] + holder.appIcon.setImageDrawable(appInfo.appIcon) + holder.appName.text = appInfo.appName + holder.packageName.text = appInfo.packageName - holder.itemView.setOnClickListener(v -> { - final boolean isSelected = appInfo.isSelected(); - setSelected(holder, !isSelected); - appInfo.setSelected(!isSelected); - - selectedApps.put(appInfo.packageName, !isSelected); - Const.saveSelectedFabricatedApps(selectedApps); + holder.itemView.setOnClickListener { + val isSelected: Boolean = appInfo.isSelected + setSelected(holder, !isSelected) + appInfo.isSelected = !isSelected + selectedApps[appInfo.packageName] = !isSelected + saveSelectedFabricatedApps(selectedApps) if (isSelected) { - OverlayManager.unregisterFabricatedOverlay(String.format(FABRICATED_OVERLAY_NAME_APPS, appInfo.packageName)); + unregisterFabricatedOverlay( + String.format( + FABRICATED_OVERLAY_NAME_APPS, + appInfo.packageName + ) + ) } else { - OverlayManager.applyFabricatedColorsPerApp(context, appInfo.packageName, null); + applyFabricatedColorsPerApp(context!!, appInfo.packageName, null) } - }); + } - setSelected(holder, appInfo.isSelected()); + setSelected(holder, appInfo.isSelected) } - @Override - public void onViewAttachedToWindow(@NonNull ViewHolder holder) { - super.onViewAttachedToWindow(holder); + override fun onViewAttachedToWindow(holder: ViewHolder) { + super.onViewAttachedToWindow(holder) - setSelected(holder, appList.get(holder.getBindingAdapterPosition()).isSelected()); + setSelected(holder, appList[holder.getBindingAdapterPosition()].isSelected) } - @Override - public int getItemCount() { - return appList.size(); + override fun getItemCount(): Int { + return appList.size } - public static class ViewHolder extends RecyclerView.ViewHolder { - - public MaterialCardView container; - public ImageView appIcon; - public TextView appName; - public TextView packageName; - public ImageView iconView; - - public ViewHolder(View view) { - super(view); - - container = view.findViewById(R.id.container); - appIcon = view.findViewById(R.id.app_icon); - appName = view.findViewById(R.id.title); - packageName = view.findViewById(R.id.summary); - iconView = view.findViewById(R.id.icon); - } + class ViewHolder(view: View) : RecyclerView.ViewHolder(view) { + var container: MaterialCardView = view.findViewById(R.id.container) + var appIcon: ImageView = view.findViewById(R.id.app_icon) + var appName: TextView = view.findViewById(R.id.title) + var packageName: TextView = view.findViewById(R.id.summary) + var iconView: ImageView = view.findViewById(R.id.icon) } - private void setSelected(ViewHolder holder, boolean isSelected) { - holder.iconView.setAlpha(isSelected ? 1.0f : 0.2f); - holder.iconView.setColorFilter(getIconColor(isSelected), PorterDuff.Mode.SRC_IN); - holder.iconView.setImageResource(isSelected ? R.drawable.ic_checked_filled : R.drawable.ic_checked_outline); - holder.container.setCardBackgroundColor(getCardBackgroundColor(isSelected)); - holder.container.setStrokeWidth(isSelected ? 0 : 2); - holder.appName.setTextColor(getTextColor(isSelected)); - holder.packageName.setTextColor(getTextColor(isSelected)); + private fun setSelected(holder: ViewHolder, isSelected: Boolean) { + holder.iconView.setAlpha(if (isSelected) 1.0f else 0.2f) + holder.iconView.setColorFilter(getIconColor(isSelected), PorterDuff.Mode.SRC_IN) + holder.iconView.setImageResource(if (isSelected) R.drawable.ic_checked_filled else R.drawable.ic_checked_outline) + holder.container.setCardBackgroundColor(getCardBackgroundColor(isSelected)) + holder.container.setStrokeWidth(if (isSelected) 0 else 2) + holder.appName.setTextColor(getTextColor(isSelected)) + holder.packageName.setTextColor(getTextColor(isSelected)) if (holder.getBindingAdapterPosition() == 0) { - ((ViewGroup.MarginLayoutParams) holder.container.getLayoutParams()).topMargin = (int) (72 * context.getResources().getDisplayMetrics().density); + (holder.container.layoutParams as MarginLayoutParams).topMargin = + (72 * context!!.resources.displayMetrics.density).toInt() } else { - ((ViewGroup.MarginLayoutParams) holder.container.getLayoutParams()).topMargin = 0; + (holder.container.layoutParams as MarginLayoutParams).topMargin = 0 } } - private @ColorInt int getCardBackgroundColor(boolean isSelected) { - return isSelected ? - ColorUtil.getColorFromAttribute(context, com.google.android.material.R.attr.colorPrimaryContainer) : - ColorUtil.getColorFromAttribute(context, com.google.android.material.R.attr.colorSurfaceContainer); + @ColorInt + private fun getCardBackgroundColor(isSelected: Boolean): Int { + return if (isSelected) getColorFromAttribute( + context!!, + com.google.android.material.R.attr.colorPrimaryContainer + ) else getColorFromAttribute( + context!!, com.google.android.material.R.attr.colorSurfaceContainer + ) } - private @ColorInt int getIconColor(boolean isSelected) { - return isSelected ? - ColorUtil.getColorFromAttribute(context, com.google.android.material.R.attr.colorPrimary) : - ColorUtil.getColorFromAttribute(context, com.google.android.material.R.attr.colorOnSurface); + @ColorInt + private fun getIconColor(isSelected: Boolean): Int { + return if (isSelected) getColorFromAttribute( + context!!, + com.google.android.material.R.attr.colorPrimary + ) else getColorFromAttribute( + context!!, com.google.android.material.R.attr.colorOnSurface + ) } - private @ColorInt int getTextColor(boolean isSelected) { - return isSelected ? - ColorUtil.getColorFromAttribute(context, com.google.android.material.R.attr.colorOnPrimaryContainer) : - ColorUtil.getColorFromAttribute(context, com.google.android.material.R.attr.colorOnSurface); + @ColorInt + private fun getTextColor(isSelected: Boolean): Int { + return if (isSelected) getColorFromAttribute( + context!!, + com.google.android.material.R.attr.colorOnPrimaryContainer + ) else getColorFromAttribute( + context!!, com.google.android.material.R.attr.colorOnSurface + ) } } diff --git a/app/src/main/java/com/drdisagree/colorblendr/ui/adapters/FragmentAdapter.kt b/app/src/main/java/com/drdisagree/colorblendr/ui/adapters/FragmentAdapter.kt index 562eb00..e90bdc2 100644 --- a/app/src/main/java/com/drdisagree/colorblendr/ui/adapters/FragmentAdapter.kt +++ b/app/src/main/java/com/drdisagree/colorblendr/ui/adapters/FragmentAdapter.kt @@ -1,33 +1,21 @@ -package com.drdisagree.colorblendr.ui.adapters; +package com.drdisagree.colorblendr.ui.adapters -import androidx.annotation.NonNull; -import androidx.fragment.app.Fragment; -import androidx.fragment.app.FragmentActivity; -import androidx.viewpager2.adapter.FragmentStateAdapter; +import androidx.fragment.app.Fragment +import androidx.fragment.app.FragmentActivity +import androidx.viewpager2.adapter.FragmentStateAdapter -import java.util.List; +class FragmentAdapter(fragmentActivity: FragmentActivity, private val fragments: List) : + FragmentStateAdapter(fragmentActivity) { -public class FragmentAdapter extends FragmentStateAdapter { - - private final List fragments; - - public FragmentAdapter(FragmentActivity fragmentActivity, List fragments) { - super(fragmentActivity); - this.fragments = fragments; - } - - @NonNull - @Override - public Fragment createFragment(int position) { - if (position >= 0 && position < fragments.size()) { - return fragments.get(position); + override fun createFragment(position: Int): Fragment { + if (position >= 0 && position < fragments.size) { + return fragments[position] } else { - throw new IndexOutOfBoundsException("Invalid fragment position: " + position); + throw IndexOutOfBoundsException("Invalid fragment position: $position") } } - @Override - public int getItemCount() { - return fragments.size(); + override fun getItemCount(): Int { + return fragments.size } } diff --git a/app/src/main/java/com/drdisagree/colorblendr/ui/adapters/OnboardingAdapter.kt b/app/src/main/java/com/drdisagree/colorblendr/ui/adapters/OnboardingAdapter.kt index f0dbfaf..e574f9a 100644 --- a/app/src/main/java/com/drdisagree/colorblendr/ui/adapters/OnboardingAdapter.kt +++ b/app/src/main/java/com/drdisagree/colorblendr/ui/adapters/OnboardingAdapter.kt @@ -1,34 +1,24 @@ -package com.drdisagree.colorblendr.ui.adapters; +package com.drdisagree.colorblendr.ui.adapters -import androidx.annotation.NonNull; -import androidx.fragment.app.Fragment; -import androidx.fragment.app.FragmentManager; -import androidx.lifecycle.Lifecycle; -import androidx.viewpager2.adapter.FragmentStateAdapter; +import androidx.fragment.app.Fragment +import androidx.fragment.app.FragmentManager +import androidx.lifecycle.Lifecycle +import androidx.viewpager2.adapter.FragmentStateAdapter -import java.util.ArrayList; +class OnboardingAdapter(fragmentManager: FragmentManager, lifecycle: Lifecycle) : + FragmentStateAdapter(fragmentManager, lifecycle) { -public class OnboardingAdapter extends FragmentStateAdapter { + private val fragmentList = ArrayList() - private final ArrayList fragmentList = new ArrayList<>(); - - public OnboardingAdapter(@NonNull FragmentManager fragmentManager, @NonNull Lifecycle lifecycle) { - super(fragmentManager, lifecycle); - } - - - @NonNull - @Override - public Fragment createFragment(int position) { - return fragmentList.get(position); + override fun createFragment(position: Int): Fragment { + return fragmentList[position] } - public void addFragment(Fragment fragment) { - fragmentList.add(fragment); + fun addFragment(fragment: Fragment) { + fragmentList.add(fragment) } - @Override - public int getItemCount() { - return fragmentList.size(); + override fun getItemCount(): Int { + return fragmentList.size } } \ No newline at end of file diff --git a/app/src/main/java/com/drdisagree/colorblendr/ui/fragments/AboutFragment.kt b/app/src/main/java/com/drdisagree/colorblendr/ui/fragments/AboutFragment.kt index 680e468..40ed815 100644 --- a/app/src/main/java/com/drdisagree/colorblendr/ui/fragments/AboutFragment.kt +++ b/app/src/main/java/com/drdisagree/colorblendr/ui/fragments/AboutFragment.kt @@ -1,56 +1,105 @@ -package com.drdisagree.colorblendr.ui.fragments; +package com.drdisagree.colorblendr.ui.fragments -import android.content.Intent; -import android.content.pm.PackageManager; -import android.net.Uri; -import android.os.Bundle; -import android.view.LayoutInflater; -import android.view.MenuItem; -import android.view.View; -import android.view.ViewGroup; +import android.content.Intent +import android.content.pm.PackageManager +import android.net.Uri +import android.os.Bundle +import android.view.LayoutInflater +import android.view.MenuItem +import android.view.View +import android.view.ViewGroup +import androidx.fragment.app.Fragment +import com.drdisagree.colorblendr.BuildConfig +import com.drdisagree.colorblendr.R +import com.drdisagree.colorblendr.databinding.FragmentAboutBinding +import com.drdisagree.colorblendr.utils.MiscUtil.setToolbarTitle -import androidx.annotation.NonNull; -import androidx.fragment.app.Fragment; +class AboutFragment : Fragment() { -import com.drdisagree.colorblendr.BuildConfig; -import com.drdisagree.colorblendr.R; -import com.drdisagree.colorblendr.databinding.FragmentAboutBinding; -import com.drdisagree.colorblendr.utils.MiscUtil; + private lateinit var binding: FragmentAboutBinding -public class AboutFragment extends Fragment { + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle? + ): View { + binding = FragmentAboutBinding.inflate(inflater, container, false) - private FragmentAboutBinding binding; - - @Override - public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - binding = FragmentAboutBinding.inflate(inflater, container, false); - - MiscUtil.setToolbarTitle(requireContext(), R.string.about_this_app_title, true, binding.header.toolbar); + setToolbarTitle( + requireContext(), + R.string.about_this_app_title, + true, + binding.header.toolbar + ) try { - binding.appIcon.setImageDrawable(requireContext().getPackageManager().getApplicationIcon(requireContext().getPackageName())); - } catch (PackageManager.NameNotFoundException ignored) { + binding.appIcon.setImageDrawable( + requireContext().packageManager.getApplicationIcon( + requireContext().packageName + ) + ) + } catch (ignored: PackageManager.NameNotFoundException) { // Unlikely to happen - binding.appIcon.setImageResource(R.mipmap.ic_launcher); + binding.appIcon.setImageResource(R.mipmap.ic_launcher) } - binding.versionCode.setText(getString(R.string.version_codes, BuildConfig.VERSION_NAME, BuildConfig.VERSION_CODE)); + binding.versionCode.text = getString( + R.string.version_codes, + BuildConfig.VERSION_NAME, + BuildConfig.VERSION_CODE + ) - binding.btnNews.setOnClickListener(v -> startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("https://t.me/IconifyOfficial")))); - binding.btnSupport.setOnClickListener(v -> startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("https://t.me/IconifyDiscussion")))); - binding.btnGithub.setOnClickListener(v -> startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("https://github.com/Mahmud0808/ColorBlendr")))); + binding.btnNews.setOnClickListener { + startActivity( + Intent( + Intent.ACTION_VIEW, + Uri.parse("https://t.me/IconifyOfficial") + ) + ) + } + binding.btnSupport.setOnClickListener { + startActivity( + Intent( + Intent.ACTION_VIEW, + Uri.parse("https://t.me/IconifyDiscussion") + ) + ) + } + binding.btnGithub.setOnClickListener { + startActivity( + Intent( + Intent.ACTION_VIEW, + Uri.parse("https://github.com/Mahmud0808/ColorBlendr") + ) + ) + } - binding.developer.setOnClickListener(v -> startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("https://github.com/Mahmud0808")))); - binding.buymeacoffee.setOnClickListener(v -> startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("https://buymeacoffee.com/drdisagree")))); + binding.developer.setOnClickListener { + startActivity( + Intent( + Intent.ACTION_VIEW, + Uri.parse("https://github.com/Mahmud0808") + ) + ) + } + binding.buymeacoffee.setOnClickListener { + startActivity( + Intent( + Intent.ACTION_VIEW, + Uri.parse("https://buymeacoffee.com/drdisagree") + ) + ) + } - return binding.getRoot(); + return binding.root } - @Override - public boolean onOptionsItemSelected(@NonNull MenuItem item) { - if (item.getItemId() == android.R.id.home) { - getParentFragmentManager().popBackStackImmediate(); - return true; + @Suppress("DEPRECATION") + @Deprecated("Deprecated in Java") + override fun onOptionsItemSelected(item: MenuItem): Boolean { + if (item.itemId == android.R.id.home) { + parentFragmentManager.popBackStackImmediate() + return true } - return super.onOptionsItemSelected(item); + return super.onOptionsItemSelected(item) } } \ No newline at end of file diff --git a/app/src/main/java/com/drdisagree/colorblendr/ui/fragments/ColorPaletteFragment.kt b/app/src/main/java/com/drdisagree/colorblendr/ui/fragments/ColorPaletteFragment.kt index 86d00be..3f0c8c0 100644 --- a/app/src/main/java/com/drdisagree/colorblendr/ui/fragments/ColorPaletteFragment.kt +++ b/app/src/main/java/com/drdisagree/colorblendr/ui/fragments/ColorPaletteFragment.kt @@ -1,278 +1,328 @@ -package com.drdisagree.colorblendr.ui.fragments; - -import static com.drdisagree.colorblendr.common.Const.MANUAL_OVERRIDE_COLORS; -import static com.drdisagree.colorblendr.common.Const.MONET_ACCENT_SATURATION; -import static com.drdisagree.colorblendr.common.Const.MONET_ACCURATE_SHADES; -import static com.drdisagree.colorblendr.common.Const.MONET_BACKGROUND_LIGHTNESS; -import static com.drdisagree.colorblendr.common.Const.MONET_BACKGROUND_SATURATION; -import static com.drdisagree.colorblendr.common.Const.MONET_LAST_UPDATED; -import static com.drdisagree.colorblendr.common.Const.MONET_PITCH_BLACK_THEME; -import static com.drdisagree.colorblendr.common.Const.MONET_STYLE; - -import android.content.ClipData; -import android.content.ClipboardManager; -import android.content.Context; -import android.os.Bundle; -import android.os.Handler; -import android.os.Looper; -import android.util.Log; -import android.util.TypedValue; -import android.view.Gravity; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.LinearLayout; -import android.widget.TextView; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.fragment.app.Fragment; -import androidx.lifecycle.ViewModelProvider; - -import com.drdisagree.colorblendr.R; -import com.drdisagree.colorblendr.common.Const; -import com.drdisagree.colorblendr.config.RPrefs; -import com.drdisagree.colorblendr.databinding.FragmentColorPaletteBinding; -import com.drdisagree.colorblendr.ui.viewmodels.SharedViewModel; -import com.drdisagree.colorblendr.utils.ColorSchemeUtil; -import com.drdisagree.colorblendr.utils.ColorUtil; -import com.drdisagree.colorblendr.utils.MiscUtil; -import com.drdisagree.colorblendr.utils.OverlayManager; -import com.google.android.material.snackbar.Snackbar; - -import java.util.ArrayList; -import java.util.Map; - -import me.jfenn.colorpickerdialog.dialogs.ColorPickerDialog; -import me.jfenn.colorpickerdialog.views.picker.ImagePickerView; - -public class ColorPaletteFragment extends Fragment { - - private static final String TAG = ColorPaletteFragment.class.getSimpleName(); - private FragmentColorPaletteBinding binding; - private LinearLayout[] colorTableRows; - private SharedViewModel sharedViewModel; - private final String[][] colorNames = ColorUtil.getColorNames(); - private final boolean notShizukuMode = Const.getWorkingMethod() != Const.WORK_METHOD.SHIZUKU; - private static final int[] colorCodes = { - 0, 10, 50, 100, 200, 300, 400, 500, 600, 700, 800, 900, 1000 - }; - - @Override - public void onCreate(@Nullable Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - sharedViewModel = new ViewModelProvider(requireActivity()).get(SharedViewModel.class); +package com.drdisagree.colorblendr.ui.fragments + +import android.annotation.SuppressLint +import android.content.ClipData +import android.content.ClipboardManager +import android.content.Context +import android.os.Bundle +import android.os.Handler +import android.os.Looper +import android.util.Log +import android.util.TypedValue +import android.view.Gravity +import android.view.LayoutInflater +import android.view.View +import android.view.View.OnLongClickListener +import android.view.ViewGroup +import android.widget.LinearLayout +import android.widget.TextView +import androidx.fragment.app.Fragment +import androidx.lifecycle.Observer +import androidx.lifecycle.ViewModelProvider +import com.drdisagree.colorblendr.R +import com.drdisagree.colorblendr.common.Const +import com.drdisagree.colorblendr.common.Const.MANUAL_OVERRIDE_COLORS +import com.drdisagree.colorblendr.common.Const.MONET_ACCENT_SATURATION +import com.drdisagree.colorblendr.common.Const.MONET_ACCURATE_SHADES +import com.drdisagree.colorblendr.common.Const.MONET_BACKGROUND_LIGHTNESS +import com.drdisagree.colorblendr.common.Const.MONET_BACKGROUND_SATURATION +import com.drdisagree.colorblendr.common.Const.MONET_LAST_UPDATED +import com.drdisagree.colorblendr.common.Const.MONET_PITCH_BLACK_THEME +import com.drdisagree.colorblendr.common.Const.MONET_STYLE +import com.drdisagree.colorblendr.common.Const.workingMethod +import com.drdisagree.colorblendr.config.RPrefs +import com.drdisagree.colorblendr.config.RPrefs.clearPref +import com.drdisagree.colorblendr.config.RPrefs.getBoolean +import com.drdisagree.colorblendr.config.RPrefs.getInt +import com.drdisagree.colorblendr.config.RPrefs.putInt +import com.drdisagree.colorblendr.config.RPrefs.putLong +import com.drdisagree.colorblendr.databinding.FragmentColorPaletteBinding +import com.drdisagree.colorblendr.ui.viewmodels.SharedViewModel +import com.drdisagree.colorblendr.utils.ColorSchemeUtil.stringToEnumMonetStyle +import com.drdisagree.colorblendr.utils.ColorUtil +import com.drdisagree.colorblendr.utils.ColorUtil.calculateTextColor +import com.drdisagree.colorblendr.utils.ColorUtil.generateModifiedColors +import com.drdisagree.colorblendr.utils.ColorUtil.getSystemColors +import com.drdisagree.colorblendr.utils.ColorUtil.intToHexColor +import com.drdisagree.colorblendr.utils.MiscUtil.convertListToIntArray +import com.drdisagree.colorblendr.utils.MiscUtil.setToolbarTitle +import com.drdisagree.colorblendr.utils.OverlayManager.applyFabricatedColors +import com.google.android.material.snackbar.Snackbar +import me.jfenn.colorpickerdialog.dialogs.ColorPickerDialog +import me.jfenn.colorpickerdialog.interfaces.OnColorPickedListener +import me.jfenn.colorpickerdialog.views.picker.ImagePickerView + +class ColorPaletteFragment : Fragment() { + + private lateinit var binding: FragmentColorPaletteBinding + private lateinit var colorTableRows: Array + private lateinit var sharedViewModel: SharedViewModel + private val colorNames: Array> = ColorUtil.colorNames + private val notShizukuMode: Boolean = workingMethod != Const.WorkMethod.SHIZUKU + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + + sharedViewModel = ViewModelProvider(requireActivity())[SharedViewModel::class.java] } - @Override - public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - binding = FragmentColorPaletteBinding.inflate(inflater, container, false); - - MiscUtil.setToolbarTitle(requireContext(), R.string.color_palette_title, true, binding.header.toolbar); - - colorTableRows = new LinearLayout[]{ - binding.colorPreview.systemAccent1, - binding.colorPreview.systemAccent2, - binding.colorPreview.systemAccent3, - binding.colorPreview.systemNeutral1, - binding.colorPreview.systemNeutral2 - }; + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle? + ): View { + binding = FragmentColorPaletteBinding.inflate(inflater, container, false) + + setToolbarTitle( + requireContext(), + R.string.color_palette_title, + true, + binding.header.toolbar + ) + + colorTableRows = arrayOf( + binding.colorPreview.systemAccent1, + binding.colorPreview.systemAccent2, + binding.colorPreview.systemAccent3, + binding.colorPreview.systemNeutral1, + binding.colorPreview.systemNeutral2 + ) // Warning message - boolean isOverrideAvailable = notShizukuMode && - RPrefs.getBoolean(MANUAL_OVERRIDE_COLORS, false); + val isOverrideAvailable: Boolean = notShizukuMode && + getBoolean(MANUAL_OVERRIDE_COLORS, false) - binding.warn.warningText.setText(isOverrideAvailable ? - R.string.color_palette_root_warn : - R.string.color_palette_rootless_warn - ); + binding.warn.warningText.setText( + if (isOverrideAvailable) R.string.color_palette_root_warn else R.string.color_palette_rootless_warn + ) - return binding.getRoot(); + return binding.getRoot() } - @Override - public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { - super.onViewCreated(view, savedInstanceState); + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) - sharedViewModel.getBooleanStates().observe(getViewLifecycleOwner(), this::updateBooleanStates); + sharedViewModel.getBooleanStates() + .observe(getViewLifecycleOwner()) { stringBooleanMap: Map -> + this.updateBooleanStates( + stringBooleanMap + ) + } // Color table preview - initColorTablePreview(colorTableRows); + initColorTablePreview(colorTableRows) } - private void updateBooleanStates(Map stringBooleanMap) { - Boolean accurateShades = stringBooleanMap.get(MONET_ACCURATE_SHADES); + private fun updateBooleanStates(stringBooleanMap: Map) { + val accurateShades: Boolean? = stringBooleanMap[MONET_ACCURATE_SHADES] if (accurateShades != null) { try { updatePreviewColors( - colorTableRows, - generateModifiedColors() - ); - } catch (Exception ignored) { + colorTableRows, + generateModifiedColors() + ) + } catch (ignored: Exception) { } } } - private void updatePreviewColors(LinearLayout[] colorTableRows, ArrayList> palette) { - if (palette == null) return; + private fun updatePreviewColors( + colorTableRows: Array, + palette: ArrayList>? + ) { + if (palette == null) return // Update preview colors - for (int i = 0; i < colorTableRows.length; i++) { - for (int j = 0; j < colorTableRows[i].getChildCount(); j++) { - colorTableRows[i].getChildAt(j).getBackground().setTint(palette.get(i).get(j)); - colorTableRows[i].getChildAt(j).setTag(palette.get(i).get(j)); - ((TextView) ((ViewGroup) colorTableRows[i].getChildAt(j)) - .getChildAt(0)) - .setTextColor(ColorUtil.calculateTextColor(palette.get(i).get(j))); + for (i in colorTableRows.indices) { + for (j in 0 until colorTableRows[i].childCount) { + colorTableRows[i].getChildAt(j).background.setTint(palette[i][j]) + colorTableRows[i].getChildAt(j).tag = palette[i][j] + ((colorTableRows[i].getChildAt(j) as ViewGroup) + .getChildAt(0) as TextView) + .setTextColor(calculateTextColor(palette[i][j])) } } } - private void initColorTablePreview(LinearLayout[] colorTableRows) { - new Thread(() -> { + @SuppressLint("SetTextI18n") + private fun initColorTablePreview(colorTableRows: Array) { + Thread { try { - ArrayList> palette = generateModifiedColors(); + val palette: ArrayList>? = generateModifiedColors() - int[][] systemColors = palette == null ? - ColorUtil.getSystemColors(requireContext()) : - MiscUtil.convertListToIntArray(palette); + val systemColors: Array = + if (palette == null) { + getSystemColors(requireContext()) + } else { + convertListToIntArray(palette) + } - for (int i = 0; i < colorTableRows.length; i++) { - for (int j = 0; j < colorTableRows[i].getChildCount(); j++) { - colorTableRows[i].getChildAt(j).getBackground().setTint(systemColors[i][j]); - colorTableRows[i].getChildAt(j).setTag(systemColors[i][j]); + for (i in colorTableRows.indices) { + for (j in 0 until colorTableRows[i].childCount) { + colorTableRows[i].getChildAt(j).background + .setTint(systemColors[i][j]) + colorTableRows[i].getChildAt(j).tag = systemColors[i][j] - if (RPrefs.getInt(colorNames[i][j], Integer.MIN_VALUE) != Integer.MIN_VALUE) { - colorTableRows[i].getChildAt(j).getBackground().setTint(RPrefs.getInt(colorNames[i][j], 0)); + if (getInt(colorNames[i][j], Int.MIN_VALUE) != Int.MIN_VALUE) { + colorTableRows[i].getChildAt(j).background + .setTint(getInt(colorNames[i][j], 0)) } - TextView textView = new TextView(requireContext()); - textView.setText(String.valueOf(colorCodes[j])); - textView.setRotation(270); - textView.setTextColor(ColorUtil.calculateTextColor(systemColors[i][j])); - textView.setTextSize(TypedValue.COMPLEX_UNIT_SP, 10); - textView.setAlpha(0.8f); - textView.setMaxLines(1); - textView.setSingleLine(true); + val textView = TextView(requireContext()) + textView.text = colorCodes[j].toString() + textView.rotation = 270f + textView.setTextColor(calculateTextColor(systemColors[i][j])) + textView.setTextSize(TypedValue.COMPLEX_UNIT_SP, 10f) + textView.setAlpha(0.8f) + textView.setMaxLines(1) + textView.setSingleLine(true) textView.setAutoSizeTextTypeUniformWithConfiguration( - 1, - 20, - 1, - TypedValue.COMPLEX_UNIT_SP - ); - - int finalI = i; - int finalJ = j; - requireActivity().runOnUiThread(() -> { - ((ViewGroup) colorTableRows[finalI].getChildAt(finalJ)).addView(textView); - ((LinearLayout) colorTableRows[finalI].getChildAt(finalJ)).setGravity(Gravity.CENTER); - }); + 1, + 20, + 1, + TypedValue.COMPLEX_UNIT_SP + ) + + val finalI: Int = i + val finalJ: Int = j + requireActivity().runOnUiThread { + (colorTableRows[finalI].getChildAt(finalJ) as ViewGroup) + .addView(textView) + (colorTableRows[finalI].getChildAt(finalJ) as LinearLayout).gravity = + Gravity.CENTER + } } } - requireActivity().runOnUiThread(() -> enablePaletteOnClickListener(colorTableRows)); - } catch (Exception ignored) { + requireActivity().runOnUiThread { + enablePaletteOnClickListener( + colorTableRows + ) + } + } catch (ignored: Exception) { } - }).start(); + }.start() } - private void enablePaletteOnClickListener(LinearLayout[] colorTableRows) { - for (int i = 0; i < colorTableRows.length; i++) { - for (int j = 0; j < colorTableRows[i].getChildCount(); j++) { - int finalI = i; - int finalJ = j; - - colorTableRows[i].getChildAt(j).setOnClickListener(v -> { - boolean manualOverride = RPrefs.getBoolean(MANUAL_OVERRIDE_COLORS, false); - String snackbarButton = getString(manualOverride ? R.string.override : R.string.copy); - - Snackbar.make( - requireView(), - getString(R.string.color_code, ColorUtil.intToHexColor((Integer) v.getTag())), - Snackbar.LENGTH_INDEFINITE) - .setAction(snackbarButton, v1 -> { + private fun enablePaletteOnClickListener(colorTableRows: Array) { + for (i in colorTableRows.indices) { + for (j in 0 until colorTableRows[i].childCount) { + val finalI: Int = i + val finalJ: Int = j + + colorTableRows[i].getChildAt(j) + .setOnClickListener { v: View -> + val manualOverride: Boolean = getBoolean(MANUAL_OVERRIDE_COLORS, false) + val snackbarButton: String = getString( + if (manualOverride) { + R.string.override + } else { + R.string.copy + } + ) + + Snackbar + .make( + requireView(), + getString(R.string.color_code, intToHexColor((v.tag as Int))), + Snackbar.LENGTH_INDEFINITE + ) + .setAction(snackbarButton) { if (!manualOverride || !notShizukuMode) { - ClipboardManager clipboard = (ClipboardManager) requireContext().getSystemService(Context.CLIPBOARD_SERVICE); - ClipData clip = ClipData.newPlainText(ColorUtil.getColorNames()[finalI][finalJ], ColorUtil.intToHexColor((Integer) v.getTag())); - clipboard.setPrimaryClip(clip); - return; + val clipboard: ClipboardManager = + requireContext().getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager + val clip: ClipData = ClipData.newPlainText( + ColorUtil.colorNames[finalI][finalJ], + intToHexColor(v.tag as Int) + ) + clipboard.setPrimaryClip(clip) + return@setAction } if (finalJ == 0 || finalJ == 12) { Snackbar.make( - requireView(), - getString(R.string.cannot_override_color), - Snackbar.LENGTH_SHORT - ) - .setAction(getString(R.string.dismiss), v2 -> { - }) - .show(); - return; + requireView(), + getString(R.string.cannot_override_color), + Snackbar.LENGTH_SHORT + ) + .setAction(getString(R.string.dismiss)) { } + .show() + return@setAction } - new ColorPickerDialog() - .withCornerRadius(10) - .withColor((Integer) v.getTag()) - .withAlphaEnabled(false) - .withPicker(ImagePickerView.class) - .withListener((pickerView, color) -> { - if ((Integer) v.getTag() != color) { - v.setTag(color); - v.getBackground().setTint(color); - ((TextView) ((ViewGroup) v) - .getChildAt(0)) - .setTextColor(ColorUtil.calculateTextColor(color)); - RPrefs.putInt(colorNames[finalI][finalJ], color); - - RPrefs.putLong(MONET_LAST_UPDATED, System.currentTimeMillis()); - new Handler(Looper.getMainLooper()).postDelayed(() -> { - try { - OverlayManager.applyFabricatedColors(requireContext()); - } catch (Exception ignored) { - } - }, 200); - } - }) - .show(getChildFragmentManager(), "overrideColorPicker" + finalI + finalJ); - }) - .show(); - }); - - colorTableRows[i].getChildAt(j).setOnLongClickListener(v -> { - if (finalJ == 0 || finalJ == 12) { - return true; + ColorPickerDialog() + .withCornerRadius(10f) + .withColor(v.tag as Int) + .withAlphaEnabled(false) + .withPicker(ImagePickerView::class.java) + .withListener { _: ColorPickerDialog?, color: Int -> + if (v.tag as Int != color) { + v.tag = color + v.background.setTint(color) + ((v as ViewGroup) + .getChildAt(0) as TextView) + .setTextColor(calculateTextColor(color)) + putInt(colorNames[finalI][finalJ], color) + + putLong(MONET_LAST_UPDATED, System.currentTimeMillis()) + Handler(Looper.getMainLooper()).postDelayed({ + try { + applyFabricatedColors(requireContext()) + } catch (ignored: Exception) { + } + }, 200) + } + } + .show( + getChildFragmentManager(), + "overrideColorPicker$finalI$finalJ" + ) + } + .show() } - RPrefs.clearPref(colorNames[finalI][finalJ]); + colorTableRows[i].getChildAt(j) + .setOnLongClickListener { + if (finalJ == 0 || finalJ == 12) { + return@setOnLongClickListener true + } + + clearPref(colorNames[finalI][finalJ]) - try { - OverlayManager.applyFabricatedColors(requireContext()); - } catch (Exception ignored) { + try { + applyFabricatedColors(requireContext()) + } catch (ignored: Exception) { + } + true } - return true; - }); } } } - private ArrayList> generateModifiedColors() { + private fun generateModifiedColors(): ArrayList>? { try { - return ColorUtil.generateModifiedColors( + return generateModifiedColors( + requireContext(), + stringToEnumMonetStyle( requireContext(), - ColorSchemeUtil.stringToEnumMonetStyle( - requireContext(), - RPrefs.getString(MONET_STYLE, getString(R.string.monet_tonalspot)) - ), - RPrefs.getInt(MONET_ACCENT_SATURATION, 100), - RPrefs.getInt(MONET_BACKGROUND_SATURATION, 100), - RPrefs.getInt(MONET_BACKGROUND_LIGHTNESS, 100), - RPrefs.getBoolean(MONET_PITCH_BLACK_THEME, false), - RPrefs.getBoolean(MONET_ACCURATE_SHADES, true) - ); - } catch (Exception e) { - Log.e(TAG, "Error generating modified colors", e); - return null; + RPrefs.getString(MONET_STYLE, getString(R.string.monet_tonalspot))!! + ), + getInt(MONET_ACCENT_SATURATION, 100), + getInt(MONET_BACKGROUND_SATURATION, 100), + getInt(MONET_BACKGROUND_LIGHTNESS, 100), + getBoolean(MONET_PITCH_BLACK_THEME, false), + getBoolean(MONET_ACCURATE_SHADES, true) + ) + } catch (e: Exception) { + Log.e(TAG, "Error generating modified colors", e) + return null } } + + companion object { + private val TAG: String = ColorPaletteFragment::class.java.getSimpleName() + private val colorCodes: IntArray = intArrayOf( + 0, 10, 50, 100, 200, 300, 400, 500, 600, 700, 800, 900, 1000 + ) + } } \ No newline at end of file diff --git a/app/src/main/java/com/drdisagree/colorblendr/ui/fragments/ColorsFragment.kt b/app/src/main/java/com/drdisagree/colorblendr/ui/fragments/ColorsFragment.kt index 73ecf38..90d0005 100644 --- a/app/src/main/java/com/drdisagree/colorblendr/ui/fragments/ColorsFragment.kt +++ b/app/src/main/java/com/drdisagree/colorblendr/ui/fragments/ColorsFragment.kt @@ -1,255 +1,284 @@ -package com.drdisagree.colorblendr.ui.fragments; - -import static com.drdisagree.colorblendr.common.Const.MONET_LAST_UPDATED; -import static com.drdisagree.colorblendr.common.Const.MONET_SEED_COLOR; -import static com.drdisagree.colorblendr.common.Const.MONET_SEED_COLOR_ENABLED; -import static com.drdisagree.colorblendr.common.Const.WALLPAPER_COLOR_LIST; - -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; -import android.content.IntentFilter; -import android.graphics.Color; -import android.os.Bundle; -import android.os.Handler; -import android.os.Looper; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.LinearLayout; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.fragment.app.Fragment; -import androidx.lifecycle.ViewModelProvider; -import androidx.localbroadcastmanager.content.LocalBroadcastManager; - -import com.drdisagree.colorblendr.R; -import com.drdisagree.colorblendr.common.Const; -import com.drdisagree.colorblendr.config.RPrefs; -import com.drdisagree.colorblendr.databinding.FragmentColorsBinding; -import com.drdisagree.colorblendr.ui.viewmodels.SharedViewModel; -import com.drdisagree.colorblendr.ui.views.WallColorPreview; -import com.drdisagree.colorblendr.utils.ColorUtil; -import com.drdisagree.colorblendr.utils.MiscUtil; -import com.drdisagree.colorblendr.utils.OverlayManager; -import com.drdisagree.colorblendr.utils.WallpaperColorUtil; -import com.google.gson.reflect.TypeToken; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; - -import me.jfenn.colorpickerdialog.dialogs.ColorPickerDialog; -import me.jfenn.colorpickerdialog.views.picker.ImagePickerView; - -@SuppressWarnings("deprecation") -public class ColorsFragment extends Fragment { - - private static final String TAG = ColorsFragment.class.getSimpleName(); - private FragmentColorsBinding binding; - private int[] monetSeedColor; - private SharedViewModel sharedViewModel; - private final boolean notShizukuMode = Const.getWorkingMethod() != Const.WORK_METHOD.SHIZUKU; - private final BroadcastReceiver wallpaperChangedReceiver = new BroadcastReceiver() { - @Override - public void onReceive(Context context, android.content.Intent intent) { - if (binding.colorsToggleGroup.getCheckedButtonId() == R.id.wallpaper_colors_button) { - addWallpaperColorItems(); +package com.drdisagree.colorblendr.ui.fragments + +import android.content.BroadcastReceiver +import android.content.Context +import android.content.Intent +import android.content.IntentFilter +import android.graphics.Color +import android.os.Bundle +import android.os.Handler +import android.os.Looper +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.LinearLayout +import androidx.fragment.app.Fragment +import androidx.lifecycle.Observer +import androidx.lifecycle.ViewModelProvider +import androidx.localbroadcastmanager.content.LocalBroadcastManager +import com.drdisagree.colorblendr.R +import com.drdisagree.colorblendr.common.Const +import com.drdisagree.colorblendr.common.Const.MONET_LAST_UPDATED +import com.drdisagree.colorblendr.common.Const.MONET_SEED_COLOR +import com.drdisagree.colorblendr.common.Const.MONET_SEED_COLOR_ENABLED +import com.drdisagree.colorblendr.common.Const.WALLPAPER_COLOR_LIST +import com.drdisagree.colorblendr.common.Const.workingMethod +import com.drdisagree.colorblendr.config.RPrefs +import com.drdisagree.colorblendr.config.RPrefs.getBoolean +import com.drdisagree.colorblendr.config.RPrefs.getInt +import com.drdisagree.colorblendr.config.RPrefs.putBoolean +import com.drdisagree.colorblendr.config.RPrefs.putInt +import com.drdisagree.colorblendr.config.RPrefs.putLong +import com.drdisagree.colorblendr.databinding.FragmentColorsBinding +import com.drdisagree.colorblendr.ui.viewmodels.SharedViewModel +import com.drdisagree.colorblendr.ui.views.WallColorPreview +import com.drdisagree.colorblendr.utils.ColorUtil.monetAccentColors +import com.drdisagree.colorblendr.utils.MiscUtil.setToolbarTitle +import com.drdisagree.colorblendr.utils.OverlayManager.applyFabricatedColors +import com.drdisagree.colorblendr.utils.WallpaperColorUtil.getWallpaperColor +import com.google.android.material.button.MaterialButtonToggleGroup +import com.google.android.material.button.MaterialButtonToggleGroup.OnButtonCheckedListener +import com.google.gson.reflect.TypeToken +import me.jfenn.colorpickerdialog.dialogs.ColorPickerDialog +import me.jfenn.colorpickerdialog.interfaces.OnColorPickedListener +import me.jfenn.colorpickerdialog.views.picker.ImagePickerView +import java.util.Arrays +import java.util.stream.Collectors + +@Suppress("deprecation") +class ColorsFragment : Fragment() { + + private lateinit var binding: FragmentColorsBinding + private lateinit var monetSeedColor: IntArray + private lateinit var sharedViewModel: SharedViewModel + private val notShizukuMode: Boolean = workingMethod != Const.WorkMethod.SHIZUKU + + private val wallpaperChangedReceiver: BroadcastReceiver = object : BroadcastReceiver() { + override fun onReceive(context: Context, intent: Intent) { + if (binding.colorsToggleGroup.checkedButtonId == R.id.wallpaper_colors_button) { + addWallpaperColorItems() } } - }; + } - @Override - public void onCreate(@Nullable Bundle savedInstanceState) { - super.onCreate(savedInstanceState); + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) - sharedViewModel = new ViewModelProvider(requireActivity()).get(SharedViewModel.class); + sharedViewModel = ViewModelProvider(requireActivity())[SharedViewModel::class.java] if (!notShizukuMode) { - SettingsFragment.clearCustomColors(); + SettingsFragment.clearCustomColors() } } - @Override - public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - binding = FragmentColorsBinding.inflate(inflater, container, false); + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle? + ): View { + binding = FragmentColorsBinding.inflate(inflater, container, false) - MiscUtil.setToolbarTitle(requireContext(), R.string.app_name, false, binding.header.toolbar); + setToolbarTitle(requireContext(), R.string.app_name, false, binding.header.toolbar) - monetSeedColor = new int[]{RPrefs.getInt( + monetSeedColor = intArrayOf( + getInt( MONET_SEED_COLOR, - WallpaperColorUtil.getWallpaperColor(requireContext()) - )}; + getWallpaperColor(requireContext()) + ) + ) - return binding.getRoot(); + return binding.getRoot() } - @Override - public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { - super.onViewCreated(view, savedInstanceState); + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) - sharedViewModel.getVisibilityStates().observe(getViewLifecycleOwner(), this::updateViewVisibility); + sharedViewModel.getVisibilityStates() + .observe(getViewLifecycleOwner()) { visibilityStates: Map -> + this.updateViewVisibility( + visibilityStates + ) + } // Color codes binding.colorsToggleGroup.check( - RPrefs.getBoolean(MONET_SEED_COLOR_ENABLED, false) ? - R.id.basic_colors_button : - R.id.wallpaper_colors_button - ); - binding.colorsToggleGroup.addOnButtonCheckedListener((group, checkedId, isChecked) -> { + if (getBoolean( + MONET_SEED_COLOR_ENABLED, + false + ) + ) R.id.basic_colors_button else R.id.wallpaper_colors_button + ) + binding.colorsToggleGroup.addOnButtonCheckedListener { _: MaterialButtonToggleGroup?, checkedId: Int, isChecked: Boolean -> if (isChecked) { if (checkedId == R.id.wallpaper_colors_button) { - addWallpaperColorItems(); + addWallpaperColorItems() } else { - addBasicColorItems(); + addBasicColorItems() } } - }); - if (RPrefs.getBoolean(MONET_SEED_COLOR_ENABLED, false)) { - addBasicColorItems(); + } + if (getBoolean(MONET_SEED_COLOR_ENABLED, false)) { + addBasicColorItems() } else { - addWallpaperColorItems(); + addWallpaperColorItems() } // Primary color - binding.seedColorPicker.setPreviewColor(RPrefs.getInt( - MONET_SEED_COLOR, - monetSeedColor[0] - )); - binding.seedColorPicker.setOnClickListener(v -> new ColorPickerDialog() - .withCornerRadius(10) + binding.seedColorPicker.previewColor = getInt( + MONET_SEED_COLOR, + monetSeedColor[0] + ) + + binding.seedColorPicker.setOnClickListener { + ColorPickerDialog() + .withCornerRadius(10f) .withColor(monetSeedColor[0]) .withAlphaEnabled(false) - .withPicker(ImagePickerView.class) - .withListener((pickerView, color) -> { + .withPicker(ImagePickerView::class.java) + .withListener { _: ColorPickerDialog?, color: Int -> if (monetSeedColor[0] != color) { - monetSeedColor[0] = color; - binding.seedColorPicker.setPreviewColor(color); - RPrefs.putInt(MONET_SEED_COLOR, monetSeedColor[0]); - RPrefs.putLong(MONET_LAST_UPDATED, System.currentTimeMillis()); - new Handler(Looper.getMainLooper()).postDelayed(() -> { + monetSeedColor[0] = color + binding.seedColorPicker.previewColor = color + putInt(MONET_SEED_COLOR, monetSeedColor[0]) + putLong(MONET_LAST_UPDATED, System.currentTimeMillis()) + Handler(Looper.getMainLooper()).postDelayed({ try { - OverlayManager.applyFabricatedColors(requireContext()); - } catch (Exception ignored) { + applyFabricatedColors(requireContext()) + } catch (ignored: Exception) { } - }, 300); + }, 300) } - }) + } .show(getChildFragmentManager(), "seedColorPicker") - ); - binding.seedColorPicker.setVisibility( - RPrefs.getBoolean(MONET_SEED_COLOR_ENABLED, false) ? - View.VISIBLE : - View.GONE - ); + } + binding.seedColorPicker.visibility = if (getBoolean(MONET_SEED_COLOR_ENABLED, false)) { + View.VISIBLE + } else { + View.GONE + } // Color palette - binding.colorPalette.setOnClickListener(v -> HomeFragment.replaceFragment(new ColorPaletteFragment())); + binding.colorPalette.setOnClickListener { + HomeFragment.replaceFragment( + ColorPaletteFragment() + ) + } // Force per app theme - binding.perAppTheme.setOnClickListener(v -> HomeFragment.replaceFragment(new PerAppThemeFragment())); - binding.perAppTheme.setEnabled(notShizukuMode); + binding.perAppTheme.setOnClickListener { + HomeFragment.replaceFragment( + PerAppThemeFragment() + ) + } + binding.perAppTheme.setEnabled(notShizukuMode) } - private void updateViewVisibility(Map visibilityStates) { - Integer seedColorVisibility = visibilityStates.get(MONET_SEED_COLOR_ENABLED); - if (seedColorVisibility != null && binding.seedColorPicker.getVisibility() != seedColorVisibility) { - binding.seedColorPicker.setVisibility(seedColorVisibility); + private fun updateViewVisibility(visibilityStates: Map) { + val seedColorVisibility: Int? = visibilityStates[MONET_SEED_COLOR_ENABLED] - String wallpaperColors = RPrefs.getString(WALLPAPER_COLOR_LIST, null); - ArrayList wallpaperColorList = Const.GSON.fromJson( - wallpaperColors, - new TypeToken>() { - }.getType() - ); + if (seedColorVisibility != null && binding.seedColorPicker.visibility != seedColorVisibility) { + binding.seedColorPicker.visibility = seedColorVisibility + + val wallpaperColors: String? = RPrefs.getString(WALLPAPER_COLOR_LIST, null) + val wallpaperColorList: ArrayList = Const.GSON.fromJson( + wallpaperColors, + object : TypeToken?>() { + }.type + ) if (seedColorVisibility == View.GONE) { - monetSeedColor = new int[]{wallpaperColorList.get(0)}; - binding.seedColorPicker.setPreviewColor(monetSeedColor[0]); + monetSeedColor = intArrayOf(wallpaperColorList[0]) + binding.seedColorPicker.previewColor = monetSeedColor[0] } else { - monetSeedColor = new int[]{RPrefs.getInt( + monetSeedColor = intArrayOf( + getInt( MONET_SEED_COLOR, - wallpaperColorList.get(0) - )}; - binding.seedColorPicker.setPreviewColor(monetSeedColor[0]); + wallpaperColorList[0] + ) + ) + binding.seedColorPicker.previewColor = monetSeedColor[0] } } } - private void addWallpaperColorItems() { - String wallpaperColors = RPrefs.getString(WALLPAPER_COLOR_LIST, null); - ArrayList wallpaperColorList; + private fun addWallpaperColorItems() { + val wallpaperColors: String? = RPrefs.getString(WALLPAPER_COLOR_LIST, null) - if (wallpaperColors != null) { - wallpaperColorList = Const.GSON.fromJson( - wallpaperColors, - new TypeToken>() { - }.getType() - ); + val wallpaperColorList: ArrayList = if (wallpaperColors != null) { + Const.GSON.fromJson( + wallpaperColors, + object : TypeToken?>() { + }.type + ) } else { - wallpaperColorList = ColorUtil.getMonetAccentColors(); + monetAccentColors } - addColorsToContainer(wallpaperColorList, true); + addColorsToContainer(wallpaperColorList, true) } - @SuppressWarnings("all") - private void addBasicColorItems() { - String[] basicColors = getResources().getStringArray(R.array.basic_color_codes); - List basicColorList = Arrays.stream(basicColors) - .map(Color::parseColor) - .collect(Collectors.toList()); + private fun addBasicColorItems() { + val basicColors: Array = resources.getStringArray(R.array.basic_color_codes) + val basicColorList: List = Arrays.stream(basicColors) + .map { colorString: String? -> Color.parseColor(colorString) } + .collect(Collectors.toList()) - addColorsToContainer(new ArrayList<>(basicColorList), false); + addColorsToContainer(ArrayList(basicColorList), false) } - private void addColorsToContainer(ArrayList colorList, boolean isWallpaperColors) { - binding.colorsContainer.removeAllViews(); - - for (int i = 0; i < colorList.size(); i++) { - int size = (int) (48 * getResources().getDisplayMetrics().density); - int margin = (int) (12 * getResources().getDisplayMetrics().density); - - WallColorPreview colorPreview = new WallColorPreview(requireContext()); - LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(size, size); - layoutParams.setMargins(margin, margin, margin, margin); - colorPreview.setLayoutParams(layoutParams); - colorPreview.setMainColor(colorList.get(i)); - colorPreview.setTag(colorList.get(i)); - colorPreview.setSelected(colorList.get(i) == RPrefs.getInt(MONET_SEED_COLOR, Integer.MIN_VALUE)); - - colorPreview.setOnClickListener(v -> { - RPrefs.putInt(MONET_SEED_COLOR, (Integer) colorPreview.getTag()); - RPrefs.putBoolean(MONET_SEED_COLOR_ENABLED, !isWallpaperColors); - binding.seedColorPicker.setPreviewColor((Integer) colorPreview.getTag()); - RPrefs.putLong(MONET_LAST_UPDATED, System.currentTimeMillis()); - OverlayManager.applyFabricatedColors(requireContext()); - }); - - binding.colorsContainer.addView(colorPreview); + private fun addColorsToContainer(colorList: ArrayList, isWallpaperColors: Boolean) { + binding.colorsContainer.removeAllViews() + + for (i in colorList.indices) { + val size: Int = (48 * resources.displayMetrics.density).toInt() + val margin: Int = (12 * resources.displayMetrics.density).toInt() + + val colorPreview = WallColorPreview(requireContext()) + val layoutParams: LinearLayout.LayoutParams = LinearLayout.LayoutParams(size, size) + layoutParams.setMargins(margin, margin, margin, margin) + colorPreview.setLayoutParams(layoutParams) + colorPreview.setMainColor(colorList[i]) + colorPreview.tag = colorList[i] + colorPreview.setSelected(colorList[i] == getInt(MONET_SEED_COLOR, Int.MIN_VALUE)) + + colorPreview.setOnClickListener { + putInt( + MONET_SEED_COLOR, + (colorPreview.tag as Int) + ) + putBoolean(MONET_SEED_COLOR_ENABLED, !isWallpaperColors) + binding.seedColorPicker.previewColor = colorPreview.tag as Int + putLong(MONET_LAST_UPDATED, System.currentTimeMillis()) + applyFabricatedColors(requireContext()) + } + + binding.colorsContainer.addView(colorPreview) } } - @Override - public void onResume() { - super.onResume(); + override fun onResume() { + super.onResume() - IntentFilter intentFilter = new IntentFilter(); - intentFilter.addAction(Intent.ACTION_WALLPAPER_CHANGED); + val intentFilter = IntentFilter() + intentFilter.addAction(Intent.ACTION_WALLPAPER_CHANGED) - LocalBroadcastManager.getInstance(requireContext()).registerReceiver(wallpaperChangedReceiver, intentFilter); + LocalBroadcastManager + .getInstance(requireContext()) + .registerReceiver(wallpaperChangedReceiver, intentFilter) } - @Override - public void onDestroy() { + override fun onDestroy() { try { - LocalBroadcastManager.getInstance(requireContext()).unregisterReceiver(wallpaperChangedReceiver); - } catch (Exception ignored) { + LocalBroadcastManager + .getInstance(requireContext()) + .unregisterReceiver(wallpaperChangedReceiver) + } catch (ignored: Exception) { // Receiver was not registered } - super.onDestroy(); + super.onDestroy() + } + + companion object { + private val TAG: String = ColorsFragment::class.java.getSimpleName() } } \ No newline at end of file diff --git a/app/src/main/java/com/drdisagree/colorblendr/ui/fragments/HomeFragment.kt b/app/src/main/java/com/drdisagree/colorblendr/ui/fragments/HomeFragment.kt index a812b54..68315fb 100644 --- a/app/src/main/java/com/drdisagree/colorblendr/ui/fragments/HomeFragment.kt +++ b/app/src/main/java/com/drdisagree/colorblendr/ui/fragments/HomeFragment.kt @@ -1,235 +1,279 @@ -package com.drdisagree.colorblendr.ui.fragments; - -import android.content.Context; -import android.content.Intent; -import android.os.Bundle; -import android.os.Handler; -import android.os.Looper; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.Toast; - -import androidx.activity.OnBackPressedCallback; -import androidx.activity.result.ActivityResultLauncher; -import androidx.activity.result.contract.ActivityResultContracts; -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.core.app.ActivityCompat; -import androidx.fragment.app.Fragment; -import androidx.fragment.app.FragmentManager; -import androidx.fragment.app.FragmentTransaction; - -import com.drdisagree.colorblendr.R; -import com.drdisagree.colorblendr.databinding.FragmentHomeBinding; -import com.drdisagree.colorblendr.service.AutoStartService; -import com.drdisagree.colorblendr.utils.AppUtil; -import com.drdisagree.colorblendr.utils.FragmentUtil; -import com.drdisagree.colorblendr.utils.SystemUtil; -import com.google.android.material.snackbar.Snackbar; - -import java.util.Map; -import java.util.Objects; - -public class HomeFragment extends Fragment { - - private FragmentHomeBinding binding; - private static Fragment currentFragment; - private static FragmentManager fragmentManager; - - @Override - public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - binding = FragmentHomeBinding.inflate(inflater, container, false); - fragmentManager = getChildFragmentManager(); +package com.drdisagree.colorblendr.ui.fragments + +import android.content.Intent +import android.os.Bundle +import android.os.Handler +import android.os.Looper +import android.view.LayoutInflater +import android.view.MenuItem +import android.view.View +import android.view.ViewGroup +import androidx.activity.OnBackPressedCallback +import androidx.activity.result.ActivityResultLauncher +import androidx.activity.result.contract.ActivityResultContracts +import androidx.core.app.ActivityCompat +import androidx.fragment.app.Fragment +import androidx.fragment.app.FragmentManager +import androidx.fragment.app.FragmentTransaction +import com.drdisagree.colorblendr.R +import com.drdisagree.colorblendr.databinding.FragmentHomeBinding +import com.drdisagree.colorblendr.service.AutoStartService +import com.drdisagree.colorblendr.service.AutoStartService.Companion.isServiceNotRunning +import com.drdisagree.colorblendr.utils.AppUtil +import com.drdisagree.colorblendr.utils.AppUtil.hasStoragePermission +import com.drdisagree.colorblendr.utils.AppUtil.openAppSettings +import com.drdisagree.colorblendr.utils.AppUtil.permissionsGranted +import com.drdisagree.colorblendr.utils.AppUtil.requestStoragePermission +import com.drdisagree.colorblendr.utils.FragmentUtil.TabSelection +import com.drdisagree.colorblendr.utils.FragmentUtil.getSlidingDirection +import com.drdisagree.colorblendr.utils.FragmentUtil.setCustomAnimations +import com.google.android.material.snackbar.Snackbar + +class HomeFragment : Fragment() { + + private lateinit var binding: FragmentHomeBinding + + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle? + ): View { + binding = FragmentHomeBinding.inflate(inflater, container, false) + myFragmentManager = getChildFragmentManager() if (savedInstanceState == null) { - replaceFragment(new ColorsFragment()); + replaceFragment(ColorsFragment()) } - return binding.getRoot(); + return binding.getRoot() } - @Override - public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { - super.onViewCreated(view, savedInstanceState); + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) - setupBottomNavigationView(); + setupBottomNavigationView() - new Handler(Looper.getMainLooper()).postDelayed(() -> { + Handler(Looper.getMainLooper()).postDelayed({ try { - if (AppUtil.permissionsGranted(requireContext())) { - if (AutoStartService.isServiceNotRunning()) { - requireContext().startForegroundService(new Intent(requireContext(), AutoStartService.class)); + if (permissionsGranted(requireContext())) { + if (isServiceNotRunning) { + requireContext().startForegroundService( + Intent( + requireContext(), + AutoStartService::class.java + ) + ) } } else { - requestPermissionsLauncher.launch(AppUtil.REQUIRED_PERMISSIONS); + requestPermissionsLauncher.launch(AppUtil.REQUIRED_PERMISSIONS) } - } catch (Exception ignored) { + } catch (ignored: Exception) { } - }, 2000); + }, 2000) - registerOnBackPressedCallback(); + registerOnBackPressedCallback() } - public static void replaceFragment(Fragment fragment) { - String tag = fragment.getClass().getSimpleName(); - FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction(); + private fun setupBottomNavigationView() { + getChildFragmentManager().addOnBackStackChangedListener { + val tag: String? = topFragment - FragmentUtil.TAB_SELECTION direction = FragmentUtil.getSlidingDirection(currentFragment, fragment); - if (currentFragment != null) { - FragmentUtil.setCustomAnimations(direction, fragmentTransaction); - } + when (tag) { + ColorsFragment::class.java.simpleName -> { + binding.bottomNavigationView.menu.getItem(0).setChecked(true) + } - fragmentTransaction.replace( - R.id.fragmentContainer, - fragment - ); - - if (Objects.equals(tag, ColorsFragment.class.getSimpleName())) { - fragmentManager.popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE); - } else if (Objects.equals(tag, ThemeFragment.class.getSimpleName()) || - Objects.equals(tag, StylesFragment.class.getSimpleName()) || - Objects.equals(tag, SettingsFragment.class.getSimpleName()) - ) { - fragmentManager.popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE); - fragmentTransaction.addToBackStack(tag); - } else { - fragmentTransaction.addToBackStack(tag); - } + ThemeFragment::class.java.simpleName -> { + binding.bottomNavigationView.menu.getItem(1).setChecked(true) + } - fragmentTransaction.commit(); - currentFragment = fragment; - } + StylesFragment::class.java.simpleName -> { + binding.bottomNavigationView.menu.getItem(2).setChecked(true) + } - private void setupBottomNavigationView() { - getChildFragmentManager().addOnBackStackChangedListener(() -> { - String tag = getTopFragment(); - - if (Objects.equals(tag, ColorsFragment.class.getSimpleName())) { - binding.bottomNavigationView.getMenu().getItem(0).setChecked(true); - } else if (Objects.equals(tag, ThemeFragment.class.getSimpleName())) { - binding.bottomNavigationView.getMenu().getItem(1).setChecked(true); - } else if (Objects.equals(tag, StylesFragment.class.getSimpleName())) { - binding.bottomNavigationView.getMenu().getItem(2).setChecked(true); - } else if (Objects.equals(tag, SettingsFragment.class.getSimpleName())) { - binding.bottomNavigationView.getMenu().getItem(3).setChecked(true); - } - }); - - binding.bottomNavigationView.setOnItemSelectedListener(item -> { - if (item.getItemId() == R.id.nav_colors) { - replaceFragment(new ColorsFragment()); - } else if (item.getItemId() == R.id.nav_themes) { - replaceFragment(new ThemeFragment()); - } else if (item.getItemId() == R.id.nav_styles) { - replaceFragment(new StylesFragment()); - } else if (item.getItemId() == R.id.nav_settings) { - replaceFragment(new SettingsFragment()); - } else { - return false; + SettingsFragment::class.java.simpleName -> { + binding.bottomNavigationView.menu.getItem(3).setChecked(true) + } } + } - return true; - }); + binding.bottomNavigationView.setOnItemSelectedListener { item: MenuItem -> + when (item.itemId) { + R.id.nav_colors -> { + replaceFragment(ColorsFragment()) + } - binding.bottomNavigationView.setOnItemReselectedListener(item -> { - // Do nothing - }); - } + R.id.nav_themes -> { + replaceFragment(ThemeFragment()) + } - private void registerOnBackPressedCallback() { - requireActivity().getOnBackPressedDispatcher().addCallback(getViewLifecycleOwner(), new OnBackPressedCallback(true) { - @Override - public void handleOnBackPressed() { - FragmentManager fragmentManager = getChildFragmentManager(); - if (fragmentManager.getBackStackEntryCount() > 0) { - fragmentManager.popBackStack(); - } else { - requireActivity().finish(); + R.id.nav_styles -> { + replaceFragment(StylesFragment()) + } + + R.id.nav_settings -> { + replaceFragment(SettingsFragment()) + } + + else -> { + return@setOnItemSelectedListener false } } - }); + true + } + + binding.bottomNavigationView.setOnItemReselectedListener { } + } + + private fun registerOnBackPressedCallback() { + requireActivity() + .onBackPressedDispatcher + .addCallback(getViewLifecycleOwner(), object : OnBackPressedCallback(true) { + override fun handleOnBackPressed() { + val fragmentManager: FragmentManager = getChildFragmentManager() + + if (fragmentManager.backStackEntryCount > 0) { + fragmentManager.popBackStack() + } else { + requireActivity().finish() + } + } + }) } - private final ActivityResultLauncher requestPermissionsLauncher = registerForActivityResult( - new ActivityResultContracts.RequestMultiplePermissions(), - this::handlePermissionsResult - ); + private val requestPermissionsLauncher: ActivityResultLauncher> = + registerForActivityResult(ActivityResultContracts.RequestMultiplePermissions()) { result: Map -> + this.handlePermissionsResult( + result + ) + } - private void handlePermissionsResult(Map result) { - for (Map.Entry pair : result.entrySet()) { - String permission = pair.getKey(); - boolean granted = pair.getValue(); + private fun handlePermissionsResult(result: Map) { + for (pair: Map.Entry in result.entries) { + val permission: String = pair.key + val granted: Boolean = pair.value if (!granted) { showGeneralPermissionSnackbar( - permission, - !ActivityCompat.shouldShowRequestPermissionRationale(requireActivity(), permission) - ); - return; + permission, + !ActivityCompat.shouldShowRequestPermissionRationale( + requireActivity(), + permission + ) + ) + return } } - if (!AppUtil.hasStoragePermission()) { - showStoragePermissionSnackbar(); - return; + if (!hasStoragePermission()) { + showStoragePermissionSnackbar() + return } - if (AutoStartService.isServiceNotRunning()) { - requireContext().startForegroundService(new Intent(requireContext(), AutoStartService.class)); + if (isServiceNotRunning) { + requireContext().startForegroundService( + Intent( + requireContext(), + AutoStartService::class.java + ) + ) } } - private void showGeneralPermissionSnackbar(String permission, boolean permanentlyDenied) { - Snackbar snackbar = Snackbar.make( - requireActivity().findViewById(android.R.id.content), - R.string.permission_must_be_granted, - Snackbar.LENGTH_INDEFINITE - ); - snackbar.setAction(R.string.grant, v -> { + private fun showGeneralPermissionSnackbar(permission: String, permanentlyDenied: Boolean) { + val snackbar: Snackbar = Snackbar.make( + requireActivity().findViewById(android.R.id.content), + R.string.permission_must_be_granted, + Snackbar.LENGTH_INDEFINITE + ) + + snackbar.setAction(R.string.grant) { if (!permanentlyDenied) { - requestPermissionsLauncher.launch(new String[]{permission}); + requestPermissionsLauncher.launch(arrayOf(permission)) } else { - AppUtil.openAppSettings(requireContext()); + openAppSettings(requireContext()) } - snackbar.dismiss(); - }); - snackbar.show(); + snackbar.dismiss() + } + + snackbar.show() } - private void showStoragePermissionSnackbar() { - Snackbar snackbar = Snackbar.make( - requireActivity().findViewById(android.R.id.content), - R.string.file_access_permission_required, - Snackbar.LENGTH_INDEFINITE - ); - snackbar.setAction(R.string.grant, v -> { - AppUtil.requestStoragePermission(requireContext()); - snackbar.dismiss(); - }); - snackbar.show(); + private fun showStoragePermissionSnackbar() { + val snackbar: Snackbar = Snackbar.make( + requireActivity().findViewById(android.R.id.content), + R.string.file_access_permission_required, + Snackbar.LENGTH_INDEFINITE + ) + + snackbar.setAction(R.string.grant) { + requestStoragePermission(requireContext()) + snackbar.dismiss() + } + + snackbar.show() } - private String getTopFragment() { - String[] fragment = {null}; + private val topFragment: String? + get() { + val fragment: Array = arrayOf(null) + + val fragmentManager: FragmentManager = getChildFragmentManager() + val last: Int = fragmentManager.fragments.size - 1 - FragmentManager fragmentManager = getChildFragmentManager(); - int last = fragmentManager.getFragments().size() - 1; + if (last >= 0) { + val topFragment: Fragment = fragmentManager.fragments[last] + currentFragment = topFragment - if (last >= 0) { - Fragment topFragment = fragmentManager.getFragments().get(last); - currentFragment = topFragment; + when (topFragment) { + is ColorsFragment -> fragment[0] = ColorsFragment::class.java.simpleName - if (topFragment instanceof ColorsFragment) - fragment[0] = ColorsFragment.class.getSimpleName(); - else if (topFragment instanceof ThemeFragment) - fragment[0] = ThemeFragment.class.getSimpleName(); - else if (topFragment instanceof StylesFragment) - fragment[0] = StylesFragment.class.getSimpleName(); - else if (topFragment instanceof SettingsFragment) - fragment[0] = SettingsFragment.class.getSimpleName(); + is ThemeFragment -> fragment[0] = ThemeFragment::class.java.simpleName + + is StylesFragment -> fragment[0] = StylesFragment::class.java.simpleName + + is SettingsFragment -> fragment[0] = SettingsFragment::class.java.simpleName + } + } + + return fragment[0] } - return fragment[0]; + companion object { + private var currentFragment: Fragment? = null + private lateinit var myFragmentManager: FragmentManager + + fun replaceFragment(fragment: Fragment) { + val tag: String = fragment.javaClass.simpleName + val fragmentTransaction: FragmentTransaction = myFragmentManager.beginTransaction() + + val direction: TabSelection = getSlidingDirection(currentFragment, fragment) + if (currentFragment != null) { + setCustomAnimations(direction, fragmentTransaction) + } + + fragmentTransaction.replace( + R.id.fragmentContainer, + fragment + ) + + when (tag) { + ColorsFragment::class.java.simpleName -> { + myFragmentManager.popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE) + } + + ThemeFragment::class.java.simpleName, StylesFragment::class.java.simpleName, SettingsFragment::class.java.simpleName -> { + myFragmentManager.popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE) + fragmentTransaction.addToBackStack(tag) + } + + else -> { + fragmentTransaction.addToBackStack(tag) + } + } + + fragmentTransaction.commit() + currentFragment = fragment + } } } \ No newline at end of file diff --git a/app/src/main/java/com/drdisagree/colorblendr/ui/fragments/OnboardingFragment.kt b/app/src/main/java/com/drdisagree/colorblendr/ui/fragments/OnboardingFragment.kt index 3096ed0..c8ab247 100644 --- a/app/src/main/java/com/drdisagree/colorblendr/ui/fragments/OnboardingFragment.kt +++ b/app/src/main/java/com/drdisagree/colorblendr/ui/fragments/OnboardingFragment.kt @@ -1,233 +1,251 @@ -package com.drdisagree.colorblendr.ui.fragments; - -import static com.drdisagree.colorblendr.common.Const.FIRST_RUN; -import static com.drdisagree.colorblendr.common.Const.WALLPAPER_COLOR_LIST; - -import android.os.Bundle; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.view.animation.AlphaAnimation; -import android.view.animation.Animation; -import android.widget.Toast; - -import androidx.activity.OnBackPressedCallback; -import androidx.annotation.NonNull; -import androidx.fragment.app.Fragment; -import androidx.viewpager2.widget.ViewPager2; - -import com.drdisagree.colorblendr.ColorBlendr; -import com.drdisagree.colorblendr.R; -import com.drdisagree.colorblendr.common.Const; -import com.drdisagree.colorblendr.config.RPrefs; -import com.drdisagree.colorblendr.databinding.FragmentOnboardingBinding; -import com.drdisagree.colorblendr.extension.MethodInterface; -import com.drdisagree.colorblendr.provider.RootConnectionProvider; -import com.drdisagree.colorblendr.provider.ShizukuConnectionProvider; -import com.drdisagree.colorblendr.service.ShizukuConnection; -import com.drdisagree.colorblendr.ui.activities.MainActivity; -import com.drdisagree.colorblendr.ui.adapters.OnboardingAdapter; -import com.drdisagree.colorblendr.utils.AppUtil; -import com.drdisagree.colorblendr.utils.FabricatedUtil; -import com.drdisagree.colorblendr.utils.ShizukuUtil; -import com.drdisagree.colorblendr.utils.WallpaperColorUtil; - -import java.util.ArrayList; - -public class OnboardingFragment extends Fragment { - - private FragmentOnboardingBinding binding; - private OnboardingAdapter adapter; - - @Override - public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - binding = FragmentOnboardingBinding.inflate(inflater, container, false); - - adapter = new OnboardingAdapter( - getChildFragmentManager(), - requireActivity().getLifecycle() - ); - - adapter.addFragment(new OnboardingItem1Fragment()); - adapter.addFragment(new OnboardingItem2Fragment()); - adapter.addFragment(new OnboardingItem3Fragment()); - - binding.viewPager.setAdapter(adapter); - - binding.viewPager.registerOnPageChangeCallback(new ViewPager2.OnPageChangeCallback() { - @Override - public void onPageSelected(int position) { - super.onPageSelected(position); - - animateBackButton(position); - changeContinueButtonText(position); +package com.drdisagree.colorblendr.ui.fragments + +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.view.animation.AlphaAnimation +import android.view.animation.Animation +import android.widget.Toast +import androidx.activity.OnBackPressedCallback +import androidx.fragment.app.Fragment +import androidx.viewpager2.widget.ViewPager2 +import com.drdisagree.colorblendr.ColorBlendr.Companion.appContext +import com.drdisagree.colorblendr.R +import com.drdisagree.colorblendr.common.Const +import com.drdisagree.colorblendr.common.Const.FIRST_RUN +import com.drdisagree.colorblendr.common.Const.WALLPAPER_COLOR_LIST +import com.drdisagree.colorblendr.common.Const.saveWorkingMethod +import com.drdisagree.colorblendr.config.RPrefs.putBoolean +import com.drdisagree.colorblendr.config.RPrefs.putString +import com.drdisagree.colorblendr.databinding.FragmentOnboardingBinding +import com.drdisagree.colorblendr.extension.MethodInterface +import com.drdisagree.colorblendr.provider.RootConnectionProvider.Companion.builder +import com.drdisagree.colorblendr.provider.ShizukuConnectionProvider +import com.drdisagree.colorblendr.service.ShizukuConnection +import com.drdisagree.colorblendr.ui.activities.MainActivity +import com.drdisagree.colorblendr.ui.adapters.OnboardingAdapter +import com.drdisagree.colorblendr.utils.AppUtil.hasStoragePermission +import com.drdisagree.colorblendr.utils.AppUtil.permissionsGranted +import com.drdisagree.colorblendr.utils.FabricatedUtil.getAndSaveSelectedFabricatedApps +import com.drdisagree.colorblendr.utils.ShizukuUtil.bindUserService +import com.drdisagree.colorblendr.utils.ShizukuUtil.getUserServiceArgs +import com.drdisagree.colorblendr.utils.ShizukuUtil.isShizukuAvailable +import com.drdisagree.colorblendr.utils.ShizukuUtil.requestShizukuPermission +import com.drdisagree.colorblendr.utils.WallpaperColorUtil.getAndSaveWallpaperColors +import com.drdisagree.colorblendr.utils.WallpaperColorUtil.getWallpaperColors + +class OnboardingFragment : Fragment() { + + private lateinit var binding: FragmentOnboardingBinding + private lateinit var adapter: OnboardingAdapter + + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle? + ): View { + binding = FragmentOnboardingBinding.inflate(inflater, container, false) + + adapter = OnboardingAdapter( + childFragmentManager, + requireActivity().lifecycle + ) + + adapter.addFragment(OnboardingItem1Fragment()) + adapter.addFragment(OnboardingItem2Fragment()) + adapter.addFragment(OnboardingItem3Fragment()) + + binding.viewPager.adapter = adapter + + binding.viewPager.registerOnPageChangeCallback(object : + ViewPager2.OnPageChangeCallback() { + override fun onPageSelected(position: Int) { + super.onPageSelected(position) + + animateBackButton(position) + changeContinueButtonText(position) } - }); + }) - binding.btnNext.setOnClickListener(v -> { - if (binding.viewPager.getCurrentItem() == adapter.getItemCount() - 1) { - if (!AppUtil.permissionsGranted(requireContext())) { - Toast.makeText(requireContext(), R.string.grant_all_permissions, Toast.LENGTH_SHORT).show(); - return; + binding.btnNext.setOnClickListener { + if (binding.viewPager.currentItem == adapter.itemCount - 1) { + if (!permissionsGranted(requireContext())) { + Toast.makeText( + requireContext(), + R.string.grant_all_permissions, + Toast.LENGTH_SHORT + ).show() + + return@setOnClickListener } - if (Const.WORKING_METHOD == Const.WORK_METHOD.NULL) { - Toast.makeText(requireContext(), R.string.select_method, Toast.LENGTH_SHORT).show(); - } else if (Const.WORKING_METHOD == Const.WORK_METHOD.ROOT) { - checkRootConnection(); - } else if (Const.WORKING_METHOD == Const.WORK_METHOD.SHIZUKU) { - checkShizukuConnection(); + when (Const.WORKING_METHOD) { + Const.WorkMethod.NULL -> { + Toast.makeText(requireContext(), R.string.select_method, Toast.LENGTH_SHORT) + .show() + } + + Const.WorkMethod.ROOT -> { + checkRootConnection() + } + + Const.WorkMethod.SHIZUKU -> { + checkShizukuConnection() + } } - return; + return@setOnClickListener } - binding.viewPager.setCurrentItem(binding.viewPager.getCurrentItem() + 1); - }); + binding.viewPager.currentItem += 1 + } - binding.btnPrev.setOnClickListener(v -> binding.viewPager.setCurrentItem(binding.viewPager.getCurrentItem() - 1, true)); + binding.btnPrev.setOnClickListener { + binding.viewPager.setCurrentItem( + binding.viewPager.currentItem - 1, true + ) + } - registerOnBackInvokedCallback(); + registerOnBackInvokedCallback() - return binding.getRoot(); + return binding.root } - private void checkRootConnection() { - RootConnectionProvider.builder(requireContext()) - .runOnSuccess(new MethodInterface() { - @Override - public void run() { - goToHomeFragment(); - } - }).run(); + private fun checkRootConnection() { + builder(requireContext()) + .runOnSuccess(object : MethodInterface() { + override fun run() { + goToHomeFragment() + } + }).run() } - private void checkShizukuConnection() { - if (ShizukuUtil.isShizukuAvailable()) { - ShizukuUtil.requestShizukuPermission(requireActivity(), granted -> { + private fun checkShizukuConnection() { + if (isShizukuAvailable) { + requestShizukuPermission(requireActivity()) { granted: Boolean -> if (granted) { - ShizukuUtil.bindUserService( - ShizukuUtil.getUserServiceArgs(ShizukuConnection.class), - ShizukuConnectionProvider.serviceConnection - ); - goToHomeFragment(); + bindUserService( + getUserServiceArgs(ShizukuConnection::class.java), + ShizukuConnectionProvider.serviceConnection + ) + goToHomeFragment() } else { Toast.makeText( - ColorBlendr.getAppContext(), - R.string.shizuku_service_not_found, - Toast.LENGTH_LONG - ).show(); + appContext, + R.string.shizuku_service_not_found, + Toast.LENGTH_LONG + ).show() } - }); + } } else { Toast.makeText( - ColorBlendr.getAppContext(), - R.string.shizuku_service_not_found, - Toast.LENGTH_LONG - ).show(); + appContext, + R.string.shizuku_service_not_found, + Toast.LENGTH_LONG + ).show() } } - private void goToHomeFragment() { - Const.saveWorkingMethod(Const.WORKING_METHOD); - WallpaperColorUtil.getAndSaveWallpaperColors(requireContext()); - FabricatedUtil.getAndSaveSelectedFabricatedApps(requireContext()); - RPrefs.putBoolean(FIRST_RUN, false); - MainActivity.replaceFragment(new HomeFragment(), true); + private fun goToHomeFragment() { + saveWorkingMethod(Const.WORKING_METHOD) + getAndSaveWallpaperColors(requireContext()) + getAndSaveSelectedFabricatedApps(requireContext()) + putBoolean(FIRST_RUN, false) + MainActivity.Companion.replaceFragment(HomeFragment(), true) } - private void animateBackButton(int position) { - int duration = 300; + private fun animateBackButton(position: Int) { + val duration = 300 - if (position == 0 && binding.btnPrev.getVisibility() == View.VISIBLE) { - AlphaAnimation fadeOut = getFadeOutAnimation(duration); - binding.btnPrev.startAnimation(fadeOut); - } else if (position != 0 && binding.btnPrev.getVisibility() != View.VISIBLE) { - AlphaAnimation fadeIn = getFadeInAnimation(duration); - binding.btnPrev.startAnimation(fadeIn); + if (position == 0 && binding.btnPrev.visibility == View.VISIBLE) { + val fadeOut = getFadeOutAnimation(duration) + binding.btnPrev.startAnimation(fadeOut) + } else if (position != 0 && binding.btnPrev.visibility != View.VISIBLE) { + val fadeIn = getFadeInAnimation(duration) + binding.btnPrev.startAnimation(fadeIn) } } - private @NonNull AlphaAnimation getFadeOutAnimation(int duration) { - AlphaAnimation fadeOut = new AlphaAnimation(1.0f, 0.0f); + @Suppress("SameParameterValue") + private fun getFadeOutAnimation(duration: Int): AlphaAnimation { + val fadeOut = AlphaAnimation(1.0f, 0.0f) - fadeOut.setDuration(duration); + fadeOut.duration = duration.toLong() - fadeOut.setAnimationListener(new Animation.AnimationListener() { - @Override - public void onAnimationStart(Animation animation) { + fadeOut.setAnimationListener(object : Animation.AnimationListener { + override fun onAnimationStart(animation: Animation) { } - @Override - public void onAnimationEnd(Animation animation) { - binding.btnPrev.setVisibility(View.GONE); + override fun onAnimationEnd(animation: Animation) { + binding.btnPrev.visibility = View.GONE } - @Override - public void onAnimationRepeat(Animation animation) { + override fun onAnimationRepeat(animation: Animation) { } - }); + }) - return fadeOut; + return fadeOut } - private @NonNull AlphaAnimation getFadeInAnimation(int duration) { - AlphaAnimation fadeIn = new AlphaAnimation(0.0f, 1.0f); + @Suppress("SameParameterValue") + private fun getFadeInAnimation(duration: Int): AlphaAnimation { + val fadeIn = AlphaAnimation(0.0f, 1.0f) - fadeIn.setDuration(duration); + fadeIn.duration = duration.toLong() - fadeIn.setAnimationListener(new Animation.AnimationListener() { - @Override - public void onAnimationStart(Animation animation) { - binding.btnPrev.setVisibility(View.VISIBLE); + fadeIn.setAnimationListener(object : Animation.AnimationListener { + override fun onAnimationStart(animation: Animation) { + binding.btnPrev.visibility = View.VISIBLE } - @Override - public void onAnimationEnd(Animation animation) { + override fun onAnimationEnd(animation: Animation) { } - @Override - public void onAnimationRepeat(Animation animation) { + override fun onAnimationRepeat(animation: Animation) { } - }); + }) - return fadeIn; + return fadeIn } - private void changeContinueButtonText(int position) { - if (position == adapter.getItemCount() - 1) { - binding.btnNext.setText(R.string.start); + private fun changeContinueButtonText(position: Int) { + if (position == adapter.itemCount - 1) { + binding.btnNext.setText(R.string.start) - new Thread(() -> { + Thread { try { - if (AppUtil.hasStoragePermission()) { - ArrayList wallpaperColors = WallpaperColorUtil.getWallpaperColors(requireContext()); - RPrefs.putString(WALLPAPER_COLOR_LIST, Const.GSON.toJson(wallpaperColors)); + if (hasStoragePermission()) { + val wallpaperColors = + getWallpaperColors(requireContext()) + putString( + WALLPAPER_COLOR_LIST, + Const.GSON.toJson(wallpaperColors) + ) } - } catch (Exception ignored) { + } catch (ignored: Exception) { } - }).start(); + }.start() } else { - binding.btnNext.setText(R.string.btn_continue); + binding.btnNext.setText(R.string.btn_continue) } } - private void registerOnBackInvokedCallback() { - requireActivity().getOnBackPressedDispatcher().addCallback( - requireActivity(), - new OnBackPressedCallback(true) { - @Override - public void handleOnBackPressed() { - onBackPressed(); - } - }); + private fun registerOnBackInvokedCallback() { + requireActivity().onBackPressedDispatcher.addCallback( + requireActivity(), + object : OnBackPressedCallback(true) { + override fun handleOnBackPressed() { + onBackPressed() + } + }) } - private void onBackPressed() { - if (binding.viewPager.getCurrentItem() == 0) { - requireActivity().finish(); + private fun onBackPressed() { + if (binding.viewPager.currentItem == 0) { + requireActivity().finish() } else { - binding.viewPager.setCurrentItem(binding.viewPager.getCurrentItem() - 1, true); + binding.viewPager.setCurrentItem(binding.viewPager.currentItem - 1, true) } } } \ No newline at end of file diff --git a/app/src/main/java/com/drdisagree/colorblendr/ui/fragments/OnboardingItem1Fragment.kt b/app/src/main/java/com/drdisagree/colorblendr/ui/fragments/OnboardingItem1Fragment.kt index 7895b2a..3046d03 100644 --- a/app/src/main/java/com/drdisagree/colorblendr/ui/fragments/OnboardingItem1Fragment.kt +++ b/app/src/main/java/com/drdisagree/colorblendr/ui/fragments/OnboardingItem1Fragment.kt @@ -1,22 +1,22 @@ -package com.drdisagree.colorblendr.ui.fragments; +package com.drdisagree.colorblendr.ui.fragments -import android.os.Bundle; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.fragment.app.Fragment +import com.drdisagree.colorblendr.databinding.FragmentOnboardingItem1Binding -import androidx.annotation.NonNull; -import androidx.fragment.app.Fragment; +class OnboardingItem1Fragment : Fragment() { -import com.drdisagree.colorblendr.databinding.FragmentOnboardingItem1Binding; + private lateinit var binding: FragmentOnboardingItem1Binding -public class OnboardingItem1Fragment extends Fragment { - - private FragmentOnboardingItem1Binding binding; - - @Override - public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - binding = FragmentOnboardingItem1Binding.inflate(inflater, container, false); - return binding.getRoot(); + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle? + ): View { + binding = FragmentOnboardingItem1Binding.inflate(inflater, container, false) + return binding.getRoot() } } \ No newline at end of file diff --git a/app/src/main/java/com/drdisagree/colorblendr/ui/fragments/OnboardingItem2Fragment.kt b/app/src/main/java/com/drdisagree/colorblendr/ui/fragments/OnboardingItem2Fragment.kt index 84f0329..c5d5359 100644 --- a/app/src/main/java/com/drdisagree/colorblendr/ui/fragments/OnboardingItem2Fragment.kt +++ b/app/src/main/java/com/drdisagree/colorblendr/ui/fragments/OnboardingItem2Fragment.kt @@ -1,155 +1,158 @@ -package com.drdisagree.colorblendr.ui.fragments; - -import android.Manifest; -import android.content.Intent; -import android.content.pm.PackageManager; -import android.net.Uri; -import android.os.Build; -import android.os.Bundle; -import android.provider.Settings; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; - -import androidx.activity.result.ActivityResultLauncher; -import androidx.activity.result.contract.ActivityResultContracts; -import androidx.annotation.NonNull; -import androidx.core.content.ContextCompat; -import androidx.fragment.app.Fragment; - -import com.drdisagree.colorblendr.BuildConfig; -import com.drdisagree.colorblendr.databinding.FragmentOnboardingItem2Binding; -import com.drdisagree.colorblendr.utils.AppUtil; - -import java.util.Map; - -public class OnboardingItem2Fragment extends Fragment { - - private FragmentOnboardingItem2Binding binding; - private boolean hasNotificationPermission = false; - private boolean hasMediaPermission = false; - private boolean hasStoragePermission = false; - - @Override - public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - binding = FragmentOnboardingItem2Binding.inflate(inflater, container, false); - - initPermissionsAndViews(); +package com.drdisagree.colorblendr.ui.fragments + +import android.Manifest +import android.content.Intent +import android.content.pm.PackageManager +import android.net.Uri +import android.os.Build +import android.os.Bundle +import android.provider.Settings +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.activity.result.ActivityResult +import androidx.activity.result.contract.ActivityResultContracts +import androidx.core.content.ContextCompat +import androidx.fragment.app.Fragment +import com.drdisagree.colorblendr.BuildConfig +import com.drdisagree.colorblendr.databinding.FragmentOnboardingItem2Binding +import com.drdisagree.colorblendr.utils.AppUtil.hasStoragePermission + +class OnboardingItem2Fragment : Fragment() { + + private lateinit var binding: FragmentOnboardingItem2Binding + private var hasNotificationPermission = false + private var hasMediaPermission = false + private var hasStoragePermission = false + + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle? + ): View { + binding = FragmentOnboardingItem2Binding.inflate(inflater, container, false) + + initPermissionsAndViews() // Post notifications permission if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { - binding.postNotifications.setOnClickListener(v -> { + binding.postNotifications.setOnClickListener { if (hasNotificationPermission) { - return; + return@setOnClickListener } - binding.postNotifications.setSelected(false); - - requestNotificationPermission.launch(Manifest.permission.POST_NOTIFICATIONS); - }); + binding.postNotifications.isSelected = false + requestNotificationPermission.launch(Manifest.permission.POST_NOTIFICATIONS) + } } else { - binding.postNotifications.setVisibility(View.GONE); + binding.postNotifications.visibility = View.GONE } // Read media images permission - binding.readMediaImages.setOnClickListener(v -> { + binding.readMediaImages.setOnClickListener { if (hasMediaPermission) { - return; + return@setOnClickListener } - - binding.readMediaImages.setSelected(false); - + binding.readMediaImages.isSelected = false requestMediaPermission.launch( - Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU ? - new String[]{ - Manifest.permission.READ_MEDIA_IMAGES - } : - new String[]{ - Manifest.permission.READ_EXTERNAL_STORAGE - }); - }); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) arrayOf( + Manifest.permission.READ_MEDIA_IMAGES + ) else arrayOf( + Manifest.permission.READ_EXTERNAL_STORAGE + ) + ) + } // All files access permission - binding.allFilesAccess.setOnClickListener(v -> { - binding.allFilesAccess.setSelected(false); - - Intent intent = new Intent(); - intent.setAction(Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION); - intent.setData(Uri.fromParts("package", BuildConfig.APPLICATION_ID, null)); - requestAllFilesPermission.launch(intent); - }); + binding.allFilesAccess.setOnClickListener { + binding.allFilesAccess.isSelected = false + val intent = Intent() + intent.setAction(Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION) + intent.setData( + Uri.fromParts( + "package", + BuildConfig.APPLICATION_ID, + null + ) + ) + requestAllFilesPermission.launch(intent) + } - return binding.getRoot(); + return binding.root } - private void initPermissionsAndViews() { + private fun initPermissionsAndViews() { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { - hasNotificationPermission = checkSelfPermission(Manifest.permission.POST_NOTIFICATIONS); - hasMediaPermission = checkSelfPermission(Manifest.permission.READ_MEDIA_IMAGES); + hasNotificationPermission = checkSelfPermission(Manifest.permission.POST_NOTIFICATIONS) + hasMediaPermission = checkSelfPermission(Manifest.permission.READ_MEDIA_IMAGES) } else { - hasNotificationPermission = true; - hasMediaPermission = checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE); + hasNotificationPermission = true + hasMediaPermission = checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE) } - hasStoragePermission = AppUtil.hasStoragePermission(); + hasStoragePermission = hasStoragePermission() if (hasNotificationPermission) { - binding.postNotifications.setSelected(true); + binding.postNotifications.isSelected = true } if (hasMediaPermission) { - binding.readMediaImages.setSelected(true); + binding.readMediaImages.isSelected = true } if (hasStoragePermission) { - binding.allFilesAccess.setSelected(true); + binding.allFilesAccess.isSelected = true } } - private final ActivityResultLauncher requestNotificationPermission = registerForActivityResult( - new ActivityResultContracts.RequestPermission(), - result -> { - if (result) { - binding.postNotifications.setSelected(true); - hasNotificationPermission = true; - } else { - binding.postNotifications.setSelected(false); - hasNotificationPermission = false; - } - } - ); - - private final ActivityResultLauncher requestMediaPermission = registerForActivityResult( - new ActivityResultContracts.RequestMultiplePermissions(), - this::handleMediaPermissionsResult - ); - - private void handleMediaPermissionsResult(Map result) { - for (Map.Entry pair : result.entrySet()) { - if (!pair.getValue()) { - binding.readMediaImages.setSelected(false); - hasMediaPermission = false; - return; + private val requestNotificationPermission = registerForActivityResult( + ActivityResultContracts.RequestPermission() + ) { result: Boolean -> + if (result) { + binding.postNotifications.isSelected = true + hasNotificationPermission = true + } else { + binding.postNotifications.isSelected = false + hasNotificationPermission = false + } + } + + private val requestMediaPermission = registerForActivityResult( + ActivityResultContracts.RequestMultiplePermissions() + ) { result: Map -> + this.handleMediaPermissionsResult( + result + ) + } + + private fun handleMediaPermissionsResult(result: Map) { + for ((_, value) in result) { + if (!value) { + binding.readMediaImages.isSelected = false + hasMediaPermission = false + return } - binding.readMediaImages.setSelected(true); - hasMediaPermission = true; + binding.readMediaImages.isSelected = true + hasMediaPermission = true } } - private final ActivityResultLauncher requestAllFilesPermission = registerForActivityResult( - new ActivityResultContracts.StartActivityForResult(), - result -> { - if (AppUtil.hasStoragePermission()) { - binding.allFilesAccess.setSelected(true); - hasStoragePermission = true; - } else { - binding.allFilesAccess.setSelected(false); - hasStoragePermission = false; - } - } - ); + private val requestAllFilesPermission = registerForActivityResult( + ActivityResultContracts.StartActivityForResult() + ) { _: ActivityResult? -> + if (hasStoragePermission()) { + binding.allFilesAccess.isSelected = true + hasStoragePermission = true + } else { + binding.allFilesAccess.isSelected = false + hasStoragePermission = false + } + } - private boolean checkSelfPermission(String permission) { - return ContextCompat.checkSelfPermission(requireContext(), permission) == PackageManager.PERMISSION_GRANTED; + private fun checkSelfPermission(permission: String): Boolean { + return ContextCompat.checkSelfPermission( + requireContext(), + permission + ) == PackageManager.PERMISSION_GRANTED } } \ No newline at end of file diff --git a/app/src/main/java/com/drdisagree/colorblendr/ui/fragments/OnboardingItem3Fragment.kt b/app/src/main/java/com/drdisagree/colorblendr/ui/fragments/OnboardingItem3Fragment.kt index 0f4c05b..2f5272c 100644 --- a/app/src/main/java/com/drdisagree/colorblendr/ui/fragments/OnboardingItem3Fragment.kt +++ b/app/src/main/java/com/drdisagree/colorblendr/ui/fragments/OnboardingItem3Fragment.kt @@ -1,34 +1,36 @@ -package com.drdisagree.colorblendr.ui.fragments; - -import android.os.Bundle; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; - -import androidx.annotation.NonNull; -import androidx.fragment.app.Fragment; - -import com.drdisagree.colorblendr.common.Const; -import com.drdisagree.colorblendr.databinding.FragmentOnboardingItem3Binding; - -public class OnboardingItem3Fragment extends Fragment { - - private FragmentOnboardingItem3Binding binding; - - @Override - public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - binding = FragmentOnboardingItem3Binding.inflate(inflater, container, false); - - binding.root.setOnClickListener(v -> { - Const.WORKING_METHOD = Const.WORK_METHOD.ROOT; - binding.shizuku.setSelected(false); - }); - - binding.shizuku.setOnClickListener(v -> { - Const.WORKING_METHOD = Const.WORK_METHOD.SHIZUKU; - binding.root.setSelected(false); - }); - - return binding.getRoot(); +package com.drdisagree.colorblendr.ui.fragments + +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.fragment.app.Fragment +import com.drdisagree.colorblendr.common.Const +import com.drdisagree.colorblendr.databinding.FragmentOnboardingItem3Binding + +class OnboardingItem3Fragment : Fragment() { + + private lateinit var binding: FragmentOnboardingItem3Binding + + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle? + ): View { + binding = FragmentOnboardingItem3Binding.inflate(inflater, container, false) + + binding.root.setOnClickListener { + Const.WORKING_METHOD = + Const.WorkMethod.ROOT + binding.shizuku.isSelected = false + } + + binding.shizuku.setOnClickListener { + Const.WORKING_METHOD = + Const.WorkMethod.SHIZUKU + binding.root.isSelected = false + } + + return binding.getRoot() } } \ No newline at end of file diff --git a/app/src/main/java/com/drdisagree/colorblendr/ui/fragments/PerAppThemeFragment.kt b/app/src/main/java/com/drdisagree/colorblendr/ui/fragments/PerAppThemeFragment.kt index 7c44cb3..2d8602a 100644 --- a/app/src/main/java/com/drdisagree/colorblendr/ui/fragments/PerAppThemeFragment.kt +++ b/app/src/main/java/com/drdisagree/colorblendr/ui/fragments/PerAppThemeFragment.kt @@ -1,301 +1,309 @@ -package com.drdisagree.colorblendr.ui.fragments; - -import static com.drdisagree.colorblendr.common.Const.APP_LIST_FILTER_METHOD; -import static com.drdisagree.colorblendr.common.Const.FABRICATED_OVERLAY_NAME_APPS; -import static com.drdisagree.colorblendr.common.Const.SHOW_PER_APP_THEME_WARN; - -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; -import android.content.IntentFilter; -import android.content.pm.ApplicationInfo; -import android.content.pm.PackageManager; -import android.graphics.drawable.Drawable; -import android.os.Bundle; -import android.os.Handler; -import android.os.Looper; -import android.text.Editable; -import android.text.TextWatcher; -import android.view.LayoutInflater; -import android.view.MenuItem; -import android.view.View; -import android.view.ViewGroup; -import android.view.ViewOutlineProvider; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.core.content.ContextCompat; -import androidx.fragment.app.Fragment; -import androidx.localbroadcastmanager.content.LocalBroadcastManager; -import androidx.recyclerview.widget.LinearLayoutManager; - -import com.drdisagree.colorblendr.R; -import com.drdisagree.colorblendr.common.Const.AppType; -import com.drdisagree.colorblendr.config.RPrefs; -import com.drdisagree.colorblendr.databinding.FragmentPerAppThemeBinding; -import com.drdisagree.colorblendr.ui.adapters.AppListAdapter; -import com.drdisagree.colorblendr.ui.models.AppInfoModel; -import com.drdisagree.colorblendr.utils.MiscUtil; -import com.drdisagree.colorblendr.utils.OverlayManager; -import com.google.android.material.dialog.MaterialAlertDialogBuilder; - -import java.util.ArrayList; -import java.util.List; - -import eightbitlab.com.blurview.RenderEffectBlur; - -public class PerAppThemeFragment extends Fragment { - - private FragmentPerAppThemeBinding binding; - private List appList; - private AppListAdapter adapter; - private final BroadcastReceiver packageReceiver = new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - AppType appType = AppType.values()[ - RPrefs.getInt(APP_LIST_FILTER_METHOD, AppType.ALL.ordinal()) - ]; - - initAppList(appType); +package com.drdisagree.colorblendr.ui.fragments + +import android.content.BroadcastReceiver +import android.content.Context +import android.content.DialogInterface +import android.content.Intent +import android.content.IntentFilter +import android.content.pm.ApplicationInfo +import android.content.pm.PackageManager +import android.os.Bundle +import android.os.Handler +import android.os.Looper +import android.text.Editable +import android.text.TextWatcher +import android.view.LayoutInflater +import android.view.MenuItem +import android.view.View +import android.view.ViewGroup +import android.view.ViewOutlineProvider +import androidx.core.content.ContextCompat +import androidx.fragment.app.Fragment +import androidx.localbroadcastmanager.content.LocalBroadcastManager +import androidx.recyclerview.widget.LinearLayoutManager +import com.drdisagree.colorblendr.R +import com.drdisagree.colorblendr.common.Const.APP_LIST_FILTER_METHOD +import com.drdisagree.colorblendr.common.Const.AppType +import com.drdisagree.colorblendr.common.Const.FABRICATED_OVERLAY_NAME_APPS +import com.drdisagree.colorblendr.common.Const.SHOW_PER_APP_THEME_WARN +import com.drdisagree.colorblendr.config.RPrefs.getBoolean +import com.drdisagree.colorblendr.config.RPrefs.getInt +import com.drdisagree.colorblendr.config.RPrefs.putBoolean +import com.drdisagree.colorblendr.config.RPrefs.putInt +import com.drdisagree.colorblendr.databinding.FragmentPerAppThemeBinding +import com.drdisagree.colorblendr.ui.adapters.AppListAdapter +import com.drdisagree.colorblendr.ui.models.AppInfoModel +import com.drdisagree.colorblendr.utils.MiscUtil.setToolbarTitle +import com.drdisagree.colorblendr.utils.OverlayManager.isOverlayEnabled +import com.google.android.material.dialog.MaterialAlertDialogBuilder +import eightbitlab.com.blurview.RenderEffectBlur +import java.util.Locale + +class PerAppThemeFragment : Fragment() { + + private lateinit var binding: FragmentPerAppThemeBinding + private var appList: List? = null + private var adapter: AppListAdapter? = null + + private val packageReceiver: BroadcastReceiver = object : BroadcastReceiver() { + override fun onReceive(context: Context, intent: Intent) { + val appType = AppType.entries[getInt( + APP_LIST_FILTER_METHOD, + AppType.ALL.ordinal + )] + + initAppList(appType) } - }; - private final TextWatcher textWatcher = new TextWatcher() { - @Override - public void beforeTextChanged(CharSequence s, int start, int count, int after) { + } + private val textWatcher: TextWatcher = object : TextWatcher { + override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) { } - @Override - public void onTextChanged(CharSequence s, int start, int before, int count) { + override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) { } - @Override - public void afterTextChanged(Editable s) { - if (!binding.searchBox.search.getText().toString().trim().isEmpty()) { - binding.searchBox.clear.setVisibility(View.VISIBLE); - filterList(binding.searchBox.search.getText().toString().trim()); + override fun afterTextChanged(s: Editable) { + if (binding.searchBox.search.text.toString().trim().isNotEmpty()) { + binding.searchBox.clear.visibility = View.VISIBLE + filterList(binding.searchBox.search.text.toString().trim()) } else { - binding.searchBox.clear.setVisibility(View.GONE); - filterList(""); + binding.searchBox.clear.visibility = View.GONE + filterList("") } } - }; + } - @Override - public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - binding = FragmentPerAppThemeBinding.inflate(inflater, container, false); + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle? + ): View { + binding = FragmentPerAppThemeBinding.inflate(inflater, container, false) - MiscUtil.setToolbarTitle(requireContext(), R.string.per_app_theme, true, binding.header.toolbar); + setToolbarTitle(requireContext(), R.string.per_app_theme, true, binding.header.toolbar) // Warning - if (!RPrefs.getBoolean(SHOW_PER_APP_THEME_WARN, true)) { - binding.warn.container.setVisibility(View.GONE); + if (!getBoolean(SHOW_PER_APP_THEME_WARN, true)) { + binding.warn.container.visibility = View.GONE + } + binding.warn.close.setOnClickListener { + Handler(Looper.getMainLooper()).postDelayed( + { + putBoolean(SHOW_PER_APP_THEME_WARN, false) + binding.warn.container.animate() + .translationX(binding.warn.container.width * 2f).alpha(0f).withEndAction { + binding.warn.container.visibility = View.GONE + }.start() + }, 50 + ) } - binding.warn.close.setOnClickListener(v -> new Handler(Looper.getMainLooper()).postDelayed(() -> { - RPrefs.putBoolean(SHOW_PER_APP_THEME_WARN, false); - binding.warn.container.animate().translationX(binding.warn.container.getWidth() * 2f).alpha(0f).withEndAction(() -> binding.warn.container.setVisibility(View.GONE)).start(); - }, 50)); - binding.recyclerView.setLayoutManager(new LinearLayoutManager(requireContext())); + binding.recyclerView.layoutManager = LinearLayoutManager(requireContext()) - return binding.getRoot(); + return binding.root } - @Override - public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { - super.onViewCreated(view, savedInstanceState); + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) - binding.searchBox.filter.setOnClickListener(v -> showFilterDialog()); + binding.searchBox.filter.setOnClickListener { showFilterDialog() } - AppType appType = AppType.values()[ - RPrefs.getInt(APP_LIST_FILTER_METHOD, AppType.ALL.ordinal()) - ]; + val appType = AppType.entries[getInt(APP_LIST_FILTER_METHOD, AppType.ALL.ordinal)] - initAppList(appType); - blurSearchView(); + initAppList(appType) + blurSearchView() } - private void initAppList(AppType appType) { - binding.recyclerView.setVisibility(View.GONE); - binding.progressBar.setVisibility(View.VISIBLE); - binding.searchBox.search.removeTextChangedListener(textWatcher); - - new Thread(() -> { - appList = getAllInstalledApps(requireContext(), appType); - adapter = new AppListAdapter(appList); + private fun initAppList(appType: AppType) { + binding.recyclerView.visibility = View.GONE + binding.progressBar.visibility = View.VISIBLE + binding.searchBox.search.removeTextChangedListener(textWatcher) + Thread { + appList = getAllInstalledApps(requireContext(), appType) + adapter = AppListAdapter(appList!!) try { - requireActivity().runOnUiThread(() -> { - binding.recyclerView.setAdapter(adapter); - - binding.searchBox.search.addTextChangedListener(textWatcher); + requireActivity().runOnUiThread { + binding.recyclerView.adapter = adapter + binding.searchBox.search.addTextChangedListener(textWatcher) - binding.progressBar.setVisibility(View.GONE); - binding.recyclerView.setVisibility(View.VISIBLE); + binding.progressBar.visibility = View.GONE + binding.recyclerView.visibility = View.VISIBLE - binding.searchBox.clear.setOnClickListener(v -> { - binding.searchBox.search.setText(""); - binding.searchBox.clear.setVisibility(View.GONE); - }); - - if (!binding.searchBox.search.getText().toString().trim().isEmpty()) { - filterList(binding.searchBox.search.getText().toString().trim()); + binding.searchBox.clear.setOnClickListener { + binding.searchBox.search.setText("") + binding.searchBox.clear.visibility = View.GONE + } + if (binding.searchBox.search.text.toString().trim().isNotEmpty()) { + filterList(binding.searchBox.search.text.toString().trim { it <= ' ' }) } - }); - } catch (Exception ignored) { + } + } catch (ignored: Exception) { // Fragment was not attached to activity } - }).start(); + }.start() } - private void filterList(String query) { + private fun filterList(query: String) { if (appList == null) { - return; + return } - List startsWithNameList = new ArrayList<>(); - List containsNameList = new ArrayList<>(); - List startsWithPackageNameList = new ArrayList<>(); - List containsPackageNameList = new ArrayList<>(); - - for (AppInfoModel app : appList) { - if (app.appName.toLowerCase().startsWith(query.toLowerCase())) { - startsWithNameList.add(app); - } else if (app.appName.toLowerCase().contains(query.toLowerCase())) { - containsNameList.add(app); - } else if (app.packageName.toLowerCase().startsWith(query.toLowerCase())) { - startsWithPackageNameList.add(app); - } else if (app.packageName.toLowerCase().contains(query.toLowerCase())) { - containsPackageNameList.add(app); + val startsWithNameList: MutableList = ArrayList() + val containsNameList: MutableList = ArrayList() + val startsWithPackageNameList: MutableList = ArrayList() + val containsPackageNameList: MutableList = ArrayList() + + for (app in appList!!) { + if (app.appName.lowercase(Locale.getDefault()) + .startsWith(query.lowercase(Locale.getDefault())) + ) { + startsWithNameList.add(app) + } else if (app.appName.lowercase(Locale.getDefault()) + .contains(query.lowercase(Locale.getDefault())) + ) { + containsNameList.add(app) + } else if (app.packageName.lowercase(Locale.getDefault()).startsWith( + query.lowercase( + Locale.getDefault() + ) + ) + ) { + startsWithPackageNameList.add(app) + } else if (app.packageName.lowercase(Locale.getDefault()).contains( + query.lowercase( + Locale.getDefault() + ) + ) + ) { + containsPackageNameList.add(app) } } - List filteredList = new ArrayList<>(); - filteredList.addAll(startsWithNameList); - filteredList.addAll(containsNameList); - filteredList.addAll(startsWithPackageNameList); - filteredList.addAll(containsPackageNameList); + val filteredList: MutableList = ArrayList() + filteredList.addAll(startsWithNameList) + filteredList.addAll(containsNameList) + filteredList.addAll(startsWithPackageNameList) + filteredList.addAll(containsPackageNameList) - adapter = new AppListAdapter(filteredList); - binding.recyclerView.setAdapter(adapter); + adapter = AppListAdapter(filteredList) + binding.recyclerView.adapter = adapter } - private static List getAllInstalledApps(Context context, AppType appType) { - List appList = new ArrayList<>(); - PackageManager packageManager = context.getPackageManager(); - - List applications = packageManager.getInstalledApplications(PackageManager.GET_META_DATA); - - for (ApplicationInfo appInfo : applications) { - String packageName = appInfo.packageName; + private fun blurSearchView() { + val background = ContextCompat.getDrawable(requireContext(), R.drawable.bg_searchbox) + binding.searchBox.blurView.setupWith(binding.root, RenderEffectBlur()) + .setFrameClearDrawable(background) + .setBlurRadius(20f) + binding.searchBox.blurView.outlineProvider = ViewOutlineProvider.BACKGROUND + binding.searchBox.blurView.clipToOutline = true + } - if (appType == AppType.LAUNCHABLE) { - Intent launchIntent = packageManager.getLaunchIntentForPackage(packageName); - if (launchIntent == null) { - continue; - } + private fun showFilterDialog() { + val items = arrayOf( + getString(R.string.filter_system_apps), + getString(R.string.filter_user_apps), + getString(R.string.filter_launchable_apps), + getString(R.string.filter_all) + ) + + val selectedFilterIndex = getInt(APP_LIST_FILTER_METHOD, AppType.ALL.ordinal) + + MaterialAlertDialogBuilder(requireContext()) + .setTitle(getString(R.string.filter_app_category)) + .setSingleChoiceItems( + items, + selectedFilterIndex + ) { dialog: DialogInterface, which: Int -> + putInt(APP_LIST_FILTER_METHOD, which) + val appType = AppType.entries[which] + + initAppList(appType) + dialog.dismiss() } + .setCancelable(true) + .show() + } - String appName = appInfo.loadLabel(packageManager).toString(); - Drawable appIcon = appInfo.loadIcon(packageManager); - boolean isSelected = OverlayManager.isOverlayEnabled( - String.format(FABRICATED_OVERLAY_NAME_APPS, packageName) - ); + override fun onResume() { + super.onResume() - boolean isSystemApp = (appInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0; + val intentFilterWithoutScheme = IntentFilter() + intentFilterWithoutScheme.addAction(Intent.ACTION_PACKAGE_ADDED) + intentFilterWithoutScheme.addAction(Intent.ACTION_PACKAGE_REMOVED) - boolean includeApp = switch (appType) { - case SYSTEM -> isSystemApp; - case USER -> !isSystemApp; - case LAUNCHABLE, ALL -> true; - }; + val intentFilterWithScheme = IntentFilter() + intentFilterWithScheme.addAction(Intent.ACTION_PACKAGE_ADDED) + intentFilterWithScheme.addAction(Intent.ACTION_PACKAGE_REMOVED) + intentFilterWithScheme.addDataScheme("package") - if (includeApp) { - AppInfoModel app = new AppInfoModel(appName, packageName, appIcon); - app.setSelected(isSelected); - appList.add(app); - } - } - - appList.sort((app1, app2) -> { - if (app1.isSelected() && !app2.isSelected()) { - return -1; - } else if (!app1.isSelected() && app2.isSelected()) { - return 1; - } else { - return app1.appName.compareToIgnoreCase(app2.appName); - } - }); - - return appList; + LocalBroadcastManager + .getInstance(requireContext()) + .registerReceiver(packageReceiver, intentFilterWithoutScheme) + LocalBroadcastManager + .getInstance(requireContext()) + .registerReceiver(packageReceiver, intentFilterWithScheme) } - private void blurSearchView() { - Drawable background = ContextCompat.getDrawable(requireContext(), R.drawable.bg_searchbox); - binding.searchBox.blurView.setupWith(binding.getRoot(), new RenderEffectBlur()) - .setFrameClearDrawable(background) - .setBlurRadius(20f); - binding.searchBox.blurView.setOutlineProvider(ViewOutlineProvider.BACKGROUND); - binding.searchBox.blurView.setClipToOutline(true); + override fun onDestroy() { + try { + LocalBroadcastManager + .getInstance(requireContext()) + .unregisterReceiver(packageReceiver) + } catch (ignored: Exception) { + // Receiver was not registered + } + super.onDestroy() } - private void showFilterDialog() { - String[] items = { - getString(R.string.filter_system_apps), - getString(R.string.filter_user_apps), - getString(R.string.filter_launchable_apps), - getString(R.string.filter_all) - }; - - int selectedFilterIndex = RPrefs.getInt(APP_LIST_FILTER_METHOD, AppType.ALL.ordinal()); + @Suppress("DEPRECATION") + @Deprecated("Deprecated in Java") + override fun onOptionsItemSelected(item: MenuItem): Boolean { + if (item.itemId == android.R.id.home) { + parentFragmentManager.popBackStackImmediate() + return true + } + return super.onOptionsItemSelected(item) + } - new MaterialAlertDialogBuilder(requireContext()) - .setTitle(getString(R.string.filter_app_category)) - .setSingleChoiceItems(items, selectedFilterIndex, (dialog, which) -> { - RPrefs.putInt(APP_LIST_FILTER_METHOD, which); + companion object { + private fun getAllInstalledApps(context: Context, appType: AppType): List { + val appList: MutableList = ArrayList() + val packageManager = context.packageManager - AppType appType = AppType.values()[which]; + val applications = packageManager.getInstalledApplications(PackageManager.GET_META_DATA) - initAppList(appType); + for (appInfo in applications) { + val packageName = appInfo.packageName - dialog.dismiss(); - }) - .setCancelable(true) - .show(); - } + if (appType == AppType.LAUNCHABLE) { + packageManager.getLaunchIntentForPackage(packageName) ?: continue + } - @Override - public void onResume() { - super.onResume(); + val appName = appInfo.loadLabel(packageManager).toString() + val appIcon = appInfo.loadIcon(packageManager) + val isSelected = isOverlayEnabled( + String.format(FABRICATED_OVERLAY_NAME_APPS, packageName) + ) - IntentFilter intentFilterWithoutScheme = new IntentFilter(); - intentFilterWithoutScheme.addAction(Intent.ACTION_PACKAGE_ADDED); - intentFilterWithoutScheme.addAction(Intent.ACTION_PACKAGE_REMOVED); + val isSystemApp = (appInfo.flags and ApplicationInfo.FLAG_SYSTEM) != 0 - IntentFilter intentFilterWithScheme = new IntentFilter(); - intentFilterWithScheme.addAction(Intent.ACTION_PACKAGE_ADDED); - intentFilterWithScheme.addAction(Intent.ACTION_PACKAGE_REMOVED); - intentFilterWithScheme.addDataScheme("package"); + val includeApp = when (appType) { + AppType.SYSTEM -> isSystemApp + AppType.USER -> !isSystemApp + AppType.LAUNCHABLE, AppType.ALL -> true + } - LocalBroadcastManager.getInstance(requireContext()).registerReceiver(packageReceiver, intentFilterWithoutScheme); - LocalBroadcastManager.getInstance(requireContext()).registerReceiver(packageReceiver, intentFilterWithScheme); - } + if (includeApp) { + val app = AppInfoModel(appName, packageName, appIcon) + app.isSelected = isSelected + appList.add(app) + } + } - @Override - public void onDestroy() { - try { - LocalBroadcastManager.getInstance(requireContext()).unregisterReceiver(packageReceiver); - } catch (Exception ignored) { - // Receiver was not registered - } - super.onDestroy(); - } + appList.sortWith(compareBy { !it.isSelected }.thenBy { it.appName.lowercase() }) - @Override - public boolean onOptionsItemSelected(@NonNull MenuItem item) { - if (item.getItemId() == android.R.id.home) { - getParentFragmentManager().popBackStackImmediate(); - return true; + return appList } - return super.onOptionsItemSelected(item); } } \ No newline at end of file diff --git a/app/src/main/java/com/drdisagree/colorblendr/ui/fragments/SettingsFragment.kt b/app/src/main/java/com/drdisagree/colorblendr/ui/fragments/SettingsFragment.kt index 5e270bb..5c3a463 100644 --- a/app/src/main/java/com/drdisagree/colorblendr/ui/fragments/SettingsFragment.kt +++ b/app/src/main/java/com/drdisagree/colorblendr/ui/fragments/SettingsFragment.kt @@ -1,387 +1,413 @@ -package com.drdisagree.colorblendr.ui.fragments; - -import static com.drdisagree.colorblendr.common.Const.FABRICATED_OVERLAY_NAME_SYSTEM; -import static com.drdisagree.colorblendr.common.Const.MANUAL_OVERRIDE_COLORS; -import static com.drdisagree.colorblendr.common.Const.MONET_ACCURATE_SHADES; -import static com.drdisagree.colorblendr.common.Const.MONET_LAST_UPDATED; -import static com.drdisagree.colorblendr.common.Const.MONET_PITCH_BLACK_THEME; -import static com.drdisagree.colorblendr.common.Const.MONET_SEED_COLOR; -import static com.drdisagree.colorblendr.common.Const.MONET_SEED_COLOR_ENABLED; -import static com.drdisagree.colorblendr.common.Const.SHIZUKU_THEMING_ENABLED; -import static com.drdisagree.colorblendr.common.Const.THEMING_ENABLED; -import static com.drdisagree.colorblendr.common.Const.TINT_TEXT_COLOR; -import static com.drdisagree.colorblendr.common.Const.WALLPAPER_COLOR_LIST; - -import android.animation.Animator; -import android.animation.AnimatorListenerAdapter; -import android.app.Activity; -import android.content.Intent; -import android.os.Bundle; -import android.os.Handler; -import android.os.Looper; -import android.util.Log; -import android.view.LayoutInflater; -import android.view.MenuItem; -import android.view.View; -import android.view.ViewGroup; -import android.widget.CompoundButton; -import android.widget.Toast; - -import androidx.activity.result.ActivityResultLauncher; -import androidx.activity.result.contract.ActivityResultContracts; -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.fragment.app.Fragment; -import androidx.lifecycle.ViewModelProvider; - -import com.drdisagree.colorblendr.ColorBlendr; -import com.drdisagree.colorblendr.R; -import com.drdisagree.colorblendr.common.Const; -import com.drdisagree.colorblendr.config.RPrefs; -import com.drdisagree.colorblendr.databinding.FragmentSettingsBinding; -import com.drdisagree.colorblendr.ui.viewmodels.SharedViewModel; -import com.drdisagree.colorblendr.utils.ColorUtil; -import com.drdisagree.colorblendr.utils.MiscUtil; -import com.drdisagree.colorblendr.utils.OverlayManager; -import com.google.android.material.dialog.MaterialAlertDialogBuilder; -import com.google.android.material.snackbar.Snackbar; -import com.google.gson.reflect.TypeToken; - -import java.util.ArrayList; -import java.util.Objects; -import java.util.concurrent.Executors; - -public class SettingsFragment extends Fragment { - - private static final String TAG = SettingsFragment.class.getSimpleName(); - private FragmentSettingsBinding binding; - private SharedViewModel sharedViewModel; - private boolean isMasterSwitchEnabled = true; - private static final String[][] colorNames = ColorUtil.getColorNames(); - private final boolean notShizukuMode = Const.getWorkingMethod() != Const.WORK_METHOD.SHIZUKU; - private final CompoundButton.OnCheckedChangeListener masterSwitch = (buttonView, isChecked) -> { - if (!isMasterSwitchEnabled) { - buttonView.setChecked(!isChecked); - return; - } - - RPrefs.putBoolean(THEMING_ENABLED, isChecked); - RPrefs.putBoolean(SHIZUKU_THEMING_ENABLED, isChecked); - RPrefs.putLong(MONET_LAST_UPDATED, System.currentTimeMillis()); - - new Handler(Looper.getMainLooper()).postDelayed(() -> { - try { - if (isChecked) { - OverlayManager.applyFabricatedColors(requireContext()); - } else { - OverlayManager.removeFabricatedColors(requireContext()); - } +package com.drdisagree.colorblendr.ui.fragments + +import android.animation.Animator +import android.animation.AnimatorListenerAdapter +import android.app.Activity +import android.content.DialogInterface +import android.content.Intent +import android.os.Bundle +import android.os.Handler +import android.os.Looper +import android.util.Log +import android.view.LayoutInflater +import android.view.MenuItem +import android.view.View +import android.view.ViewGroup +import android.widget.CompoundButton +import android.widget.Toast +import androidx.activity.result.ActivityResult +import androidx.activity.result.ActivityResultLauncher +import androidx.activity.result.contract.ActivityResultContracts +import androidx.fragment.app.Fragment +import androidx.lifecycle.ViewModelProvider +import com.drdisagree.colorblendr.ColorBlendr.Companion.appContext +import com.drdisagree.colorblendr.R +import com.drdisagree.colorblendr.common.Const +import com.drdisagree.colorblendr.common.Const.FABRICATED_OVERLAY_NAME_SYSTEM +import com.drdisagree.colorblendr.common.Const.MANUAL_OVERRIDE_COLORS +import com.drdisagree.colorblendr.common.Const.MONET_ACCURATE_SHADES +import com.drdisagree.colorblendr.common.Const.MONET_LAST_UPDATED +import com.drdisagree.colorblendr.common.Const.MONET_PITCH_BLACK_THEME +import com.drdisagree.colorblendr.common.Const.MONET_SEED_COLOR +import com.drdisagree.colorblendr.common.Const.MONET_SEED_COLOR_ENABLED +import com.drdisagree.colorblendr.common.Const.SHIZUKU_THEMING_ENABLED +import com.drdisagree.colorblendr.common.Const.THEMING_ENABLED +import com.drdisagree.colorblendr.common.Const.TINT_TEXT_COLOR +import com.drdisagree.colorblendr.common.Const.WALLPAPER_COLOR_LIST +import com.drdisagree.colorblendr.common.Const.workingMethod +import com.drdisagree.colorblendr.config.RPrefs +import com.drdisagree.colorblendr.config.RPrefs.backupPrefs +import com.drdisagree.colorblendr.config.RPrefs.clearPref +import com.drdisagree.colorblendr.config.RPrefs.getBoolean +import com.drdisagree.colorblendr.config.RPrefs.getInt +import com.drdisagree.colorblendr.config.RPrefs.putBoolean +import com.drdisagree.colorblendr.config.RPrefs.putInt +import com.drdisagree.colorblendr.config.RPrefs.putLong +import com.drdisagree.colorblendr.config.RPrefs.restorePrefs +import com.drdisagree.colorblendr.databinding.FragmentSettingsBinding +import com.drdisagree.colorblendr.ui.viewmodels.SharedViewModel +import com.drdisagree.colorblendr.utils.ColorUtil +import com.drdisagree.colorblendr.utils.MiscUtil.setToolbarTitle +import com.drdisagree.colorblendr.utils.OverlayManager.applyFabricatedColors +import com.drdisagree.colorblendr.utils.OverlayManager.isOverlayEnabled +import com.drdisagree.colorblendr.utils.OverlayManager.removeFabricatedColors +import com.google.android.material.dialog.MaterialAlertDialogBuilder +import com.google.android.material.snackbar.Snackbar +import com.google.gson.reflect.TypeToken +import java.util.concurrent.Executors + +class SettingsFragment : Fragment() { + + private lateinit var binding: FragmentSettingsBinding + private var sharedViewModel: SharedViewModel? = null + private var isMasterSwitchEnabled: Boolean = true + private val notShizukuMode: Boolean = workingMethod != Const.WorkMethod.SHIZUKU + + private val masterSwitch: CompoundButton.OnCheckedChangeListener = + CompoundButton.OnCheckedChangeListener { buttonView: CompoundButton, isChecked: Boolean -> + if (!isMasterSwitchEnabled) { + buttonView.setChecked(!isChecked) + return@OnCheckedChangeListener + } + putBoolean(THEMING_ENABLED, isChecked) + putBoolean(SHIZUKU_THEMING_ENABLED, isChecked) + putLong(MONET_LAST_UPDATED, System.currentTimeMillis()) + Handler(Looper.getMainLooper()).postDelayed({ + try { + if (isChecked) { + applyFabricatedColors(requireContext()) + } else { + removeFabricatedColors(requireContext()) + } - isMasterSwitchEnabled = false; - boolean isOverlayEnabled = OverlayManager.isOverlayEnabled(FABRICATED_OVERLAY_NAME_SYSTEM) || - RPrefs.getBoolean(SHIZUKU_THEMING_ENABLED, true); - buttonView.setChecked(isOverlayEnabled); - isMasterSwitchEnabled = true; - - if (isChecked != isOverlayEnabled) { - Toast.makeText( - requireContext(), - getString(R.string.something_went_wrong), - Toast.LENGTH_SHORT - ) - .show(); + isMasterSwitchEnabled = false + val isOverlayEnabled: Boolean = + isOverlayEnabled(FABRICATED_OVERLAY_NAME_SYSTEM) || + getBoolean(SHIZUKU_THEMING_ENABLED, true) + buttonView.setChecked(isOverlayEnabled) + isMasterSwitchEnabled = true + + if (isChecked != isOverlayEnabled) { + Toast.makeText( + requireContext(), + getString(R.string.something_went_wrong), + Toast.LENGTH_SHORT + ) + .show() + } + } catch (ignored: Exception) { } - } catch (Exception ignored) { - } - }, 300); - }; + }, 300) + } - @Override - public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - binding = FragmentSettingsBinding.inflate(inflater, container, false); + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle? + ): View { + binding = FragmentSettingsBinding.inflate(inflater, container, false) - MiscUtil.setToolbarTitle(requireContext(), R.string.settings, true, binding.header.toolbar); + setToolbarTitle(requireContext(), R.string.settings, true, binding.header.toolbar) // ColorBlendr service - binding.themingEnabled.setTitle(getString(R.string.app_service_title, getString(R.string.app_name))); - binding.themingEnabled.setSwitchChecked( - (RPrefs.getBoolean(THEMING_ENABLED, true) && - OverlayManager.isOverlayEnabled(FABRICATED_OVERLAY_NAME_SYSTEM)) || - RPrefs.getBoolean(SHIZUKU_THEMING_ENABLED, true) - ); - binding.themingEnabled.setSwitchChangeListener(masterSwitch); + binding.themingEnabled.setTitle( + getString( + R.string.app_service_title, + getString(R.string.app_name) + ) + ) + binding.themingEnabled.isSwitchChecked = (getBoolean(THEMING_ENABLED, true) && + isOverlayEnabled(FABRICATED_OVERLAY_NAME_SYSTEM)) || + getBoolean(SHIZUKU_THEMING_ENABLED, true) + + binding.themingEnabled.setSwitchChangeListener(masterSwitch) // Accurate shades - binding.accurateShades.setSwitchChecked(RPrefs.getBoolean(MONET_ACCURATE_SHADES, true)); - binding.accurateShades.setSwitchChangeListener((buttonView, isChecked) -> { - RPrefs.putBoolean(MONET_ACCURATE_SHADES, isChecked); - sharedViewModel.setBooleanState(MONET_ACCURATE_SHADES, isChecked); - applyFabricatedColors(); - }); - binding.accurateShades.setEnabled(notShizukuMode); + binding.accurateShades.isSwitchChecked = getBoolean(MONET_ACCURATE_SHADES, true) + binding.accurateShades.setSwitchChangeListener { _: CompoundButton?, isChecked: Boolean -> + putBoolean(MONET_ACCURATE_SHADES, isChecked) + sharedViewModel!!.setBooleanState(MONET_ACCURATE_SHADES, isChecked) + applyFabricatedColors() + } + binding.accurateShades.setEnabled(notShizukuMode) // Pitch black theme - binding.pitchBlackTheme.setSwitchChecked(RPrefs.getBoolean(MONET_PITCH_BLACK_THEME, false)); - binding.pitchBlackTheme.setSwitchChangeListener((buttonView, isChecked) -> { - RPrefs.putBoolean(MONET_PITCH_BLACK_THEME, isChecked); - applyFabricatedColors(); - }); - binding.pitchBlackTheme.setEnabled(notShizukuMode); + binding.pitchBlackTheme.isSwitchChecked = getBoolean(MONET_PITCH_BLACK_THEME, false) + binding.pitchBlackTheme.setSwitchChangeListener { _: CompoundButton?, isChecked: Boolean -> + putBoolean(MONET_PITCH_BLACK_THEME, isChecked) + applyFabricatedColors() + } + binding.pitchBlackTheme.setEnabled(notShizukuMode) // Custom primary color - binding.customPrimaryColor.setSwitchChecked(RPrefs.getBoolean(MONET_SEED_COLOR_ENABLED, false)); - binding.customPrimaryColor.setSwitchChangeListener((buttonView, isChecked) -> { - RPrefs.putBoolean(MONET_SEED_COLOR_ENABLED, isChecked); - sharedViewModel.setVisibilityState(MONET_SEED_COLOR_ENABLED, isChecked ? View.VISIBLE : View.GONE); - + binding.customPrimaryColor.isSwitchChecked = getBoolean(MONET_SEED_COLOR_ENABLED, false) + binding.customPrimaryColor.setSwitchChangeListener { _: CompoundButton?, isChecked: Boolean -> + putBoolean(MONET_SEED_COLOR_ENABLED, isChecked) + sharedViewModel!!.setVisibilityState( + MONET_SEED_COLOR_ENABLED, + if (isChecked) View.VISIBLE else View.GONE + ) if (!isChecked) { - String wallpaperColors = RPrefs.getString(WALLPAPER_COLOR_LIST, null); - ArrayList wallpaperColorList = Const.GSON.fromJson( - wallpaperColors, - new TypeToken>() { - }.getType() - ); - RPrefs.putInt(MONET_SEED_COLOR, wallpaperColorList.get(0)); - applyFabricatedColors(); + val wallpaperColors: String? = RPrefs.getString(WALLPAPER_COLOR_LIST, null) + val wallpaperColorList: ArrayList = Const.GSON.fromJson( + wallpaperColors, + object : TypeToken?>() { + }.type + ) + putInt(MONET_SEED_COLOR, wallpaperColorList[0]) + applyFabricatedColors() } - }); + } // Tint text color - binding.tintTextColor.setSwitchChecked(RPrefs.getBoolean(TINT_TEXT_COLOR, true)); - binding.tintTextColor.setSwitchChangeListener((buttonView, isChecked) -> { - RPrefs.putBoolean(TINT_TEXT_COLOR, isChecked); - applyFabricatedColors(); - }); - binding.tintTextColor.setEnabled(notShizukuMode); + binding.tintTextColor.isSwitchChecked = getBoolean(TINT_TEXT_COLOR, true) + binding.tintTextColor.setSwitchChangeListener { _: CompoundButton?, isChecked: Boolean -> + putBoolean(TINT_TEXT_COLOR, isChecked) + applyFabricatedColors() + } + binding.tintTextColor.setEnabled(notShizukuMode) // Override colors manually - binding.overrideColorsManually.setSwitchChecked(RPrefs.getBoolean(MANUAL_OVERRIDE_COLORS, false)); - binding.overrideColorsManually.setSwitchChangeListener((buttonView, isChecked) -> { + binding.overrideColorsManually.isSwitchChecked = getBoolean(MANUAL_OVERRIDE_COLORS, false) + binding.overrideColorsManually.setSwitchChangeListener { _: CompoundButton?, isChecked: Boolean -> if (isChecked) { - RPrefs.putBoolean(MANUAL_OVERRIDE_COLORS, true); + putBoolean(MANUAL_OVERRIDE_COLORS, true) } else { if (shouldConfirmBeforeClearing()) { - new MaterialAlertDialogBuilder(requireContext()) - .setTitle(getString(R.string.confirmation_title)) - .setMessage(getString(R.string.this_cannot_be_undone)) - .setPositiveButton(getString(android.R.string.ok), - (dialog, which) -> { - dialog.dismiss(); - RPrefs.putBoolean(MANUAL_OVERRIDE_COLORS, false); - if (numColorsOverridden() != 0) { - clearCustomColors(); - applyFabricatedColors(); - } - }) - .setNegativeButton(getString(android.R.string.cancel), (dialog, which) -> { - dialog.dismiss(); - binding.overrideColorsManually.setSwitchChecked(true); - }) - .show(); + MaterialAlertDialogBuilder(requireContext()) + .setTitle(getString(R.string.confirmation_title)) + .setMessage(getString(R.string.this_cannot_be_undone)) + .setPositiveButton(getString(android.R.string.ok)) { dialog: DialogInterface, _: Int -> + dialog.dismiss() + putBoolean(MANUAL_OVERRIDE_COLORS, false) + if (numColorsOverridden() != 0) { + clearCustomColors() + applyFabricatedColors() + } + } + .setNegativeButton(getString(android.R.string.cancel)) { dialog: DialogInterface, _: Int -> + dialog.dismiss() + binding.overrideColorsManually.isSwitchChecked = true + } + .show() } else { - RPrefs.putBoolean(MANUAL_OVERRIDE_COLORS, false); + putBoolean(MANUAL_OVERRIDE_COLORS, false) if (numColorsOverridden() != 0) { - clearCustomColors(); - applyFabricatedColors(); + clearCustomColors() + applyFabricatedColors() } } } - }); - binding.overrideColorsManually.setEnabled(notShizukuMode); + } + binding.overrideColorsManually.setEnabled(notShizukuMode) - binding.backupRestore.container.setOnClickListener(v -> crossfade(binding.backupRestore.backupRestoreButtons)); - binding.backupRestore.backup.setOnClickListener(v -> backupRestoreSettings(true)); - binding.backupRestore.restore.setOnClickListener(v -> backupRestoreSettings(false)); + binding.backupRestore.container.setOnClickListener { + crossfade( + binding.backupRestore.backupRestoreButtons + ) + } + binding.backupRestore.backup.setOnClickListener { + backupRestoreSettings( + true + ) + } + binding.backupRestore.restore.setOnClickListener { + backupRestoreSettings( + false + ) + } // About this app - binding.about.setOnClickListener(v -> HomeFragment.replaceFragment(new AboutFragment())); + binding.about.setOnClickListener { + HomeFragment.replaceFragment( + AboutFragment() + ) + } - return binding.getRoot(); + return binding.getRoot() } - @Override - public void onCreate(@Nullable Bundle savedInstanceState) { - super.onCreate(savedInstanceState); + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) - sharedViewModel = new ViewModelProvider(requireActivity()).get(SharedViewModel.class); + sharedViewModel = ViewModelProvider(requireActivity())[SharedViewModel::class.java] } - private void crossfade(View view) { + private fun crossfade(view: View) { try { - int animTime = getResources().getInteger(android.R.integer.config_mediumAnimTime); - if (view.getVisibility() == View.GONE) { - view.setAlpha(0f); - view.setVisibility(View.VISIBLE); + val animTime: Int = resources.getInteger(android.R.integer.config_mediumAnimTime) + if (view.visibility == View.GONE) { + view.setAlpha(0f) + view.visibility = View.VISIBLE view.animate() - .alpha(1f) - .setDuration(animTime) - .setListener(null); + .alpha(1f) + .setDuration(animTime.toLong()) + .setListener(null) } else { view.animate() - .alpha(0f) - .setDuration(animTime) - .setListener(new AnimatorListenerAdapter() { - @Override - public void onAnimationEnd(Animator animation) { - super.onAnimationEnd(animation); - try { - view.setAlpha(0f); - view.setVisibility(View.GONE); - } catch (Exception ignored) { - } + .alpha(0f) + .setDuration(animTime.toLong()) + .setListener(object : AnimatorListenerAdapter() { + override fun onAnimationEnd(animation: Animator) { + super.onAnimationEnd(animation) + try { + view.setAlpha(0f) + view.visibility = View.GONE + } catch (ignored: Exception) { } - }); + } + }) } - } catch (Exception ignored) { + } catch (ignored: Exception) { } } - private void backupRestoreSettings(boolean isBackingUp) { - Intent fileIntent = new Intent(); - fileIntent.setAction(isBackingUp ? Intent.ACTION_CREATE_DOCUMENT : Intent.ACTION_GET_CONTENT); - fileIntent.setType("*/*"); - fileIntent.putExtra(Intent.EXTRA_TITLE, "theme_config" + ".colorblendr"); + private fun backupRestoreSettings(isBackingUp: Boolean) { + val fileIntent = Intent().apply { + setAction(if (isBackingUp) Intent.ACTION_CREATE_DOCUMENT else Intent.ACTION_GET_CONTENT) + setType("*/*") + putExtra(Intent.EXTRA_TITLE, "theme_config" + ".colorblendr") + } if (isBackingUp) { - startBackupActivityIntent.launch(fileIntent); + startBackupActivityIntent.launch(fileIntent) } else { - startRestoreActivityIntent.launch(fileIntent); + startRestoreActivityIntent.launch(fileIntent) } } - ActivityResultLauncher startBackupActivityIntent = registerForActivityResult( - new ActivityResultContracts.StartActivityForResult(), - result -> { - if (result.getResultCode() == Activity.RESULT_OK) { - Intent data = result.getData(); - if (data == null || data.getData() == null) return; - - Executors.newSingleThreadExecutor().execute(() -> { - try { - RPrefs.backupPrefs( - Objects.requireNonNull( - ColorBlendr.getAppContext() - .getContentResolver() - .openOutputStream(data.getData()) - ) - ); - - Snackbar.make( - binding.getRoot(), - getString(R.string.backup_success), - Snackbar.LENGTH_LONG - ) - .setAction( - getString(R.string.dismiss), - v -> { - } - ) - .show(); - } catch (Exception exception) { - Snackbar.make( - binding.getRoot(), - getString(R.string.backup_fail), - Snackbar.LENGTH_INDEFINITE - ) - .setAction( - getString(R.string.retry), - v -> backupRestoreSettings(true) - ) - .show(); + private var startBackupActivityIntent: ActivityResultLauncher = + registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result: ActivityResult -> + if (result.resultCode == Activity.RESULT_OK) { + val data: Intent? = result.data + if (data?.data == null) return@registerForActivityResult + + Executors.newSingleThreadExecutor().execute { + try { + backupPrefs( + appContext + .contentResolver + .openOutputStream(data.data!!)!! + ) + + Snackbar + .make( + binding.getRoot(), + getString(R.string.backup_success), + Snackbar.LENGTH_LONG + ) + .setAction(getString(R.string.dismiss)) { } + .show() + } catch (exception: Exception) { + Snackbar + .make( + binding.getRoot(), + getString(R.string.backup_fail), + Snackbar.LENGTH_INDEFINITE + ) + .setAction(getString(R.string.retry)) { backupRestoreSettings(true) } + .show() - Log.e(TAG, "startBackupActivityIntent: ", exception); - } - }); - } - }); - - ActivityResultLauncher startRestoreActivityIntent = registerForActivityResult( - new ActivityResultContracts.StartActivityForResult(), - result -> { - if (result.getResultCode() == Activity.RESULT_OK) { - Intent data = result.getData(); - if (data == null || data.getData() == null) return; - - new MaterialAlertDialogBuilder(requireContext()) - .setTitle(getString(R.string.confirmation_title)) - .setMessage(getString(R.string.confirmation_desc)) - .setPositiveButton(getString(android.R.string.ok), - (dialog, which) -> { - dialog.dismiss(); - Executors.newSingleThreadExecutor().execute(() -> { - try { - RPrefs.restorePrefs( - Objects.requireNonNull( - ColorBlendr.getAppContext() - .getContentResolver() - .openInputStream(data.getData()) - ) - ); - - try { - OverlayManager.applyFabricatedColors(requireContext()); - } catch (Exception ignored) { - } - } catch (Exception exception) { - Snackbar.make( - binding.getRoot(), - getString(R.string.restore_fail), - Snackbar.LENGTH_INDEFINITE - ) - .setAction( - getString(R.string.retry), - v -> backupRestoreSettings(false) - ) - .show(); - - Log.e(TAG, "startBackupActivityIntent: ", exception); - } - }); - }) - .setNegativeButton(getString(android.R.string.cancel), (dialog, which) -> dialog.dismiss()) - .show(); + Log.e(TAG, "startBackupActivityIntent: ", exception) + } } - }); - - @Override - public boolean onOptionsItemSelected(@NonNull MenuItem item) { - if (item.getItemId() == android.R.id.home) { - getParentFragmentManager().popBackStackImmediate(); - return true; + } } - return super.onOptionsItemSelected(item); - } - public static void clearCustomColors() { - for (String[] colorName : colorNames) { - for (String resource : colorName) { - RPrefs.clearPref(resource); + private var startRestoreActivityIntent: ActivityResultLauncher = + registerForActivityResult( + ActivityResultContracts.StartActivityForResult() + ) { result: ActivityResult -> + if (result.resultCode == Activity.RESULT_OK) { + val data: Intent? = result.data + if (data?.data == null) return@registerForActivityResult + + MaterialAlertDialogBuilder(requireContext()) + .setTitle(getString(R.string.confirmation_title)) + .setMessage(getString(R.string.confirmation_desc)) + .setPositiveButton(getString(android.R.string.ok)) { dialog: DialogInterface, _: Int -> + dialog.dismiss() + Executors.newSingleThreadExecutor().execute { + try { + restorePrefs( + appContext + .contentResolver + .openInputStream(data.data!!)!! + ) + + try { + applyFabricatedColors(requireContext()) + } catch (ignored: Exception) { + } + } catch (exception: Exception) { + Snackbar + .make( + binding.getRoot(), + getString(R.string.restore_fail), + Snackbar.LENGTH_INDEFINITE + ) + .setAction(getString(R.string.retry)) { + backupRestoreSettings( + false + ) + } + .show() + + Log.e(TAG, "startBackupActivityIntent: ", exception) + } + } + } + .setNegativeButton(getString(android.R.string.cancel)) { dialog: DialogInterface, _: Int -> dialog.dismiss() } + .show() } } + + @Suppress("DEPRECATION") + @Deprecated("Deprecated in Java") + override fun onOptionsItemSelected(item: MenuItem): Boolean { + if (item.itemId == android.R.id.home) { + getParentFragmentManager().popBackStackImmediate() + return true + } + return super.onOptionsItemSelected(item) } - private boolean shouldConfirmBeforeClearing() { - return numColorsOverridden() > 5; + private fun shouldConfirmBeforeClearing(): Boolean { + return numColorsOverridden() > 5 } - private int numColorsOverridden() { - int colorOverridden = 0; - for (String[] colorName : colorNames) { - for (String resource : colorName) { - if (RPrefs.getInt(resource, Integer.MIN_VALUE) != Integer.MIN_VALUE) { - colorOverridden++; + private fun numColorsOverridden(): Int { + var colorOverridden = 0 + + for (colorName: Array in colorNames) { + for (resource: String in colorName) { + if (getInt(resource, Int.MIN_VALUE) != Int.MIN_VALUE) { + colorOverridden++ } } } - return colorOverridden; + return colorOverridden } - private void applyFabricatedColors() { - RPrefs.putLong(MONET_LAST_UPDATED, System.currentTimeMillis()); - new Handler(Looper.getMainLooper()).postDelayed(() -> { + private fun applyFabricatedColors() { + putLong(MONET_LAST_UPDATED, System.currentTimeMillis()) + Handler(Looper.getMainLooper()).postDelayed({ try { - OverlayManager.applyFabricatedColors(requireContext()); - } catch (Exception ignored) { + applyFabricatedColors(requireContext()) + } catch (ignored: Exception) { } - }, 300); + }, 300) + } + + companion object { + private val TAG: String = SettingsFragment::class.java.getSimpleName() + private val colorNames: Array> = ColorUtil.colorNames + + fun clearCustomColors() { + for (colorName: Array in colorNames) { + for (resource: String in colorName) { + clearPref(resource) + } + } + } } } \ No newline at end of file diff --git a/app/src/main/java/com/drdisagree/colorblendr/ui/fragments/StylesFragment.kt b/app/src/main/java/com/drdisagree/colorblendr/ui/fragments/StylesFragment.kt index 7e8db22..03146f4 100644 --- a/app/src/main/java/com/drdisagree/colorblendr/ui/fragments/StylesFragment.kt +++ b/app/src/main/java/com/drdisagree/colorblendr/ui/fragments/StylesFragment.kt @@ -1,183 +1,207 @@ -package com.drdisagree.colorblendr.ui.fragments; - -import static com.drdisagree.colorblendr.common.Const.MONET_LAST_UPDATED; -import static com.drdisagree.colorblendr.common.Const.MONET_STYLE; -import static com.drdisagree.colorblendr.common.Const.MONET_STYLE_ORIGINAL_NAME; - -import android.os.Build; -import android.os.Bundle; -import android.view.LayoutInflater; -import android.view.MenuItem; -import android.view.View; -import android.view.ViewGroup; - -import androidx.annotation.NonNull; -import androidx.annotation.StringRes; -import androidx.fragment.app.Fragment; - -import com.drdisagree.colorblendr.R; -import com.drdisagree.colorblendr.common.Const; -import com.drdisagree.colorblendr.config.RPrefs; -import com.drdisagree.colorblendr.databinding.FragmentStylesBinding; -import com.drdisagree.colorblendr.utils.MiscUtil; - -public class StylesFragment extends Fragment { - - private FragmentStylesBinding binding; - private final boolean notShizukuMode = Const.getWorkingMethod() != Const.WORK_METHOD.SHIZUKU; - private final boolean isAtleastA13 = notShizukuMode || Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU; - private final boolean isAtleastA14 = notShizukuMode || Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE; - - @Override - public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - binding = FragmentStylesBinding.inflate(inflater, container, false); - - MiscUtil.setToolbarTitle(requireContext(), R.string.styles, true, binding.header.toolbar); - - String selectedStyle = RPrefs.getString(MONET_STYLE, null); - - binding.monetNeutral.setSelected(getString(R.string.monet_neutral).equals(selectedStyle)); - binding.monetNeutral.setOnClickListener(v -> { - binding.monetNeutral.setSelected(true); - unSelectOthers(binding.monetNeutral); - RPrefs.putLong(MONET_LAST_UPDATED, System.currentTimeMillis()); - RPrefs.putString(MONET_STYLE_ORIGINAL_NAME, getOriginalName(R.string.monet_neutral)); - binding.monetNeutral.applyColorScheme(); - }); - binding.monetNeutral.setEnabled(isAtleastA13); - - binding.monetMonochrome.setSelected(getString(R.string.monet_monochrome).equals(selectedStyle)); - binding.monetMonochrome.setOnClickListener(v -> { - binding.monetMonochrome.setSelected(true); - unSelectOthers(binding.monetMonochrome); - RPrefs.putLong(MONET_LAST_UPDATED, System.currentTimeMillis()); - RPrefs.putString(MONET_STYLE_ORIGINAL_NAME, getOriginalName(R.string.monet_monochrome)); - binding.monetMonochrome.applyColorScheme(); - }); - binding.monetMonochrome.setEnabled(isAtleastA14); - - binding.monetTonalspot.setSelected(getString(R.string.monet_tonalspot).equals(selectedStyle) || selectedStyle == null); - binding.monetTonalspot.setOnClickListener(v -> { - binding.monetTonalspot.setSelected(true); - unSelectOthers(binding.monetTonalspot); - RPrefs.putLong(MONET_LAST_UPDATED, System.currentTimeMillis()); - RPrefs.putString(MONET_STYLE_ORIGINAL_NAME, getOriginalName(R.string.monet_tonalspot)); - binding.monetTonalspot.applyColorScheme(); - }); - - binding.monetVibrant.setSelected(getString(R.string.monet_vibrant).equals(selectedStyle)); - binding.monetVibrant.setOnClickListener(v -> { - binding.monetVibrant.setSelected(true); - unSelectOthers(binding.monetVibrant); - RPrefs.putLong(MONET_LAST_UPDATED, System.currentTimeMillis()); - RPrefs.putString(MONET_STYLE_ORIGINAL_NAME, getOriginalName(R.string.monet_vibrant)); - binding.monetVibrant.applyColorScheme(); - }); - binding.monetVibrant.setEnabled(isAtleastA13); - - binding.monetRainbow.setSelected(getString(R.string.monet_rainbow).equals(selectedStyle)); - binding.monetRainbow.setOnClickListener(v -> { - binding.monetRainbow.setSelected(true); - unSelectOthers(binding.monetRainbow); - RPrefs.putLong(MONET_LAST_UPDATED, System.currentTimeMillis()); - RPrefs.putString(MONET_STYLE_ORIGINAL_NAME, getOriginalName(R.string.monet_rainbow)); - binding.monetRainbow.applyColorScheme(); - }); - binding.monetRainbow.setEnabled(isAtleastA13); - - binding.monetExpressive.setSelected(getString(R.string.monet_expressive).equals(selectedStyle)); - binding.monetExpressive.setOnClickListener(v -> { - binding.monetExpressive.setSelected(true); - unSelectOthers(binding.monetExpressive); - RPrefs.putLong(MONET_LAST_UPDATED, System.currentTimeMillis()); - RPrefs.putString(MONET_STYLE_ORIGINAL_NAME, getOriginalName(R.string.monet_expressive)); - binding.monetExpressive.applyColorScheme(); - }); - binding.monetExpressive.setEnabled(isAtleastA13); - - binding.monetFidelity.setSelected(getString(R.string.monet_fidelity).equals(selectedStyle)); - binding.monetFidelity.setOnClickListener(v -> { - binding.monetFidelity.setSelected(true); - unSelectOthers(binding.monetFidelity); - RPrefs.putLong(MONET_LAST_UPDATED, System.currentTimeMillis()); - RPrefs.putString(MONET_STYLE_ORIGINAL_NAME, getOriginalName(R.string.monet_fidelity)); - binding.monetFidelity.applyColorScheme(); - }); - binding.monetFidelity.setEnabled(notShizukuMode); - - binding.monetContent.setSelected(getString(R.string.monet_content).equals(selectedStyle)); - binding.monetContent.setOnClickListener(v -> { - binding.monetContent.setSelected(true); - unSelectOthers(binding.monetContent); - RPrefs.putLong(MONET_LAST_UPDATED, System.currentTimeMillis()); - RPrefs.putString(MONET_STYLE_ORIGINAL_NAME, getOriginalName(R.string.monet_content)); - binding.monetContent.applyColorScheme(); - }); - binding.monetContent.setEnabled(notShizukuMode); - - binding.monetFruitsalad.setSelected(getString(R.string.monet_fruitsalad).equals(selectedStyle)); - binding.monetFruitsalad.setOnClickListener(v -> { - binding.monetFruitsalad.setSelected(true); - unSelectOthers(binding.monetFruitsalad); - RPrefs.putLong(MONET_LAST_UPDATED, System.currentTimeMillis()); - RPrefs.putString(MONET_STYLE_ORIGINAL_NAME, getOriginalName(R.string.monet_fruitsalad)); - binding.monetFruitsalad.applyColorScheme(); - }); - binding.monetFruitsalad.setEnabled(isAtleastA13); - - return binding.getRoot(); +package com.drdisagree.colorblendr.ui.fragments + +import android.os.Build +import android.os.Bundle +import android.view.LayoutInflater +import android.view.MenuItem +import android.view.View +import android.view.ViewGroup +import androidx.annotation.StringRes +import androidx.fragment.app.Fragment +import com.drdisagree.colorblendr.R +import com.drdisagree.colorblendr.common.Const +import com.drdisagree.colorblendr.common.Const.MONET_LAST_UPDATED +import com.drdisagree.colorblendr.common.Const.MONET_STYLE +import com.drdisagree.colorblendr.common.Const.MONET_STYLE_ORIGINAL_NAME +import com.drdisagree.colorblendr.common.Const.workingMethod +import com.drdisagree.colorblendr.config.RPrefs +import com.drdisagree.colorblendr.config.RPrefs.putLong +import com.drdisagree.colorblendr.config.RPrefs.putString +import com.drdisagree.colorblendr.databinding.FragmentStylesBinding +import com.drdisagree.colorblendr.utils.MiscUtil.setToolbarTitle + +class StylesFragment : Fragment() { + + private lateinit var binding: FragmentStylesBinding + private val notShizukuMode = workingMethod != Const.WorkMethod.SHIZUKU + private val isAtleastA13 = notShizukuMode || + Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU + private val isAtleastA14 = notShizukuMode || + Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE + + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle? + ): View { + binding = FragmentStylesBinding.inflate(inflater, container, false) + + setToolbarTitle(requireContext(), R.string.styles, true, binding.header.toolbar) + + val selectedStyle = RPrefs.getString(MONET_STYLE, null) + + binding.monetNeutral.isSelected = getString(R.string.monet_neutral) == selectedStyle + binding.monetNeutral.setOnClickListener { + binding.monetNeutral.isSelected = true + unSelectOthers(binding.monetNeutral) + putLong(MONET_LAST_UPDATED, System.currentTimeMillis()) + putString(MONET_STYLE_ORIGINAL_NAME, getOriginalName(R.string.monet_neutral)) + binding.monetNeutral.applyColorScheme() + } + binding.monetNeutral.isEnabled = isAtleastA13 + + binding.monetMonochrome.isSelected = getString(R.string.monet_monochrome) == selectedStyle + binding.monetMonochrome.setOnClickListener { + binding.monetMonochrome.isSelected = true + unSelectOthers(binding.monetMonochrome) + putLong(MONET_LAST_UPDATED, System.currentTimeMillis()) + putString(MONET_STYLE_ORIGINAL_NAME, getOriginalName(R.string.monet_monochrome)) + binding.monetMonochrome.applyColorScheme() + } + binding.monetMonochrome.isEnabled = isAtleastA14 + + binding.monetTonalspot.isSelected = + getString(R.string.monet_tonalspot) == selectedStyle || selectedStyle == null + binding.monetTonalspot.setOnClickListener { + binding.monetTonalspot.isSelected = true + unSelectOthers(binding.monetTonalspot) + putLong(MONET_LAST_UPDATED, System.currentTimeMillis()) + putString(MONET_STYLE_ORIGINAL_NAME, getOriginalName(R.string.monet_tonalspot)) + binding.monetTonalspot.applyColorScheme() + } + + binding.monetVibrant.isSelected = getString(R.string.monet_vibrant) == selectedStyle + binding.monetVibrant.setOnClickListener { + binding.monetVibrant.isSelected = true + unSelectOthers(binding.monetVibrant) + putLong(MONET_LAST_UPDATED, System.currentTimeMillis()) + putString(MONET_STYLE_ORIGINAL_NAME, getOriginalName(R.string.monet_vibrant)) + binding.monetVibrant.applyColorScheme() + } + binding.monetVibrant.isEnabled = isAtleastA13 + + binding.monetRainbow.isSelected = getString(R.string.monet_rainbow) == selectedStyle + binding.monetRainbow.setOnClickListener { + binding.monetRainbow.isSelected = true + unSelectOthers(binding.monetRainbow) + putLong(MONET_LAST_UPDATED, System.currentTimeMillis()) + putString(MONET_STYLE_ORIGINAL_NAME, getOriginalName(R.string.monet_rainbow)) + binding.monetRainbow.applyColorScheme() + } + binding.monetRainbow.isEnabled = isAtleastA13 + + binding.monetExpressive.isSelected = getString(R.string.monet_expressive) == selectedStyle + binding.monetExpressive.setOnClickListener { + binding.monetExpressive.isSelected = true + unSelectOthers(binding.monetExpressive) + putLong(MONET_LAST_UPDATED, System.currentTimeMillis()) + putString(MONET_STYLE_ORIGINAL_NAME, getOriginalName(R.string.monet_expressive)) + binding.monetExpressive.applyColorScheme() + } + binding.monetExpressive.isEnabled = isAtleastA13 + + binding.monetFidelity.isSelected = getString(R.string.monet_fidelity) == selectedStyle + binding.monetFidelity.setOnClickListener { + binding.monetFidelity.isSelected = true + unSelectOthers(binding.monetFidelity) + putLong(MONET_LAST_UPDATED, System.currentTimeMillis()) + putString(MONET_STYLE_ORIGINAL_NAME, getOriginalName(R.string.monet_fidelity)) + binding.monetFidelity.applyColorScheme() + } + binding.monetFidelity.isEnabled = notShizukuMode + + binding.monetContent.isSelected = getString(R.string.monet_content) == selectedStyle + binding.monetContent.setOnClickListener { + binding.monetContent.isSelected = true + unSelectOthers(binding.monetContent) + putLong(MONET_LAST_UPDATED, System.currentTimeMillis()) + putString(MONET_STYLE_ORIGINAL_NAME, getOriginalName(R.string.monet_content)) + binding.monetContent.applyColorScheme() + } + binding.monetContent.isEnabled = notShizukuMode + + binding.monetFruitsalad.isSelected = getString(R.string.monet_fruitsalad) == selectedStyle + binding.monetFruitsalad.setOnClickListener { + binding.monetFruitsalad.isSelected = true + unSelectOthers(binding.monetFruitsalad) + putLong(MONET_LAST_UPDATED, System.currentTimeMillis()) + putString(MONET_STYLE_ORIGINAL_NAME, getOriginalName(R.string.monet_fruitsalad)) + binding.monetFruitsalad.applyColorScheme() + } + binding.monetFruitsalad.isEnabled = isAtleastA13 + + return binding.root } - private void unSelectOthers(ViewGroup viewGroup) { - ViewGroup[] viewGroups = new ViewGroup[]{ - binding.monetNeutral, - binding.monetMonochrome, - binding.monetTonalspot, - binding.monetVibrant, - binding.monetRainbow, - binding.monetExpressive, - binding.monetFidelity, - binding.monetContent, - binding.monetFruitsalad - }; - - for (ViewGroup view : viewGroups) { - if (view != viewGroup) { - view.setSelected(false); + private fun unSelectOthers(viewGroup: ViewGroup) { + val viewGroups = arrayOf( + binding.monetNeutral, + binding.monetMonochrome, + binding.monetTonalspot, + binding.monetVibrant, + binding.monetRainbow, + binding.monetExpressive, + binding.monetFidelity, + binding.monetContent, + binding.monetFruitsalad + ) + + for (view in viewGroups) { + if (view !== viewGroup) { + view.isSelected = false } } } - @Override - public boolean onOptionsItemSelected(@NonNull MenuItem item) { - if (item.getItemId() == android.R.id.home) { - getParentFragmentManager().popBackStackImmediate(); - return true; + @Suppress("DEPRECATION") + @Deprecated("Deprecated in Java") + override fun onOptionsItemSelected(item: MenuItem): Boolean { + if (item.itemId == android.R.id.home) { + parentFragmentManager.popBackStackImmediate() + return true } - return super.onOptionsItemSelected(item); + return super.onOptionsItemSelected(item) } - private String getOriginalName(@StringRes int id) { - String name = getString(id); - - if (name.equals(getString(R.string.monet_neutral))) { - return "SPRITZ"; - } else if (name.equals(getString(R.string.monet_vibrant))) { - return "VIBRANT"; - } else if (name.equals(getString(R.string.monet_expressive))) { - return "EXPRESSIVE"; - } else if (name.equals(getString(R.string.monet_rainbow))) { - return "RAINBOW"; - } else if (name.equals(getString(R.string.monet_fruitsalad))) { - return "FRUIT_SALAD"; - } else if (name.equals(getString(R.string.monet_content))) { - return "CONTENT"; - } else if (name.equals(getString(R.string.monet_monochrome))) { - return "MONOCHROMATIC"; - } else if (name.equals(getString(R.string.monet_fidelity))) { - return "FIDELITY"; - } else { - return "TONAL_SPOT"; + private fun getOriginalName(@StringRes id: Int): String { + val name = getString(id) + + return when (name) { + getString(R.string.monet_neutral) -> { + "SPRITZ" + } + + getString(R.string.monet_vibrant) -> { + "VIBRANT" + } + + getString(R.string.monet_expressive) -> { + "EXPRESSIVE" + } + + getString(R.string.monet_rainbow) -> { + "RAINBOW" + } + + getString(R.string.monet_fruitsalad) -> { + "FRUIT_SALAD" + } + + getString(R.string.monet_content) -> { + "CONTENT" + } + + getString(R.string.monet_monochrome) -> { + "MONOCHROMATIC" + } + + getString(R.string.monet_fidelity) -> { + "FIDELITY" + } + + else -> { + "TONAL_SPOT" + } } } } \ No newline at end of file diff --git a/app/src/main/java/com/drdisagree/colorblendr/ui/fragments/ThemeFragment.kt b/app/src/main/java/com/drdisagree/colorblendr/ui/fragments/ThemeFragment.kt index 33a2f96..133590c 100644 --- a/app/src/main/java/com/drdisagree/colorblendr/ui/fragments/ThemeFragment.kt +++ b/app/src/main/java/com/drdisagree/colorblendr/ui/fragments/ThemeFragment.kt @@ -1,274 +1,276 @@ -package com.drdisagree.colorblendr.ui.fragments; - -import static com.drdisagree.colorblendr.common.Const.MONET_ACCENT_SATURATION; -import static com.drdisagree.colorblendr.common.Const.MONET_ACCURATE_SHADES; -import static com.drdisagree.colorblendr.common.Const.MONET_BACKGROUND_LIGHTNESS; -import static com.drdisagree.colorblendr.common.Const.MONET_BACKGROUND_SATURATION; -import static com.drdisagree.colorblendr.common.Const.MONET_LAST_UPDATED; -import static com.drdisagree.colorblendr.common.Const.MONET_PITCH_BLACK_THEME; -import static com.drdisagree.colorblendr.common.Const.MONET_STYLE; - -import android.os.Bundle; -import android.os.Handler; -import android.os.Looper; -import android.util.Log; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.SeekBar; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.fragment.app.Fragment; - -import com.drdisagree.colorblendr.R; -import com.drdisagree.colorblendr.common.Const; -import com.drdisagree.colorblendr.config.RPrefs; -import com.drdisagree.colorblendr.databinding.FragmentThemeBinding; -import com.drdisagree.colorblendr.utils.ColorSchemeUtil; -import com.drdisagree.colorblendr.utils.ColorUtil; -import com.drdisagree.colorblendr.utils.MiscUtil; -import com.drdisagree.colorblendr.utils.OverlayManager; -import com.drdisagree.colorblendr.utils.SystemUtil; - -import java.util.ArrayList; - -public class ThemeFragment extends Fragment { - - private static final String TAG = ThemeFragment.class.getSimpleName(); - private FragmentThemeBinding binding; - private final int[] monetAccentSaturation = new int[]{RPrefs.getInt(MONET_ACCENT_SATURATION, 100)}; - private final int[] monetBackgroundSaturation = new int[]{RPrefs.getInt(MONET_BACKGROUND_SATURATION, 100)}; - private final int[] monetBackgroundLightness = new int[]{RPrefs.getInt(MONET_BACKGROUND_LIGHTNESS, 100)}; - private final boolean notShizukuMode = Const.getWorkingMethod() != Const.WORK_METHOD.SHIZUKU; - - @Override - public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - binding = FragmentThemeBinding.inflate(inflater, container, false); - - MiscUtil.setToolbarTitle(requireContext(), R.string.theme, true, binding.header.toolbar); +package com.drdisagree.colorblendr.ui.fragments + +import android.os.Bundle +import android.os.Handler +import android.os.Looper +import android.util.Log +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.SeekBar +import android.widget.SeekBar.OnSeekBarChangeListener +import androidx.fragment.app.Fragment +import com.drdisagree.colorblendr.R +import com.drdisagree.colorblendr.common.Const +import com.drdisagree.colorblendr.common.Const.MONET_ACCENT_SATURATION +import com.drdisagree.colorblendr.common.Const.MONET_ACCURATE_SHADES +import com.drdisagree.colorblendr.common.Const.MONET_BACKGROUND_LIGHTNESS +import com.drdisagree.colorblendr.common.Const.MONET_BACKGROUND_SATURATION +import com.drdisagree.colorblendr.common.Const.MONET_LAST_UPDATED +import com.drdisagree.colorblendr.common.Const.MONET_PITCH_BLACK_THEME +import com.drdisagree.colorblendr.common.Const.MONET_STYLE +import com.drdisagree.colorblendr.common.Const.workingMethod +import com.drdisagree.colorblendr.config.RPrefs +import com.drdisagree.colorblendr.config.RPrefs.clearPref +import com.drdisagree.colorblendr.config.RPrefs.getBoolean +import com.drdisagree.colorblendr.config.RPrefs.getInt +import com.drdisagree.colorblendr.config.RPrefs.putInt +import com.drdisagree.colorblendr.config.RPrefs.putLong +import com.drdisagree.colorblendr.databinding.FragmentThemeBinding +import com.drdisagree.colorblendr.utils.ColorSchemeUtil.stringToEnumMonetStyle +import com.drdisagree.colorblendr.utils.ColorUtil.generateModifiedColors +import com.drdisagree.colorblendr.utils.MiscUtil.setToolbarTitle +import com.drdisagree.colorblendr.utils.OverlayManager.applyFabricatedColors +import com.drdisagree.colorblendr.utils.SystemUtil.isDarkMode + +class ThemeFragment : Fragment() { + + private lateinit var binding: FragmentThemeBinding + private val monetAccentSaturation: IntArray = intArrayOf( + getInt(MONET_ACCENT_SATURATION, 100) + ) + private val monetBackgroundSaturation: IntArray = intArrayOf( + getInt(MONET_BACKGROUND_SATURATION, 100) + ) + private val monetBackgroundLightness: IntArray = intArrayOf( + getInt(MONET_BACKGROUND_LIGHTNESS, 100) + ) + private val notShizukuMode: Boolean = workingMethod != Const.WorkMethod.SHIZUKU + + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle? + ): View { + binding = FragmentThemeBinding.inflate(inflater, container, false) + + setToolbarTitle(requireContext(), R.string.theme, true, binding.header.toolbar) // Color preview titles - binding.colorAccent1.title.setText(R.string.primary); - binding.colorAccent2.title.setText(R.string.secondary); - binding.colorAccent3.title.setText(R.string.tertiary); - binding.colorNeutral1.title.setText(R.string.neutral_1); - binding.colorNeutral2.title.setText(R.string.neutral_2); + binding.colorAccent1.title.setText(R.string.primary) + binding.colorAccent2.title.setText(R.string.secondary) + binding.colorAccent3.title.setText(R.string.tertiary) + binding.colorNeutral1.title.setText(R.string.neutral_1) + binding.colorNeutral2.title.setText(R.string.neutral_2) // Monet primary accent saturation - binding.accentSaturation.setSeekbarProgress(RPrefs.getInt(MONET_ACCENT_SATURATION, 100)); - binding.accentSaturation.setOnSeekbarChangeListener(new SeekBar.OnSeekBarChangeListener() { - @Override - public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { - binding.accentSaturation.setSelectedProgress(); - monetAccentSaturation[0] = progress; - updatePreviewColors(); + binding.accentSaturation.seekbarProgress = getInt(MONET_ACCENT_SATURATION, 100) + binding.accentSaturation.setOnSeekbarChangeListener(object : OnSeekBarChangeListener { + override fun onProgressChanged(seekBar: SeekBar, progress: Int, fromUser: Boolean) { + binding.accentSaturation.setSelectedProgress() + monetAccentSaturation[0] = progress + updatePreviewColors() } - @Override - public void onStartTrackingTouch(SeekBar seekBar) { + override fun onStartTrackingTouch(seekBar: SeekBar) { } - @Override - public void onStopTrackingTouch(SeekBar seekBar) { - monetAccentSaturation[0] = seekBar.getProgress(); - RPrefs.putInt(MONET_ACCENT_SATURATION, monetAccentSaturation[0]); - RPrefs.putLong(MONET_LAST_UPDATED, System.currentTimeMillis()); - new Handler(Looper.getMainLooper()).postDelayed(() -> { + override fun onStopTrackingTouch(seekBar: SeekBar) { + monetAccentSaturation[0] = seekBar.progress + putInt(MONET_ACCENT_SATURATION, monetAccentSaturation[0]) + putLong(MONET_LAST_UPDATED, System.currentTimeMillis()) + Handler(Looper.getMainLooper()).postDelayed({ try { - OverlayManager.applyFabricatedColors(requireContext()); - } catch (Exception ignored) { + applyFabricatedColors(requireContext()) + } catch (ignored: Exception) { } - }, 200); + }, 200) } - }); + }) // Long Click Reset - binding.accentSaturation.setResetClickListener(v -> { - monetAccentSaturation[0] = 100; - updatePreviewColors(); - RPrefs.clearPref(MONET_ACCENT_SATURATION); - RPrefs.putLong(MONET_LAST_UPDATED, System.currentTimeMillis()); - new Handler(Looper.getMainLooper()).postDelayed(() -> { + binding.accentSaturation.setResetClickListener { + monetAccentSaturation[0] = 100 + updatePreviewColors() + clearPref(MONET_ACCENT_SATURATION) + putLong(MONET_LAST_UPDATED, System.currentTimeMillis()) + Handler(Looper.getMainLooper()).postDelayed({ try { - OverlayManager.applyFabricatedColors(requireContext()); - } catch (Exception ignored) { + applyFabricatedColors(requireContext()) + } catch (ignored: Exception) { } - }, 200); - return true; - }); - binding.accentSaturation.setEnabled(notShizukuMode); + }, 200) + true + } + binding.accentSaturation.setEnabled(notShizukuMode) // Monet background saturation - binding.backgroundSaturation.setSeekbarProgress(RPrefs.getInt(MONET_BACKGROUND_SATURATION, 100)); - binding.backgroundSaturation.setOnSeekbarChangeListener(new SeekBar.OnSeekBarChangeListener() { - @Override - public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { - binding.backgroundSaturation.setSelectedProgress(); - monetBackgroundSaturation[0] = progress; - updatePreviewColors(); + binding.backgroundSaturation.seekbarProgress = getInt(MONET_BACKGROUND_SATURATION, 100) + binding.backgroundSaturation.setOnSeekbarChangeListener(object : OnSeekBarChangeListener { + override fun onProgressChanged(seekBar: SeekBar, progress: Int, fromUser: Boolean) { + binding.backgroundSaturation.setSelectedProgress() + monetBackgroundSaturation[0] = progress + updatePreviewColors() } - @Override - public void onStartTrackingTouch(SeekBar seekBar) { + override fun onStartTrackingTouch(seekBar: SeekBar) { } - @Override - public void onStopTrackingTouch(@NonNull SeekBar seekBar) { - monetBackgroundSaturation[0] = seekBar.getProgress(); - RPrefs.putInt(MONET_BACKGROUND_SATURATION, monetBackgroundSaturation[0]); - RPrefs.putLong(MONET_LAST_UPDATED, System.currentTimeMillis()); - new Handler(Looper.getMainLooper()).postDelayed(() -> { + override fun onStopTrackingTouch(seekBar: SeekBar) { + monetBackgroundSaturation[0] = seekBar.progress + putInt(MONET_BACKGROUND_SATURATION, monetBackgroundSaturation[0]) + putLong(MONET_LAST_UPDATED, System.currentTimeMillis()) + Handler(Looper.getMainLooper()).postDelayed({ try { - OverlayManager.applyFabricatedColors(requireContext()); - } catch (Exception ignored) { + applyFabricatedColors(requireContext()) + } catch (ignored: Exception) { } - }, 200); + }, 200) } - }); + }) // Reset button - binding.backgroundSaturation.setResetClickListener(v -> { - monetBackgroundSaturation[0] = 100; - updatePreviewColors(); - RPrefs.clearPref(MONET_BACKGROUND_SATURATION); - RPrefs.putLong(MONET_LAST_UPDATED, System.currentTimeMillis()); - new Handler(Looper.getMainLooper()).postDelayed(() -> { + binding.backgroundSaturation.setResetClickListener { + monetBackgroundSaturation[0] = 100 + updatePreviewColors() + clearPref(MONET_BACKGROUND_SATURATION) + putLong(MONET_LAST_UPDATED, System.currentTimeMillis()) + Handler(Looper.getMainLooper()).postDelayed({ try { - OverlayManager.applyFabricatedColors(requireContext()); - } catch (Exception ignored) { + applyFabricatedColors(requireContext()) + } catch (ignored: Exception) { } - }, 200); - return true; - }); - binding.backgroundSaturation.setEnabled(notShizukuMode); + }, 200) + true + } + binding.backgroundSaturation.setEnabled(notShizukuMode) // Monet background lightness - binding.backgroundLightness.setSeekbarProgress(RPrefs.getInt(MONET_BACKGROUND_LIGHTNESS, 100)); - binding.backgroundLightness.setOnSeekbarChangeListener(new SeekBar.OnSeekBarChangeListener() { - @Override - public void onProgressChanged(@NonNull SeekBar seekBar, int progress, boolean fromUser) { - binding.backgroundLightness.setSelectedProgress(); - monetBackgroundLightness[0] = progress; - updatePreviewColors(); + binding.backgroundLightness.seekbarProgress = getInt(MONET_BACKGROUND_LIGHTNESS, 100) + binding.backgroundLightness.setOnSeekbarChangeListener(object : OnSeekBarChangeListener { + override fun onProgressChanged(seekBar: SeekBar, progress: Int, fromUser: Boolean) { + binding.backgroundLightness.setSelectedProgress() + monetBackgroundLightness[0] = progress + updatePreviewColors() } - @Override - public void onStartTrackingTouch(@NonNull SeekBar seekBar) { + override fun onStartTrackingTouch(seekBar: SeekBar) { } - @Override - public void onStopTrackingTouch(@NonNull SeekBar seekBar) { - monetBackgroundLightness[0] = seekBar.getProgress(); - RPrefs.putInt(MONET_BACKGROUND_LIGHTNESS, monetBackgroundLightness[0]); - RPrefs.putLong(MONET_LAST_UPDATED, System.currentTimeMillis()); - new Handler(Looper.getMainLooper()).postDelayed(() -> { + override fun onStopTrackingTouch(seekBar: SeekBar) { + monetBackgroundLightness[0] = seekBar.progress + putInt(MONET_BACKGROUND_LIGHTNESS, monetBackgroundLightness[0]) + putLong(MONET_LAST_UPDATED, System.currentTimeMillis()) + Handler(Looper.getMainLooper()).postDelayed({ try { - OverlayManager.applyFabricatedColors(requireContext()); - } catch (Exception ignored) { + applyFabricatedColors(requireContext()) + } catch (ignored: Exception) { } - }, 200); + }, 200) } - }); + }) // Long Click Reset - binding.backgroundLightness.setResetClickListener(v -> { - monetBackgroundLightness[0] = 100; - updatePreviewColors(); - RPrefs.clearPref(MONET_BACKGROUND_LIGHTNESS); - RPrefs.putLong(MONET_LAST_UPDATED, System.currentTimeMillis()); - new Handler(Looper.getMainLooper()).postDelayed(() -> { + binding.backgroundLightness.setResetClickListener { + monetBackgroundLightness[0] = 100 + updatePreviewColors() + clearPref(MONET_BACKGROUND_LIGHTNESS) + putLong(MONET_LAST_UPDATED, System.currentTimeMillis()) + Handler(Looper.getMainLooper()).postDelayed({ try { - OverlayManager.applyFabricatedColors(requireContext()); - } catch (Exception ignored) { + applyFabricatedColors(requireContext()) + } catch (ignored: Exception) { } - }, 200); - return true; - }); - binding.backgroundLightness.setEnabled(notShizukuMode); + }, 200) + true + } + binding.backgroundLightness.setEnabled(notShizukuMode) - return binding.getRoot(); + return binding.getRoot() } - @Override - public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { - super.onViewCreated(view, savedInstanceState); + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) - updatePreviewColors(); + updatePreviewColors() } - private void updatePreviewColors() { - ArrayList> colorPalette = generateModifiedColors( - monetAccentSaturation[0], - monetBackgroundSaturation[0], - monetBackgroundLightness[0], - RPrefs.getBoolean(MONET_PITCH_BLACK_THEME, false), - RPrefs.getBoolean(MONET_ACCURATE_SHADES, true) - ); + private fun updatePreviewColors() { + val colorPalette: ArrayList>? = generateModifiedColors( + monetAccentSaturation[0], + monetBackgroundSaturation[0], + monetBackgroundLightness[0], + getBoolean(MONET_PITCH_BLACK_THEME, false), + getBoolean(MONET_ACCURATE_SHADES, true) + ) if (colorPalette != null) { - boolean isDarkMode = SystemUtil.isDarkMode(); - - binding.colorAccent1.colorContainer.setHalfCircleColor(colorPalette.get(0).get(4)); - binding.colorAccent1.colorContainer.setFirstQuarterCircleColor(colorPalette.get(0).get(5)); - binding.colorAccent1.colorContainer.setSecondQuarterCircleColor(colorPalette.get(0).get(6)); - binding.colorAccent1.colorContainer.setSquareColor(colorPalette.get(0).get(!isDarkMode ? 3 : 9)); - binding.colorAccent1.colorContainer.setPadding(8); - binding.colorAccent1.colorContainer.invalidateColors(); - - binding.colorAccent2.colorContainer.setHalfCircleColor(colorPalette.get(1).get(4)); - binding.colorAccent2.colorContainer.setFirstQuarterCircleColor(colorPalette.get(1).get(5)); - binding.colorAccent2.colorContainer.setSecondQuarterCircleColor(colorPalette.get(1).get(6)); - binding.colorAccent2.colorContainer.setSquareColor(colorPalette.get(1).get(!isDarkMode ? 3 : 9)); - binding.colorAccent2.colorContainer.setPadding(8); - binding.colorAccent2.colorContainer.invalidateColors(); - - binding.colorAccent3.colorContainer.setHalfCircleColor(colorPalette.get(2).get(4)); - binding.colorAccent3.colorContainer.setFirstQuarterCircleColor(colorPalette.get(2).get(5)); - binding.colorAccent3.colorContainer.setSecondQuarterCircleColor(colorPalette.get(2).get(6)); - binding.colorAccent3.colorContainer.setSquareColor(colorPalette.get(2).get(!isDarkMode ? 3 : 9)); - binding.colorAccent3.colorContainer.setPadding(8); - binding.colorAccent3.colorContainer.invalidateColors(); - - binding.colorNeutral1.colorContainer.setHalfCircleColor(colorPalette.get(3).get(4)); - binding.colorNeutral1.colorContainer.setFirstQuarterCircleColor(colorPalette.get(3).get(5)); - binding.colorNeutral1.colorContainer.setSecondQuarterCircleColor(colorPalette.get(3).get(6)); - binding.colorNeutral1.colorContainer.setSquareColor(colorPalette.get(3).get(!isDarkMode ? 3 : 9)); - binding.colorNeutral1.colorContainer.setPadding(8); - binding.colorNeutral1.colorContainer.invalidateColors(); - - binding.colorNeutral2.colorContainer.setHalfCircleColor(colorPalette.get(4).get(4)); - binding.colorNeutral2.colorContainer.setFirstQuarterCircleColor(colorPalette.get(4).get(5)); - binding.colorNeutral2.colorContainer.setSecondQuarterCircleColor(colorPalette.get(4).get(6)); - binding.colorNeutral2.colorContainer.setSquareColor(colorPalette.get(4).get(!isDarkMode ? 3 : 9)); - binding.colorNeutral2.colorContainer.setPadding(8); - binding.colorNeutral2.colorContainer.invalidateColors(); + val isDarkMode: Boolean = isDarkMode + + binding.colorAccent1.colorContainer.setHalfCircleColor(colorPalette[0][4]) + binding.colorAccent1.colorContainer.setFirstQuarterCircleColor(colorPalette[0][5]) + binding.colorAccent1.colorContainer.setSecondQuarterCircleColor(colorPalette[0][6]) + binding.colorAccent1.colorContainer.setSquareColor(colorPalette[0][if (!isDarkMode) 3 else 9]) + binding.colorAccent1.colorContainer.setPadding(8f) + binding.colorAccent1.colorContainer.invalidateColors() + + binding.colorAccent2.colorContainer.setHalfCircleColor(colorPalette[1][4]) + binding.colorAccent2.colorContainer.setFirstQuarterCircleColor(colorPalette[1][5]) + binding.colorAccent2.colorContainer.setSecondQuarterCircleColor(colorPalette[1][6]) + binding.colorAccent2.colorContainer.setSquareColor(colorPalette[1][if (!isDarkMode) 3 else 9]) + binding.colorAccent2.colorContainer.setPadding(8f) + binding.colorAccent2.colorContainer.invalidateColors() + + binding.colorAccent3.colorContainer.setHalfCircleColor(colorPalette[2][4]) + binding.colorAccent3.colorContainer.setFirstQuarterCircleColor(colorPalette[2][5]) + binding.colorAccent3.colorContainer.setSecondQuarterCircleColor(colorPalette[2][6]) + binding.colorAccent3.colorContainer.setSquareColor(colorPalette[2][if (!isDarkMode) 3 else 9]) + binding.colorAccent3.colorContainer.setPadding(8f) + binding.colorAccent3.colorContainer.invalidateColors() + + binding.colorNeutral1.colorContainer.setHalfCircleColor(colorPalette[3][4]) + binding.colorNeutral1.colorContainer.setFirstQuarterCircleColor(colorPalette[3][5]) + binding.colorNeutral1.colorContainer.setSecondQuarterCircleColor(colorPalette[3][6]) + binding.colorNeutral1.colorContainer.setSquareColor(colorPalette[3][if (!isDarkMode) 3 else 9]) + binding.colorNeutral1.colorContainer.setPadding(8f) + binding.colorNeutral1.colorContainer.invalidateColors() + + binding.colorNeutral2.colorContainer.setHalfCircleColor(colorPalette[4][4]) + binding.colorNeutral2.colorContainer.setFirstQuarterCircleColor(colorPalette[4][5]) + binding.colorNeutral2.colorContainer.setSecondQuarterCircleColor(colorPalette[4][6]) + binding.colorNeutral2.colorContainer.setSquareColor(colorPalette[4][if (!isDarkMode) 3 else 9]) + binding.colorNeutral2.colorContainer.setPadding(8f) + binding.colorNeutral2.colorContainer.invalidateColors() } } - private ArrayList> generateModifiedColors( - int monetAccentSaturation, - int monetBackgroundSaturation, - int monetBackgroundLightness, - boolean pitchBlackTheme, - boolean accurateShades - ) { + private fun generateModifiedColors( + monetAccentSaturation: Int, + monetBackgroundSaturation: Int, + monetBackgroundLightness: Int, + pitchBlackTheme: Boolean, + accurateShades: Boolean + ): ArrayList>? { try { - return ColorUtil.generateModifiedColors( + return generateModifiedColors( + requireContext(), + stringToEnumMonetStyle( requireContext(), - ColorSchemeUtil.stringToEnumMonetStyle( - requireContext(), - RPrefs.getString(MONET_STYLE, getString(R.string.monet_tonalspot)) - ), - monetAccentSaturation, - monetBackgroundSaturation, - monetBackgroundLightness, - pitchBlackTheme, - accurateShades - ); - } catch (Exception e) { - Log.e(TAG, "Error generating modified colors", e); - return null; + RPrefs.getString(MONET_STYLE, getString(R.string.monet_tonalspot))!! + ), + monetAccentSaturation, + monetBackgroundSaturation, + monetBackgroundLightness, + pitchBlackTheme, + accurateShades + ) + } catch (e: Exception) { + Log.e(TAG, "Error generating modified colors", e) + return null } } + + companion object { + private val TAG: String = ThemeFragment::class.java.getSimpleName() + } } \ No newline at end of file diff --git a/app/src/main/java/com/drdisagree/colorblendr/ui/models/AppInfoModel.kt b/app/src/main/java/com/drdisagree/colorblendr/ui/models/AppInfoModel.kt index 7cc5200..82cbba8 100644 --- a/app/src/main/java/com/drdisagree/colorblendr/ui/models/AppInfoModel.kt +++ b/app/src/main/java/com/drdisagree/colorblendr/ui/models/AppInfoModel.kt @@ -1,25 +1,10 @@ -package com.drdisagree.colorblendr.ui.models; +package com.drdisagree.colorblendr.ui.models -import android.graphics.drawable.Drawable; +import android.graphics.drawable.Drawable -public class AppInfoModel { - - public String appName; - public String packageName; - public Drawable appIcon; - private boolean isSelected = false; - - public AppInfoModel(String appName, String packageName, Drawable appIcon) { - this.appName = appName; - this.packageName = packageName; - this.appIcon = appIcon; - } - - public boolean isSelected() { - return isSelected; - } - - public void setSelected(boolean selected) { - isSelected = selected; - } -} +data class AppInfoModel( + var appName: String, + var packageName: String, + var appIcon: Drawable, + var isSelected: Boolean = false +) diff --git a/app/src/main/java/com/drdisagree/colorblendr/ui/viewmodels/SharedViewModel.kt b/app/src/main/java/com/drdisagree/colorblendr/ui/viewmodels/SharedViewModel.kt index 5b8e1e4..5fc2a39 100644 --- a/app/src/main/java/com/drdisagree/colorblendr/ui/viewmodels/SharedViewModel.kt +++ b/app/src/main/java/com/drdisagree/colorblendr/ui/viewmodels/SharedViewModel.kt @@ -1,41 +1,32 @@ -package com.drdisagree.colorblendr.ui.viewmodels; +package com.drdisagree.colorblendr.ui.viewmodels -import androidx.lifecycle.LiveData; -import androidx.lifecycle.MutableLiveData; -import androidx.lifecycle.ViewModel; +import androidx.lifecycle.LiveData +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel -import java.util.HashMap; -import java.util.Map; +class SharedViewModel : ViewModel() { -public class SharedViewModel extends ViewModel { + private val booleanStates: MutableLiveData> = MutableLiveData() - private final MutableLiveData> booleanStates = new MutableLiveData<>(); - - public LiveData> getBooleanStates() { - return booleanStates; + fun getBooleanStates(): LiveData> { + return booleanStates } - public void setBooleanState(String viewId, boolean state) { - Map currentStates = booleanStates.getValue(); - if (currentStates == null) { - currentStates = new HashMap<>(); - } - currentStates.put(viewId, state); - booleanStates.setValue(currentStates); + fun setBooleanState(viewId: String, state: Boolean) { + val currentStates: MutableMap = booleanStates.getValue() ?: HashMap() + currentStates[viewId] = state + booleanStates.value = currentStates } - private final MutableLiveData> visibilityStates = new MutableLiveData<>(); + private val visibilityStates: MutableLiveData> = MutableLiveData() - public LiveData> getVisibilityStates() { - return visibilityStates; + fun getVisibilityStates(): LiveData> { + return visibilityStates } - public void setVisibilityState(String viewId, int visibility) { - Map currentStates = visibilityStates.getValue(); - if (currentStates == null) { - currentStates = new HashMap<>(); - } - currentStates.put(viewId, visibility); - visibilityStates.setValue(currentStates); + fun setVisibilityState(viewId: String, visibility: Int) { + val currentStates: MutableMap = visibilityStates.getValue() ?: HashMap() + currentStates[viewId] = visibility + visibilityStates.value = currentStates } } diff --git a/app/src/main/java/com/drdisagree/colorblendr/ui/views/ColorPreview.kt b/app/src/main/java/com/drdisagree/colorblendr/ui/views/ColorPreview.kt index 78e2018..64b455e 100644 --- a/app/src/main/java/com/drdisagree/colorblendr/ui/views/ColorPreview.kt +++ b/app/src/main/java/com/drdisagree/colorblendr/ui/views/ColorPreview.kt @@ -1,117 +1,132 @@ -package com.drdisagree.colorblendr.ui.views; - -import android.content.Context; -import android.content.res.Configuration; -import android.graphics.Canvas; -import android.graphics.Paint; -import android.graphics.RectF; -import android.util.AttributeSet; -import android.view.View; - -import androidx.annotation.ColorInt; -import androidx.annotation.NonNull; -import androidx.core.content.ContextCompat; - -public class ColorPreview extends View { - - private Paint squarePaint, secondQuarterCirclePaint, firstQuarterCirclePaint, halfCirclePaint; - private RectF squareRect, circleRect; - private float padding; - - public ColorPreview(Context context) { - super(context); - init(context); +package com.drdisagree.colorblendr.ui.views + +import android.content.Context +import android.content.res.Configuration +import android.graphics.Canvas +import android.graphics.Paint +import android.graphics.RectF +import android.util.AttributeSet +import android.view.View +import androidx.annotation.ColorInt +import androidx.core.content.ContextCompat + +class ColorPreview : View { + + private var squarePaint: Paint? = null + private var secondQuarterCirclePaint: Paint? = null + private var firstQuarterCirclePaint: Paint? = null + private var halfCirclePaint: Paint? = null + private var squareRect: RectF? = null + private var circleRect: RectF? = null + private var padding: Float = 0f + + constructor(context: Context) : super(context) { + init(context) } - public ColorPreview(Context context, AttributeSet attrs) { - super(context, attrs); - init(context); + constructor(context: Context, attrs: AttributeSet?) : super(context, attrs) { + init(context) } - public ColorPreview(Context context, AttributeSet attrs, int defStyleAttr) { - super(context, attrs, defStyleAttr); - init(context); + constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super( + context, + attrs, + defStyleAttr + ) { + init(context) } - private void init(Context context) { - boolean isDarkMode = (context.getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_YES) == Configuration.UI_MODE_NIGHT_YES; - - padding = 10 * getResources().getDisplayMetrics().density; - - squareRect = new RectF(); - circleRect = new RectF(); - - squarePaint = new Paint(); - squarePaint.setColor(ContextCompat.getColor(context, - !isDarkMode ? - com.google.android.material.R.color.material_dynamic_neutral99 : - com.google.android.material.R.color.material_dynamic_neutral10 - )); - squarePaint.setStyle(Paint.Style.FILL); - - halfCirclePaint = new Paint(); - halfCirclePaint.setColor(ContextCompat.getColor(context, com.google.android.material.R.color.material_dynamic_primary90)); - halfCirclePaint.setStyle(Paint.Style.FILL); - - firstQuarterCirclePaint = new Paint(); - firstQuarterCirclePaint.setColor(ContextCompat.getColor(context, com.google.android.material.R.color.material_dynamic_secondary90)); - firstQuarterCirclePaint.setStyle(Paint.Style.FILL); - - secondQuarterCirclePaint = new Paint(); - secondQuarterCirclePaint.setColor(ContextCompat.getColor(context, com.google.android.material.R.color.material_dynamic_tertiary90)); - secondQuarterCirclePaint.setStyle(Paint.Style.FILL); + private fun init(context: Context) { + val isDarkMode: Boolean = + (context.resources.configuration.uiMode and Configuration.UI_MODE_NIGHT_YES) == Configuration.UI_MODE_NIGHT_YES + + padding = 10 * resources.displayMetrics.density + + squareRect = RectF() + circleRect = RectF() + + squarePaint = Paint() + squarePaint!!.setColor( + ContextCompat.getColor( + context, + if (!isDarkMode) com.google.android.material.R.color.material_dynamic_neutral99 else com.google.android.material.R.color.material_dynamic_neutral10 + ) + ) + squarePaint!!.style = Paint.Style.FILL + + halfCirclePaint = Paint() + halfCirclePaint!!.setColor( + ContextCompat.getColor( + context, + com.google.android.material.R.color.material_dynamic_primary90 + ) + ) + halfCirclePaint!!.style = Paint.Style.FILL + + firstQuarterCirclePaint = Paint() + firstQuarterCirclePaint!!.setColor( + ContextCompat.getColor( + context, + com.google.android.material.R.color.material_dynamic_secondary90 + ) + ) + firstQuarterCirclePaint!!.style = Paint.Style.FILL + + secondQuarterCirclePaint = Paint() + secondQuarterCirclePaint!!.setColor( + ContextCompat.getColor( + context, + com.google.android.material.R.color.material_dynamic_tertiary90 + ) + ) + secondQuarterCirclePaint!!.style = Paint.Style.FILL } - @Override - protected void onDraw(@NonNull Canvas canvas) { - super.onDraw(canvas); - - int width = getWidth(); - int height = getHeight(); + override fun onDraw(canvas: Canvas) { + super.onDraw(canvas) - float cornerRadius = 12 * getResources().getDisplayMetrics().density; - squareRect.set(0, 0, width, height); - canvas.drawRoundRect(squareRect, cornerRadius, cornerRadius, squarePaint); + val cornerRadius: Float = 12 * resources.displayMetrics.density + squareRect!!.set(0f, 0f, width.toFloat(), height.toFloat()) + canvas.drawRoundRect(squareRect!!, cornerRadius, cornerRadius, squarePaint!!) - float margin = 0 * getResources().getDisplayMetrics().density; + val margin: Float = 0 * resources.displayMetrics.density - circleRect.set(padding, padding, width - padding, height - padding - margin); - canvas.drawArc(circleRect, 180, 180, true, halfCirclePaint); + circleRect!!.set(padding, padding, width - padding, height - padding - margin) + canvas.drawArc(circleRect!!, 180f, 180f, true, halfCirclePaint!!) - circleRect.set(padding, padding + margin, width - padding - margin, height - padding); - canvas.drawArc(circleRect, 90, 90, true, firstQuarterCirclePaint); + circleRect!!.set(padding, padding + margin, width - padding - margin, height - padding) + canvas.drawArc(circleRect!!, 90f, 90f, true, firstQuarterCirclePaint!!) - circleRect.set(padding + margin, padding + margin, width - padding, height - padding); - canvas.drawArc(circleRect, 0, 90, true, secondQuarterCirclePaint); + circleRect!!.set(padding + margin, padding + margin, width - padding, height - padding) + canvas.drawArc(circleRect!!, 0f, 90f, true, secondQuarterCirclePaint!!) } - public void setSquareColor(@ColorInt int color) { - squarePaint.setColor(color); + fun setSquareColor(@ColorInt color: Int) { + squarePaint!!.setColor(color) } - public void setFirstQuarterCircleColor(@ColorInt int color) { - firstQuarterCirclePaint.setColor(color); + fun setFirstQuarterCircleColor(@ColorInt color: Int) { + firstQuarterCirclePaint!!.setColor(color) } - public void setSecondQuarterCircleColor(@ColorInt int color) { - secondQuarterCirclePaint.setColor(color); + fun setSecondQuarterCircleColor(@ColorInt color: Int) { + secondQuarterCirclePaint!!.setColor(color) } - public void setHalfCircleColor(@ColorInt int color) { - halfCirclePaint.setColor(color); + fun setHalfCircleColor(@ColorInt color: Int) { + halfCirclePaint!!.setColor(color) } - public void invalidateColors() { - invalidate(); + fun invalidateColors() { + invalidate() } - public void setPadding(float padding) { - this.padding = padding * getResources().getDisplayMetrics().density; + fun setPadding(padding: Float) { + this.padding = padding * resources.displayMetrics.density } - @Override - public void setEnabled(boolean enabled) { - super.setEnabled(enabled); - this.setAlpha(enabled ? 1.0f : 0.6f); + override fun setEnabled(enabled: Boolean) { + super.setEnabled(enabled) + this.setAlpha(if (enabled) 1.0f else 0.6f) } } diff --git a/app/src/main/java/com/drdisagree/colorblendr/ui/views/ResizableSeekbar.kt b/app/src/main/java/com/drdisagree/colorblendr/ui/views/ResizableSeekbar.kt index 27769a1..3547a73 100644 --- a/app/src/main/java/com/drdisagree/colorblendr/ui/views/ResizableSeekbar.kt +++ b/app/src/main/java/com/drdisagree/colorblendr/ui/views/ResizableSeekbar.kt @@ -1,28 +1,26 @@ -package com.drdisagree.colorblendr.ui.views; +package com.drdisagree.colorblendr.ui.views -import android.content.Context; -import android.graphics.drawable.Drawable; -import android.util.AttributeSet; +import android.content.Context +import android.util.AttributeSet +import androidx.appcompat.widget.AppCompatSeekBar -public class ResizableSeekbar extends androidx.appcompat.widget.AppCompatSeekBar { +class ResizableSeekbar : AppCompatSeekBar { - public ResizableSeekbar(Context context) { - super(context); - } + constructor(context: Context) : super(context) - public ResizableSeekbar(Context context, AttributeSet attrs) { - super(context, attrs); - } + constructor(context: Context, attrs: AttributeSet?) : super(context, attrs) - public ResizableSeekbar(Context context, AttributeSet attrs, int defStyle) { - super(context, attrs, defStyle); - } + constructor(context: Context, attrs: AttributeSet?, defStyle: Int) : super( + context, + attrs, + defStyle + ) - @Override - protected synchronized void onSizeChanged(int w, int h, int oldw, int oldh) { - super.onSizeChanged(w, h, oldw, oldh); + @Synchronized + override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) { + super.onSizeChanged(w, h, oldw, oldh) - Drawable trackDrawable = getProgressDrawable().getCurrent(); - trackDrawable.setBounds(0, 0, getMeasuredWidth(), getMeasuredHeight()); + val trackDrawable = progressDrawable.current + trackDrawable.setBounds(0, 0, measuredWidth, measuredHeight) } } diff --git a/app/src/main/java/com/drdisagree/colorblendr/ui/views/RoundedMaterialButtonToggleGroup.kt b/app/src/main/java/com/drdisagree/colorblendr/ui/views/RoundedMaterialButtonToggleGroup.kt index bbd3c19..0016958 100644 --- a/app/src/main/java/com/drdisagree/colorblendr/ui/views/RoundedMaterialButtonToggleGroup.kt +++ b/app/src/main/java/com/drdisagree/colorblendr/ui/views/RoundedMaterialButtonToggleGroup.kt @@ -1,49 +1,42 @@ -package com.drdisagree.colorblendr.ui.views; +package com.drdisagree.colorblendr.ui.views -import android.content.Context; -import android.util.AttributeSet; -import android.view.View; +import android.content.Context +import android.util.AttributeSet +import android.view.View +import com.google.android.material.button.MaterialButton +import com.google.android.material.button.MaterialButtonToggleGroup +import com.google.android.material.shape.ShapeAppearanceModel -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; +class RoundedMaterialButtonToggleGroup : MaterialButtonToggleGroup { -import com.google.android.material.button.MaterialButton; -import com.google.android.material.button.MaterialButtonToggleGroup; -import com.google.android.material.shape.ShapeAppearanceModel; + constructor(context: Context) : super(context) -public class RoundedMaterialButtonToggleGroup extends MaterialButtonToggleGroup { - public RoundedMaterialButtonToggleGroup(@NonNull Context context) { - super(context); - } - - public RoundedMaterialButtonToggleGroup(@NonNull Context context, @Nullable AttributeSet attrs) { - super(context, attrs); - } + constructor(context: Context, attrs: AttributeSet?) : super(context, attrs) - public RoundedMaterialButtonToggleGroup(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) { - super(context, attrs, defStyleAttr); - } + constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super( + context, + attrs, + defStyleAttr + ) - @Override - protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - super.onMeasure(widthMeasureSpec, heightMeasureSpec); + override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) { + super.onMeasure(widthMeasureSpec, heightMeasureSpec) - for (int i = 0; i < getChildCount(); i++) { - View childView = getChildAt(i); - if (childView instanceof MaterialButton button) { - if (button.getVisibility() == View.GONE) { - continue; + for (i in 0 until childCount) { + val childView: View = getChildAt(i) + if (childView is MaterialButton) { + if (childView.getVisibility() == GONE) { + continue } - ShapeAppearanceModel.Builder builder = button.getShapeAppearanceModel().toBuilder(); - float radius = 120 * getResources().getDisplayMetrics().density; - button.setShapeAppearanceModel( - builder - .setTopLeftCornerSize(radius) - .setBottomLeftCornerSize(radius) - .setTopRightCornerSize(radius) - .setBottomRightCornerSize(radius).build() - ); + val builder: ShapeAppearanceModel.Builder = + childView.shapeAppearanceModel.toBuilder() + val radius: Float = 120 * resources.displayMetrics.density + childView.shapeAppearanceModel = builder + .setTopLeftCornerSize(radius) + .setBottomLeftCornerSize(radius) + .setTopRightCornerSize(radius) + .setBottomRightCornerSize(radius).build() } } } diff --git a/app/src/main/java/com/drdisagree/colorblendr/ui/views/WallColorPreview.kt b/app/src/main/java/com/drdisagree/colorblendr/ui/views/WallColorPreview.kt index f75fcc1..e6be89a 100644 --- a/app/src/main/java/com/drdisagree/colorblendr/ui/views/WallColorPreview.kt +++ b/app/src/main/java/com/drdisagree/colorblendr/ui/views/WallColorPreview.kt @@ -1,299 +1,342 @@ -package com.drdisagree.colorblendr.ui.views; - -import static com.drdisagree.colorblendr.common.Const.MONET_ACCENT_SATURATION; -import static com.drdisagree.colorblendr.common.Const.MONET_ACCURATE_SHADES; -import static com.drdisagree.colorblendr.common.Const.MONET_BACKGROUND_LIGHTNESS; -import static com.drdisagree.colorblendr.common.Const.MONET_BACKGROUND_SATURATION; -import static com.drdisagree.colorblendr.common.Const.MONET_PITCH_BLACK_THEME; -import static com.drdisagree.colorblendr.common.Const.MONET_STYLE; - -import android.content.Context; -import android.content.res.Configuration; -import android.graphics.Canvas; -import android.graphics.Color; -import android.graphics.Paint; -import android.graphics.Path; -import android.graphics.RectF; -import android.os.Parcel; -import android.os.Parcelable; -import android.util.AttributeSet; -import android.view.View; - -import androidx.annotation.ColorInt; -import androidx.annotation.NonNull; -import androidx.core.content.ContextCompat; - -import com.drdisagree.colorblendr.R; -import com.drdisagree.colorblendr.config.RPrefs; -import com.drdisagree.colorblendr.utils.ColorSchemeUtil; -import com.drdisagree.colorblendr.utils.ColorUtil; -import com.drdisagree.colorblendr.utils.SystemUtil; - -import java.util.ArrayList; - -public class WallColorPreview extends View { - - private Context context; - private boolean isDarkMode; - private Paint tickPaint, squarePaint, centerCirclePaint, centerClearCirclePaint, secondQuarterCirclePaint, firstQuarterCirclePaint, halfCirclePaint; - private RectF squareRect, circleRect; - private Path tickPath; - private float clearCircleRadius, circleRadius; - private boolean isSelected = false; - private ArrayList> colorPalette; - private @ColorInt int halfCircleColor, firstQuarterCircleColor, secondQuarterCircleColor, squareColor, centerCircleColor; - - public WallColorPreview(Context context) { - super(context); - init(context); +package com.drdisagree.colorblendr.ui.views + +import android.content.Context +import android.content.res.Configuration +import android.graphics.Canvas +import android.graphics.Color +import android.graphics.Paint +import android.graphics.Path +import android.graphics.RectF +import android.os.Parcel +import android.os.Parcelable +import android.util.AttributeSet +import android.view.View +import androidx.annotation.ColorInt +import androidx.core.content.ContextCompat +import com.drdisagree.colorblendr.R +import com.drdisagree.colorblendr.common.Const.MONET_ACCENT_SATURATION +import com.drdisagree.colorblendr.common.Const.MONET_ACCURATE_SHADES +import com.drdisagree.colorblendr.common.Const.MONET_BACKGROUND_LIGHTNESS +import com.drdisagree.colorblendr.common.Const.MONET_BACKGROUND_SATURATION +import com.drdisagree.colorblendr.common.Const.MONET_PITCH_BLACK_THEME +import com.drdisagree.colorblendr.common.Const.MONET_STYLE +import com.drdisagree.colorblendr.config.RPrefs.getBoolean +import com.drdisagree.colorblendr.config.RPrefs.getInt +import com.drdisagree.colorblendr.config.RPrefs.getString +import com.drdisagree.colorblendr.utils.ColorSchemeUtil.stringToEnumMonetStyle +import com.drdisagree.colorblendr.utils.ColorUtil.calculateTextColor +import com.drdisagree.colorblendr.utils.ColorUtil.generateModifiedColors +import com.drdisagree.colorblendr.utils.SystemUtil + +class WallColorPreview : View { + + private var context: Context? = null + private var isDarkMode = false + private var tickPaint: Paint? = null + private var squarePaint: Paint? = null + private var centerCirclePaint: Paint? = null + private var centerClearCirclePaint: Paint? = null + private var secondQuarterCirclePaint: Paint? = null + private var firstQuarterCirclePaint: Paint? = null + private var halfCirclePaint: Paint? = null + private var squareRect: RectF? = null + private var circleRect: RectF? = null + private var tickPath: Path? = null + private var clearCircleRadius = 0f + private var circleRadius = 0f + private var isSelected = false + private var colorPalette: ArrayList>? = null + + @ColorInt + private var halfCircleColor = 0 + + @ColorInt + private var firstQuarterCircleColor = 0 + + @ColorInt + private var secondQuarterCircleColor = 0 + + @ColorInt + private var squareColor = 0 + + @ColorInt + private var centerCircleColor = 0 + + constructor(context: Context) : super(context) { + init(context) } - public WallColorPreview(Context context, AttributeSet attrs) { - super(context, attrs); - init(context); + constructor(context: Context, attrs: AttributeSet?) : super(context, attrs) { + init(context) } - public WallColorPreview(Context context, AttributeSet attrs, int defStyleAttr) { - super(context, attrs, defStyleAttr); - init(context); + constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super( + context, + attrs, + defStyleAttr + ) { + init(context) } - private void init(Context context) { - this.context = context; - isDarkMode = (context.getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_YES) == Configuration.UI_MODE_NIGHT_YES; - - circleRadius = 10 * getResources().getDisplayMetrics().density; - clearCircleRadius = circleRadius + 0 * getResources().getDisplayMetrics().density; - - squareRect = new RectF(); - circleRect = new RectF(); - tickPath = new Path(); - - squarePaint = new Paint(); - squarePaint.setColor(ContextCompat.getColor(context, - !isDarkMode ? - com.google.android.material.R.color.material_dynamic_neutral99 : - com.google.android.material.R.color.material_dynamic_neutral10 - )); - squarePaint.setStyle(Paint.Style.FILL); - - halfCirclePaint = new Paint(); - halfCirclePaint.setColor(ContextCompat.getColor(context, com.google.android.material.R.color.material_dynamic_primary90)); - halfCirclePaint.setStyle(Paint.Style.FILL); - halfCirclePaint.setStrokeCap(Paint.Cap.BUTT); - - firstQuarterCirclePaint = new Paint(); - firstQuarterCirclePaint.setColor(ContextCompat.getColor(context, com.google.android.material.R.color.material_dynamic_secondary90)); - firstQuarterCirclePaint.setStyle(Paint.Style.FILL); - firstQuarterCirclePaint.setStrokeCap(Paint.Cap.BUTT); - - secondQuarterCirclePaint = new Paint(); - secondQuarterCirclePaint.setColor(ContextCompat.getColor(context, com.google.android.material.R.color.material_dynamic_tertiary90)); - secondQuarterCirclePaint.setStyle(Paint.Style.FILL); - secondQuarterCirclePaint.setStrokeCap(Paint.Cap.BUTT); - - centerCirclePaint = new Paint(); - centerCirclePaint.setColor(ContextCompat.getColor(context, com.google.android.material.R.color.material_dynamic_primary70)); - centerCirclePaint.setStyle(Paint.Style.FILL); - - centerClearCirclePaint = new Paint(); - centerClearCirclePaint.setColor(ContextCompat.getColor(context, - !isDarkMode ? - com.google.android.material.R.color.material_dynamic_neutral99 : - com.google.android.material.R.color.material_dynamic_neutral10 - )); - centerClearCirclePaint.setStyle(Paint.Style.FILL); - - tickPaint = new Paint(); - tickPaint.setColor(ContextCompat.getColor(context, - !isDarkMode ? - com.google.android.material.R.color.material_dynamic_neutral99 : - com.google.android.material.R.color.material_dynamic_neutral10 - )); - tickPaint.setStyle(Paint.Style.STROKE); - tickPaint.setStrokeWidth(4); - tickPaint.setStrokeCap(Paint.Cap.ROUND); + private fun init(context: Context) { + this.context = context + isDarkMode = + (context.resources.configuration.uiMode and Configuration.UI_MODE_NIGHT_YES) == Configuration.UI_MODE_NIGHT_YES + + circleRadius = 10 * resources.displayMetrics.density + clearCircleRadius = circleRadius + 0 * resources.displayMetrics.density + + squareRect = RectF() + circleRect = RectF() + tickPath = Path() + + squarePaint = Paint() + squarePaint!!.color = ContextCompat.getColor( + context, + if (!isDarkMode) com.google.android.material.R.color.material_dynamic_neutral99 else com.google.android.material.R.color.material_dynamic_neutral10 + ) + squarePaint!!.style = Paint.Style.FILL + + halfCirclePaint = Paint() + halfCirclePaint!!.color = ContextCompat.getColor( + context, + com.google.android.material.R.color.material_dynamic_primary90 + ) + halfCirclePaint!!.style = Paint.Style.FILL + halfCirclePaint!!.strokeCap = Paint.Cap.BUTT + + firstQuarterCirclePaint = Paint() + firstQuarterCirclePaint!!.color = ContextCompat.getColor( + context, + com.google.android.material.R.color.material_dynamic_secondary90 + ) + firstQuarterCirclePaint!!.style = Paint.Style.FILL + firstQuarterCirclePaint!!.strokeCap = Paint.Cap.BUTT + + secondQuarterCirclePaint = Paint() + secondQuarterCirclePaint!!.color = ContextCompat.getColor( + context, + com.google.android.material.R.color.material_dynamic_tertiary90 + ) + secondQuarterCirclePaint!!.style = Paint.Style.FILL + secondQuarterCirclePaint!!.strokeCap = Paint.Cap.BUTT + + centerCirclePaint = Paint() + centerCirclePaint!!.color = ContextCompat.getColor( + context, + com.google.android.material.R.color.material_dynamic_primary70 + ) + centerCirclePaint!!.style = Paint.Style.FILL + + centerClearCirclePaint = Paint() + centerClearCirclePaint!!.color = ContextCompat.getColor( + context, + if (!isDarkMode) com.google.android.material.R.color.material_dynamic_neutral99 else com.google.android.material.R.color.material_dynamic_neutral10 + ) + centerClearCirclePaint!!.style = Paint.Style.FILL + + tickPaint = Paint() + tickPaint!!.color = ContextCompat.getColor( + context, + if (!isDarkMode) com.google.android.material.R.color.material_dynamic_neutral99 else com.google.android.material.R.color.material_dynamic_neutral10 + ) + tickPaint!!.style = Paint.Style.STROKE + tickPaint!!.strokeWidth = 4f + tickPaint!!.strokeCap = Paint.Cap.ROUND } - @Override - protected void onDraw(@NonNull Canvas canvas) { - super.onDraw(canvas); + override fun onDraw(canvas: Canvas) { + super.onDraw(canvas) - int width = getWidth(); - int height = getHeight(); + val width = width + val height = height - float cornerRadius = 12 * getResources().getDisplayMetrics().density; - squareRect.set(0, 0, width, height); - canvas.drawRoundRect(squareRect, cornerRadius, cornerRadius, squarePaint); + val cornerRadius = 12 * resources.displayMetrics.density + squareRect!![0f, 0f, width.toFloat()] = height.toFloat() + canvas.drawRoundRect(squareRect!!, cornerRadius, cornerRadius, squarePaint!!) - float padding = 6 * getResources().getDisplayMetrics().density; - float margin = 0 * getResources().getDisplayMetrics().density; + val padding = 6 * resources.displayMetrics.density + val margin = 0 * resources.displayMetrics.density - circleRect.set(padding, padding, width - padding, height - padding - margin); - canvas.drawArc(circleRect, 180, 180, true, halfCirclePaint); + circleRect!![padding, padding, width - padding] = height - padding - margin + canvas.drawArc(circleRect!!, 180f, 180f, true, halfCirclePaint!!) - circleRect.set(padding, padding + margin, width - padding - margin, height - padding); - canvas.drawArc(circleRect, 90, 90, true, firstQuarterCirclePaint); + circleRect!![padding, padding + margin, width - padding - margin] = height - padding + canvas.drawArc(circleRect!!, 90f, 90f, true, firstQuarterCirclePaint!!) - circleRect.set(padding + margin, padding + margin, width - padding, height - padding); - canvas.drawArc(circleRect, 0, 90, true, secondQuarterCirclePaint); + circleRect!![padding + margin, padding + margin, width - padding] = height - padding + canvas.drawArc(circleRect!!, 0f, 90f, true, secondQuarterCirclePaint!!) - circleRect.set(width / 2f - clearCircleRadius, height / 2f - clearCircleRadius, width / 2f + clearCircleRadius, height / 2f + clearCircleRadius); - canvas.drawArc(circleRect, 0, 360, true, centerClearCirclePaint); + circleRect!![width / 2f - clearCircleRadius, height / 2f - clearCircleRadius, width / 2f + clearCircleRadius] = + height / 2f + clearCircleRadius + canvas.drawArc(circleRect!!, 0f, 360f, true, centerClearCirclePaint!!) - circleRect.set(width / 2f - circleRadius, height / 2f - circleRadius, width / 2f + circleRadius, height / 2f + circleRadius); - canvas.drawCircle(width / 2f, height / 2f, circleRadius, centerCirclePaint); + circleRect!![width / 2f - circleRadius, height / 2f - circleRadius, width / 2f + circleRadius] = + height / 2f + circleRadius + canvas.drawCircle(width / 2f, height / 2f, circleRadius, centerCirclePaint!!) if (isSelected) { - tickPath.moveTo(width / 2f - circleRadius / 2, height / 2f); - tickPath.lineTo(width / 2f - circleRadius / 6, height / 2f + circleRadius / 3); - tickPath.lineTo(width / 2f + circleRadius / 2, height / 2f - circleRadius / 3); - canvas.drawPath(tickPath, tickPaint); + tickPath!!.moveTo(width / 2f - circleRadius / 2, height / 2f) + tickPath!!.lineTo(width / 2f - circleRadius / 6, height / 2f + circleRadius / 3) + tickPath!!.lineTo(width / 2f + circleRadius / 2, height / 2f - circleRadius / 3) + canvas.drawPath(tickPath!!, tickPaint!!) } } - private void setSquareColor(@ColorInt int color) { - squareColor = color; - squarePaint.setColor(color); - centerClearCirclePaint.setColor(color); + private fun setSquareColor(@ColorInt color: Int) { + squareColor = color + squarePaint!!.color = color + centerClearCirclePaint!!.color = color } - private void setFirstQuarterCircleColor(@ColorInt int color) { - firstQuarterCircleColor = color; - firstQuarterCirclePaint.setColor(color); + private fun setFirstQuarterCircleColor(@ColorInt color: Int) { + firstQuarterCircleColor = color + firstQuarterCirclePaint!!.color = color } - private void setSecondQuarterCircleColor(@ColorInt int color) { - secondQuarterCircleColor = color; - secondQuarterCirclePaint.setColor(color); + private fun setSecondQuarterCircleColor(@ColorInt color: Int) { + secondQuarterCircleColor = color + secondQuarterCirclePaint!!.color = color } - private void setHalfCircleColor(@ColorInt int color) { - halfCircleColor = color; - halfCirclePaint.setColor(color); + private fun setHalfCircleColor(@ColorInt color: Int) { + halfCircleColor = color + halfCirclePaint!!.color = color } - private void setCenterCircleColor(@ColorInt int color) { - centerCircleColor = color; - centerCirclePaint.setColor(color); - @ColorInt int textColor = ColorUtil.calculateTextColor(color); - tickPaint.setColor( - colorPalette != null ? - colorPalette.get(4).get(textColor == Color.WHITE ? 2 : 11) : - textColor - ); + private fun setCenterCircleColor(@ColorInt color: Int) { + centerCircleColor = color + centerCirclePaint!!.color = color + @ColorInt val textColor = calculateTextColor(color) + tickPaint!!.color = if (colorPalette != null) { + colorPalette!![4][if (textColor == Color.WHITE) 2 else 11] + } else { + textColor + } } - private void invalidateColors() { - invalidate(); + private fun invalidateColors() { + invalidate() } - public void setMainColor(@ColorInt int color) { - new Thread(() -> { + fun setMainColor(@ColorInt color: Int) { + Thread { try { - colorPalette = ColorUtil.generateModifiedColors( - ColorSchemeUtil.stringToEnumMonetStyle( - context, - RPrefs.getString(MONET_STYLE, context.getString(R.string.monet_tonalspot)) - ), - color, - RPrefs.getInt(MONET_ACCENT_SATURATION, 100), - RPrefs.getInt(MONET_BACKGROUND_SATURATION, 100), - RPrefs.getInt(MONET_BACKGROUND_LIGHTNESS, 100), - RPrefs.getBoolean(MONET_PITCH_BLACK_THEME, false), - RPrefs.getBoolean(MONET_ACCURATE_SHADES, true), - false, - SystemUtil.isDarkMode(), - false - ); - - setHalfCircleColor(colorPalette.get(0).get(4)); - setFirstQuarterCircleColor(colorPalette.get(2).get(5)); - setSecondQuarterCircleColor(colorPalette.get(1).get(6)); - setSquareColor(colorPalette.get(4).get(!isDarkMode ? 3 : 9)); - setCenterCircleColor(color); - invalidateColors(); - } catch (Exception ignored) { + colorPalette = generateModifiedColors( + stringToEnumMonetStyle( + context!!, + getString( + MONET_STYLE, + context!!.getString(R.string.monet_tonalspot) + )!! + ), + color, + getInt(MONET_ACCENT_SATURATION, 100), + getInt(MONET_BACKGROUND_SATURATION, 100), + getInt(MONET_BACKGROUND_LIGHTNESS, 100), + getBoolean(MONET_PITCH_BLACK_THEME, false), + getBoolean(MONET_ACCURATE_SHADES, true), + false, + SystemUtil.isDarkMode, + false + ) + + setHalfCircleColor(colorPalette!![0][4]) + setFirstQuarterCircleColor(colorPalette!![2][5]) + setSecondQuarterCircleColor(colorPalette!![1][6]) + setSquareColor(colorPalette!![4][if (!isDarkMode) 3 else 9]) + setCenterCircleColor(color) + invalidateColors() + } catch (ignored: Exception) { } - }).start(); + }.start() } - public void setSelected(boolean selected) { - isSelected = selected; - invalidateColors(); + override fun setSelected(selected: Boolean) { + isSelected = selected + invalidateColors() } - @Override - protected Parcelable onSaveInstanceState() { - Parcelable superState = super.onSaveInstanceState(); + override fun onSaveInstanceState(): Parcelable { + val superState = super.onSaveInstanceState() - SavedState ss = new SavedState(superState); - ss.halfCircleColor = halfCircleColor; - ss.firstQuarterCircleColor = firstQuarterCircleColor; - ss.secondQuarterCircleColor = secondQuarterCircleColor; - ss.squareColor = squareColor; - ss.centerCircleColor = centerCircleColor; + val ss = SavedState(superState) + ss.halfCircleColor = halfCircleColor + ss.firstQuarterCircleColor = firstQuarterCircleColor + ss.secondQuarterCircleColor = secondQuarterCircleColor + ss.squareColor = squareColor + ss.centerCircleColor = centerCircleColor - return ss; + return ss } - @Override - protected void onRestoreInstanceState(Parcelable state) { - if (!(state instanceof SavedState ss)) { - super.onRestoreInstanceState(state); - return; + override fun onRestoreInstanceState(state: Parcelable) { + if (state !is SavedState) { + super.onRestoreInstanceState(state) + return } - super.onRestoreInstanceState(ss.getSuperState()); + super.onRestoreInstanceState(state.superState) - setHalfCircleColor(ss.halfCircleColor); - setFirstQuarterCircleColor(ss.firstQuarterCircleColor); - setSecondQuarterCircleColor(ss.secondQuarterCircleColor); - setSquareColor(ss.squareColor); - setCenterCircleColor(ss.centerCircleColor); + setHalfCircleColor(state.halfCircleColor) + setFirstQuarterCircleColor(state.firstQuarterCircleColor) + setSecondQuarterCircleColor(state.secondQuarterCircleColor) + setSquareColor(state.squareColor) + setCenterCircleColor(state.centerCircleColor) } - private static class SavedState extends BaseSavedState { + private class SavedState : BaseSavedState { @ColorInt - int halfCircleColor, firstQuarterCircleColor, secondQuarterCircleColor, squareColor, centerCircleColor; + var halfCircleColor: Int = 0 - SavedState(Parcelable superState) { - super(superState); - } + @ColorInt + var firstQuarterCircleColor: Int = 0 + + @ColorInt + var secondQuarterCircleColor: Int = 0 + + @ColorInt + var squareColor: Int = 0 - private SavedState(Parcel in) { - super(in); - halfCircleColor = in.readInt(); - firstQuarterCircleColor = in.readInt(); - secondQuarterCircleColor = in.readInt(); - squareColor = in.readInt(); - centerCircleColor = in.readInt(); + @ColorInt + var centerCircleColor: Int = 0 + + constructor(superState: Parcelable?) : super(superState) + + private constructor(`in`: Parcel) : super(`in`) { + halfCircleColor = `in`.readInt() + firstQuarterCircleColor = `in`.readInt() + secondQuarterCircleColor = `in`.readInt() + squareColor = `in`.readInt() + centerCircleColor = `in`.readInt() } - @Override - public void writeToParcel(Parcel dest, int flags) { - super.writeToParcel(dest, flags); - dest.writeInt(halfCircleColor); - dest.writeInt(firstQuarterCircleColor); - dest.writeInt(secondQuarterCircleColor); - dest.writeInt(squareColor); - dest.writeInt(centerCircleColor); + override fun writeToParcel(dest: Parcel, flags: Int) { + super.writeToParcel(dest, flags) + dest.writeInt(halfCircleColor) + dest.writeInt(firstQuarterCircleColor) + dest.writeInt(secondQuarterCircleColor) + dest.writeInt(squareColor) + dest.writeInt(centerCircleColor) } - public static final Parcelable.Creator CREATOR = new Parcelable.Creator<>() { - public SavedState createFromParcel(Parcel in) { - return new SavedState(in); + companion object CREATOR : Parcelable.Creator { + override fun createFromParcel(parcel: Parcel): SavedState { + return SavedState(parcel) } - public SavedState[] newArray(int size) { - return new SavedState[size]; + override fun newArray(size: Int): Array { + return arrayOfNulls(size) } - }; + } + + override fun describeContents(): Int { + return 0 + } } - @Override - public void setEnabled(boolean enabled) { - super.setEnabled(enabled); - this.setAlpha(enabled ? 1.0f : 0.6f); + override fun setEnabled(enabled: Boolean) { + super.setEnabled(enabled) + this.alpha = if (enabled) 1.0f else 0.6f } } diff --git a/app/src/main/java/com/drdisagree/colorblendr/ui/widgets/ColorPickerWidget.kt b/app/src/main/java/com/drdisagree/colorblendr/ui/widgets/ColorPickerWidget.kt index 93073cd..1023bca 100644 --- a/app/src/main/java/com/drdisagree/colorblendr/ui/widgets/ColorPickerWidget.kt +++ b/app/src/main/java/com/drdisagree/colorblendr/ui/widgets/ColorPickerWidget.kt @@ -1,240 +1,243 @@ -package com.drdisagree.colorblendr.ui.widgets; - -import android.content.Context; -import android.content.res.ColorStateList; -import android.content.res.TypedArray; -import android.graphics.Color; -import android.graphics.drawable.Drawable; -import android.graphics.drawable.GradientDrawable; -import android.os.Parcel; -import android.os.Parcelable; -import android.util.AttributeSet; -import android.util.TypedValue; -import android.view.View; -import android.widget.ImageView; -import android.widget.RelativeLayout; -import android.widget.TextView; - -import androidx.annotation.ColorInt; -import androidx.annotation.Nullable; -import androidx.core.content.ContextCompat; - -import com.drdisagree.colorblendr.R; -import com.drdisagree.colorblendr.utils.SystemUtil; -import com.google.android.material.card.MaterialCardView; - -public class ColorPickerWidget extends RelativeLayout { - - private MaterialCardView container; - private TextView titleTextView; - private TextView summaryTextView; - private ImageView iconImageView; - private View colorView; - private @ColorInt int selectedColor = Color.WHITE; - - public ColorPickerWidget(Context context) { - super(context); - init(context, null); - } - - public ColorPickerWidget(Context context, AttributeSet attrs) { - super(context, attrs); - init(context, attrs); - } - - public ColorPickerWidget(Context context, AttributeSet attrs, int defStyleAttr) { - super(context, attrs, defStyleAttr); - init(context, attrs); - } - - private void init(Context context, AttributeSet attrs) { - inflate(context, R.layout.view_widget_colorpicker, this); - - initializeId(); - - TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.ColorPickerWidget); - setTitle(typedArray.getString(R.styleable.ColorPickerWidget_titleText)); - setSummary(typedArray.getString(R.styleable.ColorPickerWidget_summaryText)); - int icon = typedArray.getResourceId(R.styleable.ColorPickerWidget_icon, 0); - boolean iconSpaceReserved = typedArray.getBoolean(R.styleable.SwitchWidget_iconSpaceReserved, false); - int colorResId = typedArray.getResourceId(R.styleable.ColorPickerWidget_previewColor, Integer.MIN_VALUE); - selectedColor = typedArray.getColor(R.styleable.ColorPickerWidget_previewColor, Color.WHITE); - typedArray.recycle(); +package com.drdisagree.colorblendr.ui.widgets + +import android.content.Context +import android.content.res.ColorStateList +import android.content.res.TypedArray +import android.graphics.Color +import android.graphics.drawable.Drawable +import android.graphics.drawable.GradientDrawable +import android.os.Parcel +import android.os.Parcelable +import android.util.AttributeSet +import android.util.TypedValue +import android.view.View +import android.widget.ImageView +import android.widget.RelativeLayout +import android.widget.TextView +import androidx.annotation.ColorInt +import androidx.core.content.ContextCompat +import com.drdisagree.colorblendr.R +import com.drdisagree.colorblendr.utils.SystemUtil.isDarkMode +import com.google.android.material.card.MaterialCardView + +class ColorPickerWidget : RelativeLayout { + + private var container: MaterialCardView? = null + private var titleTextView: TextView? = null + private var summaryTextView: TextView? = null + private var iconImageView: ImageView? = null + private var colorView: View? = null + + @ColorInt + private var selectedColor: Int = Color.WHITE + + constructor(context: Context) : super(context) { + init(context, null) + } + + constructor(context: Context, attrs: AttributeSet?) : super(context, attrs) { + init(context, attrs) + } + + constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super( + context, + attrs, + defStyleAttr + ) { + init(context, attrs) + } + + private fun init(context: Context, attrs: AttributeSet?) { + inflate(context, R.layout.view_widget_colorpicker, this) + + initializeId() + + val typedArray: TypedArray = + context.obtainStyledAttributes(attrs, R.styleable.ColorPickerWidget) + setTitle(typedArray.getString(R.styleable.ColorPickerWidget_titleText)) + setSummary(typedArray.getString(R.styleable.ColorPickerWidget_summaryText)) + val icon: Int = typedArray.getResourceId(R.styleable.ColorPickerWidget_icon, 0) + var iconSpaceReserved: Boolean = + typedArray.getBoolean(R.styleable.SwitchWidget_iconSpaceReserved, false) + val colorResId: Int = + typedArray.getResourceId(R.styleable.ColorPickerWidget_previewColor, Int.MIN_VALUE) + selectedColor = typedArray.getColor(R.styleable.ColorPickerWidget_previewColor, Color.WHITE) + typedArray.recycle() if (icon != 0) { - iconSpaceReserved = true; - iconImageView.setImageResource(icon); + iconSpaceReserved = true + iconImageView!!.setImageResource(icon) } if (!iconSpaceReserved) { - iconImageView.setVisibility(GONE); + iconImageView!!.setVisibility(GONE) } - if (colorResId != Integer.MIN_VALUE) { - setPreviewColor(ContextCompat.getColor(getContext(), colorResId)); + if (colorResId != Int.MIN_VALUE) { + previewColor = ContextCompat.getColor(getContext(), colorResId) } } - public void setTitle(int titleResId) { - titleTextView.setText(titleResId); + fun setTitle(titleResId: Int) { + titleTextView!!.setText(titleResId) } - public void setTitle(String title) { - titleTextView.setText(title); + fun setTitle(title: String?) { + titleTextView!!.text = title } - public void setSummary(int summaryResId) { - summaryTextView.setText(summaryResId); + fun setSummary(summaryResId: Int) { + summaryTextView!!.setText(summaryResId) } - public void setSummary(String summary) { - summaryTextView.setText(summary); + fun setSummary(summary: String?) { + summaryTextView!!.text = summary } - public void setIcon(int icon) { - iconImageView.setImageResource(icon); - iconImageView.setVisibility(VISIBLE); + fun setIcon(icon: Int) { + iconImageView!!.setImageResource(icon) + iconImageView!!.setVisibility(VISIBLE) } - public void setIcon(Drawable drawable) { - iconImageView.setImageDrawable(drawable); - iconImageView.setVisibility(VISIBLE); + fun setIcon(drawable: Drawable?) { + iconImageView!!.setImageDrawable(drawable) + iconImageView!!.setVisibility(VISIBLE) } - public void setIconVisibility(int visibility) { - iconImageView.setVisibility(visibility); + fun setIconVisibility(visibility: Int) { + iconImageView!!.setVisibility(visibility) } - public @ColorInt int getPreviewColor() { - return selectedColor; - } - - public void setPreviewColor(@ColorInt int color) { - this.selectedColor = color; - - if (!isEnabled()) { - if (SystemUtil.isDarkMode()) { - color = Color.DKGRAY; - } else { - color = Color.LTGRAY; - } + @get:ColorInt + var previewColor: Int + get() { + return selectedColor } + set(color) { + var colorTemp: Int = color + this.selectedColor = colorTemp + + if (!isEnabled) { + colorTemp = if (isDarkMode) { + Color.DKGRAY + } else { + Color.LTGRAY + } + } - GradientDrawable drawable = new GradientDrawable( + val drawable = GradientDrawable( GradientDrawable.Orientation.LEFT_RIGHT, - new int[]{color, color} - ); - drawable.setShape(GradientDrawable.OVAL); - colorView.setBackground(drawable); - } + intArrayOf(colorTemp, colorTemp) + ) + drawable.setShape(GradientDrawable.OVAL) + colorView!!.background = drawable + } - @Override - public void setEnabled(boolean enabled) { - super.setEnabled(enabled); + override fun setEnabled(enabled: Boolean) { + super.setEnabled(enabled) if (enabled) { - TypedValue typedValue = new TypedValue(); - TypedArray a = getContext().obtainStyledAttributes( - typedValue.data, - new int[]{com.google.android.material.R.attr.colorPrimary} - ); - int color = a.getColor(0, 0); - a.recycle(); - - iconImageView.setImageTintList(ColorStateList.valueOf(color)); - - titleTextView.setAlpha(1.0f); - summaryTextView.setAlpha(0.8f); + val typedValue = TypedValue() + val a: TypedArray = context.obtainStyledAttributes( + typedValue.data, + intArrayOf(com.google.android.material.R.attr.colorPrimary) + ) + val color: Int = a.getColor(0, 0) + a.recycle() + + iconImageView!!.setImageTintList(ColorStateList.valueOf(color)) + + titleTextView!!.setAlpha(1.0f) + summaryTextView!!.setAlpha(0.8f) } else { - if (SystemUtil.isDarkMode()) { - iconImageView.setImageTintList(ColorStateList.valueOf(Color.DKGRAY)); + if (isDarkMode) { + iconImageView!!.setImageTintList(ColorStateList.valueOf(Color.DKGRAY)) } else { - iconImageView.setImageTintList(ColorStateList.valueOf(Color.LTGRAY)); + iconImageView!!.setImageTintList(ColorStateList.valueOf(Color.LTGRAY)) } - titleTextView.setAlpha(0.6f); - summaryTextView.setAlpha(0.4f); + titleTextView!!.setAlpha(0.6f) + summaryTextView!!.setAlpha(0.4f) } - container.setEnabled(enabled); - titleTextView.setEnabled(enabled); - summaryTextView.setEnabled(enabled); - iconImageView.setEnabled(enabled); - setPreviewColor(enabled ? getPreviewColor() : Color.GRAY); + container!!.setEnabled(enabled) + titleTextView!!.setEnabled(enabled) + summaryTextView!!.setEnabled(enabled) + iconImageView!!.setEnabled(enabled) + previewColor = if (enabled) previewColor else Color.GRAY } // to avoid listener bug, we need to re-generate unique id for each view - private void initializeId() { - container = findViewById(R.id.container); - iconImageView = findViewById(R.id.icon); - titleTextView = findViewById(R.id.title); - summaryTextView = findViewById(R.id.summary); - colorView = findViewById(R.id.color_widget); + private fun initializeId() { + container = findViewById(R.id.container) + iconImageView = findViewById(R.id.icon) + titleTextView = findViewById(R.id.title) + summaryTextView = findViewById(R.id.summary) + colorView = findViewById(R.id.color_widget) - container.setId(View.generateViewId()); - iconImageView.setId(View.generateViewId()); - titleTextView.setId(View.generateViewId()); - summaryTextView.setId(View.generateViewId()); - colorView.setId(View.generateViewId()); + container!!.setId(generateViewId()) + iconImageView!!.setId(generateViewId()) + titleTextView!!.setId(generateViewId()) + summaryTextView!!.setId(generateViewId()) + colorView!!.setId(generateViewId()) - LayoutParams layoutParams = (LayoutParams) findViewById(R.id.text_container).getLayoutParams(); - layoutParams.addRule(RelativeLayout.START_OF, colorView.getId()); - layoutParams.addRule(RelativeLayout.END_OF, iconImageView.getId()); - findViewById(R.id.text_container).setLayoutParams(layoutParams); + val layoutParams: LayoutParams = + findViewById(R.id.text_container).layoutParams as LayoutParams + layoutParams.addRule(START_OF, colorView!!.id) + layoutParams.addRule(END_OF, iconImageView!!.id) + findViewById(R.id.text_container).setLayoutParams(layoutParams) } - @Override - public void setOnClickListener(@Nullable OnClickListener l) { - container.setOnClickListener(l); + override fun setOnClickListener(l: OnClickListener?) { + container!!.setOnClickListener(l) } - @Override - protected Parcelable onSaveInstanceState() { - Parcelable superState = super.onSaveInstanceState(); + override fun onSaveInstanceState(): Parcelable { + val superState: Parcelable? = super.onSaveInstanceState() - SavedState ss = new SavedState(superState); - ss.selectedColor = selectedColor; + val ss = SavedState(superState) + ss.selectedColor = selectedColor - return ss; + return ss } - @Override - protected void onRestoreInstanceState(Parcelable state) { - if (!(state instanceof SavedState ss)) { - super.onRestoreInstanceState(state); - return; + override fun onRestoreInstanceState(state: Parcelable) { + if (state !is SavedState) { + super.onRestoreInstanceState(state) + return } - super.onRestoreInstanceState(ss.getSuperState()); + super.onRestoreInstanceState(state.superState) - setPreviewColor(ss.selectedColor); + previewColor = state.selectedColor } - private static class SavedState extends BaseSavedState { - public static final Creator CREATOR = new Creator<>() { - public SavedState createFromParcel(Parcel in) { - return new SavedState(in); - } + private class SavedState : BaseSavedState { + var selectedColor: Int = 0 - public SavedState[] newArray(int size) { - return new SavedState[size]; - } - }; - int selectedColor; + constructor(superState: Parcelable?) : super(superState) + + private constructor(`in`: Parcel) : super(`in`) { + selectedColor = `in`.readInt() + } - SavedState(Parcelable superState) { - super(superState); + override fun writeToParcel(dest: Parcel, flags: Int) { + super.writeToParcel(dest, flags) + dest.writeInt(selectedColor) } - private SavedState(Parcel in) { - super(in); - selectedColor = in.readInt(); + companion object CREATOR : Parcelable.Creator { + override fun createFromParcel(parcel: Parcel): SavedState { + return SavedState(parcel) + } + + override fun newArray(size: Int): Array { + return arrayOfNulls(size) + } } - @Override - public void writeToParcel(Parcel dest, int flags) { - super.writeToParcel(dest, flags); - dest.writeInt(selectedColor); + override fun describeContents(): Int { + return 0 } } } diff --git a/app/src/main/java/com/drdisagree/colorblendr/ui/widgets/MenuWidget.kt b/app/src/main/java/com/drdisagree/colorblendr/ui/widgets/MenuWidget.kt index 64f6192..c9fd825 100644 --- a/app/src/main/java/com/drdisagree/colorblendr/ui/widgets/MenuWidget.kt +++ b/app/src/main/java/com/drdisagree/colorblendr/ui/widgets/MenuWidget.kt @@ -1,174 +1,177 @@ -package com.drdisagree.colorblendr.ui.widgets; +package com.drdisagree.colorblendr.ui.widgets -import android.content.Context; -import android.content.res.ColorStateList; -import android.content.res.TypedArray; -import android.graphics.Color; -import android.graphics.drawable.Drawable; -import android.util.AttributeSet; -import android.util.TypedValue; -import android.view.View; -import android.widget.ImageView; -import android.widget.RelativeLayout; -import android.widget.TextView; +import android.content.Context +import android.content.res.ColorStateList +import android.graphics.Color +import android.graphics.drawable.Drawable +import android.util.AttributeSet +import android.util.TypedValue +import android.view.View +import android.widget.ImageView +import android.widget.RelativeLayout +import android.widget.TextView +import com.drdisagree.colorblendr.R +import com.drdisagree.colorblendr.utils.SystemUtil.isDarkMode +import com.google.android.material.card.MaterialCardView +import com.google.android.material.color.MaterialColors -import androidx.annotation.Nullable; +class MenuWidget : RelativeLayout { -import com.drdisagree.colorblendr.R; -import com.drdisagree.colorblendr.utils.SystemUtil; -import com.google.android.material.card.MaterialCardView; -import com.google.android.material.color.MaterialColors; + private var container: MaterialCardView? = null + private var titleTextView: TextView? = null + private var summaryTextView: TextView? = null + private var iconImageView: ImageView? = null + private var endArrowImageView: ImageView? = null -public class MenuWidget extends RelativeLayout { - - private MaterialCardView container; - private TextView titleTextView; - private TextView summaryTextView; - private ImageView iconImageView; - private ImageView endArrowImageView; - - public MenuWidget(Context context) { - super(context); - init(context, null); + constructor(context: Context) : super(context) { + init(context, null) } - public MenuWidget(Context context, AttributeSet attrs) { - super(context, attrs); - init(context, attrs); + constructor(context: Context, attrs: AttributeSet?) : super(context, attrs) { + init(context, attrs) } - public MenuWidget(Context context, AttributeSet attrs, int defStyleAttr) { - super(context, attrs, defStyleAttr); - init(context, attrs); + constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super( + context, + attrs, + defStyleAttr + ) { + init(context, attrs) } - private void init(Context context, AttributeSet attrs) { - inflate(context, R.layout.view_widget_menu, this); + private fun init(context: Context, attrs: AttributeSet?) { + inflate(context, R.layout.view_widget_menu, this) - initializeId(); + initializeId() - TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.MenuWidget); - setTitle(typedArray.getString(R.styleable.MenuWidget_titleText)); - setSummary(typedArray.getString(R.styleable.MenuWidget_summaryText)); - int icon = typedArray.getResourceId(R.styleable.MenuWidget_icon, 0); - boolean iconSpaceReserved = typedArray.getBoolean(R.styleable.MenuWidget_iconSpaceReserved, false); - boolean showEndArrow = typedArray.getBoolean(R.styleable.MenuWidget_showEndArrow, false); - typedArray.recycle(); + val typedArray = context.obtainStyledAttributes(attrs, R.styleable.MenuWidget) + setTitle(typedArray.getString(R.styleable.MenuWidget_titleText)) + setSummary(typedArray.getString(R.styleable.MenuWidget_summaryText)) + val icon = typedArray.getResourceId(R.styleable.MenuWidget_icon, 0) + var iconSpaceReserved = + typedArray.getBoolean(R.styleable.MenuWidget_iconSpaceReserved, false) + val showEndArrow = typedArray.getBoolean(R.styleable.MenuWidget_showEndArrow, false) + typedArray.recycle() if (icon != 0) { - iconSpaceReserved = true; - iconImageView.setImageResource(icon); + iconSpaceReserved = true + iconImageView!!.setImageResource(icon) } if (!iconSpaceReserved) { - iconImageView.setVisibility(GONE); + iconImageView!!.visibility = GONE } if (showEndArrow) { - endArrowImageView.setVisibility(VISIBLE); + endArrowImageView!!.visibility = VISIBLE } } - public void setTitle(int titleResId) { - titleTextView.setText(titleResId); + fun setTitle(titleResId: Int) { + titleTextView!!.setText(titleResId) } - public void setTitle(String title) { - titleTextView.setText(title); + fun setTitle(title: String?) { + titleTextView!!.text = title } - public void setSummary(int summaryResId) { - summaryTextView.setText(summaryResId); + fun setSummary(summaryResId: Int) { + summaryTextView!!.setText(summaryResId) } - public void setSummary(String summary) { - summaryTextView.setText(summary); + fun setSummary(summary: String?) { + summaryTextView!!.text = summary } - public void setIcon(int icon) { - iconImageView.setImageResource(icon); - iconImageView.setVisibility(VISIBLE); + fun setIcon(icon: Int) { + iconImageView!!.setImageResource(icon) + iconImageView!!.visibility = VISIBLE } - public void setIcon(Drawable drawable) { - iconImageView.setImageDrawable(drawable); - iconImageView.setVisibility(VISIBLE); + fun setIcon(drawable: Drawable?) { + iconImageView!!.setImageDrawable(drawable) + iconImageView!!.visibility = VISIBLE } - public void setIconVisibility(int visibility) { - iconImageView.setVisibility(visibility); + fun setIconVisibility(visibility: Int) { + iconImageView!!.visibility = visibility } - public void setEndArrowVisibility(int visibility) { - endArrowImageView.setVisibility(visibility); + fun setEndArrowVisibility(visibility: Int) { + endArrowImageView!!.visibility = visibility } - @Override - public void setOnClickListener(@Nullable OnClickListener l) { - container.setOnClickListener(l); + override fun setOnClickListener(l: OnClickListener?) { + container!!.setOnClickListener(l) } - @Override - public void setOnLongClickListener(@Nullable OnLongClickListener l) { - container.setOnLongClickListener(l); + override fun setOnLongClickListener(l: OnLongClickListener?) { + container!!.setOnLongClickListener(l) } - @Override - public void setEnabled(boolean enabled) { - super.setEnabled(enabled); + override fun setEnabled(enabled: Boolean) { + super.setEnabled(enabled) if (enabled) { - TypedValue typedValue = new TypedValue(); - TypedArray a = getContext().obtainStyledAttributes( - typedValue.data, - new int[]{com.google.android.material.R.attr.colorPrimary} - ); - int color = a.getColor(0, 0); - a.recycle(); - - iconImageView.setImageTintList(ColorStateList.valueOf(color)); - endArrowImageView.setImageTintList(ColorStateList.valueOf( - MaterialColors.getColor(this, com.google.android.material.R.attr.colorOnSurface) - )); - - titleTextView.setAlpha(1.0f); - summaryTextView.setAlpha(0.8f); + val typedValue = TypedValue() + val a = context.obtainStyledAttributes( + typedValue.data, + intArrayOf(com.google.android.material.R.attr.colorPrimary) + ) + val color = a.getColor(0, 0) + a.recycle() + + iconImageView!!.imageTintList = ColorStateList.valueOf(color) + endArrowImageView!!.imageTintList = ColorStateList.valueOf( + MaterialColors.getColor( + this, + com.google.android.material.R.attr.colorOnSurface + ) + ) + + titleTextView!!.alpha = 1.0f + summaryTextView!!.alpha = 0.8f } else { - if (SystemUtil.isDarkMode()) { - iconImageView.setImageTintList(ColorStateList.valueOf(Color.DKGRAY)); - endArrowImageView.setImageTintList(ColorStateList.valueOf(Color.DKGRAY)); + if (isDarkMode) { + iconImageView!!.imageTintList = + ColorStateList.valueOf(Color.DKGRAY) + endArrowImageView!!.imageTintList = + ColorStateList.valueOf(Color.DKGRAY) } else { - iconImageView.setImageTintList(ColorStateList.valueOf(Color.LTGRAY)); - endArrowImageView.setImageTintList(ColorStateList.valueOf(Color.LTGRAY)); + iconImageView!!.imageTintList = + ColorStateList.valueOf(Color.LTGRAY) + endArrowImageView!!.imageTintList = + ColorStateList.valueOf(Color.LTGRAY) } - titleTextView.setAlpha(0.6f); - summaryTextView.setAlpha(0.4f); + titleTextView!!.alpha = 0.6f + summaryTextView!!.alpha = 0.4f } - container.setEnabled(enabled); - iconImageView.setEnabled(enabled); - titleTextView.setEnabled(enabled); - summaryTextView.setEnabled(enabled); + container!!.isEnabled = enabled + iconImageView!!.isEnabled = enabled + titleTextView!!.isEnabled = enabled + summaryTextView!!.isEnabled = enabled } // to avoid listener bug, we need to re-generate unique id for each view - private void initializeId() { - container = findViewById(R.id.container); - iconImageView = findViewById(R.id.icon); - titleTextView = findViewById(R.id.title); - summaryTextView = findViewById(R.id.summary); - endArrowImageView = findViewById(R.id.end_arrow); - - container.setId(View.generateViewId()); - iconImageView.setId(View.generateViewId()); - titleTextView.setId(View.generateViewId()); - summaryTextView.setId(View.generateViewId()); - endArrowImageView.setId(View.generateViewId()); - - LayoutParams layoutParams = (LayoutParams) findViewById(R.id.text_container).getLayoutParams(); - layoutParams.addRule(RelativeLayout.START_OF, endArrowImageView.getId()); - layoutParams.addRule(RelativeLayout.END_OF, iconImageView.getId()); - findViewById(R.id.text_container).setLayoutParams(layoutParams); + private fun initializeId() { + container = findViewById(R.id.container) + iconImageView = findViewById(R.id.icon) + titleTextView = findViewById(R.id.title) + summaryTextView = findViewById(R.id.summary) + endArrowImageView = findViewById(R.id.end_arrow) + + container!!.setId(generateViewId()) + iconImageView!!.setId(generateViewId()) + titleTextView!!.setId(generateViewId()) + summaryTextView!!.setId(generateViewId()) + endArrowImageView!!.setId(generateViewId()) + + val textContainer = findViewById(R.id.text_container) + val layoutParams = textContainer.layoutParams as LayoutParams + layoutParams.addRule(START_OF, endArrowImageView!!.id) + layoutParams.addRule(END_OF, iconImageView!!.id) + textContainer.layoutParams = layoutParams } } diff --git a/app/src/main/java/com/drdisagree/colorblendr/ui/widgets/ResizableSeekbar.kt b/app/src/main/java/com/drdisagree/colorblendr/ui/widgets/ResizableSeekbar.kt index e0698a8..029cd1a 100644 --- a/app/src/main/java/com/drdisagree/colorblendr/ui/widgets/ResizableSeekbar.kt +++ b/app/src/main/java/com/drdisagree/colorblendr/ui/widgets/ResizableSeekbar.kt @@ -1,28 +1,26 @@ -package com.drdisagree.colorblendr.ui.widgets; +package com.drdisagree.colorblendr.ui.widgets -import android.content.Context; -import android.graphics.drawable.Drawable; -import android.util.AttributeSet; +import android.content.Context +import android.util.AttributeSet +import androidx.appcompat.widget.AppCompatSeekBar -public class ResizableSeekbar extends androidx.appcompat.widget.AppCompatSeekBar { +class ResizableSeekbar : AppCompatSeekBar { - public ResizableSeekbar(Context context) { - super(context); - } + constructor(context: Context) : super(context) - public ResizableSeekbar(Context context, AttributeSet attrs) { - super(context, attrs); - } + constructor(context: Context, attrs: AttributeSet?) : super(context, attrs) - public ResizableSeekbar(Context context, AttributeSet attrs, int defStyle) { - super(context, attrs, defStyle); - } + constructor(context: Context, attrs: AttributeSet?, defStyle: Int) : super( + context, + attrs, + defStyle + ) - @Override - protected synchronized void onSizeChanged(int w, int h, int oldw, int oldh) { - super.onSizeChanged(w, h, oldw, oldh); + @Synchronized + override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) { + super.onSizeChanged(w, h, oldw, oldh) - Drawable trackDrawable = getProgressDrawable().getCurrent(); - trackDrawable.setBounds(0, 0, getMeasuredWidth(), getMeasuredHeight()); + val trackDrawable = progressDrawable.current + trackDrawable.setBounds(0, 0, measuredWidth, measuredHeight) } } diff --git a/app/src/main/java/com/drdisagree/colorblendr/ui/widgets/SeekbarWidget.kt b/app/src/main/java/com/drdisagree/colorblendr/ui/widgets/SeekbarWidget.kt index 558ab1e..d6a0045 100644 --- a/app/src/main/java/com/drdisagree/colorblendr/ui/widgets/SeekbarWidget.kt +++ b/app/src/main/java/com/drdisagree/colorblendr/ui/widgets/SeekbarWidget.kt @@ -1,280 +1,270 @@ -package com.drdisagree.colorblendr.ui.widgets; - -import android.content.Context; -import android.content.res.TypedArray; -import android.os.Parcel; -import android.os.Parcelable; -import android.util.AttributeSet; -import android.view.View; -import android.widget.ImageView; -import android.widget.RelativeLayout; -import android.widget.SeekBar; -import android.widget.TextView; -import android.widget.Toast; - -import com.drdisagree.colorblendr.R; -import com.google.android.material.card.MaterialCardView; - -import java.text.DecimalFormat; -import java.util.Objects; - -public class SeekbarWidget extends RelativeLayout { - - private MaterialCardView container; - private TextView titleTextView; - private TextView summaryTextView; - private SeekBar seekBar; - private ImageView resetIcon; - private String valueFormat; - private int defaultValue; - private float outputScale = 1f; - private boolean isDecimalFormat = false; - private String decimalFormat = "#.#"; - private OnLongClickListener resetClickListener; - - public SeekbarWidget(Context context) { - super(context); - init(context, null); +package com.drdisagree.colorblendr.ui.widgets + +import android.content.Context +import android.os.Parcel +import android.os.Parcelable +import android.util.AttributeSet +import android.view.View +import android.widget.ImageView +import android.widget.RelativeLayout +import android.widget.SeekBar +import android.widget.SeekBar.OnSeekBarChangeListener +import android.widget.TextView +import android.widget.Toast +import com.drdisagree.colorblendr.R +import com.google.android.material.card.MaterialCardView +import java.text.DecimalFormat +import java.util.Objects + +class SeekbarWidget : RelativeLayout { + + private var container: MaterialCardView? = null + private var titleTextView: TextView? = null + private var summaryTextView: TextView? = null + private var seekBar: SeekBar? = null + private var resetIcon: ImageView? = null + private var valueFormat: String? = null + private var defaultValue = 0 + private var outputScale = 1f + private var isDecimalFormat = false + private var decimalFormat: String? = "#.#" + private var resetClickListener: OnLongClickListener? = null + + constructor(context: Context) : super(context) { + init(context, null) } - public SeekbarWidget(Context context, AttributeSet attrs) { - super(context, attrs); - init(context, attrs); + constructor(context: Context, attrs: AttributeSet?) : super(context, attrs) { + init(context, attrs) } - public SeekbarWidget(Context context, AttributeSet attrs, int defStyleAttr) { - super(context, attrs, defStyleAttr); - init(context, attrs); + constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super( + context, + attrs, + defStyleAttr + ) { + init(context, attrs) } - private void init(Context context, AttributeSet attrs) { - inflate(context, R.layout.view_widget_seekbar, this); - - initializeId(); - - TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.SeekbarWidget); - valueFormat = typedArray.getString(R.styleable.SeekbarWidget_progressFormat); - defaultValue = typedArray.getInt(R.styleable.SeekbarWidget_seekbarDefaultProgress, Integer.MAX_VALUE); - setTitle(typedArray.getString(R.styleable.SeekbarWidget_titleText)); - setSeekbarMinProgress(typedArray.getInt(R.styleable.SeekbarWidget_seekbarMinProgress, 0)); - setSeekbarMaxProgress(typedArray.getInt(R.styleable.SeekbarWidget_seekbarMaxProgress, 100)); - setSeekbarProgress(typedArray.getInt( - R.styleable.SeekbarWidget_seekbarProgress, - typedArray.getInt(R.styleable.SeekbarWidget_seekbarDefaultProgress, 50) - )); - isDecimalFormat = typedArray.getBoolean(R.styleable.SeekbarWidget_isDecimalFormat, false); - decimalFormat = typedArray.getString(R.styleable.SeekbarWidget_decimalFormat); - outputScale = typedArray.getFloat(R.styleable.SeekbarWidget_outputScale, 1f); - typedArray.recycle(); + private fun init(context: Context, attrs: AttributeSet?) { + inflate(context, R.layout.view_widget_seekbar, this) + + initializeId() + + val typedArray = context.obtainStyledAttributes(attrs, R.styleable.SeekbarWidget) + valueFormat = typedArray.getString(R.styleable.SeekbarWidget_progressFormat) + defaultValue = + typedArray.getInt(R.styleable.SeekbarWidget_seekbarDefaultProgress, Int.MAX_VALUE) + setTitle(typedArray.getString(R.styleable.SeekbarWidget_titleText)) + setSeekbarMinProgress(typedArray.getInt(R.styleable.SeekbarWidget_seekbarMinProgress, 0)) + setSeekbarMaxProgress(typedArray.getInt(R.styleable.SeekbarWidget_seekbarMaxProgress, 100)) + seekbarProgress = typedArray.getInt( + R.styleable.SeekbarWidget_seekbarProgress, + typedArray.getInt(R.styleable.SeekbarWidget_seekbarDefaultProgress, 50) + ) + isDecimalFormat = typedArray.getBoolean(R.styleable.SeekbarWidget_isDecimalFormat, false) + decimalFormat = typedArray.getString(R.styleable.SeekbarWidget_decimalFormat) + outputScale = typedArray.getFloat(R.styleable.SeekbarWidget_outputScale, 1f) + typedArray.recycle() if (valueFormat == null) { - valueFormat = ""; + valueFormat = "" } if (decimalFormat == null) { - decimalFormat = "#.#"; + decimalFormat = "#.#" } - setSelectedProgress(); - handleResetVisibility(); - setOnSeekbarChangeListener(null); - setResetClickListener(null); + setSelectedProgress() + handleResetVisibility() + setOnSeekbarChangeListener(null) + setResetClickListener(null) } - public void setTitle(int titleResId) { - titleTextView.setText(titleResId); + fun setTitle(titleResId: Int) { + titleTextView!!.setText(titleResId) } - public void setTitle(String title) { - titleTextView.setText(title); + fun setTitle(title: String?) { + titleTextView!!.text = title } - public void setSelectedProgress() { - summaryTextView.setText( - (valueFormat.isBlank() || valueFormat.isEmpty() ? - getContext().getString( - R.string.opt_selected1, - String.valueOf( - !isDecimalFormat ? - (int) (seekBar.getProgress() / outputScale) : - new DecimalFormat(decimalFormat) - .format(seekBar.getProgress() / outputScale) - ) - ) : - getContext().getString( - R.string.opt_selected2, - !isDecimalFormat ? - String.valueOf((int) seekBar.getProgress()) : - new DecimalFormat(decimalFormat) - .format(seekBar.getProgress() / outputScale), - valueFormat - ) + fun setSelectedProgress() { + summaryTextView!!.text = if (valueFormat!!.isBlank() || valueFormat!!.isEmpty()) { + context.getString( + R.string.opt_selected1, + (if (!isDecimalFormat) (seekBar!!.progress / outputScale).toInt() else DecimalFormat( + decimalFormat ) - ); - } - - public int getSeekbarProgress() { - return (int) seekBar.getProgress(); + .format((seekBar!!.progress / outputScale).toDouble())).toString() + ) + } else { + context.getString( + R.string.opt_selected2, + if (!isDecimalFormat) seekBar!!.progress.toString() else DecimalFormat( + decimalFormat + ) + .format((seekBar!!.progress / outputScale).toDouble()), + valueFormat + ) + } } - public void setSeekbarProgress(int value) { - seekBar.setProgress(value); - setSelectedProgress(); - handleResetVisibility(); - } + var seekbarProgress: Int + get() = seekBar!!.progress + set(value) { + seekBar!!.progress = value + setSelectedProgress() + handleResetVisibility() + } - public void setSeekbarMinProgress(int value) { - seekBar.setMin(value); + fun setSeekbarMinProgress(value: Int) { + seekBar!!.min = value } - public void setSeekbarMaxProgress(int value) { - seekBar.setMax(value); + fun setSeekbarMaxProgress(value: Int) { + seekBar!!.max = value } - public void setIsDecimalFormat(boolean isDecimalFormat) { - this.isDecimalFormat = isDecimalFormat; - setSelectedProgress(); + fun setIsDecimalFormat(isDecimalFormat: Boolean) { + this.isDecimalFormat = isDecimalFormat + setSelectedProgress() } - public void setDecimalFormat(String decimalFormat) { - this.decimalFormat = Objects.requireNonNullElse(decimalFormat, "#.#"); - setSelectedProgress(); + fun setDecimalFormat(decimalFormat: String) { + this.decimalFormat = Objects.requireNonNullElse(decimalFormat, "#.#") + setSelectedProgress() } - public void setOutputScale(float scale) { - this.outputScale = scale; - setSelectedProgress(); + fun setOutputScale(scale: Float) { + this.outputScale = scale + setSelectedProgress() } - public void setOnSeekbarChangeListener(SeekBar.OnSeekBarChangeListener listener) { - seekBar.setOnSeekBarChangeListener(listener); + fun setOnSeekbarChangeListener(listener: OnSeekBarChangeListener?) { + seekBar!!.setOnSeekBarChangeListener(listener) } - public void setResetClickListener(OnLongClickListener listener) { - resetClickListener = listener; + fun setResetClickListener(listener: OnLongClickListener?) { + resetClickListener = listener - resetIcon.setOnClickListener(v -> { - if (defaultValue == Integer.MAX_VALUE) { - return; + resetIcon!!.setOnClickListener { + if (defaultValue == Int.MAX_VALUE) { + return@setOnClickListener } + Toast.makeText(context, R.string.long_press_to_reset, Toast.LENGTH_SHORT).show() + } - Toast.makeText(getContext(), R.string.long_press_to_reset, Toast.LENGTH_SHORT).show(); - }); - - resetIcon.setOnLongClickListener(v -> { - if (defaultValue == Integer.MAX_VALUE) { - return false; + resetIcon!!.setOnLongClickListener { v: View -> + if (defaultValue == Int.MAX_VALUE) { + return@setOnLongClickListener false } - - setSeekbarProgress(defaultValue); - handleResetVisibility(); - notifyOnResetClicked(v); - - return true; - }); + seekbarProgress = defaultValue + handleResetVisibility() + notifyOnResetClicked(v) + true + } } - public void resetSeekbar() { - resetIcon.performLongClick(); + fun resetSeekbar() { + resetIcon!!.performLongClick() } - private void notifyOnResetClicked(View v) { + private fun notifyOnResetClicked(v: View) { if (resetClickListener != null) { - resetClickListener.onLongClick(v); + resetClickListener!!.onLongClick(v) } } - private void handleResetVisibility() { - if (defaultValue != Integer.MAX_VALUE && seekBar.getProgress() != defaultValue) { - resetIcon.setVisibility(VISIBLE); + private fun handleResetVisibility() { + if (defaultValue != Int.MAX_VALUE && seekBar!!.progress != defaultValue) { + resetIcon!!.visibility = VISIBLE } else { - resetIcon.setVisibility(GONE); + resetIcon!!.visibility = GONE } } - @Override - public void setEnabled(boolean enabled) { - super.setEnabled(enabled); + override fun setEnabled(enabled: Boolean) { + super.setEnabled(enabled) - container.setEnabled(enabled); - titleTextView.setEnabled(enabled); - summaryTextView.setEnabled(enabled); - resetIcon.setEnabled(enabled); - seekBar.setEnabled(enabled); + container!!.isEnabled = enabled + titleTextView!!.isEnabled = enabled + summaryTextView!!.isEnabled = enabled + resetIcon!!.isEnabled = enabled + seekBar!!.isEnabled = enabled if (enabled) { - titleTextView.setAlpha(1.0f); - summaryTextView.setAlpha(0.8f); + titleTextView!!.alpha = 1.0f + summaryTextView!!.alpha = 0.8f } else { - titleTextView.setAlpha(0.6f); - summaryTextView.setAlpha(0.4f); + titleTextView!!.alpha = 0.6f + summaryTextView!!.alpha = 0.4f } } // to avoid listener bug, we need to re-generate unique id for each view - private void initializeId() { - container = findViewById(R.id.container); - titleTextView = findViewById(R.id.title); - summaryTextView = findViewById(R.id.summary); - seekBar = findViewById(R.id.seekbar_widget); - resetIcon = findViewById(R.id.reset); - - container.setId(View.generateViewId()); - titleTextView.setId(View.generateViewId()); - summaryTextView.setId(View.generateViewId()); - seekBar.setId(View.generateViewId()); - resetIcon.setId(View.generateViewId()); + private fun initializeId() { + container = findViewById(R.id.container) + titleTextView = findViewById(R.id.title) + summaryTextView = findViewById(R.id.summary) + seekBar = findViewById(R.id.seekbar_widget) + resetIcon = findViewById(R.id.reset) + + container!!.setId(generateViewId()) + titleTextView!!.setId(generateViewId()) + summaryTextView!!.setId(generateViewId()) + seekBar!!.setId(generateViewId()) + resetIcon!!.setId(generateViewId()) } - @Override - protected Parcelable onSaveInstanceState() { - Parcelable superState = super.onSaveInstanceState(); + override fun onSaveInstanceState(): Parcelable { + val superState = super.onSaveInstanceState() - SavedState ss = new SavedState(superState); - ss.seekbarProgress = seekBar.getProgress(); + val ss = SavedState(superState) + ss.seekbarProgress = seekBar!!.progress - return ss; + return ss } - @Override - protected void onRestoreInstanceState(Parcelable state) { - if (!(state instanceof SavedState ss)) { - super.onRestoreInstanceState(state); - return; + override fun onRestoreInstanceState(state: Parcelable) { + if (state !is SavedState) { + super.onRestoreInstanceState(state) + return } - super.onRestoreInstanceState(ss.getSuperState()); + super.onRestoreInstanceState(state.superState) - seekBar.setProgress(ss.seekbarProgress); - setSelectedProgress(); - handleResetVisibility(); + seekBar!!.progress = state.seekbarProgress + setSelectedProgress() + handleResetVisibility() } - private static class SavedState extends BaseSavedState { - public static final Creator CREATOR = new Creator<>() { - public SeekbarWidget.SavedState createFromParcel(Parcel in) { - return new SeekbarWidget.SavedState(in); - } + private class SavedState : BaseSavedState { + var seekbarProgress: Int = 0 - public SeekbarWidget.SavedState[] newArray(int size) { - return new SeekbarWidget.SavedState[size]; - } - }; - int seekbarProgress; + constructor(superState: Parcelable?) : super(superState) - SavedState(Parcelable superState) { - super(superState); + private constructor(`in`: Parcel) : super(`in`) { + seekbarProgress = `in`.readInt() } - private SavedState(Parcel in) { - super(in); - seekbarProgress = in.readInt(); + override fun writeToParcel(dest: Parcel, flags: Int) { + super.writeToParcel(dest, flags) + dest.writeFloat(seekbarProgress.toFloat()) + } + + companion object CREATOR : Parcelable.Creator { + override fun createFromParcel(parcel: Parcel): SavedState { + return SavedState(parcel) + } + + override fun newArray(size: Int): Array { + return arrayOfNulls(size) + } } - @Override - public void writeToParcel(Parcel dest, int flags) { - super.writeToParcel(dest, flags); - dest.writeFloat(seekbarProgress); + override fun describeContents(): Int { + return 0 } } } diff --git a/app/src/main/java/com/drdisagree/colorblendr/ui/widgets/SelectableViewWidget.kt b/app/src/main/java/com/drdisagree/colorblendr/ui/widgets/SelectableViewWidget.kt index d6ba1df..99da796 100644 --- a/app/src/main/java/com/drdisagree/colorblendr/ui/widgets/SelectableViewWidget.kt +++ b/app/src/main/java/com/drdisagree/colorblendr/ui/widgets/SelectableViewWidget.kt @@ -1,245 +1,258 @@ -package com.drdisagree.colorblendr.ui.widgets; - -import android.content.Context; -import android.content.res.ColorStateList; -import android.content.res.Configuration; -import android.content.res.TypedArray; -import android.graphics.Color; -import android.graphics.PorterDuff; -import android.os.Parcel; -import android.os.Parcelable; -import android.util.AttributeSet; -import android.util.TypedValue; -import android.view.View; -import android.widget.ImageView; -import android.widget.RelativeLayout; -import android.widget.TextView; - -import androidx.annotation.ColorInt; -import androidx.annotation.Nullable; - -import com.drdisagree.colorblendr.ColorBlendr; -import com.drdisagree.colorblendr.R; -import com.drdisagree.colorblendr.utils.SystemUtil; -import com.google.android.material.card.MaterialCardView; -import com.google.android.material.color.MaterialColors; - -public class SelectableViewWidget extends RelativeLayout { - - private Context context; - private MaterialCardView container; - private TextView titleTextView; - private TextView descriptionTextView; - private ImageView iconImageView; - private OnClickListener onClickListener; - - public SelectableViewWidget(Context context) { - super(context); - init(context, null); - } - - public SelectableViewWidget(Context context, AttributeSet attrs) { - super(context, attrs); - init(context, attrs); - } - - public SelectableViewWidget(Context context, AttributeSet attrs, int defStyleAttr) { - super(context, attrs, defStyleAttr); - init(context, attrs); - } - - private void init(Context context, AttributeSet attrs) { - this.context = context; - inflate(context, R.layout.view_widget_selectable, this); - - initializeId(); - - TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.SelectableViewWidget); - setTitle(typedArray.getString(R.styleable.SelectableViewWidget_titleText)); - setDescription(typedArray.getString(R.styleable.SelectableViewWidget_descriptionText)); - setSelected(typedArray.getBoolean(R.styleable.SelectableViewWidget_isSelected, false)); - typedArray.recycle(); - - container.setOnClickListener(v -> { - if (onClickListener != null && !isSelected()) { - setSelected(true); - onClickListener.onClick(v); +package com.drdisagree.colorblendr.ui.widgets + +import android.content.Context +import android.content.res.ColorStateList +import android.content.res.Configuration +import android.content.res.TypedArray +import android.graphics.Color +import android.graphics.PorterDuff +import android.os.Parcel +import android.os.Parcelable +import android.util.AttributeSet +import android.util.TypedValue +import android.view.View +import android.widget.ImageView +import android.widget.RelativeLayout +import android.widget.TextView +import androidx.annotation.ColorInt +import com.drdisagree.colorblendr.ColorBlendr.Companion.appContext +import com.drdisagree.colorblendr.R +import com.drdisagree.colorblendr.utils.SystemUtil.isDarkMode +import com.google.android.material.card.MaterialCardView +import com.google.android.material.color.MaterialColors + +class SelectableViewWidget : RelativeLayout { + + private var context: Context? = null + private var container: MaterialCardView? = null + private var titleTextView: TextView? = null + private var descriptionTextView: TextView? = null + private var iconImageView: ImageView? = null + private var onClickListener: OnClickListener? = null + + constructor(context: Context) : super(context) { + init(context, null) + } + + constructor(context: Context, attrs: AttributeSet?) : super(context, attrs) { + init(context, attrs) + } + + constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super( + context, + attrs, + defStyleAttr + ) { + init(context, attrs) + } + + private fun init(context: Context, attrs: AttributeSet?) { + this.context = context + inflate(context, R.layout.view_widget_selectable, this) + + initializeId() + + val typedArray: TypedArray = + context.obtainStyledAttributes(attrs, R.styleable.SelectableViewWidget) + setTitle(typedArray.getString(R.styleable.SelectableViewWidget_titleText)) + setDescription(typedArray.getString(R.styleable.SelectableViewWidget_descriptionText)) + isSelected = typedArray.getBoolean(R.styleable.SelectableViewWidget_isSelected, false) + typedArray.recycle() + + container!!.setOnClickListener { v: View? -> + if (onClickListener != null && !isSelected) { + isSelected = true + onClickListener!!.onClick(v) } - }); + } - updateViewOnOrientation(); + updateViewOnOrientation() } - public void setTitle(int titleResId) { - titleTextView.setText(titleResId); + fun setTitle(titleResId: Int) { + titleTextView!!.setText(titleResId) } - public void setTitle(String title) { - titleTextView.setText(title); + fun setTitle(title: String?) { + titleTextView!!.text = title } - public void setDescription(int descriptionResId) { - descriptionTextView.setText(descriptionResId); + fun setDescription(descriptionResId: Int) { + descriptionTextView!!.setText(descriptionResId) } - public void setDescription(String description) { - descriptionTextView.setText(description); + fun setDescription(description: String?) { + descriptionTextView!!.text = description } - public boolean isSelected() { - return iconImageView.getAlpha() == 1.0f; + override fun isSelected(): Boolean { + return iconImageView!!.alpha == 1.0f } - public void setSelected(boolean isSelected) { - iconImageView.setAlpha(isSelected ? 1.0f : 0.2f); - iconImageView.setColorFilter(getIconColor(), PorterDuff.Mode.SRC_IN); - iconImageView.setImageResource(isSelected ? R.drawable.ic_checked_filled : R.drawable.ic_checked_outline); - container.setCardBackgroundColor(getCardBackgroundColor()); - container.setStrokeWidth(isSelected ? 0 : 2); - titleTextView.setTextColor(getTextColor(isSelected)); - descriptionTextView.setTextColor(getTextColor(isSelected)); + override fun setSelected(isSelected: Boolean) { + iconImageView!!.alpha = if (isSelected) 1.0f else 0.2f + iconImageView!!.setColorFilter(iconColor, PorterDuff.Mode.SRC_IN) + iconImageView!!.setImageResource(if (isSelected) R.drawable.ic_checked_filled else R.drawable.ic_checked_outline) + container!!.setCardBackgroundColor(cardBackgroundColor) + container!!.strokeWidth = if (isSelected) 0 else 2 + titleTextView!!.setTextColor(getTextColor(isSelected)) + descriptionTextView!!.setTextColor(getTextColor(isSelected)) } - @Override - public void setOnClickListener(@Nullable OnClickListener l) { - onClickListener = l; + override fun setOnClickListener(l: OnClickListener?) { + onClickListener = l } - @Override - public void setEnabled(boolean enabled) { - super.setEnabled(enabled); + override fun setEnabled(enabled: Boolean) { + super.setEnabled(enabled) if (enabled) { - TypedValue typedValue = new TypedValue(); - TypedArray a = getContext().obtainStyledAttributes( - typedValue.data, - new int[]{com.google.android.material.R.attr.colorPrimary} - ); - int color = a.getColor(0, 0); - a.recycle(); - - iconImageView.setImageTintList(ColorStateList.valueOf(color)); - - titleTextView.setAlpha(1.0f); - descriptionTextView.setAlpha(0.8f); + val typedValue: TypedValue = TypedValue() + val a: TypedArray = getContext().obtainStyledAttributes( + typedValue.data, + intArrayOf(com.google.android.material.R.attr.colorPrimary) + ) + val color: Int = a.getColor(0, 0) + a.recycle() + + iconImageView!!.imageTintList = ColorStateList.valueOf(color) + + titleTextView!!.alpha = 1.0f + descriptionTextView!!.alpha = 0.8f } else { - if (SystemUtil.isDarkMode()) { - iconImageView.setImageTintList(ColorStateList.valueOf(Color.DKGRAY)); + if (isDarkMode) { + iconImageView!!.imageTintList = + ColorStateList.valueOf(Color.DKGRAY) } else { - iconImageView.setImageTintList(ColorStateList.valueOf(Color.LTGRAY)); + iconImageView!!.imageTintList = + ColorStateList.valueOf(Color.LTGRAY) } - titleTextView.setAlpha(0.6f); - descriptionTextView.setAlpha(0.4f); + titleTextView!!.alpha = 0.6f + descriptionTextView!!.alpha = 0.4f } - container.setEnabled(enabled); - iconImageView.setEnabled(enabled); - titleTextView.setEnabled(enabled); - descriptionTextView.setEnabled(enabled); + container!!.isEnabled = enabled + iconImageView!!.isEnabled = enabled + titleTextView!!.isEnabled = enabled + descriptionTextView!!.isEnabled = enabled } // to avoid listener bug, we need to re-generate unique id for each view - private void initializeId() { - container = findViewById(R.id.container); - iconImageView = findViewById(R.id.icon); - titleTextView = findViewById(R.id.title); - descriptionTextView = findViewById(R.id.description); - - container.setId(View.generateViewId()); - iconImageView.setId(View.generateViewId()); - titleTextView.setId(View.generateViewId()); - descriptionTextView.setId(View.generateViewId()); + private fun initializeId() { + container = findViewById(R.id.container) + iconImageView = findViewById(R.id.icon) + titleTextView = findViewById(R.id.title) + descriptionTextView = findViewById(R.id.description) + + container!!.setId(generateViewId()) + iconImageView!!.setId(generateViewId()) + titleTextView!!.setId(generateViewId()) + descriptionTextView!!.setId(generateViewId()) } - private @ColorInt int getCardBackgroundColor() { - return isSelected() ? - MaterialColors.getColor(this, com.google.android.material.R.attr.colorPrimaryContainer) : - MaterialColors.getColor(this, com.google.android.material.R.attr.colorSurfaceContainer); - } - - private @ColorInt int getIconColor() { - return isSelected() ? - MaterialColors.getColor(this, com.google.android.material.R.attr.colorPrimary) : - MaterialColors.getColor(this, com.google.android.material.R.attr.colorOnSurface); - } + @get:ColorInt + private val cardBackgroundColor: Int + get() = if (isSelected) MaterialColors.getColor( + this, + com.google.android.material.R.attr.colorPrimaryContainer + ) else MaterialColors.getColor( + this, + com.google.android.material.R.attr.colorSurfaceContainer + ) + + @get:ColorInt + private val iconColor: Int + get() { + return if (isSelected) MaterialColors.getColor( + this, + com.google.android.material.R.attr.colorPrimary + ) else MaterialColors.getColor( + this, + com.google.android.material.R.attr.colorOnSurface + ) + } - private @ColorInt int getTextColor(boolean isSelected) { - return isSelected ? - MaterialColors.getColor(this, com.google.android.material.R.attr.colorOnPrimaryContainer) : - MaterialColors.getColor(this, com.google.android.material.R.attr.colorOnSurface); + @ColorInt + private fun getTextColor(isSelected: Boolean): Int { + return if (isSelected) MaterialColors.getColor( + this, + com.google.android.material.R.attr.colorOnPrimaryContainer + ) else MaterialColors.getColor( + this, com.google.android.material.R.attr.colorOnSurface + ) } - private void updateViewOnOrientation() { - Configuration config = ColorBlendr.getAppContext().getResources().getConfiguration(); - boolean isLandscape = config.orientation == Configuration.ORIENTATION_LANDSCAPE; + private fun updateViewOnOrientation() { + val config: Configuration = appContext.resources.configuration + val isLandscape: Boolean = config.orientation == Configuration.ORIENTATION_LANDSCAPE if (isLandscape) { - int screenWidth = context.getResources().getDisplayMetrics().widthPixels; - int screenHeight = context.getResources().getDisplayMetrics().heightPixels; + val screenWidth: Int = context!!.resources.displayMetrics.widthPixels + val screenHeight: Int = context!!.resources.displayMetrics.heightPixels - boolean isSmallHeightDevice = screenWidth >= screenHeight * 1.8; + val isSmallHeightDevice: Boolean = screenWidth >= screenHeight * 1.8 if (isSmallHeightDevice) { - container.setMinimumHeight(0); - descriptionTextView.setVisibility(TextView.GONE); + container!!.minimumHeight = 0 + descriptionTextView!!.visibility = GONE } } else { - int minHeightInDp = 100; - int minHeightInPixels = (int) (minHeightInDp * context.getResources().getDisplayMetrics().density); - container.setMinimumHeight(minHeightInPixels); - descriptionTextView.setVisibility(TextView.VISIBLE); + val minHeightInDp: Int = 100 + val minHeightInPixels: Int = + (minHeightInDp * context!!.resources.displayMetrics.density).toInt() + container!!.minimumHeight = minHeightInPixels + descriptionTextView!!.visibility = VISIBLE } } - @Override - protected Parcelable onSaveInstanceState() { - Parcelable superState = super.onSaveInstanceState(); + override fun onSaveInstanceState(): Parcelable { + val superState: Parcelable? = super.onSaveInstanceState() - SavedState ss = new SavedState(superState); - ss.isSelected = isSelected(); + val ss = SavedState(superState) + ss.isSelected = isSelected - return ss; + return ss } - @Override - protected void onRestoreInstanceState(Parcelable state) { - if (!(state instanceof SavedState ss)) { - super.onRestoreInstanceState(state); - return; + override fun onRestoreInstanceState(state: Parcelable) { + if (state !is SavedState) { + super.onRestoreInstanceState(state) + return } - super.onRestoreInstanceState(ss.getSuperState()); + super.onRestoreInstanceState(state.superState) - setSelected(ss.isSelected); - updateViewOnOrientation(); + isSelected = state.isSelected + updateViewOnOrientation() } - private static class SavedState extends BaseSavedState { - public static final Parcelable.Creator CREATOR = new Parcelable.Creator<>() { - public SavedState createFromParcel(Parcel in) { - return new SavedState(in); - } + private class SavedState : BaseSavedState { + var isSelected: Boolean = false - public SavedState[] newArray(int size) { - return new SavedState[size]; - } - }; - boolean isSelected; + constructor(superState: Parcelable?) : super(superState) - SavedState(Parcelable superState) { - super(superState); + private constructor(`in`: Parcel) : super(`in`) { + isSelected = `in`.readBoolean() } - private SavedState(Parcel in) { - super(in); - isSelected = in.readBoolean(); + override fun writeToParcel(dest: Parcel, flags: Int) { + super.writeToParcel(dest, flags) + dest.writeBoolean(isSelected) + } + + companion object CREATOR : Parcelable.Creator { + override fun createFromParcel(parcel: Parcel): SavedState { + return SavedState(parcel) + } + + override fun newArray(size: Int): Array { + return arrayOfNulls(size) + } } - @Override - public void writeToParcel(Parcel dest, int flags) { - super.writeToParcel(dest, flags); - dest.writeBoolean(isSelected); + override fun describeContents(): Int { + return 0 } } } diff --git a/app/src/main/java/com/drdisagree/colorblendr/ui/widgets/StylePreviewWidget.kt b/app/src/main/java/com/drdisagree/colorblendr/ui/widgets/StylePreviewWidget.kt index 5a8f386..74aefd0 100644 --- a/app/src/main/java/com/drdisagree/colorblendr/ui/widgets/StylePreviewWidget.kt +++ b/app/src/main/java/com/drdisagree/colorblendr/ui/widgets/StylePreviewWidget.kt @@ -1,255 +1,263 @@ -package com.drdisagree.colorblendr.ui.widgets; - -import static com.drdisagree.colorblendr.common.Const.MONET_ACCENT_SATURATION; -import static com.drdisagree.colorblendr.common.Const.MONET_ACCURATE_SHADES; -import static com.drdisagree.colorblendr.common.Const.MONET_BACKGROUND_LIGHTNESS; -import static com.drdisagree.colorblendr.common.Const.MONET_BACKGROUND_SATURATION; -import static com.drdisagree.colorblendr.common.Const.MONET_PITCH_BLACK_THEME; -import static com.drdisagree.colorblendr.common.Const.MONET_STYLE; - -import android.content.Context; -import android.content.res.TypedArray; -import android.os.Handler; -import android.os.Looper; -import android.os.Parcel; -import android.os.Parcelable; -import android.util.AttributeSet; -import android.view.View; -import android.widget.RelativeLayout; -import android.widget.TextView; - -import androidx.annotation.ColorInt; -import androidx.annotation.Nullable; - -import com.drdisagree.colorblendr.R; -import com.drdisagree.colorblendr.config.RPrefs; -import com.drdisagree.colorblendr.ui.views.ColorPreview; -import com.drdisagree.colorblendr.utils.ColorSchemeUtil; -import com.drdisagree.colorblendr.utils.ColorUtil; -import com.drdisagree.colorblendr.utils.OverlayManager; -import com.drdisagree.colorblendr.utils.SystemUtil; -import com.google.android.material.card.MaterialCardView; -import com.google.android.material.color.MaterialColors; - -import java.util.ArrayList; - -public class StylePreviewWidget extends RelativeLayout { - - private Context context; - private MaterialCardView container; - private TextView titleTextView; - private TextView descriptionTextView; - private ColorPreview colorContainer; - private boolean isSelected = false; - private OnClickListener onClickListener; - private String styleName; - private ColorSchemeUtil.MONET monetStyle; - private ArrayList> colorPalette; - - public StylePreviewWidget(Context context) { - super(context); - init(context, null); - } - - public StylePreviewWidget(Context context, AttributeSet attrs) { - super(context, attrs); - init(context, attrs); - } - - public StylePreviewWidget(Context context, AttributeSet attrs, int defStyleAttr) { - super(context, attrs, defStyleAttr); - init(context, attrs); - } - - private void init(Context context, AttributeSet attrs) { - this.context = context; - inflate(context, R.layout.view_widget_style_preview, this); - - initializeId(); - - TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.StylePreviewWidget); - styleName = typedArray.getString(R.styleable.StylePreviewWidget_titleText); - setTitle(styleName); - setDescription(typedArray.getString(R.styleable.StylePreviewWidget_descriptionText)); - typedArray.recycle(); - - setColorPreview(); - - container.setOnClickListener(v -> { +package com.drdisagree.colorblendr.ui.widgets + +import android.content.Context +import android.content.res.TypedArray +import android.os.Handler +import android.os.Looper +import android.os.Parcel +import android.os.Parcelable +import android.util.AttributeSet +import android.view.View +import android.widget.RelativeLayout +import android.widget.TextView +import androidx.annotation.ColorInt +import com.drdisagree.colorblendr.R +import com.drdisagree.colorblendr.common.Const.MONET_ACCENT_SATURATION +import com.drdisagree.colorblendr.common.Const.MONET_ACCURATE_SHADES +import com.drdisagree.colorblendr.common.Const.MONET_BACKGROUND_LIGHTNESS +import com.drdisagree.colorblendr.common.Const.MONET_BACKGROUND_SATURATION +import com.drdisagree.colorblendr.common.Const.MONET_PITCH_BLACK_THEME +import com.drdisagree.colorblendr.common.Const.MONET_STYLE +import com.drdisagree.colorblendr.config.RPrefs.getBoolean +import com.drdisagree.colorblendr.config.RPrefs.getInt +import com.drdisagree.colorblendr.config.RPrefs.putString +import com.drdisagree.colorblendr.ui.views.ColorPreview +import com.drdisagree.colorblendr.utils.ColorSchemeUtil.MONET +import com.drdisagree.colorblendr.utils.ColorSchemeUtil.stringToEnumMonetStyle +import com.drdisagree.colorblendr.utils.ColorUtil.generateModifiedColors +import com.drdisagree.colorblendr.utils.OverlayManager.applyFabricatedColors +import com.drdisagree.colorblendr.utils.SystemUtil.isDarkMode +import com.google.android.material.card.MaterialCardView +import com.google.android.material.color.MaterialColors + +class StylePreviewWidget : RelativeLayout { + + private var context: Context? = null + private var container: MaterialCardView? = null + private var titleTextView: TextView? = null + private var descriptionTextView: TextView? = null + private var colorContainer: ColorPreview? = null + private var isSelected: Boolean = false + private var onClickListener: OnClickListener? = null + private var styleName: String? = null + private var monetStyle: MONET? = null + private var colorPalette: ArrayList>? = null + + constructor(context: Context) : super(context) { + init(context, null) + } + + constructor(context: Context, attrs: AttributeSet?) : super(context, attrs) { + init(context, attrs) + } + + constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super( + context, + attrs, + defStyleAttr + ) { + init(context, attrs) + } + + private fun init(context: Context, attrs: AttributeSet?) { + this.context = context + inflate(context, R.layout.view_widget_style_preview, this) + + initializeId() + + val typedArray: TypedArray = + context.obtainStyledAttributes(attrs, R.styleable.StylePreviewWidget) + styleName = typedArray.getString(R.styleable.StylePreviewWidget_titleText) + setTitle(styleName) + setDescription(typedArray.getString(R.styleable.StylePreviewWidget_descriptionText)) + typedArray.recycle() + + setColorPreview() + + container!!.setOnClickListener { v: View? -> if (onClickListener != null && !isSelected()) { - setSelected(true); - onClickListener.onClick(v); + setSelected(true) + onClickListener!!.onClick(v) } - }); + } } - public void setTitle(int titleResId) { - titleTextView.setText(titleResId); + fun setTitle(titleResId: Int) { + titleTextView!!.setText(titleResId) } - public void setTitle(String title) { - titleTextView.setText(title); + fun setTitle(title: String?) { + titleTextView!!.text = title } - public void setDescription(int summaryResId) { - descriptionTextView.setText(summaryResId); + fun setDescription(summaryResId: Int) { + descriptionTextView!!.setText(summaryResId) } - public void setDescription(String summary) { - descriptionTextView.setText(summary); + fun setDescription(summary: String?) { + descriptionTextView!!.text = summary } - public boolean isSelected() { - return isSelected; + override fun isSelected(): Boolean { + return isSelected } - public void setSelected(boolean isSelected) { - this.isSelected = isSelected; - container.setCardBackgroundColor(getCardBackgroundColor()); - container.setStrokeWidth(isSelected ? 2 : 0); - titleTextView.setTextColor(getTextColor(isSelected)); - descriptionTextView.setTextColor(getTextColor(isSelected)); + override fun setSelected(isSelected: Boolean) { + this.isSelected = isSelected + container!!.setCardBackgroundColor(cardBackgroundColor) + container!!.setStrokeWidth(if (isSelected) 2 else 0) + titleTextView!!.setTextColor(getTextColor(isSelected)) + descriptionTextView!!.setTextColor(getTextColor(isSelected)) } - public void applyColorScheme() { - RPrefs.putString(MONET_STYLE, styleName); - OverlayManager.applyFabricatedColors(context); + fun applyColorScheme() { + styleName?.let { + putString(MONET_STYLE, it) + applyFabricatedColors(context!!) + } } - private void setColorPreview() { - new Thread(() -> { + private fun setColorPreview() { + Thread { try { if (styleName == null) { - styleName = context.getString(R.string.monet_tonalspot); + styleName = context!!.getString(R.string.monet_tonalspot) } - monetStyle = ColorSchemeUtil.stringToEnumMonetStyle( - context, - styleName - ); - - colorPalette = ColorUtil.generateModifiedColors( - context, - monetStyle, - RPrefs.getInt(MONET_ACCENT_SATURATION, 100), - RPrefs.getInt(MONET_BACKGROUND_SATURATION, 100), - RPrefs.getInt(MONET_BACKGROUND_LIGHTNESS, 100), - RPrefs.getBoolean(MONET_PITCH_BLACK_THEME, false), - RPrefs.getBoolean(MONET_ACCURATE_SHADES, true) - ); - - new Handler(Looper.getMainLooper()).post(() -> { - boolean isDarkMode = SystemUtil.isDarkMode(); - - colorContainer.setHalfCircleColor(colorPalette.get(0).get(4)); - colorContainer.setFirstQuarterCircleColor(colorPalette.get(2).get(5)); - colorContainer.setSecondQuarterCircleColor(colorPalette.get(1).get(6)); - colorContainer.setSquareColor(colorPalette.get(4).get(!isDarkMode ? 2 : 9)); - colorContainer.invalidateColors(); - }); - } catch (Exception ignored) { + monetStyle = stringToEnumMonetStyle( + context!!, + styleName!! + ) + + colorPalette = generateModifiedColors( + context!!, + monetStyle!!, + getInt(MONET_ACCENT_SATURATION, 100), + getInt(MONET_BACKGROUND_SATURATION, 100), + getInt(MONET_BACKGROUND_LIGHTNESS, 100), + getBoolean(MONET_PITCH_BLACK_THEME, false), + getBoolean(MONET_ACCURATE_SHADES, true) + ) + + Handler(Looper.getMainLooper()).post { + val isDarkMode: Boolean = isDarkMode + colorContainer!!.setHalfCircleColor(colorPalette!![0][4]) + colorContainer!!.setFirstQuarterCircleColor(colorPalette!![2][5]) + colorContainer!!.setSecondQuarterCircleColor(colorPalette!![1][6]) + colorContainer!!.setSquareColor(colorPalette!![4][if (!isDarkMode) 2 else 9]) + colorContainer!!.invalidateColors() + } + } catch (ignored: Exception) { } - }).start(); + }.start() } - @Override - public void setOnClickListener(@Nullable OnClickListener l) { - onClickListener = l; + override fun setOnClickListener(l: OnClickListener?) { + onClickListener = l } // to avoid listener bug, we need to re-generate unique id for each view - private void initializeId() { - container = findViewById(R.id.container); - titleTextView = findViewById(R.id.title); - descriptionTextView = findViewById(R.id.summary); - colorContainer = findViewById(R.id.color_container); - - container.setId(View.generateViewId()); - titleTextView.setId(View.generateViewId()); - descriptionTextView.setId(View.generateViewId()); - colorContainer.setId(View.generateViewId()); - - LayoutParams layoutParams = (LayoutParams) findViewById(R.id.text_container).getLayoutParams(); - layoutParams.addRule(RelativeLayout.END_OF, colorContainer.getId()); - findViewById(R.id.text_container).setLayoutParams(layoutParams); + private fun initializeId() { + container = findViewById(R.id.container) + titleTextView = findViewById(R.id.title) + descriptionTextView = findViewById(R.id.summary) + colorContainer = findViewById(R.id.color_container) + + container!!.setId(generateViewId()) + titleTextView!!.setId(generateViewId()) + descriptionTextView!!.setId(generateViewId()) + colorContainer!!.setId(generateViewId()) + + val textContainer = findViewById(R.id.text_container) + val layoutParams: LayoutParams = textContainer.layoutParams as LayoutParams + layoutParams.addRule(END_OF, colorContainer!!.id) + textContainer.setLayoutParams(layoutParams) } - private @ColorInt int getCardBackgroundColor() { - return isSelected() ? - MaterialColors.getColor(this, com.google.android.material.R.attr.colorPrimaryContainer) : - MaterialColors.getColor(this, com.google.android.material.R.attr.colorSurfaceContainer); - } + @get:ColorInt + private val cardBackgroundColor: Int + get() { + return if (isSelected()) MaterialColors.getColor( + this, + com.google.android.material.R.attr.colorPrimaryContainer + ) else MaterialColors.getColor( + this, + com.google.android.material.R.attr.colorSurfaceContainer + ) + } - private @ColorInt int getTextColor(boolean isSelected) { - return isSelected ? - MaterialColors.getColor(this, com.google.android.material.R.attr.colorOnPrimaryContainer) : - MaterialColors.getColor(this, com.google.android.material.R.attr.colorOnSurface); + @ColorInt + private fun getTextColor(isSelected: Boolean): Int { + return if (isSelected) MaterialColors.getColor( + this, + com.google.android.material.R.attr.colorOnPrimaryContainer + ) else MaterialColors.getColor( + this, com.google.android.material.R.attr.colorOnSurface + ) } - @Override - protected Parcelable onSaveInstanceState() { - Parcelable superState = super.onSaveInstanceState(); + override fun onSaveInstanceState(): Parcelable { + val superState: Parcelable? = super.onSaveInstanceState() - SavedState ss = new SavedState(superState); - ss.isSelected = isSelected(); + val ss = SavedState(superState) + ss.isSelected = isSelected() - return ss; + return ss } - @Override - protected void onRestoreInstanceState(Parcelable state) { - if (!(state instanceof SavedState ss)) { - super.onRestoreInstanceState(state); - return; + override fun onRestoreInstanceState(state: Parcelable) { + if (state !is SavedState) { + super.onRestoreInstanceState(state) + return } - super.onRestoreInstanceState(ss.getSuperState()); + super.onRestoreInstanceState(state.superState) - setSelected(ss.isSelected); - setColorPreview(); + setSelected(state.isSelected) + setColorPreview() } - @Override - public void setEnabled(boolean enabled) { + override fun setEnabled(enabled: Boolean) { if (enabled) { - titleTextView.setAlpha(1.0f); - descriptionTextView.setAlpha(0.8f); + titleTextView!!.setAlpha(1.0f) + descriptionTextView!!.setAlpha(0.8f) } else { - titleTextView.setAlpha(0.6f); - descriptionTextView.setAlpha(0.4f); + titleTextView!!.setAlpha(0.6f) + descriptionTextView!!.setAlpha(0.4f) } - container.setEnabled(enabled); - titleTextView.setEnabled(enabled); - descriptionTextView.setEnabled(enabled); - colorContainer.setEnabled(enabled); + container!!.setEnabled(enabled) + titleTextView!!.setEnabled(enabled) + descriptionTextView!!.setEnabled(enabled) + colorContainer!!.setEnabled(enabled) } - private static class SavedState extends BaseSavedState { - public static final Parcelable.Creator CREATOR = new Parcelable.Creator<>() { - public SavedState createFromParcel(Parcel in) { - return new SavedState(in); - } + private class SavedState : BaseSavedState { + var isSelected: Boolean = false - public SavedState[] newArray(int size) { - return new SavedState[size]; - } - }; - boolean isSelected; + constructor(superState: Parcelable?) : super(superState) + + private constructor(`in`: Parcel) : super(`in`) { + isSelected = `in`.readBoolean() + } - SavedState(Parcelable superState) { - super(superState); + override fun writeToParcel(dest: Parcel, flags: Int) { + super.writeToParcel(dest, flags) + dest.writeBoolean(isSelected) } - private SavedState(Parcel in) { - super(in); - isSelected = in.readBoolean(); + companion object CREATOR : Parcelable.Creator { + override fun createFromParcel(parcel: Parcel): SavedState { + return SavedState(parcel) + } + + override fun newArray(size: Int): Array { + return arrayOfNulls(size) + } } - @Override - public void writeToParcel(Parcel dest, int flags) { - super.writeToParcel(dest, flags); - dest.writeBoolean(isSelected); + override fun describeContents(): Int { + return 0 } } } diff --git a/app/src/main/java/com/drdisagree/colorblendr/ui/widgets/SwitchWidget.kt b/app/src/main/java/com/drdisagree/colorblendr/ui/widgets/SwitchWidget.kt index 824df8b..bf90254 100644 --- a/app/src/main/java/com/drdisagree/colorblendr/ui/widgets/SwitchWidget.kt +++ b/app/src/main/java/com/drdisagree/colorblendr/ui/widgets/SwitchWidget.kt @@ -1,251 +1,261 @@ -package com.drdisagree.colorblendr.ui.widgets; - -import android.content.Context; -import android.content.res.ColorStateList; -import android.content.res.TypedArray; -import android.graphics.Color; -import android.graphics.PorterDuff; -import android.graphics.drawable.Drawable; -import android.util.AttributeSet; -import android.util.TypedValue; -import android.view.View; -import android.widget.CompoundButton; -import android.widget.ImageView; -import android.widget.RelativeLayout; -import android.widget.TextView; - -import androidx.annotation.ColorInt; -import androidx.core.graphics.ColorUtils; - -import com.drdisagree.colorblendr.R; -import com.drdisagree.colorblendr.utils.SystemUtil; -import com.google.android.material.card.MaterialCardView; -import com.google.android.material.color.MaterialColors; -import com.google.android.material.materialswitch.MaterialSwitch; - -public class SwitchWidget extends RelativeLayout { - - private Context context; - private MaterialCardView container; - private TextView titleTextView; - private TextView summaryTextView; - private ImageView iconImageView; - private MaterialSwitch materialSwitch; - private MaterialSwitch.OnCheckedChangeListener switchChangeListener; - private BeforeSwitchChangeListener beforeSwitchChangeListener; - private boolean isMasterSwitch; - private String summaryOnText; - private String summaryOffText; - - public SwitchWidget(Context context) { - super(context); - init(context, null); - } - - public SwitchWidget(Context context, AttributeSet attrs) { - super(context, attrs); - init(context, attrs); - } - - public SwitchWidget(Context context, AttributeSet attrs, int defStyleAttr) { - super(context, attrs, defStyleAttr); - init(context, attrs); - } - - private void init(Context context, AttributeSet attrs) { - this.context = context; - inflate(context, R.layout.view_widget_switch, this); - - initializeId(); - - TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.SwitchWidget); - setTitle(typedArray.getString(R.styleable.SwitchWidget_titleText)); - setSummary(typedArray.getString(R.styleable.SwitchWidget_summaryText)); - int icon = typedArray.getResourceId(R.styleable.SwitchWidget_icon, 0); - boolean iconSpaceReserved = typedArray.getBoolean(R.styleable.SwitchWidget_iconSpaceReserved, false); - isMasterSwitch = typedArray.getBoolean(R.styleable.SwitchWidget_isMasterSwitch, false); - summaryOnText = typedArray.getString(R.styleable.SwitchWidget_summaryOnText); - summaryOffText = typedArray.getString(R.styleable.SwitchWidget_summaryOffText); - setSwitchChecked(typedArray.getBoolean(R.styleable.SwitchWidget_isChecked, false)); - updateSummary(); - typedArray.recycle(); +package com.drdisagree.colorblendr.ui.widgets + +import android.content.Context +import android.content.res.ColorStateList +import android.content.res.TypedArray +import android.graphics.Color +import android.graphics.PorterDuff +import android.graphics.drawable.Drawable +import android.util.AttributeSet +import android.util.TypedValue +import android.view.View +import android.widget.CompoundButton +import android.widget.ImageView +import android.widget.RelativeLayout +import android.widget.TextView +import androidx.annotation.ColorInt +import androidx.core.graphics.ColorUtils +import com.drdisagree.colorblendr.R +import com.drdisagree.colorblendr.utils.SystemUtil.isDarkMode +import com.google.android.material.card.MaterialCardView +import com.google.android.material.color.MaterialColors +import com.google.android.material.materialswitch.MaterialSwitch + +class SwitchWidget : RelativeLayout { + + private var context: Context? = null + private var container: MaterialCardView? = null + private var titleTextView: TextView? = null + private var summaryTextView: TextView? = null + private var iconImageView: ImageView? = null + private var materialSwitch: MaterialSwitch? = null + private var switchChangeListener: CompoundButton.OnCheckedChangeListener? = null + private var beforeSwitchChangeListener: BeforeSwitchChangeListener? = null + private var isMasterSwitch: Boolean = false + private var summaryOnText: String? = null + private var summaryOffText: String? = null + + constructor(context: Context) : super(context) { + init(context, null) + } + + constructor(context: Context, attrs: AttributeSet?) : super(context, attrs) { + init(context, attrs) + } + + constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super( + context, + attrs, + defStyleAttr + ) { + init(context, attrs) + } + + private fun init(context: Context, attrs: AttributeSet?) { + this.context = context + inflate(context, R.layout.view_widget_switch, this) + + initializeId() + + val typedArray: TypedArray = context.obtainStyledAttributes(attrs, R.styleable.SwitchWidget) + setTitle(typedArray.getString(R.styleable.SwitchWidget_titleText)) + setSummary(typedArray.getString(R.styleable.SwitchWidget_summaryText)) + val icon: Int = typedArray.getResourceId(R.styleable.SwitchWidget_icon, 0) + var iconSpaceReserved: Boolean = + typedArray.getBoolean(R.styleable.SwitchWidget_iconSpaceReserved, false) + isMasterSwitch = typedArray.getBoolean(R.styleable.SwitchWidget_isMasterSwitch, false) + summaryOnText = typedArray.getString(R.styleable.SwitchWidget_summaryOnText) + summaryOffText = typedArray.getString(R.styleable.SwitchWidget_summaryOffText) + isSwitchChecked = typedArray.getBoolean(R.styleable.SwitchWidget_isChecked, false) + updateSummary() + typedArray.recycle() if (icon != 0) { - iconSpaceReserved = true; - iconImageView.setImageResource(icon); + iconSpaceReserved = true + iconImageView!!.setImageResource(icon) } if (!iconSpaceReserved) { - iconImageView.setVisibility(GONE); + iconImageView!!.setVisibility(GONE) } - container.setOnClickListener(v -> { - if (materialSwitch.isEnabled()) { - materialSwitch.toggle(); + container!!.setOnClickListener { + if (materialSwitch!!.isEnabled) { + materialSwitch!!.toggle() } - }); + } - materialSwitch.setOnCheckedChangeListener((buttonView, isChecked) -> { - if (materialSwitch.isEnabled()) { + materialSwitch!!.setOnCheckedChangeListener { buttonView: CompoundButton?, isChecked: Boolean -> + if (materialSwitch!!.isEnabled) { if (beforeSwitchChangeListener != null) { - beforeSwitchChangeListener.beforeSwitchChanged(); + beforeSwitchChangeListener!!.beforeSwitchChanged() } - updateSummary(); + updateSummary() if (switchChangeListener != null) { - switchChangeListener.onCheckedChanged(buttonView, isChecked); + switchChangeListener!!.onCheckedChanged(buttonView, isChecked) } } - }); - } - - public void setTitle(int titleResId) { - titleTextView.setText(titleResId); + } } - public void setTitle(String title) { - titleTextView.setText(title); + fun setTitle(titleResId: Int) { + titleTextView!!.setText(titleResId) } - public void setSummary(int summaryResId) { - summaryTextView.setText(summaryResId); + fun setTitle(title: String?) { + titleTextView!!.text = title } - public void setSummary(String summary) { - summaryTextView.setText(summary); + fun setSummary(summaryResId: Int) { + summaryTextView!!.setText(summaryResId) } - public void setIcon(int icon) { - iconImageView.setImageResource(icon); - iconImageView.setVisibility(VISIBLE); + fun setSummary(summary: String?) { + summaryTextView!!.text = summary } - public void setIcon(Drawable drawable) { - iconImageView.setImageDrawable(drawable); - iconImageView.setVisibility(VISIBLE); + fun setIcon(icon: Int) { + iconImageView!!.setImageResource(icon) + iconImageView!!.setVisibility(VISIBLE) } - public void setIconVisibility(int visibility) { - iconImageView.setVisibility(visibility); + fun setIcon(drawable: Drawable?) { + iconImageView!!.setImageDrawable(drawable) + iconImageView!!.setVisibility(VISIBLE) } - public boolean isSwitchChecked() { - return materialSwitch.isChecked(); + fun setIconVisibility(visibility: Int) { + iconImageView!!.setVisibility(visibility) } - public void setSwitchChecked(boolean isChecked) { - materialSwitch.setChecked(isChecked); - if (switchChangeListener != null) { - switchChangeListener.onCheckedChanged(materialSwitch, isChecked); + var isSwitchChecked: Boolean + get() { + return materialSwitch!!.isChecked + } + set(isChecked) { + materialSwitch!!.setChecked(isChecked) + if (switchChangeListener != null) { + switchChangeListener!!.onCheckedChanged(materialSwitch, isChecked) + } } - } - private void updateSummary() { + private fun updateSummary() { if (summaryOnText == null || summaryOffText == null) { - return; + return } - boolean isChecked = isSwitchChecked(); + val isChecked: Boolean = isSwitchChecked if (isChecked) { - setSummary(summaryOnText); + setSummary(summaryOnText) } else { - setSummary(summaryOffText); + setSummary(summaryOffText) } if (isMasterSwitch) { - container.setCardBackgroundColor(getCardBackgroundColor(isChecked)); - iconImageView.setColorFilter(getIconColor(isChecked), PorterDuff.Mode.SRC_IN); - titleTextView.setTextColor(getTextColor(isChecked)); - summaryTextView.setTextColor(getTextColor(isChecked)); + container!!.setCardBackgroundColor(getCardBackgroundColor(isChecked)) + iconImageView!!.setColorFilter(getIconColor(isChecked), PorterDuff.Mode.SRC_IN) + titleTextView!!.setTextColor(getTextColor(isChecked)) + summaryTextView!!.setTextColor(getTextColor(isChecked)) } } - private @ColorInt int getCardBackgroundColor(boolean isSelected) { - return isSelected ? - MaterialColors.getColor(this, com.google.android.material.R.attr.colorPrimaryContainer) : - ColorUtils.setAlphaComponent( - MaterialColors.getColor(this, com.google.android.material.R.attr.colorPrimaryContainer), - 64 - ); + @ColorInt + private fun getCardBackgroundColor(isSelected: Boolean): Int { + return if (isSelected) MaterialColors.getColor( + this, + com.google.android.material.R.attr.colorPrimaryContainer + ) else ColorUtils.setAlphaComponent( + MaterialColors.getColor(this, com.google.android.material.R.attr.colorPrimaryContainer), + 64 + ) } - private @ColorInt int getIconColor(boolean isSelected) { - return isSelected ? - MaterialColors.getColor(this, com.google.android.material.R.attr.colorPrimary) : - MaterialColors.getColor(this, com.google.android.material.R.attr.colorOnSurface); + @ColorInt + private fun getIconColor(isSelected: Boolean): Int { + return if (isSelected) MaterialColors.getColor( + this, + com.google.android.material.R.attr.colorPrimary + ) else MaterialColors.getColor( + this, com.google.android.material.R.attr.colorOnSurface + ) } - private @ColorInt int getTextColor(boolean isSelected) { - return isSelected ? - MaterialColors.getColor(this, com.google.android.material.R.attr.colorOnPrimaryContainer) : - MaterialColors.getColor(this, com.google.android.material.R.attr.colorOnSurface); + @ColorInt + private fun getTextColor(isSelected: Boolean): Int { + return if (isSelected) MaterialColors.getColor( + this, + com.google.android.material.R.attr.colorOnPrimaryContainer + ) else MaterialColors.getColor( + this, com.google.android.material.R.attr.colorOnSurface + ) } - public void setSwitchChangeListener(CompoundButton.OnCheckedChangeListener listener) { - switchChangeListener = listener; + fun setSwitchChangeListener(listener: CompoundButton.OnCheckedChangeListener?) { + switchChangeListener = listener } - public void setBeforeSwitchChangeListener(BeforeSwitchChangeListener listener) { - beforeSwitchChangeListener = listener; + fun setBeforeSwitchChangeListener(listener: BeforeSwitchChangeListener?) { + beforeSwitchChangeListener = listener } - @Override - public void setEnabled(boolean enabled) { - super.setEnabled(enabled); + override fun setEnabled(enabled: Boolean) { + super.setEnabled(enabled) if (enabled) { - TypedValue typedValue = new TypedValue(); - TypedArray a = getContext().obtainStyledAttributes( - typedValue.data, - new int[]{com.google.android.material.R.attr.colorPrimary} - ); - int color = a.getColor(0, 0); - a.recycle(); - - iconImageView.setImageTintList(ColorStateList.valueOf(color)); - - titleTextView.setAlpha(1.0f); - summaryTextView.setAlpha(0.8f); + val typedValue: TypedValue = TypedValue() + val a: TypedArray = getContext().obtainStyledAttributes( + typedValue.data, + intArrayOf(com.google.android.material.R.attr.colorPrimary) + ) + val color: Int = a.getColor(0, 0) + a.recycle() + + iconImageView!!.setImageTintList(ColorStateList.valueOf(color)) + + titleTextView!!.setAlpha(1.0f) + summaryTextView!!.setAlpha(0.8f) } else { - if (SystemUtil.isDarkMode()) { - iconImageView.setImageTintList(ColorStateList.valueOf(Color.DKGRAY)); + if (isDarkMode) { + iconImageView!!.setImageTintList(ColorStateList.valueOf(Color.DKGRAY)) } else { - iconImageView.setImageTintList(ColorStateList.valueOf(Color.LTGRAY)); + iconImageView!!.setImageTintList(ColorStateList.valueOf(Color.LTGRAY)) } - titleTextView.setAlpha(0.6f); - summaryTextView.setAlpha(0.4f); + titleTextView!!.setAlpha(0.6f) + summaryTextView!!.setAlpha(0.4f) } - container.setEnabled(enabled); - iconImageView.setEnabled(enabled); - titleTextView.setEnabled(enabled); - summaryTextView.setEnabled(enabled); - materialSwitch.setEnabled(enabled); + container!!.setEnabled(enabled) + iconImageView!!.setEnabled(enabled) + titleTextView!!.setEnabled(enabled) + summaryTextView!!.setEnabled(enabled) + materialSwitch!!.setEnabled(enabled) } // to avoid listener bug, we need to re-generate unique id for each view - private void initializeId() { - container = findViewById(R.id.container); - iconImageView = findViewById(R.id.icon); - titleTextView = findViewById(R.id.title); - summaryTextView = findViewById(R.id.summary); - materialSwitch = findViewById(R.id.switch_widget); - - container.setId(View.generateViewId()); - iconImageView.setId(View.generateViewId()); - titleTextView.setId(View.generateViewId()); - summaryTextView.setId(View.generateViewId()); - materialSwitch.setId(View.generateViewId()); - - LayoutParams layoutParams = (LayoutParams) findViewById(R.id.text_container).getLayoutParams(); - layoutParams.addRule(RelativeLayout.START_OF, materialSwitch.getId()); - layoutParams.addRule(RelativeLayout.END_OF, iconImageView.getId()); - findViewById(R.id.text_container).setLayoutParams(layoutParams); - } - - public interface BeforeSwitchChangeListener { - void beforeSwitchChanged(); + private fun initializeId() { + container = findViewById(R.id.container) + iconImageView = findViewById(R.id.icon) + titleTextView = findViewById(R.id.title) + summaryTextView = findViewById(R.id.summary) + materialSwitch = findViewById(R.id.switch_widget) + + container!!.setId(generateViewId()) + iconImageView!!.setId(generateViewId()) + titleTextView!!.setId(generateViewId()) + summaryTextView!!.setId(generateViewId()) + materialSwitch!!.setId(generateViewId()) + + val textContainer = findViewById(R.id.text_container) + val layoutParams: LayoutParams = textContainer.layoutParams as LayoutParams + layoutParams.addRule(START_OF, materialSwitch!!.id) + layoutParams.addRule(END_OF, iconImageView!!.id) + textContainer.setLayoutParams(layoutParams) + } + + interface BeforeSwitchChangeListener { + fun beforeSwitchChanged() } } diff --git a/app/src/main/java/com/drdisagree/colorblendr/utils/AppUtil.kt b/app/src/main/java/com/drdisagree/colorblendr/utils/AppUtil.kt index a56d761..36bbc71 100644 --- a/app/src/main/java/com/drdisagree/colorblendr/utils/AppUtil.kt +++ b/app/src/main/java/com/drdisagree/colorblendr/utils/AppUtil.kt @@ -1,66 +1,68 @@ -package com.drdisagree.colorblendr.utils; +package com.drdisagree.colorblendr.utils -import android.Manifest; -import android.app.Activity; -import android.content.Context; -import android.content.Intent; -import android.content.pm.PackageManager; -import android.net.Uri; -import android.os.Build; -import android.os.Environment; -import android.provider.Settings; +import android.Manifest +import android.app.Activity +import android.content.Context +import android.content.Intent +import android.content.pm.PackageManager +import android.net.Uri +import android.os.Build +import android.os.Environment +import android.provider.Settings +import androidx.core.app.ActivityCompat +import androidx.core.content.ContextCompat +import com.drdisagree.colorblendr.BuildConfig -import androidx.core.app.ActivityCompat; -import androidx.core.content.ContextCompat; +object AppUtil { + val REQUIRED_PERMISSIONS: Array = + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) arrayOf( + Manifest.permission.POST_NOTIFICATIONS, + Manifest.permission.READ_MEDIA_IMAGES + ) else arrayOf( + Manifest.permission.READ_EXTERNAL_STORAGE + ) -import com.drdisagree.colorblendr.BuildConfig; - -public class AppUtil { - - public static final String[] REQUIRED_PERMISSIONS = Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU ? - new String[]{ - Manifest.permission.POST_NOTIFICATIONS, - Manifest.permission.READ_MEDIA_IMAGES - } : - new String[]{ - Manifest.permission.READ_EXTERNAL_STORAGE - }; - - public static boolean permissionsGranted(Context context) { + fun permissionsGranted(context: Context): Boolean { if (!hasStoragePermission()) { - return false; + return false } - for (String permission : REQUIRED_PERMISSIONS) { - if (ContextCompat.checkSelfPermission(context, permission) != PackageManager.PERMISSION_GRANTED) { - return false; + for (permission in REQUIRED_PERMISSIONS) { + if (ContextCompat.checkSelfPermission( + context, + permission + ) != PackageManager.PERMISSION_GRANTED + ) { + return false } } - return true; + return true } - public static boolean hasStoragePermission() { - return Environment.isExternalStorageManager() || Environment.isExternalStorageLegacy(); + fun hasStoragePermission(): Boolean { + return Environment.isExternalStorageManager() || Environment.isExternalStorageLegacy() } - public static void requestStoragePermission(Context context) { - Intent intent = new Intent(); - intent.setAction(Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION); - intent.setData(Uri.fromParts("package", BuildConfig.APPLICATION_ID, null)); - ((Activity) context).startActivityForResult(intent, 0); + fun requestStoragePermission(context: Context) { + val intent = Intent() + intent.setAction(Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION) + intent.setData(Uri.fromParts("package", BuildConfig.APPLICATION_ID, null)) + (context as Activity).startActivityForResult(intent, 0) - ActivityCompat.requestPermissions((Activity) context, new String[]{ + ActivityCompat.requestPermissions( + context, arrayOf( Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.MANAGE_EXTERNAL_STORAGE - }, 0); + ), 0 + ) } - public static void openAppSettings(Context context) { - Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS); - Uri uri = Uri.fromParts("package", context.getPackageName(), null); - intent.setData(uri); - context.startActivity(intent); + fun openAppSettings(context: Context) { + val intent = Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS) + val uri = Uri.fromParts("package", context.packageName, null) + intent.setData(uri) + context.startActivity(intent) } } diff --git a/app/src/main/java/com/drdisagree/colorblendr/utils/ColorModifiers.kt b/app/src/main/java/com/drdisagree/colorblendr/utils/ColorModifiers.kt index dd034ca..a13d140 100644 --- a/app/src/main/java/com/drdisagree/colorblendr/utils/ColorModifiers.kt +++ b/app/src/main/java/com/drdisagree/colorblendr/utils/ColorModifiers.kt @@ -1,147 +1,131 @@ -package com.drdisagree.colorblendr.utils; +package com.drdisagree.colorblendr.utils -import android.graphics.Color; +import android.graphics.Color +import com.drdisagree.colorblendr.config.RPrefs +import com.drdisagree.colorblendr.utils.ColorSchemeUtil.MONET +import java.util.concurrent.atomic.AtomicInteger +import kotlin.math.min -import com.drdisagree.colorblendr.config.RPrefs; +object ColorModifiers { -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.concurrent.atomic.AtomicInteger; + private val colorNames: Array> = ColorUtil.colorNames -public class ColorModifiers { + fun generateShades(hue: Float, chroma: Float): ArrayList { + val shadeList = ArrayList(List(12) { 0 }) - private static final String[][] colorNames = ColorUtil.getColorNames(); + shadeList[0] = ColorUtil.CAMToColor( + hue, + min(40.0, chroma.toDouble()).toFloat(), 99.0f + ) + shadeList[1] = ColorUtil.CAMToColor( + hue, + min(40.0, chroma.toDouble()).toFloat(), 95.0f + ) - public static ArrayList generateShades(float hue, float chroma) { - ArrayList shadeList = new ArrayList<>(Arrays.asList(new Integer[12])); - - shadeList.set(0, ColorUtil.CAMToColor(hue, Math.min(40.0f, chroma), 99.0f)); - shadeList.set(1, ColorUtil.CAMToColor(hue, Math.min(40.0f, chroma), 95.0f)); - - for (int i = 2; i < 12; i++) { - float lstar; - if (i == 6) { - lstar = 49.6f; + for (i in 2..11) { + val lstar = if (i == 6) { + 49.6f } else { - lstar = 100 - ((i - 1) * 10); + (100 - ((i - 1) * 10)).toFloat() } - shadeList.set(i, ColorUtil.CAMToColor(hue, chroma, lstar)); + shadeList[i] = ColorUtil.CAMToColor(hue, chroma, lstar) } - return shadeList; - } - - public static ArrayList modifyColors( - ArrayList palette, - AtomicInteger counter, - ColorSchemeUtil.MONET style, - int monetAccentSaturation, - int monetBackgroundSaturation, - int monetBackgroundLightness, - boolean pitchBlackTheme, - boolean accurateShades, - boolean modifyPitchBlack - ) { - return modifyColors( - palette, - counter, - style, - monetAccentSaturation, - monetBackgroundSaturation, - monetBackgroundLightness, - pitchBlackTheme, - accurateShades, - modifyPitchBlack, - true - ); + return shadeList } - public static ArrayList modifyColors( - ArrayList palette, - AtomicInteger counter, - ColorSchemeUtil.MONET style, - int monetAccentSaturation, - int monetBackgroundSaturation, - int monetBackgroundLightness, - boolean pitchBlackTheme, - boolean accurateShades, - boolean modifyPitchBlack, - boolean overrideColors - ) { - counter.getAndIncrement(); - - boolean accentPalette = counter.get() <= 3; - - boolean accentSaturation = monetAccentSaturation != 100; - boolean backgroundSaturation = monetBackgroundSaturation != 100; - boolean backgroundLightness = monetBackgroundLightness != 100; + fun modifyColors( + palette: ArrayList, + counter: AtomicInteger, + style: MONET, + monetAccentSaturation: Int, + monetBackgroundSaturation: Int, + monetBackgroundLightness: Int, + pitchBlackTheme: Boolean, + accurateShades: Boolean, + modifyPitchBlack: Boolean, + overrideColors: Boolean = true + ): ArrayList { + counter.getAndIncrement() + + val accentPalette = counter.get() <= 3 + + val accentSaturation = monetAccentSaturation != 100 + val backgroundSaturation = monetBackgroundSaturation != 100 + val backgroundLightness = monetBackgroundLightness != 100 if (accentPalette) { - if (accentSaturation && !style.equals(ColorSchemeUtil.MONET.MONOCHROMATIC)) { + if (accentSaturation && style != MONET.MONOCHROMATIC) { // Set accent saturation - palette.replaceAll(o -> ColorUtil.modifySaturation(o, monetAccentSaturation)); + palette.replaceAll { o: Int -> + ColorUtil.modifySaturation( + o, + monetAccentSaturation + ) + } } } else { - if (backgroundSaturation && !style.equals(ColorSchemeUtil.MONET.MONOCHROMATIC)) { + if (backgroundSaturation && style != MONET.MONOCHROMATIC) { // Set background saturation - palette.replaceAll(o -> ColorUtil.modifySaturation(o, monetBackgroundSaturation)); + palette.replaceAll { o: Int -> + ColorUtil.modifySaturation( + o, + monetBackgroundSaturation + ) + } } - if (backgroundLightness && !style.equals(ColorSchemeUtil.MONET.MONOCHROMATIC)) { + if (backgroundLightness && style != MONET.MONOCHROMATIC) { // Set background lightness - for (int j = 0; j < palette.size(); j++) { - palette.set(j, ColorUtil.modifyLightness(palette.get(j), monetBackgroundLightness, j + 1)); + for (j in palette.indices) { + palette[j] = + ColorUtil.modifyLightness(palette[j], monetBackgroundLightness, j + 1) } } if (pitchBlackTheme && modifyPitchBlack) { // Set pitch black theme - palette.set(10, Color.BLACK); + palette[10] = Color.BLACK } } - if (style.equals(ColorSchemeUtil.MONET.MONOCHROMATIC)) { + if (style == MONET.MONOCHROMATIC) { // Set monochrome lightness - for (int j = 0; j < palette.size(); j++) { - palette.set(j, ColorUtil.modifyLightness(palette.get(j), monetBackgroundLightness, j + 1)); + for (j in palette.indices) { + palette[j] = ColorUtil.modifyLightness(palette[j], monetBackgroundLightness, j + 1) } } if (overrideColors) { - for (int j = 0; j < palette.size() - 1; j++) { - int i = counter.get() - 1; + for (j in 0 until palette.size - 1) { + val i = counter.get() - 1 - int overriddenColor = RPrefs.getInt(colorNames[i][j + 1], Integer.MIN_VALUE); + val overriddenColor = RPrefs.getInt(colorNames[i][j + 1], Int.MIN_VALUE) - if (overriddenColor != Integer.MIN_VALUE) { - palette.set(j, overriddenColor); + if (overriddenColor != Int.MIN_VALUE) { + palette[j] = overriddenColor } else if (!accurateShades && i == 0 && j == 2) { - palette.set(j, palette.get(j + 2)); + palette[j] = palette[j + 2] } } } if (counter.get() >= 5) { - counter.set(0); + counter.set(0) } - return palette; + return palette } - public static Map zipToMap(List keys, List values) { - Map result = new HashMap<>(); + fun zipToMap(keys: List, values: List): Map { + val result: MutableMap = HashMap() - if (keys.size() != values.size()) { - throw new IllegalArgumentException("Lists must have the same size. Provided keys size: " + keys.size() + " Provided values size: " + values.size() + "."); - } + require(keys.size == values.size) { "Lists must have the same size. Provided keys size: " + keys.size + " Provided values size: " + values.size + "." } - for (int i = 0; i < keys.size(); i++) { - result.put(keys.get(i), values.get(i)); + for (i in keys.indices) { + result[keys[i]] = values[i] } - return result; + return result } } diff --git a/app/src/main/java/com/drdisagree/colorblendr/utils/ColorSchemeUtil.kt b/app/src/main/java/com/drdisagree/colorblendr/utils/ColorSchemeUtil.kt index 1c18058..1dfca29 100644 --- a/app/src/main/java/com/drdisagree/colorblendr/utils/ColorSchemeUtil.kt +++ b/app/src/main/java/com/drdisagree/colorblendr/utils/ColorSchemeUtil.kt @@ -1,112 +1,129 @@ -package com.drdisagree.colorblendr.utils; - -import android.content.Context; - -import androidx.annotation.ColorInt; - -import com.drdisagree.colorblendr.R; -import com.drdisagree.colorblendr.utils.monet.hct.Hct; -import com.drdisagree.colorblendr.utils.monet.palettes.TonalPalette; -import com.drdisagree.colorblendr.utils.monet.dynamiccolor.DynamicScheme; -import com.drdisagree.colorblendr.utils.monet.scheme.SchemeContent; -import com.drdisagree.colorblendr.utils.monet.scheme.SchemeExpressive; -import com.drdisagree.colorblendr.utils.monet.scheme.SchemeFidelity; -import com.drdisagree.colorblendr.utils.monet.scheme.SchemeFruitSalad; -import com.drdisagree.colorblendr.utils.monet.scheme.SchemeMonochrome; -import com.drdisagree.colorblendr.utils.monet.scheme.SchemeNeutral; -import com.drdisagree.colorblendr.utils.monet.scheme.SchemeRainbow; -import com.drdisagree.colorblendr.utils.monet.scheme.SchemeTonalSpot; -import com.drdisagree.colorblendr.utils.monet.scheme.SchemeVibrant; +package com.drdisagree.colorblendr.utils + +import android.content.Context +import androidx.annotation.ColorInt +import com.drdisagree.colorblendr.R +import com.drdisagree.colorblendr.utils.monet.dynamiccolor.DynamicScheme +import com.drdisagree.colorblendr.utils.monet.hct.Hct +import com.drdisagree.colorblendr.utils.monet.palettes.TonalPalette +import com.drdisagree.colorblendr.utils.monet.scheme.SchemeContent +import com.drdisagree.colorblendr.utils.monet.scheme.SchemeExpressive +import com.drdisagree.colorblendr.utils.monet.scheme.SchemeFidelity +import com.drdisagree.colorblendr.utils.monet.scheme.SchemeFruitSalad +import com.drdisagree.colorblendr.utils.monet.scheme.SchemeMonochrome +import com.drdisagree.colorblendr.utils.monet.scheme.SchemeNeutral +import com.drdisagree.colorblendr.utils.monet.scheme.SchemeRainbow +import com.drdisagree.colorblendr.utils.monet.scheme.SchemeTonalSpot +import com.drdisagree.colorblendr.utils.monet.scheme.SchemeVibrant + +object ColorSchemeUtil { + private val tones: IntArray = intArrayOf(100, 99, 95, 90, 80, 70, 60, 50, 40, 30, 20, 10, 0) + + fun generateColorPalette( + style: MONET, + @ColorInt color: Int, + isDark: Boolean = SystemUtil.isDarkMode, + contrast: Int = 5 + ): ArrayList> { + val palette = ArrayList>() + + val dynamicScheme = getDynamicScheme(style, color, isDark, contrast) + + val tonalPalettes = arrayOf( + dynamicScheme.primaryPalette, + dynamicScheme.secondaryPalette, + dynamicScheme.tertiaryPalette, + dynamicScheme.neutralPalette, + dynamicScheme.neutralVariantPalette + ) + + for (tonalPalette in tonalPalettes) { + palette.add(createToneList(tonalPalette)) + } -import java.util.ArrayList; + return palette + } -public class ColorSchemeUtil { + private fun getDynamicScheme( + style: MONET, + @ColorInt color: Int, + isDark: Boolean, + contrast: Int + ): DynamicScheme { + return when (style) { + MONET.SPRITZ -> SchemeNeutral(Hct.fromInt(color), isDark, contrast.toDouble()) + MONET.MONOCHROMATIC -> SchemeMonochrome(Hct.fromInt(color), isDark, contrast.toDouble()) + MONET.TONAL_SPOT -> SchemeTonalSpot(Hct.fromInt(color), isDark, contrast.toDouble()) + MONET.VIBRANT -> SchemeVibrant(Hct.fromInt(color), isDark, contrast.toDouble()) + MONET.RAINBOW -> SchemeRainbow(Hct.fromInt(color), isDark, contrast.toDouble()) + MONET.EXPRESSIVE -> SchemeExpressive(Hct.fromInt(color), isDark, contrast.toDouble()) + MONET.FIDELITY -> SchemeFidelity(Hct.fromInt(color), isDark, contrast.toDouble()) + MONET.CONTENT -> SchemeContent(Hct.fromInt(color), isDark, contrast.toDouble()) + MONET.FRUIT_SALAD -> SchemeFruitSalad(Hct.fromInt(color), isDark, contrast.toDouble()) + } + } - public enum MONET { - SPRITZ, - MONOCHROMATIC, - TONAL_SPOT, - VIBRANT, - RAINBOW, - EXPRESSIVE, - FIDELITY, - CONTENT, - FRUIT_SALAD + private fun createToneList(palette: TonalPalette): ArrayList { + val toneList = ArrayList() + for (tone in tones) { + toneList.add(palette.tone(tone)) + } + return toneList } - public static final int[] tones = {100, 99, 95, 90, 80, 70, 60, 50, 40, 30, 20, 10, 0}; + fun stringToEnumMonetStyle(context: Context, enumString: String): MONET { + return when (enumString) { + context.getString(R.string.monet_neutral) -> { + MONET.SPRITZ + } - public static ArrayList> generateColorPalette(MONET style, @ColorInt int color) { - return generateColorPalette(style, color, SystemUtil.isDarkMode(), 5); - } + context.getString(R.string.monet_monochrome) -> { + MONET.MONOCHROMATIC + } - public static ArrayList> generateColorPalette(MONET style, @ColorInt int color, boolean isDark) { - return generateColorPalette(style, color, isDark, 5); - } + context.getString(R.string.monet_tonalspot) -> { + MONET.TONAL_SPOT + } - public static ArrayList> generateColorPalette(MONET style, @ColorInt int color, boolean isDark, int contrast) { - ArrayList> palette = new ArrayList<>(); + context.getString(R.string.monet_vibrant) -> { + MONET.VIBRANT + } - DynamicScheme dynamicScheme = getDynamicScheme(style, color, isDark, contrast); + context.getString(R.string.monet_rainbow) -> { + MONET.RAINBOW + } - TonalPalette[] tonalPalettes = { - dynamicScheme.primaryPalette, - dynamicScheme.secondaryPalette, - dynamicScheme.tertiaryPalette, - dynamicScheme.neutralPalette, - dynamicScheme.neutralVariantPalette - }; + context.getString(R.string.monet_expressive) -> { + MONET.EXPRESSIVE + } - for (TonalPalette tonalPalette : tonalPalettes) { - palette.add(createToneList(tonalPalette)); - } + context.getString(R.string.monet_fidelity) -> { + MONET.FIDELITY + } - return palette; - } + context.getString(R.string.monet_content) -> { + MONET.CONTENT + } - public static DynamicScheme getDynamicScheme(MONET style, @ColorInt int color, boolean isDark, int contrast) { - return switch (style) { - case SPRITZ -> new SchemeNeutral(Hct.fromInt(color), isDark, contrast); - case MONOCHROMATIC -> new SchemeMonochrome(Hct.fromInt(color), isDark, contrast); - case TONAL_SPOT -> new SchemeTonalSpot(Hct.fromInt(color), isDark, contrast); - case VIBRANT -> new SchemeVibrant(Hct.fromInt(color), isDark, contrast); - case RAINBOW -> new SchemeRainbow(Hct.fromInt(color), isDark, contrast); - case EXPRESSIVE -> new SchemeExpressive(Hct.fromInt(color), isDark, contrast); - case FIDELITY -> new SchemeFidelity(Hct.fromInt(color), isDark, contrast); - case CONTENT -> new SchemeContent(Hct.fromInt(color), isDark, contrast); - case FRUIT_SALAD -> new SchemeFruitSalad(Hct.fromInt(color), isDark, contrast); - }; - } + context.getString(R.string.monet_fruitsalad) -> { + MONET.FRUIT_SALAD + } - private static ArrayList createToneList(TonalPalette palette) { - ArrayList toneList = new ArrayList<>(); - for (int tone : ColorSchemeUtil.tones) { - toneList.add(palette.tone(tone)); + else -> { + MONET.TONAL_SPOT + } } - return toneList; } - public static MONET stringToEnumMonetStyle(Context context, String enumString) { - if (enumString.equals(context.getString(R.string.monet_neutral))) { - return MONET.SPRITZ; - } else if (enumString.equals(context.getString(R.string.monet_monochrome))) { - return MONET.MONOCHROMATIC; - } else if (enumString.equals(context.getString(R.string.monet_tonalspot))) { - return MONET.TONAL_SPOT; - } else if (enumString.equals(context.getString(R.string.monet_vibrant))) { - return MONET.VIBRANT; - } else if (enumString.equals(context.getString(R.string.monet_rainbow))) { - return MONET.RAINBOW; - } else if (enumString.equals(context.getString(R.string.monet_expressive))) { - return MONET.EXPRESSIVE; - } else if (enumString.equals(context.getString(R.string.monet_fidelity))) { - return MONET.FIDELITY; - } else if (enumString.equals(context.getString(R.string.monet_content))) { - return MONET.CONTENT; - } else if (enumString.equals(context.getString(R.string.monet_fruitsalad))) { - return MONET.FRUIT_SALAD; - } else { - return MONET.TONAL_SPOT; - } + enum class MONET { + SPRITZ, + MONOCHROMATIC, + TONAL_SPOT, + VIBRANT, + RAINBOW, + EXPRESSIVE, + FIDELITY, + CONTENT, + FRUIT_SALAD } } diff --git a/app/src/main/java/com/drdisagree/colorblendr/utils/ColorUtil.kt b/app/src/main/java/com/drdisagree/colorblendr/utils/ColorUtil.kt index 36b4758..272db3f 100644 --- a/app/src/main/java/com/drdisagree/colorblendr/utils/ColorUtil.kt +++ b/app/src/main/java/com/drdisagree/colorblendr/utils/ColorUtil.kt @@ -1,346 +1,543 @@ -package com.drdisagree.colorblendr.utils; - -import static com.drdisagree.colorblendr.common.Const.MONET_SEED_COLOR; -import static com.drdisagree.colorblendr.common.Const.WALLPAPER_COLOR_LIST; - -import android.content.Context; -import android.graphics.Color; -import android.util.TypedValue; - -import androidx.annotation.ColorInt; -import androidx.annotation.FloatRange; -import androidx.core.content.ContextCompat; -import androidx.core.graphics.ColorUtils; - -import com.drdisagree.colorblendr.ColorBlendr; -import com.drdisagree.colorblendr.common.Const; -import com.drdisagree.colorblendr.config.RPrefs; -import com.drdisagree.colorblendr.utils.cam.Cam; -import com.google.gson.reflect.TypeToken; - -import java.util.ArrayList; -import java.util.concurrent.atomic.AtomicInteger; - -public class ColorUtil { - - public static @ColorInt int getColorFromAttribute(Context context, int attr) { - TypedValue typedValue = new TypedValue(); - context.getTheme().resolveAttribute(attr, typedValue, true); - return typedValue.data; +package com.drdisagree.colorblendr.utils + +import android.content.Context +import android.graphics.Color +import android.util.TypedValue +import androidx.annotation.ColorInt +import androidx.annotation.FloatRange +import androidx.core.content.ContextCompat +import androidx.core.graphics.ColorUtils +import com.drdisagree.colorblendr.ColorBlendr.Companion.appContext +import com.drdisagree.colorblendr.common.Const +import com.drdisagree.colorblendr.config.RPrefs +import com.drdisagree.colorblendr.utils.ColorSchemeUtil.MONET +import com.drdisagree.colorblendr.utils.ColorSchemeUtil.generateColorPalette +import com.drdisagree.colorblendr.utils.cam.Cam +import com.google.gson.reflect.TypeToken +import java.util.concurrent.atomic.AtomicInteger +import kotlin.math.min +import kotlin.math.pow + +object ColorUtil { + @ColorInt + fun getColorFromAttribute(context: Context, attr: Int): Int { + val typedValue = TypedValue() + context.theme.resolveAttribute(attr, typedValue, true) + return typedValue.data } - public static ArrayList> generateModifiedColors( - Context context, - ColorSchemeUtil.MONET style, - int accentSaturation, - int backgroundSaturation, - int backgroundLightness, - boolean pitchBlackTheme, - boolean accurateShades - ) { - return generateModifiedColors( - context, - style, - accentSaturation, - backgroundSaturation, - backgroundLightness, - pitchBlackTheme, - accurateShades, - true - ); - } + fun generateModifiedColors( + context: Context, + style: MONET, + accentSaturation: Int, + backgroundSaturation: Int, + backgroundLightness: Int, + pitchBlackTheme: Boolean, + accurateShades: Boolean, + modifyPitchBlack: Boolean = true, + isDark: Boolean = SystemUtil.isDarkMode + ): ArrayList> { + val wallpaperColors = RPrefs.getString(Const.WALLPAPER_COLOR_LIST, null) + + val wallpaperColorList = if (wallpaperColors != null) { + Const.GSON.fromJson( + wallpaperColors, + object : TypeToken>() { + }.type + ) + } else { + WallpaperColorUtil.getWallpaperColors(context) + } - public static ArrayList> generateModifiedColors( - Context context, - ColorSchemeUtil.MONET style, - int accentSaturation, - int backgroundSaturation, - int backgroundLightness, - boolean pitchBlackTheme, - boolean accurateShades, - boolean modifyPitchBlack - ) { return generateModifiedColors( - context, - style, - accentSaturation, - backgroundSaturation, - backgroundLightness, - pitchBlackTheme, - accurateShades, - modifyPitchBlack, - SystemUtil.isDarkMode() - ); + style, + RPrefs.getInt( + Const.MONET_SEED_COLOR, + wallpaperColorList[0] + ), + accentSaturation, + backgroundSaturation, + backgroundLightness, + pitchBlackTheme, + accurateShades, + modifyPitchBlack, + isDark, + true + ) } - public static ArrayList> generateModifiedColors( - Context context, - ColorSchemeUtil.MONET style, - int accentSaturation, - int backgroundSaturation, - int backgroundLightness, - boolean pitchBlackTheme, - boolean accurateShades, - boolean modifyPitchBlack, - boolean isDark - ) { - String wallpaperColors = RPrefs.getString(WALLPAPER_COLOR_LIST, null); - ArrayList wallpaperColorList; - - if (wallpaperColors != null) { - wallpaperColorList = Const.GSON.fromJson( - wallpaperColors, - new TypeToken>() { - }.getType() - ); - } else { - wallpaperColorList = WallpaperColorUtil.getWallpaperColors(context); - } + fun generateModifiedColors( + style: MONET, + @ColorInt seedColor: Int, + accentSaturation: Int, + backgroundSaturation: Int, + backgroundLightness: Int, + pitchBlackTheme: Boolean, + accurateShades: Boolean, + modifyPitchBlack: Boolean, + isDark: Boolean, + overrideColors: Boolean + ): ArrayList> { + val palette: ArrayList> = generateColorPalette( + style, + seedColor, + isDark + ) - return generateModifiedColors( + // Modify colors + for (i in palette.indices) { + val modifiedShades = ColorModifiers.modifyColors( + ArrayList(palette[i].subList(1, palette[i].size)), + AtomicInteger(i), style, - RPrefs.getInt( - MONET_SEED_COLOR, - wallpaperColorList.get(0) - ), accentSaturation, backgroundSaturation, backgroundLightness, pitchBlackTheme, accurateShades, modifyPitchBlack, - isDark, - true - ); - } - - public static ArrayList> generateModifiedColors( - ColorSchemeUtil.MONET style, - @ColorInt int seedColor, - int accentSaturation, - int backgroundSaturation, - int backgroundLightness, - boolean pitchBlackTheme, - boolean accurateShades, - boolean modifyPitchBlack, - boolean isDark, - boolean overrideColors - ) { - ArrayList> palette = ColorSchemeUtil.generateColorPalette( - style, - seedColor, - isDark - ); - - // Modify colors - for (int i = 0; i < palette.size(); i++) { - ArrayList modifiedShades = ColorModifiers.modifyColors( - new ArrayList<>(palette.get(i).subList(1, palette.get(i).size())), - new AtomicInteger(i), - style, - accentSaturation, - backgroundSaturation, - backgroundLightness, - pitchBlackTheme, - accurateShades, - modifyPitchBlack, - overrideColors - ); - for (int j = 1; j < palette.get(i).size(); j++) { - palette.get(i).set(j, modifiedShades.get(j - 1)); + overrideColors + ) + for (j in 1 until palette[i].size) { + palette[i][j] = modifiedShades[j - 1] } } - return palette; + return palette } - public static @ColorInt int getAccentColor(Context context) { - TypedValue typedValue = new TypedValue(); - context.getTheme().resolveAttribute(com.google.android.material.R.attr.colorPrimary, typedValue, true); - return typedValue.data; + @ColorInt + fun getAccentColor(context: Context): Int { + val typedValue = TypedValue() + context.theme.resolveAttribute( + com.google.android.material.R.attr.colorPrimary, + typedValue, + true + ) + return typedValue.data } - public static int modifySaturation(int color, int saturation) { - float saturationFloat = (saturation - 100) / 100f; + fun modifySaturation(color: Int, saturation: Int): Int { + val saturationFloat = (saturation - 100) / 100f - float[] hsl = new float[3]; - ColorUtils.colorToHSL(color, hsl); + val hsl = FloatArray(3) + ColorUtils.colorToHSL(color, hsl) if (saturationFloat > 0) { - hsl[1] += ((1 - hsl[1]) * saturationFloat); + hsl[1] += ((1 - hsl[1]) * saturationFloat) } else if (saturationFloat < 0) { - hsl[1] += (hsl[1] * saturationFloat); + hsl[1] += (hsl[1] * saturationFloat) } - return ColorUtils.HSLToColor(hsl); + return ColorUtils.HSLToColor(hsl) } - public static int modifyLightness(int color, int lightness, int idx) { - float lightnessFloat = (lightness - 100) / 1000f; - float shade = getSystemTintList()[idx]; + fun modifyLightness(color: Int, lightness: Int, idx: Int): Int { + var lightnessFloat = (lightness - 100) / 1000f + val shade = systemTintList[idx] - if (idx == 0 || idx == 12) { - lightnessFloat = 0; - } else if (idx == 1) { - lightnessFloat /= 10; - } else if (idx == 2) { - lightnessFloat /= 2; - } + when (idx) { + 0, 12 -> { + lightnessFloat = 0f + } - float[] hsl = new float[3]; - ColorUtils.colorToHSL(color, hsl); + 1 -> { + lightnessFloat /= 10f + } - hsl[2] = shade + lightnessFloat; + 2 -> { + lightnessFloat /= 2f + } + } - return ColorUtils.HSLToColor(hsl); - } + val hsl = FloatArray(3) + ColorUtils.colorToHSL(color, hsl) - public static float getHue(int color) { - float[] hsl = new float[3]; - ColorUtils.colorToHSL(color, hsl); + hsl[2] = shade + lightnessFloat - return hsl[0]; + return ColorUtils.HSLToColor(hsl) } - public static float[] getSystemTintList() { - return new float[]{1.0f, 0.99f, 0.95f, 0.9f, 0.8f, 0.7f, 0.6f, 0.496f, 0.4f, 0.3f, 0.2f, 0.1f, 0.0f}; - } + fun getHue(color: Int): Float { + val hsl = FloatArray(3) + ColorUtils.colorToHSL(color, hsl) - public static String[][] getColorNames() { - String[] accentTypes = {"system_accent1", "system_accent2", "system_accent3", "system_neutral1", "system_neutral2"}; - String[] values = {"0", "10", "50", "100", "200", "300", "400", "500", "600", "700", "800", "900", "1000"}; + return hsl[0] + } - String[][] colorNames = new String[accentTypes.length][values.length]; + private val systemTintList: FloatArray + get() = floatArrayOf( + 1.0f, + 0.99f, + 0.95f, + 0.9f, + 0.8f, + 0.7f, + 0.6f, + 0.496f, + 0.4f, + 0.3f, + 0.2f, + 0.1f, + 0.0f + ) + + val colorNames: Array> + get() { + val accentTypes = arrayOf( + "system_accent1", + "system_accent2", + "system_accent3", + "system_neutral1", + "system_neutral2" + ) + val values = arrayOf( + "0", + "10", + "50", + "100", + "200", + "300", + "400", + "500", + "600", + "700", + "800", + "900", + "1000" + ) + + val colorNames = Array(accentTypes.size) { + Array(values.size) { "" } + } - for (int i = 0; i < accentTypes.length; i++) { - for (int j = 0; j < values.length; j++) { - colorNames[i][j] = accentTypes[i] + "_" + values[j]; + for (i in accentTypes.indices) { + for (j in values.indices) { + colorNames[i][j] = accentTypes[i] + "_" + values[j] + } } - } - return colorNames; - } + return colorNames + } - public static String[][] getColorNamesM3(boolean isDynamic, boolean prefixG) { - String prefix = "m3_ref_palette_"; - String dynamic = "dynamic_"; + fun getColorNamesM3(isDynamic: Boolean, prefixG: Boolean): Array> { + val prefix = "m3_ref_palette_" + val dynamic = "dynamic_" - String[] accentTypes = {"primary", "secondary", "tertiary", "neutral", "neutral_variant"}; - String[] values = {"100", "99", "95", "90", "80", "70", "60", "50", "40", "30", "20", "10", "0"}; + val accentTypes = arrayOf("primary", "secondary", "tertiary", "neutral", "neutral_variant") + val values = + arrayOf("100", "99", "95", "90", "80", "70", "60", "50", "40", "30", "20", "10", "0") - String[][] colorNames = new String[accentTypes.length][values.length]; + val colorNames = Array(accentTypes.size) { Array(values.size) { "" } } - for (int i = 0; i < accentTypes.length; i++) { - for (int j = 0; j < values.length; j++) { - colorNames[i][j] = (prefixG ? "g" : "") + prefix + (isDynamic ? dynamic : "") + accentTypes[i] + values[j]; + for (i in accentTypes.indices) { + for (j in values.indices) { + colorNames[i][j] = + (if (prefixG) "g" else "") + prefix + (if (isDynamic) dynamic else "") + accentTypes[i] + values[j] } } - return colorNames; + return colorNames } - public static String intToHexColor(int colorInt) { - return String.format("#%06X", (0xFFFFFF & colorInt)); + fun intToHexColor(colorInt: Int): String { + return String.format("#%06X", (0xFFFFFF and colorInt)) } - public static String intToHexColorNoHash(int colorInt) { - return String.format("%06X", (0xFFFFFF & colorInt)); + fun intToHexColorNoHash(colorInt: Int): String { + return String.format("%06X", (0xFFFFFF and colorInt)) } - public static int[][] getSystemColors(Context context) { - return new int[][]{ - new int[]{ - context.getResources().getColor(com.google.android.material.R.color.material_dynamic_primary100, context.getTheme()), - context.getResources().getColor(com.google.android.material.R.color.material_dynamic_primary99, context.getTheme()), - context.getResources().getColor(com.google.android.material.R.color.material_dynamic_primary95, context.getTheme()), - context.getResources().getColor(com.google.android.material.R.color.material_dynamic_primary90, context.getTheme()), - context.getResources().getColor(com.google.android.material.R.color.material_dynamic_primary80, context.getTheme()), - context.getResources().getColor(com.google.android.material.R.color.material_dynamic_primary70, context.getTheme()), - context.getResources().getColor(com.google.android.material.R.color.material_dynamic_primary60, context.getTheme()), - context.getResources().getColor(com.google.android.material.R.color.material_dynamic_primary50, context.getTheme()), - context.getResources().getColor(com.google.android.material.R.color.material_dynamic_primary40, context.getTheme()), - context.getResources().getColor(com.google.android.material.R.color.material_dynamic_primary30, context.getTheme()), - context.getResources().getColor(com.google.android.material.R.color.material_dynamic_primary20, context.getTheme()), - context.getResources().getColor(com.google.android.material.R.color.material_dynamic_primary10, context.getTheme()), - context.getResources().getColor(com.google.android.material.R.color.material_dynamic_primary0, context.getTheme()) - }, - - new int[]{ - context.getResources().getColor(com.google.android.material.R.color.material_dynamic_secondary100, context.getTheme()), - context.getResources().getColor(com.google.android.material.R.color.material_dynamic_secondary99, context.getTheme()), - context.getResources().getColor(com.google.android.material.R.color.material_dynamic_secondary95, context.getTheme()), - context.getResources().getColor(com.google.android.material.R.color.material_dynamic_secondary90, context.getTheme()), - context.getResources().getColor(com.google.android.material.R.color.material_dynamic_secondary80, context.getTheme()), - context.getResources().getColor(com.google.android.material.R.color.material_dynamic_secondary70, context.getTheme()), - context.getResources().getColor(com.google.android.material.R.color.material_dynamic_secondary60, context.getTheme()), - context.getResources().getColor(com.google.android.material.R.color.material_dynamic_secondary50, context.getTheme()), - context.getResources().getColor(com.google.android.material.R.color.material_dynamic_secondary40, context.getTheme()), - context.getResources().getColor(com.google.android.material.R.color.material_dynamic_secondary30, context.getTheme()), - context.getResources().getColor(com.google.android.material.R.color.material_dynamic_secondary20, context.getTheme()), - context.getResources().getColor(com.google.android.material.R.color.material_dynamic_secondary10, context.getTheme()), - context.getResources().getColor(com.google.android.material.R.color.material_dynamic_secondary0, context.getTheme()) - }, - - new int[]{ - context.getResources().getColor(com.google.android.material.R.color.material_dynamic_tertiary100, context.getTheme()), - context.getResources().getColor(com.google.android.material.R.color.material_dynamic_tertiary99, context.getTheme()), - context.getResources().getColor(com.google.android.material.R.color.material_dynamic_tertiary95, context.getTheme()), - context.getResources().getColor(com.google.android.material.R.color.material_dynamic_tertiary90, context.getTheme()), - context.getResources().getColor(com.google.android.material.R.color.material_dynamic_tertiary80, context.getTheme()), - context.getResources().getColor(com.google.android.material.R.color.material_dynamic_tertiary70, context.getTheme()), - context.getResources().getColor(com.google.android.material.R.color.material_dynamic_tertiary60, context.getTheme()), - context.getResources().getColor(com.google.android.material.R.color.material_dynamic_tertiary50, context.getTheme()), - context.getResources().getColor(com.google.android.material.R.color.material_dynamic_tertiary40, context.getTheme()), - context.getResources().getColor(com.google.android.material.R.color.material_dynamic_tertiary30, context.getTheme()), - context.getResources().getColor(com.google.android.material.R.color.material_dynamic_tertiary20, context.getTheme()), - context.getResources().getColor(com.google.android.material.R.color.material_dynamic_tertiary10, context.getTheme()), - context.getResources().getColor(com.google.android.material.R.color.material_dynamic_tertiary0, context.getTheme()) - }, - - new int[]{ - context.getResources().getColor(com.google.android.material.R.color.material_dynamic_neutral100, context.getTheme()), - context.getResources().getColor(com.google.android.material.R.color.material_dynamic_neutral99, context.getTheme()), - context.getResources().getColor(com.google.android.material.R.color.material_dynamic_neutral95, context.getTheme()), - context.getResources().getColor(com.google.android.material.R.color.material_dynamic_neutral90, context.getTheme()), - context.getResources().getColor(com.google.android.material.R.color.material_dynamic_neutral80, context.getTheme()), - context.getResources().getColor(com.google.android.material.R.color.material_dynamic_neutral70, context.getTheme()), - context.getResources().getColor(com.google.android.material.R.color.material_dynamic_neutral60, context.getTheme()), - context.getResources().getColor(com.google.android.material.R.color.material_dynamic_neutral50, context.getTheme()), - context.getResources().getColor(com.google.android.material.R.color.material_dynamic_neutral40, context.getTheme()), - context.getResources().getColor(com.google.android.material.R.color.material_dynamic_neutral30, context.getTheme()), - context.getResources().getColor(com.google.android.material.R.color.material_dynamic_neutral20, context.getTheme()), - context.getResources().getColor(com.google.android.material.R.color.material_dynamic_neutral10, context.getTheme()), - context.getResources().getColor(com.google.android.material.R.color.material_dynamic_neutral0, context.getTheme()) - }, - - new int[]{ - context.getResources().getColor(com.google.android.material.R.color.material_dynamic_neutral_variant100, context.getTheme()), - context.getResources().getColor(com.google.android.material.R.color.material_dynamic_neutral_variant99, context.getTheme()), - context.getResources().getColor(com.google.android.material.R.color.material_dynamic_neutral_variant95, context.getTheme()), - context.getResources().getColor(com.google.android.material.R.color.material_dynamic_neutral_variant90, context.getTheme()), - context.getResources().getColor(com.google.android.material.R.color.material_dynamic_neutral_variant80, context.getTheme()), - context.getResources().getColor(com.google.android.material.R.color.material_dynamic_neutral_variant70, context.getTheme()), - context.getResources().getColor(com.google.android.material.R.color.material_dynamic_neutral_variant60, context.getTheme()), - context.getResources().getColor(com.google.android.material.R.color.material_dynamic_neutral_variant50, context.getTheme()), - context.getResources().getColor(com.google.android.material.R.color.material_dynamic_neutral_variant40, context.getTheme()), - context.getResources().getColor(com.google.android.material.R.color.material_dynamic_neutral_variant30, context.getTheme()), - context.getResources().getColor(com.google.android.material.R.color.material_dynamic_neutral_variant20, context.getTheme()), - context.getResources().getColor(com.google.android.material.R.color.material_dynamic_neutral_variant10, context.getTheme()), - context.getResources().getColor(com.google.android.material.R.color.material_dynamic_neutral_variant0, context.getTheme()) - }}; + fun getSystemColors(context: Context): Array { + return arrayOf( + intArrayOf( + context.resources.getColor( + com.google.android.material.R.color.material_dynamic_primary100, + context.theme + ), + context.resources.getColor( + com.google.android.material.R.color.material_dynamic_primary99, + context.theme + ), + context.resources.getColor( + com.google.android.material.R.color.material_dynamic_primary95, + context.theme + ), + context.resources.getColor( + com.google.android.material.R.color.material_dynamic_primary90, + context.theme + ), + context.resources.getColor( + com.google.android.material.R.color.material_dynamic_primary80, + context.theme + ), + context.resources.getColor( + com.google.android.material.R.color.material_dynamic_primary70, + context.theme + ), + context.resources.getColor( + com.google.android.material.R.color.material_dynamic_primary60, + context.theme + ), + context.resources.getColor( + com.google.android.material.R.color.material_dynamic_primary50, + context.theme + ), + context.resources.getColor( + com.google.android.material.R.color.material_dynamic_primary40, + context.theme + ), + context.resources.getColor( + com.google.android.material.R.color.material_dynamic_primary30, + context.theme + ), + context.resources.getColor( + com.google.android.material.R.color.material_dynamic_primary20, + context.theme + ), + context.resources.getColor( + com.google.android.material.R.color.material_dynamic_primary10, + context.theme + ), + context.resources.getColor( + com.google.android.material.R.color.material_dynamic_primary0, + context.theme + ) + ), + + intArrayOf( + context.resources.getColor( + com.google.android.material.R.color.material_dynamic_secondary100, + context.theme + ), + context.resources.getColor( + com.google.android.material.R.color.material_dynamic_secondary99, + context.theme + ), + context.resources.getColor( + com.google.android.material.R.color.material_dynamic_secondary95, + context.theme + ), + context.resources.getColor( + com.google.android.material.R.color.material_dynamic_secondary90, + context.theme + ), + context.resources.getColor( + com.google.android.material.R.color.material_dynamic_secondary80, + context.theme + ), + context.resources.getColor( + com.google.android.material.R.color.material_dynamic_secondary70, + context.theme + ), + context.resources.getColor( + com.google.android.material.R.color.material_dynamic_secondary60, + context.theme + ), + context.resources.getColor( + com.google.android.material.R.color.material_dynamic_secondary50, + context.theme + ), + context.resources.getColor( + com.google.android.material.R.color.material_dynamic_secondary40, + context.theme + ), + context.resources.getColor( + com.google.android.material.R.color.material_dynamic_secondary30, + context.theme + ), + context.resources.getColor( + com.google.android.material.R.color.material_dynamic_secondary20, + context.theme + ), + context.resources.getColor( + com.google.android.material.R.color.material_dynamic_secondary10, + context.theme + ), + context.resources.getColor( + com.google.android.material.R.color.material_dynamic_secondary0, + context.theme + ) + ), + + intArrayOf( + context.resources.getColor( + com.google.android.material.R.color.material_dynamic_tertiary100, + context.theme + ), + context.resources.getColor( + com.google.android.material.R.color.material_dynamic_tertiary99, + context.theme + ), + context.resources.getColor( + com.google.android.material.R.color.material_dynamic_tertiary95, + context.theme + ), + context.resources.getColor( + com.google.android.material.R.color.material_dynamic_tertiary90, + context.theme + ), + context.resources.getColor( + com.google.android.material.R.color.material_dynamic_tertiary80, + context.theme + ), + context.resources.getColor( + com.google.android.material.R.color.material_dynamic_tertiary70, + context.theme + ), + context.resources.getColor( + com.google.android.material.R.color.material_dynamic_tertiary60, + context.theme + ), + context.resources.getColor( + com.google.android.material.R.color.material_dynamic_tertiary50, + context.theme + ), + context.resources.getColor( + com.google.android.material.R.color.material_dynamic_tertiary40, + context.theme + ), + context.resources.getColor( + com.google.android.material.R.color.material_dynamic_tertiary30, + context.theme + ), + context.resources.getColor( + com.google.android.material.R.color.material_dynamic_tertiary20, + context.theme + ), + context.resources.getColor( + com.google.android.material.R.color.material_dynamic_tertiary10, + context.theme + ), + context.resources.getColor( + com.google.android.material.R.color.material_dynamic_tertiary0, + context.theme + ) + ), + + intArrayOf( + context.resources.getColor( + com.google.android.material.R.color.material_dynamic_neutral100, + context.theme + ), + context.resources.getColor( + com.google.android.material.R.color.material_dynamic_neutral99, + context.theme + ), + context.resources.getColor( + com.google.android.material.R.color.material_dynamic_neutral95, + context.theme + ), + context.resources.getColor( + com.google.android.material.R.color.material_dynamic_neutral90, + context.theme + ), + context.resources.getColor( + com.google.android.material.R.color.material_dynamic_neutral80, + context.theme + ), + context.resources.getColor( + com.google.android.material.R.color.material_dynamic_neutral70, + context.theme + ), + context.resources.getColor( + com.google.android.material.R.color.material_dynamic_neutral60, + context.theme + ), + context.resources.getColor( + com.google.android.material.R.color.material_dynamic_neutral50, + context.theme + ), + context.resources.getColor( + com.google.android.material.R.color.material_dynamic_neutral40, + context.theme + ), + context.resources.getColor( + com.google.android.material.R.color.material_dynamic_neutral30, + context.theme + ), + context.resources.getColor( + com.google.android.material.R.color.material_dynamic_neutral20, + context.theme + ), + context.resources.getColor( + com.google.android.material.R.color.material_dynamic_neutral10, + context.theme + ), + context.resources.getColor( + com.google.android.material.R.color.material_dynamic_neutral0, + context.theme + ) + ), + + intArrayOf( + context.resources.getColor( + com.google.android.material.R.color.material_dynamic_neutral_variant100, + context.theme + ), + context.resources.getColor( + com.google.android.material.R.color.material_dynamic_neutral_variant99, + context.theme + ), + context.resources.getColor( + com.google.android.material.R.color.material_dynamic_neutral_variant95, + context.theme + ), + context.resources.getColor( + com.google.android.material.R.color.material_dynamic_neutral_variant90, + context.theme + ), + context.resources.getColor( + com.google.android.material.R.color.material_dynamic_neutral_variant80, + context.theme + ), + context.resources.getColor( + com.google.android.material.R.color.material_dynamic_neutral_variant70, + context.theme + ), + context.resources.getColor( + com.google.android.material.R.color.material_dynamic_neutral_variant60, + context.theme + ), + context.resources.getColor( + com.google.android.material.R.color.material_dynamic_neutral_variant50, + context.theme + ), + context.resources.getColor( + com.google.android.material.R.color.material_dynamic_neutral_variant40, + context.theme + ), + context.resources.getColor( + com.google.android.material.R.color.material_dynamic_neutral_variant30, + context.theme + ), + context.resources.getColor( + com.google.android.material.R.color.material_dynamic_neutral_variant20, + context.theme + ), + context.resources.getColor( + com.google.android.material.R.color.material_dynamic_neutral_variant10, + context.theme + ), + context.resources.getColor( + com.google.android.material.R.color.material_dynamic_neutral_variant0, + context.theme + ) + ) + ) } - public static int calculateTextColor(@ColorInt int color) { - double darkness = 1 - (0.299 * Color.red(color) + - 0.587 * Color.green(color) + - 0.114 * Color.blue(color)) / 255; + fun calculateTextColor(@ColorInt color: Int): Int { + val darkness = + 1 - (0.299 * Color.red(color) + 0.587 * Color.green(color) + 0.114 * Color.blue(color)) / 255 - return darkness < 0.5 ? Color.BLACK : Color.WHITE; + return if (darkness < 0.5) Color.BLACK else Color.WHITE } /** * Convert a color appearance model representation to an ARGB color. - *

+ * + * * Note: the returned color may have a lower chroma than requested. Whether a chroma is * available depends on luminance. For example, there's no such thing as a high chroma light * red, due to the limitations of our eyes and/or physics. If the requested chroma is @@ -350,58 +547,80 @@ public class ColorUtil { * @param chroma chroma in CAM coordinates. * @param lstar perceptual luminance, L* in L*a*b* */ + @JvmStatic @ColorInt - public static int CAMToColor(float hue, float chroma, float lstar) { - return Cam.getInt(hue, chroma, lstar); + fun CAMToColor(hue: Float, chroma: Float, lstar: Float): Int { + return Cam.getInt(hue, chroma, lstar) } - private static final double XYZ_WHITE_REFERENCE_X = 95.047; - private static final double XYZ_WHITE_REFERENCE_Y = 100; - private static final double XYZ_WHITE_REFERENCE_Z = 108.883; + private const val XYZ_WHITE_REFERENCE_X = 95.047 + private const val XYZ_WHITE_REFERENCE_Y = 100.0 + private const val XYZ_WHITE_REFERENCE_Z = 108.883 /** * Converts a color from CIE XYZ to its RGB representation. * - *

This method expects the XYZ representation to use the D65 illuminant and the CIE - * 2° Standard Observer (1931).

+ * + * This method expects the XYZ representation to use the D65 illuminant and the CIE + * 2° Standard Observer (1931). * * @param x X component value [0...95.047) * @param y Y component value [0...100) * @param z Z component value [0...108.883) * @return int containing the RGB representation */ + @JvmStatic @ColorInt - public static int XYZToColor(@FloatRange(from = 0f, to = XYZ_WHITE_REFERENCE_X) double x, - @FloatRange(from = 0f, to = XYZ_WHITE_REFERENCE_Y) double y, - @FloatRange(from = 0f, to = XYZ_WHITE_REFERENCE_Z) double z) { - double r = (x * 3.2406 + y * -1.5372 + z * -0.4986) / 100; - double g = (x * -0.9689 + y * 1.8758 + z * 0.0415) / 100; - double b = (x * 0.0557 + y * -0.2040 + z * 1.0570) / 100; - - r = r > 0.0031308 ? 1.055 * Math.pow(r, 1 / 2.4) - 0.055 : 12.92 * r; - g = g > 0.0031308 ? 1.055 * Math.pow(g, 1 / 2.4) - 0.055 : 12.92 * g; - b = b > 0.0031308 ? 1.055 * Math.pow(b, 1 / 2.4) - 0.055 : 12.92 * b; + fun XYZToColor( + @FloatRange(from = 0.0, to = XYZ_WHITE_REFERENCE_X) x: Double, + @FloatRange(from = 0.0, to = XYZ_WHITE_REFERENCE_Y) y: Double, + @FloatRange(from = 0.0, to = XYZ_WHITE_REFERENCE_Z) z: Double + ): Int { + var r = (x * 3.2406 + y * -1.5372 + z * -0.4986) / 100 + var g = (x * -0.9689 + y * 1.8758 + z * 0.0415) / 100 + var b = (x * 0.0557 + y * -0.2040 + z * 1.0570) / 100 + + r = if (r > 0.0031308) 1.055 * r.pow(1 / 2.4) - 0.055 else 12.92 * r + g = if (g > 0.0031308) 1.055 * g.pow(1 / 2.4) - 0.055 else 12.92 * g + b = if (b > 0.0031308) 1.055 * b.pow(1 / 2.4) - 0.055 else 12.92 * b return Color.rgb( - constrain((int) Math.round(r * 255), 0, 255), - constrain((int) Math.round(g * 255), 0, 255), - constrain((int) Math.round(b * 255), 0, 255)); + constrain(Math.round(r * 255).toInt(), 0, 255), + constrain(Math.round(g * 255).toInt(), 0, 255), + constrain(Math.round(b * 255).toInt(), 0, 255) + ) } - private static float constrain(float amount, float low, float high) { - return amount < low ? low : Math.min(amount, high); + private fun constrain(amount: Float, low: Float, high: Float): Float { + return if (amount < low) low else min(amount.toDouble(), high.toDouble()).toFloat() } - @SuppressWarnings("SameParameterValue") - private static int constrain(int amount, int low, int high) { - return amount < low ? low : Math.min(amount, high); + @Suppress("SameParameterValue") + private fun constrain(amount: Int, low: Int, high: Int): Int { + return if (amount < low) low else min(amount.toDouble(), high.toDouble()).toInt() } - public static ArrayList getMonetAccentColors() { - ArrayList colors = new ArrayList<>(); - colors.add(ContextCompat.getColor(ColorBlendr.getAppContext(), android.R.color.system_accent1_400)); - colors.add(ContextCompat.getColor(ColorBlendr.getAppContext(), android.R.color.system_accent2_400)); - colors.add(ContextCompat.getColor(ColorBlendr.getAppContext(), android.R.color.system_accent3_400)); - return colors; - } + val monetAccentColors: ArrayList + get() { + val colors = ArrayList() + colors.add( + ContextCompat.getColor( + appContext, + android.R.color.system_accent1_400 + ) + ) + colors.add( + ContextCompat.getColor( + appContext, + android.R.color.system_accent2_400 + ) + ) + colors.add( + ContextCompat.getColor( + appContext, + android.R.color.system_accent3_400 + ) + ) + return colors + } } diff --git a/app/src/main/java/com/drdisagree/colorblendr/utils/DynamicColors.kt b/app/src/main/java/com/drdisagree/colorblendr/utils/DynamicColors.kt index 1c87388..6ff6bd0 100644 --- a/app/src/main/java/com/drdisagree/colorblendr/utils/DynamicColors.kt +++ b/app/src/main/java/com/drdisagree/colorblendr/utils/DynamicColors.kt @@ -1,17 +1,12 @@ -package com.drdisagree.colorblendr.utils; +package com.drdisagree.colorblendr.utils -import android.os.Build; +import android.os.Build +import androidx.core.util.Pair -import androidx.core.util.Pair; - -import java.util.ArrayList; -import java.util.List; - -public class DynamicColors { - - public static final List> ALL_DYNAMIC_COLORS_MAPPED = new ArrayList<>(); - public static final List>> FIXED_COLORS_MAPPED = new ArrayList<>(); - public static final List>>> M3_REF_PALETTE = new ArrayList<>(); +object DynamicColors { + val ALL_DYNAMIC_COLORS_MAPPED: MutableList> = ArrayList() + val FIXED_COLORS_MAPPED: MutableList>> = ArrayList() + val M3_REF_PALETTE: MutableList>>> = ArrayList() /* * This is a list of all the dynamic and fixed colors that are available in the system. @@ -49,87 +44,333 @@ public class DynamicColors { * 4 = neutral variant * -> Fourth item is the color index. */ - static { - ALL_DYNAMIC_COLORS_MAPPED.add(Pair.create("primary_container", Pair.create(0, Pair.create(3, 9)))); - ALL_DYNAMIC_COLORS_MAPPED.add(Pair.create("on_primary_container", Pair.create(0, Pair.create(11, 3)))); - ALL_DYNAMIC_COLORS_MAPPED.add(Pair.create("primary", Pair.create(0, Pair.create(8, 4)))); - ALL_DYNAMIC_COLORS_MAPPED.add(Pair.create("on_primary", Pair.create(0, Pair.create(0, 10)))); - ALL_DYNAMIC_COLORS_MAPPED.add(Pair.create("secondary_container", Pair.create(1, Pair.create(3, 9)))); - ALL_DYNAMIC_COLORS_MAPPED.add(Pair.create("on_secondary_container", Pair.create(1, Pair.create(11, 3)))); - ALL_DYNAMIC_COLORS_MAPPED.add(Pair.create("secondary", Pair.create(1, Pair.create(8, 4)))); - ALL_DYNAMIC_COLORS_MAPPED.add(Pair.create("on_secondary", Pair.create(1, Pair.create(0, 10)))); - ALL_DYNAMIC_COLORS_MAPPED.add(Pair.create("tertiary_container", Pair.create(2, Pair.create(3, 9)))); - ALL_DYNAMIC_COLORS_MAPPED.add(Pair.create("on_tertiary_container", Pair.create(2, Pair.create(11, 3)))); - ALL_DYNAMIC_COLORS_MAPPED.add(Pair.create("tertiary", Pair.create(2, Pair.create(8, 4)))); - ALL_DYNAMIC_COLORS_MAPPED.add(Pair.create("on_tertiary", Pair.create(2, Pair.create(0, 10)))); - ALL_DYNAMIC_COLORS_MAPPED.add(Pair.create("background", Pair.create(3, Pair.create(1, 11)))); - ALL_DYNAMIC_COLORS_MAPPED.add(Pair.create("on_background", Pair.create(3, Pair.create(11, 1)))); - ALL_DYNAMIC_COLORS_MAPPED.add(Pair.create("surface", Pair.create(3, Pair.create(1, 11)))); - ALL_DYNAMIC_COLORS_MAPPED.add(Pair.create("on_surface", Pair.create(3, Pair.create(10, 2)))); - ALL_DYNAMIC_COLORS_MAPPED.add(Pair.create("surface_container_low", Pair.create(3, Pair.create(2, 10)))); - ALL_DYNAMIC_COLORS_MAPPED.add(Pair.create("surface_container_lowest", Pair.create(3, Pair.create(1, 11)))); - ALL_DYNAMIC_COLORS_MAPPED.add(Pair.create("surface_container", Pair.create(3, Pair.create(2, 10)))); - ALL_DYNAMIC_COLORS_MAPPED.add(Pair.create("surface_container_high", Pair.create(3, Pair.create(Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE ? 1 : 2, 10)))); - ALL_DYNAMIC_COLORS_MAPPED.add(Pair.create("surface_container_highest", Pair.create(3, Pair.create(3, 9)))); - ALL_DYNAMIC_COLORS_MAPPED.add(Pair.create("surface_bright", Pair.create(3, Pair.create(1, 10)))); - ALL_DYNAMIC_COLORS_MAPPED.add(Pair.create("surface_dim", Pair.create(3, Pair.create(2, 11)))); - ALL_DYNAMIC_COLORS_MAPPED.add(Pair.create("surface_variant", Pair.create(4, Pair.create(2, 10)))); - ALL_DYNAMIC_COLORS_MAPPED.add(Pair.create("on_surface_variant", Pair.create(4, Pair.create(10, 2)))); - ALL_DYNAMIC_COLORS_MAPPED.add(Pair.create("outline", Pair.create(4, Pair.create(7, 6)))); - ALL_DYNAMIC_COLORS_MAPPED.add(Pair.create("outline_variant", Pair.create(4, Pair.create(4, 9)))); -// ALL_DYNAMIC_COLORS_MAPPED.add(Pair.create("error", Pair.create("#1EB326", "#B5F2B8"))); + init { + ALL_DYNAMIC_COLORS_MAPPED.add( + Pair.create( + "primary_container", + Pair.create(0, Pair.create(3, 9)) + ) + ) + ALL_DYNAMIC_COLORS_MAPPED.add( + Pair.create( + "on_primary_container", + Pair.create(0, Pair.create(11, 3)) + ) + ) + ALL_DYNAMIC_COLORS_MAPPED.add(Pair.create("primary", Pair.create(0, Pair.create(8, 4)))) + ALL_DYNAMIC_COLORS_MAPPED.add(Pair.create("on_primary", Pair.create(0, Pair.create(0, 10)))) + ALL_DYNAMIC_COLORS_MAPPED.add( + Pair.create( + "secondary_container", + Pair.create(1, Pair.create(3, 9)) + ) + ) + ALL_DYNAMIC_COLORS_MAPPED.add( + Pair.create( + "on_secondary_container", + Pair.create(1, Pair.create(11, 3)) + ) + ) + ALL_DYNAMIC_COLORS_MAPPED.add(Pair.create("secondary", Pair.create(1, Pair.create(8, 4)))) + ALL_DYNAMIC_COLORS_MAPPED.add( + Pair.create( + "on_secondary", + Pair.create(1, Pair.create(0, 10)) + ) + ) + ALL_DYNAMIC_COLORS_MAPPED.add( + Pair.create( + "tertiary_container", + Pair.create(2, Pair.create(3, 9)) + ) + ) + ALL_DYNAMIC_COLORS_MAPPED.add( + Pair.create( + "on_tertiary_container", + Pair.create(2, Pair.create(11, 3)) + ) + ) + ALL_DYNAMIC_COLORS_MAPPED.add(Pair.create("tertiary", Pair.create(2, Pair.create(8, 4)))) + ALL_DYNAMIC_COLORS_MAPPED.add( + Pair.create( + "on_tertiary", + Pair.create(2, Pair.create(0, 10)) + ) + ) + ALL_DYNAMIC_COLORS_MAPPED.add(Pair.create("background", Pair.create(3, Pair.create(1, 11)))) + ALL_DYNAMIC_COLORS_MAPPED.add( + Pair.create( + "on_background", + Pair.create(3, Pair.create(11, 1)) + ) + ) + ALL_DYNAMIC_COLORS_MAPPED.add(Pair.create("surface", Pair.create(3, Pair.create(1, 11)))) + ALL_DYNAMIC_COLORS_MAPPED.add(Pair.create("on_surface", Pair.create(3, Pair.create(10, 2)))) + ALL_DYNAMIC_COLORS_MAPPED.add( + Pair.create( + "surface_container_low", + Pair.create(3, Pair.create(2, 10)) + ) + ) + ALL_DYNAMIC_COLORS_MAPPED.add( + Pair.create( + "surface_container_lowest", + Pair.create(3, Pair.create(1, 11)) + ) + ) + ALL_DYNAMIC_COLORS_MAPPED.add( + Pair.create( + "surface_container", + Pair.create(3, Pair.create(2, 10)) + ) + ) + ALL_DYNAMIC_COLORS_MAPPED.add( + Pair.create( + "surface_container_high", + Pair.create( + 3, + Pair.create( + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) 1 else 2, + 10 + ) + ) + ) + ) + ALL_DYNAMIC_COLORS_MAPPED.add( + Pair.create( + "surface_container_highest", + Pair.create(3, Pair.create(3, 9)) + ) + ) + ALL_DYNAMIC_COLORS_MAPPED.add( + Pair.create( + "surface_bright", + Pair.create(3, Pair.create(1, 10)) + ) + ) + ALL_DYNAMIC_COLORS_MAPPED.add( + Pair.create( + "surface_dim", + Pair.create(3, Pair.create(2, 11)) + ) + ) + ALL_DYNAMIC_COLORS_MAPPED.add( + Pair.create( + "surface_variant", + Pair.create(4, Pair.create(2, 10)) + ) + ) + ALL_DYNAMIC_COLORS_MAPPED.add( + Pair.create( + "on_surface_variant", + Pair.create(4, Pair.create(10, 2)) + ) + ) + ALL_DYNAMIC_COLORS_MAPPED.add(Pair.create("outline", Pair.create(4, Pair.create(7, 6)))) + ALL_DYNAMIC_COLORS_MAPPED.add( + Pair.create( + "outline_variant", + Pair.create(4, Pair.create(4, 9)) + ) + ) + // ALL_DYNAMIC_COLORS_MAPPED.add(Pair.create("error", Pair.create("#1EB326", "#B5F2B8"))); // ALL_DYNAMIC_COLORS_MAPPED.add(Pair.create("on_error", Pair.create("#FFFFFF", "#106014"))); // ALL_DYNAMIC_COLORS_MAPPED.add(Pair.create("error_container", Pair.create("#DCF9DE", "#188C1D"))); // ALL_DYNAMIC_COLORS_MAPPED.add(Pair.create("on_error_container", Pair.create("#0B410E", "#DCF9DE"))); - ALL_DYNAMIC_COLORS_MAPPED.add(Pair.create("control_activated", Pair.create(1, Pair.create(8, 4)))); -// ALL_DYNAMIC_COLORS_MAPPED.add(Pair.create("control_normal", )); - ALL_DYNAMIC_COLORS_MAPPED.add(Pair.create("control_highlight", Pair.create("#1F000000", "#33FFFFFF"))); -// ALL_DYNAMIC_COLORS_MAPPED.add(Pair.create("text_primary_inverse", )); + ALL_DYNAMIC_COLORS_MAPPED.add( + Pair.create( + "control_activated", + Pair.create(1, Pair.create(8, 4)) + ) + ) + // ALL_DYNAMIC_COLORS_MAPPED.add(Pair.create("control_normal", )); + ALL_DYNAMIC_COLORS_MAPPED.add( + Pair.create( + "control_highlight", + Pair.create("#1F000000", "#33FFFFFF") + ) + ) + // ALL_DYNAMIC_COLORS_MAPPED.add(Pair.create("text_primary_inverse", )); // ALL_DYNAMIC_COLORS_MAPPED.add(Pair.create("text_secondary_and_tertiary_inverse", )); // ALL_DYNAMIC_COLORS_MAPPED.add(Pair.create("text_primary_inverse_disable_only", )); // ALL_DYNAMIC_COLORS_MAPPED.add(Pair.create("text_secondary_and_tertiary_inverse_disabled", )); // ALL_DYNAMIC_COLORS_MAPPED.add(Pair.create("text_hint_inverse", )); - ALL_DYNAMIC_COLORS_MAPPED.add(Pair.create("palette_key_color_primary", Pair.create(0, Pair.create(4, 8)))); - ALL_DYNAMIC_COLORS_MAPPED.add(Pair.create("palette_key_color_secondary", Pair.create(1, Pair.create(4, 8)))); - ALL_DYNAMIC_COLORS_MAPPED.add(Pair.create("palette_key_color_tertiary", Pair.create(2, Pair.create(4, 8)))); - ALL_DYNAMIC_COLORS_MAPPED.add(Pair.create("palette_key_color_neutral", Pair.create(3, Pair.create(4, 8)))); - ALL_DYNAMIC_COLORS_MAPPED.add(Pair.create("palette_key_color_neutral_variant", Pair.create(4, Pair.create(4, 8)))); + ALL_DYNAMIC_COLORS_MAPPED.add( + Pair.create( + "palette_key_color_primary", + Pair.create(0, Pair.create(4, 8)) + ) + ) + ALL_DYNAMIC_COLORS_MAPPED.add( + Pair.create( + "palette_key_color_secondary", + Pair.create(1, Pair.create(4, 8)) + ) + ) + ALL_DYNAMIC_COLORS_MAPPED.add( + Pair.create( + "palette_key_color_tertiary", + Pair.create(2, Pair.create(4, 8)) + ) + ) + ALL_DYNAMIC_COLORS_MAPPED.add( + Pair.create( + "palette_key_color_neutral", + Pair.create(3, Pair.create(4, 8)) + ) + ) + ALL_DYNAMIC_COLORS_MAPPED.add( + Pair.create( + "palette_key_color_neutral_variant", + Pair.create(4, Pair.create(4, 8)) + ) + ) - FIXED_COLORS_MAPPED.add(Pair.create("primary_fixed", Pair.create(0, 3))); - FIXED_COLORS_MAPPED.add(Pair.create("primary_fixed_dim", Pair.create(0, 4))); - FIXED_COLORS_MAPPED.add(Pair.create("on_primary_fixed", Pair.create(0, 11))); - FIXED_COLORS_MAPPED.add(Pair.create("on_primary_fixed_variant", Pair.create(0, 9))); - FIXED_COLORS_MAPPED.add(Pair.create("secondary_fixed", Pair.create(1, 3))); - FIXED_COLORS_MAPPED.add(Pair.create("secondary_fixed_dim", Pair.create(1, 4))); - FIXED_COLORS_MAPPED.add(Pair.create("on_secondary_fixed", Pair.create(1, 11))); - FIXED_COLORS_MAPPED.add(Pair.create("on_secondary_fixed_variant", Pair.create(1, 9))); - FIXED_COLORS_MAPPED.add(Pair.create("tertiary_fixed", Pair.create(2, 4))); - FIXED_COLORS_MAPPED.add(Pair.create("tertiary_fixed_dim", Pair.create(2, 4))); - FIXED_COLORS_MAPPED.add(Pair.create("on_tertiary_fixed", Pair.create(2, 11))); - FIXED_COLORS_MAPPED.add(Pair.create("on_tertiary_fixed_variant", Pair.create(2, 9))); + FIXED_COLORS_MAPPED.add(Pair.create("primary_fixed", Pair.create(0, 3))) + FIXED_COLORS_MAPPED.add(Pair.create("primary_fixed_dim", Pair.create(0, 4))) + FIXED_COLORS_MAPPED.add(Pair.create("on_primary_fixed", Pair.create(0, 11))) + FIXED_COLORS_MAPPED.add(Pair.create("on_primary_fixed_variant", Pair.create(0, 9))) + FIXED_COLORS_MAPPED.add(Pair.create("secondary_fixed", Pair.create(1, 3))) + FIXED_COLORS_MAPPED.add(Pair.create("secondary_fixed_dim", Pair.create(1, 4))) + FIXED_COLORS_MAPPED.add(Pair.create("on_secondary_fixed", Pair.create(1, 11))) + FIXED_COLORS_MAPPED.add(Pair.create("on_secondary_fixed_variant", Pair.create(1, 9))) + FIXED_COLORS_MAPPED.add(Pair.create("tertiary_fixed", Pair.create(2, 4))) + FIXED_COLORS_MAPPED.add(Pair.create("tertiary_fixed_dim", Pair.create(2, 4))) + FIXED_COLORS_MAPPED.add(Pair.create("on_tertiary_fixed", Pair.create(2, 11))) + FIXED_COLORS_MAPPED.add(Pair.create("on_tertiary_fixed_variant", Pair.create(2, 9))) // Google uses "gm3" prefix for these resources, MaterialComponents use "m3" instead. - M3_REF_PALETTE.add(Pair.create("m3_ref_palette_dynamic_neutral4", Pair.create(-60, Pair.create(3, 11)))); - M3_REF_PALETTE.add(Pair.create("m3_ref_palette_dynamic_neutral6", Pair.create(-40, Pair.create(3, 11)))); - M3_REF_PALETTE.add(Pair.create("m3_ref_palette_dynamic_neutral12", Pair.create(20, Pair.create(3, 10)))); - M3_REF_PALETTE.add(Pair.create("m3_ref_palette_dynamic_neutral17", Pair.create(70, Pair.create(3, 10)))); - M3_REF_PALETTE.add(Pair.create("m3_ref_palette_dynamic_neutral22", Pair.create(20, Pair.create(3, 10)))); - M3_REF_PALETTE.add(Pair.create("m3_ref_palette_dynamic_neutral24", Pair.create(40, Pair.create(3, 10)))); - M3_REF_PALETTE.add(Pair.create("m3_ref_palette_dynamic_neutral87", Pair.create(70, Pair.create(3, 4)))); - M3_REF_PALETTE.add(Pair.create("m3_ref_palette_dynamic_neutral92", Pair.create(20, Pair.create(3, 3)))); - M3_REF_PALETTE.add(Pair.create("m3_ref_palette_dynamic_neutral94", Pair.create(40, Pair.create(3, 3)))); - M3_REF_PALETTE.add(Pair.create("m3_ref_palette_dynamic_neutral96", Pair.create(10, Pair.create(3, 2)))); - M3_REF_PALETTE.add(Pair.create("m3_ref_palette_dynamic_neutral98", Pair.create(30, Pair.create(3, 2)))); - M3_REF_PALETTE.add(Pair.create("m3_ref_palette_dynamic_neutral_variant4", Pair.create(-60, Pair.create(4, 11)))); - M3_REF_PALETTE.add(Pair.create("m3_ref_palette_dynamic_neutral_variant6", Pair.create(-40, Pair.create(4, 11)))); - M3_REF_PALETTE.add(Pair.create("m3_ref_palette_dynamic_neutral_variant12", Pair.create(20, Pair.create(4, 10)))); - M3_REF_PALETTE.add(Pair.create("m3_ref_palette_dynamic_neutral_variant17", Pair.create(70, Pair.create(4, 10)))); - M3_REF_PALETTE.add(Pair.create("m3_ref_palette_dynamic_neutral_variant22", Pair.create(20, Pair.create(4, 10)))); - M3_REF_PALETTE.add(Pair.create("m3_ref_palette_dynamic_neutral_variant24", Pair.create(40, Pair.create(4, 10)))); - M3_REF_PALETTE.add(Pair.create("m3_ref_palette_dynamic_neutral_variant87", Pair.create(70, Pair.create(4, 4)))); - M3_REF_PALETTE.add(Pair.create("m3_ref_palette_dynamic_neutral_variant92", Pair.create(20, Pair.create(4, 3)))); - M3_REF_PALETTE.add(Pair.create("m3_ref_palette_dynamic_neutral_variant94", Pair.create(40, Pair.create(4, 3)))); - M3_REF_PALETTE.add(Pair.create("m3_ref_palette_dynamic_neutral_variant96", Pair.create(10, Pair.create(4, 2)))); - M3_REF_PALETTE.add(Pair.create("m3_ref_palette_dynamic_neutral_variant98", Pair.create(30, Pair.create(4, 2)))); + M3_REF_PALETTE.add( + Pair.create( + "m3_ref_palette_dynamic_neutral4", + Pair.create(-60, Pair.create(3, 11)) + ) + ) + M3_REF_PALETTE.add( + Pair.create( + "m3_ref_palette_dynamic_neutral6", + Pair.create(-40, Pair.create(3, 11)) + ) + ) + M3_REF_PALETTE.add( + Pair.create( + "m3_ref_palette_dynamic_neutral12", + Pair.create(20, Pair.create(3, 10)) + ) + ) + M3_REF_PALETTE.add( + Pair.create( + "m3_ref_palette_dynamic_neutral17", + Pair.create(70, Pair.create(3, 10)) + ) + ) + M3_REF_PALETTE.add( + Pair.create( + "m3_ref_palette_dynamic_neutral22", + Pair.create(20, Pair.create(3, 10)) + ) + ) + M3_REF_PALETTE.add( + Pair.create( + "m3_ref_palette_dynamic_neutral24", + Pair.create(40, Pair.create(3, 10)) + ) + ) + M3_REF_PALETTE.add( + Pair.create( + "m3_ref_palette_dynamic_neutral87", + Pair.create(70, Pair.create(3, 4)) + ) + ) + M3_REF_PALETTE.add( + Pair.create( + "m3_ref_palette_dynamic_neutral92", + Pair.create(20, Pair.create(3, 3)) + ) + ) + M3_REF_PALETTE.add( + Pair.create( + "m3_ref_palette_dynamic_neutral94", + Pair.create(40, Pair.create(3, 3)) + ) + ) + M3_REF_PALETTE.add( + Pair.create( + "m3_ref_palette_dynamic_neutral96", + Pair.create(10, Pair.create(3, 2)) + ) + ) + M3_REF_PALETTE.add( + Pair.create( + "m3_ref_palette_dynamic_neutral98", + Pair.create(30, Pair.create(3, 2)) + ) + ) + M3_REF_PALETTE.add( + Pair.create( + "m3_ref_palette_dynamic_neutral_variant4", + Pair.create(-60, Pair.create(4, 11)) + ) + ) + M3_REF_PALETTE.add( + Pair.create( + "m3_ref_palette_dynamic_neutral_variant6", + Pair.create(-40, Pair.create(4, 11)) + ) + ) + M3_REF_PALETTE.add( + Pair.create( + "m3_ref_palette_dynamic_neutral_variant12", + Pair.create(20, Pair.create(4, 10)) + ) + ) + M3_REF_PALETTE.add( + Pair.create( + "m3_ref_palette_dynamic_neutral_variant17", + Pair.create(70, Pair.create(4, 10)) + ) + ) + M3_REF_PALETTE.add( + Pair.create( + "m3_ref_palette_dynamic_neutral_variant22", + Pair.create(20, Pair.create(4, 10)) + ) + ) + M3_REF_PALETTE.add( + Pair.create( + "m3_ref_palette_dynamic_neutral_variant24", + Pair.create(40, Pair.create(4, 10)) + ) + ) + M3_REF_PALETTE.add( + Pair.create( + "m3_ref_palette_dynamic_neutral_variant87", + Pair.create(70, Pair.create(4, 4)) + ) + ) + M3_REF_PALETTE.add( + Pair.create( + "m3_ref_palette_dynamic_neutral_variant92", + Pair.create(20, Pair.create(4, 3)) + ) + ) + M3_REF_PALETTE.add( + Pair.create( + "m3_ref_palette_dynamic_neutral_variant94", + Pair.create(40, Pair.create(4, 3)) + ) + ) + M3_REF_PALETTE.add( + Pair.create( + "m3_ref_palette_dynamic_neutral_variant96", + Pair.create(10, Pair.create(4, 2)) + ) + ) + M3_REF_PALETTE.add( + Pair.create( + "m3_ref_palette_dynamic_neutral_variant98", + Pair.create(30, Pair.create(4, 2)) + ) + ) } } diff --git a/app/src/main/java/com/drdisagree/colorblendr/utils/FabricatedUtil.kt b/app/src/main/java/com/drdisagree/colorblendr/utils/FabricatedUtil.kt index f3378b4..914de9a 100644 --- a/app/src/main/java/com/drdisagree/colorblendr/utils/FabricatedUtil.kt +++ b/app/src/main/java/com/drdisagree/colorblendr/utils/FabricatedUtil.kt @@ -1,280 +1,304 @@ -package com.drdisagree.colorblendr.utils; - -import static com.drdisagree.colorblendr.common.Const.FABRICATED_OVERLAY_NAME_APPS; -import static com.drdisagree.colorblendr.common.Const.MONET_BACKGROUND_LIGHTNESS; -import static com.drdisagree.colorblendr.common.Const.MONET_PITCH_BLACK_THEME; -import static com.drdisagree.colorblendr.common.Const.TINT_TEXT_COLOR; - -import android.content.Context; -import android.content.pm.ApplicationInfo; -import android.content.pm.PackageManager; -import android.graphics.Color; - -import androidx.annotation.ColorInt; -import androidx.core.util.Pair; - -import com.drdisagree.colorblendr.common.Const; -import com.drdisagree.colorblendr.config.RPrefs; -import com.drdisagree.colorblendr.utils.fabricated.FabricatedOverlayResource; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; - -public class FabricatedUtil { - - private static final String[][] colorNames = ColorUtil.getColorNames(); - private static final String[][] colorNamesM3var1 = ColorUtil.getColorNamesM3(false, false); - private static final String[][] colorNamesM3var2 = ColorUtil.getColorNamesM3(true, false); - private static final String[][] colorNamesM3var3 = ColorUtil.getColorNamesM3(true, true); - private static final String[][] colorNamesM3var4 = ColorUtil.getColorNamesM3(false, true); - - public static void createDynamicOverlay( - FabricatedOverlayResource overlay, - ArrayList> paletteLight, - ArrayList> paletteDark +package com.drdisagree.colorblendr.utils + +import android.content.Context +import android.content.pm.PackageManager +import android.graphics.Color +import androidx.annotation.ColorInt +import androidx.core.util.Pair +import com.drdisagree.colorblendr.common.Const +import com.drdisagree.colorblendr.config.RPrefs +import com.drdisagree.colorblendr.utils.fabricated.FabricatedOverlayResource +import java.util.function.Consumer + +object FabricatedUtil { + private val colorNames: Array> = ColorUtil.colorNames + private val colorNamesM3var1: Array> = ColorUtil.getColorNamesM3( + isDynamic = false, + prefixG = false + ) + private val colorNamesM3var2: Array> = ColorUtil.getColorNamesM3( + isDynamic = true, + prefixG = false + ) + private val colorNamesM3var3: Array> = ColorUtil.getColorNamesM3( + isDynamic = true, + prefixG = true + ) + private val colorNamesM3var4: Array> = ColorUtil.getColorNamesM3( + isDynamic = false, + prefixG = true + ) + + fun createDynamicOverlay( + overlay: FabricatedOverlayResource, + paletteLight: ArrayList>, + paletteDark: ArrayList> ) { - assignDynamicPaletteToOverlay(overlay, true /* isDark */, paletteDark); - assignDynamicPaletteToOverlay(overlay, false /* isDark */, paletteLight); - assignFixedColorsToOverlay(overlay, paletteLight); + assignDynamicPaletteToOverlay(overlay, true, /* isDark */paletteDark) + assignDynamicPaletteToOverlay(overlay, false, /* isDark */paletteLight) + assignFixedColorsToOverlay(overlay, paletteLight) } - @SuppressWarnings("unchecked") - private static void assignDynamicPaletteToOverlay(FabricatedOverlayResource overlay, boolean isDark, ArrayList> palette) { - String suffix = isDark ? "dark" : "light"; - boolean pitchBlackTheme = RPrefs.getBoolean(MONET_PITCH_BLACK_THEME, false); - - DynamicColors.ALL_DYNAMIC_COLORS_MAPPED.forEach(pair -> { - String resourceName = "system_" + pair.first + "_" + suffix; - int colorValue; - - Pair valPair = (Pair) pair.second; - if (valPair.first instanceof String) { - colorValue = Color.parseColor((String) (isDark ? - valPair.second : - valPair.first - )); + @Suppress("UNCHECKED_CAST") + private fun assignDynamicPaletteToOverlay( + overlay: FabricatedOverlayResource, + isDark: Boolean, + palette: ArrayList> + ) { + val suffix = if (isDark) "dark" else "light" + val pitchBlackTheme = RPrefs.getBoolean(Const.MONET_PITCH_BLACK_THEME, false) + + DynamicColors.ALL_DYNAMIC_COLORS_MAPPED.forEach(Consumer { pair: Pair -> + val resourceName = "system_" + pair.first + "_" + suffix + var colorValue: Int + + val valPair = pair.second as Pair? + if (valPair!!.first is String) { + colorValue = Color.parseColor( + (if (isDark) valPair.second else valPair.first + ) as String + ) } else { - Pair colorIndexPair = (Pair) valPair.second; - colorValue = palette.get((Integer) valPair.first).get( - isDark ? - colorIndexPair.second : - colorIndexPair.first - ); + val colorIndexPair = valPair.second as Pair + colorValue = + palette[(valPair.first as Int)][if (isDark) colorIndexPair.second else colorIndexPair.first] colorValue = replaceColorForPitchBlackTheme( - pitchBlackTheme, - resourceName, - colorValue, - isDark ? - colorIndexPair.second : - colorIndexPair.first - ); + pitchBlackTheme, + resourceName, + colorValue, + if (isDark) colorIndexPair.second else colorIndexPair.first + ) } - - overlay.setColor(resourceName, colorValue); - }); + overlay.setColor(resourceName, colorValue) + }) } - private static void assignFixedColorsToOverlay(FabricatedOverlayResource overlay, ArrayList> paletteLight) { - DynamicColors.FIXED_COLORS_MAPPED.forEach(pair -> { - String resourceName = "system_" + pair.first; - int colorValue = paletteLight.get(pair.second.first).get(pair.second.second); - overlay.setColor(resourceName, colorValue); - }); + private fun assignFixedColorsToOverlay( + overlay: FabricatedOverlayResource, + paletteLight: ArrayList> + ) { + DynamicColors.FIXED_COLORS_MAPPED.forEach(Consumer { pair: Pair> -> + val resourceName = "system_" + pair.first + val colorValue = paletteLight[pair.second!!.first!!][pair.second!!.second!!] + overlay.setColor(resourceName, colorValue) + }) } - public static void assignPerAppColorsToOverlay(FabricatedOverlayResource overlay, ArrayList> palette) { - boolean pitchBlackTheme = RPrefs.getBoolean(MONET_PITCH_BLACK_THEME, false); + fun assignPerAppColorsToOverlay( + overlay: FabricatedOverlayResource, + palette: ArrayList> + ) { + val pitchBlackTheme = RPrefs.getBoolean(Const.MONET_PITCH_BLACK_THEME, false) // Format of pair: >> - DynamicColors.M3_REF_PALETTE.forEach(pair -> { - String resourceName = pair.first; - - Pair> valPair = pair.second; + DynamicColors.M3_REF_PALETTE.forEach(Consumer { pair: Pair>> -> + val resourceName = pair.first + val valPair = pair.second // TODO: Use lightness value to modify the color // int lightnessToChange = valPair.first + 100; - - Pair colorIndexPair = valPair.second; - int baseColor = palette.get(colorIndexPair.first).get(colorIndexPair.second); - baseColor = replaceColorForPitchBlackTheme(pitchBlackTheme, resourceName, baseColor, colorIndexPair.second); - - overlay.setColor(resourceName, baseColor); - overlay.setColor("g" + resourceName, baseColor); - }); - - for (int i = 0; i < 5; i++) { - for (int j = 0; j < 13; j++) { - overlay.setColor(colorNamesM3var1[i][j], palette.get(i).get(j)); - overlay.setColor(colorNamesM3var2[i][j], palette.get(i).get(j)); - overlay.setColor(colorNamesM3var3[i][j], palette.get(i).get(j)); - overlay.setColor(colorNamesM3var4[i][j], palette.get(i).get(j)); + val colorIndexPair = valPair!!.second + var baseColor = palette[colorIndexPair!!.first!!][colorIndexPair.second] + baseColor = replaceColorForPitchBlackTheme( + pitchBlackTheme, + resourceName, + baseColor, + colorIndexPair.second + ) + + overlay.setColor(resourceName, baseColor) + overlay.setColor("g$resourceName", baseColor) + }) + + for (i in 0..4) { + for (j in 0..12) { + overlay.setColor(colorNamesM3var1[i][j], palette[i][j]) + overlay.setColor(colorNamesM3var2[i][j], palette[i][j]) + overlay.setColor(colorNamesM3var3[i][j], palette[i][j]) + overlay.setColor(colorNamesM3var4[i][j], palette[i][j]) } } - replaceColorsPerPackageName(overlay, palette, pitchBlackTheme); + replaceColorsPerPackageName(overlay, palette, pitchBlackTheme) - if (!RPrefs.getBoolean(TINT_TEXT_COLOR, true)) { - addTintlessTextColors(overlay); + if (!RPrefs.getBoolean(Const.TINT_TEXT_COLOR, true)) { + addTintlessTextColors(overlay) } } - public static void getAndSaveSelectedFabricatedApps(Context context) { - PackageManager packageManager = context.getPackageManager(); - List applications = packageManager.getInstalledApplications(PackageManager.GET_META_DATA); - HashMap selectedApps = new HashMap<>(); -// selectedApps.put(BuildConfig.APPLICATION_ID, true); + fun getAndSaveSelectedFabricatedApps(context: Context) { + val packageManager = context.packageManager + val applications = packageManager.getInstalledApplications(PackageManager.GET_META_DATA) + val selectedApps = HashMap() - for (ApplicationInfo appInfo : applications) { - String packageName = appInfo.packageName; - boolean isSelected = OverlayManager.isOverlayEnabled( - String.format(FABRICATED_OVERLAY_NAME_APPS, packageName) - ); + // selectedApps.put(BuildConfig.APPLICATION_ID, true); + for (appInfo in applications) { + val packageName = appInfo.packageName + val isSelected = OverlayManager.isOverlayEnabled( + String.format(Const.FABRICATED_OVERLAY_NAME_APPS, packageName) + ) if (isSelected) { - selectedApps.put(packageName, true); + selectedApps[packageName] = true } } - Const.saveSelectedFabricatedApps(selectedApps); + Const.saveSelectedFabricatedApps(selectedApps) } - public static @ColorInt int replaceColorForPitchBlackTheme(boolean pitchBlackTheme, String resourceName, int colorValue, int colorIndex) { + @ColorInt + fun replaceColorForPitchBlackTheme( + pitchBlackTheme: Boolean, + resourceName: String?, + colorValue: Int, + colorIndex: Int + ): Int { if (pitchBlackTheme) { - int lightness = RPrefs.getInt(MONET_BACKGROUND_LIGHTNESS, 100); - return switch (resourceName) { - case "m3_ref_palette_dynamic_neutral_variant6", - "gm3_ref_palette_dynamic_neutral_variant6", - "system_background_dark", - "system_surface_dark" -> Color.BLACK; - case "m3_ref_palette_dynamic_neutral_variant12", - "gm3_ref_palette_dynamic_neutral_variant12" -> - ColorUtil.modifyLightness(colorValue, lightness - 40, colorIndex); - case "m3_ref_palette_dynamic_neutral_variant17", - "gm3_ref_palette_dynamic_neutral_variant17", - "gm3_system_bar_color_night" -> - ColorUtil.modifyLightness(colorValue, lightness - 60, colorIndex); - case "system_surface_container_dark" -> - ColorUtil.modifyLightness(colorValue, lightness - 20, colorIndex); - default -> colorValue; - }; + val lightness = RPrefs.getInt(Const.MONET_BACKGROUND_LIGHTNESS, 100) + return when (resourceName) { + "m3_ref_palette_dynamic_neutral_variant6", "gm3_ref_palette_dynamic_neutral_variant6", "system_background_dark", "system_surface_dark" -> Color.BLACK + "m3_ref_palette_dynamic_neutral_variant12", "gm3_ref_palette_dynamic_neutral_variant12" -> ColorUtil.modifyLightness( + colorValue, + lightness - 40, + colorIndex + ) + + "m3_ref_palette_dynamic_neutral_variant17", "gm3_ref_palette_dynamic_neutral_variant17", "gm3_system_bar_color_night" -> ColorUtil.modifyLightness( + colorValue, + lightness - 60, + colorIndex + ) + + "system_surface_container_dark" -> ColorUtil.modifyLightness( + colorValue, + lightness - 20, + colorIndex + ) + + else -> colorValue + } } - return colorValue; + return colorValue } - public static void addTintlessTextColors(FabricatedOverlayResource overlay) { - String[] prefixes = new String[]{ - "m3_sys_color_", - "m3_sys_color_dynamic_" - }; - String[] variants = new String[]{ - "dark_", - "light_", - }; - String[] suffixes = new String[]{ - "on_surface", - "on_surface_variant", - "on_background" - }; - - for (String prefix : prefixes) { - for (String variant : variants) { - for (String suffix : suffixes) { - String resourceName = prefix + variant + suffix; + private fun addTintlessTextColors(overlay: FabricatedOverlayResource) { + val prefixes = arrayOf( + "m3_sys_color_", + "m3_sys_color_dynamic_" + ) + val variants = arrayOf( + "dark_", + "light_", + ) + val suffixes = arrayOf( + "on_surface", + "on_surface_variant", + "on_background" + ) + + for (prefix in prefixes) { + for (variant in variants) { + for (suffix in suffixes) { + val resourceName = prefix + variant + suffix overlay.setColor( - resourceName, - variant.contains("dark") ? - Color.WHITE : - Color.BLACK - ); + resourceName, + if (variant.contains("dark")) Color.WHITE else Color.BLACK + ) } } } // Dark mode - ArrayList> resourcesDark = new ArrayList<>(); - resourcesDark.add(new Pair<>("m3_ref_palette_dynamic_neutral90", Color.WHITE)); - resourcesDark.add(new Pair<>("m3_ref_palette_dynamic_neutral95", Color.WHITE)); - resourcesDark.add(new Pair<>("m3_ref_palette_dynamic_neutral_variant70", 0xFFCCCCCC)); - resourcesDark.add(new Pair<>("m3_ref_palette_dynamic_neutral_variant80", Color.WHITE)); - resourcesDark.add(new Pair<>("text_color_primary_dark", Color.WHITE)); - resourcesDark.add(new Pair<>("text_color_secondary_dark", 0xB3FFFFFF)); - resourcesDark.add(new Pair<>("text_color_tertiary_dark", 0x80FFFFFF)); - resourcesDark.add(new Pair<>("google_dark_default_color_on_background", Color.WHITE)); - resourcesDark.add(new Pair<>("gm_ref_palette_grey500", Color.WHITE)); + val resourcesDark = ArrayList>() + resourcesDark.add(Pair("m3_ref_palette_dynamic_neutral90", Color.WHITE)) + resourcesDark.add(Pair("m3_ref_palette_dynamic_neutral95", Color.WHITE)) + resourcesDark.add(Pair("m3_ref_palette_dynamic_neutral_variant70", -0x333334)) + resourcesDark.add(Pair("m3_ref_palette_dynamic_neutral_variant80", Color.WHITE)) + resourcesDark.add(Pair("text_color_primary_dark", Color.WHITE)) + resourcesDark.add(Pair("text_color_secondary_dark", -0x4c000001)) + resourcesDark.add(Pair("text_color_tertiary_dark", -0x7f000001)) + resourcesDark.add(Pair("google_dark_default_color_on_background", Color.WHITE)) + resourcesDark.add(Pair("gm_ref_palette_grey500", Color.WHITE)) // Light mode - ArrayList> resourcesLight = new ArrayList<>(); - resourcesLight.add(new Pair<>("m3_ref_palette_dynamic_neutral10", Color.BLACK)); - resourcesLight.add(new Pair<>("m3_ref_palette_dynamic_neutral_variant30", 0xB3000000)); - resourcesLight.add(new Pair<>("text_color_primary_light", Color.BLACK)); - resourcesLight.add(new Pair<>("text_color_secondary_light", 0xB3000000)); - resourcesLight.add(new Pair<>("text_color_tertiary_light", 0x80000000)); - resourcesDark.add(new Pair<>("google_default_color_on_background", Color.BLACK)); - resourcesDark.add(new Pair<>("gm_ref_palette_grey700", Color.BLACK)); - - for (Pair pair : resourcesDark) { - overlay.setColor(pair.first, pair.second); - overlay.setColor("g" + pair.first, pair.second); + val resourcesLight = ArrayList>() + resourcesLight.add(Pair("m3_ref_palette_dynamic_neutral10", Color.BLACK)) + resourcesLight.add(Pair("m3_ref_palette_dynamic_neutral_variant30", -0x4d000000)) + resourcesLight.add(Pair("text_color_primary_light", Color.BLACK)) + resourcesLight.add(Pair("text_color_secondary_light", -0x4d000000)) + resourcesLight.add(Pair("text_color_tertiary_light", -0x80000000)) + resourcesDark.add(Pair("google_default_color_on_background", Color.BLACK)) + resourcesDark.add(Pair("gm_ref_palette_grey700", Color.BLACK)) + + for (pair in resourcesDark) { + overlay.setColor(pair.first, pair.second) + overlay.setColor("g" + pair.first, pair.second) } - for (Pair pair : resourcesLight) { - overlay.setColor(pair.first, pair.second); - overlay.setColor("g" + pair.first, pair.second); + for (pair in resourcesLight) { + overlay.setColor(pair.first, pair.second) + overlay.setColor("g" + pair.first, pair.second) } // For settings text color on android 14 - overlay.setColor("settingslib_text_color_primary_device_default", Color.WHITE, "night"); - overlay.setColor("settingslib_text_color_secondary_device_default", 0xB3FFFFFF, "night"); + overlay.setColor("settingslib_text_color_primary_device_default", Color.WHITE, "night") + overlay.setColor("settingslib_text_color_secondary_device_default", -0x4c000001, "night") } - private static void replaceColorsPerPackageName(FabricatedOverlayResource overlay, ArrayList> palette, boolean pitchBlackTheme) { + private fun replaceColorsPerPackageName( + overlay: FabricatedOverlayResource, + palette: ArrayList>, + pitchBlackTheme: Boolean + ) { if (overlay.targetPackage.startsWith("com.android.systemui.clocks.")) { // Android 14 clocks - for (int i = 0; i < 5; i++) { - for (int j = 0; j < 13; j++) { - overlay.setColor(colorNames[i][j], palette.get(i).get(j)); + for (i in 0..4) { + for (j in 0..12) { + overlay.setColor(colorNames[i][j], palette[i][j]) } } - } else if (overlay.targetPackage.equals("com.google.android.googlequicksearchbox")) { // Google Feeds + } else if (overlay.targetPackage == "com.google.android.googlequicksearchbox") { // Google Feeds if (pitchBlackTheme) { - overlay.setColor("gm3_ref_palette_dynamic_neutral_variant20", Color.BLACK); + overlay.setColor("gm3_ref_palette_dynamic_neutral_variant20", Color.BLACK) } - } else if (overlay.targetPackage.equals("com.google.android.apps.magazines")) { // Google News - overlay.setColor("cluster_divider_bg", Color.TRANSPARENT); - overlay.setColor("cluster_divider_border", Color.TRANSPARENT); - - overlay.setColor("appwidget_background_day", palette.get(3).get(2)); - overlay.setColor("home_background_day", palette.get(3).get(2)); - overlay.setColor("google_default_color_background", palette.get(3).get(2)); - overlay.setColor("gm3_system_bar_color_day", palette.get(4).get(3)); - overlay.setColor("google_default_color_on_background", palette.get(3).get(11)); - overlay.setColor("google_dark_default_color_on_background", palette.get(3).get(1)); - overlay.setColor("google_default_color_on_background", palette.get(3).get(11)); - overlay.setColor("gm3_system_bar_color_night", palette.get(4).get(10)); + } else if (overlay.targetPackage == "com.google.android.apps.magazines") { // Google News + overlay.setColor("cluster_divider_bg", Color.TRANSPARENT) + overlay.setColor("cluster_divider_border", Color.TRANSPARENT) + + overlay.setColor("appwidget_background_day", palette[3][2]) + overlay.setColor("home_background_day", palette[3][2]) + overlay.setColor("google_default_color_background", palette[3][2]) + overlay.setColor("gm3_system_bar_color_day", palette[4][3]) + overlay.setColor("google_default_color_on_background", palette[3][11]) + overlay.setColor("google_dark_default_color_on_background", palette[3][1]) + overlay.setColor("google_default_color_on_background", palette[3][11]) + overlay.setColor("gm3_system_bar_color_night", palette[4][10]) if (pitchBlackTheme) { - overlay.setColor("appwidget_background_night", Color.BLACK); - overlay.setColor("home_background_night", Color.BLACK); - overlay.setColor("google_dark_default_color_background", Color.BLACK); + overlay.setColor("appwidget_background_night", Color.BLACK) + overlay.setColor("home_background_night", Color.BLACK) + overlay.setColor("google_dark_default_color_background", Color.BLACK) } else { - overlay.setColor("appwidget_background_night", palette.get(3).get(11)); - overlay.setColor("home_background_night", palette.get(3).get(11)); - overlay.setColor("google_dark_default_color_background", palette.get(3).get(11)); + overlay.setColor("appwidget_background_night", palette[3][11]) + overlay.setColor("home_background_night", palette[3][11]) + overlay.setColor("google_dark_default_color_background", palette[3][11]) } - } else if (overlay.targetPackage.equals("com.google.android.play.games")) { // Google Play Games + } else if (overlay.targetPackage == "com.google.android.play.games") { // Google Play Games // Light mode - overlay.setColor("google_white", palette.get(3).get(2)); - overlay.setColor("gm_ref_palette_grey300", palette.get(4).get(4)); - overlay.setColor("gm_ref_palette_grey700", palette.get(3).get(11)); - overlay.setColor("replay__pal_games_light_600", palette.get(0).get(8)); + overlay.setColor("google_white", palette[3][2]) + overlay.setColor("gm_ref_palette_grey300", palette[4][4]) + overlay.setColor("gm_ref_palette_grey700", palette[3][11]) + overlay.setColor("replay__pal_games_light_600", palette[0][8]) // Dark mode - overlay.setColor("gm_ref_palette_grey900", pitchBlackTheme ? Color.BLACK : palette.get(3).get(11)); - overlay.setColor("gm_ref_palette_grey600", palette.get(4).get(8)); - overlay.setColor("gm_ref_palette_grey500", palette.get(3).get(1)); - overlay.setColor("replay__pal_games_dark_300", palette.get(0).get(5)); + overlay.setColor( + "gm_ref_palette_grey900", + if (pitchBlackTheme) Color.BLACK else palette[3][11] + ) + overlay.setColor("gm_ref_palette_grey600", palette[4][8]) + overlay.setColor("gm_ref_palette_grey500", palette[3][1]) + overlay.setColor("replay__pal_games_dark_300", palette[0][5]) } } } diff --git a/app/src/main/java/com/drdisagree/colorblendr/utils/FragmentUtil.kt b/app/src/main/java/com/drdisagree/colorblendr/utils/FragmentUtil.kt index ba47cb7..b9e2db6 100644 --- a/app/src/main/java/com/drdisagree/colorblendr/utils/FragmentUtil.kt +++ b/app/src/main/java/com/drdisagree/colorblendr/utils/FragmentUtil.kt @@ -1,98 +1,105 @@ -package com.drdisagree.colorblendr.utils; +package com.drdisagree.colorblendr.utils -import androidx.fragment.app.Fragment; -import androidx.fragment.app.FragmentTransaction; +import androidx.fragment.app.Fragment +import androidx.fragment.app.FragmentTransaction +import com.drdisagree.colorblendr.R +import com.drdisagree.colorblendr.ui.fragments.AboutFragment +import com.drdisagree.colorblendr.ui.fragments.ColorPaletteFragment +import com.drdisagree.colorblendr.ui.fragments.ColorsFragment +import com.drdisagree.colorblendr.ui.fragments.PerAppThemeFragment +import com.drdisagree.colorblendr.ui.fragments.SettingsFragment +import com.drdisagree.colorblendr.ui.fragments.StylesFragment +import com.drdisagree.colorblendr.ui.fragments.ThemeFragment -import com.drdisagree.colorblendr.R; -import com.drdisagree.colorblendr.ui.fragments.AboutFragment; -import com.drdisagree.colorblendr.ui.fragments.ColorPaletteFragment; -import com.drdisagree.colorblendr.ui.fragments.ColorsFragment; -import com.drdisagree.colorblendr.ui.fragments.PerAppThemeFragment; -import com.drdisagree.colorblendr.ui.fragments.SettingsFragment; -import com.drdisagree.colorblendr.ui.fragments.StylesFragment; -import com.drdisagree.colorblendr.ui.fragments.ThemeFragment; - -public class FragmentUtil { - - public enum TAB_SELECTION { - FROM_LEFT_TO_RIGHT, - FROM_RIGHT_TO_LEFT, - NONE - } - - public static TAB_SELECTION getSlidingDirection(Fragment currentFragment, Fragment newFragment) { +object FragmentUtil { + fun getSlidingDirection(currentFragment: Fragment?, newFragment: Fragment): TabSelection { if (currentFragment == null) { - return TAB_SELECTION.NONE; + return TabSelection.NONE } - TAB_SELECTION direction; - - if (isInGroup1(currentFragment) && !isInGroup1(newFragment)) { - direction = TAB_SELECTION.FROM_LEFT_TO_RIGHT; - } else if (isInGroup4(currentFragment) && !isInGroup4(newFragment)) { - direction = TAB_SELECTION.FROM_RIGHT_TO_LEFT; + val direction = if (isInGroup1(currentFragment) && !isInGroup1(newFragment)) { + TabSelection.FROM_LEFT_TO_RIGHT + } else if (isInGroup4(currentFragment) && !isInGroup4( + newFragment + ) + ) { + TabSelection.FROM_RIGHT_TO_LEFT } else if (isInGroup2(currentFragment)) { if (isInGroup1(newFragment)) { - direction = TAB_SELECTION.FROM_RIGHT_TO_LEFT; - } else if (isInGroup3(newFragment) || isInGroup4(newFragment)) { - direction = TAB_SELECTION.FROM_LEFT_TO_RIGHT; + TabSelection.FROM_RIGHT_TO_LEFT + } else if (isInGroup3(newFragment) || isInGroup4( + newFragment + ) + ) { + TabSelection.FROM_LEFT_TO_RIGHT } else { - return TAB_SELECTION.NONE; + return TabSelection.NONE } } else if (isInGroup3(currentFragment)) { if (isInGroup4(newFragment)) { - direction = TAB_SELECTION.FROM_LEFT_TO_RIGHT; - } else if (isInGroup1(newFragment) || isInGroup2(newFragment)) { - direction = TAB_SELECTION.FROM_RIGHT_TO_LEFT; + TabSelection.FROM_LEFT_TO_RIGHT + } else if (isInGroup1(newFragment) || isInGroup2( + newFragment + ) + ) { + TabSelection.FROM_RIGHT_TO_LEFT } else { - return TAB_SELECTION.NONE; + return TabSelection.NONE } } else { - return TAB_SELECTION.NONE; + return TabSelection.NONE } - return direction; + return direction } - public static void setCustomAnimations(TAB_SELECTION direction, FragmentTransaction fragmentTransaction) { - switch (direction) { - case FROM_LEFT_TO_RIGHT -> fragmentTransaction.setCustomAnimations( - R.anim.slide_in_right, - R.anim.slide_out_left, - R.anim.slide_in_left, - R.anim.slide_out_right - ); - case FROM_RIGHT_TO_LEFT -> fragmentTransaction.setCustomAnimations( - R.anim.slide_in_left, - R.anim.slide_out_right, - R.anim.slide_in_right, - R.anim.slide_out_left - ); - case NONE -> fragmentTransaction.setCustomAnimations( - R.anim.fade_in, - R.anim.fade_out, - R.anim.fade_in, - R.anim.fade_out - ); + fun setCustomAnimations(direction: TabSelection, fragmentTransaction: FragmentTransaction) { + when (direction) { + TabSelection.FROM_LEFT_TO_RIGHT -> fragmentTransaction.setCustomAnimations( + R.anim.slide_in_right, + R.anim.slide_out_left, + R.anim.slide_in_left, + R.anim.slide_out_right + ) + + TabSelection.FROM_RIGHT_TO_LEFT -> fragmentTransaction.setCustomAnimations( + R.anim.slide_in_left, + R.anim.slide_out_right, + R.anim.slide_in_right, + R.anim.slide_out_left + ) + + TabSelection.NONE -> fragmentTransaction.setCustomAnimations( + R.anim.fade_in, + R.anim.fade_out, + R.anim.fade_in, + R.anim.fade_out + ) } } - private static boolean isInGroup1(Fragment fragment) { - return fragment instanceof ColorsFragment || - fragment instanceof PerAppThemeFragment || - fragment instanceof ColorPaletteFragment; + private fun isInGroup1(fragment: Fragment): Boolean { + return fragment is ColorsFragment || + fragment is PerAppThemeFragment || + fragment is ColorPaletteFragment + } + + private fun isInGroup2(fragment: Fragment): Boolean { + return fragment is ThemeFragment } - private static boolean isInGroup2(Fragment fragment) { - return fragment instanceof ThemeFragment; + private fun isInGroup3(fragment: Fragment): Boolean { + return fragment is StylesFragment } - private static boolean isInGroup3(Fragment fragment) { - return fragment instanceof StylesFragment; + private fun isInGroup4(fragment: Fragment): Boolean { + return fragment is SettingsFragment || + fragment is AboutFragment } - private static boolean isInGroup4(Fragment fragment) { - return fragment instanceof SettingsFragment || - fragment instanceof AboutFragment; + enum class TabSelection { + FROM_LEFT_TO_RIGHT, + FROM_RIGHT_TO_LEFT, + NONE } } diff --git a/app/src/main/java/com/drdisagree/colorblendr/utils/MiscUtil.kt b/app/src/main/java/com/drdisagree/colorblendr/utils/MiscUtil.kt index 664919e..a4efdfd 100644 --- a/app/src/main/java/com/drdisagree/colorblendr/utils/MiscUtil.kt +++ b/app/src/main/java/com/drdisagree/colorblendr/utils/MiscUtil.kt @@ -1,57 +1,59 @@ -package com.drdisagree.colorblendr.utils; +package com.drdisagree.colorblendr.utils -import android.content.Context; +import android.content.Context +import androidx.annotation.StringRes +import androidx.appcompat.app.AppCompatActivity +import com.google.android.material.appbar.MaterialToolbar +import org.json.JSONException +import org.json.JSONObject -import androidx.annotation.StringRes; -import androidx.appcompat.app.ActionBar; -import androidx.appcompat.app.AppCompatActivity; +object MiscUtil { -import com.google.android.material.appbar.MaterialToolbar; - -import org.json.JSONException; -import org.json.JSONObject; - -import java.util.ArrayList; -import java.util.Iterator; - -public class MiscUtil { - - public static int[][] convertListToIntArray(ArrayList> arrayList) { - return arrayList.stream() - .map(row -> row.stream().mapToInt(Integer::intValue).toArray()) - .toArray(int[][]::new); + fun convertListToIntArray(arrayList: ArrayList>): Array { + return arrayList.map { row -> row.toIntArray() }.toTypedArray() } - public static void setToolbarTitle(Context context, @StringRes int title, boolean showBackButton, MaterialToolbar toolbar) { - ((AppCompatActivity) context).setSupportActionBar(toolbar); - ActionBar actionBar = ((AppCompatActivity) context).getSupportActionBar(); + fun setToolbarTitle( + context: Context, + @StringRes title: Int, + showBackButton: Boolean, + toolbar: MaterialToolbar? + ) { + (context as AppCompatActivity).setSupportActionBar(toolbar) + val actionBar = context.supportActionBar if (actionBar != null) { - ((AppCompatActivity) context).getSupportActionBar().setTitle(title); - ((AppCompatActivity) context).getSupportActionBar().setDisplayHomeAsUpEnabled(showBackButton); - ((AppCompatActivity) context).getSupportActionBar().setDisplayShowHomeEnabled(showBackButton); + context.supportActionBar!!.setTitle(title) + context.supportActionBar!!.setDisplayHomeAsUpEnabled(showBackButton) + context.supportActionBar!!.setDisplayShowHomeEnabled(showBackButton) } } - public static String mergeJsonStrings(String target, String source) throws JSONException { - if (target == null || target.isEmpty()) { - target = new JSONObject().toString(); + @Throws(JSONException::class) + fun mergeJsonStrings(target: String?, source: String?): String { + var targetTemp = target + var sourceTemp = source + + if (target.isNullOrEmpty()) { + targetTemp = JSONObject().toString() } - if (source == null || source.isEmpty()) { - source = new JSONObject().toString(); + if (source.isNullOrEmpty()) { + sourceTemp = JSONObject().toString() } - JSONObject targetJson = new JSONObject(target); - JSONObject sourceJson = new JSONObject(source); - return mergeJsonObjects(targetJson, sourceJson).toString(); + val targetJson = JSONObject(targetTemp!!) + val sourceJson = JSONObject(sourceTemp!!) + + return mergeJsonObjects(targetJson, sourceJson).toString() } - public static JSONObject mergeJsonObjects(JSONObject target, JSONObject source) throws JSONException { - Iterator keys = source.keys(); + @Throws(JSONException::class) + fun mergeJsonObjects(target: JSONObject, source: JSONObject): JSONObject { + val keys = source.keys() while (keys.hasNext()) { - String key = keys.next(); - target.put(key, source.get(key)); + val key = keys.next() + target.put(key, source[key]) } - return target; + return target } } diff --git a/app/src/main/java/com/drdisagree/colorblendr/utils/OverlayManager.kt b/app/src/main/java/com/drdisagree/colorblendr/utils/OverlayManager.kt index a374690..6bd369e 100644 --- a/app/src/main/java/com/drdisagree/colorblendr/utils/OverlayManager.kt +++ b/app/src/main/java/com/drdisagree/colorblendr/utils/OverlayManager.kt @@ -1,408 +1,447 @@ -package com.drdisagree.colorblendr.utils; - -import static com.drdisagree.colorblendr.common.Const.FABRICATED_OVERLAY_NAME_APPS; -import static com.drdisagree.colorblendr.common.Const.FABRICATED_OVERLAY_NAME_SYSTEM; -import static com.drdisagree.colorblendr.common.Const.FABRICATED_OVERLAY_NAME_SYSTEMUI; -import static com.drdisagree.colorblendr.common.Const.FRAMEWORK_PACKAGE; -import static com.drdisagree.colorblendr.common.Const.MONET_ACCENT_SATURATION; -import static com.drdisagree.colorblendr.common.Const.MONET_ACCURATE_SHADES; -import static com.drdisagree.colorblendr.common.Const.MONET_BACKGROUND_LIGHTNESS; -import static com.drdisagree.colorblendr.common.Const.MONET_BACKGROUND_SATURATION; -import static com.drdisagree.colorblendr.common.Const.MONET_PITCH_BLACK_THEME; -import static com.drdisagree.colorblendr.common.Const.MONET_STYLE; -import static com.drdisagree.colorblendr.common.Const.SHIZUKU_THEMING_ENABLED; -import static com.drdisagree.colorblendr.common.Const.SYSTEMUI_PACKAGE; -import static com.drdisagree.colorblendr.common.Const.THEMING_ENABLED; -import static com.drdisagree.colorblendr.common.Const.TINT_TEXT_COLOR; - -import android.content.Context; -import android.graphics.Color; -import android.os.RemoteException; -import android.util.Log; - -import com.drdisagree.colorblendr.ColorBlendr; -import com.drdisagree.colorblendr.R; -import com.drdisagree.colorblendr.common.Const; -import com.drdisagree.colorblendr.config.RPrefs; -import com.drdisagree.colorblendr.extension.ThemeOverlayPackage; -import com.drdisagree.colorblendr.service.IRootConnection; -import com.drdisagree.colorblendr.service.IShizukuConnection; -import com.drdisagree.colorblendr.utils.fabricated.FabricatedOverlayResource; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; - -@SuppressWarnings("unused") -public class OverlayManager { - - private static final String TAG = OverlayManager.class.getSimpleName(); - private static IRootConnection mRootConnection = ColorBlendr.getRootConnection(); - private static IShizukuConnection mShizukuConnection = ColorBlendr.getShizukuConnection(); - private static final String[][] colorNames = ColorUtil.getColorNames(); - - public static void enableOverlay(String packageName) { +package com.drdisagree.colorblendr.utils + +import android.content.Context +import android.graphics.Color +import android.os.RemoteException +import android.util.Log +import com.drdisagree.colorblendr.ColorBlendr.Companion.rootConnection +import com.drdisagree.colorblendr.ColorBlendr.Companion.shizukuConnection +import com.drdisagree.colorblendr.R +import com.drdisagree.colorblendr.common.Const +import com.drdisagree.colorblendr.config.RPrefs +import com.drdisagree.colorblendr.extension.ThemeOverlayPackage +import com.drdisagree.colorblendr.utils.ColorUtil.generateModifiedColors +import com.drdisagree.colorblendr.utils.fabricated.FabricatedOverlayResource + +@Suppress("unused") +object OverlayManager { + private val TAG: String = OverlayManager::class.java.simpleName + private var mRootConnection = rootConnection + private var mShizukuConnection = shizukuConnection + private val colorNames: Array> = ColorUtil.colorNames + + fun enableOverlay(packageName: String) { if (mRootConnection == null) { - mRootConnection = ColorBlendr.getRootConnection(); + mRootConnection = rootConnection if (mRootConnection == null) { - Log.w(TAG, "Root service connection is null"); - return; + Log.w(TAG, "Root service connection is null") + return } } try { - mRootConnection.enableOverlay(Collections.singletonList(packageName)); - } catch (RemoteException e) { - Log.e(TAG, "Failed to enable overlay: " + packageName, e); + mRootConnection!!.enableOverlay(listOf(packageName)) + } catch (e: RemoteException) { + Log.e( + TAG, + "Failed to enable overlay: $packageName", e + ) } } - public static void disableOverlay(String packageName) { + fun disableOverlay(packageName: String) { if (mRootConnection == null) { - mRootConnection = ColorBlendr.getRootConnection(); + mRootConnection = rootConnection if (mRootConnection == null) { - Log.w(TAG, "Root service connection is null"); - return; + Log.w(TAG, "Root service connection is null") + return } } try { - mRootConnection.disableOverlay(Collections.singletonList(packageName)); - } catch (RemoteException e) { - Log.e(TAG, "Failed to disable overlay: " + packageName, e); + mRootConnection!!.disableOverlay(listOf(packageName)) + } catch (e: RemoteException) { + Log.e( + TAG, + "Failed to disable overlay: $packageName", e + ) } } - public static boolean isOverlayInstalled(String packageName) { + fun isOverlayInstalled(packageName: String): Boolean { if (mRootConnection == null) { - mRootConnection = ColorBlendr.getRootConnection(); + mRootConnection = rootConnection if (mRootConnection == null) { - Log.w(TAG, "Root service connection is null"); - return false; + Log.w(TAG, "Root service connection is null") + return false } } try { - return mRootConnection.isOverlayInstalled(packageName); - } catch (RemoteException e) { - Log.e(TAG, "Failed to check if overlay is installed: " + packageName, e); - return false; + return mRootConnection!!.isOverlayInstalled(packageName) ?: false + } catch (e: RemoteException) { + Log.e( + TAG, + "Failed to check if overlay is installed: $packageName", e + ) + return false } } - public static boolean isOverlayEnabled(String packageName) { + fun isOverlayEnabled(packageName: String): Boolean { if (mRootConnection == null) { - mRootConnection = ColorBlendr.getRootConnection(); + mRootConnection = rootConnection if (mRootConnection == null) { - Log.w(TAG, "Root service connection is null"); - return false; + Log.w(TAG, "Root service connection is null") + return false } } try { - return mRootConnection.isOverlayEnabled(packageName); - } catch (RemoteException e) { - Log.e(TAG, "Failed to check if overlay is enabled: " + packageName, e); - return false; + return mRootConnection!!.isOverlayEnabled(packageName) ?: false + } catch (e: RemoteException) { + Log.e( + TAG, + "Failed to check if overlay is enabled: $packageName", e + ) + return false } } - public static void uninstallOverlayUpdates(String packageName) { + fun uninstallOverlayUpdates(packageName: String) { if (mRootConnection == null) { - mRootConnection = ColorBlendr.getRootConnection(); + mRootConnection = rootConnection if (mRootConnection == null) { - Log.w(TAG, "Root service connection is null"); - return; + Log.w(TAG, "Root service connection is null") + return } } try { - mRootConnection.uninstallOverlayUpdates(packageName); - } catch (RemoteException e) { - Log.e(TAG, "Failed to uninstall overlay updates: " + packageName, e); + mRootConnection!!.uninstallOverlayUpdates(packageName) + } catch (e: RemoteException) { + Log.e( + TAG, + "Failed to uninstall overlay updates: $packageName", e + ) } } - public static void registerFabricatedOverlay(FabricatedOverlayResource fabricatedOverlay) { - if (Const.getWorkingMethod() != Const.WORK_METHOD.ROOT) { - return; + private fun registerFabricatedOverlay(fabricatedOverlay: FabricatedOverlayResource) { + if (Const.workingMethod != Const.WorkMethod.ROOT) { + return } if (mRootConnection == null) { - mRootConnection = ColorBlendr.getRootConnection(); + mRootConnection = rootConnection if (mRootConnection == null) { - Log.w(TAG, "Root service connection is null"); - return; + Log.w(TAG, "Root service connection is null") + return } } try { - mRootConnection.registerFabricatedOverlay(fabricatedOverlay); - mRootConnection.enableOverlayWithIdentifier(Collections.singletonList(fabricatedOverlay.overlayName)); - } catch (RemoteException e) { - Log.e(TAG, "Failed to register fabricated overlay: " + fabricatedOverlay.overlayName, e); + mRootConnection!!.registerFabricatedOverlay(fabricatedOverlay) + mRootConnection!!.enableOverlayWithIdentifier(listOf(fabricatedOverlay.overlayName)) + } catch (e: RemoteException) { + Log.e(TAG, "Failed to register fabricated overlay: " + fabricatedOverlay.overlayName, e) } } - public static void unregisterFabricatedOverlay(String packageName) { - if (Const.getWorkingMethod() != Const.WORK_METHOD.ROOT) { - return; + fun unregisterFabricatedOverlay(packageName: String) { + if (Const.workingMethod != Const.WorkMethod.ROOT) { + return } if (mRootConnection == null) { - mRootConnection = ColorBlendr.getRootConnection(); + mRootConnection = rootConnection if (mRootConnection == null) { - Log.w(TAG, "Root service connection is null"); - return; + Log.w(TAG, "Root service connection is null") + return } } try { - mRootConnection.unregisterFabricatedOverlay(packageName); - } catch (RemoteException e) { - Log.e(TAG, "Failed to unregister fabricated overlay: " + packageName, e); + mRootConnection!!.unregisterFabricatedOverlay(packageName) + } catch (e: RemoteException) { + Log.e( + TAG, + "Failed to unregister fabricated overlay: $packageName", e + ) } } - public static void applyFabricatedColors(Context context) { - if (!RPrefs.getBoolean(THEMING_ENABLED, true) && !RPrefs.getBoolean(SHIZUKU_THEMING_ENABLED, true)) { - return; + fun applyFabricatedColors(context: Context) { + if (!RPrefs.getBoolean( + Const.THEMING_ENABLED, + true + ) && !RPrefs.getBoolean(Const.SHIZUKU_THEMING_ENABLED, true) + ) { + return } if (applyFabricatedColorsNonRoot(context)) { - return; - } - - ColorSchemeUtil.MONET style = ColorSchemeUtil.stringToEnumMonetStyle( - context, - RPrefs.getString(MONET_STYLE, context.getString(R.string.monet_tonalspot)) - ); - int monetAccentSaturation = RPrefs.getInt(MONET_ACCENT_SATURATION, 100); - int monetBackgroundSaturation = RPrefs.getInt(MONET_BACKGROUND_SATURATION, 100); - int monetBackgroundLightness = RPrefs.getInt(MONET_BACKGROUND_LIGHTNESS, 100); - boolean pitchBlackTheme = RPrefs.getBoolean(MONET_PITCH_BLACK_THEME, false); - boolean accurateShades = RPrefs.getBoolean(MONET_ACCURATE_SHADES, true); - - ArrayList> paletteLight = ColorUtil.generateModifiedColors( - context, - style, - monetAccentSaturation, - monetBackgroundSaturation, - monetBackgroundLightness, - pitchBlackTheme, - accurateShades, - false, - false - ); - - ArrayList> paletteDark = ColorUtil.generateModifiedColors( - context, - style, - monetAccentSaturation, - monetBackgroundSaturation, - monetBackgroundLightness, - pitchBlackTheme, - accurateShades, - false, - true - ); - - ArrayList fabricatedOverlays = new ArrayList<>(); - fabricatedOverlays.add(new FabricatedOverlayResource( - FABRICATED_OVERLAY_NAME_SYSTEM, - FRAMEWORK_PACKAGE - )); - - for (int i = 0; i < 5; i++) { - for (int j = 0; j < 13; j++) { - fabricatedOverlays.get(0).setColor(colorNames[i][j], paletteDark.get(i).get(j)); + return + } + + val style = ColorSchemeUtil.stringToEnumMonetStyle( + context, + RPrefs.getString(Const.MONET_STYLE, context.getString(R.string.monet_tonalspot))!! + ) + val monetAccentSaturation = RPrefs.getInt(Const.MONET_ACCENT_SATURATION, 100) + val monetBackgroundSaturation = RPrefs.getInt(Const.MONET_BACKGROUND_SATURATION, 100) + val monetBackgroundLightness = RPrefs.getInt(Const.MONET_BACKGROUND_LIGHTNESS, 100) + val pitchBlackTheme = RPrefs.getBoolean(Const.MONET_PITCH_BLACK_THEME, false) + val accurateShades = RPrefs.getBoolean(Const.MONET_ACCURATE_SHADES, true) + + val paletteLight = ColorUtil.generateModifiedColors( + context, + style, + monetAccentSaturation, + monetBackgroundSaturation, + monetBackgroundLightness, + pitchBlackTheme, + accurateShades, + modifyPitchBlack = false, + isDark = false + ) + + val paletteDark = ColorUtil.generateModifiedColors( + context, + style, + monetAccentSaturation, + monetBackgroundSaturation, + monetBackgroundLightness, + pitchBlackTheme, + accurateShades, + modifyPitchBlack = false, + isDark = true + ) + + val fabricatedOverlays = ArrayList() + fabricatedOverlays.add( + FabricatedOverlayResource( + Const.FABRICATED_OVERLAY_NAME_SYSTEM, + Const.FRAMEWORK_PACKAGE + ) + ) + + for (i in 0..4) { + for (j in 0..12) { + fabricatedOverlays[0].setColor( + colorNames[i][j], + paletteDark[i][j] + ) } } FabricatedUtil.createDynamicOverlay( - fabricatedOverlays.get(0), - paletteLight, - paletteDark - ); - - HashMap selectedApps = Const.getSelectedFabricatedApps(); - - for (String packageName : selectedApps.keySet()) { - if (Boolean.TRUE.equals(selectedApps.get(packageName)) && - SystemUtil.isAppInstalled(packageName)) { - FabricatedOverlayResource fabricatedOverlayPerApp = getFabricatedColorsPerApp( - context, - packageName, - SystemUtil.isDarkMode() ? - paletteDark : - paletteLight - ); - - fabricatedOverlays.add(fabricatedOverlayPerApp); + fabricatedOverlays[0], + paletteLight, + paletteDark + ) + + val selectedApps = Const.selectedFabricatedApps + + for (packageName in selectedApps.keys) { + if (java.lang.Boolean.TRUE == selectedApps[packageName] && + SystemUtil.isAppInstalled(packageName) + ) { + val fabricatedOverlayPerApp = getFabricatedColorsPerApp( + context, + packageName, + if (SystemUtil.isDarkMode) paletteDark else paletteLight + ) + + fabricatedOverlays.add(fabricatedOverlayPerApp) } } - fabricatedOverlays.get(0).setColor( - "system_surface_dim_dark", - fabricatedOverlays.get(0).getColor(colorNames[3][11]) // system_neutral1_900 - ); // A14 notification scrim color - fabricatedOverlays.get(0).setColor( - "system_surface_container_high_dark", - fabricatedOverlays.get(0).getColor(colorNames[3][10]) // system_neutral1_800 - ); // A14 notification background color + fabricatedOverlays[0].setColor( + "system_surface_dim_dark", + fabricatedOverlays[0].getColor( + colorNames[3][11] + ) // system_neutral1_900 + ) // A14 notification scrim color + fabricatedOverlays[0].setColor( + "system_surface_container_high_dark", + fabricatedOverlays[0].getColor( + colorNames[3][10] + ) // system_neutral1_800 + ) // A14 notification background color if (pitchBlackTheme) { - fabricatedOverlays.get(0).setColor("surface_header_dark_sysui", Color.BLACK); // QS top part color - fabricatedOverlays.get(0).setColor("system_surface_dim_dark", Color.BLACK); // A14 notification scrim color - fabricatedOverlays.get(0).setColor(colorNames[3][11], Color.BLACK); - fabricatedOverlays.get(0).setColor(colorNames[4][11], Color.BLACK); + fabricatedOverlays[0].setColor( + "surface_header_dark_sysui", + Color.BLACK + ) // QS top part color + fabricatedOverlays[0].setColor( + "system_surface_dim_dark", + Color.BLACK + ) // A14 notification scrim color + fabricatedOverlays[0].setColor( + colorNames[3][11], Color.BLACK + ) + fabricatedOverlays[0].setColor( + colorNames[4][11], Color.BLACK + ) } - if (!RPrefs.getBoolean(TINT_TEXT_COLOR, true)) { - fabricatedOverlays.get(0).setColor("text_color_primary_device_default_dark", Color.WHITE); - fabricatedOverlays.get(0).setColor("text_color_secondary_device_default_dark", 0xB3FFFFFF); - fabricatedOverlays.get(0).setColor("text_color_primary_device_default_light", Color.BLACK); - fabricatedOverlays.get(0).setColor("text_color_secondary_device_default_light", 0xB3000000); + if (!RPrefs.getBoolean(Const.TINT_TEXT_COLOR, true)) { + fabricatedOverlays[0].setColor("text_color_primary_device_default_dark", Color.WHITE) + fabricatedOverlays[0].setColor("text_color_secondary_device_default_dark", -0x4c000001) + fabricatedOverlays[0].setColor("text_color_primary_device_default_light", Color.BLACK) + fabricatedOverlays[0].setColor("text_color_secondary_device_default_light", -0x4d000000) } - fabricatedOverlays.add(new FabricatedOverlayResource( - FABRICATED_OVERLAY_NAME_SYSTEMUI, - SYSTEMUI_PACKAGE - )); + fabricatedOverlays.add( + FabricatedOverlayResource( + Const.FABRICATED_OVERLAY_NAME_SYSTEMUI, + Const.SYSTEMUI_PACKAGE + ) + ) - fabricatedOverlays.get(fabricatedOverlays.size() - 1).setBoolean("flag_monet", false); + fabricatedOverlays[fabricatedOverlays.size - 1].setBoolean("flag_monet", false) - for (FabricatedOverlayResource fabricatedOverlay : fabricatedOverlays) { - registerFabricatedOverlay(fabricatedOverlay); + for (fabricatedOverlay in fabricatedOverlays) { + registerFabricatedOverlay(fabricatedOverlay) } } - public static void applyFabricatedColorsPerApp(Context context, String packageName, ArrayList> palette) { + fun applyFabricatedColorsPerApp( + context: Context, + packageName: String, + palette: ArrayList>? + ) { registerFabricatedOverlay( - getFabricatedColorsPerApp( - context, - packageName, - palette - ) - ); + getFabricatedColorsPerApp( + context, + packageName, + palette + ) + ) } - public static void removeFabricatedColors(Context context) { + fun removeFabricatedColors(context: Context) { if (removeFabricatedColorsNonRoot(context)) { - return; + return } - ArrayList fabricatedOverlays = new ArrayList<>(); - HashMap selectedApps = Const.getSelectedFabricatedApps(); + val fabricatedOverlays = ArrayList() + val selectedApps = Const.selectedFabricatedApps - for (String packageName : selectedApps.keySet()) { - if (Boolean.TRUE.equals(selectedApps.get(packageName))) { - fabricatedOverlays.add(String.format(FABRICATED_OVERLAY_NAME_APPS, packageName)); + for (packageName in selectedApps.keys) { + if (java.lang.Boolean.TRUE == selectedApps[packageName]) { + fabricatedOverlays.add( + String.format( + Const.FABRICATED_OVERLAY_NAME_APPS, + packageName + ) + ) } } - fabricatedOverlays.add(FABRICATED_OVERLAY_NAME_SYSTEM); - fabricatedOverlays.add(FABRICATED_OVERLAY_NAME_SYSTEMUI); + fabricatedOverlays.add(Const.FABRICATED_OVERLAY_NAME_SYSTEM) + fabricatedOverlays.add(Const.FABRICATED_OVERLAY_NAME_SYSTEMUI) - for (String packageName : fabricatedOverlays) { - unregisterFabricatedOverlay(packageName); + for (packageName in fabricatedOverlays) { + unregisterFabricatedOverlay(packageName) } } - private static FabricatedOverlayResource getFabricatedColorsPerApp(Context context, String packageName, ArrayList> palette) { - if (palette == null) { - palette = ColorUtil.generateModifiedColors( + private fun getFabricatedColorsPerApp( + context: Context, + packageName: String, + palette: ArrayList>? + ): FabricatedOverlayResource { + var paletteTemp = palette + + if (paletteTemp == null) { + paletteTemp = generateModifiedColors( + context, + ColorSchemeUtil.stringToEnumMonetStyle( context, - ColorSchemeUtil.stringToEnumMonetStyle( - context, - RPrefs.getString(MONET_STYLE, context.getString(R.string.monet_tonalspot)) - ), - RPrefs.getInt(MONET_ACCENT_SATURATION, 100), - RPrefs.getInt(MONET_BACKGROUND_SATURATION, 100), - RPrefs.getInt(MONET_BACKGROUND_LIGHTNESS, 100), - RPrefs.getBoolean(MONET_PITCH_BLACK_THEME, false), - RPrefs.getBoolean(MONET_ACCURATE_SHADES, true), - false - ); - } - - FabricatedOverlayResource fabricatedOverlay = new FabricatedOverlayResource( - String.format(FABRICATED_OVERLAY_NAME_APPS, packageName), - packageName - ); - - FabricatedUtil.assignPerAppColorsToOverlay(fabricatedOverlay, palette); - - return fabricatedOverlay; + RPrefs.getString( + Const.MONET_STYLE, + context.getString(R.string.monet_tonalspot) + )!! + ), + RPrefs.getInt(Const.MONET_ACCENT_SATURATION, 100), + RPrefs.getInt(Const.MONET_BACKGROUND_SATURATION, 100), + RPrefs.getInt(Const.MONET_BACKGROUND_LIGHTNESS, 100), + RPrefs.getBoolean(Const.MONET_PITCH_BLACK_THEME, false), + RPrefs.getBoolean(Const.MONET_ACCURATE_SHADES, true), + modifyPitchBlack = false + ) + } + + val fabricatedOverlay = FabricatedOverlayResource( + String.format(Const.FABRICATED_OVERLAY_NAME_APPS, packageName), + packageName + ) + + FabricatedUtil.assignPerAppColorsToOverlay(fabricatedOverlay, paletteTemp) + + return fabricatedOverlay } - public static boolean applyFabricatedColorsNonRoot(Context context) { - if (Const.getWorkingMethod() != Const.WORK_METHOD.SHIZUKU) { - return false; + private fun applyFabricatedColorsNonRoot(context: Context): Boolean { + if (Const.workingMethod != Const.WorkMethod.SHIZUKU) { + return false } - if (!ShizukuUtil.isShizukuAvailable() || !ShizukuUtil.hasShizukuPermission(context)) { - Log.w(TAG, "Shizuku permission not available"); - return true; + if (!ShizukuUtil.isShizukuAvailable || !ShizukuUtil.hasShizukuPermission(context)) { + Log.w(TAG, "Shizuku permission not available") + return true } if (mShizukuConnection == null) { - mShizukuConnection = ColorBlendr.getShizukuConnection(); + mShizukuConnection = shizukuConnection if (mShizukuConnection == null) { - Log.w(TAG, "Shizuku service connection is null"); - return true; + Log.w(TAG, "Shizuku service connection is null") + return true } } try { - String currentSettings = mShizukuConnection.getCurrentSettings(); - String jsonString = ThemeOverlayPackage.getThemeCustomizationOverlayPackages().toString(); + val currentSettings = mShizukuConnection!!.currentSettings + val jsonString = ThemeOverlayPackage.themeCustomizationOverlayPackages.toString() - if (!jsonString.isEmpty()) { - mShizukuConnection.applyFabricatedColors( - MiscUtil.mergeJsonStrings(currentSettings, jsonString) - ); + if (jsonString.isNotEmpty()) { + mShizukuConnection!!.applyFabricatedColors( + MiscUtil.mergeJsonStrings(currentSettings, jsonString) + ) } - } catch (Exception e) { - Log.d(TAG, "applyFabricatedColorsNonRoot: ", e); + } catch (e: Exception) { + Log.d(TAG, "applyFabricatedColorsNonRoot: ", e) } - return true; + return true } - public static boolean removeFabricatedColorsNonRoot(Context context) { - if (Const.getWorkingMethod() != Const.WORK_METHOD.SHIZUKU) { - return false; + private fun removeFabricatedColorsNonRoot(context: Context): Boolean { + if (Const.workingMethod != Const.WorkMethod.SHIZUKU) { + return false } - if (!ShizukuUtil.isShizukuAvailable() || !ShizukuUtil.hasShizukuPermission(context)) { - Log.w(TAG, "Shizuku permission not available"); - return true; + if (!ShizukuUtil.isShizukuAvailable || !ShizukuUtil.hasShizukuPermission(context)) { + Log.w(TAG, "Shizuku permission not available") + return true } if (mShizukuConnection == null) { - mShizukuConnection = ColorBlendr.getShizukuConnection(); + mShizukuConnection = shizukuConnection if (mShizukuConnection == null) { - Log.w(TAG, "Shizuku service connection is null"); - return true; + Log.w(TAG, "Shizuku service connection is null") + return true } } try { - mShizukuConnection.removeFabricatedColors(); - } catch (Exception e) { - Log.d(TAG, "removeFabricatedColorsNonRoot: ", e); + mShizukuConnection!!.removeFabricatedColors() + } catch (e: Exception) { + Log.d(TAG, "removeFabricatedColorsNonRoot: ", e) } - return true; + return true } } diff --git a/app/src/main/java/com/drdisagree/colorblendr/utils/ShizukuUtil.kt b/app/src/main/java/com/drdisagree/colorblendr/utils/ShizukuUtil.kt index 899e268..6b3fbef 100644 --- a/app/src/main/java/com/drdisagree/colorblendr/utils/ShizukuUtil.kt +++ b/app/src/main/java/com/drdisagree/colorblendr/utils/ShizukuUtil.kt @@ -1,79 +1,74 @@ -package com.drdisagree.colorblendr.utils; +package com.drdisagree.colorblendr.utils -import static com.drdisagree.colorblendr.common.Const.SHIZUKU_PERMISSION_REQUEST_ID; +import android.content.ComponentName +import android.content.Context +import android.content.ServiceConnection +import android.content.pm.PackageManager +import androidx.activity.ComponentActivity +import androidx.activity.result.contract.ActivityResultContracts +import com.drdisagree.colorblendr.BuildConfig +import com.drdisagree.colorblendr.common.Const +import rikka.shizuku.Shizuku +import rikka.shizuku.Shizuku.OnRequestPermissionResultListener +import rikka.shizuku.Shizuku.UserServiceArgs +import rikka.shizuku.ShizukuProvider -import android.content.ComponentName; -import android.content.Context; -import android.content.ServiceConnection; -import android.content.pm.PackageManager; +object ShizukuUtil { + val isShizukuAvailable: Boolean + get() = Shizuku.pingBinder() -import androidx.activity.ComponentActivity; -import androidx.activity.result.ActivityResultLauncher; -import androidx.activity.result.contract.ActivityResultContracts; - -import com.drdisagree.colorblendr.BuildConfig; - -import rikka.shizuku.Shizuku; -import rikka.shizuku.ShizukuProvider; - -public class ShizukuUtil { - - public static boolean isShizukuAvailable() { - return Shizuku.pingBinder(); - } - - public static boolean hasShizukuPermission(Context context) { - if (!isShizukuAvailable()) { - return false; + fun hasShizukuPermission(context: Context): Boolean { + if (!isShizukuAvailable) { + return false } - if (Shizuku.getVersion() >= 11 && !Shizuku.isPreV11()) { - return Shizuku.checkSelfPermission() == PackageManager.PERMISSION_GRANTED; + return if (Shizuku.getVersion() >= 11 && !Shizuku.isPreV11()) { + Shizuku.checkSelfPermission() == PackageManager.PERMISSION_GRANTED } else { - return context.checkCallingOrSelfPermission(ShizukuProvider.PERMISSION) == PackageManager.PERMISSION_GRANTED; + context.checkCallingOrSelfPermission(ShizukuProvider.PERMISSION) == PackageManager.PERMISSION_GRANTED } } - public static void requestShizukuPermission(ComponentActivity activity, ShizukuPermissionCallback callback) { + fun requestShizukuPermission(activity: ComponentActivity, callback: ShizukuPermissionCallback) { if (Shizuku.getVersion() >= 11 && !Shizuku.isPreV11()) { - Shizuku.addRequestPermissionResultListener(new Shizuku.OnRequestPermissionResultListener() { - @Override - public void onRequestPermissionResult(int requestCode, int grantResult) { - Shizuku.removeRequestPermissionResultListener(this); - callback.onPermissionResult(grantResult == PackageManager.PERMISSION_GRANTED); + Shizuku.addRequestPermissionResultListener(object : OnRequestPermissionResultListener { + override fun onRequestPermissionResult(requestCode: Int, grantResult: Int) { + Shizuku.removeRequestPermissionResultListener(this) + callback.onPermissionResult(grantResult == PackageManager.PERMISSION_GRANTED) } - }); - Shizuku.requestPermission(SHIZUKU_PERMISSION_REQUEST_ID); + }) + Shizuku.requestPermission(Const.SHIZUKU_PERMISSION_REQUEST_ID) } else { - ActivityResultLauncher permCallback = activity.registerForActivityResult( - new ActivityResultContracts.RequestPermission(), - callback::onPermissionResult - ); + val permCallback = activity.registerForActivityResult( + ActivityResultContracts.RequestPermission() + ) { granted: Boolean -> callback.onPermissionResult(granted) } - permCallback.launch(ShizukuProvider.PERMISSION); + permCallback.launch(ShizukuProvider.PERMISSION) } } - public interface ShizukuPermissionCallback { - void onPermissionResult(boolean granted); + fun getUserServiceArgs(className: Class<*>): UserServiceArgs { + return UserServiceArgs( + ComponentName( + BuildConfig.APPLICATION_ID, + className.name + ) + ) + .daemon(false) + .processNameSuffix("user_service") + .debuggable(BuildConfig.DEBUG) + .version(BuildConfig.VERSION_CODE) } - public static Shizuku.UserServiceArgs getUserServiceArgs(Class className) { - return new Shizuku.UserServiceArgs(new ComponentName( - BuildConfig.APPLICATION_ID, - className.getName() - )) - .daemon(false) - .processNameSuffix("user_service") - .debuggable(BuildConfig.DEBUG) - .version(BuildConfig.VERSION_CODE); + fun bindUserService(userServiceArgs: UserServiceArgs, serviceConnection: ServiceConnection) { + Shizuku.bindUserService(userServiceArgs, serviceConnection) } - public static void bindUserService(Shizuku.UserServiceArgs userServiceArgs, ServiceConnection serviceConnection) { - Shizuku.bindUserService(userServiceArgs, serviceConnection); + fun unbindUserService(userServiceArgs: UserServiceArgs, serviceConnection: ServiceConnection?) { + Shizuku.unbindUserService(userServiceArgs, serviceConnection, true) } - public static void unbindUserService(Shizuku.UserServiceArgs userServiceArgs, ServiceConnection serviceConnection) { - Shizuku.unbindUserService(userServiceArgs, serviceConnection, true); + fun interface ShizukuPermissionCallback { + fun onPermissionResult(granted: Boolean) } } diff --git a/app/src/main/java/com/drdisagree/colorblendr/utils/SystemUtil.kt b/app/src/main/java/com/drdisagree/colorblendr/utils/SystemUtil.kt index b6ebffb..fbbfe2c 100644 --- a/app/src/main/java/com/drdisagree/colorblendr/utils/SystemUtil.kt +++ b/app/src/main/java/com/drdisagree/colorblendr/utils/SystemUtil.kt @@ -1,80 +1,79 @@ -package com.drdisagree.colorblendr.utils; +package com.drdisagree.colorblendr.utils -import static com.drdisagree.colorblendr.common.Const.screenOrientation; +import android.content.Context +import android.content.pm.PackageManager +import android.content.res.Configuration +import android.hardware.Sensor +import android.hardware.SensorEvent +import android.hardware.SensorEventListener +import android.view.Surface +import android.view.WindowManager +import com.drdisagree.colorblendr.ColorBlendr.Companion.appContext +import com.drdisagree.colorblendr.common.Const +import kotlin.math.abs -import android.content.Context; -import android.content.Intent; -import android.content.pm.PackageManager; -import android.content.res.Configuration; -import android.hardware.Sensor; -import android.hardware.SensorEvent; -import android.hardware.SensorEventListener; -import android.net.Uri; -import android.provider.Settings; -import android.view.Display; -import android.view.Surface; -import android.view.WindowManager; +object SystemUtil { + val isDarkMode: Boolean + get() = (appContext!!.resources + .configuration.uiMode and Configuration.UI_MODE_NIGHT_YES) == Configuration.UI_MODE_NIGHT_YES -import com.drdisagree.colorblendr.ColorBlendr; - -public class SystemUtil { - - public static boolean isDarkMode() { - return (ColorBlendr.getAppContext().getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_YES) == Configuration.UI_MODE_NIGHT_YES; - } - - public static boolean isAppInstalled(String package_name) { + fun isAppInstalled(packageName: String): Boolean { try { - ColorBlendr.getAppContext() - .getPackageManager() - .getPackageInfo(package_name, PackageManager.GET_META_DATA); - return true; - } catch (PackageManager.NameNotFoundException ignored) { - return false; + appContext!! + .packageManager + .getPackageInfo(packageName, PackageManager.GET_META_DATA) + return true + } catch (ignored: PackageManager.NameNotFoundException) { + return false } } - @SuppressWarnings("deprecation") - public static int getScreenRotation(Context context) { - final Display display = ((WindowManager) context.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay(); + @Suppress("deprecation") + fun getScreenRotation(context: Context): Int { + val display = + (context.getSystemService(Context.WINDOW_SERVICE) as WindowManager).defaultDisplay - int rotation = switch (display.getRotation()) { - case Surface.ROTATION_0 -> 0; - case Surface.ROTATION_90 -> 90; - case Surface.ROTATION_180 -> 180; - case Surface.ROTATION_270 -> 270; - default -> -1; - }; + var rotation = when (display.rotation) { + Surface.ROTATION_0 -> 0 + Surface.ROTATION_90 -> 90 + Surface.ROTATION_180 -> 180 + Surface.ROTATION_270 -> 270 + else -> -1 + } if (rotation == -1) { - rotation = screenOrientation.get(); + rotation = Const.screenOrientation.get() } - return rotation; + return rotation } - public static final SensorEventListener sensorEventListener = new SensorEventListener() { - @Override - public void onSensorChanged(SensorEvent event) { - if (Math.abs(event.values[1]) > Math.abs(event.values[0]) && Math.abs(event.values[1]) > Math.abs(event.values[2])) { // Vertical + val sensorEventListener: SensorEventListener = object : SensorEventListener { + override fun onSensorChanged(event: SensorEvent) { + if (abs(event.values[1].toDouble()) > abs(event.values[0].toDouble()) && abs( + event.values[1].toDouble() + ) > abs(event.values[2].toDouble()) + ) { // Vertical if (event.values[1] > 0) { - screenOrientation.set(0); // Head Up + Const.screenOrientation.set(0) // Head Up } else { - screenOrientation.set(180); // Head Down + Const.screenOrientation.set(180) // Head Down } - } else if (Math.abs(event.values[0]) > Math.abs(event.values[1]) && Math.abs(event.values[0]) > Math.abs(event.values[2])) { // Horizontal + } else if (abs(event.values[0].toDouble()) > abs(event.values[1].toDouble()) && abs( + event.values[0].toDouble() + ) > abs(event.values[2].toDouble()) + ) { // Horizontal if (event.values[0] > 0) { - screenOrientation.set(90); // Left + Const.screenOrientation.set(90) // Left } else { - screenOrientation.set(270); // Right + Const.screenOrientation.set(270) // Right } } else { // Flat - screenOrientation.set(0); + Const.screenOrientation.set(0) } } - @Override - public void onAccuracyChanged(Sensor sensor, int accuracy) { + override fun onAccuracyChanged(sensor: Sensor, accuracy: Int) { } - }; + } } diff --git a/app/src/main/java/com/drdisagree/colorblendr/utils/WallpaperColorUtil.kt b/app/src/main/java/com/drdisagree/colorblendr/utils/WallpaperColorUtil.kt index 5479a4c..1baadba 100644 --- a/app/src/main/java/com/drdisagree/colorblendr/utils/WallpaperColorUtil.kt +++ b/app/src/main/java/com/drdisagree/colorblendr/utils/WallpaperColorUtil.kt @@ -1,255 +1,271 @@ -package com.drdisagree.colorblendr.utils; - -import static com.drdisagree.colorblendr.common.Const.MONET_SEED_COLOR; -import static com.drdisagree.colorblendr.common.Const.WALLPAPER_COLOR_LIST; - -import android.app.WallpaperManager; -import android.content.Context; -import android.graphics.Bitmap; -import android.graphics.BitmapFactory; -import android.graphics.Canvas; -import android.graphics.drawable.BitmapDrawable; -import android.graphics.drawable.Drawable; -import android.os.Handler; -import android.os.Looper; -import android.os.ParcelFileDescriptor; -import android.util.Log; -import android.util.Size; - -import androidx.annotation.ColorInt; -import androidx.annotation.NonNull; - -import com.drdisagree.colorblendr.ColorBlendr; -import com.drdisagree.colorblendr.common.Const; -import com.drdisagree.colorblendr.config.RPrefs; -import com.drdisagree.colorblendr.utils.monet.quantize.QuantizerCelebi; -import com.drdisagree.colorblendr.utils.monet.score.Score; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.concurrent.Callable; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.Future; - -public class WallpaperColorUtil { - - private static final String TAG = WallpaperColorUtil.class.getSimpleName(); - private static final int SMALL_SIDE = 128; - private static final int MAX_BITMAP_SIZE = 112; - private static final int MAX_WALLPAPER_EXTRACTION_AREA = MAX_BITMAP_SIZE * MAX_BITMAP_SIZE; - - public static void getAndSaveWallpaperColors(Context context) { - if (RPrefs.getInt(MONET_SEED_COLOR, Integer.MIN_VALUE) == Integer.MIN_VALUE && - AppUtil.permissionsGranted(context) +package com.drdisagree.colorblendr.utils + +import android.app.WallpaperManager +import android.content.Context +import android.graphics.Bitmap +import android.graphics.BitmapFactory +import android.graphics.Canvas +import android.graphics.drawable.BitmapDrawable +import android.graphics.drawable.Drawable +import android.os.Handler +import android.os.Looper +import android.os.ParcelFileDescriptor +import android.util.Log +import android.util.Size +import androidx.annotation.ColorInt +import com.drdisagree.colorblendr.ColorBlendr.Companion.appContext +import com.drdisagree.colorblendr.common.Const +import com.drdisagree.colorblendr.config.RPrefs +import com.drdisagree.colorblendr.utils.monet.quantize.QuantizerCelebi +import com.drdisagree.colorblendr.utils.monet.score.Score +import java.io.IOException +import java.util.concurrent.Callable +import java.util.concurrent.ExecutionException +import java.util.concurrent.ExecutorService +import java.util.concurrent.Executors +import java.util.concurrent.Future +import kotlin.math.min +import kotlin.math.sqrt + +object WallpaperColorUtil { + private val TAG: String = WallpaperColorUtil::class.java.simpleName + private const val SMALL_SIDE = 128 + private const val MAX_BITMAP_SIZE = 112 + private const val MAX_WALLPAPER_EXTRACTION_AREA = MAX_BITMAP_SIZE * MAX_BITMAP_SIZE + + fun getAndSaveWallpaperColors(context: Context) { + if (RPrefs.getInt(Const.MONET_SEED_COLOR, Int.MIN_VALUE) == Int.MIN_VALUE && + AppUtil.permissionsGranted(context) ) { - ArrayList wallpaperColors = getWallpaperColors(context); - RPrefs.putString(WALLPAPER_COLOR_LIST, Const.GSON.toJson(wallpaperColors)); - RPrefs.putInt(MONET_SEED_COLOR, wallpaperColors.get(0)); + val wallpaperColors = getWallpaperColors(context) + RPrefs.putString(Const.WALLPAPER_COLOR_LIST, Const.GSON.toJson(wallpaperColors)) + RPrefs.putInt( + Const.MONET_SEED_COLOR, + wallpaperColors[0] + ) } } - public static @ColorInt int getWallpaperColor(Context context) { - return getWallpaperColors(context).get(0); + @ColorInt + fun getWallpaperColor(context: Context): Int { + return getWallpaperColors(context)[0] } - public static ArrayList getWallpaperColors(Context context) { + fun getWallpaperColors(context: Context): ArrayList { if (!AppUtil.permissionsGranted(context)) { - return ColorUtil.getMonetAccentColors(); + return ColorUtil.monetAccentColors } - Future wallpaperFuture = WallpaperLoader.loadWallpaperAsync(context, WallpaperManager.FLAG_SYSTEM, null); + val wallpaperFuture = + WallpaperLoader.loadWallpaperAsync(context, WallpaperManager.FLAG_SYSTEM, null) try { - Bitmap wallpaperBitmap = wallpaperFuture.get(); + val wallpaperBitmap = wallpaperFuture.get() if (wallpaperBitmap != null) { - return WallpaperColorUtil.getWallpaperColors(wallpaperBitmap); + return getWallpaperColors(wallpaperBitmap) } - } catch (ExecutionException | InterruptedException e) { - Log.e(TAG, "Error getting wallpaper color", e); + } catch (e: ExecutionException) { + Log.e(TAG, "Error getting wallpaper color", e) + } catch (e: InterruptedException) { + Log.e(TAG, "Error getting wallpaper color", e) } - return ColorUtil.getMonetAccentColors(); + return ColorUtil.monetAccentColors } - private static class WallpaperLoader { - - private static final String TAG = WallpaperLoader.class.getSimpleName(); - private static final ExecutorService executorService = Executors.newFixedThreadPool(2); - private static final Handler mainHandler = new Handler(Looper.getMainLooper()); - - public interface WallpaperLoadListener { - void onWallpaperLoaded(Bitmap bitmap); - } - - public static Future loadWallpaperAsync(Context context, int which, WallpaperLoadListener listener) { - Callable callable = () -> loadWallpaper(context, which); - Future future = executorService.submit(callable); - - if (listener != null) { - executorService.execute(() -> { - try { - Bitmap result = future.get(); - notifyOnMainThread(listener, result); - } catch (Exception e) { - Log.e(TAG, "Error getting wallpaper bitmap async", e); - } - }); - } - - return future; - } - - private static Bitmap loadWallpaper(Context context, int which) { - try { - ParcelFileDescriptor wallpaperFile; - WallpaperManager wallpaperManager = WallpaperManager.getInstance(context); - - if (wallpaperManager.getWallpaperInfo() != null) { - return drawableToBitmap( - wallpaperManager.getWallpaperInfo().loadThumbnail( - ColorBlendr.getAppContext().getPackageManager() - ) - ); - } - - if (which == WallpaperManager.FLAG_SYSTEM) { - wallpaperFile = wallpaperManager.getWallpaperFile(WallpaperManager.FLAG_SYSTEM); - } else { - wallpaperFile = wallpaperManager.getWallpaperFile(WallpaperManager.FLAG_LOCK); - } - - if (wallpaperFile == null) { - Log.e(TAG, "Error getting wallpaper bitmap: wallpaperFile is null"); - return null; - } - - Bitmap decodeFileDescriptor = createMiniBitmap( - BitmapFactory.decodeFileDescriptor( - wallpaperFile.getFileDescriptor() - ) - ); - wallpaperFile.close(); - - return decodeFileDescriptor; - } catch (IOException e) { - Log.e(TAG, "Error getting wallpaper bitmap", e); - return null; - } - } - - private static void notifyOnMainThread(WallpaperLoadListener listener, Bitmap bitmap) { - mainHandler.post(() -> { - if (listener != null) { - listener.onWallpaperLoaded(bitmap); - } - }); - } - } - - private static Bitmap createMiniBitmap(@NonNull Bitmap bitmap) { - int smallestSide = Math.min(bitmap.getWidth(), bitmap.getHeight()); - float scale = Math.min(1.0f, (float) SMALL_SIDE / smallestSide); - return createMiniBitmap(bitmap, - (int) (scale * bitmap.getWidth()), - (int) (scale * bitmap.getHeight())); + private fun createMiniBitmap(bitmap: Bitmap): Bitmap { + val smallestSide = + min(bitmap.width.toDouble(), bitmap.height.toDouble()).toInt() + val scale = min( + 1.0, + (SMALL_SIDE.toFloat() / smallestSide).toDouble() + ).toFloat() + return createMiniBitmap( + bitmap, + (scale * bitmap.width).toInt(), + (scale * bitmap.height).toInt() + ) } - private static Bitmap createMiniBitmap(@NonNull Bitmap bitmap, int width, int height) { - return Bitmap.createScaledBitmap(bitmap, width, height, false); + private fun createMiniBitmap(bitmap: Bitmap, width: Int, height: Int): Bitmap { + return Bitmap.createScaledBitmap(bitmap, width, height, false) } - private static Size calculateOptimalSize(int width, int height) { - final int requestedArea = width * height; - double scale = 1; + private fun calculateOptimalSize(width: Int, height: Int): Size { + val requestedArea = width * height + var scale = 1.0 if (requestedArea > MAX_WALLPAPER_EXTRACTION_AREA) { - scale = Math.sqrt(MAX_WALLPAPER_EXTRACTION_AREA / (double) requestedArea); + scale = sqrt(MAX_WALLPAPER_EXTRACTION_AREA / requestedArea.toDouble()) } - int newWidth = (int) (width * scale); - int newHeight = (int) (height * scale); + var newWidth = (width * scale).toInt() + var newHeight = (height * scale).toInt() if (newWidth == 0) { - newWidth = 1; + newWidth = 1 } if (newHeight == 0) { - newHeight = 1; + newHeight = 1 } - return new Size(newWidth, newHeight); + return Size(newWidth, newHeight) } - private static ArrayList getWallpaperColors(Bitmap bitmap) { - if (bitmap == null) { - return ColorUtil.getMonetAccentColors(); - } + private fun getWallpaperColors(bitmap: Bitmap?): ArrayList { + var bitmapTemp = bitmap ?: return ColorUtil.monetAccentColors - int bitmapArea = bitmap.getWidth() * bitmap.getHeight(); + val bitmapArea = bitmapTemp.width * bitmapTemp.height if (bitmapArea > MAX_WALLPAPER_EXTRACTION_AREA) { - Size optimalSize = calculateOptimalSize(bitmap.getWidth(), bitmap.getHeight()); - bitmap = Bitmap.createScaledBitmap(bitmap, optimalSize.getWidth(), optimalSize.getHeight(), false); + val optimalSize = calculateOptimalSize(bitmapTemp.width, bitmapTemp.height) + bitmapTemp = + Bitmap.createScaledBitmap(bitmapTemp, optimalSize.width, optimalSize.height, false) } - int width = bitmap.getWidth(); - int height = bitmap.getHeight(); - int[] pixels = new int[width * height]; + val width = bitmapTemp.width + val height = bitmapTemp.height + val pixels = IntArray(width * height) - bitmap.getPixels(pixels, 0, width, 0, 0, width, height); + bitmapTemp.getPixels(pixels, 0, width, 0, 0, width, height) - ArrayList wallpaperColors = new ArrayList<>( - Score.score( - QuantizerCelebi.quantize(pixels, 25) - ) - ); + val wallpaperColors = ArrayList( + Score.score( + QuantizerCelebi.quantize(pixels, 25) + ) + ) - return wallpaperColors.isEmpty() ? ColorUtil.getMonetAccentColors() : wallpaperColors; + return if (wallpaperColors.isEmpty()) ColorUtil.monetAccentColors else wallpaperColors } - public static Bitmap drawableToBitmap(Drawable drawable) { - Bitmap bitmap; + fun drawableToBitmap(drawable: Drawable): Bitmap { + val bitmap: Bitmap - if (drawable instanceof BitmapDrawable bitmapDrawable) { - if (bitmapDrawable.getBitmap() != null) { - return bitmapDrawable.getBitmap(); + if (drawable is BitmapDrawable) { + if (drawable.bitmap != null) { + return drawable.bitmap } } - int intrinsicWidth = drawable.getIntrinsicWidth(); - int intrinsicHeight = drawable.getIntrinsicHeight(); + val intrinsicWidth = drawable.intrinsicWidth + val intrinsicHeight = drawable.intrinsicHeight if (intrinsicWidth <= 0 || intrinsicHeight <= 0) { - ArrayList colors = ColorUtil.getMonetAccentColors(); - int colorCount = colors.size(); + val colors = ColorUtil.monetAccentColors + val colorCount = colors.size - bitmap = Bitmap.createBitmap(colorCount, 1, Bitmap.Config.ARGB_8888); - Canvas canvas = new Canvas(bitmap); + bitmap = Bitmap.createBitmap(colorCount, 1, Bitmap.Config.ARGB_8888) + val canvas = Canvas(bitmap) - int colorIndex = 0; + var colorIndex = 0 if (colorCount > 0) { - int rectWidth = canvas.getWidth() / colorCount; - for (Integer color : colors) { - canvas.save(); - canvas.clipRect(colorIndex * rectWidth, 0, (colorIndex + 1) * rectWidth, canvas.getHeight()); - canvas.drawColor(color); - canvas.restore(); - colorIndex++; + val rectWidth = canvas.width / colorCount + for (color in colors) { + canvas.save() + canvas.clipRect( + colorIndex * rectWidth, + 0, + (colorIndex + 1) * rectWidth, + canvas.height + ) + canvas.drawColor(color) + canvas.restore() + colorIndex++ } } } else { bitmap = createMiniBitmap( - Bitmap.createBitmap( - intrinsicWidth, - intrinsicHeight, - Bitmap.Config.ARGB_8888 + Bitmap.createBitmap( + intrinsicWidth, + intrinsicHeight, + Bitmap.Config.ARGB_8888 + ) + ) + val canvas = Canvas(bitmap) + drawable.setBounds(0, 0, intrinsicWidth, intrinsicHeight) + drawable.draw(canvas) + } + + return bitmap + } + + private object WallpaperLoader { + private val TAG: String = WallpaperLoader::class.java.simpleName + private val executorService: ExecutorService = Executors.newFixedThreadPool(2) + private val mainHandler = Handler(Looper.getMainLooper()) + + fun loadWallpaperAsync( + context: Context?, + which: Int, + listener: WallpaperLoadListener? + ): Future { + val callable = + Callable { loadWallpaper(context, which) } + val future = executorService.submit(callable) + + if (listener != null) { + executorService.execute { + try { + val result = future.get() + notifyOnMainThread(listener, result) + } catch (e: Exception) { + Log.e( + TAG, + "Error getting wallpaper bitmap async", + e + ) + } + } + } + + return future + } + + fun loadWallpaper(context: Context?, which: Int): Bitmap? { + try { + val wallpaperFile: ParcelFileDescriptor? + val wallpaperManager = WallpaperManager.getInstance(context) + + if (wallpaperManager.wallpaperInfo != null) { + return drawableToBitmap( + wallpaperManager.wallpaperInfo.loadThumbnail( + appContext.packageManager + ) ) - ); - Canvas canvas = new Canvas(bitmap); - drawable.setBounds(0, 0, intrinsicWidth, intrinsicHeight); - drawable.draw(canvas); + } + + wallpaperFile = if (which == WallpaperManager.FLAG_SYSTEM) { + wallpaperManager.getWallpaperFile(WallpaperManager.FLAG_SYSTEM) + } else { + wallpaperManager.getWallpaperFile(WallpaperManager.FLAG_LOCK) + } + + if (wallpaperFile == null) { + Log.e(TAG, "Error getting wallpaper bitmap: wallpaperFile is null") + return null + } + + val decodeFileDescriptor = createMiniBitmap( + BitmapFactory.decodeFileDescriptor( + wallpaperFile.fileDescriptor + ) + ) + wallpaperFile.close() + + return decodeFileDescriptor + } catch (e: IOException) { + Log.e(TAG, "Error getting wallpaper bitmap", e) + return null + } } - return bitmap; + fun notifyOnMainThread(listener: WallpaperLoadListener?, bitmap: Bitmap?) { + mainHandler.post { + listener?.onWallpaperLoaded(bitmap) + } + } + + interface WallpaperLoadListener { + fun onWallpaperLoaded(bitmap: Bitmap?) + } } } diff --git a/app/src/main/java/com/drdisagree/colorblendr/utils/annotations/TestingOnly.kt b/app/src/main/java/com/drdisagree/colorblendr/utils/annotations/TestingOnly.kt index dda4c72..31be539 100644 --- a/app/src/main/java/com/drdisagree/colorblendr/utils/annotations/TestingOnly.kt +++ b/app/src/main/java/com/drdisagree/colorblendr/utils/annotations/TestingOnly.kt @@ -1,14 +1,13 @@ -package com.drdisagree.colorblendr.utils.annotations; +package com.drdisagree.colorblendr.utils.annotations -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** +/* * Annotation to mark fields and methods used for testing purposes only. */ -@Retention(RetentionPolicy.SOURCE) -@Target({ElementType.FIELD, ElementType.METHOD}) -public @interface TestingOnly { -} +@Retention(AnnotationRetention.SOURCE) +@Target( + AnnotationTarget.FIELD, + AnnotationTarget.FUNCTION, + AnnotationTarget.PROPERTY_GETTER, + AnnotationTarget.PROPERTY_SETTER +) +annotation class TestingOnly diff --git a/app/src/main/java/com/drdisagree/colorblendr/utils/fabricated/FabricatedOverlayEntry.kt b/app/src/main/java/com/drdisagree/colorblendr/utils/fabricated/FabricatedOverlayEntry.kt index 154c1e4..b7e2771 100644 --- a/app/src/main/java/com/drdisagree/colorblendr/utils/fabricated/FabricatedOverlayEntry.kt +++ b/app/src/main/java/com/drdisagree/colorblendr/utils/fabricated/FabricatedOverlayEntry.kt @@ -1,91 +1,60 @@ -package com.drdisagree.colorblendr.utils.fabricated; +package com.drdisagree.colorblendr.utils.fabricated -import android.os.Build; -import android.os.Parcel; -import android.os.Parcelable; +import android.os.Build +import android.os.Parcel +import android.os.Parcelable -public class FabricatedOverlayEntry implements Parcelable { +open class FabricatedOverlayEntry : Parcelable { + var resourceName: String? + var resourceType: Int + var resourceValue: Int + private var configuration: String? - private String resourceName; - private int resourceType; - private int resourceValue; - private String configuration; - - public FabricatedOverlayEntry(String resourceName, int resourceType, int resourceValue) { - this(resourceName, resourceType, resourceValue, null); - } - - public FabricatedOverlayEntry(String resourceName, int resourceType, int resourceValue, String configuration) { - this.resourceName = resourceName; - this.resourceType = resourceType; - this.resourceValue = resourceValue; - this.configuration = configuration; - } - - public String getResourceName() { - return resourceName; - } - - public void setResourceName(String resourceName) { - this.resourceName = resourceName; + constructor( + resourceName: String?, + resourceType: Int, + resourceValue: Int, + configuration: String? = null + ) { + this.resourceName = resourceName + this.resourceType = resourceType + this.resourceValue = resourceValue + this.configuration = configuration } - public int getResourceType() { - return resourceType; + fun getConfiguration(): String? { + return if (Build.VERSION.SDK_INT < Build.VERSION_CODES.UPSIDE_DOWN_CAKE) null else configuration } - public void setResourceType(int resourceType) { - this.resourceType = resourceType; + fun setConfiguration(configuration: String?) { + this.configuration = configuration } - public int getResourceValue() { - return resourceValue; + protected constructor(`in`: Parcel) { + resourceName = `in`.readString() + resourceType = `in`.readInt() + resourceValue = `in`.readInt() + configuration = `in`.readString() } - public void setResourceValue(int resourceValue) { - this.resourceValue = resourceValue; + override fun describeContents(): Int { + return 0 } - public String getConfiguration() { - return - Build.VERSION.SDK_INT < Build.VERSION_CODES.UPSIDE_DOWN_CAKE ? - null : - configuration; + override fun writeToParcel(dest: Parcel, flags: Int) { + dest.writeString(resourceName) + dest.writeInt(resourceType) + dest.writeInt(resourceValue) + dest.writeString(configuration) } - public void setConfiguration(String configuration) { - this.configuration = configuration; - } - - protected FabricatedOverlayEntry(Parcel in) { - resourceName = in.readString(); - resourceType = in.readInt(); - resourceValue = in.readInt(); - configuration = in.readString(); - } - - public static final Creator CREATOR = new Creator<>() { - @Override - public FabricatedOverlayEntry createFromParcel(Parcel in) { - return new FabricatedOverlayEntry(in); + companion object CREATOR : Parcelable.Creator { + override fun createFromParcel(parcel: Parcel): FabricatedOverlayEntry { + return FabricatedOverlayEntry(parcel) } - @Override - public FabricatedOverlayEntry[] newArray(int size) { - return new FabricatedOverlayEntry[size]; + override fun newArray(size: Int): Array { + return arrayOfNulls(size) } - }; - - @Override - public int describeContents() { - return 0; - } - - @Override - public void writeToParcel(Parcel dest, int flags) { - dest.writeString(resourceName); - dest.writeInt(resourceType); - dest.writeInt(resourceValue); - dest.writeString(configuration); } } diff --git a/app/src/main/java/com/drdisagree/colorblendr/utils/fabricated/FabricatedOverlayResource.kt b/app/src/main/java/com/drdisagree/colorblendr/utils/fabricated/FabricatedOverlayResource.kt index 4ee24ec..57ea269 100644 --- a/app/src/main/java/com/drdisagree/colorblendr/utils/fabricated/FabricatedOverlayResource.kt +++ b/app/src/main/java/com/drdisagree/colorblendr/utils/fabricated/FabricatedOverlayResource.kt @@ -1,133 +1,150 @@ -package com.drdisagree.colorblendr.utils.fabricated; +package com.drdisagree.colorblendr.utils.fabricated -import static com.drdisagree.colorblendr.common.Const.FABRICATED_OVERLAY_SOURCE_PACKAGE; +import android.os.Parcel +import android.os.Parcelable +import android.util.TypedValue +import com.drdisagree.colorblendr.common.Const +import com.drdisagree.colorblendr.utils.fabricated.FabricatedOverlayEntry -import android.os.Parcel; -import android.os.Parcelable; -import android.util.TypedValue; +open class FabricatedOverlayResource : Parcelable { + val overlayName: String + val targetPackage: String + val sourcePackage: String + private var entries: MutableMap = HashMap() -import java.util.HashMap; -import java.util.Map; - -public class FabricatedOverlayResource implements Parcelable { - - public final String overlayName; - public final String targetPackage; - public final String sourcePackage; - - public Map entries = new HashMap<>(); + constructor( + overlayName: String, + targetPackage: String, + sourcePackage: String = Const.FABRICATED_OVERLAY_SOURCE_PACKAGE + ) { + this.overlayName = overlayName + this.targetPackage = targetPackage + this.sourcePackage = sourcePackage + } - public FabricatedOverlayResource(String overlayName, String targetPackage) { - this(overlayName, targetPackage, FABRICATED_OVERLAY_SOURCE_PACKAGE); + fun setInteger(name: String, value: Int) { + this.setInteger(name, value, null) } - public FabricatedOverlayResource(String overlayName, String targetPackage, String sourcePackage) { - this.overlayName = overlayName; - this.targetPackage = targetPackage; - this.sourcePackage = sourcePackage; + @Suppress("SameParameterValue") + private fun setInteger(name: String, value: Int, configuration: String?) { + val formattedName = formatName(name, "integer") + entries[formattedName] = FabricatedOverlayEntry( + formattedName, + TypedValue.TYPE_INT_DEC, + value, + configuration + ) } - public void setInteger(String name, int value) { - this.setInteger(name, value, null); + fun setBoolean(name: String, value: Boolean) { + this.setBoolean(name, value, null) } - public void setInteger(String name, int value, String configuration) { - String formattedName = formatName(name, "integer"); - entries.put(formattedName, new FabricatedOverlayEntry(formattedName, TypedValue.TYPE_INT_DEC, value, configuration)); + @Suppress("SameParameterValue") + private fun setBoolean(name: String, value: Boolean, configuration: String?) { + val formattedName = formatName(name, "bool") + entries[formattedName] = FabricatedOverlayEntry( + formattedName, + TypedValue.TYPE_INT_BOOLEAN, + if (value) 1 else 0, + configuration + ) } - public void setBoolean(String name, boolean value) { - this.setBoolean(name, value, null); + fun setDimension(name: String, value: Int) { + this.setDimension(name, value, null) } - public void setBoolean(String name, boolean value, String configuration) { - String formattedName = formatName(name, "bool"); - entries.put(formattedName, new FabricatedOverlayEntry(formattedName, TypedValue.TYPE_INT_BOOLEAN, value ? 1 : 0, configuration)); + @Suppress("SameParameterValue") + private fun setDimension(name: String, value: Int, configuration: String?) { + val formattedName = formatName(name, "dimen") + entries[formattedName] = FabricatedOverlayEntry( + formattedName, + TypedValue.TYPE_DIMENSION, + value, + configuration + ) } - public void setDimension(String name, int value) { - this.setDimension(name, value, null); + fun setAttribute(name: String, value: Int) { + this.setAttribute(name, value, null) } - public void setDimension(String name, int value, String configuration) { - String formattedName = formatName(name, "dimen"); - entries.put(formattedName, new FabricatedOverlayEntry(formattedName, TypedValue.TYPE_DIMENSION, value, configuration)); + @Suppress("SameParameterValue") + private fun setAttribute(name: String, value: Int, configuration: String?) { + val formattedName = formatName(name, "attr") + entries[formattedName] = FabricatedOverlayEntry( + formattedName, + TypedValue.TYPE_ATTRIBUTE, + value, + configuration + ) } - public void setAttribute(String name, int value) { - this.setAttribute(name, value, null); + fun setColor(name: String, value: Int) { + this.setColor(name, value, null) } - public void setAttribute(String name, int value, String configuration) { - String formattedName = formatName(name, "attr"); - entries.put(formattedName, new FabricatedOverlayEntry(formattedName, TypedValue.TYPE_ATTRIBUTE, value, configuration)); + fun setColor(name: String, value: Int, configuration: String?) { + val formattedName = formatName(name, "color") + entries[formattedName] = FabricatedOverlayEntry( + formattedName, + TypedValue.TYPE_INT_COLOR_ARGB8, + value, + configuration + ) } - public void setColor(String name, int value) { - this.setColor(name, value, null); + fun getColor(name: String): Int { + val formattedName = formatName(name, "color") + val entry = entries[formattedName] + + return entry?.resourceValue ?: throw RuntimeException("No entry found for $formattedName") } - public void setColor(String name, int value, String configuration) { - String formattedName = formatName(name, "color"); - entries.put(formattedName, new FabricatedOverlayEntry(formattedName, TypedValue.TYPE_INT_COLOR_ARGB8, value, configuration)); + fun getEntries(): Map { + return entries } - public int getColor(String name) { - String formattedName = formatName(name, "color"); - FabricatedOverlayEntry entry = entries.get(formattedName); + fun setEntries(entries: MutableMap) { + this.entries = entries + } - if (entry == null) { - throw new IllegalArgumentException("No entry found for " + formattedName); + private fun formatName(name: String, type: String): String { + return if (name.contains(":") && name.contains("/")) { + name } else { - return entry.getResourceValue(); + "$targetPackage:$type/$name" } } - public Map getEntries() { - return entries; + @Suppress("DEPRECATION") + protected constructor(`in`: Parcel) { + overlayName = `in`.readString().toString() + targetPackage = `in`.readString().toString() + sourcePackage = `in`.readString().toString() + `in`.readMap(entries, FabricatedOverlayEntry::class.java.classLoader) } - public void setEntries(Map entries) { - this.entries = entries; + override fun describeContents(): Int { + return 0 } - private String formatName(String name, String type) { - if (name.contains(":") && name.contains("/")) { - return name; - } else { - return targetPackage + ":" + type + "/" + name; - } - } - - protected FabricatedOverlayResource(Parcel in) { - overlayName = in.readString(); - targetPackage = in.readString(); - sourcePackage = in.readString(); - in.readMap(entries, FabricatedOverlayEntry.class.getClassLoader()); + override fun writeToParcel(dest: Parcel, flags: Int) { + dest.writeString(overlayName) + dest.writeString(targetPackage) + dest.writeString(sourcePackage) + dest.writeMap(entries) } - public static final Creator CREATOR = new Creator<>() { - @Override - public FabricatedOverlayResource createFromParcel(Parcel in) { - return new FabricatedOverlayResource(in); + companion object CREATOR : Parcelable.Creator { + override fun createFromParcel(parcel: Parcel): FabricatedOverlayResource { + return FabricatedOverlayResource(parcel) } - @Override - public FabricatedOverlayResource[] newArray(int size) { - return new FabricatedOverlayResource[size]; + override fun newArray(size: Int): Array { + return arrayOfNulls(size) } - }; - - @Override - public int describeContents() { - return 0; - } - - @Override - public void writeToParcel(Parcel dest, int flags) { - dest.writeString(overlayName); - dest.writeString(targetPackage); - dest.writeString(sourcePackage); - dest.writeMap(entries); } } From 1742efbce2bed050dd878d48728dc12d5ea13b0d Mon Sep 17 00:00:00 2001 From: DrDisagree Date: Sat, 17 Aug 2024 17:53:08 +0600 Subject: [PATCH 4/7] Use coroutine for better performance --- app/proguard-rules.pro | 1 - .../colorblendr/extension/MethodInterface.kt | 5 - .../provider/RootConnectionProvider.kt | 128 +++++----- .../colorblendr/service/AutoStartService.kt | 15 +- .../colorblendr/service/BroadcastListener.kt | 239 +++++++++--------- .../colorblendr/service/RootConnection.kt | 3 +- .../colorblendr/service/ShizukuConnection.kt | 39 ++- .../ui/activities/SplashActivity.kt | 64 +++-- .../colorblendr/ui/adapters/AppListAdapter.kt | 22 +- .../ui/fragments/ColorPaletteFragment.kt | 128 +++++----- .../ui/fragments/ColorsFragment.kt | 54 ++-- .../ui/fragments/OnboardingFragment.kt | 62 ++--- .../ui/fragments/OnboardingItem3Fragment.kt | 6 +- .../ui/fragments/PerAppThemeFragment.kt | 31 ++- .../ui/fragments/SettingsFragment.kt | 93 ++++--- .../colorblendr/ui/fragments/ThemeFragment.kt | 76 +++--- .../colorblendr/ui/views/WallColorPreview.kt | 74 +++--- .../ui/widgets/StylePreviewWidget.kt | 53 ++-- .../drdisagree/colorblendr/utils/ColorUtil.kt | 20 +- .../colorblendr/utils/FabricatedUtil.kt | 2 +- .../colorblendr/utils/OverlayManager.kt | 38 ++- .../colorblendr/utils/WallpaperColorUtil.kt | 177 +++++-------- 22 files changed, 665 insertions(+), 665 deletions(-) delete mode 100644 app/src/main/java/com/drdisagree/colorblendr/extension/MethodInterface.kt diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro index 396659c..3163f38 100644 --- a/app/proguard-rules.pro +++ b/app/proguard-rules.pro @@ -18,7 +18,6 @@ -allowaccessmodification # AIDL --keep,allowoptimization,allowobfuscation class com.drdisagree.colorblendr.extension.MethodInterface { *; } -keep,allowoptimization,allowobfuscation class com.drdisagree.colorblendr.service.IRootConnection { *; } -keep,allowoptimization,allowobfuscation class com.drdisagree.colorblendr.service.IShizukuConnection { *; } -keep,allowoptimization,allowobfuscation class com.drdisagree.colorblendr.utils.fabricated.FabricatedOverlayResource { *; } diff --git a/app/src/main/java/com/drdisagree/colorblendr/extension/MethodInterface.kt b/app/src/main/java/com/drdisagree/colorblendr/extension/MethodInterface.kt deleted file mode 100644 index 056a272..0000000 --- a/app/src/main/java/com/drdisagree/colorblendr/extension/MethodInterface.kt +++ /dev/null @@ -1,5 +0,0 @@ -package com.drdisagree.colorblendr.extension - -abstract class MethodInterface { - abstract fun run() -} diff --git a/app/src/main/java/com/drdisagree/colorblendr/provider/RootConnectionProvider.kt b/app/src/main/java/com/drdisagree/colorblendr/provider/RootConnectionProvider.kt index 9f0c83d..f437f6f 100644 --- a/app/src/main/java/com/drdisagree/colorblendr/provider/RootConnectionProvider.kt +++ b/app/src/main/java/com/drdisagree/colorblendr/provider/RootConnectionProvider.kt @@ -4,27 +4,27 @@ import android.content.ComponentName import android.content.Context import android.content.Intent import android.content.ServiceConnection -import android.os.Handler import android.os.IBinder -import android.os.Looper import android.util.Log import android.widget.Toast import com.drdisagree.colorblendr.ColorBlendr.Companion.appContext import com.drdisagree.colorblendr.R import com.drdisagree.colorblendr.common.Const import com.drdisagree.colorblendr.common.Const.workingMethod -import com.drdisagree.colorblendr.extension.MethodInterface import com.drdisagree.colorblendr.service.IRootConnection import com.drdisagree.colorblendr.service.RootConnection import com.topjohnwu.superuser.ipc.RootService +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext import java.util.concurrent.CountDownLatch import java.util.concurrent.TimeUnit -class RootConnectionProvider private constructor(private val context: Context?) : - ServiceConnection { +class RootConnectionProvider private constructor(private val context: Context) : ServiceConnection { - private var methodRunOnSuccess: MethodInterface? = null - private var methodRunOnFailure: MethodInterface? = null + private var onSuccess: (() -> Unit)? = null + private var onFailure: (() -> Unit)? = null private fun bindServiceConnection() { if (isServiceConnected) { @@ -32,10 +32,10 @@ class RootConnectionProvider private constructor(private val context: Context?) return } - Handler(Looper.getMainLooper()).post { + CoroutineScope(Dispatchers.Main).launch { RootService.bind( Intent(context, RootConnection::class.java), - this + this@RootConnectionProvider ) } } @@ -59,72 +59,45 @@ class RootConnectionProvider private constructor(private val context: Context?) bindServiceConnection() } - class ServiceConnectionThread(private val instance: RootConnectionProvider) : Thread() { - override fun run() { + private suspend fun connectService(): Boolean { + return withContext(Dispatchers.IO) { try { - instance.bindServiceConnection() - val success = mServiceConnectionTimer.await(10, TimeUnit.SECONDS) - Handler(Looper.getMainLooper()).post( - if (success) SuccessRunnable(instance) else FailureRunnable(instance) - ) + bindServiceConnection() + mServiceConnectionTimer.await(10, TimeUnit.SECONDS) } catch (e: Exception) { - Handler(Looper.getMainLooper()).post { - Toast.makeText( - appContext, - R.string.something_went_wrong, - Toast.LENGTH_LONG - ).show() - } Log.e(TAG, "Error starting service connection", e) + false } } } - private data class SuccessRunnable(val instance: RootConnectionProvider) : Runnable { - override fun run() { - Handler(Looper.getMainLooper()).post { - if (instance.methodRunOnSuccess != null) { - instance.methodRunOnSuccess!!.run() - } - } - } + fun setOnSuccess(callback: (() -> Unit)?) { + this.onSuccess = callback } - private data class FailureRunnable(val instance: RootConnectionProvider) : Runnable { - override fun run() { - Handler(Looper.getMainLooper()).post { - if (instance.methodRunOnFailure != null) { - instance.methodRunOnFailure!!.run() - } else { - if (workingMethod == Const.WorkMethod.ROOT || - Const.WORKING_METHOD == Const.WorkMethod.ROOT - ) { - Toast.makeText( - appContext, - R.string.root_service_not_found, - Toast.LENGTH_LONG - ).show() - } - } - } - } + fun setOnFailure(callback: (() -> Unit)?) { + this.onFailure = callback } - class Builder(context: Context?) { - private val instance = RootConnectionProvider(context) - - fun runOnSuccess(method: MethodInterface?): Builder { - instance.methodRunOnSuccess = method - return this - } - - fun runOnFailure(method: MethodInterface?): Builder { - instance.methodRunOnFailure = method - return this + private fun handleSuccess() { + CoroutineScope(Dispatchers.Main).launch { + onSuccess?.invoke() } + } - fun run() { - ServiceConnectionThread(instance).start() + private fun handleFailure() { + CoroutineScope(Dispatchers.Main).launch { + onFailure?.invoke() ?: run { + if (workingMethod == Const.WorkMethod.ROOT || + Const.WORKING_METHOD == Const.WorkMethod.ROOT + ) { + Toast.makeText( + appContext, + R.string.root_service_not_found, + Toast.LENGTH_LONG + ).show() + } + } } } @@ -134,12 +107,39 @@ class RootConnectionProvider private constructor(private val context: Context?) private var isServiceConnected = false private val mServiceConnectionTimer = CountDownLatch(1) - @JvmStatic - fun builder(context: Context?): Builder { + fun builder(context: Context): Builder { return Builder(context) } val isNotConnected: Boolean get() = !isServiceConnected } + + class Builder(context: Context) { + private val instance = RootConnectionProvider(context) + + fun onSuccess(callback: () -> Unit): Builder { + instance.setOnSuccess(callback) + return this + } + + fun onFailure(callback: () -> Unit): Builder { + instance.setOnFailure(callback) + return this + } + + fun run() { + CoroutineScope(Dispatchers.IO).launch { + val success = instance.connectService() + + withContext(Dispatchers.Main) { + if (success) { + instance.handleSuccess() + } else { + instance.handleFailure() + } + } + } + } + } } diff --git a/app/src/main/java/com/drdisagree/colorblendr/service/AutoStartService.kt b/app/src/main/java/com/drdisagree/colorblendr/service/AutoStartService.kt index eb13d2c..07c71ad 100644 --- a/app/src/main/java/com/drdisagree/colorblendr/service/AutoStartService.kt +++ b/app/src/main/java/com/drdisagree/colorblendr/service/AutoStartService.kt @@ -22,7 +22,6 @@ import com.drdisagree.colorblendr.ColorBlendr.Companion.rootConnection import com.drdisagree.colorblendr.R import com.drdisagree.colorblendr.common.Const import com.drdisagree.colorblendr.common.Const.workingMethod -import com.drdisagree.colorblendr.extension.MethodInterface import com.drdisagree.colorblendr.provider.RootConnectionProvider import com.drdisagree.colorblendr.provider.ShizukuConnectionProvider import com.drdisagree.colorblendr.utils.ColorUtil.getAccentColor @@ -37,7 +36,9 @@ import java.util.Timer import java.util.TimerTask class AutoStartService : Service() { + private var notificationManager: NotificationManager? = null + override fun onBind(intent: Intent): IBinder? { return null } @@ -51,14 +52,14 @@ class AutoStartService : Service() { showNotification() registerReceivers() - if (BroadcastListener.Companion.lastOrientation == -1) { - BroadcastListener.Companion.lastOrientation = getScreenRotation( + if (BroadcastListener.lastOrientation == -1) { + BroadcastListener.lastOrientation = getScreenRotation( this ) } } - override fun onStartCommand(intent: Intent, flags: Int, startId: Int): Int { + override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { super.onStartCommand(intent, flags, startId) setupSystemUIRestartListener() @@ -179,11 +180,7 @@ class AutoStartService : Service() { RootConnectionProvider.isNotConnected ) { RootConnectionProvider.builder(appContext) - .runOnSuccess(object : MethodInterface() { - override fun run() { - initSystemUIRestartListener() - } - }) + .onSuccess { initSystemUIRestartListener() } .run() } else if (workingMethod == Const.WorkMethod.SHIZUKU && ShizukuConnectionProvider.isNotConnected && diff --git a/app/src/main/java/com/drdisagree/colorblendr/service/BroadcastListener.kt b/app/src/main/java/com/drdisagree/colorblendr/service/BroadcastListener.kt index c67d388..78b6cf7 100644 --- a/app/src/main/java/com/drdisagree/colorblendr/service/BroadcastListener.kt +++ b/app/src/main/java/com/drdisagree/colorblendr/service/BroadcastListener.kt @@ -3,8 +3,6 @@ package com.drdisagree.colorblendr.service import android.content.BroadcastReceiver import android.content.Context import android.content.Intent -import android.os.Handler -import android.os.Looper import android.util.Log import androidx.localbroadcastmanager.content.LocalBroadcastManager import com.drdisagree.colorblendr.common.Const @@ -23,7 +21,6 @@ import com.drdisagree.colorblendr.config.RPrefs.getLong import com.drdisagree.colorblendr.config.RPrefs.putInt import com.drdisagree.colorblendr.config.RPrefs.putLong import com.drdisagree.colorblendr.config.RPrefs.putString -import com.drdisagree.colorblendr.extension.MethodInterface import com.drdisagree.colorblendr.provider.RootConnectionProvider import com.drdisagree.colorblendr.utils.AppUtil.permissionsGranted import com.drdisagree.colorblendr.utils.OverlayManager.applyFabricatedColors @@ -31,6 +28,11 @@ import com.drdisagree.colorblendr.utils.OverlayManager.applyFabricatedColorsPerA import com.drdisagree.colorblendr.utils.OverlayManager.unregisterFabricatedOverlay import com.drdisagree.colorblendr.utils.SystemUtil.getScreenRotation import com.drdisagree.colorblendr.utils.WallpaperColorUtil.getWallpaperColors +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.delay +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext import kotlin.math.abs class BroadcastListener : BroadcastReceiver() { @@ -44,30 +46,68 @@ class BroadcastListener : BroadcastReceiver() { val currentOrientation = getScreenRotation(context) - if (Intent.ACTION_BOOT_COMPLETED == intent.action || - Intent.ACTION_LOCKED_BOOT_COMPLETED == intent.action - ) { - // Start background service on boot - if (permissionsGranted(context) && AutoStartService.isServiceNotRunning) { - context.startForegroundService(Intent(context, AutoStartService::class.java)) - } + CoroutineScope(Dispatchers.Main).launch { + when (intent.action) { + Intent.ACTION_BOOT_COMPLETED, + Intent.ACTION_LOCKED_BOOT_COMPLETED -> { + handleBootCompleted(context) + } + + Intent.ACTION_WALLPAPER_CHANGED -> { + handleWallpaperChanged(context) + } + + Intent.ACTION_CONFIGURATION_CHANGED -> { + if (lastOrientation == currentOrientation) { + validateRootAndUpdateColors(context) { + updateAllColors(context) + } + } - validateRootAndUpdateColors(context, object : MethodInterface() { - override fun run() { - cooldownTime = 10000 - Handler(Looper.getMainLooper()).postDelayed({ - cooldownTime = 5000 - }, 10000) - updateAllColors(context) + lastOrientation = currentOrientation } - }) + + Intent.ACTION_PACKAGE_REMOVED -> { + handlePackageRemoved(context, intent) + } + + Intent.ACTION_MY_PACKAGE_REPLACED, + Intent.ACTION_PACKAGE_REPLACED -> { + handlePackageReplaced(context, intent) + } + } + + if (intent.action in listOf( + Intent.ACTION_PACKAGE_ADDED, + Intent.ACTION_PACKAGE_REMOVED, + Intent.ACTION_WALLPAPER_CHANGED + ) + ) { + LocalBroadcastManager.getInstance(context).sendBroadcast(intent) + } } + } - // Update wallpaper colors on wallpaper change - if (Intent.ACTION_WALLPAPER_CHANGED == intent.action && - permissionsGranted(context) - ) { - val wallpaperColors = getWallpaperColors(context) + private suspend fun handleBootCompleted(context: Context) { + if (permissionsGranted(context) && AutoStartService.isServiceNotRunning) { + context.startForegroundService(Intent(context, AutoStartService::class.java)) + } + + validateRootAndUpdateColors(context) { + cooldownTime = 10000 + CoroutineScope(Dispatchers.Main).launch { + delay(10000) + cooldownTime = 5000 + } + updateAllColors(context) + } + } + + private suspend fun handleWallpaperChanged(context: Context) { + if (permissionsGranted(context)) { + val wallpaperColors = withContext(Dispatchers.IO) { + getWallpaperColors(context) + } putString(WALLPAPER_COLOR_LIST, Const.GSON.toJson(wallpaperColors)) if (!getBoolean(MONET_SEED_COLOR_ENABLED, false)) { @@ -75,113 +115,82 @@ class BroadcastListener : BroadcastReceiver() { } } - // Update fabricated colors on wallpaper change - if (Intent.ACTION_WALLPAPER_CHANGED == intent.action || - (Intent.ACTION_CONFIGURATION_CHANGED == intent.action && - lastOrientation == currentOrientation) - ) { - validateRootAndUpdateColors(context, object : MethodInterface() { - override fun run() { - updateAllColors(context) - } - }) - } else if (lastOrientation != currentOrientation) { - lastOrientation = currentOrientation + validateRootAndUpdateColors(context) { + updateAllColors(context) } + } - if (Intent.ACTION_PACKAGE_REMOVED == intent.action) { - // Remove fabricated colors for uninstalled apps - val data = intent.data - - if (data != null) { - val packageName = data.schemeSpecificPart - val selectedApps: HashMap = selectedFabricatedApps - - if (selectedApps.containsKey(packageName) && java.lang.Boolean.TRUE == selectedApps[packageName]) { - selectedApps.remove(packageName) - saveSelectedFabricatedApps(selectedApps) - - validateRootAndUpdateColors(context, object : MethodInterface() { - override fun run() { - unregisterFabricatedOverlay( - kotlin.String.format( - FABRICATED_OVERLAY_NAME_APPS, - packageName - ) - ) - } - }) + private suspend fun handlePackageRemoved(context: Context, intent: Intent) { + intent.data?.schemeSpecificPart?.let { packageName -> + val selectedApps: HashMap = selectedFabricatedApps + + if (selectedApps.containsKey(packageName) && selectedApps[packageName] == true) { + selectedApps.remove(packageName) + saveSelectedFabricatedApps(selectedApps) + + validateRootAndUpdateColors(context) { + unregisterFabricatedOverlay( + String.format( + FABRICATED_OVERLAY_NAME_APPS, + packageName + ) + ) } } - } else if (Intent.ACTION_MY_PACKAGE_REPLACED == intent.action) { - // Update fabricated colors for updated app - validateRootAndUpdateColors(context, object : MethodInterface() { - override fun run() { - updateAllColors(context) - } - }) - } else if (Intent.ACTION_PACKAGE_REPLACED == intent.action) { - // Update fabricated colors for updated app - val data = intent.data - - if (data != null) { - val packageName = data.schemeSpecificPart - val selectedApps = selectedFabricatedApps - - if (selectedApps.containsKey(packageName) && java.lang.Boolean.TRUE == selectedApps[packageName]) { - validateRootAndUpdateColors(context, object : MethodInterface() { - override fun run() { - applyFabricatedColorsPerApp(context, packageName, null) - } - }) + } + } + + private suspend fun handlePackageReplaced(context: Context, intent: Intent) { + intent.data?.schemeSpecificPart?.let { packageName -> + val selectedApps = selectedFabricatedApps + + if (selectedApps.containsKey(packageName) && selectedApps[packageName] == true) { + validateRootAndUpdateColors(context) { + applyFabricatedColorsPerApp(context, packageName, null) } } } + } - if (Intent.ACTION_PACKAGE_ADDED == intent.action || - Intent.ACTION_PACKAGE_REMOVED == intent.action || - Intent.ACTION_WALLPAPER_CHANGED == intent.action - ) { - LocalBroadcastManager.getInstance(context).sendBroadcast(intent) + private suspend fun validateRootAndUpdateColors(context: Context, method: suspend () -> Unit) { + if (workingMethod == Const.WorkMethod.ROOT && RootConnectionProvider.isNotConnected) { + RootConnectionProvider + .builder(context) + .onSuccess { + CoroutineScope(Dispatchers.Main).launch { + method() + } + } + .run() + } else { + method() } } - companion object { - private val TAG: String = BroadcastListener::class.java.simpleName - var lastOrientation: Int = -1 - private var cooldownTime: Long = 5000 - - private fun validateRootAndUpdateColors(context: Context, method: MethodInterface) { - if (workingMethod == Const.WorkMethod.ROOT && - RootConnectionProvider.isNotConnected - ) { - RootConnectionProvider.builder(context) - .runOnSuccess(method) - .run() - } else { - method.run() - } + private fun updateAllColors(context: Context) { + if (!getBoolean(THEMING_ENABLED, true) && !getBoolean(SHIZUKU_THEMING_ENABLED, true)) { + return } - private fun updateAllColors(context: Context) { - if (!getBoolean(THEMING_ENABLED, true) && !getBoolean(SHIZUKU_THEMING_ENABLED, true)) { - return - } + if (abs( + (getLong( + MONET_LAST_UPDATED, + 0 + ) - System.currentTimeMillis()).toDouble() + ) >= cooldownTime + ) { + putLong(MONET_LAST_UPDATED, System.currentTimeMillis()) - if (abs( - (getLong( - MONET_LAST_UPDATED, - 0 - ) - System.currentTimeMillis()).toDouble() - ) >= cooldownTime - ) { - putLong(MONET_LAST_UPDATED, System.currentTimeMillis()) - Handler(Looper.getMainLooper()).postDelayed({ - applyFabricatedColors( - context - ) - }, 500) + CoroutineScope(Dispatchers.Main).launch { + delay(500) + applyFabricatedColors(context) } } } + + companion object { + private val TAG: String = BroadcastListener::class.java.simpleName + var lastOrientation: Int = -1 + private var cooldownTime: Long = 5000 + } } diff --git a/app/src/main/java/com/drdisagree/colorblendr/service/RootConnection.kt b/app/src/main/java/com/drdisagree/colorblendr/service/RootConnection.kt index 4df7011..34b192c 100644 --- a/app/src/main/java/com/drdisagree/colorblendr/service/RootConnection.kt +++ b/app/src/main/java/com/drdisagree/colorblendr/service/RootConnection.kt @@ -20,7 +20,6 @@ import android.util.Log import com.drdisagree.colorblendr.common.Const.FABRICATED_OVERLAY_NAME_SYSTEM import com.drdisagree.colorblendr.common.Const.FABRICATED_OVERLAY_SOURCE_PACKAGE import com.drdisagree.colorblendr.common.Const.SYSTEMUI_PACKAGE -import com.drdisagree.colorblendr.extension.MethodInterface import com.drdisagree.colorblendr.utils.fabricated.FabricatedOverlayResource import com.topjohnwu.superuser.Shell import com.topjohnwu.superuser.internal.Utils @@ -405,7 +404,7 @@ class RootConnection : RootService() { private var omtbClass: Class<*>? = null private var SystemUI_UID = -1 private var mActivityManager: IActivityManager? = null - private val onSystemUIRestartedListener: MethodInterface? = null + private val onSystemUiRestart: (() -> Unit)? = null @SuppressLint("StaticFieldLeak", "RestrictedApi") private val context: Context = Utils.getContext() diff --git a/app/src/main/java/com/drdisagree/colorblendr/service/ShizukuConnection.kt b/app/src/main/java/com/drdisagree/colorblendr/service/ShizukuConnection.kt index a03186f..991536d 100644 --- a/app/src/main/java/com/drdisagree/colorblendr/service/ShizukuConnection.kt +++ b/app/src/main/java/com/drdisagree/colorblendr/service/ShizukuConnection.kt @@ -51,31 +51,28 @@ class ShizukuConnection : IShizukuConnection.Stub { @get:Throws(JSONException::class) private val originalSettings: JSONObject get() { - val currentSettings = currentSettings - val jsonObject = JSONObject(currentSettings) + return JSONObject(currentSettings).apply { + val keysToRemove = arrayOf( + ThemeOverlayPackage.THEME_STYLE, + ThemeOverlayPackage.COLOR_SOURCE, + ThemeOverlayPackage.SYSTEM_PALETTE + ) - val keysToRemove = arrayOf( - ThemeOverlayPackage.THEME_STYLE, - ThemeOverlayPackage.COLOR_SOURCE, - ThemeOverlayPackage.SYSTEM_PALETTE - ) + for (key in keysToRemove) { + remove(key) + } - for (key in keysToRemove) { - jsonObject.remove(key) - } + if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.S_V2) { + remove(ThemeOverlayPackage.ACCENT_COLOR) + } - if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.S_V2) { - jsonObject.remove(ThemeOverlayPackage.ACCENT_COLOR) + putOpt(ThemeOverlayPackage.COLOR_BOTH, "0") + putOpt(ThemeOverlayPackage.COLOR_SOURCE, "home_wallpaper") + putOpt( + ThemeOverlayPackage.APPLIED_TIMESTAMP, + System.currentTimeMillis() + ) } - - jsonObject.putOpt(ThemeOverlayPackage.COLOR_BOTH, "0") - jsonObject.putOpt(ThemeOverlayPackage.COLOR_SOURCE, "home_wallpaper") - jsonObject.putOpt( - ThemeOverlayPackage.APPLIED_TIMESTAMP, - System.currentTimeMillis() - ) - - return jsonObject } companion object { diff --git a/app/src/main/java/com/drdisagree/colorblendr/ui/activities/SplashActivity.kt b/app/src/main/java/com/drdisagree/colorblendr/ui/activities/SplashActivity.kt index a222adf..0d91b2a 100644 --- a/app/src/main/java/com/drdisagree/colorblendr/ui/activities/SplashActivity.kt +++ b/app/src/main/java/com/drdisagree/colorblendr/ui/activities/SplashActivity.kt @@ -11,17 +11,19 @@ import com.drdisagree.colorblendr.common.Const import com.drdisagree.colorblendr.common.Const.FIRST_RUN import com.drdisagree.colorblendr.common.Const.workingMethod import com.drdisagree.colorblendr.config.RPrefs.getBoolean -import com.drdisagree.colorblendr.extension.MethodInterface import com.drdisagree.colorblendr.provider.RootConnectionProvider.Companion.builder import com.drdisagree.colorblendr.provider.ShizukuConnectionProvider import com.drdisagree.colorblendr.service.ShizukuConnection -import com.drdisagree.colorblendr.utils.FabricatedUtil.getAndSaveSelectedFabricatedApps +import com.drdisagree.colorblendr.utils.FabricatedUtil.updateFabricatedAppList import com.drdisagree.colorblendr.utils.ShizukuUtil.bindUserService import com.drdisagree.colorblendr.utils.ShizukuUtil.getUserServiceArgs import com.drdisagree.colorblendr.utils.ShizukuUtil.hasShizukuPermission import com.drdisagree.colorblendr.utils.ShizukuUtil.isShizukuAvailable -import com.drdisagree.colorblendr.utils.WallpaperColorUtil.getAndSaveWallpaperColors +import com.drdisagree.colorblendr.utils.WallpaperColorUtil.updateWallpaperColorList import com.google.android.material.color.DynamicColors +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch import java.util.concurrent.CountDownLatch import java.util.concurrent.atomic.AtomicBoolean @@ -34,27 +36,47 @@ class SplashActivity : AppCompatActivity() { val success = AtomicBoolean(false) val countDownLatch = CountDownLatch(1) + handleInitialization(success, countDownLatch) + + try { + countDownLatch.await() + } catch (ignored: InterruptedException) { + } + + startActivity( + Intent( + this@SplashActivity, + MainActivity::class.java + ).apply { + putExtra("success", success.get()) + } + ) + finish() + } + + private fun handleInitialization( + success: AtomicBoolean, + countDownLatch: CountDownLatch + ) { if (!getBoolean(FIRST_RUN, true) && workingMethod != Const.WorkMethod.NULL ) { if (workingMethod == Const.WorkMethod.ROOT) { builder(appContext) - .runOnSuccess(object : MethodInterface() { - override fun run() { - getAndSaveWallpaperColors(applicationContext) - getAndSaveSelectedFabricatedApps(applicationContext) + .onSuccess { + CoroutineScope(Dispatchers.IO).launch { + updateWallpaperColorList(applicationContext) + updateFabricatedAppList(applicationContext) success.set(true) keepShowing = false countDownLatch.countDown() } - }) - .runOnFailure(object : MethodInterface() { - override fun run() { - success.set(false) - keepShowing = false - countDownLatch.countDown() - } - }) + } + .onFailure { + success.set(false) + keepShowing = false + countDownLatch.countDown() + } .run() } else if (workingMethod == Const.WorkMethod.SHIZUKU) { if (isShizukuAvailable && hasShizukuPermission(this)) { @@ -73,18 +95,6 @@ class SplashActivity : AppCompatActivity() { keepShowing = false countDownLatch.countDown() } - - try { - countDownLatch.await() - } catch (ignored: InterruptedException) { - } - val intent = Intent( - this@SplashActivity, - MainActivity::class.java - ) - intent.putExtra("success", success.get()) - startActivity(intent) - finish() } override fun onCreate(savedInstanceState: Bundle?) { diff --git a/app/src/main/java/com/drdisagree/colorblendr/ui/adapters/AppListAdapter.kt b/app/src/main/java/com/drdisagree/colorblendr/ui/adapters/AppListAdapter.kt index d548b13..e5e5f23 100644 --- a/app/src/main/java/com/drdisagree/colorblendr/ui/adapters/AppListAdapter.kt +++ b/app/src/main/java/com/drdisagree/colorblendr/ui/adapters/AppListAdapter.kt @@ -21,6 +21,9 @@ import com.drdisagree.colorblendr.utils.ColorUtil.getColorFromAttribute import com.drdisagree.colorblendr.utils.OverlayManager.applyFabricatedColorsPerApp import com.drdisagree.colorblendr.utils.OverlayManager.unregisterFabricatedOverlay import com.google.android.material.card.MaterialCardView +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch class AppListAdapter(private val appList: List) : RecyclerView.Adapter() { @@ -62,15 +65,18 @@ class AppListAdapter(private val appList: List) : selectedApps[appInfo.packageName] = !isSelected saveSelectedFabricatedApps(selectedApps) - if (isSelected) { - unregisterFabricatedOverlay( - String.format( - FABRICATED_OVERLAY_NAME_APPS, - appInfo.packageName + + CoroutineScope(Dispatchers.Main).launch { + if (isSelected) { + unregisterFabricatedOverlay( + String.format( + FABRICATED_OVERLAY_NAME_APPS, + appInfo.packageName + ) ) - ) - } else { - applyFabricatedColorsPerApp(context!!, appInfo.packageName, null) + } else { + applyFabricatedColorsPerApp(context!!, appInfo.packageName, null) + } } } diff --git a/app/src/main/java/com/drdisagree/colorblendr/ui/fragments/ColorPaletteFragment.kt b/app/src/main/java/com/drdisagree/colorblendr/ui/fragments/ColorPaletteFragment.kt index 3f0c8c0..e3c8791 100644 --- a/app/src/main/java/com/drdisagree/colorblendr/ui/fragments/ColorPaletteFragment.kt +++ b/app/src/main/java/com/drdisagree/colorblendr/ui/fragments/ColorPaletteFragment.kt @@ -5,19 +5,15 @@ import android.content.ClipData import android.content.ClipboardManager import android.content.Context import android.os.Bundle -import android.os.Handler -import android.os.Looper import android.util.Log import android.util.TypedValue import android.view.Gravity import android.view.LayoutInflater import android.view.View -import android.view.View.OnLongClickListener import android.view.ViewGroup import android.widget.LinearLayout import android.widget.TextView import androidx.fragment.app.Fragment -import androidx.lifecycle.Observer import androidx.lifecycle.ViewModelProvider import com.drdisagree.colorblendr.R import com.drdisagree.colorblendr.common.Const @@ -41,15 +37,18 @@ import com.drdisagree.colorblendr.ui.viewmodels.SharedViewModel import com.drdisagree.colorblendr.utils.ColorSchemeUtil.stringToEnumMonetStyle import com.drdisagree.colorblendr.utils.ColorUtil import com.drdisagree.colorblendr.utils.ColorUtil.calculateTextColor -import com.drdisagree.colorblendr.utils.ColorUtil.generateModifiedColors import com.drdisagree.colorblendr.utils.ColorUtil.getSystemColors import com.drdisagree.colorblendr.utils.ColorUtil.intToHexColor import com.drdisagree.colorblendr.utils.MiscUtil.convertListToIntArray import com.drdisagree.colorblendr.utils.MiscUtil.setToolbarTitle import com.drdisagree.colorblendr.utils.OverlayManager.applyFabricatedColors import com.google.android.material.snackbar.Snackbar +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.delay +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext import me.jfenn.colorpickerdialog.dialogs.ColorPickerDialog -import me.jfenn.colorpickerdialog.interfaces.OnColorPickedListener import me.jfenn.colorpickerdialog.views.picker.ImagePickerView class ColorPaletteFragment : Fragment() { @@ -146,62 +145,56 @@ class ColorPaletteFragment : Fragment() { @SuppressLint("SetTextI18n") private fun initColorTablePreview(colorTableRows: Array) { - Thread { + CoroutineScope(Dispatchers.IO).launch { try { val palette: ArrayList>? = generateModifiedColors() + val systemColors: Array = if (palette == null) { + getSystemColors(requireContext()) + } else { + convertListToIntArray(palette) + } - val systemColors: Array = - if (palette == null) { - getSystemColors(requireContext()) - } else { - convertListToIntArray(palette) - } - - for (i in colorTableRows.indices) { - for (j in 0 until colorTableRows[i].childCount) { - colorTableRows[i].getChildAt(j).background - .setTint(systemColors[i][j]) - colorTableRows[i].getChildAt(j).tag = systemColors[i][j] + withContext(Dispatchers.Main) { + for (i in colorTableRows.indices) { + for (j in 0 until colorTableRows[i].childCount) { + val childView = colorTableRows[i].getChildAt(j) + childView.background.setTint(systemColors[i][j]) + childView.tag = systemColors[i][j] - if (getInt(colorNames[i][j], Int.MIN_VALUE) != Int.MIN_VALUE) { - colorTableRows[i].getChildAt(j).background - .setTint(getInt(colorNames[i][j], 0)) - } + if (getInt(colorNames[i][j], Int.MIN_VALUE) != Int.MIN_VALUE) { + childView.background.setTint(getInt(colorNames[i][j], 0)) + } - val textView = TextView(requireContext()) - textView.text = colorCodes[j].toString() - textView.rotation = 270f - textView.setTextColor(calculateTextColor(systemColors[i][j])) - textView.setTextSize(TypedValue.COMPLEX_UNIT_SP, 10f) - textView.setAlpha(0.8f) - textView.setMaxLines(1) - textView.setSingleLine(true) - textView.setAutoSizeTextTypeUniformWithConfiguration( - 1, - 20, - 1, - TypedValue.COMPLEX_UNIT_SP - ) + val textView = TextView(requireContext()).apply { + text = colorCodes[j].toString() + rotation = 270f + setTextColor(calculateTextColor(systemColors[i][j])) + setTextSize(TypedValue.COMPLEX_UNIT_SP, 10f) + alpha = 0.8f + setMaxLines(1) + setSingleLine(true) + setAutoSizeTextTypeUniformWithConfiguration( + 1, + 20, + 1, + TypedValue.COMPLEX_UNIT_SP + ) + } - val finalI: Int = i - val finalJ: Int = j - requireActivity().runOnUiThread { - (colorTableRows[finalI].getChildAt(finalJ) as ViewGroup) - .addView(textView) - (colorTableRows[finalI].getChildAt(finalJ) as LinearLayout).gravity = + (colorTableRows[i].getChildAt(j) as ViewGroup).addView(textView) + (colorTableRows[i].getChildAt(j) as LinearLayout).gravity = Gravity.CENTER } } - } - requireActivity().runOnUiThread { - enablePaletteOnClickListener( - colorTableRows - ) + // Enable click listeners on the main thread + enablePaletteOnClickListener(colorTableRows) } - } catch (ignored: Exception) { + } catch (e: Exception) { + // Handle any exceptions (e.g., logging) + Log.e(TAG, "Error initializing color table preview", e) } - }.start() + } } private fun enablePaletteOnClickListener(colorTableRows: Array) { @@ -264,13 +257,19 @@ class ColorPaletteFragment : Fragment() { .setTextColor(calculateTextColor(color)) putInt(colorNames[finalI][finalJ], color) - putLong(MONET_LAST_UPDATED, System.currentTimeMillis()) - Handler(Looper.getMainLooper()).postDelayed({ - try { - applyFabricatedColors(requireContext()) - } catch (ignored: Exception) { + CoroutineScope(Dispatchers.Main).launch { + putLong( + MONET_LAST_UPDATED, + System.currentTimeMillis() + ) + delay(200) + withContext(Dispatchers.IO) { + try { + applyFabricatedColors(requireContext()) + } catch (ignored: Exception) { + } } - }, 200) + } } } .show( @@ -289,9 +288,17 @@ class ColorPaletteFragment : Fragment() { clearPref(colorNames[finalI][finalJ]) - try { - applyFabricatedColors(requireContext()) - } catch (ignored: Exception) { + CoroutineScope(Dispatchers.Main).launch { + putLong( + MONET_LAST_UPDATED, + System.currentTimeMillis() + ) + withContext(Dispatchers.IO) { + try { + applyFabricatedColors(requireContext()) + } catch (ignored: Exception) { + } + } } true } @@ -301,8 +308,7 @@ class ColorPaletteFragment : Fragment() { private fun generateModifiedColors(): ArrayList>? { try { - return generateModifiedColors( - requireContext(), + return ColorUtil.generateModifiedColors( stringToEnumMonetStyle( requireContext(), RPrefs.getString(MONET_STYLE, getString(R.string.monet_tonalspot))!! diff --git a/app/src/main/java/com/drdisagree/colorblendr/ui/fragments/ColorsFragment.kt b/app/src/main/java/com/drdisagree/colorblendr/ui/fragments/ColorsFragment.kt index 90d0005..833ff25 100644 --- a/app/src/main/java/com/drdisagree/colorblendr/ui/fragments/ColorsFragment.kt +++ b/app/src/main/java/com/drdisagree/colorblendr/ui/fragments/ColorsFragment.kt @@ -6,14 +6,11 @@ import android.content.Intent import android.content.IntentFilter import android.graphics.Color import android.os.Bundle -import android.os.Handler -import android.os.Looper import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import android.widget.LinearLayout import androidx.fragment.app.Fragment -import androidx.lifecycle.Observer import androidx.lifecycle.ViewModelProvider import androidx.localbroadcastmanager.content.LocalBroadcastManager import com.drdisagree.colorblendr.R @@ -35,12 +32,14 @@ import com.drdisagree.colorblendr.ui.views.WallColorPreview import com.drdisagree.colorblendr.utils.ColorUtil.monetAccentColors import com.drdisagree.colorblendr.utils.MiscUtil.setToolbarTitle import com.drdisagree.colorblendr.utils.OverlayManager.applyFabricatedColors -import com.drdisagree.colorblendr.utils.WallpaperColorUtil.getWallpaperColor import com.google.android.material.button.MaterialButtonToggleGroup -import com.google.android.material.button.MaterialButtonToggleGroup.OnButtonCheckedListener import com.google.gson.reflect.TypeToken +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.delay +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext import me.jfenn.colorpickerdialog.dialogs.ColorPickerDialog -import me.jfenn.colorpickerdialog.interfaces.OnColorPickedListener import me.jfenn.colorpickerdialog.views.picker.ImagePickerView import java.util.Arrays import java.util.stream.Collectors @@ -80,14 +79,9 @@ class ColorsFragment : Fragment() { setToolbarTitle(requireContext(), R.string.app_name, false, binding.header.toolbar) - monetSeedColor = intArrayOf( - getInt( - MONET_SEED_COLOR, - getWallpaperColor(requireContext()) - ) - ) + monetSeedColor = intArrayOf(getInt(MONET_SEED_COLOR, 0)) - return binding.getRoot() + return binding.root } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { @@ -140,13 +134,20 @@ class ColorsFragment : Fragment() { monetSeedColor[0] = color binding.seedColorPicker.previewColor = color putInt(MONET_SEED_COLOR, monetSeedColor[0]) - putLong(MONET_LAST_UPDATED, System.currentTimeMillis()) - Handler(Looper.getMainLooper()).postDelayed({ - try { - applyFabricatedColors(requireContext()) - } catch (ignored: Exception) { + + CoroutineScope(Dispatchers.Main).launch { + putLong( + MONET_LAST_UPDATED, + System.currentTimeMillis() + ) + delay(300) + withContext(Dispatchers.IO) { + try { + applyFabricatedColors(requireContext()) + } catch (ignored: Exception) { + } } - }, 300) + } } } .show(getChildFragmentManager(), "seedColorPicker") @@ -248,8 +249,19 @@ class ColorsFragment : Fragment() { ) putBoolean(MONET_SEED_COLOR_ENABLED, !isWallpaperColors) binding.seedColorPicker.previewColor = colorPreview.tag as Int - putLong(MONET_LAST_UPDATED, System.currentTimeMillis()) - applyFabricatedColors(requireContext()) + + CoroutineScope(Dispatchers.Main).launch { + putLong( + MONET_LAST_UPDATED, + System.currentTimeMillis() + ) + withContext(Dispatchers.IO) { + try { + applyFabricatedColors(requireContext()) + } catch (ignored: Exception) { + } + } + } } binding.colorsContainer.addView(colorPreview) diff --git a/app/src/main/java/com/drdisagree/colorblendr/ui/fragments/OnboardingFragment.kt b/app/src/main/java/com/drdisagree/colorblendr/ui/fragments/OnboardingFragment.kt index c8ab247..c98cb11 100644 --- a/app/src/main/java/com/drdisagree/colorblendr/ui/fragments/OnboardingFragment.kt +++ b/app/src/main/java/com/drdisagree/colorblendr/ui/fragments/OnboardingFragment.kt @@ -9,31 +9,28 @@ import android.view.animation.Animation import android.widget.Toast import androidx.activity.OnBackPressedCallback import androidx.fragment.app.Fragment +import androidx.lifecycle.lifecycleScope import androidx.viewpager2.widget.ViewPager2 import com.drdisagree.colorblendr.ColorBlendr.Companion.appContext import com.drdisagree.colorblendr.R import com.drdisagree.colorblendr.common.Const import com.drdisagree.colorblendr.common.Const.FIRST_RUN -import com.drdisagree.colorblendr.common.Const.WALLPAPER_COLOR_LIST import com.drdisagree.colorblendr.common.Const.saveWorkingMethod import com.drdisagree.colorblendr.config.RPrefs.putBoolean -import com.drdisagree.colorblendr.config.RPrefs.putString import com.drdisagree.colorblendr.databinding.FragmentOnboardingBinding -import com.drdisagree.colorblendr.extension.MethodInterface -import com.drdisagree.colorblendr.provider.RootConnectionProvider.Companion.builder +import com.drdisagree.colorblendr.provider.RootConnectionProvider import com.drdisagree.colorblendr.provider.ShizukuConnectionProvider import com.drdisagree.colorblendr.service.ShizukuConnection import com.drdisagree.colorblendr.ui.activities.MainActivity import com.drdisagree.colorblendr.ui.adapters.OnboardingAdapter -import com.drdisagree.colorblendr.utils.AppUtil.hasStoragePermission import com.drdisagree.colorblendr.utils.AppUtil.permissionsGranted -import com.drdisagree.colorblendr.utils.FabricatedUtil.getAndSaveSelectedFabricatedApps +import com.drdisagree.colorblendr.utils.FabricatedUtil.updateFabricatedAppList import com.drdisagree.colorblendr.utils.ShizukuUtil.bindUserService import com.drdisagree.colorblendr.utils.ShizukuUtil.getUserServiceArgs import com.drdisagree.colorblendr.utils.ShizukuUtil.isShizukuAvailable import com.drdisagree.colorblendr.utils.ShizukuUtil.requestShizukuPermission -import com.drdisagree.colorblendr.utils.WallpaperColorUtil.getAndSaveWallpaperColors -import com.drdisagree.colorblendr.utils.WallpaperColorUtil.getWallpaperColors +import com.drdisagree.colorblendr.utils.WallpaperColorUtil.updateWallpaperColorList +import kotlinx.coroutines.launch class OnboardingFragment : Fragment() { @@ -57,6 +54,7 @@ class OnboardingFragment : Fragment() { adapter.addFragment(OnboardingItem3Fragment()) binding.viewPager.adapter = adapter + binding.viewPager.offscreenPageLimit = adapter.itemCount binding.viewPager.registerOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() { @@ -82,8 +80,11 @@ class OnboardingFragment : Fragment() { when (Const.WORKING_METHOD) { Const.WorkMethod.NULL -> { - Toast.makeText(requireContext(), R.string.select_method, Toast.LENGTH_SHORT) - .show() + Toast.makeText( + requireContext(), + R.string.select_method, + Toast.LENGTH_SHORT + ).show() } Const.WorkMethod.ROOT -> { @@ -113,12 +114,10 @@ class OnboardingFragment : Fragment() { } private fun checkRootConnection() { - builder(requireContext()) - .runOnSuccess(object : MethodInterface() { - override fun run() { - goToHomeFragment() - } - }).run() + RootConnectionProvider + .builder(requireContext()) + .onSuccess { goToHomeFragment() } + .run() } private fun checkShizukuConnection() { @@ -148,11 +147,16 @@ class OnboardingFragment : Fragment() { } private fun goToHomeFragment() { - saveWorkingMethod(Const.WORKING_METHOD) - getAndSaveWallpaperColors(requireContext()) - getAndSaveSelectedFabricatedApps(requireContext()) - putBoolean(FIRST_RUN, false) - MainActivity.Companion.replaceFragment(HomeFragment(), true) + lifecycleScope.launch { + try { + updateWallpaperColorList(requireContext()) + updateFabricatedAppList(requireContext()) + putBoolean(FIRST_RUN, false) + saveWorkingMethod(Const.WORKING_METHOD) + MainActivity.replaceFragment(HomeFragment(), true) + } catch (_: Exception) { + } + } } private fun animateBackButton(position: Int) { @@ -212,20 +216,6 @@ class OnboardingFragment : Fragment() { private fun changeContinueButtonText(position: Int) { if (position == adapter.itemCount - 1) { binding.btnNext.setText(R.string.start) - - Thread { - try { - if (hasStoragePermission()) { - val wallpaperColors = - getWallpaperColors(requireContext()) - putString( - WALLPAPER_COLOR_LIST, - Const.GSON.toJson(wallpaperColors) - ) - } - } catch (ignored: Exception) { - } - }.start() } else { binding.btnNext.setText(R.string.btn_continue) } @@ -248,4 +238,4 @@ class OnboardingFragment : Fragment() { binding.viewPager.setCurrentItem(binding.viewPager.currentItem - 1, true) } } -} \ No newline at end of file +} diff --git a/app/src/main/java/com/drdisagree/colorblendr/ui/fragments/OnboardingItem3Fragment.kt b/app/src/main/java/com/drdisagree/colorblendr/ui/fragments/OnboardingItem3Fragment.kt index 2f5272c..2f98903 100644 --- a/app/src/main/java/com/drdisagree/colorblendr/ui/fragments/OnboardingItem3Fragment.kt +++ b/app/src/main/java/com/drdisagree/colorblendr/ui/fragments/OnboardingItem3Fragment.kt @@ -20,14 +20,12 @@ class OnboardingItem3Fragment : Fragment() { binding = FragmentOnboardingItem3Binding.inflate(inflater, container, false) binding.root.setOnClickListener { - Const.WORKING_METHOD = - Const.WorkMethod.ROOT + Const.WORKING_METHOD = Const.WorkMethod.ROOT binding.shizuku.isSelected = false } binding.shizuku.setOnClickListener { - Const.WORKING_METHOD = - Const.WorkMethod.SHIZUKU + Const.WORKING_METHOD = Const.WorkMethod.SHIZUKU binding.root.isSelected = false } diff --git a/app/src/main/java/com/drdisagree/colorblendr/ui/fragments/PerAppThemeFragment.kt b/app/src/main/java/com/drdisagree/colorblendr/ui/fragments/PerAppThemeFragment.kt index 2d8602a..f03cf75 100644 --- a/app/src/main/java/com/drdisagree/colorblendr/ui/fragments/PerAppThemeFragment.kt +++ b/app/src/main/java/com/drdisagree/colorblendr/ui/fragments/PerAppThemeFragment.kt @@ -8,8 +8,6 @@ import android.content.IntentFilter import android.content.pm.ApplicationInfo import android.content.pm.PackageManager import android.os.Bundle -import android.os.Handler -import android.os.Looper import android.text.Editable import android.text.TextWatcher import android.view.LayoutInflater @@ -37,6 +35,11 @@ import com.drdisagree.colorblendr.utils.MiscUtil.setToolbarTitle import com.drdisagree.colorblendr.utils.OverlayManager.isOverlayEnabled import com.google.android.material.dialog.MaterialAlertDialogBuilder import eightbitlab.com.blurview.RenderEffectBlur +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.delay +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext import java.util.Locale class PerAppThemeFragment : Fragment() { @@ -87,15 +90,14 @@ class PerAppThemeFragment : Fragment() { binding.warn.container.visibility = View.GONE } binding.warn.close.setOnClickListener { - Handler(Looper.getMainLooper()).postDelayed( - { - putBoolean(SHOW_PER_APP_THEME_WARN, false) - binding.warn.container.animate() - .translationX(binding.warn.container.width * 2f).alpha(0f).withEndAction { - binding.warn.container.visibility = View.GONE - }.start() - }, 50 - ) + CoroutineScope(Dispatchers.Main).launch { + delay(50) + putBoolean(SHOW_PER_APP_THEME_WARN, false) + binding.warn.container.animate() + .translationX(binding.warn.container.width * 2f).alpha(0f).withEndAction { + binding.warn.container.visibility = View.GONE + }.start() + } } binding.recyclerView.layoutManager = LinearLayoutManager(requireContext()) @@ -119,11 +121,12 @@ class PerAppThemeFragment : Fragment() { binding.progressBar.visibility = View.VISIBLE binding.searchBox.search.removeTextChangedListener(textWatcher) - Thread { + CoroutineScope(Dispatchers.IO).launch { appList = getAllInstalledApps(requireContext(), appType) adapter = AppListAdapter(appList!!) + try { - requireActivity().runOnUiThread { + withContext(Dispatchers.Main) { binding.recyclerView.adapter = adapter binding.searchBox.search.addTextChangedListener(textWatcher) @@ -141,7 +144,7 @@ class PerAppThemeFragment : Fragment() { } catch (ignored: Exception) { // Fragment was not attached to activity } - }.start() + } } private fun filterList(query: String) { diff --git a/app/src/main/java/com/drdisagree/colorblendr/ui/fragments/SettingsFragment.kt b/app/src/main/java/com/drdisagree/colorblendr/ui/fragments/SettingsFragment.kt index 5c3a463..23f0452 100644 --- a/app/src/main/java/com/drdisagree/colorblendr/ui/fragments/SettingsFragment.kt +++ b/app/src/main/java/com/drdisagree/colorblendr/ui/fragments/SettingsFragment.kt @@ -6,8 +6,6 @@ import android.app.Activity import android.content.DialogInterface import android.content.Intent import android.os.Bundle -import android.os.Handler -import android.os.Looper import android.util.Log import android.view.LayoutInflater import android.view.MenuItem @@ -54,6 +52,11 @@ import com.drdisagree.colorblendr.utils.OverlayManager.removeFabricatedColors import com.google.android.material.dialog.MaterialAlertDialogBuilder import com.google.android.material.snackbar.Snackbar import com.google.gson.reflect.TypeToken +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.delay +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext import java.util.concurrent.Executors class SettingsFragment : Fragment() { @@ -66,25 +69,31 @@ class SettingsFragment : Fragment() { private val masterSwitch: CompoundButton.OnCheckedChangeListener = CompoundButton.OnCheckedChangeListener { buttonView: CompoundButton, isChecked: Boolean -> if (!isMasterSwitchEnabled) { - buttonView.setChecked(!isChecked) + buttonView.isChecked = !isChecked return@OnCheckedChangeListener } + putBoolean(THEMING_ENABLED, isChecked) putBoolean(SHIZUKU_THEMING_ENABLED, isChecked) putLong(MONET_LAST_UPDATED, System.currentTimeMillis()) - Handler(Looper.getMainLooper()).postDelayed({ + + CoroutineScope(Dispatchers.Main).launch { try { - if (isChecked) { - applyFabricatedColors(requireContext()) - } else { - removeFabricatedColors(requireContext()) + delay(300) + + withContext(Dispatchers.IO) { + if (isChecked) { + applyFabricatedColors(requireContext()) + } else { + removeFabricatedColors(requireContext()) + } } isMasterSwitchEnabled = false val isOverlayEnabled: Boolean = isOverlayEnabled(FABRICATED_OVERLAY_NAME_SYSTEM) || getBoolean(SHIZUKU_THEMING_ENABLED, true) - buttonView.setChecked(isOverlayEnabled) + buttonView.isChecked = isOverlayEnabled isMasterSwitchEnabled = true if (isChecked != isOverlayEnabled) { @@ -92,12 +101,11 @@ class SettingsFragment : Fragment() { requireContext(), getString(R.string.something_went_wrong), Toast.LENGTH_SHORT - ) - .show() + ).show() } } catch (ignored: Exception) { } - }, 300) + } } override fun onCreateView( @@ -314,9 +322,7 @@ class SettingsFragment : Fragment() { } private var startRestoreActivityIntent: ActivityResultLauncher = - registerForActivityResult( - ActivityResultContracts.StartActivityForResult() - ) { result: ActivityResult -> + registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result: ActivityResult -> if (result.resultCode == Activity.RESULT_OK) { val data: Intent? = result.data if (data?.data == null) return@registerForActivityResult @@ -326,7 +332,8 @@ class SettingsFragment : Fragment() { .setMessage(getString(R.string.confirmation_desc)) .setPositiveButton(getString(android.R.string.ok)) { dialog: DialogInterface, _: Int -> dialog.dismiss() - Executors.newSingleThreadExecutor().execute { + + CoroutineScope(Dispatchers.IO).launch { try { restorePrefs( appContext @@ -334,25 +341,29 @@ class SettingsFragment : Fragment() { .openInputStream(data.data!!)!! ) - try { - applyFabricatedColors(requireContext()) - } catch (ignored: Exception) { + withContext(Dispatchers.Main) { + try { + applyFabricatedColors(requireContext()) + } catch (ignored: Exception) { + } } } catch (exception: Exception) { - Snackbar - .make( - binding.getRoot(), - getString(R.string.restore_fail), - Snackbar.LENGTH_INDEFINITE - ) - .setAction(getString(R.string.retry)) { - backupRestoreSettings( - false + withContext(Dispatchers.Main) { + Snackbar + .make( + binding.getRoot(), + getString(R.string.restore_fail), + Snackbar.LENGTH_INDEFINITE ) - } - .show() - - Log.e(TAG, "startBackupActivityIntent: ", exception) + .setAction(getString(R.string.retry)) { + backupRestoreSettings( + false + ) + } + .show() + + Log.e(TAG, "startBackupActivityIntent: ", exception) + } } } } @@ -389,13 +400,19 @@ class SettingsFragment : Fragment() { } private fun applyFabricatedColors() { - putLong(MONET_LAST_UPDATED, System.currentTimeMillis()) - Handler(Looper.getMainLooper()).postDelayed({ - try { - applyFabricatedColors(requireContext()) - } catch (ignored: Exception) { + CoroutineScope(Dispatchers.Main).launch { + putLong( + MONET_LAST_UPDATED, + System.currentTimeMillis() + ) + delay(300) + withContext(Dispatchers.IO) { + try { + applyFabricatedColors(requireContext()) + } catch (ignored: Exception) { + } } - }, 300) + } } companion object { diff --git a/app/src/main/java/com/drdisagree/colorblendr/ui/fragments/ThemeFragment.kt b/app/src/main/java/com/drdisagree/colorblendr/ui/fragments/ThemeFragment.kt index 133590c..499c60f 100644 --- a/app/src/main/java/com/drdisagree/colorblendr/ui/fragments/ThemeFragment.kt +++ b/app/src/main/java/com/drdisagree/colorblendr/ui/fragments/ThemeFragment.kt @@ -1,8 +1,6 @@ package com.drdisagree.colorblendr.ui.fragments import android.os.Bundle -import android.os.Handler -import android.os.Looper import android.util.Log import android.view.LayoutInflater import android.view.View @@ -28,10 +26,15 @@ import com.drdisagree.colorblendr.config.RPrefs.putInt import com.drdisagree.colorblendr.config.RPrefs.putLong import com.drdisagree.colorblendr.databinding.FragmentThemeBinding import com.drdisagree.colorblendr.utils.ColorSchemeUtil.stringToEnumMonetStyle -import com.drdisagree.colorblendr.utils.ColorUtil.generateModifiedColors +import com.drdisagree.colorblendr.utils.ColorUtil import com.drdisagree.colorblendr.utils.MiscUtil.setToolbarTitle import com.drdisagree.colorblendr.utils.OverlayManager.applyFabricatedColors import com.drdisagree.colorblendr.utils.SystemUtil.isDarkMode +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.delay +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext class ThemeFragment : Fragment() { @@ -78,13 +81,7 @@ class ThemeFragment : Fragment() { override fun onStopTrackingTouch(seekBar: SeekBar) { monetAccentSaturation[0] = seekBar.progress putInt(MONET_ACCENT_SATURATION, monetAccentSaturation[0]) - putLong(MONET_LAST_UPDATED, System.currentTimeMillis()) - Handler(Looper.getMainLooper()).postDelayed({ - try { - applyFabricatedColors(requireContext()) - } catch (ignored: Exception) { - } - }, 200) + applyFabricatedColors() } }) @@ -93,13 +90,7 @@ class ThemeFragment : Fragment() { monetAccentSaturation[0] = 100 updatePreviewColors() clearPref(MONET_ACCENT_SATURATION) - putLong(MONET_LAST_UPDATED, System.currentTimeMillis()) - Handler(Looper.getMainLooper()).postDelayed({ - try { - applyFabricatedColors(requireContext()) - } catch (ignored: Exception) { - } - }, 200) + applyFabricatedColors() true } binding.accentSaturation.setEnabled(notShizukuMode) @@ -119,13 +110,7 @@ class ThemeFragment : Fragment() { override fun onStopTrackingTouch(seekBar: SeekBar) { monetBackgroundSaturation[0] = seekBar.progress putInt(MONET_BACKGROUND_SATURATION, monetBackgroundSaturation[0]) - putLong(MONET_LAST_UPDATED, System.currentTimeMillis()) - Handler(Looper.getMainLooper()).postDelayed({ - try { - applyFabricatedColors(requireContext()) - } catch (ignored: Exception) { - } - }, 200) + applyFabricatedColors() } }) @@ -134,13 +119,7 @@ class ThemeFragment : Fragment() { monetBackgroundSaturation[0] = 100 updatePreviewColors() clearPref(MONET_BACKGROUND_SATURATION) - putLong(MONET_LAST_UPDATED, System.currentTimeMillis()) - Handler(Looper.getMainLooper()).postDelayed({ - try { - applyFabricatedColors(requireContext()) - } catch (ignored: Exception) { - } - }, 200) + applyFabricatedColors() true } binding.backgroundSaturation.setEnabled(notShizukuMode) @@ -160,13 +139,7 @@ class ThemeFragment : Fragment() { override fun onStopTrackingTouch(seekBar: SeekBar) { monetBackgroundLightness[0] = seekBar.progress putInt(MONET_BACKGROUND_LIGHTNESS, monetBackgroundLightness[0]) - putLong(MONET_LAST_UPDATED, System.currentTimeMillis()) - Handler(Looper.getMainLooper()).postDelayed({ - try { - applyFabricatedColors(requireContext()) - } catch (ignored: Exception) { - } - }, 200) + applyFabricatedColors() } }) @@ -175,13 +148,7 @@ class ThemeFragment : Fragment() { monetBackgroundLightness[0] = 100 updatePreviewColors() clearPref(MONET_BACKGROUND_LIGHTNESS) - putLong(MONET_LAST_UPDATED, System.currentTimeMillis()) - Handler(Looper.getMainLooper()).postDelayed({ - try { - applyFabricatedColors(requireContext()) - } catch (ignored: Exception) { - } - }, 200) + applyFabricatedColors() true } binding.backgroundLightness.setEnabled(notShizukuMode) @@ -195,6 +162,22 @@ class ThemeFragment : Fragment() { updatePreviewColors() } + private fun applyFabricatedColors() { + CoroutineScope(Dispatchers.Main).launch { + putLong( + MONET_LAST_UPDATED, + System.currentTimeMillis() + ) + delay(200) + withContext(Dispatchers.IO) { + try { + applyFabricatedColors(requireContext()) + } catch (ignored: Exception) { + } + } + } + } + private fun updatePreviewColors() { val colorPalette: ArrayList>? = generateModifiedColors( monetAccentSaturation[0], @@ -252,8 +235,7 @@ class ThemeFragment : Fragment() { accurateShades: Boolean ): ArrayList>? { try { - return generateModifiedColors( - requireContext(), + return ColorUtil.generateModifiedColors( stringToEnumMonetStyle( requireContext(), RPrefs.getString(MONET_STYLE, getString(R.string.monet_tonalspot))!! diff --git a/app/src/main/java/com/drdisagree/colorblendr/ui/views/WallColorPreview.kt b/app/src/main/java/com/drdisagree/colorblendr/ui/views/WallColorPreview.kt index e6be89a..56c7590 100644 --- a/app/src/main/java/com/drdisagree/colorblendr/ui/views/WallColorPreview.kt +++ b/app/src/main/java/com/drdisagree/colorblendr/ui/views/WallColorPreview.kt @@ -27,6 +27,11 @@ import com.drdisagree.colorblendr.utils.ColorSchemeUtil.stringToEnumMonetStyle import com.drdisagree.colorblendr.utils.ColorUtil.calculateTextColor import com.drdisagree.colorblendr.utils.ColorUtil.generateModifiedColors import com.drdisagree.colorblendr.utils.SystemUtil +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.Job +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext class WallColorPreview : View { @@ -46,21 +51,22 @@ class WallColorPreview : View { private var circleRadius = 0f private var isSelected = false private var colorPalette: ArrayList>? = null + private val coroutineScope = CoroutineScope(Dispatchers.Main + Job()) @ColorInt - private var halfCircleColor = 0 + private var halfCircleColor = Color.DKGRAY @ColorInt - private var firstQuarterCircleColor = 0 + private var firstQuarterCircleColor = Color.DKGRAY @ColorInt - private var secondQuarterCircleColor = 0 + private var secondQuarterCircleColor = Color.DKGRAY @ColorInt - private var squareColor = 0 + private var squareColor = Color.DKGRAY @ColorInt - private var centerCircleColor = 0 + private var centerCircleColor = Color.DKGRAY constructor(context: Context) : super(context) { init(context) @@ -220,36 +226,40 @@ class WallColorPreview : View { } fun setMainColor(@ColorInt color: Int) { - Thread { + coroutineScope.launch { try { - colorPalette = generateModifiedColors( - stringToEnumMonetStyle( - context!!, - getString( - MONET_STYLE, - context!!.getString(R.string.monet_tonalspot) - )!! - ), - color, - getInt(MONET_ACCENT_SATURATION, 100), - getInt(MONET_BACKGROUND_SATURATION, 100), - getInt(MONET_BACKGROUND_LIGHTNESS, 100), - getBoolean(MONET_PITCH_BLACK_THEME, false), - getBoolean(MONET_ACCURATE_SHADES, true), - false, - SystemUtil.isDarkMode, - false - ) - - setHalfCircleColor(colorPalette!![0][4]) - setFirstQuarterCircleColor(colorPalette!![2][5]) - setSecondQuarterCircleColor(colorPalette!![1][6]) - setSquareColor(colorPalette!![4][if (!isDarkMode) 3 else 9]) - setCenterCircleColor(color) - invalidateColors() + colorPalette = withContext(Dispatchers.IO) { + generateModifiedColors( + stringToEnumMonetStyle( + context!!, + getString( + MONET_STYLE, + context!!.getString(R.string.monet_tonalspot) + )!! + ), + color, + getInt(MONET_ACCENT_SATURATION, 100), + getInt(MONET_BACKGROUND_SATURATION, 100), + getInt(MONET_BACKGROUND_LIGHTNESS, 100), + getBoolean(MONET_PITCH_BLACK_THEME, false), + getBoolean(MONET_ACCURATE_SHADES, true), + false, + SystemUtil.isDarkMode, + false + ) + } + + withContext(Dispatchers.Main) { + setHalfCircleColor(colorPalette!![0][4]) + setFirstQuarterCircleColor(colorPalette!![2][5]) + setSecondQuarterCircleColor(colorPalette!![1][6]) + setSquareColor(colorPalette!![4][if (!isDarkMode) 3 else 9]) + setCenterCircleColor(color) + invalidateColors() + } } catch (ignored: Exception) { } - }.start() + } } override fun setSelected(selected: Boolean) { diff --git a/app/src/main/java/com/drdisagree/colorblendr/ui/widgets/StylePreviewWidget.kt b/app/src/main/java/com/drdisagree/colorblendr/ui/widgets/StylePreviewWidget.kt index 74aefd0..d701140 100644 --- a/app/src/main/java/com/drdisagree/colorblendr/ui/widgets/StylePreviewWidget.kt +++ b/app/src/main/java/com/drdisagree/colorblendr/ui/widgets/StylePreviewWidget.kt @@ -2,11 +2,10 @@ package com.drdisagree.colorblendr.ui.widgets import android.content.Context import android.content.res.TypedArray -import android.os.Handler -import android.os.Looper import android.os.Parcel import android.os.Parcelable import android.util.AttributeSet +import android.util.Log import android.view.View import android.widget.RelativeLayout import android.widget.TextView @@ -29,6 +28,11 @@ import com.drdisagree.colorblendr.utils.OverlayManager.applyFabricatedColors import com.drdisagree.colorblendr.utils.SystemUtil.isDarkMode import com.google.android.material.card.MaterialCardView import com.google.android.material.color.MaterialColors +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.Job +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext class StylePreviewWidget : RelativeLayout { @@ -42,6 +46,7 @@ class StylePreviewWidget : RelativeLayout { private var styleName: String? = null private var monetStyle: MONET? = null private var colorPalette: ArrayList>? = null + private val coroutineScope = CoroutineScope(Dispatchers.Main + Job()) constructor(context: Context) : super(context) { init(context, null) @@ -72,7 +77,9 @@ class StylePreviewWidget : RelativeLayout { setDescription(typedArray.getString(R.styleable.StylePreviewWidget_descriptionText)) typedArray.recycle() - setColorPreview() + coroutineScope.launch { + setColorPreview() + } container!!.setOnClickListener { v: View? -> if (onClickListener != null && !isSelected()) { @@ -113,12 +120,15 @@ class StylePreviewWidget : RelativeLayout { fun applyColorScheme() { styleName?.let { putString(MONET_STYLE, it) - applyFabricatedColors(context!!) + + coroutineScope.launch { + applyFabricatedColors(context!!) + } } } - private fun setColorPreview() { - Thread { + private suspend fun setColorPreview() { + withContext(Dispatchers.IO) { try { if (styleName == null) { styleName = context!!.getString(R.string.monet_tonalspot) @@ -130,7 +140,6 @@ class StylePreviewWidget : RelativeLayout { ) colorPalette = generateModifiedColors( - context!!, monetStyle!!, getInt(MONET_ACCENT_SATURATION, 100), getInt(MONET_BACKGROUND_SATURATION, 100), @@ -138,18 +147,21 @@ class StylePreviewWidget : RelativeLayout { getBoolean(MONET_PITCH_BLACK_THEME, false), getBoolean(MONET_ACCURATE_SHADES, true) ) + } catch (e: Exception) { + Log.e(TAG, "Error generating color palette", e) + return@withContext + } - Handler(Looper.getMainLooper()).post { - val isDarkMode: Boolean = isDarkMode - colorContainer!!.setHalfCircleColor(colorPalette!![0][4]) - colorContainer!!.setFirstQuarterCircleColor(colorPalette!![2][5]) - colorContainer!!.setSecondQuarterCircleColor(colorPalette!![1][6]) - colorContainer!!.setSquareColor(colorPalette!![4][if (!isDarkMode) 2 else 9]) - colorContainer!!.invalidateColors() + withContext(Dispatchers.Main) { + colorContainer?.apply { + setHalfCircleColor(colorPalette!![0][4]) + setFirstQuarterCircleColor(colorPalette!![2][5]) + setSecondQuarterCircleColor(colorPalette!![1][6]) + setSquareColor(colorPalette!![4][if (!isDarkMode) 2 else 9]) + invalidateColors() } - } catch (ignored: Exception) { } - }.start() + } } override fun setOnClickListener(l: OnClickListener?) { @@ -214,7 +226,10 @@ class StylePreviewWidget : RelativeLayout { super.onRestoreInstanceState(state.superState) setSelected(state.isSelected) - setColorPreview() + + coroutineScope.launch { + setColorPreview() + } } override fun setEnabled(enabled: Boolean) { @@ -260,4 +275,8 @@ class StylePreviewWidget : RelativeLayout { return 0 } } + + companion object { + private val TAG: String = StylePreviewWidget::class.java.simpleName + } } diff --git a/app/src/main/java/com/drdisagree/colorblendr/utils/ColorUtil.kt b/app/src/main/java/com/drdisagree/colorblendr/utils/ColorUtil.kt index 272db3f..7e3b5db 100644 --- a/app/src/main/java/com/drdisagree/colorblendr/utils/ColorUtil.kt +++ b/app/src/main/java/com/drdisagree/colorblendr/utils/ColorUtil.kt @@ -19,6 +19,7 @@ import kotlin.math.min import kotlin.math.pow object ColorUtil { + @ColorInt fun getColorFromAttribute(context: Context, attr: Int): Int { val typedValue = TypedValue() @@ -27,7 +28,6 @@ object ColorUtil { } fun generateModifiedColors( - context: Context, style: MONET, accentSaturation: Int, backgroundSaturation: Int, @@ -37,16 +37,16 @@ object ColorUtil { modifyPitchBlack: Boolean = true, isDark: Boolean = SystemUtil.isDarkMode ): ArrayList> { - val wallpaperColors = RPrefs.getString(Const.WALLPAPER_COLOR_LIST, null) + val wallpaperColorList: ArrayList? = + RPrefs.getString(Const.WALLPAPER_COLOR_LIST, null)?.let { + Const.GSON.fromJson( + it, + object : TypeToken>() {}.type + ) + } - val wallpaperColorList = if (wallpaperColors != null) { - Const.GSON.fromJson( - wallpaperColors, - object : TypeToken>() { - }.type - ) - } else { - WallpaperColorUtil.getWallpaperColors(context) + if (wallpaperColorList == null) { + throw Exception("No wallpaper color list found") } return generateModifiedColors( diff --git a/app/src/main/java/com/drdisagree/colorblendr/utils/FabricatedUtil.kt b/app/src/main/java/com/drdisagree/colorblendr/utils/FabricatedUtil.kt index 914de9a..4fa8312 100644 --- a/app/src/main/java/com/drdisagree/colorblendr/utils/FabricatedUtil.kt +++ b/app/src/main/java/com/drdisagree/colorblendr/utils/FabricatedUtil.kt @@ -127,7 +127,7 @@ object FabricatedUtil { } } - fun getAndSaveSelectedFabricatedApps(context: Context) { + fun updateFabricatedAppList(context: Context) { val packageManager = context.packageManager val applications = packageManager.getInstalledApplications(PackageManager.GET_META_DATA) val selectedApps = HashMap() diff --git a/app/src/main/java/com/drdisagree/colorblendr/utils/OverlayManager.kt b/app/src/main/java/com/drdisagree/colorblendr/utils/OverlayManager.kt index 6bd369e..95bd528 100644 --- a/app/src/main/java/com/drdisagree/colorblendr/utils/OverlayManager.kt +++ b/app/src/main/java/com/drdisagree/colorblendr/utils/OverlayManager.kt @@ -15,6 +15,7 @@ import com.drdisagree.colorblendr.utils.fabricated.FabricatedOverlayResource @Suppress("unused") object OverlayManager { + private val TAG: String = OverlayManager::class.java.simpleName private var mRootConnection = rootConnection private var mShizukuConnection = shizukuConnection @@ -71,7 +72,7 @@ object OverlayManager { } try { - return mRootConnection!!.isOverlayInstalled(packageName) ?: false + return mRootConnection!!.isOverlayInstalled(packageName) } catch (e: RemoteException) { Log.e( TAG, @@ -92,7 +93,7 @@ object OverlayManager { } try { - return mRootConnection!!.isOverlayEnabled(packageName) ?: false + return mRootConnection!!.isOverlayEnabled(packageName) } catch (e: RemoteException) { Log.e( TAG, @@ -168,7 +169,7 @@ object OverlayManager { } } - fun applyFabricatedColors(context: Context) { + suspend fun applyFabricatedColors(context: Context) { if (!RPrefs.getBoolean( Const.THEMING_ENABLED, true @@ -192,25 +193,23 @@ object OverlayManager { val accurateShades = RPrefs.getBoolean(Const.MONET_ACCURATE_SHADES, true) val paletteLight = ColorUtil.generateModifiedColors( - context, - style, - monetAccentSaturation, - monetBackgroundSaturation, - monetBackgroundLightness, - pitchBlackTheme, - accurateShades, + style = style, + accentSaturation = monetAccentSaturation, + backgroundSaturation = monetBackgroundSaturation, + backgroundLightness = monetBackgroundLightness, + pitchBlackTheme = pitchBlackTheme, + accurateShades = accurateShades, modifyPitchBlack = false, isDark = false ) val paletteDark = ColorUtil.generateModifiedColors( - context, - style, - monetAccentSaturation, - monetBackgroundSaturation, - monetBackgroundLightness, - pitchBlackTheme, - accurateShades, + style = style, + accentSaturation = monetAccentSaturation, + backgroundSaturation = monetBackgroundSaturation, + backgroundLightness = monetBackgroundLightness, + pitchBlackTheme = pitchBlackTheme, + accurateShades = accurateShades, modifyPitchBlack = false, isDark = true ) @@ -305,7 +304,7 @@ object OverlayManager { } } - fun applyFabricatedColorsPerApp( + suspend fun applyFabricatedColorsPerApp( context: Context, packageName: String, palette: ArrayList>? @@ -346,7 +345,7 @@ object OverlayManager { } } - private fun getFabricatedColorsPerApp( + private suspend fun getFabricatedColorsPerApp( context: Context, packageName: String, palette: ArrayList>? @@ -355,7 +354,6 @@ object OverlayManager { if (paletteTemp == null) { paletteTemp = generateModifiedColors( - context, ColorSchemeUtil.stringToEnumMonetStyle( context, RPrefs.getString( diff --git a/app/src/main/java/com/drdisagree/colorblendr/utils/WallpaperColorUtil.kt b/app/src/main/java/com/drdisagree/colorblendr/utils/WallpaperColorUtil.kt index 1baadba..20df82b 100644 --- a/app/src/main/java/com/drdisagree/colorblendr/utils/WallpaperColorUtil.kt +++ b/app/src/main/java/com/drdisagree/colorblendr/utils/WallpaperColorUtil.kt @@ -7,9 +7,6 @@ import android.graphics.BitmapFactory import android.graphics.Canvas import android.graphics.drawable.BitmapDrawable import android.graphics.drawable.Drawable -import android.os.Handler -import android.os.Looper -import android.os.ParcelFileDescriptor import android.util.Log import android.util.Size import androidx.annotation.ColorInt @@ -18,68 +15,54 @@ import com.drdisagree.colorblendr.common.Const import com.drdisagree.colorblendr.config.RPrefs import com.drdisagree.colorblendr.utils.monet.quantize.QuantizerCelebi import com.drdisagree.colorblendr.utils.monet.score.Score +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.withContext import java.io.IOException -import java.util.concurrent.Callable -import java.util.concurrent.ExecutionException -import java.util.concurrent.ExecutorService -import java.util.concurrent.Executors -import java.util.concurrent.Future import kotlin.math.min import kotlin.math.sqrt object WallpaperColorUtil { + private val TAG: String = WallpaperColorUtil::class.java.simpleName private const val SMALL_SIDE = 128 private const val MAX_BITMAP_SIZE = 112 private const val MAX_WALLPAPER_EXTRACTION_AREA = MAX_BITMAP_SIZE * MAX_BITMAP_SIZE - fun getAndSaveWallpaperColors(context: Context) { - if (RPrefs.getInt(Const.MONET_SEED_COLOR, Int.MIN_VALUE) == Int.MIN_VALUE && - AppUtil.permissionsGranted(context) - ) { + suspend fun updateWallpaperColorList(context: Context) { + if (AppUtil.permissionsGranted(context)) { val wallpaperColors = getWallpaperColors(context) RPrefs.putString(Const.WALLPAPER_COLOR_LIST, Const.GSON.toJson(wallpaperColors)) - RPrefs.putInt( - Const.MONET_SEED_COLOR, - wallpaperColors[0] - ) + RPrefs.putInt(Const.MONET_SEED_COLOR, wallpaperColors[0]) } } @ColorInt - fun getWallpaperColor(context: Context): Int { + suspend fun getWallpaperColor(context: Context): Int { return getWallpaperColors(context)[0] } - fun getWallpaperColors(context: Context): ArrayList { + suspend fun getWallpaperColors(context: Context): ArrayList { if (!AppUtil.permissionsGranted(context)) { return ColorUtil.monetAccentColors } - val wallpaperFuture = - WallpaperLoader.loadWallpaperAsync(context, WallpaperManager.FLAG_SYSTEM, null) - - try { - val wallpaperBitmap = wallpaperFuture.get() - if (wallpaperBitmap != null) { - return getWallpaperColors(wallpaperBitmap) - } - } catch (e: ExecutionException) { - Log.e(TAG, "Error getting wallpaper color", e) - } catch (e: InterruptedException) { + return try { + val wallpaperBitmap = WallpaperLoader.loadWallpaperAsync( + context, + WallpaperManager.FLAG_SYSTEM + ) + wallpaperBitmap?.let { + getWallpaperColors(it) + } ?: ColorUtil.monetAccentColors + } catch (e: Exception) { Log.e(TAG, "Error getting wallpaper color", e) + ColorUtil.monetAccentColors } - - return ColorUtil.monetAccentColors } private fun createMiniBitmap(bitmap: Bitmap): Bitmap { - val smallestSide = - min(bitmap.width.toDouble(), bitmap.height.toDouble()).toInt() - val scale = min( - 1.0, - (SMALL_SIDE.toFloat() / smallestSide).toDouble() - ).toFloat() + val smallestSide = min(bitmap.width.toDouble(), bitmap.height.toDouble()).toInt() + val scale = min(1.0, (SMALL_SIDE.toFloat() / smallestSide).toDouble()).toFloat() return createMiniBitmap( bitmap, (scale * bitmap.width).toInt(), @@ -117,9 +100,16 @@ object WallpaperColorUtil { val bitmapArea = bitmapTemp.width * bitmapTemp.height if (bitmapArea > MAX_WALLPAPER_EXTRACTION_AREA) { - val optimalSize = calculateOptimalSize(bitmapTemp.width, bitmapTemp.height) - bitmapTemp = - Bitmap.createScaledBitmap(bitmapTemp, optimalSize.width, optimalSize.height, false) + val optimalSize = calculateOptimalSize( + bitmapTemp.width, + bitmapTemp.height + ) + bitmapTemp = Bitmap.createScaledBitmap( + bitmapTemp, + optimalSize.width, + optimalSize.height, + false + ) } val width = bitmapTemp.width @@ -149,17 +139,14 @@ object WallpaperColorUtil { val intrinsicWidth = drawable.intrinsicWidth val intrinsicHeight = drawable.intrinsicHeight - if (intrinsicWidth <= 0 || intrinsicHeight <= 0) { + bitmap = if (intrinsicWidth <= 0 || intrinsicHeight <= 0) { val colors = ColorUtil.monetAccentColors val colorCount = colors.size - bitmap = Bitmap.createBitmap(colorCount, 1, Bitmap.Config.ARGB_8888) - val canvas = Canvas(bitmap) - - var colorIndex = 0 - if (colorCount > 0) { + Bitmap.createBitmap(colorCount, 1, Bitmap.Config.ARGB_8888).apply { + val canvas = Canvas(this) val rectWidth = canvas.width / colorCount - for (color in colors) { + colors.forEachIndexed { colorIndex, color -> canvas.save() canvas.clipRect( colorIndex * rectWidth, @@ -169,103 +156,69 @@ object WallpaperColorUtil { ) canvas.drawColor(color) canvas.restore() - colorIndex++ } } } else { - bitmap = createMiniBitmap( + createMiniBitmap( Bitmap.createBitmap( intrinsicWidth, intrinsicHeight, Bitmap.Config.ARGB_8888 - ) + ).apply { + val canvas = Canvas(this) + drawable.setBounds(0, 0, intrinsicWidth, intrinsicHeight) + drawable.draw(canvas) + } ) - val canvas = Canvas(bitmap) - drawable.setBounds(0, 0, intrinsicWidth, intrinsicHeight) - drawable.draw(canvas) } return bitmap } private object WallpaperLoader { + private val TAG: String = WallpaperLoader::class.java.simpleName - private val executorService: ExecutorService = Executors.newFixedThreadPool(2) - private val mainHandler = Handler(Looper.getMainLooper()) + private val ioDispatcher = Dispatchers.IO - fun loadWallpaperAsync( + suspend fun loadWallpaperAsync( context: Context?, - which: Int, - listener: WallpaperLoadListener? - ): Future { - val callable = - Callable { loadWallpaper(context, which) } - val future = executorService.submit(callable) - - if (listener != null) { - executorService.execute { - try { - val result = future.get() - notifyOnMainThread(listener, result) - } catch (e: Exception) { - Log.e( - TAG, - "Error getting wallpaper bitmap async", - e - ) - } - } - } - - return future + which: Int + ): Bitmap? = withContext(ioDispatcher) { + loadWallpaper(context, which) } - fun loadWallpaper(context: Context?, which: Int): Bitmap? { - try { - val wallpaperFile: ParcelFileDescriptor? + private fun loadWallpaper(context: Context?, which: Int): Bitmap? { + return try { val wallpaperManager = WallpaperManager.getInstance(context) if (wallpaperManager.wallpaperInfo != null) { - return drawableToBitmap( + drawableToBitmap( wallpaperManager.wallpaperInfo.loadThumbnail( appContext.packageManager ) ) - } - - wallpaperFile = if (which == WallpaperManager.FLAG_SYSTEM) { - wallpaperManager.getWallpaperFile(WallpaperManager.FLAG_SYSTEM) } else { - wallpaperManager.getWallpaperFile(WallpaperManager.FLAG_LOCK) - } + val wallpaperFile = if (which == WallpaperManager.FLAG_SYSTEM) { + wallpaperManager.getWallpaperFile(WallpaperManager.FLAG_SYSTEM) + } else { + wallpaperManager.getWallpaperFile(WallpaperManager.FLAG_LOCK) + } - if (wallpaperFile == null) { - Log.e(TAG, "Error getting wallpaper bitmap: wallpaperFile is null") - return null + wallpaperFile?.let { + val decodeFileDescriptor = createMiniBitmap( + BitmapFactory.decodeFileDescriptor(it.fileDescriptor) + ) + it.close() + decodeFileDescriptor + } ?: run { + Log.e(TAG, "Error getting wallpaper bitmap: wallpaperFile is null") + null + } } - - val decodeFileDescriptor = createMiniBitmap( - BitmapFactory.decodeFileDescriptor( - wallpaperFile.fileDescriptor - ) - ) - wallpaperFile.close() - - return decodeFileDescriptor } catch (e: IOException) { Log.e(TAG, "Error getting wallpaper bitmap", e) - return null + null } } - - fun notifyOnMainThread(listener: WallpaperLoadListener?, bitmap: Bitmap?) { - mainHandler.post { - listener?.onWallpaperLoaded(bitmap) - } - } - - interface WallpaperLoadListener { - fun onWallpaperLoaded(bitmap: Bitmap?) - } } } From d26154da6ef150a41f262c98e1369266e5752f80 Mon Sep 17 00:00:00 2001 From: DrDisagree Date: Sat, 17 Aug 2024 20:28:15 +0600 Subject: [PATCH 5/7] Remove nested pairs for better readability --- .../colorblendr/utils/DynamicColors.kt | 1000 +++++++++++------ .../colorblendr/utils/FabricatedUtil.kt | 185 ++- 2 files changed, 762 insertions(+), 423 deletions(-) diff --git a/app/src/main/java/com/drdisagree/colorblendr/utils/DynamicColors.kt b/app/src/main/java/com/drdisagree/colorblendr/utils/DynamicColors.kt index 6ff6bd0..40aac85 100644 --- a/app/src/main/java/com/drdisagree/colorblendr/utils/DynamicColors.kt +++ b/app/src/main/java/com/drdisagree/colorblendr/utils/DynamicColors.kt @@ -1,376 +1,652 @@ package com.drdisagree.colorblendr.utils +import android.graphics.Color import android.os.Build -import androidx.core.util.Pair + +data class ColorMapping( + val resourceName: String, + val tonalPalette: TonalPalette? = null, + val colorIndex: Int? = null, + val lightModeColorIndex: Int? = null, + val darkModeColorIndex: Int? = null, + val lightModeColorCode: Int? = null, + val colorCode: Int? = null, + val darkModeColorCode: Int? = null, + val lightnessAdjustment: Int? = null +) + +enum class TonalPalette(val index: Int) { + PRIMARY(0), + SECONDARY(1), + TERTIARY(2), + NEUTRAL(3), + NEUTRAL_VARIANT(4) +} object DynamicColors { - val ALL_DYNAMIC_COLORS_MAPPED: MutableList> = ArrayList() - val FIXED_COLORS_MAPPED: MutableList>> = ArrayList() - val M3_REF_PALETTE: MutableList>>> = ArrayList() + + val ALL_DYNAMIC_COLORS_MAPPED: MutableList = ArrayList() + val FIXED_COLORS_MAPPED: MutableList = ArrayList() + val M3_REF_PALETTE: MutableList = ArrayList() /* * This is a list of all the dynamic and fixed colors that are available in the system. - * - * **Dynamic colors:** - * -> First item is the name of the color. - * -> Second item is the tonal palette index. - * 0 = primary - * 1 = secondary - * 2 = tertiary - * 3 = neutral - * 4 = neutral variant - * -> Third item is the color index in light mode. - * -> Fourth item is the color index in dark mode. - * - * **Fixed colors:** - * -> First item is the name of the color. - * -> Second item is the tonal palette index. - * 0 = primary - * 1 = secondary - * 2 = tertiary - * 3 = neutral - * 4 = neutral variant - * -> Third item is the color index. - * - * **M3 ref colors:** - * -> First item is the name of the color. - * Second item is the lightness percentage to increase or decrease - * from the base color given by the second item of the inner pair. - * -> Third item is the tonal palette index. - * 0 = primary - * 1 = secondary - * 2 = tertiary - * 3 = neutral - * 4 = neutral variant - * -> Fourth item is the color index. */ init { - ALL_DYNAMIC_COLORS_MAPPED.add( - Pair.create( - "primary_container", - Pair.create(0, Pair.create(3, 9)) - ) - ) - ALL_DYNAMIC_COLORS_MAPPED.add( - Pair.create( - "on_primary_container", - Pair.create(0, Pair.create(11, 3)) - ) - ) - ALL_DYNAMIC_COLORS_MAPPED.add(Pair.create("primary", Pair.create(0, Pair.create(8, 4)))) - ALL_DYNAMIC_COLORS_MAPPED.add(Pair.create("on_primary", Pair.create(0, Pair.create(0, 10)))) - ALL_DYNAMIC_COLORS_MAPPED.add( - Pair.create( - "secondary_container", - Pair.create(1, Pair.create(3, 9)) - ) - ) - ALL_DYNAMIC_COLORS_MAPPED.add( - Pair.create( - "on_secondary_container", - Pair.create(1, Pair.create(11, 3)) - ) - ) - ALL_DYNAMIC_COLORS_MAPPED.add(Pair.create("secondary", Pair.create(1, Pair.create(8, 4)))) - ALL_DYNAMIC_COLORS_MAPPED.add( - Pair.create( - "on_secondary", - Pair.create(1, Pair.create(0, 10)) - ) - ) - ALL_DYNAMIC_COLORS_MAPPED.add( - Pair.create( - "tertiary_container", - Pair.create(2, Pair.create(3, 9)) - ) - ) - ALL_DYNAMIC_COLORS_MAPPED.add( - Pair.create( - "on_tertiary_container", - Pair.create(2, Pair.create(11, 3)) - ) - ) - ALL_DYNAMIC_COLORS_MAPPED.add(Pair.create("tertiary", Pair.create(2, Pair.create(8, 4)))) - ALL_DYNAMIC_COLORS_MAPPED.add( - Pair.create( - "on_tertiary", - Pair.create(2, Pair.create(0, 10)) - ) - ) - ALL_DYNAMIC_COLORS_MAPPED.add(Pair.create("background", Pair.create(3, Pair.create(1, 11)))) - ALL_DYNAMIC_COLORS_MAPPED.add( - Pair.create( - "on_background", - Pair.create(3, Pair.create(11, 1)) - ) - ) - ALL_DYNAMIC_COLORS_MAPPED.add(Pair.create("surface", Pair.create(3, Pair.create(1, 11)))) - ALL_DYNAMIC_COLORS_MAPPED.add(Pair.create("on_surface", Pair.create(3, Pair.create(10, 2)))) - ALL_DYNAMIC_COLORS_MAPPED.add( - Pair.create( - "surface_container_low", - Pair.create(3, Pair.create(2, 10)) - ) - ) - ALL_DYNAMIC_COLORS_MAPPED.add( - Pair.create( - "surface_container_lowest", - Pair.create(3, Pair.create(1, 11)) - ) - ) - ALL_DYNAMIC_COLORS_MAPPED.add( - Pair.create( - "surface_container", - Pair.create(3, Pair.create(2, 10)) - ) - ) - ALL_DYNAMIC_COLORS_MAPPED.add( - Pair.create( - "surface_container_high", - Pair.create( - 3, - Pair.create( - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) 1 else 2, - 10 - ) - ) - ) - ) - ALL_DYNAMIC_COLORS_MAPPED.add( - Pair.create( - "surface_container_highest", - Pair.create(3, Pair.create(3, 9)) - ) - ) - ALL_DYNAMIC_COLORS_MAPPED.add( - Pair.create( - "surface_bright", - Pair.create(3, Pair.create(1, 10)) - ) - ) - ALL_DYNAMIC_COLORS_MAPPED.add( - Pair.create( - "surface_dim", - Pair.create(3, Pair.create(2, 11)) - ) - ) - ALL_DYNAMIC_COLORS_MAPPED.add( - Pair.create( - "surface_variant", - Pair.create(4, Pair.create(2, 10)) - ) - ) - ALL_DYNAMIC_COLORS_MAPPED.add( - Pair.create( - "on_surface_variant", - Pair.create(4, Pair.create(10, 2)) - ) - ) - ALL_DYNAMIC_COLORS_MAPPED.add(Pair.create("outline", Pair.create(4, Pair.create(7, 6)))) - ALL_DYNAMIC_COLORS_MAPPED.add( - Pair.create( - "outline_variant", - Pair.create(4, Pair.create(4, 9)) - ) - ) - // ALL_DYNAMIC_COLORS_MAPPED.add(Pair.create("error", Pair.create("#1EB326", "#B5F2B8"))); -// ALL_DYNAMIC_COLORS_MAPPED.add(Pair.create("on_error", Pair.create("#FFFFFF", "#106014"))); -// ALL_DYNAMIC_COLORS_MAPPED.add(Pair.create("error_container", Pair.create("#DCF9DE", "#188C1D"))); -// ALL_DYNAMIC_COLORS_MAPPED.add(Pair.create("on_error_container", Pair.create("#0B410E", "#DCF9DE"))); - ALL_DYNAMIC_COLORS_MAPPED.add( - Pair.create( - "control_activated", - Pair.create(1, Pair.create(8, 4)) - ) - ) - // ALL_DYNAMIC_COLORS_MAPPED.add(Pair.create("control_normal", )); - ALL_DYNAMIC_COLORS_MAPPED.add( - Pair.create( - "control_highlight", - Pair.create("#1F000000", "#33FFFFFF") - ) - ) - // ALL_DYNAMIC_COLORS_MAPPED.add(Pair.create("text_primary_inverse", )); -// ALL_DYNAMIC_COLORS_MAPPED.add(Pair.create("text_secondary_and_tertiary_inverse", )); -// ALL_DYNAMIC_COLORS_MAPPED.add(Pair.create("text_primary_inverse_disable_only", )); -// ALL_DYNAMIC_COLORS_MAPPED.add(Pair.create("text_secondary_and_tertiary_inverse_disabled", )); -// ALL_DYNAMIC_COLORS_MAPPED.add(Pair.create("text_hint_inverse", )); - ALL_DYNAMIC_COLORS_MAPPED.add( - Pair.create( - "palette_key_color_primary", - Pair.create(0, Pair.create(4, 8)) - ) - ) - ALL_DYNAMIC_COLORS_MAPPED.add( - Pair.create( - "palette_key_color_secondary", - Pair.create(1, Pair.create(4, 8)) - ) - ) - ALL_DYNAMIC_COLORS_MAPPED.add( - Pair.create( - "palette_key_color_tertiary", - Pair.create(2, Pair.create(4, 8)) - ) - ) - ALL_DYNAMIC_COLORS_MAPPED.add( - Pair.create( - "palette_key_color_neutral", - Pair.create(3, Pair.create(4, 8)) - ) - ) - ALL_DYNAMIC_COLORS_MAPPED.add( - Pair.create( - "palette_key_color_neutral_variant", - Pair.create(4, Pair.create(4, 8)) - ) - ) + /* + * **Dynamic colors:** + * -> First item is the name of the color. + * -> Second item is the tonal palette index. + * 0 = primary + * 1 = secondary + * 2 = tertiary + * 3 = neutral + * 4 = neutral variant + * -> Third item is the color index in light mode. + * -> Fourth item is the color index in dark mode. + */ + ALL_DYNAMIC_COLORS_MAPPED.apply { + add( + ColorMapping( + resourceName = "primary_container", + tonalPalette = TonalPalette.PRIMARY, + lightModeColorIndex = 3, + darkModeColorIndex = 9 + ) + ) + add( + ColorMapping( + resourceName = "on_primary_container", + tonalPalette = TonalPalette.PRIMARY, + lightModeColorIndex = 11, + darkModeColorIndex = 3 + ) + ) + add( + ColorMapping( + resourceName = "primary", + tonalPalette = TonalPalette.PRIMARY, + lightModeColorIndex = 8, + darkModeColorIndex = 4 + ) + ) + add( + ColorMapping( + resourceName = "on_primary", + tonalPalette = TonalPalette.PRIMARY, + lightModeColorIndex = 0, + darkModeColorIndex = 10 + ) + ) + add( + ColorMapping( + resourceName = "secondary_container", + tonalPalette = TonalPalette.SECONDARY, + lightModeColorIndex = 3, + darkModeColorIndex = 9 + ) + ) + add( + ColorMapping( + resourceName = "on_secondary_container", + tonalPalette = TonalPalette.SECONDARY, + lightModeColorIndex = 11, + darkModeColorIndex = 3 + ) + ) + add( + ColorMapping( + resourceName = "secondary", + tonalPalette = TonalPalette.SECONDARY, + lightModeColorIndex = 8, + darkModeColorIndex = 4 + ) + ) + add( + ColorMapping( + resourceName = "on_secondary", + tonalPalette = TonalPalette.SECONDARY, + lightModeColorIndex = 0, + darkModeColorIndex = 10 + ) + ) + add( + ColorMapping( + resourceName = "tertiary_container", + tonalPalette = TonalPalette.TERTIARY, + lightModeColorIndex = 3, + darkModeColorIndex = 9 + ) + ) + add( + ColorMapping( + resourceName = "on_tertiary_container", + tonalPalette = TonalPalette.TERTIARY, + lightModeColorIndex = 11, + darkModeColorIndex = 3 + ) + ) + add( + ColorMapping( + resourceName = "tertiary", + tonalPalette = TonalPalette.TERTIARY, + lightModeColorIndex = 8, + darkModeColorIndex = 4 + ) + ) + add( + ColorMapping( + resourceName = "on_tertiary", + tonalPalette = TonalPalette.TERTIARY, + lightModeColorIndex = 0, + darkModeColorIndex = 10 + ) + ) + add( + ColorMapping( + resourceName = "background", + tonalPalette = TonalPalette.NEUTRAL, + lightModeColorIndex = 1, + darkModeColorIndex = 11 + ) + ) + add( + ColorMapping( + resourceName = "on_background", + tonalPalette = TonalPalette.NEUTRAL, + lightModeColorIndex = 11, + darkModeColorIndex = 1 + ) + ) + add( + ColorMapping( + resourceName = "surface", + tonalPalette = TonalPalette.NEUTRAL, + lightModeColorIndex = 1, + darkModeColorIndex = 11 + ) + ) + add( + ColorMapping( + resourceName = "on_surface", + tonalPalette = TonalPalette.NEUTRAL, + lightModeColorIndex = 10, + darkModeColorIndex = 2 + ) + ) + add( + ColorMapping( + resourceName = "surface_container_low", + tonalPalette = TonalPalette.NEUTRAL, + lightModeColorIndex = 2, + darkModeColorIndex = 10 + ) + ) + add( + ColorMapping( + resourceName = "surface_container_lowest", + tonalPalette = TonalPalette.NEUTRAL, + lightModeColorIndex = 1, + darkModeColorIndex = 11 + ) + ) + add( + ColorMapping( + resourceName = "surface_container", + tonalPalette = TonalPalette.NEUTRAL, + lightModeColorIndex = 2, + darkModeColorIndex = 10 + ) + ) + add( + ColorMapping( + resourceName = "surface_container_high", + tonalPalette = TonalPalette.NEUTRAL, + lightModeColorIndex = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) { + 1 + } else { + 2 + }, + darkModeColorIndex = 10 + ) + ) + add( + ColorMapping( + resourceName = "surface_container_highest", + tonalPalette = TonalPalette.NEUTRAL, + lightModeColorIndex = 3, + darkModeColorIndex = 9 + ) + ) + add( + ColorMapping( + resourceName = "surface_bright", + tonalPalette = TonalPalette.NEUTRAL, + lightModeColorIndex = 1, + darkModeColorIndex = 10 + ) + ) + add( + ColorMapping( + resourceName = "surface_dim", + tonalPalette = TonalPalette.NEUTRAL, + lightModeColorIndex = 2, + darkModeColorIndex = 11 + ) + ) + add( + ColorMapping( + resourceName = "surface_variant", + tonalPalette = TonalPalette.NEUTRAL_VARIANT, + lightModeColorIndex = 2, + darkModeColorIndex = 10 + ) + ) + add( + ColorMapping( + resourceName = "on_surface_variant", + tonalPalette = TonalPalette.NEUTRAL_VARIANT, + lightModeColorIndex = 10, + darkModeColorIndex = 2 + ) + ) + add( + ColorMapping( + resourceName = "outline", + tonalPalette = TonalPalette.NEUTRAL_VARIANT, + lightModeColorIndex = 7, + darkModeColorIndex = 6 + ) + ) + add( + ColorMapping( + resourceName = "outline_variant", + tonalPalette = TonalPalette.NEUTRAL_VARIANT, + lightModeColorIndex = 4, + darkModeColorIndex = 9 + ) + ) +// add( +// ColorMapping( +// resourceName = "error", +// lightModeColorCode = Color.parseColor("#1EB326"), +// darkModeColorCode = Color.parseColor("#B5F2B8") +// ) +// ) +// add( +// ColorMapping( +// resourceName = "on_error", +// lightModeColorCode = Color.parseColor("#FFFFFF"), +// darkModeColorCode = Color.parseColor("#106014") +// ) +// ) +// add( +// ColorMapping( +// resourceName = "error_container", +// lightModeColorCode = Color.parseColor("#DCF9DE"), +// darkModeColorCode = Color.parseColor("#188C1D") +// ) +// ) +// add( +// ColorMapping( +// resourceName = "on_error_container", +// lightModeColorCode = Color.parseColor("#0B410E"), +// darkModeColorCode = Color.parseColor("#DCF9DE") +// ) +// ) + add( + ColorMapping( + resourceName = "control_activated", + tonalPalette = TonalPalette.SECONDARY, + lightModeColorIndex = 8, + darkModeColorIndex = 4 + ) + ) +// add(ColorMapping(resourceName = "control_normal")) + add( + ColorMapping( + resourceName = "control_highlight", + lightModeColorCode = Color.parseColor("#1F000000"), + darkModeColorCode = Color.parseColor("#33FFFFFF") + ) + ) +// add(ColorMapping(resourceName = "text_primary_inverse")) +// add(ColorMapping(resourceName = "text_secondary_and_tertiary_inverse")) +// add(ColorMapping(resourceName = "text_primary_inverse_disable_only")) +// add(ColorMapping(resourceName = "text_secondary_and_tertiary_inverse_disabled")) +// add(ColorMapping(resourceName = "text_hint_inverse")) + add( + ColorMapping( + resourceName = "palette_key_color_primary", + tonalPalette = TonalPalette.PRIMARY, + lightModeColorIndex = 4, + darkModeColorIndex = 8 + ) + ) + add( + ColorMapping( + resourceName = "palette_key_color_secondary", + tonalPalette = TonalPalette.SECONDARY, + lightModeColorIndex = 4, + darkModeColorIndex = 8 + ) + ) + add( + ColorMapping( + resourceName = "palette_key_color_tertiary", + tonalPalette = TonalPalette.TERTIARY, + lightModeColorIndex = 4, + darkModeColorIndex = 8 + ) + ) + add( + ColorMapping( + resourceName = "palette_key_color_neutral", + tonalPalette = TonalPalette.NEUTRAL, + lightModeColorIndex = 4, + darkModeColorIndex = 8 + ) + ) + add( + ColorMapping( + resourceName = "palette_key_color_neutral_variant", + tonalPalette = TonalPalette.NEUTRAL_VARIANT, + lightModeColorIndex = 4, + darkModeColorIndex = 8 + ) + ) + } - FIXED_COLORS_MAPPED.add(Pair.create("primary_fixed", Pair.create(0, 3))) - FIXED_COLORS_MAPPED.add(Pair.create("primary_fixed_dim", Pair.create(0, 4))) - FIXED_COLORS_MAPPED.add(Pair.create("on_primary_fixed", Pair.create(0, 11))) - FIXED_COLORS_MAPPED.add(Pair.create("on_primary_fixed_variant", Pair.create(0, 9))) - FIXED_COLORS_MAPPED.add(Pair.create("secondary_fixed", Pair.create(1, 3))) - FIXED_COLORS_MAPPED.add(Pair.create("secondary_fixed_dim", Pair.create(1, 4))) - FIXED_COLORS_MAPPED.add(Pair.create("on_secondary_fixed", Pair.create(1, 11))) - FIXED_COLORS_MAPPED.add(Pair.create("on_secondary_fixed_variant", Pair.create(1, 9))) - FIXED_COLORS_MAPPED.add(Pair.create("tertiary_fixed", Pair.create(2, 4))) - FIXED_COLORS_MAPPED.add(Pair.create("tertiary_fixed_dim", Pair.create(2, 4))) - FIXED_COLORS_MAPPED.add(Pair.create("on_tertiary_fixed", Pair.create(2, 11))) - FIXED_COLORS_MAPPED.add(Pair.create("on_tertiary_fixed_variant", Pair.create(2, 9))) + /* + * **Fixed colors:** + * -> First item is the name of the color. + * -> Second item is the tonal palette index. + * 0 = primary + * 1 = secondary + * 2 = tertiary + * 3 = neutral + * 4 = neutral variant + * -> Third item is the color index. + */ + FIXED_COLORS_MAPPED.apply { + add( + ColorMapping( + resourceName = "primary_fixed", + tonalPalette = TonalPalette.PRIMARY, + colorIndex = 3 + ) + ) + add( + ColorMapping( + resourceName = "primary_fixed_dim", + tonalPalette = TonalPalette.PRIMARY, + colorIndex = 4 + ) + ) + add( + ColorMapping( + resourceName = "on_primary_fixed", + tonalPalette = TonalPalette.PRIMARY, + colorIndex = 11 + ) + ) + add( + ColorMapping( + resourceName = "on_primary_fixed_variant", + tonalPalette = TonalPalette.PRIMARY, + colorIndex = 9 + ) + ) + add( + ColorMapping( + resourceName = "secondary_fixed", + tonalPalette = TonalPalette.SECONDARY, + colorIndex = 3 + ) + ) + add( + ColorMapping( + resourceName = "secondary_fixed_dim", + tonalPalette = TonalPalette.SECONDARY, + colorIndex = 4 + ) + ) + add( + ColorMapping( + resourceName = "on_secondary_fixed", + tonalPalette = TonalPalette.SECONDARY, + colorIndex = 11 + ) + ) + add( + ColorMapping( + resourceName = "on_secondary_fixed_variant", + tonalPalette = TonalPalette.SECONDARY, + colorIndex = 9 + ) + ) + add( + ColorMapping( + resourceName = "tertiary_fixed", + tonalPalette = TonalPalette.TERTIARY, + colorIndex = 4 + ) + ) + add( + ColorMapping( + resourceName = "tertiary_fixed_dim", + tonalPalette = TonalPalette.TERTIARY, + colorIndex = 4 + ) + ) + add( + ColorMapping( + resourceName = "on_tertiary_fixed", + tonalPalette = TonalPalette.TERTIARY, + colorIndex = 11 + ) + ) + add( + ColorMapping( + resourceName = "on_tertiary_fixed_variant", + tonalPalette = TonalPalette.TERTIARY, + colorIndex = 9 + ) + ) + } - // Google uses "gm3" prefix for these resources, MaterialComponents use "m3" instead. - M3_REF_PALETTE.add( - Pair.create( - "m3_ref_palette_dynamic_neutral4", - Pair.create(-60, Pair.create(3, 11)) - ) - ) - M3_REF_PALETTE.add( - Pair.create( - "m3_ref_palette_dynamic_neutral6", - Pair.create(-40, Pair.create(3, 11)) - ) - ) - M3_REF_PALETTE.add( - Pair.create( - "m3_ref_palette_dynamic_neutral12", - Pair.create(20, Pair.create(3, 10)) - ) - ) - M3_REF_PALETTE.add( - Pair.create( - "m3_ref_palette_dynamic_neutral17", - Pair.create(70, Pair.create(3, 10)) - ) - ) - M3_REF_PALETTE.add( - Pair.create( - "m3_ref_palette_dynamic_neutral22", - Pair.create(20, Pair.create(3, 10)) - ) - ) - M3_REF_PALETTE.add( - Pair.create( - "m3_ref_palette_dynamic_neutral24", - Pair.create(40, Pair.create(3, 10)) - ) - ) - M3_REF_PALETTE.add( - Pair.create( - "m3_ref_palette_dynamic_neutral87", - Pair.create(70, Pair.create(3, 4)) - ) - ) - M3_REF_PALETTE.add( - Pair.create( - "m3_ref_palette_dynamic_neutral92", - Pair.create(20, Pair.create(3, 3)) - ) - ) - M3_REF_PALETTE.add( - Pair.create( - "m3_ref_palette_dynamic_neutral94", - Pair.create(40, Pair.create(3, 3)) - ) - ) - M3_REF_PALETTE.add( - Pair.create( - "m3_ref_palette_dynamic_neutral96", - Pair.create(10, Pair.create(3, 2)) - ) - ) - M3_REF_PALETTE.add( - Pair.create( - "m3_ref_palette_dynamic_neutral98", - Pair.create(30, Pair.create(3, 2)) - ) - ) - M3_REF_PALETTE.add( - Pair.create( - "m3_ref_palette_dynamic_neutral_variant4", - Pair.create(-60, Pair.create(4, 11)) - ) - ) - M3_REF_PALETTE.add( - Pair.create( - "m3_ref_palette_dynamic_neutral_variant6", - Pair.create(-40, Pair.create(4, 11)) - ) - ) - M3_REF_PALETTE.add( - Pair.create( - "m3_ref_palette_dynamic_neutral_variant12", - Pair.create(20, Pair.create(4, 10)) - ) - ) - M3_REF_PALETTE.add( - Pair.create( - "m3_ref_palette_dynamic_neutral_variant17", - Pair.create(70, Pair.create(4, 10)) - ) - ) - M3_REF_PALETTE.add( - Pair.create( - "m3_ref_palette_dynamic_neutral_variant22", - Pair.create(20, Pair.create(4, 10)) - ) - ) - M3_REF_PALETTE.add( - Pair.create( - "m3_ref_palette_dynamic_neutral_variant24", - Pair.create(40, Pair.create(4, 10)) - ) - ) - M3_REF_PALETTE.add( - Pair.create( - "m3_ref_palette_dynamic_neutral_variant87", - Pair.create(70, Pair.create(4, 4)) - ) - ) - M3_REF_PALETTE.add( - Pair.create( - "m3_ref_palette_dynamic_neutral_variant92", - Pair.create(20, Pair.create(4, 3)) - ) - ) - M3_REF_PALETTE.add( - Pair.create( - "m3_ref_palette_dynamic_neutral_variant94", - Pair.create(40, Pair.create(4, 3)) - ) - ) - M3_REF_PALETTE.add( - Pair.create( - "m3_ref_palette_dynamic_neutral_variant96", - Pair.create(10, Pair.create(4, 2)) - ) - ) - M3_REF_PALETTE.add( - Pair.create( - "m3_ref_palette_dynamic_neutral_variant98", - Pair.create(30, Pair.create(4, 2)) - ) - ) + /* + * **M3 ref colors:** + * -> First item is the name of the color. + * -> Second item is the lightness percentage to increase or decrease + * from the base color given by the second item of the inner pair. + * -> Third item is the tonal palette index. + * 0 = primary + * 1 = secondary + * 2 = tertiary + * 3 = neutral + * 4 = neutral variant + * -> Fourth item is the color index. + * + * Google uses "gm3" prefix for these resources, MaterialComponents uses "m3" instead. + */ + M3_REF_PALETTE.apply { + add( + ColorMapping( + resourceName = "m3_ref_palette_dynamic_neutral4", + lightnessAdjustment = -60, + tonalPalette = TonalPalette.NEUTRAL, + colorIndex = 11 + ) + ) + add( + ColorMapping( + resourceName = "m3_ref_palette_dynamic_neutral6", + lightnessAdjustment = -40, + tonalPalette = TonalPalette.NEUTRAL, + colorIndex = 11 + ) + ) + add( + ColorMapping( + resourceName = "m3_ref_palette_dynamic_neutral12", + lightnessAdjustment = 20, + tonalPalette = TonalPalette.NEUTRAL, + colorIndex = 10 + ) + ) + add( + ColorMapping( + resourceName = "m3_ref_palette_dynamic_neutral17", + lightnessAdjustment = 70, + tonalPalette = TonalPalette.NEUTRAL, + colorIndex = 10 + ) + ) + add( + ColorMapping( + resourceName = "m3_ref_palette_dynamic_neutral22", + lightnessAdjustment = 20, + tonalPalette = TonalPalette.NEUTRAL, + colorIndex = 11 + ) + ) + add( + ColorMapping( + resourceName = "m3_ref_palette_dynamic_neutral24", + lightnessAdjustment = 40, + tonalPalette = TonalPalette.NEUTRAL, + colorIndex = 11 + ) + ) + add( + ColorMapping( + resourceName = "m3_ref_palette_dynamic_neutral87", + lightnessAdjustment = 70, + tonalPalette = TonalPalette.NEUTRAL, + colorIndex = 4 + ) + ) + add( + ColorMapping( + resourceName = "m3_ref_palette_dynamic_neutral92", + lightnessAdjustment = 20, + tonalPalette = TonalPalette.NEUTRAL, + colorIndex = 3 + ) + ) + add( + ColorMapping( + resourceName = "m3_ref_palette_dynamic_neutral94", + lightnessAdjustment = 40, + tonalPalette = TonalPalette.NEUTRAL, + colorIndex = 3 + ) + ) + add( + ColorMapping( + resourceName = "m3_ref_palette_dynamic_neutral96", + lightnessAdjustment = 10, + tonalPalette = TonalPalette.NEUTRAL, + colorIndex = 2 + ) + ) + add( + ColorMapping( + resourceName = "m3_ref_palette_dynamic_neutral98", + lightnessAdjustment = 30, + tonalPalette = TonalPalette.NEUTRAL, + colorIndex = 2 + ) + ) + add( + ColorMapping( + resourceName = "m3_ref_palette_dynamic_neutral_variant4", + lightnessAdjustment = -60, + tonalPalette = TonalPalette.NEUTRAL_VARIANT, + colorIndex = 11 + ) + ) + add( + ColorMapping( + resourceName = "m3_ref_palette_dynamic_neutral_variant6", + lightnessAdjustment = -40, + tonalPalette = TonalPalette.NEUTRAL_VARIANT, + colorIndex = 11 + ) + ) + add( + ColorMapping( + resourceName = "m3_ref_palette_dynamic_neutral_variant12", + lightnessAdjustment = 20, + tonalPalette = TonalPalette.NEUTRAL_VARIANT, + colorIndex = 10 + ) + ) + add( + ColorMapping( + resourceName = "m3_ref_palette_dynamic_neutral_variant17", + lightnessAdjustment = 70, + tonalPalette = TonalPalette.NEUTRAL_VARIANT, + colorIndex = 10 + ) + ) + add( + ColorMapping( + resourceName = "m3_ref_palette_dynamic_neutral_variant22", + lightnessAdjustment = 20, + tonalPalette = TonalPalette.NEUTRAL_VARIANT, + colorIndex = 11 + ) + ) + add( + ColorMapping( + resourceName = "m3_ref_palette_dynamic_neutral_variant24", + lightnessAdjustment = 40, + tonalPalette = TonalPalette.NEUTRAL_VARIANT, + colorIndex = 11 + ) + ) + add( + ColorMapping( + resourceName = "m3_ref_palette_dynamic_neutral_variant87", + lightnessAdjustment = 70, + tonalPalette = TonalPalette.NEUTRAL_VARIANT, + colorIndex = 4 + ) + ) + add( + ColorMapping( + resourceName = "m3_ref_palette_dynamic_neutral_variant92", + lightnessAdjustment = 20, + tonalPalette = TonalPalette.NEUTRAL_VARIANT, + colorIndex = 3 + ) + ) + add( + ColorMapping( + resourceName = "m3_ref_palette_dynamic_neutral_variant94", + lightnessAdjustment = 40, + tonalPalette = TonalPalette.NEUTRAL_VARIANT, + colorIndex = 3 + ) + ) + add( + ColorMapping( + resourceName = "m3_ref_palette_dynamic_neutral_variant96", + lightnessAdjustment = 10, + tonalPalette = TonalPalette.NEUTRAL_VARIANT, + colorIndex = 2 + ) + ) + add( + ColorMapping( + resourceName = "m3_ref_palette_dynamic_neutral_variant98", + lightnessAdjustment = 30, + tonalPalette = TonalPalette.NEUTRAL_VARIANT, + colorIndex = 2 + ) + ) + } } } diff --git a/app/src/main/java/com/drdisagree/colorblendr/utils/FabricatedUtil.kt b/app/src/main/java/com/drdisagree/colorblendr/utils/FabricatedUtil.kt index 4fa8312..1d779cf 100644 --- a/app/src/main/java/com/drdisagree/colorblendr/utils/FabricatedUtil.kt +++ b/app/src/main/java/com/drdisagree/colorblendr/utils/FabricatedUtil.kt @@ -8,7 +8,6 @@ import androidx.core.util.Pair import com.drdisagree.colorblendr.common.Const import com.drdisagree.colorblendr.config.RPrefs import com.drdisagree.colorblendr.utils.fabricated.FabricatedOverlayResource -import java.util.function.Consumer object FabricatedUtil { private val colorNames: Array> = ColorUtil.colorNames @@ -39,50 +38,59 @@ object FabricatedUtil { assignFixedColorsToOverlay(overlay, paletteLight) } - @Suppress("UNCHECKED_CAST") private fun assignDynamicPaletteToOverlay( overlay: FabricatedOverlayResource, isDark: Boolean, palette: ArrayList> ) { val suffix = if (isDark) "dark" else "light" - val pitchBlackTheme = RPrefs.getBoolean(Const.MONET_PITCH_BLACK_THEME, false) - - DynamicColors.ALL_DYNAMIC_COLORS_MAPPED.forEach(Consumer { pair: Pair -> - val resourceName = "system_" + pair.first + "_" + suffix - var colorValue: Int + val isPitchBlackTheme = RPrefs.getBoolean(Const.MONET_PITCH_BLACK_THEME, false) + + DynamicColors.ALL_DYNAMIC_COLORS_MAPPED.forEach { colorMapping -> + val pair = extractResourceFromColorMapping( + colorMapping = colorMapping, + prefix = "system_", + suffix = suffix, + palette = palette, + isDark = isDark + ) + val resourceName = pair.first + var colorValue: Int = pair.second - val valPair = pair.second as Pair? - if (valPair!!.first is String) { - colorValue = Color.parseColor( - (if (isDark) valPair.second else valPair.first - ) as String - ) - } else { - val colorIndexPair = valPair.second as Pair - colorValue = - palette[(valPair.first as Int)][if (isDark) colorIndexPair.second else colorIndexPair.first] + if (colorMapping.tonalPalette != null) { + val colorIndex = colorMapping.colorIndex ?: if (isDark) { + colorMapping.darkModeColorIndex + } else { + colorMapping.lightModeColorIndex + }!! colorValue = replaceColorForPitchBlackTheme( - pitchBlackTheme, - resourceName, - colorValue, - if (isDark) colorIndexPair.second else colorIndexPair.first + pitchBlackTheme = isPitchBlackTheme, + resourceName = resourceName, + colorValue = colorValue, + colorIndex = colorIndex ) } + overlay.setColor(resourceName, colorValue) - }) + } } private fun assignFixedColorsToOverlay( overlay: FabricatedOverlayResource, paletteLight: ArrayList> ) { - DynamicColors.FIXED_COLORS_MAPPED.forEach(Consumer { pair: Pair> -> - val resourceName = "system_" + pair.first - val colorValue = paletteLight[pair.second!!.first!!][pair.second!!.second!!] + DynamicColors.FIXED_COLORS_MAPPED.forEach { colorMapping -> + val pair = extractResourceFromColorMapping( + colorMapping = colorMapping, + prefix = "system_", + palette = paletteLight + ) + val resourceName = pair.first + val colorValue = pair.second + overlay.setColor(resourceName, colorValue) - }) + } } fun assignPerAppColorsToOverlay( @@ -91,25 +99,38 @@ object FabricatedUtil { ) { val pitchBlackTheme = RPrefs.getBoolean(Const.MONET_PITCH_BLACK_THEME, false) - // Format of pair: >> - DynamicColors.M3_REF_PALETTE.forEach(Consumer { pair: Pair>> -> - val resourceName = pair.first - val valPair = pair.second - - // TODO: Use lightness value to modify the color - // int lightnessToChange = valPair.first + 100; - val colorIndexPair = valPair!!.second - var baseColor = palette[colorIndexPair!!.first!!][colorIndexPair.second] - baseColor = replaceColorForPitchBlackTheme( - pitchBlackTheme, - resourceName, - baseColor, - colorIndexPair.second + DynamicColors.M3_REF_PALETTE.forEach { colorMapping -> + val pair = extractResourceFromColorMapping( + colorMapping = colorMapping, + palette = palette ) + val resourceName = pair.first + var colorValue = pair.second + + if (colorMapping.colorIndex != null) { + val colorIndex = colorMapping.colorIndex + + if (colorMapping.lightnessAdjustment != null) { + val lightnessAdjustment = colorMapping.lightnessAdjustment + 100 + + colorValue = ColorUtil.modifyLightness( + colorValue, + lightnessAdjustment, + colorIndex + ) + } + + colorValue = replaceColorForPitchBlackTheme( + pitchBlackTheme = pitchBlackTheme, + resourceName = resourceName, + colorValue = colorValue, + colorIndex = colorIndex + ) + } - overlay.setColor(resourceName, baseColor) - overlay.setColor("g$resourceName", baseColor) - }) + overlay.setColor(resourceName, colorValue) + overlay.setColor("g$resourceName", colorValue) + } for (i in 0..4) { for (j in 0..12) { @@ -150,33 +171,45 @@ object FabricatedUtil { @ColorInt fun replaceColorForPitchBlackTheme( pitchBlackTheme: Boolean, - resourceName: String?, + resourceName: String, colorValue: Int, colorIndex: Int ): Int { if (pitchBlackTheme) { val lightness = RPrefs.getInt(Const.MONET_BACKGROUND_LIGHTNESS, 100) + return when (resourceName) { - "m3_ref_palette_dynamic_neutral_variant6", "gm3_ref_palette_dynamic_neutral_variant6", "system_background_dark", "system_surface_dark" -> Color.BLACK - "m3_ref_palette_dynamic_neutral_variant12", "gm3_ref_palette_dynamic_neutral_variant12" -> ColorUtil.modifyLightness( - colorValue, - lightness - 40, - colorIndex - ) + "m3_ref_palette_dynamic_neutral_variant6", "gm3_ref_palette_dynamic_neutral_variant6", "system_background_dark", "system_surface_dark" -> { + Color.BLACK + } - "m3_ref_palette_dynamic_neutral_variant17", "gm3_ref_palette_dynamic_neutral_variant17", "gm3_system_bar_color_night" -> ColorUtil.modifyLightness( - colorValue, - lightness - 60, - colorIndex - ) + "m3_ref_palette_dynamic_neutral_variant12", "gm3_ref_palette_dynamic_neutral_variant12" -> { + ColorUtil.modifyLightness( + colorValue, + lightness - 40, + colorIndex + ) + } - "system_surface_container_dark" -> ColorUtil.modifyLightness( - colorValue, - lightness - 20, - colorIndex - ) + "m3_ref_palette_dynamic_neutral_variant17", "gm3_ref_palette_dynamic_neutral_variant17", "gm3_system_bar_color_night" -> { + ColorUtil.modifyLightness( + colorValue, + lightness - 60, + colorIndex + ) + } + + "system_surface_container_dark" -> { + ColorUtil.modifyLightness( + colorValue, + lightness - 20, + colorIndex + ) + } - else -> colorValue + else -> { + colorValue + } } } @@ -301,4 +334,34 @@ object FabricatedUtil { overlay.setColor("replay__pal_games_dark_300", palette[0][5]) } } + + private fun extractResourceFromColorMapping( + colorMapping: ColorMapping, + prefix: String = "", + suffix: String = "", + palette: ArrayList>, + isDark: Boolean = false + ): Pair { + val resourceName = prefix + colorMapping.resourceName + "_" + suffix + + val colorValue: Int = if (colorMapping.tonalPalette != null) { + if (colorMapping.colorIndex != null) { + palette[colorMapping.tonalPalette.index][colorMapping.colorIndex] + } else { + if (isDark) { + palette[colorMapping.tonalPalette.index][colorMapping.darkModeColorIndex!!] + } else { + palette[colorMapping.tonalPalette.index][colorMapping.lightModeColorIndex!!] + } + } + } else { + colorMapping.colorCode ?: if (isDark) { + colorMapping.darkModeColorCode + } else { + colorMapping.lightModeColorCode + } + }!! + + return Pair(resourceName, colorValue) + } } From f89be02df6fd35dc22f78dc78321df15f7907e44 Mon Sep 17 00:00:00 2001 From: DrDisagree Date: Sat, 17 Aug 2024 21:30:51 +0600 Subject: [PATCH 6/7] Fix shizuku theming issue when current settings is null --- .../com/drdisagree/colorblendr/ColorBlendr.kt | 4 +- .../extension/ThemeOverlayPackage.kt | 60 ++++++++++--------- .../provider/RootConnectionProvider.kt | 5 +- .../provider/ShizukuConnectionProvider.kt | 14 +++-- .../colorblendr/service/ShizukuConnection.kt | 34 +++++++---- .../ui/fragments/ColorsFragment.kt | 5 +- .../colorblendr/utils/OverlayManager.kt | 26 ++++++-- 7 files changed, 91 insertions(+), 57 deletions(-) diff --git a/app/src/main/java/com/drdisagree/colorblendr/ColorBlendr.kt b/app/src/main/java/com/drdisagree/colorblendr/ColorBlendr.kt index 3289a95..7a8d6ca 100644 --- a/app/src/main/java/com/drdisagree/colorblendr/ColorBlendr.kt +++ b/app/src/main/java/com/drdisagree/colorblendr/ColorBlendr.kt @@ -49,10 +49,10 @@ class ColorBlendr : Application() { @JvmStatic val rootConnection: IRootConnection? - get() = RootConnectionProvider.serviceProvider + get() = RootConnectionProvider.getServiceProvider @JvmStatic val shizukuConnection: IShizukuConnection? - get() = ShizukuConnectionProvider.serviceProvider + get() = ShizukuConnectionProvider.getServiceProvider } } \ No newline at end of file diff --git a/app/src/main/java/com/drdisagree/colorblendr/extension/ThemeOverlayPackage.kt b/app/src/main/java/com/drdisagree/colorblendr/extension/ThemeOverlayPackage.kt index 030922e..0e60e69 100644 --- a/app/src/main/java/com/drdisagree/colorblendr/extension/ThemeOverlayPackage.kt +++ b/app/src/main/java/com/drdisagree/colorblendr/extension/ThemeOverlayPackage.kt @@ -11,6 +11,7 @@ import com.drdisagree.colorblendr.utils.ColorUtil.intToHexColorNoHash import org.json.JSONObject object ThemeOverlayPackage { + private val TAG: String = ThemeOverlayPackage::class.java.simpleName const val THEME_STYLE: String = "android.theme.customization.theme_style" const val COLOR_SOURCE: String = "android.theme.customization.color_source" @@ -21,26 +22,21 @@ object ThemeOverlayPackage { val themeCustomizationOverlayPackages: JSONObject get() { - val `object` = JSONObject() - - try { - `object`.putOpt( - THEME_STYLE, - getString(MONET_STYLE_ORIGINAL_NAME, "TONAL_SPOT") - ) - `object`.putOpt(COLOR_SOURCE, "preset") - `object`.putOpt( - SYSTEM_PALETTE, - intToHexColorNoHash( - getInt( - MONET_SEED_COLOR, - Color.BLUE + return try { + JSONObject().apply { + putOpt( + COLOR_SOURCE, + "preset" + ) + putOpt( + THEME_STYLE, + getString( + MONET_STYLE_ORIGINAL_NAME, + "TONAL_SPOT" ) ) - ) - if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.S_V2) { - `object`.putOpt( - ACCENT_COLOR, + putOpt( + SYSTEM_PALETTE, intToHexColorNoHash( getInt( MONET_SEED_COLOR, @@ -48,19 +44,25 @@ object ThemeOverlayPackage { ) ) ) + if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.S_V2) { + putOpt( + ACCENT_COLOR, + intToHexColorNoHash( + getInt( + MONET_SEED_COLOR, + Color.BLUE + ) + ) + ) + } + putOpt( + APPLIED_TIMESTAMP, + System.currentTimeMillis() + ) } - `object`.putOpt( - APPLIED_TIMESTAMP, - System.currentTimeMillis() - ) } catch (e: Exception) { - Log.e( - TAG, - "getThemeCustomizationOverlayPackages:", - e - ) + Log.e(TAG, "themeCustomizationOverlayPackages:", e) + JSONObject() } - - return `object` } } diff --git a/app/src/main/java/com/drdisagree/colorblendr/provider/RootConnectionProvider.kt b/app/src/main/java/com/drdisagree/colorblendr/provider/RootConnectionProvider.kt index f437f6f..3460abf 100644 --- a/app/src/main/java/com/drdisagree/colorblendr/provider/RootConnectionProvider.kt +++ b/app/src/main/java/com/drdisagree/colorblendr/provider/RootConnectionProvider.kt @@ -103,7 +103,7 @@ class RootConnectionProvider private constructor(private val context: Context) : companion object { private val TAG: String = RootConnectionProvider::class.java.simpleName - var serviceProvider: IRootConnection? = null + private var serviceProvider: IRootConnection? = null private var isServiceConnected = false private val mServiceConnectionTimer = CountDownLatch(1) @@ -113,6 +113,9 @@ class RootConnectionProvider private constructor(private val context: Context) : val isNotConnected: Boolean get() = !isServiceConnected + + val getServiceProvider: IRootConnection? + get() = serviceProvider } class Builder(context: Context) { diff --git a/app/src/main/java/com/drdisagree/colorblendr/provider/ShizukuConnectionProvider.kt b/app/src/main/java/com/drdisagree/colorblendr/provider/ShizukuConnectionProvider.kt index 1bf447a..3ff630b 100644 --- a/app/src/main/java/com/drdisagree/colorblendr/provider/ShizukuConnectionProvider.kt +++ b/app/src/main/java/com/drdisagree/colorblendr/provider/ShizukuConnectionProvider.kt @@ -2,14 +2,15 @@ package com.drdisagree.colorblendr.provider import android.content.ComponentName import android.content.ServiceConnection -import android.os.Handler import android.os.IBinder -import android.os.Looper import android.util.Log import com.drdisagree.colorblendr.service.IShizukuConnection import com.drdisagree.colorblendr.service.ShizukuConnection import com.drdisagree.colorblendr.utils.ShizukuUtil.bindUserService import com.drdisagree.colorblendr.utils.ShizukuUtil.getUserServiceArgs +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch object ShizukuConnectionProvider { @@ -18,8 +19,8 @@ object ShizukuConnectionProvider { private var isServiceConnected = false val serviceConnection: ServiceConnection = object : ServiceConnection { - override fun onServiceConnected(name: ComponentName, binder: IBinder) { - if (!binder.pingBinder()) { + override fun onServiceConnected(name: ComponentName, binder: IBinder?) { + if (binder == null || !binder.pingBinder()) { Log.w(TAG, "Service binder is null or not alive") return } @@ -40,12 +41,15 @@ object ShizukuConnectionProvider { val isNotConnected: Boolean get() = !isServiceConnected + val getServiceProvider: IShizukuConnection? + get() = serviceProvider + private fun bindServiceConnection() { if (isServiceConnected) { return } - Handler(Looper.getMainLooper()).post { + CoroutineScope(Dispatchers.Main).launch { bindUserService( getUserServiceArgs(ShizukuConnection::class.java), serviceConnection diff --git a/app/src/main/java/com/drdisagree/colorblendr/service/ShizukuConnection.kt b/app/src/main/java/com/drdisagree/colorblendr/service/ShizukuConnection.kt index 991536d..5c14db3 100644 --- a/app/src/main/java/com/drdisagree/colorblendr/service/ShizukuConnection.kt +++ b/app/src/main/java/com/drdisagree/colorblendr/service/ShizukuConnection.kt @@ -12,6 +12,11 @@ import org.json.JSONObject import kotlin.system.exitProcess class ShizukuConnection : IShizukuConnection.Stub { + + companion object { + private val TAG: String = ShizukuConnection::class.java.simpleName + } + constructor() { Log.i(TAG, "Constructed with no arguments") } @@ -30,13 +35,18 @@ class ShizukuConnection : IShizukuConnection.Stub { } override fun applyFabricatedColors(jsonString: String) { - val mCommand = + Log.i( + TAG, + "applyFabricatedColors: settings put secure $THEME_CUSTOMIZATION_OVERLAY_PACKAGES '$jsonString'" + ) + Shell.cmd( "settings put secure $THEME_CUSTOMIZATION_OVERLAY_PACKAGES '$jsonString'" - Shell.cmd(mCommand).exec() + ).exec() } override fun removeFabricatedColors() { try { + Log.i(TAG, "removeFabricatedColors: $originalSettings") applyFabricatedColors(originalSettings.toString()) } catch (e: Exception) { Log.e(TAG, "removeFabricatedColors: ", e) @@ -44,8 +54,15 @@ class ShizukuConnection : IShizukuConnection.Stub { } override fun getCurrentSettings(): String { - val mCommand = "settings get secure $THEME_CUSTOMIZATION_OVERLAY_PACKAGES" - return Shell.cmd(mCommand).exec().out[0] + val currentSettings = Shell.cmd( + "settings get secure $THEME_CUSTOMIZATION_OVERLAY_PACKAGES" + ).exec().out[0] + + return if (currentSettings == "null") { + JSONObject().toString() + } else { + currentSettings + } } @get:Throws(JSONException::class) @@ -68,14 +85,7 @@ class ShizukuConnection : IShizukuConnection.Stub { putOpt(ThemeOverlayPackage.COLOR_BOTH, "0") putOpt(ThemeOverlayPackage.COLOR_SOURCE, "home_wallpaper") - putOpt( - ThemeOverlayPackage.APPLIED_TIMESTAMP, - System.currentTimeMillis() - ) + putOpt(ThemeOverlayPackage.APPLIED_TIMESTAMP, System.currentTimeMillis()) } } - - companion object { - private val TAG: String = ShizukuConnection::class.java.simpleName - } } diff --git a/app/src/main/java/com/drdisagree/colorblendr/ui/fragments/ColorsFragment.kt b/app/src/main/java/com/drdisagree/colorblendr/ui/fragments/ColorsFragment.kt index 833ff25..955dc7c 100644 --- a/app/src/main/java/com/drdisagree/colorblendr/ui/fragments/ColorsFragment.kt +++ b/app/src/main/java/com/drdisagree/colorblendr/ui/fragments/ColorsFragment.kt @@ -243,10 +243,7 @@ class ColorsFragment : Fragment() { colorPreview.setSelected(colorList[i] == getInt(MONET_SEED_COLOR, Int.MIN_VALUE)) colorPreview.setOnClickListener { - putInt( - MONET_SEED_COLOR, - (colorPreview.tag as Int) - ) + putInt(MONET_SEED_COLOR, colorPreview.tag as Int) putBoolean(MONET_SEED_COLOR_ENABLED, !isWallpaperColors) binding.seedColorPicker.previewColor = colorPreview.tag as Int diff --git a/app/src/main/java/com/drdisagree/colorblendr/utils/OverlayManager.kt b/app/src/main/java/com/drdisagree/colorblendr/utils/OverlayManager.kt index 95bd528..4c961bf 100644 --- a/app/src/main/java/com/drdisagree/colorblendr/utils/OverlayManager.kt +++ b/app/src/main/java/com/drdisagree/colorblendr/utils/OverlayManager.kt @@ -22,6 +22,10 @@ object OverlayManager { private val colorNames: Array> = ColorUtil.colorNames fun enableOverlay(packageName: String) { + if (Const.workingMethod != Const.WorkMethod.ROOT) { + return + } + if (mRootConnection == null) { mRootConnection = rootConnection @@ -42,6 +46,10 @@ object OverlayManager { } fun disableOverlay(packageName: String) { + if (Const.workingMethod != Const.WorkMethod.ROOT) { + return + } + if (mRootConnection == null) { mRootConnection = rootConnection @@ -62,6 +70,10 @@ object OverlayManager { } fun isOverlayInstalled(packageName: String): Boolean { + if (Const.workingMethod != Const.WorkMethod.ROOT) { + return false + } + if (mRootConnection == null) { mRootConnection = rootConnection @@ -83,6 +95,10 @@ object OverlayManager { } fun isOverlayEnabled(packageName: String): Boolean { + if (Const.workingMethod != Const.WorkMethod.ROOT) { + return false + } + if (mRootConnection == null) { mRootConnection = rootConnection @@ -104,6 +120,10 @@ object OverlayManager { } fun uninstallOverlayUpdates(packageName: String) { + if (Const.workingMethod != Const.WorkMethod.ROOT) { + return + } + if (mRootConnection == null) { mRootConnection = rootConnection @@ -170,10 +190,8 @@ object OverlayManager { } suspend fun applyFabricatedColors(context: Context) { - if (!RPrefs.getBoolean( - Const.THEMING_ENABLED, - true - ) && !RPrefs.getBoolean(Const.SHIZUKU_THEMING_ENABLED, true) + if (!RPrefs.getBoolean(Const.THEMING_ENABLED, true) && + !RPrefs.getBoolean(Const.SHIZUKU_THEMING_ENABLED, true) ) { return } From b61626778f3015cf0d7cecdba519c7683dd39e57 Mon Sep 17 00:00:00 2001 From: DrDisagree Date: Sat, 17 Aug 2024 21:48:57 +0600 Subject: [PATCH 7/7] Bump version code --- app/build.gradle.kts | 4 ++-- fastlane/metadata/android/en-US/changelogs/15.txt | 10 ++++++++++ 2 files changed, 12 insertions(+), 2 deletions(-) create mode 100644 fastlane/metadata/android/en-US/changelogs/15.txt diff --git a/app/build.gradle.kts b/app/build.gradle.kts index cae5c66..cbd7aa0 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -13,8 +13,8 @@ android { defaultConfig { minSdk = 31 targetSdk = 34 - versionCode = 14 - versionName = "v1.6" + versionCode = 15 + versionName = "v1.7" } buildTypes { diff --git a/fastlane/metadata/android/en-US/changelogs/15.txt b/fastlane/metadata/android/en-US/changelogs/15.txt new file mode 100644 index 0000000..450e725 --- /dev/null +++ b/fastlane/metadata/android/en-US/changelogs/15.txt @@ -0,0 +1,10 @@ +Changelog: + +• Converted codebase to kotlin. +• Fixed lag issue while switching page. +• Fixed crash in certain situations. +• Adjust lightness for m3 ref palette. + +Note: Gboard is now obfuscated. RIP! + +Translation credit goes to all the contributors on our Crowdin platform.