mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
[flutter]: config toolbar ui
This commit is contained in:
@ -1,10 +1,8 @@
|
|||||||
import 'package:editor/flutter_quill.dart';
|
import 'package:editor/flutter_quill.dart';
|
||||||
import 'package:editor/models/documents/style.dart';
|
import 'package:editor/models/documents/style.dart';
|
||||||
import 'package:flowy_infra/image.dart';
|
|
||||||
import 'package:flowy_infra/theme.dart';
|
|
||||||
import 'package:flowy_infra_ui/style_widget/icon_button.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:provider/provider.dart';
|
|
||||||
|
import 'toolbar_icon_button.dart';
|
||||||
|
|
||||||
class FlowyCheckListButton extends StatefulWidget {
|
class FlowyCheckListButton extends StatefulWidget {
|
||||||
const FlowyCheckListButton({
|
const FlowyCheckListButton({
|
||||||
@ -77,13 +75,11 @@ class _FlowyCheckListButtonState extends State<FlowyCheckListButton> {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final theme = context.watch<AppTheme>();
|
return ToolbarIconButton(
|
||||||
return FlowyIconButton(
|
|
||||||
onPressed: _toggleAttribute,
|
onPressed: _toggleAttribute,
|
||||||
width: widget.iconSize * kIconButtonFactor,
|
width: widget.iconSize * kIconButtonFactor,
|
||||||
icon: svg('editor/checkbox'),
|
iconName: 'editor/checkbox',
|
||||||
highlightColor: _isToggled == true ? theme.shader5 : theme.shader6,
|
isToggled: _isToggled ?? false,
|
||||||
hoverColor: theme.shader5,
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,96 @@
|
|||||||
|
import 'package:editor/flutter_quill.dart';
|
||||||
|
import 'package:flowy_infra/image.dart';
|
||||||
|
import 'package:flowy_infra/theme.dart';
|
||||||
|
import 'package:flowy_infra_ui/style_widget/icon_button.dart';
|
||||||
|
import 'package:flutter/foundation.dart';
|
||||||
|
import 'package:editor/models/documents/style.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
|
import 'toolbar_icon_button.dart';
|
||||||
|
|
||||||
|
class FlowyHeaderStyleButton extends StatefulWidget {
|
||||||
|
const FlowyHeaderStyleButton({
|
||||||
|
required this.controller,
|
||||||
|
this.iconSize = kDefaultIconSize,
|
||||||
|
Key? key,
|
||||||
|
}) : super(key: key);
|
||||||
|
|
||||||
|
final QuillController controller;
|
||||||
|
final double iconSize;
|
||||||
|
|
||||||
|
@override
|
||||||
|
_FlowyHeaderStyleButtonState createState() => _FlowyHeaderStyleButtonState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _FlowyHeaderStyleButtonState extends State<FlowyHeaderStyleButton> {
|
||||||
|
Attribute? _value;
|
||||||
|
|
||||||
|
Style get _selectionStyle => widget.controller.getSelectionStyle();
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
setState(() {
|
||||||
|
_value = _selectionStyle.attributes[Attribute.header.key] ?? Attribute.header;
|
||||||
|
});
|
||||||
|
widget.controller.addListener(_didChangeEditingValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final _valueToText = <Attribute, String>{
|
||||||
|
Attribute.h1: 'H1',
|
||||||
|
Attribute.h2: 'H2',
|
||||||
|
Attribute.h3: 'H3',
|
||||||
|
};
|
||||||
|
|
||||||
|
final _valueAttribute = <Attribute>[Attribute.h1, Attribute.h2, Attribute.h3];
|
||||||
|
final _valueString = <String>['H1', 'H2', 'H3'];
|
||||||
|
final _attributeImageName = <String>['editor/H1', 'editor/H2', 'editor/H3'];
|
||||||
|
|
||||||
|
return Row(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: List.generate(3, (index) {
|
||||||
|
// final child =
|
||||||
|
// _valueToText[_value] == _valueString[index] ? svg('editor/H1', color: Colors.white) : svg('editor/H1');
|
||||||
|
|
||||||
|
final _isToggled = _valueToText[_value] == _valueString[index];
|
||||||
|
return ToolbarIconButton(
|
||||||
|
onPressed: () {
|
||||||
|
if (_isToggled) {
|
||||||
|
widget.controller.formatSelection(Attribute.header);
|
||||||
|
} else {
|
||||||
|
widget.controller.formatSelection(_valueAttribute[index]);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
width: widget.iconSize * kIconButtonFactor,
|
||||||
|
iconName: _attributeImageName[index],
|
||||||
|
isToggled: _isToggled,
|
||||||
|
);
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void _didChangeEditingValue() {
|
||||||
|
setState(() {
|
||||||
|
_value = _selectionStyle.attributes[Attribute.header.key] ?? Attribute.header;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void didUpdateWidget(covariant FlowyHeaderStyleButton oldWidget) {
|
||||||
|
super.didUpdateWidget(oldWidget);
|
||||||
|
if (oldWidget.controller != widget.controller) {
|
||||||
|
oldWidget.controller.removeListener(_didChangeEditingValue);
|
||||||
|
widget.controller.addListener(_didChangeEditingValue);
|
||||||
|
_value = _selectionStyle.attributes[Attribute.header.key] ?? Attribute.header;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
widget.controller.removeListener(_didChangeEditingValue);
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
}
|
@ -1,9 +1,9 @@
|
|||||||
import 'package:editor/flutter_quill.dart';
|
import 'package:editor/flutter_quill.dart';
|
||||||
import 'package:flowy_infra/image.dart';
|
|
||||||
import 'package:flowy_infra_ui/style_widget/icon_button.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:image_picker/image_picker.dart';
|
import 'package:image_picker/image_picker.dart';
|
||||||
|
|
||||||
|
import 'toolbar_icon_button.dart';
|
||||||
|
|
||||||
class FlowyImageButton extends StatelessWidget {
|
class FlowyImageButton extends StatelessWidget {
|
||||||
const FlowyImageButton({
|
const FlowyImageButton({
|
||||||
required this.controller,
|
required this.controller,
|
||||||
@ -32,13 +32,11 @@ class FlowyImageButton extends StatelessWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final theme = Theme.of(context);
|
return ToolbarIconButton(
|
||||||
|
iconName: 'editor/image',
|
||||||
return FlowyIconButton(
|
|
||||||
icon: svg('editor/image'),
|
|
||||||
width: iconSize * 1.77,
|
width: iconSize * 1.77,
|
||||||
highlightColor: theme.canvasColor,
|
|
||||||
onPressed: () => _onPressedHandler(context),
|
onPressed: () => _onPressedHandler(context),
|
||||||
|
isToggled: false,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import 'package:app_flowy/workspace/presentation/widgets/dialogs.dart';
|
||||||
import 'package:editor/flutter_quill.dart';
|
import 'package:editor/flutter_quill.dart';
|
||||||
import 'package:flowy_infra/image.dart';
|
import 'package:flowy_infra/image.dart';
|
||||||
import 'package:flowy_infra/theme.dart';
|
import 'package:flowy_infra/theme.dart';
|
||||||
@ -47,33 +48,39 @@ class _FlowyLinkStyleButtonState extends State<FlowyLinkStyleButton> {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
final theme = context.watch<AppTheme>();
|
||||||
final isEnabled = !widget.controller.selection.isCollapsed;
|
final isEnabled = !widget.controller.selection.isCollapsed;
|
||||||
final pressedHandler = isEnabled ? () => _openLinkDialog(context) : null;
|
final pressedHandler = isEnabled ? () => _openLinkDialog(context) : null;
|
||||||
|
final icon = isEnabled ? svg('editor/share') : svg('editor/share', color: theme.shader4);
|
||||||
final theme = context.watch<AppTheme>();
|
|
||||||
|
|
||||||
return FlowyIconButton(
|
return FlowyIconButton(
|
||||||
onPressed: pressedHandler,
|
onPressed: pressedHandler,
|
||||||
icon: svg('editor/share'),
|
iconPadding: const EdgeInsets.symmetric(horizontal: 4, vertical: 4),
|
||||||
highlightColor: isEnabled == true ? theme.shader5 : theme.shader6,
|
icon: icon,
|
||||||
|
fillColor: theme.shader6,
|
||||||
hoverColor: theme.shader5,
|
hoverColor: theme.shader5,
|
||||||
width: widget.iconSize * kIconButtonFactor,
|
width: widget.iconSize * kIconButtonFactor,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _openLinkDialog(BuildContext context) {
|
void _openLinkDialog(BuildContext context) {
|
||||||
// showDialog<String>(
|
final style = widget.controller.getSelectionStyle();
|
||||||
// context: context,
|
final values = style.values.where((v) => v.key == Attribute.link.key).map((v) => v.value);
|
||||||
// builder: (ctx) {
|
String value = "";
|
||||||
// return const LinkDialog();
|
if (values.isNotEmpty) {
|
||||||
// },
|
assert(values.length == 1);
|
||||||
// ).then(_linkSubmitted);
|
value = values.first;
|
||||||
}
|
|
||||||
|
|
||||||
void _linkSubmitted(String? value) {
|
|
||||||
if (value == null || value.isEmpty) {
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
widget.controller.formatSelection(LinkAttribute(value));
|
|
||||||
|
TextFieldDialog(
|
||||||
|
title: 'URL',
|
||||||
|
value: value,
|
||||||
|
confirm: (newValue) {
|
||||||
|
if (newValue.isEmpty) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
widget.controller.formatSelection(LinkAttribute(newValue));
|
||||||
|
},
|
||||||
|
).show(context);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,20 +1,18 @@
|
|||||||
import 'package:editor/flutter_quill.dart';
|
import 'package:editor/flutter_quill.dart';
|
||||||
import 'package:editor/models/documents/style.dart';
|
import 'package:editor/models/documents/style.dart';
|
||||||
|
|
||||||
import 'package:flowy_infra/theme.dart';
|
|
||||||
import 'package:flowy_infra_ui/style_widget/icon_button.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:provider/provider.dart';
|
|
||||||
|
import 'toolbar_icon_button.dart';
|
||||||
|
|
||||||
class FlowyToggleStyleButton extends StatefulWidget {
|
class FlowyToggleStyleButton extends StatefulWidget {
|
||||||
final Attribute attribute;
|
final Attribute attribute;
|
||||||
final Widget icon;
|
final String normalIcon;
|
||||||
final double iconSize;
|
final double iconSize;
|
||||||
final QuillController controller;
|
final QuillController controller;
|
||||||
|
|
||||||
const FlowyToggleStyleButton({
|
const FlowyToggleStyleButton({
|
||||||
required this.attribute,
|
required this.attribute,
|
||||||
required this.icon,
|
required this.normalIcon,
|
||||||
required this.controller,
|
required this.controller,
|
||||||
this.iconSize = kDefaultIconSize,
|
this.iconSize = kDefaultIconSize,
|
||||||
Key? key,
|
Key? key,
|
||||||
@ -36,14 +34,11 @@ class _ToggleStyleButtonState extends State<FlowyToggleStyleButton> {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final theme = context.watch<AppTheme>();
|
return ToolbarIconButton(
|
||||||
|
|
||||||
return FlowyIconButton(
|
|
||||||
onPressed: _toggleAttribute,
|
onPressed: _toggleAttribute,
|
||||||
width: widget.iconSize * kIconButtonFactor,
|
width: widget.iconSize * kIconButtonFactor,
|
||||||
icon: widget.icon,
|
isToggled: _isToggled ?? false,
|
||||||
highlightColor: _isToggled == true ? theme.shader5 : theme.shader6,
|
iconName: widget.normalIcon,
|
||||||
hoverColor: theme.shader5,
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,9 +2,10 @@ import 'dart:async';
|
|||||||
import 'dart:math';
|
import 'dart:math';
|
||||||
|
|
||||||
import 'package:editor/flutter_quill.dart';
|
import 'package:editor/flutter_quill.dart';
|
||||||
import 'package:flowy_infra/image.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:styled_widget/styled_widget.dart';
|
||||||
import 'check_button.dart';
|
import 'check_button.dart';
|
||||||
|
import 'header_button.dart';
|
||||||
import 'image_button.dart';
|
import 'image_button.dart';
|
||||||
import 'link_button.dart';
|
import 'link_button.dart';
|
||||||
import 'toggle_button.dart';
|
import 'toggle_button.dart';
|
||||||
@ -16,7 +17,7 @@ class EditorToolbar extends StatelessWidget implements PreferredSizeWidget {
|
|||||||
|
|
||||||
const EditorToolbar({
|
const EditorToolbar({
|
||||||
required this.children,
|
required this.children,
|
||||||
this.toolBarHeight = 36,
|
this.toolBarHeight = 46,
|
||||||
this.color,
|
this.color,
|
||||||
Key? key,
|
Key? key,
|
||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
@ -26,7 +27,7 @@ class EditorToolbar extends StatelessWidget implements PreferredSizeWidget {
|
|||||||
return Container(
|
return Container(
|
||||||
color: Theme.of(context).canvasColor,
|
color: Theme.of(context).canvasColor,
|
||||||
constraints: BoxConstraints.tightFor(height: preferredSize.height),
|
constraints: BoxConstraints.tightFor(height: preferredSize.height),
|
||||||
child: ToolbarButtonList(buttons: children),
|
child: ToolbarButtonList(buttons: children).padding(horizontal: 4, vertical: 4),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -62,25 +63,25 @@ class EditorToolbar extends StatelessWidget implements PreferredSizeWidget {
|
|||||||
),
|
),
|
||||||
FlowyToggleStyleButton(
|
FlowyToggleStyleButton(
|
||||||
attribute: Attribute.bold,
|
attribute: Attribute.bold,
|
||||||
icon: svg('editor/bold'),
|
normalIcon: 'editor/bold',
|
||||||
iconSize: toolbarIconSize,
|
iconSize: toolbarIconSize,
|
||||||
controller: controller,
|
controller: controller,
|
||||||
),
|
),
|
||||||
FlowyToggleStyleButton(
|
FlowyToggleStyleButton(
|
||||||
attribute: Attribute.italic,
|
attribute: Attribute.italic,
|
||||||
icon: svg("editor/restore"),
|
normalIcon: 'editor/restore',
|
||||||
iconSize: toolbarIconSize,
|
iconSize: toolbarIconSize,
|
||||||
controller: controller,
|
controller: controller,
|
||||||
),
|
),
|
||||||
FlowyToggleStyleButton(
|
FlowyToggleStyleButton(
|
||||||
attribute: Attribute.underline,
|
attribute: Attribute.underline,
|
||||||
icon: svg('editor/underline'),
|
normalIcon: 'editor/underline',
|
||||||
iconSize: toolbarIconSize,
|
iconSize: toolbarIconSize,
|
||||||
controller: controller,
|
controller: controller,
|
||||||
),
|
),
|
||||||
FlowyToggleStyleButton(
|
FlowyToggleStyleButton(
|
||||||
attribute: Attribute.strikeThrough,
|
attribute: Attribute.strikeThrough,
|
||||||
icon: svg('editor/strikethrough'),
|
normalIcon: 'editor/strikethrough',
|
||||||
iconSize: toolbarIconSize,
|
iconSize: toolbarIconSize,
|
||||||
controller: controller,
|
controller: controller,
|
||||||
),
|
),
|
||||||
@ -98,20 +99,20 @@ class EditorToolbar extends StatelessWidget implements PreferredSizeWidget {
|
|||||||
webImagePickImpl: webImagePickImpl,
|
webImagePickImpl: webImagePickImpl,
|
||||||
mediaPickSettingSelector: mediaPickSettingSelector,
|
mediaPickSettingSelector: mediaPickSettingSelector,
|
||||||
),
|
),
|
||||||
SelectHeaderStyleButton(
|
FlowyHeaderStyleButton(
|
||||||
controller: controller,
|
controller: controller,
|
||||||
iconSize: toolbarIconSize,
|
iconSize: toolbarIconSize,
|
||||||
),
|
),
|
||||||
FlowyToggleStyleButton(
|
FlowyToggleStyleButton(
|
||||||
attribute: Attribute.ol,
|
attribute: Attribute.ol,
|
||||||
controller: controller,
|
controller: controller,
|
||||||
icon: svg('editor/numbers'),
|
normalIcon: 'editor/numbers',
|
||||||
iconSize: toolbarIconSize,
|
iconSize: toolbarIconSize,
|
||||||
),
|
),
|
||||||
FlowyToggleStyleButton(
|
FlowyToggleStyleButton(
|
||||||
attribute: Attribute.ul,
|
attribute: Attribute.ul,
|
||||||
controller: controller,
|
controller: controller,
|
||||||
icon: svg('editor/bullet_list'),
|
normalIcon: 'editor/bullet_list',
|
||||||
iconSize: toolbarIconSize,
|
iconSize: toolbarIconSize,
|
||||||
),
|
),
|
||||||
FlowyCheckListButton(
|
FlowyCheckListButton(
|
||||||
@ -122,31 +123,13 @@ class EditorToolbar extends StatelessWidget implements PreferredSizeWidget {
|
|||||||
FlowyToggleStyleButton(
|
FlowyToggleStyleButton(
|
||||||
attribute: Attribute.inlineCode,
|
attribute: Attribute.inlineCode,
|
||||||
controller: controller,
|
controller: controller,
|
||||||
icon: svg('editor/inline_block'),
|
normalIcon: 'editor/inline_block',
|
||||||
iconSize: toolbarIconSize,
|
iconSize: toolbarIconSize,
|
||||||
),
|
),
|
||||||
FlowyToggleStyleButton(
|
FlowyToggleStyleButton(
|
||||||
attribute: Attribute.blockQuote,
|
attribute: Attribute.blockQuote,
|
||||||
controller: controller,
|
controller: controller,
|
||||||
icon: svg('editor/quote'),
|
normalIcon: 'editor/quote',
|
||||||
iconSize: toolbarIconSize,
|
|
||||||
),
|
|
||||||
FlowyToggleStyleButton(
|
|
||||||
attribute: Attribute.blockQuote,
|
|
||||||
controller: controller,
|
|
||||||
icon: svg('editor/quote'),
|
|
||||||
iconSize: toolbarIconSize,
|
|
||||||
),
|
|
||||||
FlowyToggleStyleButton(
|
|
||||||
attribute: Attribute.blockQuote,
|
|
||||||
controller: controller,
|
|
||||||
icon: svg('editor/quote'),
|
|
||||||
iconSize: toolbarIconSize,
|
|
||||||
),
|
|
||||||
FlowyToggleStyleButton(
|
|
||||||
attribute: Attribute.blockQuote,
|
|
||||||
controller: controller,
|
|
||||||
icon: svg('editor/quote'),
|
|
||||||
iconSize: toolbarIconSize,
|
iconSize: toolbarIconSize,
|
||||||
),
|
),
|
||||||
FlowyLinkStyleButton(
|
FlowyLinkStyleButton(
|
||||||
@ -191,14 +174,25 @@ class _ToolbarButtonListState extends State<ToolbarButtonList> with WidgetsBindi
|
|||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return LayoutBuilder(
|
return LayoutBuilder(
|
||||||
builder: (BuildContext context, BoxConstraints constraints) {
|
builder: (BuildContext context, BoxConstraints constraints) {
|
||||||
|
List<Widget> children = [];
|
||||||
|
double width = (widget.buttons.length + 2) * kDefaultIconSize * kIconButtonFactor;
|
||||||
|
final isFit = constraints.maxWidth > width;
|
||||||
|
if (!isFit) {
|
||||||
|
children.add(_buildLeftArrow());
|
||||||
|
width = width + 18;
|
||||||
|
}
|
||||||
|
|
||||||
|
children.add(_buildScrollableList(constraints));
|
||||||
|
|
||||||
|
if (!isFit) {
|
||||||
|
children.add(_buildRightArrow());
|
||||||
|
width = width + 18;
|
||||||
|
}
|
||||||
|
|
||||||
return SizedBox(
|
return SizedBox(
|
||||||
width: min(constraints.maxWidth, (widget.buttons.length + 3) * kDefaultIconSize * kIconButtonFactor + 16),
|
width: min(constraints.maxWidth, width),
|
||||||
child: Row(
|
child: Row(
|
||||||
children: <Widget>[
|
children: children,
|
||||||
_buildLeftArrow(),
|
|
||||||
_buildScrollableList(constraints),
|
|
||||||
_buildRightColor(),
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
@ -261,7 +255,7 @@ class _ToolbarButtonListState extends State<ToolbarButtonList> with WidgetsBindi
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildRightColor() {
|
Widget _buildRightArrow() {
|
||||||
return SizedBox(
|
return SizedBox(
|
||||||
width: 8,
|
width: 8,
|
||||||
child: Transform.translate(
|
child: Transform.translate(
|
||||||
@ -273,7 +267,6 @@ class _ToolbarButtonListState extends State<ToolbarButtonList> with WidgetsBindi
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// ScrollBehavior without the Material glow effect.
|
|
||||||
class _NoGlowBehavior extends ScrollBehavior {
|
class _NoGlowBehavior extends ScrollBehavior {
|
||||||
@override
|
@override
|
||||||
Widget buildViewportChrome(BuildContext _, Widget child, AxisDirection __) {
|
Widget buildViewportChrome(BuildContext _, Widget child, AxisDirection __) {
|
||||||
|
@ -0,0 +1,29 @@
|
|||||||
|
import 'package:flowy_infra/image.dart';
|
||||||
|
import 'package:flowy_infra/theme.dart';
|
||||||
|
import 'package:flowy_infra_ui/style_widget/icon_button.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
|
class ToolbarIconButton extends StatelessWidget {
|
||||||
|
final double width;
|
||||||
|
final VoidCallback? onPressed;
|
||||||
|
final bool isToggled;
|
||||||
|
final String iconName;
|
||||||
|
|
||||||
|
const ToolbarIconButton(
|
||||||
|
{Key? key, required this.onPressed, required this.isToggled, required this.width, required this.iconName})
|
||||||
|
: super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final theme = context.watch<AppTheme>();
|
||||||
|
return FlowyIconButton(
|
||||||
|
iconPadding: const EdgeInsets.symmetric(horizontal: 4, vertical: 4),
|
||||||
|
onPressed: onPressed,
|
||||||
|
width: width,
|
||||||
|
icon: isToggled == true ? svg(iconName, color: Colors.white) : svg(iconName),
|
||||||
|
fillColor: isToggled == true ? theme.main1 : theme.shader6,
|
||||||
|
hoverColor: isToggled == true ? theme.main1 : theme.shader5,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -14,30 +14,30 @@ import 'package:flowy_infra_ui/widget/dialog/styled_dialogs.dart';
|
|||||||
import 'package:textstyle_extensions/textstyle_extensions.dart';
|
import 'package:textstyle_extensions/textstyle_extensions.dart';
|
||||||
export 'package:flowy_infra_ui/widget/dialog/styled_dialogs.dart';
|
export 'package:flowy_infra_ui/widget/dialog/styled_dialogs.dart';
|
||||||
|
|
||||||
class RenameDialog extends StatefulWidget {
|
class TextFieldDialog extends StatefulWidget {
|
||||||
final String name;
|
final String value;
|
||||||
final String title;
|
final String title;
|
||||||
final void Function()? cancel;
|
final void Function()? cancel;
|
||||||
final void Function(String) confirm;
|
final void Function(String) confirm;
|
||||||
|
|
||||||
const RenameDialog({
|
const TextFieldDialog({
|
||||||
required this.title,
|
required this.title,
|
||||||
required this.name,
|
required this.value,
|
||||||
required this.confirm,
|
required this.confirm,
|
||||||
this.cancel,
|
this.cancel,
|
||||||
Key? key,
|
Key? key,
|
||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<RenameDialog> createState() => _CreateRenameDialog();
|
State<TextFieldDialog> createState() => _CreateTextFieldDialog();
|
||||||
}
|
}
|
||||||
|
|
||||||
class _CreateRenameDialog extends State<RenameDialog> {
|
class _CreateTextFieldDialog extends State<TextFieldDialog> {
|
||||||
String newViewName = "";
|
String newValue = "";
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
newViewName = widget.name;
|
newValue = widget.value;
|
||||||
super.initState();
|
super.initState();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -53,9 +53,10 @@ class _CreateRenameDialog extends State<RenameDialog> {
|
|||||||
VSpace(Insets.sm * 1.5),
|
VSpace(Insets.sm * 1.5),
|
||||||
],
|
],
|
||||||
FlowyFormTextInput(
|
FlowyFormTextInput(
|
||||||
hintText: widget.name,
|
hintText: widget.value,
|
||||||
|
autoFocus: true,
|
||||||
onChanged: (text) {
|
onChanged: (text) {
|
||||||
newViewName = text;
|
newValue = text;
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
SizedBox(height: Insets.l),
|
SizedBox(height: Insets.l),
|
||||||
@ -63,7 +64,7 @@ class _CreateRenameDialog extends State<RenameDialog> {
|
|||||||
height: 40,
|
height: 40,
|
||||||
child: OkCancelButton(
|
child: OkCancelButton(
|
||||||
onOkPressed: () {
|
onOkPressed: () {
|
||||||
widget.confirm(newViewName);
|
widget.confirm(newValue);
|
||||||
},
|
},
|
||||||
onCancelPressed: () {
|
onCancelPressed: () {
|
||||||
if (widget.cancel != null) {
|
if (widget.cancel != null) {
|
||||||
|
@ -80,14 +80,14 @@ class AddButton extends StatelessWidget {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return FlowyIconButton(
|
return FlowyIconButton(
|
||||||
width: 16,
|
width: 22,
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
ActionList(
|
ActionList(
|
||||||
anchorContext: context,
|
anchorContext: context,
|
||||||
onSelected: onSelected,
|
onSelected: onSelected,
|
||||||
).show(context);
|
).show(context);
|
||||||
},
|
},
|
||||||
icon: svg("home/add"),
|
icon: svg("home/add").padding(horizontal: 3, vertical: 3),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -63,23 +63,25 @@ class ViewSectionItem extends StatelessWidget {
|
|||||||
Widget _render(BuildContext context, bool onHover, ViewState state) {
|
Widget _render(BuildContext context, bool onHover, ViewState state) {
|
||||||
List<Widget> children = [
|
List<Widget> children = [
|
||||||
SizedBox(width: 16, height: 16, child: state.view.thumbnail()),
|
SizedBox(width: 16, height: 16, child: state.view.thumbnail()),
|
||||||
const HSpace(6),
|
const HSpace(2),
|
||||||
FlowyText.regular(state.view.name, fontSize: 12),
|
FlowyText.regular(state.view.name, fontSize: 12),
|
||||||
];
|
];
|
||||||
|
|
||||||
if (onHover || state.isEditing) {
|
if (onHover || state.isEditing) {
|
||||||
children.add(const Spacer());
|
children.add(const Spacer());
|
||||||
children.add(ViewDisclosureButton(
|
children.add(
|
||||||
onTap: () => context.read<ViewBloc>().add(const ViewEvent.setIsEditing(true)),
|
ViewDisclosureButton(
|
||||||
onSelected: (action) {
|
onTap: () => context.read<ViewBloc>().add(const ViewEvent.setIsEditing(true)),
|
||||||
context.read<ViewBloc>().add(const ViewEvent.setIsEditing(false));
|
onSelected: (action) {
|
||||||
_handleAction(context, action);
|
context.read<ViewBloc>().add(const ViewEvent.setIsEditing(false));
|
||||||
},
|
_handleAction(context, action);
|
||||||
));
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return SizedBox(
|
return SizedBox(
|
||||||
height: 24,
|
height: 26,
|
||||||
child: Row(children: children).padding(
|
child: Row(children: children).padding(
|
||||||
left: MenuAppSizes.expandedPadding,
|
left: MenuAppSizes.expandedPadding,
|
||||||
right: MenuAppSizes.expandedIconPadding,
|
right: MenuAppSizes.expandedIconPadding,
|
||||||
@ -91,11 +93,11 @@ class ViewSectionItem extends StatelessWidget {
|
|||||||
action.foldRight({}, (action, previous) {
|
action.foldRight({}, (action, previous) {
|
||||||
switch (action) {
|
switch (action) {
|
||||||
case ViewAction.rename:
|
case ViewAction.rename:
|
||||||
RenameDialog(
|
TextFieldDialog(
|
||||||
title: 'Rename',
|
title: 'Rename',
|
||||||
name: context.read<ViewBloc>().state.view.name,
|
value: context.read<ViewBloc>().state.view.name,
|
||||||
confirm: (newName) {
|
confirm: (newValue) {
|
||||||
context.read<ViewBloc>().add(ViewEvent.rename(newName));
|
context.read<ViewBloc>().add(ViewEvent.rename(newValue));
|
||||||
},
|
},
|
||||||
).show(context);
|
).show(context);
|
||||||
|
|
||||||
@ -126,7 +128,8 @@ class ViewDisclosureButton extends StatelessWidget {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return FlowyIconButton(
|
return FlowyIconButton(
|
||||||
width: 16,
|
iconPadding: const EdgeInsets.all(5),
|
||||||
|
width: 26,
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
onTap();
|
onTap();
|
||||||
ViewActionList(
|
ViewActionList(
|
||||||
|
@ -1,10 +1,8 @@
|
|||||||
import 'package:flutter/widgets.dart';
|
import 'package:flutter/widgets.dart';
|
||||||
import 'package:flutter_svg/flutter_svg.dart';
|
import 'package:flutter_svg/flutter_svg.dart';
|
||||||
|
|
||||||
Widget svg(String name) {
|
Widget svg(String name, {Color? color}) {
|
||||||
final Widget svg = SvgPicture.asset(
|
final Widget svg = SvgPicture.asset('assets/images/$name.svg', color: color);
|
||||||
'assets/images/$name.svg',
|
|
||||||
);
|
|
||||||
|
|
||||||
return svg;
|
return svg;
|
||||||
}
|
}
|
||||||
|
@ -6,7 +6,7 @@ class FlowyIconButton extends StatelessWidget {
|
|||||||
final double? height;
|
final double? height;
|
||||||
final Widget icon;
|
final Widget icon;
|
||||||
final VoidCallback? onPressed;
|
final VoidCallback? onPressed;
|
||||||
final Color? highlightColor;
|
final Color? fillColor;
|
||||||
final Color? hoverColor;
|
final Color? hoverColor;
|
||||||
final EdgeInsets iconPadding;
|
final EdgeInsets iconPadding;
|
||||||
|
|
||||||
@ -15,14 +15,26 @@ class FlowyIconButton extends StatelessWidget {
|
|||||||
this.height,
|
this.height,
|
||||||
this.onPressed,
|
this.onPressed,
|
||||||
this.width = 30,
|
this.width = 30,
|
||||||
this.highlightColor = Colors.transparent,
|
this.fillColor = Colors.transparent,
|
||||||
this.hoverColor = Colors.transparent,
|
this.hoverColor = Colors.transparent,
|
||||||
this.iconPadding = const EdgeInsets.symmetric(horizontal: 6, vertical: 6),
|
this.iconPadding = EdgeInsets.zero,
|
||||||
required this.icon,
|
required this.icon,
|
||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
Widget child = icon;
|
||||||
|
|
||||||
|
// if (onPressed == null) {
|
||||||
|
// child = ColorFiltered(
|
||||||
|
// colorFilter: ColorFilter.mode(
|
||||||
|
// Colors.grey,
|
||||||
|
// BlendMode.saturation,
|
||||||
|
// ),
|
||||||
|
// child: child,
|
||||||
|
// );
|
||||||
|
// }
|
||||||
|
|
||||||
return ConstrainedBox(
|
return ConstrainedBox(
|
||||||
constraints: BoxConstraints.tightFor(width: width, height: width),
|
constraints: BoxConstraints.tightFor(width: width, height: width),
|
||||||
child: RawMaterialButton(
|
child: RawMaterialButton(
|
||||||
@ -30,7 +42,7 @@ class FlowyIconButton extends StatelessWidget {
|
|||||||
hoverElevation: 0,
|
hoverElevation: 0,
|
||||||
highlightElevation: 0,
|
highlightElevation: 0,
|
||||||
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(2)),
|
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(2)),
|
||||||
fillColor: highlightColor,
|
fillColor: fillColor,
|
||||||
hoverColor: hoverColor,
|
hoverColor: hoverColor,
|
||||||
focusColor: Colors.transparent,
|
focusColor: Colors.transparent,
|
||||||
splashColor: Colors.transparent,
|
splashColor: Colors.transparent,
|
||||||
@ -39,7 +51,7 @@ class FlowyIconButton extends StatelessWidget {
|
|||||||
onPressed: onPressed,
|
onPressed: onPressed,
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: iconPadding,
|
padding: iconPadding,
|
||||||
child: SizedBox.fromSize(child: icon, size: Size(width, width)),
|
child: SizedBox.fromSize(child: child, size: Size(width, width)),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
Reference in New Issue
Block a user