From 1ad1a11d6b1a74446db963d3f7a63cb93c9e0a33 Mon Sep 17 00:00:00 2001 From: Feodor Fitsner Date: Sun, 5 Jun 2022 09:22:04 -0700 Subject: [PATCH] Fixed #10 (#14) --- client/lib/actions.dart | 5 + client/lib/controls/app_bar.dart | 11 +- client/lib/controls/page.dart | 157 +++++----- client/lib/models/app_state.dart | 37 +-- client/lib/models/page_load_view_model.dart | 6 +- client/lib/models/page_media_view_model.dart | 27 ++ client/lib/models/page_size_view_model.dart | 20 -- client/lib/reducers.dart | 2 + .../{screen_size.dart => page_media.dart} | 25 +- media/logo/logo-inkscape.svg | 267 ++++++++++++++++++ 10 files changed, 435 insertions(+), 122 deletions(-) create mode 100644 client/lib/models/page_media_view_model.dart delete mode 100644 client/lib/models/page_size_view_model.dart rename client/lib/widgets/{screen_size.dart => page_media.dart} (54%) create mode 100644 media/logo/logo-inkscape.svg diff --git a/client/lib/actions.dart b/client/lib/actions.dart index e509d4552..7f3dabf2e 100644 --- a/client/lib/actions.dart +++ b/client/lib/actions.dart @@ -27,6 +27,11 @@ class PageSizeChangeAction { PageSizeChangeAction(this.newSize); } +class PageBrightnessChangeAction { + final Brightness brightness; + PageBrightnessChangeAction(this.brightness); +} + class RegisterWebClientAction { final RegisterWebClientResponse payload; RegisterWebClientAction(this.payload); diff --git a/client/lib/controls/app_bar.dart b/client/lib/controls/app_bar.dart index da385285e..fd3bef2fe 100644 --- a/client/lib/controls/app_bar.dart +++ b/client/lib/controls/app_bar.dart @@ -10,6 +10,7 @@ class AppBarControl extends StatelessWidget implements PreferredSizeWidget { final bool parentDisabled; final List children; final double height; + final ThemeData theme; const AppBarControl( {Key? key, @@ -17,7 +18,8 @@ class AppBarControl extends StatelessWidget implements PreferredSizeWidget { required this.control, required this.children, required this.parentDisabled, - required this.height}) + required this.height, + required this.theme}) : super(key: key); @override @@ -31,10 +33,9 @@ class AppBarControl extends StatelessWidget implements PreferredSizeWidget { var leadingWidth = control.attrDouble("leadingWidth"); var centerTitle = control.attrBool("centerTitle", false)!; - var color = HexColor.fromString( - Theme.of(context), control.attrString("color", "")!); - var bgcolor = HexColor.fromString( - Theme.of(context), control.attrString("bgcolor", "")!); + var color = HexColor.fromString(theme, control.attrString("color", "")!); + var bgcolor = + HexColor.fromString(theme, control.attrString("bgcolor", "")!); return AppBar( leading: leadingCtrls.isNotEmpty diff --git a/client/lib/controls/page.dart b/client/lib/controls/page.dart index 6ee2fde38..f192002ff 100644 --- a/client/lib/controls/page.dart +++ b/client/lib/controls/page.dart @@ -5,12 +5,13 @@ import '../models/app_state.dart'; import '../models/control.dart'; import '../models/control_type.dart'; import '../models/controls_view_model.dart'; +import '../models/page_media_view_model.dart'; import '../utils/alignment.dart'; import '../utils/colors.dart'; import '../utils/desktop.dart'; import '../utils/edge_insets.dart'; import '../utils/theme.dart'; -import '../widgets/screen_size.dart'; +import '../widgets/page_media.dart'; import 'app_bar.dart'; import 'create_control.dart'; import 'scrollable_control.dart'; @@ -73,7 +74,7 @@ class PageControl extends StatelessWidget { } // theme - var theme = parseTheme(control, "theme") ?? + var lightTheme = parseTheme(control, "theme") ?? ThemeData( colorSchemeSeed: Colors.blue, brightness: Brightness.light, @@ -109,76 +110,90 @@ class PageControl extends StatelessWidget { childIds.add(appBar.id); } - return StoreConnector( + return StoreConnector( distinct: true, - converter: (store) => ControlsViewModel.fromStore(store, childIds), - builder: (context, childrenViews) { - debugPrint("Offstage StoreConnector build"); - - // offstage - List offstageWidgets = offstage != null - ? childrenViews.controlViews.first.children - .where((c) => - c.isVisible && c.type != ControlType.floatingActionButton) - .map((c) => createControl(offstage, c.id, disabled)) - .toList() - : []; - - List fab = offstage != null - ? childrenViews.controlViews.first.children - .where((c) => - c.isVisible && c.type == ControlType.floatingActionButton) - .toList() - : []; - - var appBarView = - appBar != null ? childrenViews.controlViews.last : null; - - var column = Column( - mainAxisAlignment: mainAlignment, - crossAxisAlignment: crossAlignment, - children: controls); - - return MaterialApp( - title: title, - theme: theme, - darkTheme: darkTheme, - themeMode: themeMode, - home: Scaffold( - appBar: appBarView != null - ? AppBarControl( - parent: control, - control: appBarView.control, - children: appBarView.children, - parentDisabled: disabled, - height: appBarView.control - .attrDouble("toolbarHeight", kToolbarHeight)!, - ) - : null, - body: Stack(children: [ - SizedBox.expand( - child: Container( - padding: parseEdgeInsets(control, "padding") ?? - const EdgeInsets.all(10), - decoration: BoxDecoration( - color: HexColor.fromString(Theme.of(context), - control.attrString("bgcolor", "")!)), - child: scrollMode != ScrollMode.none - ? ScrollableControl( - child: column, - scrollDirection: Axis.vertical, - scrollMode: scrollMode, - autoScroll: autoScroll, - ) - : column)), - ...offstageWidgets, - const ScreenSize() - ]), - floatingActionButton: fab.isNotEmpty - ? createControl(offstage, fab.first.id, disabled) - : null, - ), - ); + converter: (store) => PageMediaViewModel.fromStore(store), + builder: (context, media) { + var theme = themeMode == ThemeMode.light || + (themeMode == ThemeMode.system && + media.displayBrightness == Brightness.light) + ? lightTheme + : darkTheme; + + return StoreConnector( + distinct: true, + converter: (store) => + ControlsViewModel.fromStore(store, childIds), + builder: (context, childrenViews) { + debugPrint("Offstage StoreConnector build"); + + // offstage + List offstageWidgets = offstage != null + ? childrenViews.controlViews.first.children + .where((c) => + c.isVisible && + c.type != ControlType.floatingActionButton) + .map((c) => createControl(offstage, c.id, disabled)) + .toList() + : []; + + List fab = offstage != null + ? childrenViews.controlViews.first.children + .where((c) => + c.isVisible && + c.type == ControlType.floatingActionButton) + .toList() + : []; + + var appBarView = + appBar != null ? childrenViews.controlViews.last : null; + + var column = Column( + mainAxisAlignment: mainAlignment, + crossAxisAlignment: crossAlignment, + children: controls); + + return MaterialApp( + title: title, + theme: lightTheme, + darkTheme: darkTheme, + themeMode: themeMode, + home: Scaffold( + appBar: appBarView != null + ? AppBarControl( + parent: control, + control: appBarView.control, + children: appBarView.children, + parentDisabled: disabled, + height: appBarView.control + .attrDouble("toolbarHeight", kToolbarHeight)!, + theme: theme) + : null, + body: Stack(children: [ + SizedBox.expand( + child: Container( + padding: parseEdgeInsets(control, "padding") ?? + const EdgeInsets.all(10), + decoration: BoxDecoration( + color: HexColor.fromString(theme, + control.attrString("bgcolor", "")!)), + child: scrollMode != ScrollMode.none + ? ScrollableControl( + child: column, + scrollDirection: Axis.vertical, + scrollMode: scrollMode, + autoScroll: autoScroll, + ) + : column)), + ...offstageWidgets, + const PageMedia() + ]), + floatingActionButton: fab.isNotEmpty + ? createControl(offstage, fab.first.id, disabled) + : null, + ), + ); + }); }); } } diff --git a/client/lib/models/app_state.dart b/client/lib/models/app_state.dart index 6df49fc82..5e3f1cfc4 100644 --- a/client/lib/models/app_state.dart +++ b/client/lib/models/app_state.dart @@ -17,6 +17,7 @@ class AppState extends Equatable { final String error; final Size size; final String sizeBreakpoint; + final Brightness displayBrightness; final Map sizeBreakpoints; final Map controls; @@ -29,25 +30,27 @@ class AppState extends Equatable { required this.size, required this.sizeBreakpoint, required this.sizeBreakpoints, + required this.displayBrightness, required this.controls}); factory AppState.initial() => const AppState( - pageUri: null, - sessionId: "", - isLoading: true, - reconnectingTimeout: 0, - error: "", - size: Size(0, 0), - sizeBreakpoint: "", - sizeBreakpoints: { - "xs": 0, - "sm": 576, - "md": 768, - "lg": 992, - "xl": 1200, - "xxl": 1400 - }, - controls: {}); + pageUri: null, + sessionId: "", + isLoading: true, + reconnectingTimeout: 0, + error: "", + size: Size(0, 0), + sizeBreakpoint: "", + sizeBreakpoints: { + "xs": 0, + "sm": 576, + "md": 768, + "lg": 992, + "xl": 1200, + "xxl": 1400 + }, + displayBrightness: Brightness.light, + controls: {}); AppState copyWith( {Uri? pageUri, @@ -58,6 +61,7 @@ class AppState extends Equatable { Size? size, String? sizeBreakpoint, Map? sizeBreakpoints, + Brightness? displayBrightness, Map? controls}) => AppState( pageUri: pageUri ?? this.pageUri, @@ -68,6 +72,7 @@ class AppState extends Equatable { size: size ?? this.size, sizeBreakpoint: sizeBreakpoint ?? this.sizeBreakpoint, sizeBreakpoints: sizeBreakpoints ?? this.sizeBreakpoints, + displayBrightness: displayBrightness ?? this.displayBrightness, controls: controls ?? this.controls); @override diff --git a/client/lib/models/page_load_view_model.dart b/client/lib/models/page_load_view_model.dart index fc821630c..6b1385e48 100644 --- a/client/lib/models/page_load_view_model.dart +++ b/client/lib/models/page_load_view_model.dart @@ -2,12 +2,12 @@ import 'package:equatable/equatable.dart'; import 'package:redux/redux.dart'; import 'app_state.dart'; -import 'page_size_view_model.dart'; +import 'page_media_view_model.dart'; class PageLoadViewModel extends Equatable { final Uri? pageUri; final String sessionId; - final PageSizeViewModel sizeViewModel; + final PageMediaViewModel sizeViewModel; const PageLoadViewModel( {required this.pageUri, @@ -18,7 +18,7 @@ class PageLoadViewModel extends Equatable { return PageLoadViewModel( pageUri: store.state.pageUri, sessionId: store.state.sessionId, - sizeViewModel: PageSizeViewModel.fromStore(store)); + sizeViewModel: PageMediaViewModel.fromStore(store)); } @override diff --git a/client/lib/models/page_media_view_model.dart b/client/lib/models/page_media_view_model.dart new file mode 100644 index 000000000..5c8886a5e --- /dev/null +++ b/client/lib/models/page_media_view_model.dart @@ -0,0 +1,27 @@ +import 'dart:ui'; + +import 'package:equatable/equatable.dart'; +import 'package:redux/redux.dart'; + +import 'app_state.dart'; + +class PageMediaViewModel extends Equatable { + final Size size; + final Brightness displayBrightness; + final Function dispatch; + + const PageMediaViewModel( + {required this.size, + required this.displayBrightness, + required this.dispatch}); + + static PageMediaViewModel fromStore(Store store) { + return PageMediaViewModel( + size: store.state.size, + displayBrightness: store.state.displayBrightness, + dispatch: store.dispatch); + } + + @override + List get props => [size, displayBrightness, dispatch]; +} diff --git a/client/lib/models/page_size_view_model.dart b/client/lib/models/page_size_view_model.dart deleted file mode 100644 index 2fb3dddee..000000000 --- a/client/lib/models/page_size_view_model.dart +++ /dev/null @@ -1,20 +0,0 @@ -import 'dart:ui'; - -import 'package:equatable/equatable.dart'; -import 'package:redux/redux.dart'; - -import 'app_state.dart'; - -class PageSizeViewModel extends Equatable { - final Size size; - final Function dispatch; - - const PageSizeViewModel({required this.size, required this.dispatch}); - - static PageSizeViewModel fromStore(Store store) { - return PageSizeViewModel(size: store.state.size, dispatch: store.dispatch); - } - - @override - List get props => [size, dispatch]; -} diff --git a/client/lib/reducers.dart b/client/lib/reducers.dart index 25229d280..59e4075c4 100644 --- a/client/lib/reducers.dart +++ b/client/lib/reducers.dart @@ -58,6 +58,8 @@ AppState appReducer(AppState state, dynamic action) { } return state.copyWith(size: action.newSize, sizeBreakpoint: newBreakpoint); + } else if (action is PageBrightnessChangeAction) { + return state.copyWith(displayBrightness: action.brightness); } else if (action is RegisterWebClientAction) { // // register web client diff --git a/client/lib/widgets/screen_size.dart b/client/lib/widgets/page_media.dart similarity index 54% rename from client/lib/widgets/screen_size.dart rename to client/lib/widgets/page_media.dart index d189663f8..14a375b14 100644 --- a/client/lib/widgets/screen_size.dart +++ b/client/lib/widgets/page_media.dart @@ -1,20 +1,20 @@ import 'dart:async'; -import 'package:flet_view/models/page_size_view_model.dart'; +import 'package:flet_view/models/page_media_view_model.dart'; import 'package:flutter/material.dart'; import 'package:flutter_redux/flutter_redux.dart'; import '../actions.dart'; import '../models/app_state.dart'; -class ScreenSize extends StatefulWidget { - const ScreenSize({Key? key}) : super(key: key); +class PageMedia extends StatefulWidget { + const PageMedia({Key? key}) : super(key: key); @override - State createState() => _ScreenSizeState(); + State createState() => _PageMediaState(); } -class _ScreenSizeState extends State { +class _PageMediaState extends State { Timer? _debounce; _onScreenSizeChanged(Size newSize, Function dispatch) { @@ -25,11 +25,16 @@ class _ScreenSizeState extends State { }); } + _onScreenBrightnessChanged(Brightness brightness, Function dispatch) { + debugPrint("Send new brightness to reducer: $brightness"); + dispatch(PageBrightnessChangeAction(brightness)); + } + @override Widget build(BuildContext context) { - return StoreConnector( + return StoreConnector( distinct: true, - converter: (store) => PageSizeViewModel.fromStore(store), + converter: (store) => PageMediaViewModel.fromStore(store), builder: (context, viewModel) { MediaQueryData media = MediaQuery.of(context); if (media.size != viewModel.size) { @@ -37,6 +42,12 @@ class _ScreenSizeState extends State { } else { debugPrint("Page size did not change."); } + if (media.platformBrightness != viewModel.displayBrightness) { + _onScreenBrightnessChanged( + media.platformBrightness, viewModel.dispatch); + } else { + debugPrint("Page brightness did not change."); + } return const SizedBox.shrink(); }); } diff --git a/media/logo/logo-inkscape.svg b/media/logo/logo-inkscape.svg new file mode 100644 index 000000000..4891fe339 --- /dev/null +++ b/media/logo/logo-inkscape.svg @@ -0,0 +1,267 @@ + + + +white rounded squaremaskableFletFletfletFletFletflet