Theme switching with ChangeProvider

This commit is contained in:
Sarah Jamie Lewis 2021-01-27 12:18:28 -08:00
parent 5cbc0814f6
commit d45ac78e64
4 changed files with 91 additions and 25 deletions

12
ARCH.md Normal file
View File

@ -0,0 +1,12 @@
# State Management
We use a MultiProvider to distribute state to the underlying widgets. Right now there are 2 top
level Providers: FlwtchState (the app) and OpaqueTheme.
## Theme
OpaqueTheme extends ChangeProvider. SetLight and SetDark are functions that call notifyListeners()
ChangeNotiferProvider is used to package OpaqueTheme into a provider which is a top level
provider (as every widget in the app needs to be re-rendered on a theme switch).

View File

@ -32,17 +32,17 @@ class FlwtchState extends State<Flwtch> {
// mergenotes: ui stuff // mergenotes: ui stuff
ProfileModel selectedProfile; ProfileModel selectedProfile;
String selectedConversation = ""; String selectedConversation = "";
var columns = [1];// default or 'single column' mode var columns = [1]; // default or 'single column' mode
//var columns = [1, 1, 2]; //var columns = [1, 1, 2];
AppModel appStatus; AppModel appStatus;
HashMap<String, ProfileModel> profiles; HashMap<String, ProfileModel> profiles;
@override @override
initState() { initState() {
super.initState(); super.initState();
cwtchInit = false; cwtchInit = false;
profiles = new HashMap<String, ProfileModel>(); profiles = new HashMap<String, ProfileModel>();
print("FlwtchState.initState()"); print("FlwtchState.initState()");
@ -80,32 +80,55 @@ class FlwtchState extends State<Flwtch> {
}); });
} }
ChangeNotifierProvider<OpaqueTheme> getOpaqueProvider() {
return ChangeNotifierProvider(create: (context) => OpaqueTheme(Opaque.dark));
}
Provider<FlwtchState> getFlwtchStateProvider() {
return Provider<FlwtchState>(
create: (_) => this,
);
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
appStatus = AppModel(cwtch: cwtch); appStatus = AppModel(cwtch: cwtch);
final newTextTheme = Theme.of(context).textTheme.apply( final newTextTheme = Theme.of(context).textTheme.apply(
bodyColor: Opaque.current().mainTextColor(), bodyColor: Opaque.current().mainTextColor(),
displayColor: Opaque.current().mainTextColor(), displayColor: Opaque.current().mainTextColor(),
); );
print("FlwtchState.build() cwtchInit: $cwtchInit"); print("FlwtchState.build() cwtchInit: $cwtchInit");
return Provider<FlwtchState>( return MultiProvider(
create: (_) => this, providers: [getFlwtchStateProvider(), getOpaqueProvider()],
child: MaterialApp( builder: (context, widget) { return MaterialApp(
title: 'Cwtch', title: 'Cwtch',
theme: ThemeData( theme: ThemeData(
visualDensity: VisualDensity.adaptivePlatformDensity, visualDensity: VisualDensity.adaptivePlatformDensity,
primarySwatch: Colors.red, primarySwatch: Colors.red,
primaryColor: Opaque.current().backgroundMainColor(), primaryColor: Provider.of<OpaqueTheme>(context)
canvasColor: Opaque.current().backgroundPaneColor(), .current()
accentColor: Opaque.current().defaultButtonColor(), .backgroundMainColor(),
buttonColor: Opaque.current().defaultButtonColor(), canvasColor: Provider.of<OpaqueTheme>(context)
textTheme: newTextTheme, .current()
), .backgroundPaneColor(),
// from dan: home: cwtchInit == true ? ProfileMgrView(cwtch) : SplashView(), accentColor: Provider.of<OpaqueTheme>(context)
// from erinn: home: columns.length == 3 ? TripleColumnView() : ProfileMgrView(), .current()
home: cwtchInit == true ? (columns.length == 3 ? TripleColumnView() : ProfileMgrView()) : SplashView(), .defaultButtonColor(),
)); buttonColor: Provider.of<OpaqueTheme>(context)
.current()
.defaultButtonColor(),
textTheme: newTextTheme,
),
// from dan: home: cwtchInit == true ? ProfileMgrView(cwtch) : SplashView(),
// from erinn: home: columns.length == 3 ? TripleColumnView() : ProfileMgrView(),
home: cwtchInit == true
? (columns.length == 3
? TripleColumnView()
: ProfileMgrView())
: SplashView(),
);},
);
} }
} }

View File

@ -5,6 +5,8 @@
import 'dart:ui'; import 'dart:ui';
import 'dart:core'; import 'dart:core';
import 'package:flutter/material.dart';
abstract class OpaqueThemeType { abstract class OpaqueThemeType {
static final Color red = Color(0xFFFF0000); static final Color red = Color(0xFFFF0000);
Color backgroundMainColor(){return red;} Color backgroundMainColor(){return red;}
@ -421,9 +423,12 @@ class Opaque extends OpaqueThemeType {
int chatPaneMinSize() { return chatPaneMinSizeBase[p[scale]]; } int chatPaneMinSize() { return chatPaneMinSizeBase[p[scale]]; }
int doublePaneMinSize() { return sidePaneMinSize() + chatPaneMinSize(); } int doublePaneMinSize() { return sidePaneMinSize() + chatPaneMinSize(); }
static OpaqueThemeType _current;
static final OpaqueThemeType dark = CwtchDark(); static final OpaqueThemeType dark = CwtchDark();
static final OpaqueThemeType light = CwtchLight(); static final OpaqueThemeType light = CwtchLight();
static OpaqueThemeType current() { return dark; } static void setDark() { _current = dark; }
static void setLight() { _current = light; }
static OpaqueThemeType current() { if (_current == null) {setDark();} return _current; }
int scale = 2; int scale = 2;
@ -507,3 +512,15 @@ int scale = 2;
} }
/// TODO: Wire into libCwtch saveSettings / updateTheme etc...
class OpaqueTheme extends ChangeNotifier {
OpaqueThemeType theme;
void setDark() { theme = Opaque.dark; notifyListeners();}
void setLight() { theme = Opaque.light; notifyListeners();}
OpaqueThemeType current() { return theme; }
OpaqueTheme(this.theme);
}

View File

@ -1,4 +1,7 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_app/main.dart';
import 'package:flutter_app/opaque.dart';
import 'package:provider/provider.dart';
class GlobalSettingsView extends StatefulWidget { class GlobalSettingsView extends StatefulWidget {
@override @override
@ -35,7 +38,18 @@ class _GlobalSettingsViewState extends State<GlobalSettingsView> {
}, },
), ),
Text("Zoom"), Text("Zoom"),
Text("Theme"), SwitchListTile(
title: const Text('Theme'),
value: Provider.of<OpaqueTheme>(context).current() == Opaque.light,
onChanged: (bool value) {
if (value) {
Provider.of<OpaqueTheme>(context, listen: false).setLight();
} else {
Provider.of<OpaqueTheme>(context, listen: false).setDark();
}
},
secondary: const Icon(Icons.lightbulb_outline),
),
Text("Experiments enabled"), Text("Experiments enabled"),
Text("Text magnification reference"), Text("Text magnification reference"),
Text("Acknowledgements"), Text("Acknowledgements"),