Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Custom board background and theme improvement #1370

Merged
merged 41 commits into from
Jan 29, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
c4e7779
Try out new theme
veloce Dec 23, 2024
252820e
Cupertino theme
veloce Jan 14, 2025
298c137
More work on flex color scheme
veloce Jan 15, 2025
d3b5ae9
More wip on flex color scheme
veloce Jan 15, 2025
b7152fd
More work on flex color scheme
veloce Jan 15, 2025
1e82ccf
Flex theme fixes
veloce Jan 16, 2025
4d34101
More theme tweaks
veloce Jan 16, 2025
d97add0
More flex scheme tweaks
veloce Jan 19, 2025
09cdd4b
More work on flex theme
veloce Jan 20, 2025
048263a
More work on flex theme
veloce Jan 21, 2025
3e67c3b
More flex them tweaks
veloce Jan 23, 2025
657a6fc
Use a grid theme selector
veloce Jan 23, 2025
96060a6
WIP on custom board background themes
veloce Jan 23, 2025
7886ae6
More work on custom board background theme
veloce Jan 23, 2025
ff7ec6a
More work on board theme
veloce Jan 23, 2025
ffefc06
Color fixes
veloce Jan 23, 2025
ef2f74b
Fix lint
veloce Jan 23, 2025
43718bc
Fix board prefs in bg selector screen
veloce Jan 23, 2025
d35c930
Use global grey theme for now, more tweaks
veloce Jan 24, 2025
0c38ebb
Tweak clock style
veloce Jan 24, 2025
3648375
Restore android system theme
veloce Jan 25, 2025
c1c6694
Refactor
veloce Jan 25, 2025
2fe117b
Tweaks
veloce Jan 25, 2025
87fe3c1
First implem of custom image background
veloce Jan 26, 2025
0051a71
More work on custom image
veloce Jan 27, 2025
bda8235
More work on custom background theme
veloce Jan 27, 2025
c5595e9
Fix shimmer for transp scaffolds
veloce Jan 28, 2025
821b5f9
Tweak clock tool colors
veloce Jan 28, 2025
1d51b39
Move code to end of file
veloce Jan 28, 2025
98d70be
Make sure system scheme exists
veloce Jan 28, 2025
970e199
Fix board background select screen on tablets
veloce Jan 28, 2025
a203b88
Fix board alignment on portrait
veloce Jan 28, 2025
d75594e
Tweaks
veloce Jan 28, 2025
009a6ad
Ensure board background theme widget is not built on each state change
veloce Jan 29, 2025
0b50a27
Keep preferences notifiers alive
veloce Jan 29, 2025
1d6ee1f
Switch to system board when system colors are activated
veloce Jan 29, 2025
da08a91
List tile icon color tweak
veloce Jan 29, 2025
0d92027
More harmonization between android and ios
veloce Jan 29, 2025
b9985e9
More harmonization
veloce Jan 29, 2025
62dace7
Tweak listings dark background, fix for iOS
veloce Jan 29, 2025
873fba6
Fix lint
veloce Jan 29, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions android/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,4 @@ GeneratedPluginRegistrant.java
key.properties
**/*.keystore
**/*.jks
**/.cxx
6 changes: 6 additions & 0 deletions ios/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,8 @@ PODS:
- GoogleUtilities/UserDefaults (8.0.2):
- GoogleUtilities/Logger
- GoogleUtilities/Privacy
- image_picker_ios (0.0.1):
- Flutter
- nanopb (3.30910.0):
- nanopb/decode (= 3.30910.0)
- nanopb/encode (= 3.30910.0)
Expand Down Expand Up @@ -157,6 +159,7 @@ DEPENDENCIES:
- flutter_local_notifications (from `.symlinks/plugins/flutter_local_notifications/ios`)
- flutter_native_splash (from `.symlinks/plugins/flutter_native_splash/ios`)
- flutter_secure_storage (from `.symlinks/plugins/flutter_secure_storage/ios`)
- image_picker_ios (from `.symlinks/plugins/image_picker_ios/ios`)
- objective_c (from `.symlinks/plugins/objective_c/ios`)
- package_info_plus (from `.symlinks/plugins/package_info_plus/ios`)
- path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/darwin`)
Expand Down Expand Up @@ -211,6 +214,8 @@ EXTERNAL SOURCES:
:path: ".symlinks/plugins/flutter_native_splash/ios"
flutter_secure_storage:
:path: ".symlinks/plugins/flutter_secure_storage/ios"
image_picker_ios:
:path: ".symlinks/plugins/image_picker_ios/ios"
objective_c:
:path: ".symlinks/plugins/objective_c/ios"
package_info_plus:
Expand Down Expand Up @@ -257,6 +262,7 @@ SPEC CHECKSUMS:
flutter_secure_storage: 1ed9476fba7e7a782b22888f956cce43e2c62f13
GoogleDataTransport: aae35b7ea0c09004c3797d53c8c41f66f219d6a7
GoogleUtilities: 26a3abef001b6533cf678d3eb38fd3f614b7872d
image_picker_ios: 7fe1ff8e34c1790d6fff70a32484959f563a928a
nanopb: fad817b59e0457d11a5dfbde799381cd727c1275
objective_c: 89e720c30d716b036faf9c9684022048eee1eee2
package_info_plus: af8e2ca6888548050f16fa2f1938db7b5a5df499
Expand Down
3 changes: 3 additions & 0 deletions ios/Runner.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -424,6 +424,7 @@
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
SUPPORTS_MACCATALYST = NO;
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = YES;
SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD = NO;
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
Expand Down Expand Up @@ -566,6 +567,7 @@
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
SUPPORTS_MACCATALYST = NO;
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = YES;
SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD = NO;
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 5.0;
Expand Down Expand Up @@ -602,6 +604,7 @@
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
SUPPORTS_MACCATALYST = NO;
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = YES;
SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD = NO;
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
Expand Down
2 changes: 2 additions & 0 deletions ios/Runner/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,8 @@
</array>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>NSPhotoLibraryUsageDescription</key>
<string>Photo Library Access Warning</string>
<key>UIApplicationSupportsIndirectInputEvents</key>
<true/>
<key>UIBackgroundModes</key>
Expand Down
267 changes: 130 additions & 137 deletions lib/src/app.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import 'package:dynamic_color/dynamic_color.dart';
import 'package:flex_color_scheme/flex_color_scheme.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart' show SystemUiOverlayStyle;
import 'package:flutter_native_splash/flutter_native_splash.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:lichess_mobile/l10n/l10n.dart';
Expand All @@ -10,14 +11,13 @@ import 'package:lichess_mobile/src/model/challenge/challenge_service.dart';
import 'package:lichess_mobile/src/model/common/preloaded_data.dart';
import 'package:lichess_mobile/src/model/correspondence/correspondence_service.dart';
import 'package:lichess_mobile/src/model/notifications/notification_service.dart';
import 'package:lichess_mobile/src/model/settings/board_preferences.dart';
import 'package:lichess_mobile/src/model/settings/brightness.dart';
import 'package:lichess_mobile/src/model/settings/general_preferences.dart';
import 'package:lichess_mobile/src/navigation.dart';
import 'package:lichess_mobile/src/network/connectivity.dart';
import 'package:lichess_mobile/src/network/http.dart';
import 'package:lichess_mobile/src/network/socket.dart';
import 'package:lichess_mobile/src/styles/styles.dart';
import 'package:lichess_mobile/src/utils/color_palette.dart' show getSystemScheme;
import 'package:lichess_mobile/src/utils/screen.dart';

/// Application initialization and main entry point.
Expand Down Expand Up @@ -119,149 +119,142 @@ class _AppState extends ConsumerState<Application> {
@override
Widget build(BuildContext context) {
final generalPrefs = ref.watch(generalPreferencesProvider);
final isTablet = isTabletOrLarger(context);
final isIOS = Theme.of(context).platform == TargetPlatform.iOS;
final remainingHeight = estimateRemainingHeightLeftBoard(context);
final systemScheme = getSystemScheme();
final flexScheme =
generalPrefs.systemColors == true && systemScheme != null
? systemScheme
: FlexColor.espresso;
final themeLight = FlexThemeData.light(
colors: flexScheme.light,
surfaceMode: FlexSurfaceMode.highScaffoldLowSurface,
blendLevel: 10,
cupertinoOverrideTheme: const CupertinoThemeData(applyThemeToAll: true),
appBarStyle: isIOS ? null : FlexAppBarStyle.scaffoldBackground,
);
final themeDark = FlexThemeData.dark(
colors: flexScheme.dark,
surfaceMode: FlexSurfaceMode.level,
blendLevel: 40,
cupertinoOverrideTheme: const CupertinoThemeData(applyThemeToAll: true),
appBarStyle: isIOS ? null : FlexAppBarStyle.scaffoldBackground,
);

final brightness = ref.watch(currentBrightnessProvider);
final boardTheme = ref.watch(boardPreferencesProvider.select((state) => state.boardTheme));
final floatingActionButtonTheme =
generalPrefs.systemColors
? null
: FloatingActionButtonThemeData(
backgroundColor: themeLight.colorScheme.primaryFixedDim,
foregroundColor: themeLight.colorScheme.onPrimaryFixed,
);

final remainingHeight = estimateRemainingHeightLeftBoard(context);
const cupertinoTitleColor = CupertinoDynamicColor.withBrightness(
color: Color(0xFF000000),
darkColor: Color(0xFFF5F5F5),
);

return DynamicColorBuilder(
builder: (lightColorScheme, darkColorScheme) {
// TODO remove this workaround when the dynamic_color colorScheme bug is fixed
// See: https://github.com/material-foundation/flutter-packages/issues/574
final (fixedLightScheme, fixedDarkScheme) =
lightColorScheme != null && darkColorScheme != null
? _generateDynamicColourSchemes(lightColorScheme, darkColorScheme)
: (null, null);
final lightCupertino = CupertinoThemeData(
primaryColor: themeLight.colorScheme.primary,
primaryContrastingColor: themeLight.colorScheme.onPrimary,
brightness: Brightness.light,
scaffoldBackgroundColor: themeLight.scaffoldBackgroundColor,
barBackgroundColor: themeLight.appBarTheme.backgroundColor?.withValues(
alpha: isTablet ? 1.0 : 0.9,
),
textTheme: const CupertinoThemeData().textTheme.copyWith(
primaryColor: themeLight.colorScheme.primary,
textStyle: const CupertinoThemeData().textTheme.textStyle.copyWith(
color: themeLight.colorScheme.onSurface,
),
navTitleTextStyle: const CupertinoThemeData().textTheme.navTitleTextStyle.copyWith(
color: cupertinoTitleColor,
),
navLargeTitleTextStyle: const CupertinoThemeData().textTheme.navLargeTitleTextStyle
.copyWith(color: cupertinoTitleColor),
),
);

final isTablet = isTabletOrLarger(context);
final isIOS = Theme.of(context).platform == TargetPlatform.iOS;
final darkCupertino = CupertinoThemeData(
primaryColor: themeDark.colorScheme.primaryFixed,
primaryContrastingColor: themeDark.colorScheme.onPrimaryFixed,
brightness: Brightness.dark,
scaffoldBackgroundColor: themeDark.scaffoldBackgroundColor,
barBackgroundColor: themeDark.appBarTheme.backgroundColor?.withValues(
alpha: isTablet ? 1.0 : 0.9,
),
textTheme: const CupertinoThemeData().textTheme.copyWith(
primaryColor: themeDark.colorScheme.primaryFixed,
textStyle: const CupertinoThemeData().textTheme.textStyle.copyWith(
color: themeDark.colorScheme.onSurface,
),
navTitleTextStyle: const CupertinoThemeData().textTheme.navTitleTextStyle.copyWith(
color: cupertinoTitleColor,
),
navLargeTitleTextStyle: const CupertinoThemeData().textTheme.navLargeTitleTextStyle
.copyWith(color: cupertinoTitleColor),
),
);

final dynamicColorScheme =
brightness == Brightness.light ? fixedLightScheme : fixedDarkScheme;
// The high blend theme is used only for the navigation bar in light mode.
final highBlendThemeLight = FlexThemeData.light(
colors: flexScheme.light,
surfaceMode: FlexSurfaceMode.highBackgroundLowScaffold,
blendLevel: 16,
);

final ColorScheme colorScheme = switch (generalPrefs.appThemeSeed) {
AppThemeSeed.board => ColorScheme.fromSeed(
seedColor: boardTheme.colors.darkSquare,
brightness: brightness,
return AnnotatedRegion<SystemUiOverlayStyle>(
value: FlexColorScheme.themedSystemNavigationBar(
context,
systemNavBarStyle: FlexSystemNavBarStyle.transparent,
),
child: MaterialApp(
localizationsDelegates: AppLocalizations.localizationsDelegates,
supportedLocales: kSupportedLocales,
onGenerateTitle: (BuildContext context) => 'lichess.org',
locale: generalPrefs.locale,
theme: themeLight.copyWith(
cupertinoOverrideTheme: lightCupertino,
splashFactory: isIOS ? NoSplash.splashFactory : null,
textTheme: isIOS ? Typography.blackCupertino : null,
listTileTheme: ListTileTheme.of(context).copyWith(
titleTextStyle: isIOS ? lightCupertino.textTheme.textStyle : null,
subtitleTextStyle: isIOS ? lightCupertino.textTheme.textStyle : null,
leadingAndTrailingTextStyle: isIOS ? lightCupertino.textTheme.textStyle : null,
),
AppThemeSeed.system =>
dynamicColorScheme ??
ColorScheme.fromSeed(
seedColor: boardTheme.colors.darkSquare,
brightness: brightness,
),
};

final cupertinoThemeData = CupertinoThemeData(
primaryColor: colorScheme.primary,
primaryContrastingColor: colorScheme.onPrimary,
brightness: brightness,
textTheme: CupertinoTheme.of(context).textTheme.copyWith(
primaryColor: colorScheme.primary,
textStyle: CupertinoTheme.of(
context,
).textTheme.textStyle.copyWith(color: Styles.cupertinoLabelColor),
navTitleTextStyle: CupertinoTheme.of(
context,
).textTheme.navTitleTextStyle.copyWith(color: Styles.cupertinoTitleColor),
navLargeTitleTextStyle: CupertinoTheme.of(
context,
).textTheme.navLargeTitleTextStyle.copyWith(color: Styles.cupertinoTitleColor),
floatingActionButtonTheme: floatingActionButtonTheme,
navigationBarTheme: NavigationBarTheme.of(context).copyWith(
height: remainingHeight < kSmallRemainingHeightLeftBoardThreshold ? 60 : null,
backgroundColor: highBlendThemeLight.colorScheme.surface,
indicatorColor: darken(highBlendThemeLight.colorScheme.secondaryContainer, 0.05),
elevation: 3,
),
scaffoldBackgroundColor: Styles.cupertinoScaffoldColor,
barBackgroundColor:
isTablet ? Styles.cupertinoTabletAppBarColor : Styles.cupertinoAppBarColor,
);

return MaterialApp(
localizationsDelegates: AppLocalizations.localizationsDelegates,
supportedLocales: kSupportedLocales,
onGenerateTitle: (BuildContext context) => 'lichess.org',
locale: generalPrefs.locale,
theme: ThemeData.from(
colorScheme: colorScheme,
textTheme:
isIOS
? brightness == Brightness.light
? Typography.blackCupertino
: Styles.whiteCupertinoTextTheme
: null,
).copyWith(
splashFactory: isIOS ? NoSplash.splashFactory : null,
cupertinoOverrideTheme: cupertinoThemeData,
navigationBarTheme: NavigationBarTheme.of(context).copyWith(
height: remainingHeight < kSmallRemainingHeightLeftBoardThreshold ? 60 : null,
),
extensions: [lichessCustomColors.harmonized(colorScheme)],
extensions: [lichessCustomColors.harmonized(themeLight.colorScheme)],
),
darkTheme: themeDark.copyWith(
cupertinoOverrideTheme: darkCupertino,
splashFactory: isIOS ? NoSplash.splashFactory : null,
textTheme: isIOS ? Typography.whiteCupertino : null,
listTileTheme: ListTileTheme.of(context).copyWith(
titleTextStyle: isIOS ? darkCupertino.textTheme.textStyle : null,
subtitleTextStyle: isIOS ? darkCupertino.textTheme.textStyle : null,
leadingAndTrailingTextStyle: isIOS ? darkCupertino.textTheme.textStyle : null,
),
themeMode: switch (generalPrefs.themeMode) {
BackgroundThemeMode.light => ThemeMode.light,
BackgroundThemeMode.dark => ThemeMode.dark,
BackgroundThemeMode.system => ThemeMode.system,
},
builder:
Theme.of(context).platform == TargetPlatform.iOS
? (context, child) {
return CupertinoTheme(
data: cupertinoThemeData,
child: IconTheme.merge(
data: IconThemeData(
color: CupertinoTheme.of(context).textTheme.textStyle.color,
),
child: Material(child: child),
),
);
}
: null,
home: const BottomNavScaffold(),
navigatorObservers: [rootNavPageRouteObserver],
);
},
floatingActionButtonTheme: floatingActionButtonTheme,
navigationBarTheme: NavigationBarTheme.of(
context,
).copyWith(height: remainingHeight < kSmallRemainingHeightLeftBoardThreshold ? 60 : null),
extensions: [lichessCustomColors.harmonized(themeDark.colorScheme)],
),
themeMode: switch (generalPrefs.themeMode) {
BackgroundThemeMode.light => ThemeMode.light,
BackgroundThemeMode.dark => ThemeMode.dark,
BackgroundThemeMode.system => ThemeMode.system,
},
home: const BottomNavScaffold(),
navigatorObservers: [rootNavPageRouteObserver],
),
);
}
}

// --

(ColorScheme light, ColorScheme dark) _generateDynamicColourSchemes(
ColorScheme lightDynamic,
ColorScheme darkDynamic,
) {
final lightBase = ColorScheme.fromSeed(seedColor: lightDynamic.primary);
final darkBase = ColorScheme.fromSeed(
seedColor: darkDynamic.primary,
brightness: Brightness.dark,
);

final lightAdditionalColours = _extractAdditionalColours(lightBase);
final darkAdditionalColours = _extractAdditionalColours(darkBase);

final lightScheme = _insertAdditionalColours(lightBase, lightAdditionalColours);
final darkScheme = _insertAdditionalColours(darkBase, darkAdditionalColours);

return (lightScheme.harmonized(), darkScheme.harmonized());
}

List<Color> _extractAdditionalColours(ColorScheme scheme) => [
scheme.surface,
scheme.surfaceDim,
scheme.surfaceBright,
scheme.surfaceContainerLowest,
scheme.surfaceContainerLow,
scheme.surfaceContainer,
scheme.surfaceContainerHigh,
scheme.surfaceContainerHighest,
];

ColorScheme _insertAdditionalColours(ColorScheme scheme, List<Color> additionalColours) =>
scheme.copyWith(
surface: additionalColours[0],
surfaceDim: additionalColours[1],
surfaceBright: additionalColours[2],
surfaceContainerLowest: additionalColours[3],
surfaceContainerLow: additionalColours[4],
surfaceContainer: additionalColours[5],
surfaceContainerHigh: additionalColours[6],
surfaceContainerHighest: additionalColours[7],
);
6 changes: 3 additions & 3 deletions lib/src/init.dart
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ Future<void> setupFirstLaunch() async {
final installedVersion = prefs.getString('installed_version');

// TODO remove this migration code after a few releases
if (installedVersion != null && Version.parse(installedVersion) <= Version(0, 13, 9)) {
if (installedVersion != null && Version.parse(installedVersion) < Version(0, 13, 14)) {
_migrateThemeSettings();
}

Expand Down Expand Up @@ -68,9 +68,9 @@ Future<void> _migrateThemeSettings() async {
}
final generalPrefs = GeneralPrefs.fromJson(jsonDecode(stored) as Map<String, dynamic>);
final migrated = generalPrefs.copyWith(
appThemeSeed:
systemColors:
// ignore: deprecated_member_use_from_same_package
generalPrefs.systemColors == true ? AppThemeSeed.system : AppThemeSeed.board,
generalPrefs.appThemeSeed == AppThemeSeed.system,
);
await prefs.setString(PrefCategory.general.storageKey, jsonEncode(migrated.toJson()));
} catch (e) {
Expand Down
Loading