mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
[flutter]: config editor navigation items
This commit is contained in:
parent
fb1733e188
commit
ae82e052f2
@ -1,16 +1,36 @@
|
||||
import 'package:app_flowy/workspace/presentation/stack_page/doc/doc_stack_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/startup/startup.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/fading_index_stack.dart';
|
||||
import 'package:app_flowy/workspace/presentation/widgets/prelude.dart';
|
||||
|
||||
abstract class HomeStackContext extends Equatable {
|
||||
typedef NavigationCallback = void Function(String id);
|
||||
|
||||
abstract class NavigationItem {
|
||||
String get title;
|
||||
String get identifier;
|
||||
|
||||
NavigationCallback get action => (id) {
|
||||
getIt<HomeStack>().setStackWithId(id);
|
||||
};
|
||||
}
|
||||
|
||||
abstract class HomeStackContext extends Equatable with NavigationItem {
|
||||
List<NavigationItem> get navigationItems;
|
||||
|
||||
@override
|
||||
String get title;
|
||||
|
||||
@override
|
||||
String get identifier;
|
||||
|
||||
ViewType get type;
|
||||
|
||||
Widget render();
|
||||
}
|
||||
|
||||
@ -27,10 +47,7 @@ HomeStackContext stackCtxFromView(View view) {
|
||||
|
||||
class HomeStackNotifier extends ChangeNotifier {
|
||||
HomeStackContext inner;
|
||||
|
||||
HomeStackNotifier({
|
||||
HomeStackContext? context,
|
||||
}) : inner = context ?? DefaultHomeStackContext();
|
||||
HomeStackNotifier({HomeStackContext? context}) : inner = context ?? DefaultHomeStackContext();
|
||||
|
||||
set context(HomeStackContext context) {
|
||||
inner = context;
|
||||
@ -40,7 +57,7 @@ class HomeStackNotifier extends ChangeNotifier {
|
||||
HomeStackContext get context => inner;
|
||||
}
|
||||
|
||||
// HomePageStack is initialized as singleton to controll the page stack.
|
||||
// HomeStack is initialized as singleton to controll the page stack.
|
||||
class HomeStack {
|
||||
final HomeStackNotifier _notifier = HomeStackNotifier();
|
||||
HomeStack();
|
||||
@ -53,6 +70,8 @@ class HomeStack {
|
||||
_notifier.context = context;
|
||||
}
|
||||
|
||||
void setStackWithId(String id) {}
|
||||
|
||||
Widget stackTopBar() {
|
||||
return MultiProvider(
|
||||
providers: [
|
||||
|
@ -1,5 +1,4 @@
|
||||
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_button.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
@ -7,34 +6,38 @@ 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 with ChangeNotifier {
|
||||
HomeStackNotifier pageStackNotifier;
|
||||
NavigationNotifier(this.pageStackNotifier);
|
||||
HomeStackNotifier homeStackNotifier;
|
||||
NavigationNotifier(this.homeStackNotifier);
|
||||
|
||||
void update(HomeStackNotifier notifier) {
|
||||
pageStackNotifier = notifier;
|
||||
homeStackNotifier = notifier;
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
List<NaviItem> get naviItems {
|
||||
List<NaviItem> items = [
|
||||
ViewNaviItemImpl(pageStackNotifier.context),
|
||||
// ViewNaviItemImpl(pageStackNotifier.view),
|
||||
// ViewNaviItemImpl(pageStackNotifier.view),
|
||||
// ViewNaviItemImpl(pageStackNotifier.view),
|
||||
// ViewNaviItemImpl(pageStackNotifier.view),
|
||||
// ViewNaviItemImpl(pageStackNotifier.view)
|
||||
];
|
||||
return items;
|
||||
}
|
||||
List<NavigationItem> get naviItems => homeStackNotifier.context.navigationItems;
|
||||
}
|
||||
|
||||
// [[Navigation]]
|
||||
// ┌───────────────────────┐
|
||||
// 2.notify listeners ┌──────│DefaultHomeStackContext│
|
||||
// ┌────────────────┐ ┌───────────┐ ┌────────────────┐ │ └───────────────────────┘
|
||||
// │HomeStackNotifie│◀──────────│ HomeStack │◀──│HomeStackContext│◀─ impl
|
||||
// └────────────────┘ └───────────┘ └────────────────┘ │ ┌───────────────────┐
|
||||
// │ ▲ └───────│ DocStackContext │
|
||||
// │ │ └───────────────────┘
|
||||
// 3.notify change 1.set context
|
||||
// │ │
|
||||
// ▼ │
|
||||
// ┌───────────────────┐ ┌──────────────────┐
|
||||
// │NavigationNotifier │ │ ViewSectionItem │
|
||||
// └───────────────────┘ └──────────────────┘
|
||||
// │
|
||||
// │
|
||||
// ▼
|
||||
// ┌─────────────────┐
|
||||
// │ FlowyNavigation │ 4.render navigation items
|
||||
// └─────────────────┘
|
||||
class FlowyNavigation extends StatelessWidget {
|
||||
const FlowyNavigation({Key? key}) : super(key: key);
|
||||
|
||||
@ -42,10 +45,7 @@ class FlowyNavigation extends StatelessWidget {
|
||||
Widget build(BuildContext context) {
|
||||
return ChangeNotifierProxyProvider<HomeStackNotifier, NavigationNotifier>(
|
||||
create: (_) => NavigationNotifier(
|
||||
Provider.of<HomeStackNotifier>(
|
||||
context,
|
||||
listen: false,
|
||||
),
|
||||
Provider.of<HomeStackNotifier>(context, listen: false),
|
||||
),
|
||||
update: (_, notifier, controller) => controller!..update(notifier),
|
||||
child: Consumer(builder: (ctx, NavigationNotifier notifier, child) {
|
||||
@ -54,12 +54,12 @@ class FlowyNavigation extends StatelessWidget {
|
||||
);
|
||||
}
|
||||
|
||||
List<Widget> _renderChildren(List<NaviItem> items) {
|
||||
List<Widget> _renderChildren(List<NavigationItem> items) {
|
||||
if (items.isEmpty) {
|
||||
return [];
|
||||
}
|
||||
|
||||
List<NaviItem> newItems = _filter(items);
|
||||
List<NavigationItem> newItems = _filter(items);
|
||||
Widget last = NaviItemWidget(newItems.removeLast());
|
||||
|
||||
List<Widget> widgets = List.empty(growable: true);
|
||||
@ -69,7 +69,7 @@ class FlowyNavigation extends StatelessWidget {
|
||||
return widgets;
|
||||
}
|
||||
|
||||
List<NaviItem> _filter(List<NaviItem> items) {
|
||||
List<NavigationItem> _filter(List<NavigationItem> items) {
|
||||
final length = items.length;
|
||||
if (length > 4) {
|
||||
final first = items[0];
|
||||
@ -87,16 +87,17 @@ class FlowyNavigation extends StatelessWidget {
|
||||
}
|
||||
|
||||
class NaviItemWidget extends StatelessWidget {
|
||||
final NaviItem item;
|
||||
final NavigationItem item;
|
||||
const NaviItemWidget(this.item, {Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return SizedBox(
|
||||
height: 30,
|
||||
height: 24,
|
||||
child: FlowyTextButton(
|
||||
item.title,
|
||||
fontSize: 14,
|
||||
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 2),
|
||||
fontSize: 12,
|
||||
onPressed: () {
|
||||
debugPrint('show app document');
|
||||
},
|
||||
@ -117,18 +118,18 @@ class NaviItemDivider extends StatelessWidget {
|
||||
}
|
||||
}
|
||||
|
||||
class EllipsisNaviItem extends NaviItem {
|
||||
final List<NaviItem> items;
|
||||
class EllipsisNaviItem extends NavigationItem {
|
||||
final List<NavigationItem> items;
|
||||
EllipsisNaviItem({
|
||||
required this.items,
|
||||
});
|
||||
|
||||
@override
|
||||
NaviAction get action => throw UnimplementedError();
|
||||
String get title => "...";
|
||||
|
||||
@override
|
||||
NavigationCallback get action => (id) {};
|
||||
|
||||
@override
|
||||
String get identifier => "Ellipsis";
|
||||
|
||||
@override
|
||||
String get title => "...";
|
||||
}
|
||||
|
@ -19,6 +19,9 @@ class DefaultHomeStackContext extends HomeStackContext {
|
||||
Widget render() {
|
||||
return const AnnouncementStackPage();
|
||||
}
|
||||
|
||||
@override
|
||||
List<NavigationItem> get navigationItems => [this];
|
||||
}
|
||||
|
||||
class AnnouncementStackPage extends StatefulWidget {
|
||||
|
@ -28,6 +28,21 @@ class DocStackContext extends HomeStackContext {
|
||||
Widget render() {
|
||||
return DocStackPage(_view, key: ValueKey(_view.id));
|
||||
}
|
||||
|
||||
@override
|
||||
List<NavigationItem> get navigationItems => makeNavigationItems();
|
||||
|
||||
// List<NavigationItem> get navigationItems => naviStacks.map((stack) {
|
||||
// return NavigationItemImpl(context: stack);
|
||||
// }).toList();
|
||||
|
||||
List<NavigationItem> makeNavigationItems() {
|
||||
return [
|
||||
this,
|
||||
this,
|
||||
this,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
class DocStackPage extends StatefulWidget {
|
||||
|
@ -1,4 +1,3 @@
|
||||
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';
|
||||
@ -86,18 +85,3 @@ class HomeTitle extends StatelessWidget {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class ViewNaviItemImpl extends NaviItem {
|
||||
final HomeStackContext view;
|
||||
|
||||
ViewNaviItemImpl(this.view);
|
||||
|
||||
@override
|
||||
NaviAction get action => () => getIt<HomeStack>().setStack(view);
|
||||
|
||||
@override
|
||||
String get identifier => view.identifier;
|
||||
|
||||
@override
|
||||
String get title => view.title;
|
||||
}
|
||||
|
@ -11,7 +11,7 @@ class FlowyHover extends StatefulWidget {
|
||||
const FlowyHover({
|
||||
Key? key,
|
||||
required this.builder,
|
||||
this.config = const HoverDisplayConfig(),
|
||||
required this.config,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
@ -23,40 +23,39 @@ class _FlowyHoverState extends State<FlowyHover> {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final hoverColor = _onHover ? widget.config.hoverColor : Theme.of(context).colorScheme.background;
|
||||
final config = widget.config.copyWith(hoverColor: hoverColor);
|
||||
|
||||
return MouseRegion(
|
||||
cursor: SystemMouseCursors.click,
|
||||
onEnter: (p) => setOnHover(true),
|
||||
onExit: (p) => setOnHover(false),
|
||||
child: FlowyHoverBackground(config: config, child: widget.builder(context, _onHover)),
|
||||
child: render(),
|
||||
);
|
||||
}
|
||||
|
||||
void setOnHover(bool value) => setState(() => _onHover = value);
|
||||
|
||||
Widget render() {
|
||||
if (_onHover) {
|
||||
return FlowyHoverBackground(
|
||||
config: widget.config,
|
||||
child: widget.builder(context, _onHover),
|
||||
);
|
||||
} else {
|
||||
return widget.builder(context, _onHover);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class HoverDisplayConfig {
|
||||
final Color borderColor;
|
||||
final double borderWidth;
|
||||
final Color? hoverColor;
|
||||
final Color hoverColor;
|
||||
final BorderRadius borderRadius;
|
||||
|
||||
const HoverDisplayConfig(
|
||||
{this.borderColor = Colors.transparent,
|
||||
this.borderWidth = 0,
|
||||
this.borderRadius = const BorderRadius.all(Radius.circular(6)),
|
||||
this.hoverColor});
|
||||
|
||||
HoverDisplayConfig copyWith({Color? hoverColor}) {
|
||||
return HoverDisplayConfig(
|
||||
borderColor: borderColor,
|
||||
borderWidth: borderWidth,
|
||||
borderRadius: borderRadius,
|
||||
hoverColor: hoverColor,
|
||||
);
|
||||
}
|
||||
required this.hoverColor});
|
||||
}
|
||||
|
||||
class FlowyHoverBackground extends StatelessWidget {
|
||||
@ -67,12 +66,11 @@ class FlowyHoverBackground extends StatelessWidget {
|
||||
const FlowyHoverBackground({
|
||||
Key? key,
|
||||
required this.child,
|
||||
this.config = const HoverDisplayConfig(),
|
||||
required this.config,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final color = config.hoverColor ?? Theme.of(context).colorScheme.background;
|
||||
final hoverBorder = Border.all(
|
||||
color: config.borderColor,
|
||||
width: config.borderWidth,
|
||||
@ -81,7 +79,7 @@ class FlowyHoverBackground extends StatelessWidget {
|
||||
return Container(
|
||||
decoration: BoxDecoration(
|
||||
border: hoverBorder,
|
||||
color: color,
|
||||
color: config.hoverColor,
|
||||
borderRadius: config.borderRadius,
|
||||
),
|
||||
child: child,
|
||||
|
@ -1,7 +1,9 @@
|
||||
import 'package:flowy_infra/theme.dart';
|
||||
import 'package:flowy_infra_ui/style_widget/hover.dart';
|
||||
import 'package:flowy_infra_ui/style_widget/text.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
class FlowyTextButton extends StatelessWidget {
|
||||
final String text;
|
||||
@ -17,12 +19,11 @@ class FlowyTextButton extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final theme = context.watch<AppTheme>();
|
||||
return InkWell(
|
||||
onTap: onPressed,
|
||||
child: FlowyHover(
|
||||
config: HoverDisplayConfig(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
hoverColor: Colors.grey.shade300),
|
||||
config: HoverDisplayConfig(borderRadius: BorderRadius.circular(6), hoverColor: theme.bg3),
|
||||
builder: (context, onHover) => _render(),
|
||||
),
|
||||
);
|
||||
|
Loading…
Reference in New Issue
Block a user