[flutter]: update home page topbar title after the view name changed

This commit is contained in:
appflowy 2021-10-28 21:55:22 +08:00
parent 6c8ecc8296
commit 17f5a6ac9d
6 changed files with 95 additions and 53 deletions

View File

@ -9,7 +9,7 @@ import 'package:app_flowy/workspace/presentation/widgets/prelude.dart';
typedef NavigationCallback = void Function(String id); typedef NavigationCallback = void Function(String id);
abstract class NavigationItem { abstract class NavigationItem {
Widget get titleWidget; Widget get naviTitle;
String get identifier; String get identifier;
NavigationCallback get action => (id) { NavigationCallback get action => (id) {
@ -25,30 +25,44 @@ enum HomeStackType {
List<HomeStackType> pages = HomeStackType.values.toList(); List<HomeStackType> pages = HomeStackType.values.toList();
abstract class HomeStackContext extends Equatable with NavigationItem { abstract class HomeStackContext<T> with NavigationItem {
List<NavigationItem> get navigationItems; List<NavigationItem> get navigationItems;
@override @override
Widget get titleWidget; Widget get naviTitle;
@override @override
String get identifier; String get identifier;
ValueNotifier<T> get isUpdated;
HomeStackType get type; HomeStackType get type;
Widget render(); Widget buildWidget();
void dispose();
} }
class HomeStackNotifier extends ChangeNotifier { class HomeStackNotifier extends ChangeNotifier {
HomeStackContext inner; HomeStackContext stackContext;
HomeStackNotifier({HomeStackContext? context}) : inner = context ?? BlankStackContext(); Widget get titleWidget => stackContext.naviTitle;
HomeStackNotifier({HomeStackContext? context}) : stackContext = context ?? BlankStackContext();
set context(HomeStackContext context) { set context(HomeStackContext context) {
inner = context; notifyChange() {
notifyListeners();
}
stackContext.isUpdated.removeListener(notifyChange);
stackContext.dispose();
stackContext = context;
stackContext.isUpdated.addListener(notifyChange);
notifyListeners(); notifyListeners();
} }
HomeStackContext get context => inner; HomeStackContext get context => stackContext;
} }
// HomeStack is initialized as singleton to controll the page stack. // HomeStack is initialized as singleton to controll the page stack.
@ -57,7 +71,7 @@ class HomeStackManager {
HomeStackManager(); HomeStackManager();
Widget title() { Widget title() {
return _notifier.context.titleWidget; return _notifier.context.naviTitle;
} }
void setStack(HomeStackContext context) { void setStack(HomeStackContext context) {
@ -71,9 +85,12 @@ class HomeStackManager {
providers: [ providers: [
ChangeNotifierProvider.value(value: _notifier), ChangeNotifierProvider.value(value: _notifier),
], ],
child: Consumer(builder: (ctx, HomeStackNotifier notifier, child) { child: Selector<HomeStackNotifier, Widget>(
return HomeTopBar(view: notifier.context); selector: (context, notifier) => notifier.titleWidget,
}), builder: (context, widget, child) {
return const HomeTopBar();
},
),
); );
} }
@ -87,7 +104,7 @@ class HomeStackManager {
index: pages.indexOf(notifier.context.type), index: pages.indexOf(notifier.context.type),
children: HomeStackType.values.map((viewType) { children: HomeStackType.values.map((viewType) {
if (viewType == notifier.context.type) { if (viewType == notifier.context.type) {
return notifier.context.render(); return notifier.context.buildWidget();
} else { } else {
return const BlankStackPage(); return const BlankStackPage();
} }

View File

@ -8,15 +8,13 @@ import 'package:styled_widget/styled_widget.dart';
typedef NaviAction = void Function(); typedef NaviAction = void Function();
class NavigationNotifier with ChangeNotifier { class NavigationNotifier with ChangeNotifier {
HomeStackNotifier homeStackNotifier; List<NavigationItem> navigationItems;
NavigationNotifier(this.homeStackNotifier); NavigationNotifier({required this.navigationItems});
void update(HomeStackNotifier notifier) { void update(HomeStackNotifier notifier) {
homeStackNotifier = notifier; navigationItems = notifier.context.navigationItems;
notifyListeners(); notifyListeners();
} }
List<NavigationItem> get naviItems => homeStackNotifier.context.navigationItems;
} }
// [[diagram: HomeStack navigation flow]] // [[diagram: HomeStack navigation flow]]
@ -45,12 +43,15 @@ class FlowyNavigation extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return ChangeNotifierProxyProvider<HomeStackNotifier, NavigationNotifier>( return ChangeNotifierProxyProvider<HomeStackNotifier, NavigationNotifier>(
create: (_) => NavigationNotifier( create: (_) {
Provider.of<HomeStackNotifier>(context, listen: false), final notifier = Provider.of<HomeStackNotifier>(context, listen: false);
), return NavigationNotifier(
navigationItems: notifier.context.navigationItems,
);
},
update: (_, notifier, controller) => controller!..update(notifier), update: (_, notifier, controller) => controller!..update(notifier),
child: Consumer(builder: (ctx, NavigationNotifier notifier, child) { child: Consumer(builder: (ctx, NavigationNotifier notifier, child) {
return Row(children: _renderChildren(notifier.naviItems)); return Row(children: _renderChildren(notifier.navigationItems));
}), }),
); );
} }
@ -96,7 +97,7 @@ class IconNaviItemWidget extends StatelessWidget {
return SizedBox( return SizedBox(
height: 24, height: 24,
child: InkWell( child: InkWell(
child: item.titleWidget, child: item.naviTitle,
onTap: () { onTap: () {
debugPrint('show app document'); debugPrint('show app document');
}, },
@ -114,7 +115,7 @@ class NaviItemWidget extends StatelessWidget {
return SizedBox( return SizedBox(
height: 24, height: 24,
child: InkWell( child: InkWell(
child: item.titleWidget, child: item.naviTitle,
onTap: () { onTap: () {
debugPrint('show app document'); debugPrint('show app document');
}, },
@ -142,7 +143,7 @@ class EllipsisNaviItem extends NavigationItem {
}); });
@override @override
Widget get titleWidget => const FlowyText.medium('...'); Widget get naviTitle => const FlowyText.medium('...');
@override @override
NavigationCallback get action => (id) {}; NavigationCallback get action => (id) {};

View File

@ -1,28 +1,32 @@
import 'package:app_flowy/workspace/domain/page_stack/page_stack.dart'; import 'package:app_flowy/workspace/domain/page_stack/page_stack.dart';
import 'package:flowy_infra_ui/style_widget/text.dart'; import 'package:flowy_infra_ui/style_widget/text.dart';
import 'package:flowy_sdk/protobuf/flowy-workspace/view_create.pb.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
class BlankStackContext extends HomeStackContext { class BlankStackContext extends HomeStackContext {
final ValueNotifier<bool> _isUpdated = ValueNotifier<bool>(false);
@override @override
String get identifier => "1"; String get identifier => "1";
@override @override
List<Object?> get props => ["1"]; Widget get naviTitle => const FlowyText.medium('Blank page', fontSize: 12);
@override
Widget get titleWidget => const FlowyText.medium('Blank page', fontSize: 12);
@override @override
HomeStackType get type => HomeStackType.blank; HomeStackType get type => HomeStackType.blank;
@override @override
Widget render() { Widget buildWidget() {
return const BlankStackPage(); return const BlankStackPage();
} }
@override @override
List<NavigationItem> get navigationItems => [this]; List<NavigationItem> get navigationItems => [this];
@override
ValueNotifier<bool> get isUpdated => _isUpdated;
@override
void dispose() {}
} }
class BlankStackPage extends StatefulWidget { class BlankStackPage extends StatefulWidget {

View File

@ -1,3 +1,5 @@
import 'package:app_flowy/startup/startup.dart';
import 'package:app_flowy/workspace/domain/i_view.dart';
import 'package:app_flowy/workspace/domain/page_stack/page_stack.dart'; import 'package:app_flowy/workspace/domain/page_stack/page_stack.dart';
import 'package:app_flowy/workspace/domain/view_ext.dart'; import 'package:app_flowy/workspace/domain/view_ext.dart';
import 'package:flowy_infra_ui/style_widget/text.dart'; import 'package:flowy_infra_ui/style_widget/text.dart';
@ -7,36 +9,55 @@ import 'package:flutter/material.dart';
import 'doc_page.dart'; import 'doc_page.dart';
class DocStackContext extends HomeStackContext { class DocStackContext extends HomeStackContext {
final View _view; View _view;
DocStackContext({required View view, Key? key}) : _view = view; late IViewListener _listener;
final ValueNotifier<String> _isUpdated = ValueNotifier<String>("");
DocStackContext({required View view, Key? key}) : _view = view {
_listener = getIt<IViewListener>(param1: view);
_listener.start(updatedCallback: (result) {
result.fold(
(newView) {
_view = newView;
_isUpdated.value = _view.name;
},
(error) {},
);
});
}
@override @override
Widget get titleWidget => FlowyText.medium(_view.name, fontSize: 12); Widget get naviTitle => FlowyText.medium(_view.name, fontSize: 12);
@override @override
String get identifier => _view.id; String get identifier => _view.id;
@override @override
HomeStackType get type => _view.stackType(); HomeStackType get type => _view.stackType();
@override @override
List<Object?> get props => [_view.id]; Widget buildWidget() {
@override
Widget render() {
return DocStackPage(_view, key: ValueKey(_view.id)); return DocStackPage(_view, key: ValueKey(_view.id));
} }
@override @override
List<NavigationItem> get navigationItems => makeNavigationItems(); List<NavigationItem> get navigationItems => _makeNavigationItems();
@override
ValueNotifier<String> get isUpdated => _isUpdated;
// List<NavigationItem> get navigationItems => naviStacks.map((stack) { // List<NavigationItem> get navigationItems => naviStacks.map((stack) {
// return NavigationItemImpl(context: stack); // return NavigationItemImpl(context: stack);
// }).toList(); // }).toList();
List<NavigationItem> makeNavigationItems() { List<NavigationItem> _makeNavigationItems() {
return [ return [
this, this,
]; ];
} }
@override
void dispose() {
_listener.stop();
}
} }
class DocStackPage extends StatefulWidget { class DocStackPage extends StatefulWidget {

View File

@ -19,25 +19,30 @@ import 'package:styled_widget/styled_widget.dart';
import 'widget/trash_header.dart'; import 'widget/trash_header.dart';
class TrashStackContext extends HomeStackContext { class TrashStackContext extends HomeStackContext {
final ValueNotifier<bool> _isUpdated = ValueNotifier<bool>(false);
@override @override
String get identifier => "TrashStackContext"; String get identifier => "TrashStackContext";
@override @override
List<Object?> get props => ["TrashStackContext"]; Widget get naviTitle => const FlowyText.medium('Trash', fontSize: 12);
@override
Widget get titleWidget => const FlowyText.medium('Trash', fontSize: 12);
@override @override
HomeStackType get type => HomeStackType.trash; HomeStackType get type => HomeStackType.trash;
@override @override
Widget render() { Widget buildWidget() {
return const TrashStackPage(key: ValueKey('TrashStackPage')); return const TrashStackPage(key: ValueKey('TrashStackPage'));
} }
@override @override
List<NavigationItem> get navigationItems => [this]; List<NavigationItem> get navigationItems => [this];
@override
ValueNotifier<bool> get isUpdated => _isUpdated;
@override
void dispose() {}
} }
class TrashStackPage extends StatefulWidget { class TrashStackPage extends StatefulWidget {

View File

@ -1,5 +1,4 @@
import 'package:app_flowy/workspace/domain/image.dart'; import 'package:app_flowy/workspace/domain/image.dart';
import 'package:app_flowy/workspace/domain/page_stack/page_stack.dart';
import 'package:app_flowy/workspace/presentation/home/home_sizes.dart'; import 'package:app_flowy/workspace/presentation/home/home_sizes.dart';
import 'package:app_flowy/workspace/presentation/home/navigation.dart'; import 'package:app_flowy/workspace/presentation/home/navigation.dart';
import 'package:flowy_infra/size.dart'; import 'package:flowy_infra/size.dart';
@ -12,8 +11,7 @@ import 'package:flowy_infra_ui/style_widget/extension.dart';
import 'package:flowy_infra_ui/style_widget/text.dart'; import 'package:flowy_infra_ui/style_widget/text.dart';
class HomeTopBar extends StatelessWidget { class HomeTopBar extends StatelessWidget {
final HomeStackContext view; const HomeTopBar({Key? key}) : super(key: key);
const HomeTopBar({Key? key, required this.view}) : super(key: key);
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
@ -22,7 +20,7 @@ class HomeTopBar extends StatelessWidget {
child: Row( child: Row(
crossAxisAlignment: CrossAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center,
children: [ children: [
_renderNavigation(view), const FlowyNavigation(),
const Spacer(), const Spacer(),
_renderShareButton(), _renderShareButton(),
// _renderMoreButton(), // _renderMoreButton(),
@ -48,10 +46,6 @@ class HomeTopBar extends StatelessWidget {
}, },
); );
} }
Widget _renderNavigation(HomeStackContext view) {
return const FlowyNavigation();
}
} }
class HomeTitle extends StatelessWidget { class HomeTitle extends StatelessWidget {