Skip to content

Commit

Permalink
Migrate to Material 3 (#31)
Browse files Browse the repository at this point in the history
* Initial migration

* Migration #2

* Migration #3

* Dynamic Accent Color
  • Loading branch information
TomBursch authored Jul 29, 2022
1 parent f579a55 commit aa05369
Show file tree
Hide file tree
Showing 35 changed files with 585 additions and 341 deletions.
128 changes: 74 additions & 54 deletions lib/app.dart
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import 'package:animations/animations.dart';
import 'package:dynamic_color/dynamic_color.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
Expand Down Expand Up @@ -45,64 +46,83 @@ class App extends StatelessWidget {
BlocProvider.value(value: _settingsCubit),
],
child: BlocBuilder<SettingsCubit, SettingsState>(
builder: (context, state) => MaterialApp(
onGenerateTitle: (BuildContext context) =>
AppLocalizations.of(context)!.appTitle,
localizationsDelegates: AppLocalizations.localizationsDelegates,
supportedLocales: AppLocalizations.supportedLocales,
theme: AppThemes.light,
darkTheme: AppThemes.dark,
themeMode: state.themeMode,
debugShowCheckedModeBanner: false,
restorationScopeId: "com.tombursch.kitchenowl",
home: Builder(
builder: (context) => AnnotatedRegion<SystemUiOverlayStyle>(
value: _getSystemUI(context, state),
child: BlocBuilder<AuthCubit, AuthState>(
bloc: _authCubit,
builder: (context, state) => PageTransitionSwitcher(
transitionBuilder: (
Widget child,
Animation<double> animation,
Animation<double> secondaryAnimation,
) {
return SharedAxisTransition(
animation: animation,
secondaryAnimation: secondaryAnimation,
transitionType: SharedAxisTransitionType.horizontal,
child: child,
);
},
child: Builder(
key: ValueKey(state.orderId),
builder: (context) {
if (state is Setup) return const SetupPage();
if (state is Onboarding) return const OnboardingPage();
if (state is Unauthenticated) return const LoginPage();
if (state is Authenticated) return const HomePage();
if (state is Unreachable) {
return const UnreachablePage();
}
if (state is Unsupported) {
return UnsupportedPage(
unsupportedBackend: state.unsupportedBackend,
);
}
if (state is LoadingOnboard) {
return SplashPage(
message:
AppLocalizations.of(context)!.onboardingLoading,
);
}
builder: (context, state) =>
DynamicColorBuilder(builder: (lightDynamic, darkDynamic) {
ColorScheme lightColorScheme = AppThemes.lightScheme;
ColorScheme darkColorScheme = AppThemes.darkScheme;

return const SplashPage();
if (state.dynamicAccentColor &&
lightDynamic != null &&
darkDynamic != null) {
// On Android S+ devices, use the provided dynamic color scheme.
// (Recommended) Harmonize the dynamic color scheme' built-in semantic colors.
lightColorScheme = lightDynamic.harmonized();
darkColorScheme = darkDynamic.harmonized();
}

return MaterialApp(
onGenerateTitle: (BuildContext context) =>
AppLocalizations.of(context)!.appTitle,
localizationsDelegates: AppLocalizations.localizationsDelegates,
supportedLocales: AppLocalizations.supportedLocales,
theme: AppThemes.light(lightColorScheme),
darkTheme: AppThemes.dark(darkColorScheme),
themeMode: state.themeMode,
debugShowCheckedModeBanner: false,
restorationScopeId: "com.tombursch.kitchenowl",
home: Builder(
builder: (context) => AnnotatedRegion<SystemUiOverlayStyle>(
value: _getSystemUI(context, state),
child: BlocBuilder<AuthCubit, AuthState>(
bloc: _authCubit,
builder: (context, state) => PageTransitionSwitcher(
transitionBuilder: (
Widget child,
Animation<double> animation,
Animation<double> secondaryAnimation,
) {
return SharedAxisTransition(
animation: animation,
secondaryAnimation: secondaryAnimation,
transitionType: SharedAxisTransitionType.horizontal,
child: child,
);
},
child: Builder(
key: ValueKey(state.orderId),
builder: (context) {
if (state is Setup) return const SetupPage();
if (state is Onboarding) {
return const OnboardingPage();
}
if (state is Unauthenticated) {
return const LoginPage();
}
if (state is Authenticated) return const HomePage();
if (state is Unreachable) {
return const UnreachablePage();
}
if (state is Unsupported) {
return UnsupportedPage(
unsupportedBackend: state.unsupportedBackend,
);
}
if (state is LoadingOnboard) {
return SplashPage(
message: AppLocalizations.of(context)!
.onboardingLoading,
);
}

return const SplashPage();
},
),
),
),
),
),
),
),
);
}),
),
),
);
Expand All @@ -123,7 +143,7 @@ class App extends StatelessWidget {
}
light:
case ThemeMode.light:
final Color backgroundColor = AppThemes.light.scaffoldBackgroundColor;
final Color backgroundColor = Theme.of(context).colorScheme.background;
return SystemUiOverlayStyle.dark.copyWith(
statusBarColor: Colors.transparent,
statusBarIconBrightness: Brightness.dark,
Expand All @@ -134,7 +154,7 @@ class App extends StatelessWidget {
);
dark:
case ThemeMode.dark:
final Color backgroundColor = AppThemes.dark.scaffoldBackgroundColor;
final Color backgroundColor = Theme.of(context).colorScheme.background;
return SystemUiOverlayStyle.light.copyWith(
statusBarColor: Colors.transparent,
statusBarIconBrightness: Brightness.light,
Expand Down
16 changes: 15 additions & 1 deletion lib/cubits/settings_cubit.dart
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ class SettingsCubit extends Cubit<SettingsState> {
Future<void> load() async {
final themeModeIndex =
PreferenceStorage.getInstance().readInt(key: 'themeMode');
final dynamicAccentColor =
PreferenceStorage.getInstance().readBool(key: 'dynamicAccentColor');
Config.deviceInfo = DeviceInfoPlugin().deviceInfo;
Config.packageInfo = PackageInfo.fromPlatform();

Expand All @@ -51,6 +53,7 @@ class SettingsCubit extends Cubit<SettingsState> {
emit(SettingsState(
themeMode: themeMode,
serverSettings: serverSettings,
dynamicAccentColor: await dynamicAccentColor ?? false,
));
}

Expand All @@ -67,6 +70,12 @@ class SettingsCubit extends Cubit<SettingsState> {
}
}

void setUseDynamicAccentColor(bool dynamicAccentColor) {
PreferenceStorage.getInstance()
.writeBool(key: 'dynamicAccentColor', value: dynamicAccentColor);
emit(state.copyWith(dynamicAccentColor: dynamicAccentColor));
}

void setFeaturePlanner(bool featurePlanner) {
PreferenceStorage.getInstance()
.writeBool(key: 'featurePlanner', value: featurePlanner);
Expand All @@ -86,24 +95,29 @@ class SettingsState extends Equatable {
final ThemeMode themeMode;
final bool forcedOfflineMode;
final ServerSettings serverSettings;
final bool dynamicAccentColor;

const SettingsState({
this.themeMode = ThemeMode.system,
this.forcedOfflineMode = false,
this.serverSettings = const ServerSettings(),
this.dynamicAccentColor = false,
});

SettingsState copyWith({
ThemeMode? themeMode,
bool? forcedOfflineMode,
ServerSettings? serverSettings,
bool? dynamicAccentColor,
}) =>
SettingsState(
themeMode: themeMode ?? this.themeMode,
forcedOfflineMode: forcedOfflineMode ?? this.forcedOfflineMode,
serverSettings: serverSettings ?? this.serverSettings,
dynamicAccentColor: dynamicAccentColor ?? this.dynamicAccentColor,
);

@override
List<Object?> get props => [themeMode, forcedOfflineMode, serverSettings];
List<Object?> get props =>
[themeMode, forcedOfflineMode, serverSettings, dynamicAccentColor];
}
1 change: 1 addition & 0 deletions lib/l10n/app_de.arb
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
"delete": "Löschen",
"description": "Beschreibung",
"done": "Fertig",
"dynamicAccentColor": "Dynamische Akzentfarbe",
"error": "Ein Fehler ist aufgetreten",
"expenseAdd": "Ausgabe Hinzufügen",
"expenseAmount": "Betrag",
Expand Down
1 change: 1 addition & 0 deletions lib/l10n/app_en.arb
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
"delete": "Delete",
"description": "Description",
"done": "Done",
"dynamicAccentColor": "Dynamic Accent Color",
"error": "An error occured",
"expenseAdd": "Add Expense",
"expenseAmount": "Amount",
Expand Down
88 changes: 31 additions & 57 deletions lib/pages/home_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -147,13 +147,16 @@ class _HomePageState extends State<HomePage> {
expenseCubit.refresh();
}
},
closedElevation: 6.0,
closedElevation: 4.0,
closedShape: const RoundedRectangleBorder(
borderRadius: BorderRadius.all(
Radius.circular(56 / 2),
Radius.circular(14),
),
),
closedColor: Theme.of(context).colorScheme.secondary,
closedColor: Theme.of(context)
.floatingActionButtonTheme
.backgroundColor ??
Theme.of(context).colorScheme.secondary,
closedBuilder: (
BuildContext context,
VoidCallback openContainer,
Expand Down Expand Up @@ -210,56 +213,27 @@ class _HomePageState extends State<HomePage> {
);

if (!useBottomNavigationBar) {
final bool extendedRail = getValueForScreenType<bool>(
context: context,
mobile: false,
tablet: false,
desktop: true,
);
body = Row(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
SizedBox(
width: 200,
child: ListView(children: [
// Image.asset('assets/images/header.png'),
Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
AppLocalizations.of(context)!.appTitle,
style: Theme.of(context).textTheme.headline5,
),
),
const Divider(),
..._homePageMenuItems
.asMap()
.entries
.map(
(e) => ListTile(
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.horizontal(
right: Radius.circular(5),
),
),
tileColor: _selectedIndex == e.key
? Theme.of(context).colorScheme.primary
: null,
title: Text(
e.value.label,
style: TextStyle(
color: _selectedIndex == e.key
? Colors.white
: null,
),
),
leading: Icon(
e.value.icon,
color: _selectedIndex == e.key
? Colors.white
: null,
),
onTap: () =>
_onItemTapped(e.key, _homePageMenuItems),
),
)
.toList(),
]),
NavigationRail(
extended: extendedRail,
destinations: _homePageMenuItems
.map((e) => NavigationRailDestination(
icon: Icon(e.icon),
label: Text(e.label),
))
.toList(),
selectedIndex: _selectedIndex,
onDestinationSelected: (i) =>
_onItemTapped(i, _homePageMenuItems),
),
const VerticalDivider(),
Expanded(child: body),
],
);
Expand All @@ -270,18 +244,18 @@ class _HomePageState extends State<HomePage> {
floatingActionButton:
_homePageMenuItems[_selectedIndex].floatingActionButton,
bottomNavigationBar: useBottomNavigationBar
? BottomNavigationBar(
showUnselectedLabels: false,
showSelectedLabels: true,
type: BottomNavigationBarType.fixed,
items: _homePageMenuItems
.map((e) => BottomNavigationBarItem(
? NavigationBar(
labelBehavior:
NavigationDestinationLabelBehavior.onlyShowSelected,
destinations: _homePageMenuItems
.map((e) => NavigationDestination(
icon: Icon(e.icon),
label: e.label,
))
.toList(),
currentIndex: _selectedIndex,
onTap: (i) => _onItemTapped(i, _homePageMenuItems),
selectedIndex: _selectedIndex,
onDestinationSelected: (i) =>
_onItemTapped(i, _homePageMenuItems),
)
: null,
);
Expand Down
Loading

0 comments on commit aa05369

Please sign in to comment.