Skip to content

Commit

Permalink
Merge pull request #1064 from nextcloud/fix/neon/nextcloud-theme-cont…
Browse files Browse the repository at this point in the history
…rast
  • Loading branch information
provokateurin authored Nov 2, 2023
2 parents 64f1c18 + f93226b commit a50b341
Show file tree
Hide file tree
Showing 11 changed files with 119 additions and 68 deletions.
4 changes: 4 additions & 0 deletions packages/app/linux/flutter/generated_plugin_registrant.cc
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,17 @@

#include "generated_plugin_registrant.h"

#include <dynamic_color/dynamic_color_plugin.h>
#include <file_selector_linux/file_selector_plugin.h>
#include <screen_retriever/screen_retriever_plugin.h>
#include <tray_manager/tray_manager_plugin.h>
#include <url_launcher_linux/url_launcher_plugin.h>
#include <window_manager/window_manager_plugin.h>

void fl_register_plugins(FlPluginRegistry* registry) {
g_autoptr(FlPluginRegistrar) dynamic_color_registrar =
fl_plugin_registry_get_registrar_for_plugin(registry, "DynamicColorPlugin");
dynamic_color_plugin_register_with_registrar(dynamic_color_registrar);
g_autoptr(FlPluginRegistrar) file_selector_linux_registrar =
fl_plugin_registry_get_registrar_for_plugin(registry, "FileSelectorPlugin");
file_selector_plugin_register_with_registrar(file_selector_linux_registrar);
Expand Down
1 change: 1 addition & 0 deletions packages/app/linux/flutter/generated_plugins.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#

list(APPEND FLUTTER_PLUGIN_LIST
dynamic_color
file_selector_linux
screen_retriever
tray_manager
Expand Down
8 changes: 8 additions & 0 deletions packages/app/pubspec.lock
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "3.2.3"
dynamic_color:
dependency: transitive
description:
name: dynamic_color
sha256: "8b8bd1d798bd393e11eddeaa8ae95b12ff028bf7d5998fc5d003488cd5f4ce2f"
url: "https://pub.dev"
source: hosted
version: "1.6.8"
dynamite_runtime:
dependency: "direct overridden"
description:
Expand Down
2 changes: 1 addition & 1 deletion packages/neon/neon/lib/l10n/en.arb
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@
"globalOptionsThemeModeDark": "Dark",
"globalOptionsThemeModeAutomatic": "Automatic",
"globalOptionsThemeOLEDAsDark": "OLED theme as dark theme",
"globalOptionsThemeKeepOriginalAccentColor": "Keep the original accent color",
"globalOptionsThemeUseNextcloudTheme": "Use Nextcloud theme",
"globalOptionsPushNotificationsEnabled": "Enabled",
"globalOptionsPushNotificationsEnabledDisabledNotice": "No UnifiedPush distributor could be found or you denied the permission for showing notifications. Please go to the app settings and allow notifications and go to https://unifiedpush.org/users/distributors and setup any of the listed distributors. Then re-open this app and you should be able to enable notifications",
"globalOptionsPushNotificationsDistributor": "UnifiedPush Distributor",
Expand Down
6 changes: 3 additions & 3 deletions packages/neon/neon/lib/l10n/localizations.dart
Original file line number Diff line number Diff line change
Expand Up @@ -509,11 +509,11 @@ abstract class NeonLocalizations {
/// **'OLED theme as dark theme'**
String get globalOptionsThemeOLEDAsDark;

/// No description provided for @globalOptionsThemeKeepOriginalAccentColor.
/// No description provided for @globalOptionsThemeUseNextcloudTheme.
///
/// In en, this message translates to:
/// **'Keep the original accent color'**
String get globalOptionsThemeKeepOriginalAccentColor;
/// **'Use Nextcloud theme'**
String get globalOptionsThemeUseNextcloudTheme;

/// No description provided for @globalOptionsPushNotificationsEnabled.
///
Expand Down
2 changes: 1 addition & 1 deletion packages/neon/neon/lib/l10n/localizations_en.dart
Original file line number Diff line number Diff line change
Expand Up @@ -252,7 +252,7 @@ class NeonLocalizationsEn extends NeonLocalizations {
String get globalOptionsThemeOLEDAsDark => 'OLED theme as dark theme';

@override
String get globalOptionsThemeKeepOriginalAccentColor => 'Keep the original accent color';
String get globalOptionsThemeUseNextcloudTheme => 'Use Nextcloud theme';

@override
String get globalOptionsPushNotificationsEnabled => 'Enabled';
Expand Down
79 changes: 43 additions & 36 deletions packages/neon/neon/lib/src/app.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import 'dart:async';
import 'dart:convert';

import 'package:collection/collection.dart';
import 'package:dynamic_color/dynamic_color.dart';
import 'package:flutter/material.dart';
import 'package:flutter_native_splash/flutter_native_splash.dart';
import 'package:meta/meta.dart';
Expand Down Expand Up @@ -284,42 +285,48 @@ class _NeonAppState extends State<NeonApp> with WidgetsBindingObserver, tray.Tra
}

@override
Widget build(final BuildContext context) => OptionsCollectionBuilder(
valueListenable: _globalOptions,
builder: (final context, final options, final _) => StreamBuilder<Account?>(
stream: _accountsBloc.activeAccount,
builder: (final context, final activeAccountSnapshot) {
FlutterNativeSplash.remove();
return ResultBuilder<core.OcsGetCapabilitiesResponseApplicationJson_Ocs_Data?>.behaviorSubject(
subject: activeAccountSnapshot.hasData
? _accountsBloc.getCapabilitiesBlocFor(activeAccountSnapshot.data!).capabilities
: null,
builder: (final context, final capabilitiesSnapshot) {
final appTheme = AppTheme(
capabilitiesSnapshot.data?.capabilities.themingPublicCapabilities?.theming,
keepOriginalAccentColor: options.themeKeepOriginalAccentColor.value,
oledAsDark: options.themeOLEDAsDark.value,
appThemes: _appImplementations.map((final a) => a.theme).whereNotNull(),
neonTheme: widget.neonTheme,
);

return MaterialApp.router(
localizationsDelegates: [
..._appImplementations.map((final app) => app.localizationsDelegate),
...NeonLocalizations.localizationsDelegates,
],
supportedLocales: {
..._appImplementations.map((final app) => app.supportedLocales).expand((final element) => element),
...NeonLocalizations.supportedLocales,
},
themeMode: options.themeMode.value,
theme: appTheme.lightTheme,
darkTheme: appTheme.darkTheme,
routerConfig: _routerDelegate,
);
},
);
},
Widget build(final BuildContext context) => DynamicColorBuilder(
builder: (final deviceThemeLight, final deviceThemeDark) => OptionsCollectionBuilder(
valueListenable: _globalOptions,
builder: (final context, final options, final _) => StreamBuilder<Account?>(
stream: _accountsBloc.activeAccount,
builder: (final context, final activeAccountSnapshot) {
FlutterNativeSplash.remove();
return ResultBuilder<core.OcsGetCapabilitiesResponseApplicationJson_Ocs_Data?>.behaviorSubject(
subject: activeAccountSnapshot.hasData
? _accountsBloc.getCapabilitiesBlocFor(activeAccountSnapshot.data!).capabilities
: null,
builder: (final context, final capabilitiesSnapshot) {
final appTheme = AppTheme(
nextcloudTheme: capabilitiesSnapshot.data?.capabilities.themingPublicCapabilities?.theming,
useNextcloudTheme: options.themeUseNextcloudTheme.value,
deviceThemeLight: deviceThemeLight,
deviceThemeDark: deviceThemeDark,
oledAsDark: options.themeOLEDAsDark.value,
appThemes: _appImplementations.map((final a) => a.theme).whereNotNull(),
neonTheme: widget.neonTheme,
);

return MaterialApp.router(
localizationsDelegates: [
..._appImplementations.map((final app) => app.localizationsDelegate),
...NeonLocalizations.localizationsDelegates,
],
supportedLocales: {
..._appImplementations
.map((final app) => app.supportedLocales)
.expand((final element) => element),
...NeonLocalizations.supportedLocales,
},
themeMode: options.themeMode.value,
theme: appTheme.lightTheme,
darkTheme: appTheme.darkTheme,
routerConfig: _routerDelegate,
);
},
);
},
),
),
);
}
2 changes: 1 addition & 1 deletion packages/neon/neon/lib/src/pages/settings.dart
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ class _SettingsPageState extends State<SettingsPage> {
option: globalOptions.themeOLEDAsDark,
),
ToggleSettingsTile(
option: globalOptions.themeKeepOriginalAccentColor,
option: globalOptions.themeUseNextcloudTheme,
),
],
),
Expand Down
64 changes: 47 additions & 17 deletions packages/neon/neon/lib/src/theme/theme.dart
Original file line number Diff line number Diff line change
Expand Up @@ -10,19 +10,27 @@ import 'package:nextcloud/core.dart' as core;
@immutable
class AppTheme {
/// Creates a new Neon app theme.
const AppTheme(
this.nextcloudTheme, {
const AppTheme({
required this.nextcloudTheme,
required this.deviceThemeLight,
required this.deviceThemeDark,
required this.neonTheme,
final bool keepOriginalAccentColor = false,
final bool useNextcloudTheme = false,
this.oledAsDark = false,
this.appThemes,
}) : keepOriginalAccentColor = nextcloudTheme == null || keepOriginalAccentColor;
}) : useNextcloudTheme = nextcloudTheme == null || useNextcloudTheme;

/// The theme provided by the Nextcloud server.
final core.ThemingPublicCapabilities_Theming? nextcloudTheme;

/// Whether to force the use of the Nextcloud accent color.
final bool keepOriginalAccentColor;
/// Whether to use of the Nextcloud theme.
final bool useNextcloudTheme;

/// The light theme provided by the device.
final ColorScheme? deviceThemeLight;

/// The dark theme provided by the device.
final ColorScheme? deviceThemeDark;

/// Whether to use [NcColors.oledBackground] in the dark theme.
final bool oledAsDark;
Expand All @@ -34,18 +42,39 @@ class AppTheme {
final NeonTheme neonTheme;

ColorScheme _buildColorScheme(final Brightness brightness) {
final primary = nextcloudTheme?.color != null ? HexColor(nextcloudTheme!.color) : neonTheme.colorScheme.primary;
final keepOriginalAccentColorOverride = keepOriginalAccentColor ? primary : null;
final oledBackgroundOverride = oledAsDark && brightness == Brightness.dark ? NcColors.oledBackground : null;

return ColorScheme.fromSeed(
seedColor: primary,
ColorScheme? colorScheme;

if (nextcloudTheme != null && useNextcloudTheme) {
final primaryColor = HexColor(nextcloudTheme!.color);
final onPrimaryColor = HexColor(nextcloudTheme!.colorText);

colorScheme = ColorScheme.fromSeed(
seedColor: primaryColor,
brightness: brightness,
).copyWith(
primary: primaryColor,
onPrimary: onPrimaryColor,
secondary: primaryColor,
onSecondary: onPrimaryColor,
tertiary: primaryColor,
onTertiary: onPrimaryColor,
);
} else {
colorScheme = brightness == Brightness.dark ? deviceThemeDark : deviceThemeLight;
}

colorScheme ??= ColorScheme.fromSeed(
seedColor: NcColors.primary,
brightness: brightness,
).copyWith(
background: oledBackgroundOverride,
primary: keepOriginalAccentColorOverride,
secondary: keepOriginalAccentColorOverride,
);

if (oledAsDark && brightness == Brightness.dark) {
colorScheme = colorScheme.copyWith(
background: NcColors.oledBackground,
);
}

return colorScheme;
}

ThemeData _getTheme(final Brightness brightness) {
Expand All @@ -55,7 +84,8 @@ class AppTheme {
useMaterial3: true,
colorScheme: colorScheme,
scaffoldBackgroundColor: colorScheme.background,
cardColor: colorScheme.background, // For LicensePage
cardColor: colorScheme.background,
// For LicensePage
snackBarTheme: _snackBarTheme,
dividerTheme: _dividerTheme,
scrollbarTheme: _scrollbarTheme,
Expand Down
16 changes: 8 additions & 8 deletions packages/neon/neon/lib/src/utils/global_options.dart
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ class GlobalOptions extends OptionsCollection {
late final List<Option<dynamic>> options = [
themeMode,
themeOLEDAsDark,
themeKeepOriginalAccentColor,
themeUseNextcloudTheme,
pushNotificationsEnabled,
pushNotificationsDistributor,
startupMinimized,
Expand Down Expand Up @@ -150,14 +150,14 @@ class GlobalOptions extends OptionsCollection {
defaultValue: false,
);

/// Whether the `ColorScheme` should keep the accent color provided by the Nextcloud server.
/// Whether the `ColorScheme` should keep the colors provided by the Nextcloud server.
///
/// Defaults to `false` generating a Material 3 style color.
late final themeKeepOriginalAccentColor = ToggleOption(
late final themeUseNextcloudTheme = ToggleOption(
storage: storage,
key: GlobalOptionKeys.themeKeepOriginalAccentColor,
label: (final context) => NeonLocalizations.of(context).globalOptionsThemeKeepOriginalAccentColor,
defaultValue: false,
key: GlobalOptionKeys.themeUseNextcloudTheme,
label: (final context) => NeonLocalizations.of(context).globalOptionsThemeUseNextcloudTheme,
defaultValue: true,
);

/// Whether to enable the push notifications plugin.
Expand Down Expand Up @@ -286,8 +286,8 @@ enum GlobalOptionKeys implements Storable {
/// The storage key for [GlobalOptions.themeOLEDAsDark]
themeOLEDAsDark._('theme-oled-as-dark'),

/// The storage key for [GlobalOptions.themeKeepOriginalAccentColor]
themeKeepOriginalAccentColor._('theme-keep-original-accent-color'),
/// The storage key for [GlobalOptions.themeUseNextcloudTheme]
themeUseNextcloudTheme._('theme-use-nextcloud-theme'),

/// The storage key for [GlobalOptions.pushNotificationsEnabled]
pushNotificationsEnabled._('push-notifications-enabled'),
Expand Down
3 changes: 2 additions & 1 deletion packages/neon/neon/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ environment:
dependencies:
collection: ^1.0.0
crypto: ^3.0.0
dynamic_color: ^1.0.0
file_picker: ^6.0.0
filesize: ^2.0.0
flutter:
Expand Down Expand Up @@ -66,7 +67,7 @@ dev_dependencies:
git:
url: https://github.com/nextcloud/neon
path: packages/neon_lints
test: ^1.24.9
test: ^1.24.3
vector_graphics_compiler: ^1.1.9

flutter:
Expand Down

0 comments on commit a50b341

Please sign in to comment.