refactor: extract theme model from settings

This commit is contained in:
Rongjian Zhang
2019-09-02 21:52:32 +08:00
parent 6c6233cbcb
commit a67b389f72
18 changed files with 293 additions and 258 deletions

View File

@@ -1,5 +1,6 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart'; import 'package:flutter/cupertino.dart';
import 'package:git_touch/models/theme.dart';
import 'package:git_touch/screens/repo.dart'; import 'package:git_touch/screens/repo.dart';
import 'package:primer/primer.dart'; import 'package:primer/primer.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
@@ -25,6 +26,15 @@ class _HomeState extends State<Home> {
int active = 0; int active = 0;
// String login; // String login;
@override
void initState() {
super.initState();
nextTick(() {
// FIXME:
Provider.of<ThemeModel>(context).init();
});
}
Widget _buildNotificationIcon(BuildContext context) { Widget _buildNotificationIcon(BuildContext context) {
int count = Provider.of<NotificationModel>(context).count; int count = Provider.of<NotificationModel>(context).count;
if (count == 0) { if (count == 0) {
@@ -106,7 +116,7 @@ class _HomeState extends State<Home> {
); );
// TODO: // TODO:
if (!settings.ready) { if (!settings.ready || !Provider.of<ThemeModel>(context).ready) {
return MaterialApp(theme: themData, home: Scaffold(body: Text('a'))); return MaterialApp(theme: themData, home: Scaffold(body: Text('a')));
} }
@@ -115,7 +125,7 @@ class _HomeState extends State<Home> {
return MaterialApp(theme: themData, home: LoginScreen()); return MaterialApp(theme: themData, home: LoginScreen());
} }
switch (settings.theme) { switch (Provider.of<ThemeModel>(context).theme) {
case ThemeMap.cupertino: case ThemeMap.cupertino:
return CupertinoApp( return CupertinoApp(
home: CupertinoTheme( home: CupertinoTheme(
@@ -163,6 +173,7 @@ class App extends StatelessWidget {
return MultiProvider( return MultiProvider(
providers: [ providers: [
ChangeNotifierProvider(builder: (context) => NotificationModel()), ChangeNotifierProvider(builder: (context) => NotificationModel()),
ChangeNotifierProvider(builder: (context) => ThemeModel()),
], ],
child: SettingsProvider(child: Home()), child: SettingsProvider(child: Home()),
); );

184
lib/models/theme.dart Normal file
View File

@@ -0,0 +1,184 @@
import 'dart:io';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';
class DialogOption<T> {
final T value;
final Widget widget;
DialogOption({this.value, this.widget});
}
class ThemeMap {
static const material = 0;
static const cupertino = 1;
static const values = [ThemeMap.material, ThemeMap.cupertino];
}
class ThemeModel with ChangeNotifier {
static const storageKey = 'theme';
int _theme;
int get theme => _theme;
bool get ready => _theme != null;
init() async {
var prefs = await SharedPreferences.getInstance();
int v = prefs.getInt(storageKey);
print('read theme: $v');
if (ThemeMap.values.contains(v)) {
_theme = v;
} else if (Platform.isIOS) {
_theme = ThemeMap.cupertino;
} else {
_theme = ThemeMap.material;
}
notifyListeners();
}
Future<void> setTheme(int v) async {
SharedPreferences prefs = await SharedPreferences.getInstance();
_theme = v;
await prefs.setInt(storageKey, v);
print('write theme: $v');
notifyListeners();
}
void pushRoute({
@required BuildContext context,
@required WidgetBuilder builder,
bool fullscreenDialog = false,
}) {
switch (theme) {
case ThemeMap.cupertino:
Navigator.of(context).push(CupertinoPageRoute(
builder: builder,
fullscreenDialog: fullscreenDialog,
));
break;
default:
Navigator.of(context).push(MaterialPageRoute(
builder: builder,
fullscreenDialog: fullscreenDialog,
));
}
}
Future<bool> showConfirm(BuildContext context, String text) {
switch (theme) {
case ThemeMap.cupertino:
return showCupertinoDialog(
context: context,
builder: (context) {
return CupertinoAlertDialog(
title: Text(text),
actions: <Widget>[
CupertinoDialogAction(
child: const Text('cancel'),
isDefaultAction: true,
onPressed: () {
Navigator.pop(context, false);
},
),
CupertinoDialogAction(
child: const Text('OK'),
onPressed: () {
Navigator.pop(context, true);
},
),
],
);
},
);
default:
return showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
content: Text(
text,
// style: dialogTextStyle
),
actions: <Widget>[
FlatButton(
child: const Text('CANCEL'),
onPressed: () {
Navigator.pop(context, false);
},
),
FlatButton(
child: const Text('OK'),
onPressed: () {
Navigator.pop(context, true);
},
)
],
);
},
);
}
}
Future<T> showDialogOptions<T>(
BuildContext context, List<DialogOption<T>> options) {
var title = Text('Pick your reaction');
var cancelWidget = Text('Cancel');
switch (theme) {
case ThemeMap.cupertino:
return showCupertinoDialog<T>(
context: context,
builder: (BuildContext context) {
return CupertinoAlertDialog(
title: title,
actions: options.map((option) {
return CupertinoDialogAction(
child: option.widget,
onPressed: () {
Navigator.pop(context, option.value);
},
);
}).toList()
..add(
CupertinoDialogAction(
child: cancelWidget,
isDestructiveAction: true,
onPressed: () {
Navigator.pop(context, null);
},
),
),
);
},
);
default:
return showDialog(
context: context,
builder: (BuildContext context) {
return SimpleDialog(
title: title,
children: options.map<Widget>((option) {
return SimpleDialogOption(
child: option.widget,
onPressed: () {
Navigator.pop(context, option.value);
},
);
}).toList()
..add(SimpleDialogOption(
child: cancelWidget,
onPressed: () {
Navigator.pop(context, null);
},
)),
);
},
);
}
}
}

View File

@@ -37,12 +37,6 @@ class PlatformType {
// Future<T> queryGitlab(SettingsProviderState settings); // Future<T> queryGitlab(SettingsProviderState settings);
// } // }
class ThemeMap {
static const material = 0;
static const cupertino = 1;
static const values = [0, 1];
}
class SettingsProvider extends StatefulWidget { class SettingsProvider extends StatefulWidget {
final Widget child; final Widget child;
@@ -60,7 +54,6 @@ class SettingsProvider extends StatefulWidget {
class SettingsProviderState extends State<SettingsProvider> { class SettingsProviderState extends State<SettingsProvider> {
bool ready = false; bool ready = false;
int theme;
Map<String, AccountModel> githubAccountMap; Map<String, AccountModel> githubAccountMap;
Map<String, Map<String, Map<String, AccountModel>>> accountMap; Map<String, Map<String, Map<String, AccountModel>>> accountMap;
@@ -76,16 +69,6 @@ class SettingsProviderState extends State<SettingsProvider> {
String prefix = 'https://api.github.com'; String prefix = 'https://api.github.com';
Future<void> setTheme(int _theme) async {
SharedPreferences prefs = await SharedPreferences.getInstance();
theme = _theme;
await prefs.setInt(StorageKeys.theme, theme);
print('write theme: $theme');
setState(() {});
}
String get token { String get token {
if (activeLogin == null) return null; if (activeLogin == null) return null;
@@ -134,7 +117,7 @@ class SettingsProviderState extends State<SettingsProvider> {
'client_id': clientId, 'client_id': clientId,
'client_secret': clientSecret, 'client_secret': clientSecret,
'code': code, 'code': code,
'state': randomString, 'state': _oauthState,
}), }),
); );
// print(res.body); // print(res.body);
@@ -215,7 +198,7 @@ class SettingsProviderState extends State<SettingsProvider> {
} }
void _initDataFromPref() async { void _initDataFromPref() async {
SharedPreferences prefs = await SharedPreferences.getInstance(); var prefs = await SharedPreferences.getInstance();
// read GitHub accounts // read GitHub accounts
try { try {
@@ -262,14 +245,6 @@ class SettingsProviderState extends State<SettingsProvider> {
accountMap = {}; accountMap = {};
} }
int _theme = prefs.getInt(StorageKeys.theme);
print('read theme: $_theme');
if (ThemeMap.values.contains(_theme)) {
theme = _theme;
} else if (Platform.isIOS) {
theme = ThemeMap.cupertino;
}
setState(() { setState(() {
ready = true; ready = true;
}); });
@@ -283,6 +258,9 @@ class SettingsProviderState extends State<SettingsProvider> {
}); });
} }
Map<String, String> get _headers =>
{HttpHeaders.authorizationHeader: 'token $token'};
// http timeout // http timeout
var _timeoutDuration = Duration(seconds: 10); var _timeoutDuration = Duration(seconds: 10);
// var _timeoutDuration = Duration(seconds: 1); // var _timeoutDuration = Duration(seconds: 1);
@@ -315,7 +293,7 @@ class SettingsProviderState extends State<SettingsProvider> {
} }
Future<dynamic> getWithCredentials(String url, {String contentType}) async { Future<dynamic> getWithCredentials(String url, {String contentType}) async {
var headers = {HttpHeaders.authorizationHeader: 'token $token'}; var headers = _headers;
if (contentType != null) { if (contentType != null) {
// https://developer.github.com/v3/repos/contents/#custom-media-types // https://developer.github.com/v3/repos/contents/#custom-media-types
headers[HttpHeaders.contentTypeHeader] = contentType; headers[HttpHeaders.contentTypeHeader] = contentType;
@@ -328,69 +306,37 @@ class SettingsProviderState extends State<SettingsProvider> {
return data; return data;
} }
Future<dynamic> patchWithCredentials(String url) async { Future<void> patchWithCredentials(String url) async {
var headers = {HttpHeaders.authorizationHeader: 'token $token'}; await http.patch(prefix + url, headers: _headers).timeout(_timeoutDuration);
await http.patch(prefix + url, headers: headers).timeout(_timeoutDuration);
return true;
} }
Future<dynamic> putWithCredentials(String url, Future<void> putWithCredentials(String url,
{String contentType, String body}) async { {String contentType, String body}) async {
var headers = {HttpHeaders.authorizationHeader: 'token $token'}; await http
final res = await http .put(prefix + url, headers: _headers, body: body ?? {})
.put(prefix + url, headers: headers, body: body ?? {})
.timeout(_timeoutDuration); .timeout(_timeoutDuration);
// print(res.body);
return true;
} }
Future<dynamic> postWithCredentials(String url, Future<void> postWithCredentials(String url,
{String contentType, String body}) async { {String contentType, String body}) async {
var headers = {HttpHeaders.authorizationHeader: 'token $token'};
final res = await http final res = await http
.post(prefix + url, headers: headers, body: body ?? {}) .post(prefix + url, headers: _headers, body: body ?? {})
.timeout(_timeoutDuration);
// print(res.body);
return true;
}
Future<dynamic> deleteWithCredentials(String url) async {
var headers = {HttpHeaders.authorizationHeader: 'token $token'};
final res = await http
.delete(prefix + url, headers: headers)
.timeout(_timeoutDuration); .timeout(_timeoutDuration);
// print(res.body); // print(res.body);
return true;
} }
void pushRoute({ Future<void> deleteWithCredentials(String url) async {
@required BuildContext context, await http
@required WidgetBuilder builder, .delete(prefix + url, headers: _headers)
bool fullscreenDialog = false, .timeout(_timeoutDuration);
}) {
switch (theme) {
case ThemeMap.cupertino:
Navigator.of(context).push(CupertinoPageRoute(
builder: builder,
fullscreenDialog: fullscreenDialog,
));
break;
default:
Navigator.of(context).push(MaterialPageRoute(
builder: builder,
fullscreenDialog: fullscreenDialog,
));
}
} }
String randomString; String _oauthState;
void redirectToGithubOauth() {
generateRandomString() { _oauthState = nanoid();
randomString = nanoid(); launch(
return randomString; 'https://github.com/login/oauth/authorize?client_id=$clientId&redirect_uri=gittouch://login&scope=user%20repo&state=$_oauthState',
);
} }
@override @override

View File

@@ -1,7 +1,8 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart'; import 'package:flutter/cupertino.dart';
import 'package:flutter/widgets.dart'; import 'package:flutter/widgets.dart';
import '../providers/settings.dart'; import 'package:git_touch/models/theme.dart';
import 'package:provider/provider.dart';
import '../widgets/error_reload.dart'; import '../widgets/error_reload.dart';
import '../widgets/loading.dart'; import '../widgets/loading.dart';
import '../widgets/empty.dart'; import '../widgets/empty.dart';
@@ -185,7 +186,7 @@ class _ListScaffoldState<T, K> extends State<ListScaffold<T, K>> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
switch (SettingsProvider.of(context).theme) { switch (Provider.of<ThemeModel>(context).theme) {
case ThemeMap.cupertino: case ThemeMap.cupertino:
List<Widget> slivers = [ List<Widget> slivers = [
CupertinoSliverRefreshControl(onRefresh: _refresh) CupertinoSliverRefreshControl(onRefresh: _refresh)

View File

@@ -1,7 +1,8 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart'; import 'package:flutter/cupertino.dart';
import 'package:flutter/widgets.dart'; import 'package:flutter/widgets.dart';
import '../providers/settings.dart'; import 'package:git_touch/models/theme.dart';
import 'package:provider/provider.dart';
import '../widgets/loading.dart'; import '../widgets/loading.dart';
import '../widgets/link.dart'; import '../widgets/link.dart';
import '../widgets/error_reload.dart'; import '../widgets/error_reload.dart';
@@ -182,7 +183,7 @@ class _LongListScaffoldState<T, K> extends State<LongListScaffold<T, K>> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
switch (SettingsProvider.of(context).theme) { switch (Provider.of<ThemeModel>(context).theme) {
case ThemeMap.cupertino: case ThemeMap.cupertino:
List<Widget> slivers = [ List<Widget> slivers = [
CupertinoSliverRefreshControl(onRefresh: _refresh) CupertinoSliverRefreshControl(onRefresh: _refresh)

View File

@@ -1,7 +1,8 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart'; import 'package:flutter/cupertino.dart';
import 'package:flutter/widgets.dart'; import 'package:flutter/widgets.dart';
import '../providers/settings.dart'; import 'package:git_touch/models/theme.dart';
import 'package:provider/provider.dart';
import '../widgets/loading.dart'; import '../widgets/loading.dart';
import '../widgets/error_reload.dart'; import '../widgets/error_reload.dart';
@@ -81,7 +82,7 @@ class _RefreshScaffoldState<T> extends State<RefreshScaffold<T>> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
switch (SettingsProvider.of(context).theme) { switch (Provider.of<ThemeModel>(context).theme) {
case ThemeMap.cupertino: case ThemeMap.cupertino:
return CupertinoPageScaffold( return CupertinoPageScaffold(
navigationBar: CupertinoNavigationBar( navigationBar: CupertinoNavigationBar(

View File

@@ -1,7 +1,8 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart'; import 'package:flutter/cupertino.dart';
import 'package:flutter/widgets.dart'; import 'package:flutter/widgets.dart';
import '../providers/settings.dart'; import 'package:git_touch/models/theme.dart';
import 'package:provider/provider.dart';
import '../widgets/loading.dart'; import '../widgets/loading.dart';
import '../widgets/error_reload.dart'; import '../widgets/error_reload.dart';
@@ -39,7 +40,7 @@ class RefreshStatelessScaffold extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
switch (SettingsProvider.of(context).theme) { switch (Provider.of<ThemeModel>(context).theme) {
case ThemeMap.cupertino: case ThemeMap.cupertino:
return CupertinoPageScaffold( return CupertinoPageScaffold(
navigationBar: navigationBar:

View File

@@ -1,7 +1,8 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart'; import 'package:flutter/cupertino.dart';
import 'package:flutter/widgets.dart'; import 'package:flutter/widgets.dart';
import '../providers/settings.dart'; import 'package:git_touch/models/theme.dart';
import 'package:provider/provider.dart';
class SimpleScaffold extends StatelessWidget { class SimpleScaffold extends StatelessWidget {
final Widget title; final Widget title;
@@ -20,7 +21,7 @@ class SimpleScaffold extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
switch (SettingsProvider.of(context).theme) { switch (Provider.of<ThemeModel>(context).theme) {
case ThemeMap.cupertino: case ThemeMap.cupertino:
return CupertinoPageScaffold( return CupertinoPageScaffold(
navigationBar: navigationBar:

View File

@@ -113,12 +113,7 @@ class _LoginScreenState extends State<LoginScreen> {
...accounts.map(_buildAccountItem), ...accounts.map(_buildAccountItem),
_buildAddItem( _buildAddItem(
text: 'GitHub Account', text: 'GitHub Account',
onTap: () { onTap: settings.redirectToGithubOauth,
var state = settings.generateRandomString();
launch(
'https://github.com/login/oauth/authorize?client_id=$clientId&redirect_uri=gittouch://login&scope=user%20repo&state=$state',
);
},
), ),
// _buildAddItem( // _buildAddItem(
// text: 'GitLab Account', // text: 'GitLab Account',

View File

@@ -3,6 +3,7 @@ import 'package:flutter/cupertino.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import '../scaffolds/refresh_stateless.dart'; import '../scaffolds/refresh_stateless.dart';
import 'package:git_touch/models/notification.dart'; import 'package:git_touch/models/notification.dart';
import 'package:git_touch/models/theme.dart';
import '../providers/settings.dart'; import '../providers/settings.dart';
import '../widgets/notification_item.dart'; import '../widgets/notification_item.dart';
import '../widgets/list_group.dart'; import '../widgets/list_group.dart';
@@ -205,7 +206,7 @@ $key: pullRequest(number: ${item.number}) {
}; };
Widget _buildTitle() { Widget _buildTitle() {
switch (SettingsProvider.of(context).theme) { switch (Provider.of<ThemeModel>(context).theme) {
case ThemeMap.cupertino: case ThemeMap.cupertino:
// var textStyle = DefaultTextStyle.of(context).style; // var textStyle = DefaultTextStyle.of(context).style;
return DefaultTextStyle( return DefaultTextStyle(
@@ -224,7 +225,8 @@ $key: pullRequest(number: ${item.number}) {
} }
void _confirm() async { void _confirm() async {
var value = await showConfirm(context, 'Mark all as read?'); var value = await Provider.of<ThemeModel>(context)
.showConfirm(context, 'Mark all as read?');
if (value) { if (value) {
await SettingsProvider.of(context).putWithCredentials('/notifications'); await SettingsProvider.of(context).putWithCredentials('/notifications');
await _onSwitchTab(); await _onSwitchTab();

View File

@@ -2,8 +2,10 @@ import 'dart:convert';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart'; import 'package:flutter/cupertino.dart';
import 'package:flutter_markdown/flutter_markdown.dart'; import 'package:flutter_markdown/flutter_markdown.dart';
import 'package:git_touch/models/theme.dart';
import 'package:git_touch/screens/commits.dart'; import 'package:git_touch/screens/commits.dart';
import 'package:git_touch/screens/object.dart'; import 'package:git_touch/screens/object.dart';
import 'package:provider/provider.dart';
import 'package:share/share.dart'; import 'package:share/share.dart';
import 'package:url_launcher/url_launcher.dart'; import 'package:url_launcher/url_launcher.dart';
import '../providers/settings.dart'; import '../providers/settings.dart';
@@ -122,7 +124,7 @@ class _RepoScreenState extends State<RepoScreen> {
break; break;
} }
SettingsProvider.of(context) Provider.of<ThemeModel>(context)
.pushRoute(context: context, builder: builder); .pushRoute(context: context, builder: builder);
}, },
), ),

View File

@@ -1,5 +1,7 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart'; import 'package:flutter/cupertino.dart';
import 'package:git_touch/models/theme.dart';
import 'package:provider/provider.dart';
import '../providers/settings.dart'; import '../providers/settings.dart';
import '../scaffolds/simple.dart'; import '../scaffolds/simple.dart';
import '../utils/utils.dart'; import '../utils/utils.dart';
@@ -42,7 +44,7 @@ class _SearchScreenState extends State<SearchScreen> {
} }
Widget _buildInput() { Widget _buildInput() {
switch (SettingsProvider.of(context).theme) { switch (Provider.of<ThemeModel>(context).theme) {
case ThemeMap.cupertino: case ThemeMap.cupertino:
return CupertinoTextField( return CupertinoTextField(
// padding: EdgeInsets.all(10), // padding: EdgeInsets.all(10),
@@ -60,14 +62,16 @@ class _SearchScreenState extends State<SearchScreen> {
return SimpleScaffold( return SimpleScaffold(
title: Text('Search GitHub Repositories'), title: Text('Search GitHub Repositories'),
bodyBuilder: () { bodyBuilder: () {
return Column(children: <Widget>[ return Column(
Container(padding: EdgeInsets.all(8), child: _buildInput()), children: <Widget>[
loading Container(padding: EdgeInsets.all(8), child: _buildInput()),
? Loading() loading
: Column( ? Loading()
children: repos.map((repo) => RepoItem(repo)).toList(), : Column(
) children: repos.map((repo) => RepoItem(repo)).toList(),
]); )
],
);
}, },
); );
} }

View File

@@ -1,8 +1,9 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:git_touch/models/theme.dart';
import 'package:provider/provider.dart';
import 'package:url_launcher/url_launcher.dart'; import 'package:url_launcher/url_launcher.dart';
import 'package:launch_review/launch_review.dart'; import 'package:launch_review/launch_review.dart';
import '../scaffolds/simple.dart'; import '../scaffolds/simple.dart';
import '../providers/settings.dart';
import '../widgets/table_view.dart'; import '../widgets/table_view.dart';
import '../screens/repo.dart'; import '../screens/repo.dart';
import '../screens/login.dart'; import '../screens/login.dart';
@@ -15,7 +16,7 @@ class SettingsScreen extends StatefulWidget {
class _SettingsScreenState extends State<SettingsScreen> { class _SettingsScreenState extends State<SettingsScreen> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
var settings = SettingsProvider.of(context); var themeProvider = Provider.of<ThemeModel>(context);
return SimpleScaffold( return SimpleScaffold(
title: Text('Settings'), title: Text('Settings'),
@@ -36,19 +37,19 @@ class _SettingsScreenState extends State<SettingsScreen> {
items: [ items: [
TableViewItem( TableViewItem(
text: 'material', text: 'material',
checked: settings.theme == ThemeMap.material, checked: themeProvider.theme == ThemeMap.material,
onTap: () { onTap: () {
if (settings.theme != ThemeMap.material) { if (themeProvider.theme != ThemeMap.material) {
settings.setTheme(ThemeMap.material); themeProvider.setTheme(ThemeMap.material);
} }
}, },
), ),
TableViewItem( TableViewItem(
text: 'cupertino', text: 'cupertino',
checked: settings.theme == ThemeMap.cupertino, checked: themeProvider.theme == ThemeMap.cupertino,
onTap: () { onTap: () {
if (settings.theme != ThemeMap.cupertino) { if (themeProvider.theme != ThemeMap.cupertino) {
settings.setTheme(ThemeMap.cupertino); themeProvider.setTheme(ThemeMap.cupertino);
} }
}, },
), ),

View File

@@ -34,125 +34,6 @@ void nextTick(Function callback, [int milliseconds = 0]) {
}); });
} }
Future<bool> showConfirm(BuildContext context, String text) {
switch (SettingsProvider.of(context).theme) {
case ThemeMap.cupertino:
return showCupertinoDialog(
context: context,
builder: (context) {
return CupertinoAlertDialog(
title: Text(text),
actions: <Widget>[
CupertinoDialogAction(
child: const Text('cancel'),
isDefaultAction: true,
onPressed: () {
Navigator.pop(context, false);
},
),
CupertinoDialogAction(
child: const Text('OK'),
onPressed: () {
Navigator.pop(context, true);
},
),
],
);
},
);
default:
return showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
content: Text(
text,
// style: dialogTextStyle
),
actions: <Widget>[
FlatButton(
child: const Text('CANCEL'),
onPressed: () {
Navigator.pop(context, false);
},
),
FlatButton(
child: const Text('OK'),
onPressed: () {
Navigator.pop(context, true);
},
)
],
);
},
);
}
}
class DialogOption<T> {
final T value;
final Widget widget;
DialogOption({this.value, this.widget});
}
Future<T> showDialogOptions<T>(
BuildContext context, List<DialogOption<T>> options) {
var title = Text('Pick your reaction');
var cancelWidget = Text('Cancel');
switch (SettingsProvider.of(context).theme) {
case ThemeMap.cupertino:
return showCupertinoDialog<T>(
context: context,
builder: (BuildContext context) {
return CupertinoAlertDialog(
title: title,
actions: options.map((option) {
return CupertinoDialogAction(
child: option.widget,
onPressed: () {
Navigator.pop(context, option.value);
},
);
}).toList()
..add(
CupertinoDialogAction(
child: cancelWidget,
isDestructiveAction: true,
onPressed: () {
Navigator.pop(context, null);
},
),
),
);
},
);
default:
return showDialog(
context: context,
builder: (BuildContext context) {
return SimpleDialog(
title: title,
children: options.map<Widget>((option) {
return SimpleDialogOption(
child: option.widget,
onPressed: () {
Navigator.pop(context, option.value);
},
);
}).toList()
..add(SimpleDialogOption(
child: cancelWidget,
onPressed: () {
Navigator.pop(context, null);
},
)),
);
},
);
}
}
TextSpan createLinkSpan(BuildContext context, String text, Function handle) { TextSpan createLinkSpan(BuildContext context, String text, Function handle) {
return TextSpan( return TextSpan(
text: text, text: text,

View File

@@ -1,6 +1,7 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart'; import 'package:flutter/cupertino.dart';
import '../providers/settings.dart'; import 'package:provider/provider.dart';
import 'package:git_touch/models/theme.dart';
class MyAction { class MyAction {
String text; String text;
@@ -28,7 +29,7 @@ class ActionButton extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
switch (SettingsProvider.of(context).theme) { switch (Provider.of<ThemeModel>(context).theme) {
case ThemeMap.cupertino: case ThemeMap.cupertino:
return GestureDetector( return GestureDetector(
child: Icon(iconData, size: 24), child: Icon(iconData, size: 24),

View File

@@ -1,5 +1,7 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_markdown/flutter_markdown.dart'; import 'package:flutter_markdown/flutter_markdown.dart';
import 'package:git_touch/models/theme.dart';
import 'package:provider/provider.dart';
import 'package:timeago/timeago.dart' as timeago; import 'package:timeago/timeago.dart' as timeago;
import 'package:primer/primer.dart'; import 'package:primer/primer.dart';
import '../utils/utils.dart'; import '../utils/utils.dart';
@@ -102,19 +104,19 @@ class CommentItem extends StatelessWidget {
..add( ..add(
Link( Link(
onTap: () async { onTap: () async {
var result = await showDialogOptions( var result = await Provider.of<ThemeModel>(context)
context, .showDialogOptions(
emojiMap.entries.map((entry) { context,
var emojiKey = entry.key; emojiMap.entries.map((entry) {
return DialogOption( var emojiKey = entry.key;
value: emojiKey, return DialogOption(
widget: Container( value: emojiKey,
decoration: _getDecorationByKey(emojiKey), widget: Container(
child: Text(emojiKey + ' ' + entry.value), decoration: _getDecorationByKey(emojiKey),
), child: Text(emojiKey + ' ' + entry.value),
); ),
}).toList(), );
); }).toList());
onReaction(result, _hasReacted(result)); onReaction(result, _hasReacted(result));
}, },
child: Container( child: Container(

View File

@@ -1,7 +1,8 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart'; import 'package:flutter/cupertino.dart';
import 'package:provider/provider.dart';
import 'package:url_launcher/url_launcher.dart'; import 'package:url_launcher/url_launcher.dart';
import '../providers/settings.dart'; import 'package:git_touch/models/theme.dart';
class Link extends StatelessWidget { class Link extends StatelessWidget {
final Widget child; final Widget child;
@@ -31,11 +32,10 @@ class Link extends StatelessWidget {
} }
if (screenBuilder != null) { if (screenBuilder != null) {
SettingsProvider.of(context).pushRoute( Provider.of<ThemeModel>(context).pushRoute(
context: context, context: context,
builder: screenBuilder, builder: screenBuilder,
fullscreenDialog: fullscreenDialog, fullscreenDialog: fullscreenDialog);
);
} }
if (url != null) { if (url != null) {
@@ -45,7 +45,7 @@ class Link extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
var theme = SettingsProvider.of(context).theme; var theme = Provider.of<ThemeModel>(context).theme;
if (iconButton != null) { if (iconButton != null) {
return IconButton( return IconButton(

View File

@@ -1,6 +1,7 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart'; import 'package:flutter/cupertino.dart';
import '../providers/settings.dart'; import 'package:git_touch/models/theme.dart';
import 'package:provider/provider.dart';
class Loading extends StatelessWidget { class Loading extends StatelessWidget {
final bool more; final bool more;
@@ -10,7 +11,7 @@ class Loading extends StatelessWidget {
Widget _buildIndicator(BuildContext context) { Widget _buildIndicator(BuildContext context) {
// return Image.asset('images/loading.webp'); // return Image.asset('images/loading.webp');
switch (SettingsProvider.of(context).theme) { switch (Provider.of<ThemeModel>(context).theme) {
case ThemeMap.cupertino: case ThemeMap.cupertino:
return CupertinoActivityIndicator(radius: 12); return CupertinoActivityIndicator(radius: 12);
default: default: