added hook for stores

This commit is contained in:
shilangyu 2020-09-16 23:15:42 +02:00
parent d3eee1e837
commit c6b03c3aef
6 changed files with 71 additions and 69 deletions

8
lib/hooks/stores.dart Normal file
View File

@ -0,0 +1,8 @@
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:provider/provider.dart';
import '../stores/accounts_store.dart';
import '../stores/config_store.dart';
AccountsStore useAccountsStore() => useContext().watch<AccountsStore>();
ConfigStore useConfigStore() => useContext().watch<ConfigStore>();

View File

@ -1,8 +1,10 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:flutter_mobx/flutter_mobx.dart'; import 'package:flutter_mobx/flutter_mobx.dart';
import 'package:lemmur/pages/profile_tab.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'pages/instance.dart'; import 'hooks/stores.dart';
import 'stores/accounts_store.dart'; import 'stores/accounts_store.dart';
import 'stores/config_store.dart'; import 'stores/config_store.dart';
@ -32,32 +34,34 @@ Future<void> main() async {
); );
} }
class MyApp extends StatelessWidget { class MyApp extends HookWidget {
@override @override
Widget build(BuildContext context) => Observer( Widget build(BuildContext context) {
builder: (ctx) { final configStore = useConfigStore();
var maybeAmoledColor =
ctx.watch<ConfigStore>().amoledDarkMode ? Colors.black : null;
return MaterialApp( return Observer(
title: 'Flutter Demo', builder: (ctx) {
themeMode: ctx.watch<ConfigStore>().theme, final maybeAmoledColor =
darkTheme: ThemeData.dark().copyWith( configStore.amoledDarkMode ? Colors.black : null;
scaffoldBackgroundColor: maybeAmoledColor,
backgroundColor: maybeAmoledColor, return MaterialApp(
canvasColor: maybeAmoledColor, title: 'Flutter Demo',
cardColor: maybeAmoledColor, themeMode: configStore.theme,
splashColor: maybeAmoledColor, darkTheme: ThemeData.dark().copyWith(
), scaffoldBackgroundColor: maybeAmoledColor,
theme: ThemeData( backgroundColor: maybeAmoledColor,
visualDensity: VisualDensity.adaptivePlatformDensity, canvasColor: maybeAmoledColor,
), cardColor: maybeAmoledColor,
home: InstancePage( splashColor: maybeAmoledColor,
instanceUrl: 'dev.lemmy.ml', ),
), theme: ThemeData(
); visualDensity: VisualDensity.adaptivePlatformDensity,
}, ),
); home: UserProfileTab(),
);
},
);
}
} }
class MyHomePage extends StatefulWidget { class MyHomePage extends StatefulWidget {

View File

@ -4,11 +4,10 @@ import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:fuzzy/fuzzy.dart'; import 'package:fuzzy/fuzzy.dart';
import 'package:lemmur/hooks/stores.dart';
import 'package:lemmy_api_client/lemmy_api_client.dart'; import 'package:lemmy_api_client/lemmy_api_client.dart';
import 'package:provider/provider.dart';
import '../hooks/delayed_loading.dart'; import '../hooks/delayed_loading.dart';
import '../stores/accounts_store.dart';
import '../util/extensions/iterators.dart'; import '../util/extensions/iterators.dart';
import '../util/text_color.dart'; import '../util/text_color.dart';
@ -20,9 +19,9 @@ class CommunitiesTab extends HookWidget {
var theme = Theme.of(context); var theme = Theme.of(context);
var filterController = useTextEditingController(); var filterController = useTextEditingController();
useValueListenable(filterController); useValueListenable(filterController);
var amountOfDisplayInstances = useMemoized(() { final accountsStore = useAccountsStore();
var accountsStore = context.watch<AccountsStore>();
var amountOfDisplayInstances = useMemoized(() {
return accountsStore.users.keys return accountsStore.users.keys
.where((e) => !accountsStore.isAnonymousFor(e)) .where((e) => !accountsStore.isAnonymousFor(e))
.length; .length;
@ -31,8 +30,6 @@ class CommunitiesTab extends HookWidget {
// TODO: use useMemoFuture // TODO: use useMemoFuture
var instancesFut = useMemoized(() { var instancesFut = useMemoized(() {
var accountsStore = context.watch<AccountsStore>();
var futures = accountsStore.users.keys var futures = accountsStore.users.keys
.where((e) => !accountsStore.isAnonymousFor(e)) .where((e) => !accountsStore.isAnonymousFor(e))
.map( .map(
@ -44,8 +41,6 @@ class CommunitiesTab extends HookWidget {
return Future.wait(futures); return Future.wait(futures);
}); });
var communitiesFut = useMemoized(() { var communitiesFut = useMemoized(() {
var accountsStore = context.watch<AccountsStore>();
var futures = accountsStore.users.keys var futures = accountsStore.users.keys
.where((e) => !accountsStore.isAnonymousFor(e)) .where((e) => !accountsStore.isAnonymousFor(e))
.map( .map(
@ -239,6 +234,7 @@ class _CommunitySubscribeToggle extends HookWidget {
var theme = Theme.of(context); var theme = Theme.of(context);
var subbed = useState(true); var subbed = useState(true);
var delayed = useDelayedLoading(const Duration(milliseconds: 500)); var delayed = useDelayedLoading(const Duration(milliseconds: 500));
final accountsStore = useAccountsStore();
handleTap() async { handleTap() async {
delayed.start(); delayed.start();
@ -247,10 +243,7 @@ class _CommunitySubscribeToggle extends HookWidget {
await LemmyApi(instanceUrl).v1.followCommunity( await LemmyApi(instanceUrl).v1.followCommunity(
communityId: communityId, communityId: communityId,
follow: !subbed.value, follow: !subbed.value,
auth: context auth: accountsStore.defaultTokenFor(instanceUrl).raw,
.read<AccountsStore>()
.defaultTokenFor(instanceUrl)
.raw,
); );
subbed.value = !subbed.value; subbed.value = !subbed.value;
} on Exception catch (err) { } on Exception catch (err) {

View File

@ -6,12 +6,11 @@ import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:intl/intl.dart'; import 'package:intl/intl.dart';
import 'package:lemmur/hooks/stores.dart';
import 'package:lemmy_api_client/lemmy_api_client.dart'; import 'package:lemmy_api_client/lemmy_api_client.dart';
import 'package:provider/provider.dart';
import 'package:url_launcher/url_launcher.dart' as ul; import 'package:url_launcher/url_launcher.dart' as ul;
import '../hooks/memo_future.dart'; import '../hooks/memo_future.dart';
import '../stores/accounts_store.dart';
import '../util/api_extensions.dart'; import '../util/api_extensions.dart';
import '../util/goto.dart'; import '../util/goto.dart';
import '../util/intl.dart'; import '../util/intl.dart';
@ -49,8 +48,10 @@ class CommunityPage extends HookWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final theme = Theme.of(context); final theme = Theme.of(context);
final accountsStore = useAccountsStore();
var fullCommunitySnap = useMemoFuture(() { var fullCommunitySnap = useMemoFuture(() {
final token = context.watch<AccountsStore>().defaultTokenFor(instanceUrl); final token = accountsStore.defaultTokenFor(instanceUrl);
if (communityId != null) { if (communityId != null) {
return LemmyApi(instanceUrl).v1.getCommunity( return LemmyApi(instanceUrl).v1.getCommunity(
@ -535,14 +536,14 @@ class _FollowButton extends HookWidget {
final theme = Theme.of(context); final theme = Theme.of(context);
final isSubbed = useState(community.subscribed ?? false); final isSubbed = useState(community.subscribed ?? false);
final colorOnTopOfAccent = textColorBasedOnBackground(theme.accentColor); final token = useAccountsStore().defaultTokenFor(community.instanceUrl);
final token =
context.watch<AccountsStore>().defaultTokenFor(community.instanceUrl);
// TODO: use hook for handling spinner and pending // TODO: use hook for handling spinner and pending
final showSpinner = useState(false); final showSpinner = useState(false);
final isPending = useState(false); final isPending = useState(false);
final colorOnTopOfAccent = textColorBasedOnBackground(theme.accentColor);
subscribe() async { subscribe() async {
if (token == null) { if (token == null) {
Scaffold.of(context).showSnackBar( Scaffold.of(context).showSnackBar(

View File

@ -2,9 +2,8 @@ import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:flutter_mobx/flutter_mobx.dart'; import 'package:flutter_mobx/flutter_mobx.dart';
import 'package:provider/provider.dart'; import 'package:lemmur/hooks/stores.dart';
import '../stores/accounts_store.dart';
import '../util/api_extensions.dart'; import '../util/api_extensions.dart';
import '../util/goto.dart'; import '../util/goto.dart';
import '../widgets/bottom_modal.dart'; import '../widgets/bottom_modal.dart';
@ -17,10 +16,11 @@ class UserProfileTab extends HookWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
var theme = Theme.of(context); var theme = Theme.of(context);
final accountsStore = useAccountsStore();
return Observer( return Observer(
builder: (ctx) { builder: (ctx) {
if (ctx.watch<AccountsStore>().hasNoAccount) { if (accountsStore.hasNoAccount) {
return Scaffold( return Scaffold(
body: Center( body: Center(
child: Column( child: Column(
@ -40,7 +40,7 @@ class UserProfileTab extends HookWidget {
); );
} }
var user = ctx.watch<AccountsStore>().defaultUser; var user = accountsStore.defaultUser;
return Scaffold( return Scaffold(
extendBodyBehindAppBar: true, extendBodyBehindAppBar: true,
@ -71,10 +71,7 @@ class UserProfileTab extends HookWidget {
builder: (_) { builder: (_) {
var userTags = <String>[]; var userTags = <String>[];
ctx accountsStore.users.forEach((instanceUrl, value) {
.read<AccountsStore>()
.users
.forEach((instanceUrl, value) {
value.forEach((username, _) { value.forEach((username, _) {
userTags.add('$username@$instanceUrl'); userTags.add('$username@$instanceUrl');
}); });
@ -82,7 +79,7 @@ class UserProfileTab extends HookWidget {
return Observer( return Observer(
builder: (ctx) { builder: (ctx) {
var user = ctx.watch<AccountsStore>().defaultUser; var user = accountsStore.defaultUser;
var instanceUrl = user.instanceUrl; var instanceUrl = user.instanceUrl;
return BottomModal( return BottomModal(
@ -96,7 +93,7 @@ class UserProfileTab extends HookWidget {
groupValue: '${user.name}@$instanceUrl', groupValue: '${user.name}@$instanceUrl',
onChanged: (selected) { onChanged: (selected) {
var userTag = selected.split('@'); var userTag = selected.split('@');
ctx.read<AccountsStore>().setDefaultAccount( accountsStore.setDefaultAccount(
userTag[1], userTag[0]); userTag[1], userTag[0]);
Navigator.of(ctx).pop(); Navigator.of(ctx).pop();
}, },

View File

@ -2,10 +2,8 @@ import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:flutter_mobx/flutter_mobx.dart'; import 'package:flutter_mobx/flutter_mobx.dart';
import 'package:provider/provider.dart'; import 'package:lemmur/hooks/stores.dart';
import '../stores/accounts_store.dart';
import '../stores/config_store.dart';
import '../util/goto.dart'; import '../util/goto.dart';
class SettingsPage extends StatelessWidget { class SettingsPage extends StatelessWidget {
@ -49,6 +47,7 @@ class AppearanceConfigPage extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
var theme = Theme.of(context); var theme = Theme.of(context);
final configStore = useConfigStore();
return Scaffold( return Scaffold(
appBar: AppBar( appBar: AppBar(
@ -66,16 +65,16 @@ class AppearanceConfigPage extends StatelessWidget {
RadioListTile<ThemeMode>( RadioListTile<ThemeMode>(
value: theme, value: theme,
title: Text(theme.toString().split('.')[1]), title: Text(theme.toString().split('.')[1]),
groupValue: ctx.watch<ConfigStore>().theme, groupValue: configStore.theme,
onChanged: (selected) { onChanged: (selected) {
ctx.read<ConfigStore>().theme = selected; configStore.theme = selected;
}, },
), ),
SwitchListTile( SwitchListTile(
title: Text('AMOLED dark mode'), title: Text('AMOLED dark mode'),
value: ctx.watch<ConfigStore>().amoledDarkMode, value: configStore.amoledDarkMode,
onChanged: (checked) { onChanged: (checked) {
ctx.read<ConfigStore>().amoledDarkMode = checked; configStore.amoledDarkMode = checked;
}) })
], ],
), ),
@ -90,6 +89,7 @@ class AccountsConfigPage extends HookWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
var theme = Theme.of(context); var theme = Theme.of(context);
final accountsStore = useAccountsStore();
return Scaffold( return Scaffold(
key: _scaffoldKey, key: _scaffoldKey,
@ -112,7 +112,6 @@ class AccountsConfigPage extends HookWidget {
), ),
body: Observer( body: Observer(
builder: (ctx) { builder: (ctx) {
var accountsStore = ctx.watch<AccountsStore>();
var theme = Theme.of(context); var theme = Theme.of(context);
return ListView( return ListView(
@ -168,15 +167,14 @@ class _AccountsConfigAddInstanceDialog extends HookWidget {
Widget build(BuildContext context) { Widget build(BuildContext context) {
var instanceController = useTextEditingController(); var instanceController = useTextEditingController();
useValueListenable(instanceController); useValueListenable(instanceController);
final accountsStore = useAccountsStore();
var loading = useState(false); var loading = useState(false);
handleOnAdd() async { handleOnAdd() async {
try { try {
loading.value = true; loading.value = true;
await context await accountsStore.addInstance(instanceController.text);
.read<AccountsStore>()
.addInstance(instanceController.text);
scaffoldKey.currentState.hideCurrentSnackBar(); scaffoldKey.currentState.hideCurrentSnackBar();
} on Exception catch (err) { } on Exception catch (err) {
scaffoldKey.currentState.showSnackBar(SnackBar( scaffoldKey.currentState.showSnackBar(SnackBar(
@ -226,17 +224,18 @@ class _AccountsConfigAddAccountDialog extends HookWidget {
var passwordController = useTextEditingController(); var passwordController = useTextEditingController();
useValueListenable(usernameController); useValueListenable(usernameController);
useValueListenable(passwordController); useValueListenable(passwordController);
final accountsStore = useAccountsStore();
var loading = useState(false); var loading = useState(false);
handleOnAdd() async { handleOnAdd() async {
try { try {
loading.value = true; loading.value = true;
await context.read<AccountsStore>().addAccount( await accountsStore.addAccount(
instanceUrl, instanceUrl,
usernameController.text, usernameController.text,
passwordController.text, passwordController.text,
); );
} on Exception catch (err) { } on Exception catch (err) {
scaffoldKey.currentState.showSnackBar(SnackBar( scaffoldKey.currentState.showSnackBar(SnackBar(
content: Text(err.toString()), content: Text(err.toString()),