[flutter]: config ui of menu view
3
app_flowy/.vscode/settings.json
vendored
@ -17,5 +17,6 @@
|
||||
"editor.wordWrapColumn": 120,
|
||||
"editor.minimap.maxColumn": 140,
|
||||
"prettier.printWidth": 140,
|
||||
"editor.wordWrap": "wordWrapColumn"
|
||||
"editor.wordWrap": "wordWrapColumn",
|
||||
"dart.lineLength": 120
|
||||
}
|
@ -1,6 +0,0 @@
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M6 5L3 8L6 11" stroke="#333333" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<rect width="4" height="1" rx="0.5" transform="matrix(-1 0 0 1 13 5)" fill="#333333"/>
|
||||
<rect width="6" height="1" rx="0.5" transform="matrix(-1 0 0 1 13 7.5)" fill="#333333"/>
|
||||
<rect width="4" height="1" rx="0.5" transform="matrix(-1 0 0 1 13 10)" fill="#333333"/>
|
||||
</svg>
|
Before Width: | Height: | Size: 457 B |
Before Width: | Height: | Size: 516 B After Width: | Height: | Size: 516 B |
Before Width: | Height: | Size: 495 B After Width: | Height: | Size: 495 B |
Before Width: | Height: | Size: 286 B After Width: | Height: | Size: 286 B |
Before Width: | Height: | Size: 449 B After Width: | Height: | Size: 449 B |
Before Width: | Height: | Size: 525 B After Width: | Height: | Size: 525 B |
Before Width: | Height: | Size: 512 B After Width: | Height: | Size: 512 B |
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 2.3 KiB |
Before Width: | Height: | Size: 394 B After Width: | Height: | Size: 394 B |
Before Width: | Height: | Size: 579 B After Width: | Height: | Size: 579 B |
Before Width: | Height: | Size: 905 B After Width: | Height: | Size: 905 B |
Before Width: | Height: | Size: 433 B After Width: | Height: | Size: 433 B |
Before Width: | Height: | Size: 387 B After Width: | Height: | Size: 387 B |
@ -4,7 +4,6 @@ import 'package:flowy_infra/image.dart';
|
||||
import 'package:flowy_infra/theme.dart';
|
||||
import 'package:flowy_infra_ui/style_widget/text.dart';
|
||||
import 'package:flowy_infra_ui/widget/spacing.dart';
|
||||
import 'package:flowy_infra_ui/style_widget/text_button.dart';
|
||||
import 'package:flowy_infra/flowy_icon_data_icons.dart';
|
||||
import 'package:flowy_sdk/protobuf/flowy-workspace/app_create.pb.dart';
|
||||
import 'package:flowy_sdk/protobuf/flowy-workspace/view_create.pb.dart';
|
||||
@ -23,65 +22,61 @@ class AppHeader extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final theme = context.watch<AppTheme>();
|
||||
return Row(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
InkWell(
|
||||
onTap: () {
|
||||
ExpandableController.of(context,
|
||||
rebuildOnChange: false, required: true)
|
||||
?.toggle();
|
||||
},
|
||||
child: ExpandableIcon(
|
||||
theme: ExpandableThemeData(
|
||||
expandIcon: FlowyIconData.drop_down_show,
|
||||
collapseIcon: FlowyIconData.drop_down_hide,
|
||||
iconColor: theme.shader1,
|
||||
iconSize: AppPageSize.expandedIconSize,
|
||||
iconPadding: EdgeInsets.zero,
|
||||
hasIcon: false,
|
||||
return SizedBox(
|
||||
height: 20,
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
InkWell(
|
||||
onTap: () {
|
||||
ExpandableController.of(context, rebuildOnChange: false, required: true)?.toggle();
|
||||
},
|
||||
child: ExpandableIcon(
|
||||
theme: ExpandableThemeData(
|
||||
expandIcon: FlowyIconData.drop_down_show,
|
||||
collapseIcon: FlowyIconData.drop_down_hide,
|
||||
iconColor: theme.shader1,
|
||||
iconSize: AppPageSize.expandedIconSize,
|
||||
iconPadding: EdgeInsets.zero,
|
||||
hasIcon: false,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
HSpace(AppPageSize.expandedIconRightSpace),
|
||||
Expanded(
|
||||
child: GestureDetector(
|
||||
onTapDown: (_) {
|
||||
ExpandableController.of(context,
|
||||
rebuildOnChange: false, required: true)
|
||||
?.toggle();
|
||||
},
|
||||
child: FlowyText(
|
||||
app.name,
|
||||
fontSize: 12,
|
||||
),
|
||||
)),
|
||||
HSpace(AppPageSize.expandedIconRightSpace),
|
||||
Expanded(
|
||||
child: GestureDetector(
|
||||
onTapDown: (_) {
|
||||
ExpandableController.of(context, rebuildOnChange: false, required: true)?.toggle();
|
||||
},
|
||||
child: FlowyText.medium(
|
||||
app.name,
|
||||
fontSize: 12,
|
||||
),
|
||||
)),
|
||||
|
||||
// FlowyIconButton(
|
||||
// icon: const Icon(Icons.add),
|
||||
// onPressed: () {
|
||||
// debugPrint('add view');
|
||||
// FlowyOverlay.of(context)
|
||||
// .insert(widget: Text('test'), identifier: 'identifier');
|
||||
// },
|
||||
// ),
|
||||
PopupMenuButton(
|
||||
iconSize: 16,
|
||||
tooltip: 'create new view',
|
||||
icon: svg("home/add"),
|
||||
padding: EdgeInsets.zero,
|
||||
onSelected: (viewType) =>
|
||||
_createView(viewType as ViewType, context),
|
||||
itemBuilder: (context) => menuItemBuilder())
|
||||
],
|
||||
// FlowyIconButton(
|
||||
// icon: const Icon(Icons.add),
|
||||
// onPressed: () {
|
||||
// debugPrint('add view');
|
||||
// FlowyOverlay.of(context)
|
||||
// .insert(widget: Text('test'), identifier: 'identifier');
|
||||
// },
|
||||
// ),
|
||||
PopupMenuButton(
|
||||
iconSize: 16,
|
||||
tooltip: 'create new view',
|
||||
icon: svg("home/add"),
|
||||
padding: EdgeInsets.zero,
|
||||
onSelected: (viewType) => _createView(viewType as ViewType, context),
|
||||
itemBuilder: (context) => menuItemBuilder())
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
List<PopupMenuEntry> menuItemBuilder() {
|
||||
return ViewType.values
|
||||
.where((element) => element != ViewType.Blank)
|
||||
.map((ty) {
|
||||
return ViewType.values.where((element) => element != ViewType.Blank).map((ty) {
|
||||
return PopupMenuItem<ViewType>(
|
||||
value: ty,
|
||||
child: Row(
|
||||
|
@ -15,11 +15,10 @@ import 'package:styled_widget/styled_widget.dart';
|
||||
import 'app_header.dart';
|
||||
|
||||
class AppPageSize {
|
||||
static double expandedIconSize = 20;
|
||||
static double expandedIconSize = 16;
|
||||
static double expandedIconRightSpace = 6;
|
||||
static double scale = 1;
|
||||
static double get expandedPadding =>
|
||||
expandedIconSize * scale + expandedIconRightSpace;
|
||||
static double get expandedPadding => expandedIconSize * scale + expandedIconRightSpace;
|
||||
}
|
||||
|
||||
class ViewListData extends ChangeNotifier {
|
||||
|
@ -67,7 +67,7 @@ class ViewListPage extends StatelessWidget {
|
||||
);
|
||||
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 2),
|
||||
padding: const EdgeInsets.symmetric(vertical: 4),
|
||||
child: viewWidget,
|
||||
);
|
||||
}).toList(growable: false);
|
||||
|
@ -1,5 +1,5 @@
|
||||
class HomeSizes {
|
||||
static double get menuTopBarHeight => 60;
|
||||
static double get menuTopBarHeight => 48;
|
||||
static double get menuAddButtonHeight => 60;
|
||||
static double get topBarHeight => 60;
|
||||
static double get editPannelTopBarHeight => 60;
|
||||
|
@ -1,10 +1,13 @@
|
||||
import 'package:flowy_infra/theme.dart';
|
||||
import 'package:flowy_infra_ui/style_widget/hover.dart';
|
||||
import 'package:flowy_infra_ui/style_widget/icon_button.dart';
|
||||
import 'package:flowy_infra_ui/style_widget/text.dart';
|
||||
import 'package:flowy_infra_ui/widget/spacing.dart';
|
||||
import 'package:flowy_sdk/protobuf/flowy-workspace/view_create.pb.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:app_flowy/workspace/domain/image.dart';
|
||||
import 'package:app_flowy/workspace/presentation/app/app_page.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:styled_widget/styled_widget.dart';
|
||||
|
||||
class ViewWidgetContext {
|
||||
@ -21,16 +24,13 @@ class ViewPage extends StatelessWidget {
|
||||
final ViewWidgetContext viewCtx;
|
||||
final bool isSelected;
|
||||
final OpenViewCallback onOpen;
|
||||
ViewPage(
|
||||
{Key? key,
|
||||
required this.viewCtx,
|
||||
required this.onOpen,
|
||||
required this.isSelected})
|
||||
ViewPage({Key? key, required this.viewCtx, required this.onOpen, required this.isSelected})
|
||||
: super(key: viewCtx.valueKey());
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final config = HoverDisplayConfig(hoverColor: Colors.grey.shade200);
|
||||
final theme = context.watch<AppTheme>();
|
||||
final config = HoverDisplayConfig(hoverColor: theme.bg3);
|
||||
return InkWell(
|
||||
onTap: _openView(context),
|
||||
child: FlowyHover(
|
||||
@ -40,30 +40,37 @@ class ViewPage extends StatelessWidget {
|
||||
);
|
||||
}
|
||||
|
||||
Widget _render(
|
||||
BuildContext context, bool onHover, HoverDisplayConfig config) {
|
||||
const double width = 22;
|
||||
Widget _render(BuildContext context, bool onHover, HoverDisplayConfig config) {
|
||||
List<Widget> children = [
|
||||
SizedBox(
|
||||
width: width,
|
||||
height: width,
|
||||
child: svgForViewType(viewCtx.view.viewType)),
|
||||
width: 16,
|
||||
height: 16,
|
||||
child: svgForViewType(viewCtx.view.viewType),
|
||||
),
|
||||
const HSpace(6),
|
||||
Text(
|
||||
FlowyText.regular(
|
||||
viewCtx.view.name,
|
||||
textAlign: TextAlign.start,
|
||||
style: const TextStyle(fontSize: 15),
|
||||
fontSize: 12,
|
||||
),
|
||||
];
|
||||
|
||||
if (onHover) {
|
||||
_addedHover(children, width);
|
||||
children.add(const Spacer());
|
||||
children.add(ViewMoreButton(
|
||||
width: 16,
|
||||
onPressed: () {
|
||||
debugPrint('show view setting');
|
||||
},
|
||||
));
|
||||
}
|
||||
|
||||
Widget widget = Row(children: children).padding(
|
||||
vertical: 5,
|
||||
left: AppPageSize.expandedPadding,
|
||||
right: 5,
|
||||
Widget widget = Container(
|
||||
child: Row(children: children).padding(
|
||||
left: AppPageSize.expandedPadding,
|
||||
right: 12,
|
||||
),
|
||||
height: 24,
|
||||
alignment: Alignment.centerLeft,
|
||||
);
|
||||
|
||||
if (isSelected) {
|
||||
@ -76,17 +83,4 @@ class ViewPage extends StatelessWidget {
|
||||
Function() _openView(BuildContext context) {
|
||||
return () => onOpen(viewCtx.view);
|
||||
}
|
||||
|
||||
void _addedHover(List<Widget> children, double hoverWidth) {
|
||||
children.add(const Spacer());
|
||||
children.add(Align(
|
||||
alignment: Alignment.center,
|
||||
child: FlowyMoreButton(
|
||||
width: hoverWidth,
|
||||
onPressed: () {
|
||||
debugPrint('show view setting');
|
||||
},
|
||||
),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
@ -51,7 +51,7 @@ class HomeTopBar extends StatelessWidget {
|
||||
}
|
||||
|
||||
Widget _renderMoreButton() {
|
||||
return FlowyMoreButton(
|
||||
return ViewMoreButton(
|
||||
width: 24,
|
||||
onPressed: () {
|
||||
debugPrint('show more');
|
||||
@ -79,11 +79,7 @@ class HomeTitle extends StatelessWidget {
|
||||
return Flexible(
|
||||
child: Row(
|
||||
children: [
|
||||
Image(
|
||||
fit: BoxFit.scaleDown,
|
||||
width: 15,
|
||||
height: 15,
|
||||
image: assetImageForViewType(type)),
|
||||
Image(fit: BoxFit.scaleDown, width: 15, height: 15, image: assetImageForViewType(type)),
|
||||
const HSpace(6),
|
||||
FlowyText(title, fontSize: 16),
|
||||
],
|
||||
|
@ -23,8 +23,7 @@ class MenuList extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return ExpandableTheme(
|
||||
data: ExpandableThemeData(
|
||||
useInkWell: true, animationDuration: Durations.medium),
|
||||
data: ExpandableThemeData(useInkWell: true, animationDuration: Durations.medium),
|
||||
child: Expanded(
|
||||
child: ListView.separated(
|
||||
itemCount: menuItems.length,
|
||||
@ -32,7 +31,7 @@ class MenuList extends StatelessWidget {
|
||||
if (index == 0) {
|
||||
return const VSpace(29);
|
||||
} else {
|
||||
return const VSpace(9);
|
||||
return const VSpace(24);
|
||||
}
|
||||
},
|
||||
physics: const BouncingScrollPhysics(),
|
||||
|
@ -3,6 +3,7 @@ import 'package:app_flowy/workspace/presentation/widgets/menu/menu_top_bar.dart'
|
||||
import 'package:dartz/dartz.dart';
|
||||
import 'package:flowy_infra/size.dart';
|
||||
import 'package:flowy_infra_ui/widget/error_page.dart';
|
||||
import 'package:flowy_infra_ui/widget/spacing.dart';
|
||||
import 'package:flowy_sdk/protobuf/flowy-user/user_profile.pb.dart';
|
||||
import 'package:flowy_sdk/protobuf/flowy-workspace/app_create.pb.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
@ -38,13 +39,10 @@ class HomeMenu extends StatelessWidget {
|
||||
return MultiBlocProvider(
|
||||
providers: [
|
||||
BlocProvider<MenuBloc>(
|
||||
create: (context) =>
|
||||
getIt<MenuBloc>(param1: user, param2: workspaceId)
|
||||
..add(const MenuEvent.initial())),
|
||||
create: (context) => getIt<MenuBloc>(param1: user, param2: workspaceId)..add(const MenuEvent.initial())),
|
||||
BlocProvider(
|
||||
create: (context) =>
|
||||
getIt<MenuWatchBloc>(param1: user, param2: workspaceId)
|
||||
..add(const MenuWatchEvent.started())),
|
||||
getIt<MenuWatchBloc>(param1: user, param2: workspaceId)..add(const MenuWatchEvent.started())),
|
||||
],
|
||||
child: MultiBlocListener(
|
||||
listeners: [
|
||||
@ -76,6 +74,7 @@ class HomeMenu extends StatelessWidget {
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: [
|
||||
_renderTopBar(context),
|
||||
const VSpace(32),
|
||||
_renderMenuList(context),
|
||||
],
|
||||
).padding(horizontal: Insets.l),
|
||||
@ -104,16 +103,12 @@ class HomeMenu extends StatelessWidget {
|
||||
|
||||
Widget _renderNewAppButton(BuildContext context) {
|
||||
return NewAppButton(
|
||||
press: (appName) =>
|
||||
context.read<MenuBloc>().add(MenuEvent.createApp(appName, desc: "")),
|
||||
press: (appName) => context.read<MenuBloc>().add(MenuEvent.createApp(appName, desc: "")),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _renderTopBar(BuildContext context) {
|
||||
return SizedBox(
|
||||
height: HomeSizes.menuTopBarHeight,
|
||||
child: const MenuTopBar(),
|
||||
);
|
||||
return const MenuTopBar();
|
||||
}
|
||||
|
||||
List<MenuItem> menuItemsWithApps(Option<List<App>> someApps) {
|
||||
|
@ -9,19 +9,21 @@ class MenuTopBar extends StatelessWidget {
|
||||
Widget build(BuildContext context) {
|
||||
return BlocBuilder<MenuBloc, MenuState>(
|
||||
builder: (context, state) {
|
||||
return Row(
|
||||
children: [
|
||||
svgWithSize("flowy_logo_with_text", const Size(92, 17)),
|
||||
const Spacer(),
|
||||
IconButton(
|
||||
iconSize: 16,
|
||||
icon: svg("home/hide_menu"),
|
||||
alignment: Alignment.centerRight,
|
||||
padding: EdgeInsets.zero,
|
||||
onPressed: () =>
|
||||
context.read<MenuBloc>().add(const MenuEvent.collapse()),
|
||||
),
|
||||
],
|
||||
return SizedBox(
|
||||
height: 48,
|
||||
child: Row(
|
||||
children: [
|
||||
svgWithSize("flowy_logo_with_text", const Size(92, 17)),
|
||||
const Spacer(),
|
||||
IconButton(
|
||||
iconSize: 16,
|
||||
icon: svg("home/hide_menu"),
|
||||
alignment: Alignment.centerRight,
|
||||
padding: EdgeInsets.zero,
|
||||
onPressed: () => context.read<MenuBloc>().add(const MenuEvent.collapse()),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
|
@ -23,17 +23,14 @@ class _FlowyHoverState extends State<FlowyHover> {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final hoverColor = _onHover
|
||||
? widget.config.hoverColor
|
||||
: Theme.of(context).colorScheme.background;
|
||||
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: FlowyHoverBackground(config: config, child: widget.builder(context, _onHover)),
|
||||
);
|
||||
}
|
||||
|
||||
@ -49,15 +46,16 @@ class HoverDisplayConfig {
|
||||
const HoverDisplayConfig(
|
||||
{this.borderColor = Colors.transparent,
|
||||
this.borderWidth = 0,
|
||||
this.borderRadius = const BorderRadius.all(Radius.circular(8)),
|
||||
this.borderRadius = const BorderRadius.all(Radius.circular(6)),
|
||||
this.hoverColor});
|
||||
|
||||
HoverDisplayConfig copyWith({Color? hoverColor}) {
|
||||
return HoverDisplayConfig(
|
||||
borderColor: borderColor,
|
||||
borderWidth: borderWidth,
|
||||
borderRadius: borderRadius,
|
||||
hoverColor: hoverColor);
|
||||
borderColor: borderColor,
|
||||
borderWidth: borderWidth,
|
||||
borderRadius: borderRadius,
|
||||
hoverColor: hoverColor,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,3 +1,4 @@
|
||||
import 'package:flowy_infra/image.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class FlowyIconButton extends StatelessWidget {
|
||||
@ -32,12 +33,12 @@ class FlowyIconButton extends StatelessWidget {
|
||||
}
|
||||
}
|
||||
|
||||
class FlowyMoreButton extends StatelessWidget {
|
||||
class ViewMoreButton extends StatelessWidget {
|
||||
final double width;
|
||||
final double? height;
|
||||
final VoidCallback? onPressed;
|
||||
|
||||
const FlowyMoreButton({
|
||||
const ViewMoreButton({
|
||||
Key? key,
|
||||
this.height,
|
||||
this.onPressed,
|
||||
@ -49,7 +50,7 @@ class FlowyMoreButton extends StatelessWidget {
|
||||
return FlowyIconButton(
|
||||
width: width,
|
||||
height: height,
|
||||
icon: const Icon(Icons.more_vert),
|
||||
icon: svg("editor/details"),
|
||||
onPressed: onPressed,
|
||||
);
|
||||
}
|
||||
|
@ -6,13 +6,25 @@ class FlowyText extends StatelessWidget {
|
||||
final String title;
|
||||
final TextOverflow overflow;
|
||||
final double fontSize;
|
||||
final FontWeight fontWeight;
|
||||
const FlowyText(
|
||||
this.title, {
|
||||
Key? key,
|
||||
this.overflow = TextOverflow.ellipsis,
|
||||
this.fontSize = 16,
|
||||
this.fontWeight = FontWeight.w500,
|
||||
}) : super(key: key);
|
||||
|
||||
const FlowyText.medium(this.title, {Key? key, this.fontSize = 16, TextOverflow? overflow})
|
||||
: fontWeight = FontWeight.w500,
|
||||
overflow = overflow ?? TextOverflow.ellipsis,
|
||||
super(key: key);
|
||||
|
||||
const FlowyText.regular(this.title, {Key? key, this.fontSize = 16, TextOverflow? overflow})
|
||||
: fontWeight = FontWeight.w400,
|
||||
overflow = overflow ?? TextOverflow.ellipsis,
|
||||
super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final theme = context.watch<AppTheme>();
|
||||
@ -21,7 +33,7 @@ class FlowyText extends StatelessWidget {
|
||||
softWrap: false,
|
||||
style: TextStyle(
|
||||
color: theme.shader1,
|
||||
fontWeight: FontWeight.w500,
|
||||
fontWeight: fontWeight,
|
||||
fontSize: fontSize + 2,
|
||||
));
|
||||
}
|
||||
|
@ -98,6 +98,7 @@ flutter:
|
||||
assets:
|
||||
- assets/images/
|
||||
- assets/images/home/
|
||||
- assets/images/editor/
|
||||
# - images/a_dot_ham.jpeg
|
||||
|
||||
# An image asset can refer to one or more resolution-specific "variants", see
|
||||
|