Skip to content

Commit

Permalink
theme provider set up
Browse files Browse the repository at this point in the history
  • Loading branch information
richtwin567 committed Aug 20, 2020
1 parent 8e2e51c commit 1912099
Show file tree
Hide file tree
Showing 15 changed files with 339 additions and 151 deletions.
33 changes: 22 additions & 11 deletions lib/main.dart
Original file line number Diff line number Diff line change
@@ -1,27 +1,38 @@
import 'package:device_preview/device_preview.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:fst_app_flutter/models/theme_model.dart';
import 'package:fst_app_flutter/routing/generate_routes.dart';

import 'package:fst_app_flutter/utils/app_theme.dart';
import 'package:provider/provider.dart';

void main() {
SystemChrome.setSystemUIOverlayStyle(SystemUiOverlayStyle(
statusBarColor: AppTheme.apptheme.primaryColor,
));

runApp(DevicePreview(child: FSTApp()));
}

class FSTApp extends StatelessWidget {
// This widget is the root of the application.
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
theme: AppTheme.apptheme,
title: 'FST App',
builder: DevicePreview.appBuilder,
onGenerateRoute: Router.generateRoute,
);

return ChangeNotifierProvider(
create: (context) => ThemeModel(),
child: Consumer<ThemeModel>(
builder:(context, themeModel, child) {
SystemChrome.setSystemUIOverlayStyle(SystemUiOverlayStyle(
statusBarColor: AppTheme.getTheme(themeModel.selectedTheme,MediaQuery.platformBrightnessOf(context)).primaryColor,
));
return MaterialApp(
debugShowCheckedModeBanner: false,
theme: AppTheme.getTheme(ThemeMode.light, MediaQuery.platformBrightnessOf(context)),
darkTheme: AppTheme.getTheme(ThemeMode.dark, MediaQuery.platformBrightnessOf(context)),
themeMode: themeModel.selectedTheme,
title: 'FST App',
builder: DevicePreview.appBuilder,
onGenerateRoute: Router.generateRoute,
);
},
));
}
}
17 changes: 17 additions & 0 deletions lib/models/theme_model.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:fst_app_flutter/preferences/theme_preference.dart';

class ThemeModel with ChangeNotifier {
ThemePreference themePreference = ThemePreference();
//set to system theme by default
ThemeMode _currentTheme = ThemeMode.system;

ThemeMode get selectedTheme => _currentTheme;

set switchThemeTo(ThemeMode themeMode) {
_currentTheme = themeMode;
themePreference.setThemeMode(themeMode);
notifyListeners();
}
}
41 changes: 41 additions & 0 deletions lib/preferences/theme_preference.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';

class ThemePreference {
var lightThemeStatus = ThemeMode.light.toString();
var systemThemeStatus = ThemeMode.system.toString();
var darkThemeStatus = ThemeMode.dark.toString();
SharedPreferences prefs;

_initializeFromDisk() async {
prefs = await SharedPreferences.getInstance();
}

setThemeMode(ThemeMode option) async {
_initializeFromDisk();
if (option == ThemeMode.dark) {
prefs.setBool(darkThemeStatus, true);
prefs.setBool(lightThemeStatus, false);
prefs.setBool(systemThemeStatus, false);
} else if (option == ThemeMode.light) {
prefs.setBool(darkThemeStatus, false);
prefs.setBool(lightThemeStatus, true);
prefs.setBool(systemThemeStatus, false);
} else {
prefs.setBool(darkThemeStatus, false);
prefs.setBool(lightThemeStatus, false);
prefs.setBool(systemThemeStatus, true);
}
}

ThemeMode get mode {
_initializeFromDisk();
if (prefs.getBool(darkThemeStatus) ?? false) {
return ThemeMode.dark;
} else if (prefs.getBool(lightThemeStatus) ?? false) {
return ThemeMode.light;
} else {
return ThemeMode.system;
}
}
}
Empty file.
Empty file.
Empty file.
21 changes: 12 additions & 9 deletions lib/screens/contact_screen/contact_state.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import 'package:flutter/material.dart';
import 'package:flutter/scheduler.dart';
import 'package:fst_app_flutter/models/theme_model.dart';
import 'package:fst_app_flutter/services/handle_heroku_requests.dart';
import 'package:fst_app_flutter/utils/app_theme.dart';
import 'package:fst_app_flutter/widgets/contact_tile.dart';
import 'package:fst_app_flutter/routing/routes.dart';
import 'contact_view_stateful.dart';
Expand Down Expand Up @@ -102,6 +105,10 @@ abstract class ContactViewState extends State<ContactViewStateful>
/// toggle in [revealSearchField].
bool extraActions = true;

ThemeModel themeModel;

ContactViewState({@required this.themeModel});

/// Load all contacts when page is loaded initially. Initilize animations and controllers.
@override
void initState() {
Expand All @@ -110,15 +117,10 @@ abstract class ContactViewState extends State<ContactViewStateful>
.then((data) => contacts = data.toSet().toList());
appBarColorController =
AnimationController(vsync: this, duration: Duration(milliseconds: 250));
appBarBgColor = TweenSequence([
TweenSequenceItem(
tween: ColorTween(
begin: Color.fromRGBO(0, 62, 138, 1.0), end: Colors.blue[800]),
weight: 1.0),
TweenSequenceItem(
tween: ColorTween(begin: Colors.blue[800], end: Colors.white),
weight: 0.5)
]);

appBarBgColor = ColorTween(
begin: AppTheme.getTheme(themeModel.selectedTheme,SchedulerBinding.instance.window.platformBrightness).appBarTheme.color,
end: AppTheme.getTheme(themeModel.selectedTheme,SchedulerBinding.instance.window.platformBrightness).scaffoldBackgroundColor);
dropdownController =
AnimationController(vsync: this, duration: Duration(milliseconds: 250));
searchController = TextEditingController();
Expand All @@ -129,6 +131,7 @@ abstract class ContactViewState extends State<ContactViewStateful>
});
});
}


/// Dispose all disposable controllers.
@override
Expand Down
6 changes: 4 additions & 2 deletions lib/screens/contact_screen/contact_view_mobile.dart
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
import 'package:flutter/material.dart';
import 'package:fst_app_flutter/models/theme_model.dart';
import 'package:fst_app_flutter/screens/contact_screen/contact_view_mobile_state.dart';
import 'package:fst_app_flutter/screens/contact_screen/contact_view_stateful.dart';
import 'package:provider/provider.dart';

/// Full mobile portrait contact view made using [ContactViewMobilePortraitState].
class ContactViewMobilePortrait extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
body: ContactViewStateful(state: ContactViewMobilePortraitState()));
body: Consumer<ThemeModel>(builder:(context, theme, child) => ContactViewStateful(state: ContactViewMobilePortraitState(themeModel: theme))));
}
}

Expand All @@ -16,6 +18,6 @@ class ContactViewMobileLandscape extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
body: ContactViewStateful(state: ContactViewMobileLandscapeState()));
body: Consumer<ThemeModel>(builder: (context, theme, child) => ContactViewStateful(state: ContactViewMobileLandscapeState(themeModel: theme))));
}
}
134 changes: 70 additions & 64 deletions lib/screens/contact_screen/contact_view_mobile_state.dart
Original file line number Diff line number Diff line change
@@ -1,91 +1,97 @@
import 'package:flutter/material.dart';
import 'package:fst_app_flutter/models/theme_model.dart';
import 'package:fst_app_flutter/screens/contact_screen/contact_state.dart';

/// [ContactViewState] designed for phones in landscape orientation.
class ContactViewMobileLandscapeState extends ContactViewState {
ContactViewMobileLandscapeState({@required ThemeModel themeModel})
: super(themeModel: themeModel);

@override
Widget build(BuildContext context) {
var mq = MediaQuery.of(context);
var topViewInsets = mq.padding.top;

return Scaffold(
backgroundColor: Theme.of(context).backgroundColor,
body: SafeArea(
child: Stack(
children: <Widget>[
Container(),
buildStaticContactListArea(
posFromTop: kToolbarHeight,
height: mq.size.height - kToolbarHeight,
width: mq.size.width,
padH: mq.size.width * 0.05,
padV: mq.size.height * 0.05,
posFromLeft: 0.0,
thickness: 1.0,
),
Container(),
buildAppBarArea(
height: kToolbarHeight,
animationIntervalStart: 0.0,
animationIntervalEnd: 1.0,
actions: <Widget>[
filterDropdown(context,
height: kToolbarHeight,
width: mq.size.width / 3,
isExpanded: true,
elevation: 0.0),
],
elevation: 4.0),
],
)));
//backgroundColor: Theme.of(context).backgroundColor,
body: Stack(
children: <Widget>[
Container(),
buildStaticContactListArea(
posFromTop: kToolbarHeight + topViewInsets,
height: mq.size.height - kToolbarHeight,
width: mq.size.width,
padH: mq.size.width * 0.05,
padV: mq.size.height * 0.05,
posFromLeft: 0.0,
thickness: 1.0,
),
Container(),
buildAppBarArea(
height: kToolbarHeight,
animationIntervalStart: 0.0,
animationIntervalEnd: 1.0,
actions: <Widget>[
filterDropdown(context,
height: kToolbarHeight,
width: mq.size.width / 3,
isExpanded: true,
elevation: 0.0),
],
elevation: 4.0),
],
));
}
}

/// [ContactViewState] designed for phones in portrait orientation.
class ContactViewMobilePortraitState extends ContactViewState {
ContactViewMobilePortraitState({@required ThemeModel themeModel})
: super(themeModel: themeModel);

@override
Widget build(BuildContext context) {
// width and height calculations made using the [MediaQueryData]
var mq = MediaQuery.of(context);
// horizontal and vertical padding for the list of contacts
var padH = mq.size.width * 0.1;
var padV = (mq.size.height - (kToolbarHeight * 2)) * 0.07;
var topViewInsets = mq.padding.top;

return Scaffold(
backgroundColor: Theme.of(context).backgroundColor,
body: SafeArea(
child: Stack(
children: <Widget>[
Container(),
buildMovingContactListArea(
height: mq.size.height - (kToolbarHeight * 2),
padH: padH,
padV: padV,
width: mq.size.width,
posFromTop: kToolbarHeight * 2,
posFromLeft: 0.0,
thickness: 1.0,
growLeft: 0.0,
growTop: (kToolbarHeight * 2) * 0.5,
growBottom: 0.0,
growRight: 0.0,
posFromBottom: 0.0,
posFromRight: 0.0,
controller: dropdownController,
),
buildFilterDropdownArea(context,
posFromTop: kToolbarHeight,
width: MediaQuery.of(context).size.width,
height: kToolbarHeight,
isExpanded: true,
elevation: 4.0),
buildAppBarArea(
height: kToolbarHeight,
animationIntervalStart: 0.40,
animationIntervalEnd: 1.0,
actions: <Widget>[],
elevation: 0.0),
],
),
//backgroundColor: Theme.of(context).backgroundColor,
body: Stack(
children: <Widget>[
Container(),
buildMovingContactListArea(
height: mq.size.height - (kToolbarHeight * 2),
padH: padH,
padV: padV,
width: mq.size.width,
posFromTop: kToolbarHeight * 2 + topViewInsets,
posFromLeft: 0.0,
thickness: 1.0,
growLeft: 0.0,
growTop: (kToolbarHeight * 2) * 0.5,
growBottom: 0.0,
growRight: 0.0,
posFromBottom: 0.0,
posFromRight: 0.0,
controller: dropdownController,
),
buildFilterDropdownArea(context,
posFromTop: kToolbarHeight + topViewInsets,
width: MediaQuery.of(context).size.width,
height: kToolbarHeight,
isExpanded: true,
elevation: 4.0),
buildAppBarArea(
height: kToolbarHeight + topViewInsets,
animationIntervalStart: 0.40,
animationIntervalEnd: 1.0,
actions: <Widget>[],
elevation: 0.0),
],
),
);
}
Expand Down
6 changes: 4 additions & 2 deletions lib/screens/contact_screen/contact_view_tablet.dart
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
import 'package:flutter/material.dart';
import 'package:fst_app_flutter/models/theme_model.dart';
import 'package:fst_app_flutter/screens/contact_screen/contact_view_stateful.dart';
import 'package:fst_app_flutter/screens/contact_screen/contact_view_tablet_state.dart';
import 'package:provider/provider.dart';

/// Full portrait tablet contact view made using [ContactViewTabletPortraitState].
class ContactViewTabletPortrait extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
body: ContactViewStateful(state: ContactViewTabletPortraitState()));
body: Consumer<ThemeModel>(builder: (context, theme, child) => ContactViewStateful(state: ContactViewTabletPortraitState(themeModel: theme))));
}
}

Expand All @@ -16,6 +18,6 @@ class ContactViewTabletLandscape extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
body: ContactViewStateful(state: ContactViewTabletLandscapeState()));
body: Consumer<ThemeModel>(builder: (context, theme, child) => ContactViewStateful(state: ContactViewTabletLandscapeState(themeModel: theme))));
}
}
Loading

0 comments on commit 1912099

Please sign in to comment.