瀏覽代碼

[flutter]: modify view's name in topbar

appflowy 3 年之前
父節點
當前提交
4f41c8d3e5

+ 24 - 36
app_flowy/lib/workspace/presentation/home/navigation.dart

@@ -61,14 +61,22 @@ class FlowyNavigation extends StatelessWidget {
         );
       },
       update: (_, notifier, controller) => controller!..update(notifier),
-      child: Row(children: [
-        Selector<NavigationNotifier, PublishNotifier<bool>>(
-            selector: (context, notifier) => notifier.collapasedNotifier,
-            builder: (ctx, collapsedNotifier, child) => _renderCollapse(ctx, collapsedNotifier)),
-        Selector<NavigationNotifier, List<NavigationItem>>(
+      child: Expanded(
+        child: Row(children: [
+          Selector<NavigationNotifier, PublishNotifier<bool>>(
+              selector: (context, notifier) => notifier.collapasedNotifier,
+              builder: (ctx, collapsedNotifier, child) => _renderCollapse(ctx, collapsedNotifier)),
+          Selector<NavigationNotifier, List<NavigationItem>>(
             selector: (context, notifier) => notifier.navigationItems,
-            builder: (ctx, items, child) => Row(children: _renderNavigationItems(items))),
-      ]),
+            builder: (ctx, items, child) => Expanded(
+              child: Wrap(
+                children: _renderNavigationItems(items),
+                crossAxisAlignment: WrapCrossAlignment.start,
+              ),
+            ),
+          ),
+        ]),
+      ),
     );
   }
 
@@ -106,7 +114,13 @@ class FlowyNavigation extends StatelessWidget {
     Widget last = NaviItemWidget(newItems.removeLast());
 
     List<Widget> widgets = List.empty(growable: true);
-    widgets.addAll(newItems.map((item) => NaviItemDivider(child: NaviItemWidget(item))).toList());
+    // widgets.addAll(newItems.map((item) => NaviItemDivider(child: NaviItemWidget(item))).toList());
+
+    for (final item in newItems) {
+      widgets.add(NaviItemWidget(item));
+      widgets.add(const Text('/'));
+    }
+
     widgets.add(last);
 
     return widgets;
@@ -129,39 +143,13 @@ class FlowyNavigation extends StatelessWidget {
   }
 }
 
-class IconNaviItemWidget extends StatelessWidget {
-  final NavigationItem item;
-  const IconNaviItemWidget(this.item, {Key? key}) : super(key: key);
-
-  @override
-  Widget build(BuildContext context) {
-    return SizedBox(
-      height: 24,
-      child: InkWell(
-        child: item.leftBarItem,
-        onTap: () {
-          debugPrint('show app document');
-        },
-      ).padding(horizontal: 8, vertical: 2),
-    );
-  }
-}
-
 class NaviItemWidget extends StatelessWidget {
   final NavigationItem item;
   const NaviItemWidget(this.item, {Key? key}) : super(key: key);
 
   @override
   Widget build(BuildContext context) {
-    return SizedBox(
-      height: 24,
-      child: InkWell(
-        child: item.leftBarItem,
-        onTap: () {
-          debugPrint('show app document');
-        },
-      ).padding(horizontal: 8, vertical: 2),
-    );
+    return item.leftBarItem.padding(horizontal: 2, vertical: 2);
   }
 }
 
@@ -172,7 +160,7 @@ class NaviItemDivider extends StatelessWidget {
   @override
   Widget build(BuildContext context) {
     return Row(
-      children: [child, const Text('/').padding(horizontal: 2)],
+      children: [child, const Text('/')],
     );
   }
 }

+ 75 - 2
app_flowy/lib/workspace/presentation/stack_page/doc/doc_stack_page.dart

@@ -3,12 +3,15 @@ import 'package:app_flowy/workspace/application/doc/share_bloc.dart';
 import 'package:app_flowy/workspace/domain/i_view.dart';
 import 'package:app_flowy/workspace/domain/page_stack/page_stack.dart';
 import 'package:app_flowy/workspace/domain/view_ext.dart';
+import 'package:app_flowy/workspace/infrastructure/repos/view_repo.dart';
 import 'package:app_flowy/workspace/presentation/widgets/dialogs.dart';
 import 'package:app_flowy/workspace/presentation/widgets/pop_up_action.dart';
 import 'package:flowy_infra/size.dart';
+import 'package:flowy_infra/theme.dart';
 import 'package:flowy_infra_ui/flowy_infra_ui.dart';
 import 'package:flowy_infra_ui/style_widget/text.dart';
 import 'package:flowy_infra_ui/widget/rounded_button.dart';
+import 'package:flowy_infra_ui/widget/rounded_input_field.dart';
 import 'package:flowy_log/flowy_log.dart';
 import 'package:flowy_sdk/protobuf/flowy-workspace-infra/export.pb.dart';
 import 'package:flowy_sdk/protobuf/flowy-workspace-infra/view_create.pb.dart';
@@ -40,7 +43,7 @@ class DocStackContext extends HomeStackContext<String, ShareActionWrapper> {
   }
 
   @override
-  Widget get leftBarItem => FlowyText.medium(_view.name, fontSize: 12);
+  Widget get leftBarItem => DocLeftBarItem(view: _view);
 
   @override
   Widget? get rightBarItem => DocShareButton(view: _view);
@@ -65,7 +68,9 @@ class DocStackContext extends HomeStackContext<String, ShareActionWrapper> {
   //     }).toList();
 
   List<NavigationItem> _makeNavigationItems() {
-    return [this];
+    return [
+      this,
+    ];
   }
 
   @override
@@ -74,6 +79,74 @@ class DocStackContext extends HomeStackContext<String, ShareActionWrapper> {
   }
 }
 
+class DocLeftBarItem extends StatefulWidget {
+  final View view;
+
+  const DocLeftBarItem({required this.view, Key? key}) : super(key: key);
+
+  @override
+  State<DocLeftBarItem> createState() => _DocLeftBarItemState();
+}
+
+class _DocLeftBarItemState extends State<DocLeftBarItem> {
+  final _controller = TextEditingController();
+  final _focusNode = FocusNode();
+  late ViewRepository repo;
+
+  @override
+  void initState() {
+    repo = ViewRepository(view: widget.view);
+    _focusNode.addListener(_handleFocusChanged);
+
+    super.initState();
+  }
+
+  @override
+  void dispose() {
+    _controller.dispose();
+    _focusNode.dispose();
+    super.dispose();
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    _controller.text = widget.view.name;
+
+    final theme = context.watch<AppTheme>();
+    return IntrinsicWidth(
+      child: TextField(
+        controller: _controller,
+        focusNode: _focusNode,
+        scrollPadding: EdgeInsets.zero,
+        decoration: const InputDecoration(
+          contentPadding: EdgeInsets.zero,
+          border: InputBorder.none,
+          isDense: true,
+        ),
+        style: TextStyle(
+          color: theme.shader1,
+          fontSize: 14,
+          fontWeight: FontWeight.w500,
+          overflow: TextOverflow.ellipsis,
+        ),
+        // cursorColor: widget.cursorColor,
+        // obscureText: widget.enableObscure,
+      ),
+    );
+  }
+
+  void _handleFocusChanged() {
+    if (_controller.text.isEmpty) {
+      _controller.text = widget.view.name;
+      return;
+    }
+
+    if (_controller.text != widget.view.name) {
+      repo.updateView(name: _controller.text);
+    }
+  }
+}
+
 class DocShareButton extends StatelessWidget {
   final View view;
   DocShareButton({Key? key, required this.view}) : super(key: ValueKey(view.id));

+ 1 - 1
app_flowy/lib/workspace/presentation/widgets/home_top_bar.dart

@@ -21,7 +21,7 @@ class HomeTopBar extends StatelessWidget {
         crossAxisAlignment: CrossAxisAlignment.center,
         children: [
           const FlowyNavigation(),
-          const Spacer(),
+          const HSpace(16),
           ChangeNotifierProvider.value(
             value: Provider.of<HomeStackNotifier>(context, listen: false),
             child: Consumer(

+ 10 - 20
app_flowy/packages/flowy_infra_ui/lib/style_widget/text_input.dart

@@ -10,8 +10,7 @@ import 'package:provider/provider.dart';
 import 'package:textstyle_extensions/textstyle_extensions.dart';
 
 class FlowyFormTextInput extends StatelessWidget {
-  static EdgeInsets kDefaultTextInputPadding =
-      EdgeInsets.only(bottom: Insets.sm, top: 4);
+  static EdgeInsets kDefaultTextInputPadding = EdgeInsets.only(bottom: Insets.sm, top: 4);
 
   final String? label;
   final bool? autoFocus;
@@ -61,8 +60,7 @@ class FlowyFormTextInput extends StatelessWidget {
       inputDecoration: InputDecoration(
         isDense: true,
         contentPadding: contentPadding ?? kDefaultTextInputPadding,
-        border: const ThinUnderlineBorder(
-            borderSide: BorderSide(width: 5, color: Colors.red)),
+        border: const ThinUnderlineBorder(borderSide: BorderSide(width: 5, color: Colors.red)),
         //focusedBorder: UnderlineInputBorder(borderSide: BorderSide(width: .5, color: Colors.red)),
         hintText: hintText,
       ),
@@ -143,8 +141,7 @@ class StyledSearchTextInputState extends State<StyledSearchTextInput> {
 
   @override
   void initState() {
-    _controller =
-        widget.controller ?? TextEditingController(text: widget.initialValue);
+    _controller = widget.controller ?? TextEditingController(text: widget.initialValue);
     _focusNode = FocusNode(
       debugLabel: widget.label ?? '',
       onKey: (FocusNode node, RawKeyEvent evt) {
@@ -160,8 +157,7 @@ class StyledSearchTextInputState extends State<StyledSearchTextInput> {
       canRequestFocus: true,
     );
     // Listen for focus out events
-    _focusNode
-        .addListener(() => widget.onFocusChanged?.call(_focusNode.hasFocus));
+    _focusNode.addListener(() => widget.onFocusChanged?.call(_focusNode.hasFocus));
     widget.onFocusCreated?.call(_focusNode);
     if (widget.autoFocus ?? false) {
       scheduleMicrotask(() => _focusNode.requestFocus());
@@ -210,8 +206,7 @@ class StyledSearchTextInputState extends State<StyledSearchTextInput> {
             InputDecoration(
                 prefixIcon: widget.prefixIcon,
                 suffixIcon: widget.suffixIcon,
-                contentPadding:
-                    widget.contentPadding ?? EdgeInsets.all(Insets.m),
+                contentPadding: widget.contentPadding ?? EdgeInsets.all(Insets.m),
                 border: const OutlineInputBorder(borderSide: BorderSide.none),
                 isDense: true,
                 icon: widget.icon == null ? null : Icon(widget.icon),
@@ -259,8 +254,7 @@ class ThinUnderlineBorder extends InputBorder {
   bool get isOutline => false;
 
   @override
-  UnderlineInputBorder copyWith(
-      {BorderSide? borderSide, BorderRadius? borderRadius}) {
+  UnderlineInputBorder copyWith({BorderSide? borderSide, BorderRadius? borderRadius}) {
     return UnderlineInputBorder(
       borderSide: borderSide ?? this.borderSide,
       borderRadius: borderRadius ?? this.borderRadius,
@@ -280,8 +274,7 @@ class ThinUnderlineBorder extends InputBorder {
   @override
   Path getInnerPath(Rect rect, {TextDirection? textDirection}) {
     return Path()
-      ..addRect(Rect.fromLTWH(rect.left, rect.top, rect.width,
-          math.max(0.0, rect.height - borderSide.width)));
+      ..addRect(Rect.fromLTWH(rect.left, rect.top, rect.width, math.max(0.0, rect.height - borderSide.width)));
   }
 
   @override
@@ -292,8 +285,7 @@ class ThinUnderlineBorder extends InputBorder {
   @override
   ShapeBorder? lerpFrom(ShapeBorder? a, double t) {
     if (a is UnderlineInputBorder) {
-      final newBorderRadius =
-          BorderRadius.lerp(a.borderRadius, borderRadius, t);
+      final newBorderRadius = BorderRadius.lerp(a.borderRadius, borderRadius, t);
 
       if (newBorderRadius != null) {
         return UnderlineInputBorder(
@@ -308,8 +300,7 @@ class ThinUnderlineBorder extends InputBorder {
   @override
   ShapeBorder? lerpTo(ShapeBorder? b, double t) {
     if (b is UnderlineInputBorder) {
-      final newBorderRadius =
-          BorderRadius.lerp(b.borderRadius, borderRadius, t);
+      final newBorderRadius = BorderRadius.lerp(b.borderRadius, borderRadius, t);
       if (newBorderRadius != null) {
         return UnderlineInputBorder(
           borderSide: BorderSide.lerp(borderSide, b.borderSide, t),
@@ -335,8 +326,7 @@ class ThinUnderlineBorder extends InputBorder {
     double gapPercentage = 0.0,
     TextDirection? textDirection,
   }) {
-    if (borderRadius.bottomLeft != Radius.zero ||
-        borderRadius.bottomRight != Radius.zero) {
+    if (borderRadius.bottomLeft != Radius.zero || borderRadius.bottomRight != Radius.zero) {
       canvas.clipPath(getOuterPath(rect, textDirection: textDirection));
     }
     canvas.drawLine(rect.bottomLeft, rect.bottomRight, borderSide.toPaint());

+ 4 - 1
app_flowy/packages/flowy_infra_ui/lib/widget/rounded_input_field.dart

@@ -17,12 +17,15 @@ class RoundedInputField extends StatefulWidget {
   final String errorText;
   final TextStyle style;
   final ValueChanged<String>? onChanged;
+  final String? initialValue;
   late bool enableObscure;
   var _text = "";
 
   RoundedInputField({
     Key? key,
     this.hintText,
+    this.errorText = "",
+    this.initialValue,
     this.icon,
     this.obscureText = false,
     this.obscureIcon,
@@ -32,7 +35,6 @@ class RoundedInputField extends StatefulWidget {
     this.highlightBorderColor = Colors.transparent,
     this.cursorColor = Colors.black,
     this.style = const TextStyle(fontSize: 20, fontWeight: FontWeight.w500),
-    this.errorText = "",
   }) : super(key: key) {
     enableObscure = obscureText;
   }
@@ -62,6 +64,7 @@ class _RoundedInputFieldState extends State<RoundedInputField> {
         borderRadius: Corners.s10Border,
         borderColor: borderColor,
         child: TextFormField(
+          initialValue: widget.initialValue,
           onChanged: (value) {
             widget._text = value;
             if (widget.onChanged != null) {