From 23ac4d024928f94c544131f9e5fb90eb33556708 Mon Sep 17 00:00:00 2001 From: appflowy Date: Wed, 28 Jul 2021 18:19:16 +0800 Subject: [PATCH] config navigation widget --- .../domain/page_stack/page_stack.dart | 69 ++-- .../domain/page_stack/page_stack_bloc.dart | 35 -- .../page_stack/page_stack_bloc.freezed.dart | 337 ------------------ .../workspace/presentation/doc/doc_page.dart | 1 + .../presentation/home/navigation_list.dart | 137 +++++++ .../presentation/widgets/blank_page.dart | 2 +- .../presentation/widgets/home_top_bar.dart | 29 +- .../lib/style_widget/navigation_list.dart | 104 ------ 8 files changed, 205 insertions(+), 509 deletions(-) delete mode 100644 app_flowy/lib/workspace/domain/page_stack/page_stack_bloc.dart delete mode 100644 app_flowy/lib/workspace/domain/page_stack/page_stack_bloc.freezed.dart create mode 100644 app_flowy/lib/workspace/presentation/home/navigation_list.dart delete mode 100644 app_flowy/packages/flowy_infra_ui/lib/style_widget/navigation_list.dart diff --git a/app_flowy/lib/workspace/domain/page_stack/page_stack.dart b/app_flowy/lib/workspace/domain/page_stack/page_stack.dart index 750fc7aa76..81c08086b5 100644 --- a/app_flowy/lib/workspace/domain/page_stack/page_stack.dart +++ b/app_flowy/lib/workspace/domain/page_stack/page_stack.dart @@ -1,57 +1,72 @@ -import 'package:app_flowy/workspace/domain/page_stack/page_stack_bloc.dart'; -import 'package:app_flowy/workspace/presentation/doc/doc_page.dart'; import 'package:equatable/equatable.dart'; import 'package:flowy_sdk/protobuf/flowy-workspace/view_create.pb.dart'; import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; +import 'package:app_flowy/workspace/presentation/doc/doc_page.dart'; import 'package:app_flowy/workspace/presentation/widgets/blank_page.dart'; import 'package:app_flowy/workspace/presentation/widgets/fading_index_stack.dart'; import 'package:app_flowy/workspace/presentation/widgets/prelude.dart'; -import 'package:flutter_bloc/flutter_bloc.dart'; abstract class HomeStackView extends Equatable { final ViewType type; final String title; - const HomeStackView({required this.type, required this.title}); + final String identifier; + const HomeStackView( + {required this.type, required this.title, required this.identifier}); +} + +class PageStackNotifier extends ChangeNotifier { + HomeStackView? innerView; + + PageStackNotifier({ + this.innerView, + }); + + set view(HomeStackView view) { + innerView = view; + notifyListeners(); + } + + HomeStackView get view { + return innerView ?? const AnnouncementStackView(); + } } // HomePageStack is initialized as singleton to controll the page stack. class HomePageStack { - final PageStackBloc _bloc = PageStackBloc(); + final PageStackNotifier _notifier = PageStackNotifier(); HomePageStack(); String title() { - return _bloc.state.stackView.title; + return _notifier.view.title; } void setStackView(HomeStackView? stackView) { - _bloc.add(PageStackEvent.setStackView( - stackView ?? const AnnouncementStackView())); + _notifier.view = stackView ?? const AnnouncementStackView(); } Widget stackTopBar() { - return BlocProvider( - create: (context) => _bloc, - child: BlocBuilder( - builder: (context, state) { - return HomeTopBar( - view: state.stackView, - ); - }, - ), + return MultiProvider( + providers: [ + ChangeNotifierProvider(create: (_) => _notifier), + ], + child: Consumer(builder: (ctx, PageStackNotifier notifier, child) { + return HomeTopBar(view: notifier.view); + }), ); } Widget stackWidget() { - return BlocProvider( - create: (context) => _bloc, - child: BlocBuilder( - builder: (context, state) { - return FadingIndexedStack( - index: pages.indexOf(state.stackView.type), - children: _buildStackWidget(state.stackView), - ); - }, - ), + return MultiProvider( + providers: [ + ChangeNotifierProvider(create: (_) => _notifier), + ], + child: Consumer(builder: (ctx, PageStackNotifier notifier, child) { + return FadingIndexedStack( + index: pages.indexOf(notifier.view.type), + children: _buildStackWidget(notifier.view), + ); + }), ); } } diff --git a/app_flowy/lib/workspace/domain/page_stack/page_stack_bloc.dart b/app_flowy/lib/workspace/domain/page_stack/page_stack_bloc.dart deleted file mode 100644 index c20dced4ca..0000000000 --- a/app_flowy/lib/workspace/domain/page_stack/page_stack_bloc.dart +++ /dev/null @@ -1,35 +0,0 @@ -import 'package:app_flowy/workspace/domain/page_stack/page_stack.dart'; -import 'package:app_flowy/workspace/presentation/widgets/blank_page.dart'; -import 'package:freezed_annotation/freezed_annotation.dart'; -import 'package:flutter_bloc/flutter_bloc.dart'; -part 'page_stack_bloc.freezed.dart'; - -class PageStackBloc extends Bloc { - PageStackBloc() : super(PageStackState.initial()); - - @override - Stream mapEventToState( - PageStackEvent event, - ) async* { - yield* event.map(setStackView: (NewPageContext value) async* { - yield state.copyWith(stackView: value.newStackView); - }); - } -} - -@freezed -abstract class PageStackEvent with _$PageStackEvent { - const factory PageStackEvent.setStackView(HomeStackView newStackView) = - NewPageContext; -} - -@freezed -abstract class PageStackState implements _$PageStackState { - const factory PageStackState({ - required HomeStackView stackView, - }) = _PageStackState; - - factory PageStackState.initial() => const PageStackState( - stackView: AnnouncementStackView(), - ); -} diff --git a/app_flowy/lib/workspace/domain/page_stack/page_stack_bloc.freezed.dart b/app_flowy/lib/workspace/domain/page_stack/page_stack_bloc.freezed.dart deleted file mode 100644 index 1ba34c8d62..0000000000 --- a/app_flowy/lib/workspace/domain/page_stack/page_stack_bloc.freezed.dart +++ /dev/null @@ -1,337 +0,0 @@ -// GENERATED CODE - DO NOT MODIFY BY HAND -// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target - -part of 'page_stack_bloc.dart'; - -// ************************************************************************** -// FreezedGenerator -// ************************************************************************** - -T _$identity(T value) => value; - -final _privateConstructorUsedError = UnsupportedError( - 'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more informations: https://github.com/rrousselGit/freezed#custom-getters-and-methods'); - -/// @nodoc -class _$PageStackEventTearOff { - const _$PageStackEventTearOff(); - - NewPageContext setStackView(HomeStackView newStackView) { - return NewPageContext( - newStackView, - ); - } -} - -/// @nodoc -const $PageStackEvent = _$PageStackEventTearOff(); - -/// @nodoc -mixin _$PageStackEvent { - HomeStackView get newStackView => throw _privateConstructorUsedError; - - @optionalTypeArgs - TResult when({ - required TResult Function(HomeStackView newStackView) setStackView, - }) => - throw _privateConstructorUsedError; - @optionalTypeArgs - TResult maybeWhen({ - TResult Function(HomeStackView newStackView)? setStackView, - required TResult orElse(), - }) => - throw _privateConstructorUsedError; - @optionalTypeArgs - TResult map({ - required TResult Function(NewPageContext value) setStackView, - }) => - throw _privateConstructorUsedError; - @optionalTypeArgs - TResult maybeMap({ - TResult Function(NewPageContext value)? setStackView, - required TResult orElse(), - }) => - throw _privateConstructorUsedError; - - @JsonKey(ignore: true) - $PageStackEventCopyWith get copyWith => - throw _privateConstructorUsedError; -} - -/// @nodoc -abstract class $PageStackEventCopyWith<$Res> { - factory $PageStackEventCopyWith( - PageStackEvent value, $Res Function(PageStackEvent) then) = - _$PageStackEventCopyWithImpl<$Res>; - $Res call({HomeStackView newStackView}); -} - -/// @nodoc -class _$PageStackEventCopyWithImpl<$Res> - implements $PageStackEventCopyWith<$Res> { - _$PageStackEventCopyWithImpl(this._value, this._then); - - final PageStackEvent _value; - // ignore: unused_field - final $Res Function(PageStackEvent) _then; - - @override - $Res call({ - Object? newStackView = freezed, - }) { - return _then(_value.copyWith( - newStackView: newStackView == freezed - ? _value.newStackView - : newStackView // ignore: cast_nullable_to_non_nullable - as HomeStackView, - )); - } -} - -/// @nodoc -abstract class $NewPageContextCopyWith<$Res> - implements $PageStackEventCopyWith<$Res> { - factory $NewPageContextCopyWith( - NewPageContext value, $Res Function(NewPageContext) then) = - _$NewPageContextCopyWithImpl<$Res>; - @override - $Res call({HomeStackView newStackView}); -} - -/// @nodoc -class _$NewPageContextCopyWithImpl<$Res> - extends _$PageStackEventCopyWithImpl<$Res> - implements $NewPageContextCopyWith<$Res> { - _$NewPageContextCopyWithImpl( - NewPageContext _value, $Res Function(NewPageContext) _then) - : super(_value, (v) => _then(v as NewPageContext)); - - @override - NewPageContext get _value => super._value as NewPageContext; - - @override - $Res call({ - Object? newStackView = freezed, - }) { - return _then(NewPageContext( - newStackView == freezed - ? _value.newStackView - : newStackView // ignore: cast_nullable_to_non_nullable - as HomeStackView, - )); - } -} - -/// @nodoc - -class _$NewPageContext implements NewPageContext { - const _$NewPageContext(this.newStackView); - - @override - final HomeStackView newStackView; - - @override - String toString() { - return 'PageStackEvent.setStackView(newStackView: $newStackView)'; - } - - @override - bool operator ==(dynamic other) { - return identical(this, other) || - (other is NewPageContext && - (identical(other.newStackView, newStackView) || - const DeepCollectionEquality() - .equals(other.newStackView, newStackView))); - } - - @override - int get hashCode => - runtimeType.hashCode ^ const DeepCollectionEquality().hash(newStackView); - - @JsonKey(ignore: true) - @override - $NewPageContextCopyWith get copyWith => - _$NewPageContextCopyWithImpl(this, _$identity); - - @override - @optionalTypeArgs - TResult when({ - required TResult Function(HomeStackView newStackView) setStackView, - }) { - return setStackView(newStackView); - } - - @override - @optionalTypeArgs - TResult maybeWhen({ - TResult Function(HomeStackView newStackView)? setStackView, - required TResult orElse(), - }) { - if (setStackView != null) { - return setStackView(newStackView); - } - return orElse(); - } - - @override - @optionalTypeArgs - TResult map({ - required TResult Function(NewPageContext value) setStackView, - }) { - return setStackView(this); - } - - @override - @optionalTypeArgs - TResult maybeMap({ - TResult Function(NewPageContext value)? setStackView, - required TResult orElse(), - }) { - if (setStackView != null) { - return setStackView(this); - } - return orElse(); - } -} - -abstract class NewPageContext implements PageStackEvent { - const factory NewPageContext(HomeStackView newStackView) = _$NewPageContext; - - @override - HomeStackView get newStackView => throw _privateConstructorUsedError; - @override - @JsonKey(ignore: true) - $NewPageContextCopyWith get copyWith => - throw _privateConstructorUsedError; -} - -/// @nodoc -class _$PageStackStateTearOff { - const _$PageStackStateTearOff(); - - _PageStackState call({required HomeStackView stackView}) { - return _PageStackState( - stackView: stackView, - ); - } -} - -/// @nodoc -const $PageStackState = _$PageStackStateTearOff(); - -/// @nodoc -mixin _$PageStackState { - HomeStackView get stackView => throw _privateConstructorUsedError; - - @JsonKey(ignore: true) - $PageStackStateCopyWith get copyWith => - throw _privateConstructorUsedError; -} - -/// @nodoc -abstract class $PageStackStateCopyWith<$Res> { - factory $PageStackStateCopyWith( - PageStackState value, $Res Function(PageStackState) then) = - _$PageStackStateCopyWithImpl<$Res>; - $Res call({HomeStackView stackView}); -} - -/// @nodoc -class _$PageStackStateCopyWithImpl<$Res> - implements $PageStackStateCopyWith<$Res> { - _$PageStackStateCopyWithImpl(this._value, this._then); - - final PageStackState _value; - // ignore: unused_field - final $Res Function(PageStackState) _then; - - @override - $Res call({ - Object? stackView = freezed, - }) { - return _then(_value.copyWith( - stackView: stackView == freezed - ? _value.stackView - : stackView // ignore: cast_nullable_to_non_nullable - as HomeStackView, - )); - } -} - -/// @nodoc -abstract class _$PageStackStateCopyWith<$Res> - implements $PageStackStateCopyWith<$Res> { - factory _$PageStackStateCopyWith( - _PageStackState value, $Res Function(_PageStackState) then) = - __$PageStackStateCopyWithImpl<$Res>; - @override - $Res call({HomeStackView stackView}); -} - -/// @nodoc -class __$PageStackStateCopyWithImpl<$Res> - extends _$PageStackStateCopyWithImpl<$Res> - implements _$PageStackStateCopyWith<$Res> { - __$PageStackStateCopyWithImpl( - _PageStackState _value, $Res Function(_PageStackState) _then) - : super(_value, (v) => _then(v as _PageStackState)); - - @override - _PageStackState get _value => super._value as _PageStackState; - - @override - $Res call({ - Object? stackView = freezed, - }) { - return _then(_PageStackState( - stackView: stackView == freezed - ? _value.stackView - : stackView // ignore: cast_nullable_to_non_nullable - as HomeStackView, - )); - } -} - -/// @nodoc - -class _$_PageStackState implements _PageStackState { - const _$_PageStackState({required this.stackView}); - - @override - final HomeStackView stackView; - - @override - String toString() { - return 'PageStackState(stackView: $stackView)'; - } - - @override - bool operator ==(dynamic other) { - return identical(this, other) || - (other is _PageStackState && - (identical(other.stackView, stackView) || - const DeepCollectionEquality() - .equals(other.stackView, stackView))); - } - - @override - int get hashCode => - runtimeType.hashCode ^ const DeepCollectionEquality().hash(stackView); - - @JsonKey(ignore: true) - @override - _$PageStackStateCopyWith<_PageStackState> get copyWith => - __$PageStackStateCopyWithImpl<_PageStackState>(this, _$identity); -} - -abstract class _PageStackState implements PageStackState { - const factory _PageStackState({required HomeStackView stackView}) = - _$_PageStackState; - - @override - HomeStackView get stackView => throw _privateConstructorUsedError; - @override - @JsonKey(ignore: true) - _$PageStackStateCopyWith<_PageStackState> get copyWith => - throw _privateConstructorUsedError; -} diff --git a/app_flowy/lib/workspace/presentation/doc/doc_page.dart b/app_flowy/lib/workspace/presentation/doc/doc_page.dart index bf43ca2f24..08c3148a05 100644 --- a/app_flowy/lib/workspace/presentation/doc/doc_page.dart +++ b/app_flowy/lib/workspace/presentation/doc/doc_page.dart @@ -60,6 +60,7 @@ class DocPageStackView extends HomeStackView { : super( type: view.viewType, title: view.name, + identifier: view.id, ); @override diff --git a/app_flowy/lib/workspace/presentation/home/navigation_list.dart b/app_flowy/lib/workspace/presentation/home/navigation_list.dart new file mode 100644 index 0000000000..9b96ec02f4 --- /dev/null +++ b/app_flowy/lib/workspace/presentation/home/navigation_list.dart @@ -0,0 +1,137 @@ +import 'package:app_flowy/workspace/domain/page_stack/page_stack.dart'; +import 'package:app_flowy/workspace/presentation/widgets/home_top_bar.dart'; +import 'package:flowy_infra_ui/style_widget/text.dart'; +import 'package:flowy_infra_ui/style_widget/text_button.dart'; +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; +import 'package:styled_widget/styled_widget.dart'; + +typedef NaviAction = void Function(); + +abstract class NaviItem { + String get identifier; + String get title; + NaviAction get action; +} + +class NavigationNotifier extends ChangeNotifier { + PageStackNotifier pageStackNotifier; + NavigationNotifier(this.pageStackNotifier); + + void update(PageStackNotifier notifier) { + pageStackNotifier = notifier; + notifyListeners(); + } + + List get naviItems { + List items = [ + ViewNaviItemImpl(pageStackNotifier.view), + ViewNaviItemImpl(pageStackNotifier.view), + ViewNaviItemImpl(pageStackNotifier.view), + ViewNaviItemImpl(pageStackNotifier.view), + ViewNaviItemImpl(pageStackNotifier.view), + ViewNaviItemImpl(pageStackNotifier.view) + ]; + return items; + } +} + +class StyledNavigationList extends StatelessWidget { + const StyledNavigationList({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return ChangeNotifierProxyProvider( + create: (_) => NavigationNotifier( + Provider.of( + context, + listen: false, + ), + ), + update: (_, notifier, controller) => controller!..update(notifier), + child: Consumer(builder: (ctx, NavigationNotifier notifier, child) { + return Row(children: _renderChildren(notifier.naviItems)); + }), + ); + } + + List _renderChildren(List items) { + if (items.isEmpty) { + return []; + } + + List newItems = _filter(items); + Widget last = NaviItemWidget(newItems.removeLast()); + + List widgets = List.empty(growable: true); + widgets.addAll(newItems + .map((item) => NaviItemDivider(child: NaviItemWidget(item))) + .toList()); + widgets.add(last); + + return widgets; + } + + List _filter(List items) { + final length = items.length; + if (length > 4) { + final first = items[0]; + final ellipsisItems = items.getRange(1, length - 2).toList(); + final last = items.getRange(length - 2, length).toList(); + return [ + first, + EllipsisNaviItem(items: ellipsisItems), + ...last, + ]; + } else { + return items; + } + } +} + +class NaviItemWidget extends StatelessWidget { + final NaviItem item; + const NaviItemWidget(this.item, {Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return SizedBox( + height: 30, + child: FlowyTextButton( + item.title, + fontSize: 14, + onPressed: () { + debugPrint('show app document'); + }, + ), + ); + } +} + +class NaviItemDivider extends StatelessWidget { + final Widget child; + const NaviItemDivider({Key? key, required this.child}) : super(key: key); + + @override + Widget build(BuildContext context) { + return Row( + children: [child, const Text('/').padding(horizontal: 2)], + ); + } +} + +class EllipsisNaviItem extends NaviItem { + final List items; + EllipsisNaviItem({ + required this.items, + }); + + @override + NaviAction get action => throw UnimplementedError(); + + @override + String get identifier => "Ellipsis"; + + @override + String get title => "..."; +} diff --git a/app_flowy/lib/workspace/presentation/widgets/blank_page.dart b/app_flowy/lib/workspace/presentation/widgets/blank_page.dart index 159fa8d2ce..d282792286 100644 --- a/app_flowy/lib/workspace/presentation/widgets/blank_page.dart +++ b/app_flowy/lib/workspace/presentation/widgets/blank_page.dart @@ -3,7 +3,7 @@ import 'package:flowy_sdk/protobuf/flowy-workspace/view_create.pb.dart'; import 'package:flutter/material.dart'; class AnnouncementStackView extends HomeStackView { - const AnnouncementStackView() : super(type: ViewType.Blank, title: 'Blank'); + const AnnouncementStackView() : super(type: ViewType.Blank, title: 'Blank', identifier: "Announcement"); @override List get props => []; diff --git a/app_flowy/lib/workspace/presentation/widgets/home_top_bar.dart b/app_flowy/lib/workspace/presentation/widgets/home_top_bar.dart index 09c4a80791..9ef7773c7c 100644 --- a/app_flowy/lib/workspace/presentation/widgets/home_top_bar.dart +++ b/app_flowy/lib/workspace/presentation/widgets/home_top_bar.dart @@ -1,12 +1,14 @@ +import 'package:app_flowy/startup/startup.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/navigation_list.dart'; import 'package:flowy_infra_ui/widget/rounded_button.dart'; import 'package:flowy_infra_ui/widget/spacing.dart'; +import 'package:flowy_sdk/protobuf/flowy-workspace/view_create.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-workspace/view_create.pbenum.dart'; import 'package:flutter/material.dart'; import 'package:flowy_infra_ui/style_widget/icon_button.dart'; -// import 'package:flowy_infra_ui/style_widget/styled_navigation_list.dart'; import 'package:flowy_infra_ui/style_widget/extension.dart'; import 'package:flowy_infra_ui/style_widget/text.dart'; @@ -21,13 +23,15 @@ class HomeTopBar extends StatelessWidget { child: Row( crossAxisAlignment: CrossAxisAlignment.center, children: [ - HomeTitle(title: view.title, type: view.type), + _renderNavigationList(view), const Spacer(), _renderShareButton(), _renderMoreButton(), ], ) - .padding(horizontal: HomeInsets.topBarTitlePadding) + .padding( + horizontal: HomeInsets.topBarTitlePadding, + ) .bottomBorder(color: Colors.grey.shade300), ); } @@ -55,8 +59,8 @@ class HomeTopBar extends StatelessWidget { ); } - Widget _renderNavigationList() { - return Container(); + Widget _renderNavigationList(HomeStackView view) { + return const StyledNavigationList(); } } @@ -87,3 +91,18 @@ class HomeTitle extends StatelessWidget { ); } } + +class ViewNaviItemImpl extends NaviItem { + final HomeStackView view; + + ViewNaviItemImpl(this.view); + + @override + NaviAction get action => () => getIt().setStackView(view); + + @override + String get identifier => view.identifier; + + @override + String get title => view.title; +} diff --git a/app_flowy/packages/flowy_infra_ui/lib/style_widget/navigation_list.dart b/app_flowy/packages/flowy_infra_ui/lib/style_widget/navigation_list.dart deleted file mode 100644 index c6a24d063d..0000000000 --- a/app_flowy/packages/flowy_infra_ui/lib/style_widget/navigation_list.dart +++ /dev/null @@ -1,104 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:provider/provider.dart'; - -typedef NaviAction = void Function(String); - -abstract class NaviItem { - String get identifier; - NaviAction get action; -} - -class StyledNavigationController extends ChangeNotifier { - List naviItems; - StyledNavigationController({this.naviItems = const []}); -} - -class StyledNavigationList extends StatelessWidget { - const StyledNavigationList({Key? key}) : super(key: key); - - @override - Widget build(BuildContext context) { - return MultiProvider( - providers: [ - ChangeNotifierProvider(create: (_) => StyledNavigationController()), - ], - child: Consumer(builder: (ctx, StyledNavigationController ctrl, child) { - return Row( - children: _buildNaviItemWidget(ctrl.naviItems), - ); - }), - ); - } - - List _buildNaviItemWidget(List items) { - if (items.isEmpty) { - return []; - } - - List newItems = _filter(items); - Widget last = NaviItemWidget(newItems.removeLast()); - - List widgets = newItems - .map((item) => NaviItemDivider(child: NaviItemWidget(item))) - .toList(); - - widgets.add(last); - - return widgets; - } - - List _filter(List items) { - final length = items.length; - if (length > 4) { - final first = items[0]; - final ellipsisItems = items.getRange(1, length - 2).toList(); - final last = items.getRange(length - 2, length).toList(); - return [ - first, - EllipsisNaviItem(items: ellipsisItems), - ...last, - ]; - } else { - return items; - } - } -} - -class NaviItemWidget extends StatelessWidget { - final NaviItem item; - const NaviItemWidget(this.item, {Key? key}) : super(key: key); - - @override - Widget build(BuildContext context) { - return Container( - child: null, - ); - } -} - -class NaviItemDivider extends StatelessWidget { - final Widget child; - const NaviItemDivider({Key? key, required this.child}) : super(key: key); - - @override - Widget build(BuildContext context) { - return Row( - children: [child, const Text('/')], - ); - } -} - -class EllipsisNaviItem extends NaviItem { - final List items; - EllipsisNaviItem({ - required this.items, - }); - - @override - // TODO: implement action - NaviAction get action => throw UnimplementedError(); - - @override - // TODO: implement identifier - String get identifier => throw UnimplementedError(); -}