Custom Color scheme complete support added

This commit is contained in:
Kingkor Roy Tirtho 2022-05-26 23:17:57 +06:00
parent 94db62baa5
commit 066baa3745
8 changed files with 196 additions and 16 deletions

View File

@ -0,0 +1,136 @@
import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:spotube/provider/UserPreferences.dart';
final colorsMap = {
"Red": Colors.red,
"Pink": Colors.pink,
"Purple": Colors.purple,
"DeepPurple": Colors.deepPurple,
"Indigo": Colors.indigo,
"Blue": Colors.blue,
"LightBlue": Colors.lightBlue,
"Cyan": Colors.cyan,
"Teal": Colors.teal,
"Green": Colors.green,
"LightGreen": Colors.lightGreen,
"Lime": Colors.lime,
"Yellow": Colors.yellow,
"Amber": Colors.amber,
"Orange": Colors.orange,
"DeepOrange": Colors.deepOrange,
"Brown": Colors.brown,
"BlueGrey": Colors.blueGrey,
"Grey": Colors.grey,
};
enum ColorSchemeType {
accent,
background,
}
class ColorSchemePickerDialog extends HookConsumerWidget {
final ColorSchemeType schemeType;
const ColorSchemePickerDialog({required this.schemeType, Key? key})
: super(key: key);
@override
Widget build(BuildContext context, ref) {
final preferences = ref.watch(userPreferencesProvider);
final scheme = schemeType == ColorSchemeType.accent
? preferences.accentColorScheme
: preferences.backgroundColorScheme;
final active = useState<String>(colorsMap.entries.firstWhere(
(element) {
return scheme.value == element.value.value;
},
).key);
return AlertDialog(
title: Text("Pick ${schemeType.name} color scheme"),
actions: [
TextButton(
child: const Text("Cancel"),
onPressed: () {
Navigator.pop(context);
},
),
ElevatedButton(
child: const Text("Save"),
onPressed: () {
switch (schemeType) {
case ColorSchemeType.accent:
preferences.setAccentColorScheme(colorsMap[active.value]!);
break;
default:
preferences.setBackgroundColorScheme(
colorsMap[active.value]!,
);
}
Navigator.pop(context);
},
)
],
content: SizedBox(
height: 200,
width: 400,
child: Center(
child: Wrap(
spacing: 10,
runSpacing: 10,
children: colorsMap.entries
.map(
(e) => ColorTile(
color: e.value,
isActive: active.value == e.key,
tooltip: e.key,
onPressed: () {
active.value = e.key;
},
),
)
.toList(),
),
),
),
);
}
}
class ColorTile extends StatelessWidget {
final MaterialColor color;
final bool isActive;
final void Function()? onPressed;
final String? tooltip;
const ColorTile({
required this.color,
this.isActive = false,
this.onPressed,
this.tooltip = "",
Key? key,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return Tooltip(
message: tooltip,
child: GestureDetector(
onTap: onPressed,
child: Container(
height: 50,
width: 50,
decoration: BoxDecoration(
border: isActive
? const Border.fromBorderSide(
BorderSide(color: Colors.black, width: 5),
)
: null,
shape: BoxShape.circle,
color: color,
),
),
),
);
}
}

View File

@ -5,6 +5,7 @@ import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:go_router/go_router.dart'; import 'package:go_router/go_router.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:shared_preferences/shared_preferences.dart'; import 'package:shared_preferences/shared_preferences.dart';
import 'package:spotube/components/Settings/ColorSchemePickerDialog.dart';
import 'package:spotube/components/Settings/SettingsHotkeyTile.dart'; import 'package:spotube/components/Settings/SettingsHotkeyTile.dart';
import 'package:spotube/components/Shared/Hyperlink.dart'; import 'package:spotube/components/Shared/Hyperlink.dart';
import 'package:spotube/components/Shared/PageWindowTitleBar.dart'; import 'package:spotube/components/Shared/PageWindowTitleBar.dart';
@ -39,6 +40,16 @@ class Settings extends HookConsumerWidget {
packageName: 'spotube', packageName: 'spotube',
); );
final pickColorScheme = useCallback((ColorSchemeType schemeType) {
return () => showDialog(
context: context,
builder: (context) {
return ColorSchemePickerDialog(
schemeType: schemeType,
);
});
}, []);
return SafeArea( return SafeArea(
child: Scaffold( child: Scaffold(
appBar: PageWindowTitleBar( appBar: PageWindowTitleBar(
@ -159,6 +170,27 @@ class Settings extends HookConsumerWidget {
], ],
), ),
const SizedBox(height: 10), const SizedBox(height: 10),
ListTile(
title: const Text("Accent Color Scheme"),
trailing: ColorTile(
color: preferences.accentColorScheme,
onPressed: pickColorScheme(ColorSchemeType.accent),
isActive: true,
),
onTap: pickColorScheme(ColorSchemeType.accent),
),
const SizedBox(height: 10),
ListTile(
title: const Text("Background Color Scheme"),
trailing: ColorTile(
color: preferences.backgroundColorScheme,
onPressed:
pickColorScheme(ColorSchemeType.background),
isActive: true,
),
onTap: pickColorScheme(ColorSchemeType.background),
),
const SizedBox(height: 10),
Row( Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [ children: [

View File

@ -47,6 +47,10 @@ class MyApp extends HookConsumerWidget {
Widget build(BuildContext context, ref) { Widget build(BuildContext context, ref) {
final themeMode = final themeMode =
ref.watch(userPreferencesProvider.select((s) => s.themeMode)); ref.watch(userPreferencesProvider.select((s) => s.themeMode));
final accentMaterialColor =
ref.watch(userPreferencesProvider.select((s) => s.accentColorScheme));
final backgroundMaterialColor = ref
.watch(userPreferencesProvider.select((s) => s.backgroundColorScheme));
final player = ref.watch(audioPlayerProvider); final player = ref.watch(audioPlayerProvider);
final youtube = ref.watch(youtubeProvider); final youtube = ref.watch(youtubeProvider);
useEffect(() { useEffect(() {
@ -62,12 +66,12 @@ class MyApp extends HookConsumerWidget {
debugShowCheckedModeBanner: false, debugShowCheckedModeBanner: false,
title: 'Spotube', title: 'Spotube',
theme: lightTheme( theme: lightTheme(
accentMaterialColor: Colors.deepPurple, accentMaterialColor: accentMaterialColor,
backgroundMaterialColor: Colors.grey, backgroundMaterialColor: backgroundMaterialColor,
), ),
darkTheme: darkTheme( darkTheme: darkTheme(
accentMaterialColor: Colors.purple, accentMaterialColor: accentMaterialColor,
backgroundMaterialColor: Colors.grey, backgroundMaterialColor: backgroundMaterialColor,
), ),
themeMode: themeMode, themeMode: themeMode,
); );

View File

@ -1,14 +1,13 @@
import 'package:go_router/go_router.dart'; import 'package:go_router/go_router.dart';
import 'package:palette_generator/palette_generator.dart';
import 'package:spotify/spotify.dart'; import 'package:spotify/spotify.dart';
import 'package:spotube/components/Album/AlbumView.dart'; import 'package:spotube/components/Album/AlbumView.dart';
import 'package:spotube/components/Artist/ArtistAlbumView.dart'; import 'package:spotube/components/Artist/ArtistAlbumView.dart';
import 'package:spotube/components/Artist/ArtistProfile.dart'; import 'package:spotube/components/Artist/ArtistProfile.dart';
import 'package:spotube/components/Home/Home.dart'; import 'package:spotube/components/Home/Home.dart';
import 'package:spotube/components/Login.dart'; import 'package:spotube/components/Settings/Login.dart';
import 'package:spotube/components/Player/PlayerView.dart'; import 'package:spotube/components/Player/PlayerView.dart';
import 'package:spotube/components/Playlist/PlaylistView.dart'; import 'package:spotube/components/Playlist/PlaylistView.dart';
import 'package:spotube/components/Settings.dart'; import 'package:spotube/components/Settings/Settings.dart';
import 'package:spotube/components/Shared/SpotubePageRoute.dart'; import 'package:spotube/components/Shared/SpotubePageRoute.dart';
GoRouter createGoRouter() => GoRouter( GoRouter createGoRouter() => GoRouter(

View File

@ -4,9 +4,11 @@ import 'dart:convert';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:hotkey_manager/hotkey_manager.dart'; import 'package:hotkey_manager/hotkey_manager.dart';
import 'package:spotube/components/Settings/ColorSchemePickerDialog.dart';
import 'package:spotube/helpers/get-random-element.dart'; import 'package:spotube/helpers/get-random-element.dart';
import 'package:spotube/models/generated_secrets.dart'; import 'package:spotube/models/generated_secrets.dart';
import 'package:spotube/utils/PersistedChangeNotifier.dart'; import 'package:spotube/utils/PersistedChangeNotifier.dart';
import 'package:collection/collection.dart';
class UserPreferences extends PersistedChangeNotifier { class UserPreferences extends PersistedChangeNotifier {
ThemeMode themeMode; ThemeMode themeMode;
@ -18,19 +20,19 @@ class UserPreferences extends PersistedChangeNotifier {
HotKey? prevTrackHotKey; HotKey? prevTrackHotKey;
HotKey? playPauseHotKey; HotKey? playPauseHotKey;
MaterialColor? accentColorScheme; MaterialColor accentColorScheme;
MaterialColor? backgroundColorScheme; MaterialColor backgroundColorScheme;
UserPreferences({ UserPreferences({
required this.geniusAccessToken, required this.geniusAccessToken,
required this.recommendationMarket, required this.recommendationMarket,
required this.themeMode, required this.themeMode,
required this.ytSearchFormat, required this.ytSearchFormat,
this.saveTrackLyrics = false, this.saveTrackLyrics = false,
this.accentColorScheme = Colors.green,
this.backgroundColorScheme = Colors.grey,
this.nextTrackHotKey, this.nextTrackHotKey,
this.prevTrackHotKey, this.prevTrackHotKey,
this.playPauseHotKey, this.playPauseHotKey,
this.accentColorScheme,
this.backgroundColorScheme,
}) : super(); }) : super();
void setThemeMode(ThemeMode mode) { void setThemeMode(ThemeMode mode) {
@ -110,6 +112,12 @@ class UserPreferences extends PersistedChangeNotifier {
: null; : null;
ytSearchFormat = map["ytSearchFormat"] ?? ytSearchFormat; ytSearchFormat = map["ytSearchFormat"] ?? ytSearchFormat;
themeMode = ThemeMode.values[map["themeMode"] ?? 0]; themeMode = ThemeMode.values[map["themeMode"] ?? 0];
backgroundColorScheme = colorsMap.values
.firstWhereOrNull((e) => e.value == map["backgroundColorScheme"]) ??
backgroundColorScheme;
accentColorScheme = colorsMap.values
.firstWhereOrNull((e) => e.value == map["accentColorScheme"]) ??
accentColorScheme;
} }
@override @override
@ -123,6 +131,8 @@ class UserPreferences extends PersistedChangeNotifier {
"playPauseHotKey": jsonEncode(playPauseHotKey?.toJson() ?? {}), "playPauseHotKey": jsonEncode(playPauseHotKey?.toJson() ?? {}),
"ytSearchFormat": ytSearchFormat, "ytSearchFormat": ytSearchFormat,
"themeMode": themeMode.index, "themeMode": themeMode.index,
"backgroundColorScheme": backgroundColorScheme.value,
"accentColorScheme": accentColorScheme.value,
}; };
} }
} }

View File

@ -1,8 +1,8 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
ThemeData darkTheme({ ThemeData darkTheme({
MaterialColor accentMaterialColor = Colors.green, required MaterialColor accentMaterialColor,
MaterialColor backgroundMaterialColor = Colors.blueGrey, required MaterialColor backgroundMaterialColor,
}) { }) {
return ThemeData( return ThemeData(
useMaterial3: true, useMaterial3: true,

View File

@ -14,10 +14,9 @@ final materialWhite = MaterialColor(Colors.white.value, {
}); });
ThemeData lightTheme({ ThemeData lightTheme({
MaterialColor accentMaterialColor = Colors.green, required MaterialColor accentMaterialColor,
MaterialColor? backgroundMaterialColor, required MaterialColor backgroundMaterialColor,
}) { }) {
backgroundMaterialColor ??= materialWhite;
return ThemeData( return ThemeData(
useMaterial3: true, useMaterial3: true,
primaryColor: accentMaterialColor, primaryColor: accentMaterialColor,