mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
[flutter]: config menu trash ui
This commit is contained in:
parent
50172e3fd4
commit
0d5a16e447
@ -1,18 +1,15 @@
|
|||||||
import 'package:equatable/equatable.dart';
|
import 'package:equatable/equatable.dart';
|
||||||
import 'package:flowy_sdk/protobuf/flowy-workspace/view_create.pb.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
import 'package:app_flowy/startup/startup.dart';
|
import 'package:app_flowy/startup/startup.dart';
|
||||||
import 'package:app_flowy/workspace/presentation/stack_page/blank/blank_page.dart';
|
import 'package:app_flowy/workspace/presentation/stack_page/blank/blank_page.dart';
|
||||||
import 'package:app_flowy/workspace/presentation/stack_page/doc/doc_stack_page.dart';
|
|
||||||
import 'package:app_flowy/workspace/presentation/stack_page/home_stack.dart';
|
import 'package:app_flowy/workspace/presentation/stack_page/home_stack.dart';
|
||||||
import 'package:app_flowy/workspace/presentation/widgets/prelude.dart';
|
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 {
|
||||||
String get title;
|
Widget get titleWidget;
|
||||||
String get identifier;
|
String get identifier;
|
||||||
|
|
||||||
NavigationCallback get action => (id) {
|
NavigationCallback get action => (id) {
|
||||||
@ -20,33 +17,28 @@ abstract class NavigationItem {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum HomeStackType {
|
||||||
|
blank,
|
||||||
|
doc,
|
||||||
|
trash,
|
||||||
|
}
|
||||||
|
|
||||||
|
List<HomeStackType> pages = HomeStackType.values.toList();
|
||||||
|
|
||||||
abstract class HomeStackContext extends Equatable with NavigationItem {
|
abstract class HomeStackContext extends Equatable with NavigationItem {
|
||||||
List<NavigationItem> get navigationItems;
|
List<NavigationItem> get navigationItems;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get title;
|
Widget get titleWidget;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get identifier;
|
String get identifier;
|
||||||
|
|
||||||
ViewType get type;
|
HomeStackType get type;
|
||||||
|
|
||||||
Widget render();
|
Widget render();
|
||||||
}
|
}
|
||||||
|
|
||||||
extension ViewStackContext on View {
|
|
||||||
HomeStackContext intoStackContext() {
|
|
||||||
switch (viewType) {
|
|
||||||
case ViewType.Blank:
|
|
||||||
return BlankStackContext();
|
|
||||||
case ViewType.Doc:
|
|
||||||
return DocStackContext(view: this);
|
|
||||||
default:
|
|
||||||
return BlankStackContext();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class HomeStackNotifier extends ChangeNotifier {
|
class HomeStackNotifier extends ChangeNotifier {
|
||||||
HomeStackContext inner;
|
HomeStackContext inner;
|
||||||
HomeStackNotifier({HomeStackContext? context}) : inner = context ?? BlankStackContext();
|
HomeStackNotifier({HomeStackContext? context}) : inner = context ?? BlankStackContext();
|
||||||
@ -64,8 +56,8 @@ class HomeStackManager {
|
|||||||
final HomeStackNotifier _notifier = HomeStackNotifier();
|
final HomeStackNotifier _notifier = HomeStackNotifier();
|
||||||
HomeStackManager();
|
HomeStackManager();
|
||||||
|
|
||||||
String title() {
|
Widget title() {
|
||||||
return _notifier.context.title;
|
return _notifier.context.titleWidget;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setStack(HomeStackContext context) {
|
void setStack(HomeStackContext context) {
|
||||||
@ -93,7 +85,7 @@ class HomeStackManager {
|
|||||||
child: Consumer(builder: (ctx, HomeStackNotifier notifier, child) {
|
child: Consumer(builder: (ctx, HomeStackNotifier notifier, child) {
|
||||||
return FadingIndexedStack(
|
return FadingIndexedStack(
|
||||||
index: pages.indexOf(notifier.context.type),
|
index: pages.indexOf(notifier.context.type),
|
||||||
children: ViewType.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.render();
|
||||||
} else {
|
} else {
|
||||||
@ -105,5 +97,3 @@ class HomeStackManager {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
List<ViewType> pages = ViewType.values.toList();
|
|
||||||
|
30
app_flowy/lib/workspace/domain/view_ext.dart
Normal file
30
app_flowy/lib/workspace/domain/view_ext.dart
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
import 'package:app_flowy/workspace/domain/page_stack/page_stack.dart';
|
||||||
|
import 'package:app_flowy/workspace/presentation/stack_page/blank/blank_page.dart';
|
||||||
|
import 'package:app_flowy/workspace/presentation/stack_page/doc/doc_stack_page.dart';
|
||||||
|
import 'package:flowy_sdk/protobuf/flowy-workspace/view_create.pb.dart';
|
||||||
|
|
||||||
|
extension ToHomeStackContext on View {
|
||||||
|
HomeStackContext stackContext() {
|
||||||
|
switch (viewType) {
|
||||||
|
case ViewType.Blank:
|
||||||
|
return BlankStackContext();
|
||||||
|
case ViewType.Doc:
|
||||||
|
return DocStackContext(view: this);
|
||||||
|
default:
|
||||||
|
return BlankStackContext();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension ToHomeStackType on View {
|
||||||
|
HomeStackType stackType() {
|
||||||
|
switch (viewType) {
|
||||||
|
case ViewType.Blank:
|
||||||
|
return HomeStackType.blank;
|
||||||
|
case ViewType.Doc:
|
||||||
|
return HomeStackType.doc;
|
||||||
|
default:
|
||||||
|
return HomeStackType.blank;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,4 +1,5 @@
|
|||||||
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_button.dart';
|
import 'package:flowy_infra_ui/style_widget/text_button.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
@ -94,14 +95,12 @@ class IconNaviItemWidget extends StatelessWidget {
|
|||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return SizedBox(
|
return SizedBox(
|
||||||
height: 24,
|
height: 24,
|
||||||
child: FlowyTextButton(
|
child: InkWell(
|
||||||
item.title,
|
child: item.titleWidget,
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 2),
|
onTap: () {
|
||||||
fontSize: 12,
|
|
||||||
onPressed: () {
|
|
||||||
debugPrint('show app document');
|
debugPrint('show app document');
|
||||||
},
|
},
|
||||||
),
|
).padding(horizontal: 8, vertical: 2),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -114,14 +113,12 @@ class NaviItemWidget extends StatelessWidget {
|
|||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return SizedBox(
|
return SizedBox(
|
||||||
height: 24,
|
height: 24,
|
||||||
child: FlowyTextButton(
|
child: InkWell(
|
||||||
item.title,
|
child: item.titleWidget,
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 2),
|
onTap: () {
|
||||||
fontSize: 12,
|
|
||||||
onPressed: () {
|
|
||||||
debugPrint('show app document');
|
debugPrint('show app document');
|
||||||
},
|
},
|
||||||
),
|
).padding(horizontal: 8, vertical: 2),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -145,7 +142,7 @@ class EllipsisNaviItem extends NavigationItem {
|
|||||||
});
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get title => "...";
|
Widget get titleWidget => const FlowyText.medium('...');
|
||||||
|
|
||||||
@override
|
@override
|
||||||
NavigationCallback get action => (id) {};
|
NavigationCallback get action => (id) {};
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
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_sdk/protobuf/flowy-workspace/view_create.pb.dart';
|
import 'package:flowy_sdk/protobuf/flowy-workspace/view_create.pb.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
@ -10,10 +11,10 @@ class BlankStackContext extends HomeStackContext {
|
|||||||
List<Object?> get props => ["1"];
|
List<Object?> get props => ["1"];
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get title => "Blank page";
|
Widget get titleWidget => const FlowyText.medium('Blank page', fontSize: 12);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
ViewType get type => ViewType.Blank;
|
HomeStackType get type => HomeStackType.blank;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget render() {
|
Widget render() {
|
||||||
@ -28,10 +29,10 @@ class BlankStackPage extends StatefulWidget {
|
|||||||
const BlankStackPage({Key? key}) : super(key: key);
|
const BlankStackPage({Key? key}) : super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<BlankStackPage> createState() => _AnnouncementPage();
|
State<BlankStackPage> createState() => _BlankStackPageState();
|
||||||
}
|
}
|
||||||
|
|
||||||
class _AnnouncementPage extends State<BlankStackPage> {
|
class _BlankStackPageState extends State<BlankStackPage> {
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return SizedBox.expand(
|
return SizedBox.expand(
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
import 'package:app_flowy/startup/startup.dart';
|
import 'package:app_flowy/startup/startup.dart';
|
||||||
import 'package:app_flowy/workspace/application/doc/doc_bloc.dart';
|
import 'package:app_flowy/workspace/application/doc/doc_bloc.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:flowy_infra_ui/style_widget/text.dart';
|
||||||
import 'package:flowy_log/flowy_log.dart';
|
import 'package:flowy_log/flowy_log.dart';
|
||||||
import 'package:flowy_infra_ui/widget/error_page.dart';
|
import 'package:flowy_infra_ui/widget/error_page.dart';
|
||||||
import 'package:flowy_sdk/protobuf/flowy-workspace/view_create.pb.dart';
|
import 'package:flowy_sdk/protobuf/flowy-workspace/view_create.pb.dart';
|
||||||
@ -15,11 +17,11 @@ class DocStackContext extends HomeStackContext {
|
|||||||
DocStackContext({required View view, Key? key}) : _view = view;
|
DocStackContext({required View view, Key? key}) : _view = view;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get title => _view.name;
|
Widget get titleWidget => FlowyText.medium(_view.name, fontSize: 12);
|
||||||
@override
|
@override
|
||||||
String get identifier => _view.id;
|
String get identifier => _view.id;
|
||||||
@override
|
@override
|
||||||
ViewType get type => _view.viewType;
|
HomeStackType get type => _view.stackType();
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<Object?> get props => [_view.id];
|
List<Object?> get props => [_view.id];
|
||||||
|
@ -0,0 +1,47 @@
|
|||||||
|
import 'package:app_flowy/workspace/domain/page_stack/page_stack.dart';
|
||||||
|
import 'package:flowy_infra_ui/style_widget/text.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
class TrashStackContext extends HomeStackContext {
|
||||||
|
@override
|
||||||
|
String get identifier => "TrashStackContext";
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object?> get props => ["TrashStackContext"];
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget get titleWidget => const FlowyText.medium('Trash', fontSize: 12);
|
||||||
|
|
||||||
|
@override
|
||||||
|
HomeStackType get type => HomeStackType.trash;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget render() {
|
||||||
|
return const TrashStackPage();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<NavigationItem> get navigationItems => [this];
|
||||||
|
}
|
||||||
|
|
||||||
|
class TrashStackPage extends StatefulWidget {
|
||||||
|
const TrashStackPage({Key? key}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<TrashStackPage> createState() => _TrashStackPageState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _TrashStackPageState extends State<TrashStackPage> {
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return SizedBox.expand(
|
||||||
|
child: Container(
|
||||||
|
color: Colors.white,
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.all(10),
|
||||||
|
child: Container(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -18,6 +18,7 @@ import 'package:app_flowy/workspace/presentation/widgets/menu/widget/menu_user.d
|
|||||||
|
|
||||||
import 'widget/app/menu_app.dart';
|
import 'widget/app/menu_app.dart';
|
||||||
import 'widget/app/create_button.dart';
|
import 'widget/app/create_button.dart';
|
||||||
|
import 'widget/menu_trash.dart';
|
||||||
|
|
||||||
// [[diagram: HomeMenu's widget structure]]
|
// [[diagram: HomeMenu's widget structure]]
|
||||||
// get user profile or modify user
|
// get user profile or modify user
|
||||||
@ -101,6 +102,9 @@ class HomeMenu extends StatelessWidget {
|
|||||||
],
|
],
|
||||||
).padding(horizontal: Insets.l),
|
).padding(horizontal: Insets.l),
|
||||||
),
|
),
|
||||||
|
const VSpace(20),
|
||||||
|
_renderTrash(context).padding(horizontal: Insets.l),
|
||||||
|
const VSpace(20),
|
||||||
_renderNewAppButton(context),
|
_renderNewAppButton(context),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
@ -112,10 +116,10 @@ class HomeMenu extends StatelessWidget {
|
|||||||
builder: (context, state) {
|
builder: (context, state) {
|
||||||
return state.map(
|
return state.map(
|
||||||
initial: (_) => MenuList(
|
initial: (_) => MenuList(
|
||||||
menuItems: menuItemsWithApps(context.read<MenuBloc>().state.apps),
|
menuItems: buildMenuItems(context.read<MenuBloc>().state.apps),
|
||||||
),
|
),
|
||||||
loadApps: (s) => MenuList(
|
loadApps: (s) => MenuList(
|
||||||
menuItems: menuItemsWithApps(some(s.apps)),
|
menuItems: buildMenuItems(some(s.apps)),
|
||||||
),
|
),
|
||||||
loadFail: (s) => FlowyErrorPage(s.error.toString()),
|
loadFail: (s) => FlowyErrorPage(s.error.toString()),
|
||||||
);
|
);
|
||||||
@ -123,6 +127,10 @@ class HomeMenu extends StatelessWidget {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Widget _renderTrash(BuildContext context) {
|
||||||
|
return const MenuTrash();
|
||||||
|
}
|
||||||
|
|
||||||
Widget _renderNewAppButton(BuildContext context) {
|
Widget _renderNewAppButton(BuildContext context) {
|
||||||
return NewAppButton(
|
return NewAppButton(
|
||||||
press: (appName) => context.read<MenuBloc>().add(MenuEvent.createApp(appName, desc: "")),
|
press: (appName) => context.read<MenuBloc>().add(MenuEvent.createApp(appName, desc: "")),
|
||||||
@ -133,31 +141,14 @@ class HomeMenu extends StatelessWidget {
|
|||||||
return const MenuTopBar();
|
return const MenuTopBar();
|
||||||
}
|
}
|
||||||
|
|
||||||
List<MenuItem> menuItemsWithApps(Option<List<App>> someApps) {
|
List<MenuItem> buildMenuItems(Option<List<App>> apps) {
|
||||||
return MenuItemBuilder().withUser(user).withApps(someApps).build();
|
List<MenuItem> items = [];
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class MenuItemBuilder {
|
|
||||||
List<MenuItem> items = [];
|
|
||||||
|
|
||||||
MenuItemBuilder();
|
|
||||||
|
|
||||||
MenuItemBuilder withUser(UserProfile user) {
|
|
||||||
items.add(MenuUser(user));
|
items.add(MenuUser(user));
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
MenuItemBuilder withApps(Option<List<App>> someApps) {
|
List<MenuItem> appWidgets =
|
||||||
List<MenuItem> appWidgets = someApps.foldRight(
|
apps.foldRight([], (apps, _) => apps.map((app) => MenuApp(MenuAppContext(app))).toList());
|
||||||
[],
|
|
||||||
(apps, _) => apps.map((app) => MenuApp(MenuAppContext(app))).toList(),
|
|
||||||
);
|
|
||||||
items.addAll(appWidgets);
|
items.addAll(appWidgets);
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
List<MenuItem> build() {
|
|
||||||
return items;
|
return items;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import 'package:app_flowy/startup/startup.dart';
|
import 'package:app_flowy/startup/startup.dart';
|
||||||
import 'package:app_flowy/workspace/application/view/view_bloc.dart';
|
import 'package:app_flowy/workspace/application/view/view_bloc.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:dartz/dartz.dart' as dartz;
|
import 'package:dartz/dartz.dart' as dartz;
|
||||||
import 'package:flowy_infra/image.dart';
|
import 'package:flowy_infra/image.dart';
|
||||||
import 'package:flowy_infra/theme.dart';
|
import 'package:flowy_infra/theme.dart';
|
||||||
@ -44,7 +45,7 @@ class ViewSectionItem extends StatelessWidget {
|
|||||||
return InkWell(
|
return InkWell(
|
||||||
onTap: () {
|
onTap: () {
|
||||||
onSelected(context.read<ViewBloc>().state.view);
|
onSelected(context.read<ViewBloc>().state.view);
|
||||||
getIt<HomeStackManager>().setStack(state.view.intoStackContext());
|
getIt<HomeStackManager>().setStack(state.view.stackContext());
|
||||||
},
|
},
|
||||||
child: FlowyHover(
|
child: FlowyHover(
|
||||||
config: HoverDisplayConfig(hoverColor: theme.bg3),
|
config: HoverDisplayConfig(hoverColor: theme.bg3),
|
||||||
|
@ -0,0 +1,33 @@
|
|||||||
|
import 'package:app_flowy/startup/startup.dart';
|
||||||
|
import 'package:app_flowy/workspace/domain/page_stack/page_stack.dart';
|
||||||
|
import 'package:app_flowy/workspace/presentation/stack_page/trash_page.dart';
|
||||||
|
import 'package:flowy_infra/image.dart';
|
||||||
|
import 'package:flowy_infra_ui/style_widget/text.dart';
|
||||||
|
import 'package:flowy_infra_ui/widget/spacing.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter/widgets.dart';
|
||||||
|
|
||||||
|
class MenuTrash extends StatelessWidget {
|
||||||
|
const MenuTrash({Key? key}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return SizedBox(
|
||||||
|
height: 26,
|
||||||
|
child: InkWell(
|
||||||
|
onTap: () {
|
||||||
|
getIt<HomeStackManager>().setStack(TrashStackContext());
|
||||||
|
},
|
||||||
|
child: _render(context),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _render(BuildContext context) {
|
||||||
|
return Row(children: [
|
||||||
|
SizedBox(width: 16, height: 16, child: svg("home/trash")),
|
||||||
|
const HSpace(6),
|
||||||
|
const FlowyText.medium('Trash', fontSize: 12),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
@ -11,6 +11,8 @@ import 'package:flowy_infra_ui/style_widget/icon_button.dart';
|
|||||||
class MenuUser extends MenuItem {
|
class MenuUser extends MenuItem {
|
||||||
final UserProfile user;
|
final UserProfile user;
|
||||||
MenuUser(this.user, {Key? key}) : super(key: ValueKey(user.id));
|
MenuUser(this.user, {Key? key}) : super(key: ValueKey(user.id));
|
||||||
|
@override
|
||||||
|
MenuItemType get type => MenuItemType.userProfile;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
@ -60,7 +62,4 @@ class MenuUser extends MenuItem {
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
|
||||||
MenuItemType get type => MenuItemType.userProfile;
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user