浏览代码

fix: can't input url in Grid (#2737)

* fix: launch url in url cell

* fix: can't input url in Grid

* feat: support selecting or deselecting all items in export page

* fix: remove the circle shape

* fix: light mode toolbar color

* chore: update language and adjust the launch page
Lucas.Xu 1 年之前
父节点
当前提交
02b7149514

+ 7 - 4
frontend/appflowy_flutter/assets/translations/en.json

@@ -196,6 +196,8 @@
       "restartApp": "Please restart app for the changes to take effect.",
       "restartApp": "Please restart app for the changes to take effect.",
       "exportDatabase": "Export database",
       "exportDatabase": "Export database",
       "selectFiles": "Select the files that need to be export",
       "selectFiles": "Select the files that need to be export",
+      "selectAll": "Select all",
+      "deselectAll": "Deselect all",
       "createNewFolder": "Create a new folder",
       "createNewFolder": "Create a new folder",
       "createNewFolderDesc": "Tell us where you want to store your data",
       "createNewFolderDesc": "Tell us where you want to store your data",
       "defineWhereYourDataIsStored": "Define where your data is stored",
       "defineWhereYourDataIsStored": "Define where your data is stored",
@@ -211,12 +213,13 @@
       "folderPath": "Path to store your folder",
       "folderPath": "Path to store your folder",
       "locationCannotBeEmpty": "Path cannot be empty",
       "locationCannotBeEmpty": "Path cannot be empty",
       "pathCopiedSnackbar": "File storage path copied to clipboard!",
       "pathCopiedSnackbar": "File storage path copied to clipboard!",
-      "changeLocationTooltips": "Change the files read the data directory",
+      "changeLocationTooltips": "Change the data directory",
       "change": "Change",
       "change": "Change",
-      "openLocationTooltips": "Open the files read the data directory",
-      "recoverLocationTooltips": "Recover the files read the data directory",
+      "openLocationTooltips": "Open another data directory",
+      "recoverLocationTooltips": "Reset to AppFlowy's default data directory",
       "exportFileSuccess": "Export file successfully!",
       "exportFileSuccess": "Export file successfully!",
-      "exportFileFail": "Export file failed!"
+      "exportFileFail": "Export file failed!",
+      "export": "Export"
     },
     },
     "user": {
     "user": {
       "name": "Name",
       "name": "Name",

+ 57 - 64
frontend/appflowy_flutter/lib/plugins/database_view/widgets/row/cells/url_cell/url_cell.dart

@@ -10,7 +10,7 @@ import 'package:flowy_infra_ui/flowy_infra_ui.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter/services.dart';
 import 'package:flutter/services.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';
-import 'package:url_launcher/url_launcher.dart';
+import 'package:url_launcher/url_launcher_string.dart';
 import '../../../../grid/presentation/layout/sizes.dart';
 import '../../../../grid/presentation/layout/sizes.dart';
 import '../../accessory/cell_accessory.dart';
 import '../../accessory/cell_accessory.dart';
 import '../../cell_builder.dart';
 import '../../cell_builder.dart';
@@ -36,13 +36,11 @@ enum GridURLCellAccessoryType {
 }
 }
 
 
 class GridURLCell extends GridCellWidget {
 class GridURLCell extends GridCellWidget {
-  final CellControllerBuilder cellControllerBuilder;
-  late final GridURLCellStyle? cellStyle;
   GridURLCell({
   GridURLCell({
+    super.key,
     required this.cellControllerBuilder,
     required this.cellControllerBuilder,
     GridCellStyle? style,
     GridCellStyle? style,
-    Key? key,
-  }) : super(key: key) {
+  }) {
     if (style != null) {
     if (style != null) {
       cellStyle = (style as GridURLCellStyle);
       cellStyle = (style as GridURLCellStyle);
     } else {
     } else {
@@ -50,6 +48,9 @@ class GridURLCell extends GridCellWidget {
     }
     }
   }
   }
 
 
+  final CellControllerBuilder cellControllerBuilder;
+  late final GridURLCellStyle? cellStyle;
+
   @override
   @override
   GridCellState<GridURLCell> createState() => _GridURLCellState();
   GridCellState<GridURLCell> createState() => _GridURLCellState();
 
 
@@ -104,28 +105,35 @@ class GridURLCell extends GridCellWidget {
       };
       };
 }
 }
 
 
-class _GridURLCellState extends GridCellState<GridURLCell> {
+class _GridURLCellState extends GridFocusNodeCellState<GridURLCell> {
   final _popoverController = PopoverController();
   final _popoverController = PopoverController();
-  late URLCellBloc _cellBloc;
-  late TextEditingController _controller;
-  late FocusNode _focusNode;
+  late final URLCellBloc _cellBloc;
+  late final TextEditingController _controller;
 
 
   @override
   @override
   void initState() {
   void initState() {
+    super.initState();
+
     final cellController =
     final cellController =
         widget.cellControllerBuilder.build() as URLCellController;
         widget.cellControllerBuilder.build() as URLCellController;
-    _cellBloc = URLCellBloc(cellController: cellController);
-    _cellBloc.add(const URLCellEvent.initial());
+    _cellBloc = URLCellBloc(cellController: cellController)
+      ..add(const URLCellEvent.initial());
     _controller = TextEditingController(text: _cellBloc.state.content);
     _controller = TextEditingController(text: _cellBloc.state.content);
-    _focusNode = FocusNode();
-    super.initState();
+  }
+
+  @override
+  Future<void> dispose() async {
+    _cellBloc.close();
+    super.dispose();
   }
   }
 
 
   @override
   @override
   Widget build(BuildContext context) {
   Widget build(BuildContext context) {
     return BlocProvider.value(
     return BlocProvider.value(
       value: _cellBloc,
       value: _cellBloc,
-      child: BlocBuilder<URLCellBloc, URLCellState>(
+      child: BlocConsumer<URLCellBloc, URLCellState>(
+        listenWhen: (previous, current) => previous.content != current.content,
+        listener: (context, state) => _controller.text = state.content,
         builder: (context, state) {
         builder: (context, state) {
           final urlEditor = Padding(
           final urlEditor = Padding(
             padding: EdgeInsets.only(
             padding: EdgeInsets.only(
@@ -134,7 +142,7 @@ class _GridURLCellState extends GridCellState<GridURLCell> {
             ),
             ),
             child: TextField(
             child: TextField(
               controller: _controller,
               controller: _controller,
-              focusNode: _focusNode,
+              focusNode: focusNode,
               maxLines: 1,
               maxLines: 1,
               style: (widget.cellStyle?.textStyle ??
               style: (widget.cellStyle?.textStyle ??
                       Theme.of(context).textTheme.bodyMedium)
                       Theme.of(context).textTheme.bodyMedium)
@@ -143,8 +151,6 @@ class _GridURLCellState extends GridCellState<GridURLCell> {
                 decoration: TextDecoration.underline,
                 decoration: TextDecoration.underline,
               ),
               ),
               autofocus: false,
               autofocus: false,
-              onEditingComplete: focusChanged,
-              onSubmitted: (value) => focusChanged(isUrlSubmitted: true),
               decoration: InputDecoration(
               decoration: InputDecoration(
                 contentPadding: EdgeInsets.only(
                 contentPadding: EdgeInsets.only(
                   top: GridSize.cellContentInsets.top,
                   top: GridSize.cellContentInsets.top,
@@ -162,24 +168,10 @@ class _GridURLCellState extends GridCellState<GridURLCell> {
     );
     );
   }
   }
 
 
-  void focusChanged({
-    bool isUrlSubmitted = false,
-  }) {
-    if (mounted) {
-      if (_cellBloc.isClosed == false &&
-          _controller.text != _cellBloc.state.content) {
-        _cellBloc.add(URLCellEvent.updateURL(_controller.text));
-      }
-      if (isUrlSubmitted) {
-        _focusNode.unfocus();
-      }
-    }
-  }
-
   @override
   @override
-  Future<void> dispose() async {
-    _cellBloc.close();
-    super.dispose();
+  Future<void> focusChanged() async {
+    _cellBloc.add(URLCellEvent.updateURL(_controller.text));
+    return super.focusChanged();
   }
   }
 
 
   @override
   @override
@@ -192,19 +184,17 @@ class _GridURLCellState extends GridCellState<GridURLCell> {
   String? onCopy() => _cellBloc.state.content;
   String? onCopy() => _cellBloc.state.content;
 
 
   @override
   @override
-  void onInsert(String value) {
-    _cellBloc.add(URLCellEvent.updateURL(value));
-  }
+  void onInsert(String value) => _cellBloc.add(URLCellEvent.updateURL(value));
 }
 }
 
 
 class _EditURLAccessory extends StatefulWidget {
 class _EditURLAccessory extends StatefulWidget {
-  final CellControllerBuilder cellControllerBuilder;
-  final BuildContext anchorContext;
   const _EditURLAccessory({
   const _EditURLAccessory({
     required this.cellControllerBuilder,
     required this.cellControllerBuilder,
     required this.anchorContext,
     required this.anchorContext,
-    Key? key,
-  }) : super(key: key);
+  });
+
+  final CellControllerBuilder cellControllerBuilder;
+  final BuildContext anchorContext;
 
 
   @override
   @override
   State<StatefulWidget> createState() => _EditURLAccessoryState();
   State<StatefulWidget> createState() => _EditURLAccessoryState();
@@ -212,20 +202,14 @@ class _EditURLAccessory extends StatefulWidget {
 
 
 class _EditURLAccessoryState extends State<_EditURLAccessory>
 class _EditURLAccessoryState extends State<_EditURLAccessory>
     with GridCellAccessoryState {
     with GridCellAccessoryState {
-  late PopoverController _popoverController;
-
-  @override
-  void initState() {
-    _popoverController = PopoverController();
-    super.initState();
-  }
+  final popoverController = PopoverController();
 
 
   @override
   @override
   Widget build(BuildContext context) {
   Widget build(BuildContext context) {
     return AppFlowyPopover(
     return AppFlowyPopover(
       margin: EdgeInsets.zero,
       margin: EdgeInsets.zero,
       constraints: BoxConstraints.loose(const Size(300, 160)),
       constraints: BoxConstraints.loose(const Size(300, 160)),
-      controller: _popoverController,
+      controller: popoverController,
       direction: PopoverDirection.bottomWithLeftAligned,
       direction: PopoverDirection.bottomWithLeftAligned,
       offset: const Offset(0, 8),
       offset: const Offset(0, 8),
       child: svgWidget(
       child: svgWidget(
@@ -236,7 +220,7 @@ class _EditURLAccessoryState extends State<_EditURLAccessory>
         return URLEditorPopover(
         return URLEditorPopover(
           cellController:
           cellController:
               widget.cellControllerBuilder.build() as URLCellController,
               widget.cellControllerBuilder.build() as URLCellController,
-          onExit: () => _popoverController.close(),
+          onExit: () => popoverController.close(),
         );
         );
       },
       },
     );
     );
@@ -244,14 +228,17 @@ class _EditURLAccessoryState extends State<_EditURLAccessory>
 
 
   @override
   @override
   void onTap() {
   void onTap() {
-    _popoverController.show();
+    popoverController.show();
   }
   }
 }
 }
 
 
 class _CopyURLAccessory extends StatefulWidget {
 class _CopyURLAccessory extends StatefulWidget {
+  const _CopyURLAccessory({
+    super.key,
+    required this.cellContext,
+  });
+
   final URLCellController cellContext;
   final URLCellController cellContext;
-  const _CopyURLAccessory({required this.cellContext, Key? key})
-      : super(key: key);
 
 
   @override
   @override
   State<StatefulWidget> createState() => _CopyURLAccessoryState();
   State<StatefulWidget> createState() => _CopyURLAccessoryState();
@@ -270,16 +257,22 @@ class _CopyURLAccessoryState extends State<_CopyURLAccessory>
   @override
   @override
   void onTap() {
   void onTap() {
     final content =
     final content =
-        widget.cellContext.getCellData(loadIfNotExist: false)?.content ?? "";
+        widget.cellContext.getCellData(loadIfNotExist: false)?.content;
+    if (content == null) {
+      return;
+    }
     Clipboard.setData(ClipboardData(text: content));
     Clipboard.setData(ClipboardData(text: content));
     showMessageToast(LocaleKeys.grid_row_copyProperty.tr());
     showMessageToast(LocaleKeys.grid_row_copyProperty.tr());
   }
   }
 }
 }
 
 
 class _VisitURLAccessory extends StatefulWidget {
 class _VisitURLAccessory extends StatefulWidget {
+  const _VisitURLAccessory({
+    super.key,
+    required this.cellContext,
+  });
+
   final URLCellController cellContext;
   final URLCellController cellContext;
-  const _VisitURLAccessory({required this.cellContext, Key? key})
-      : super(key: key);
 
 
   @override
   @override
   State<StatefulWidget> createState() => _VisitURLAccessoryState();
   State<StatefulWidget> createState() => _VisitURLAccessoryState();
@@ -297,14 +290,14 @@ class _VisitURLAccessoryState extends State<_VisitURLAccessory>
 
 
   @override
   @override
   void onTap() {
   void onTap() {
-    var content =
-        widget.cellContext.getCellData(loadIfNotExist: false)?.content ?? "";
-    if (!content.startsWith('http://') && !content.startsWith('https://')) {
-      content = 'http://$content';
-    }
-    final uri = Uri.parse(content);
-    if (content.isNotEmpty) {
-      canLaunchUrl(uri).then((value) => launchUrl(uri));
+    final content =
+        widget.cellContext.getCellData(loadIfNotExist: false)?.content;
+    if (content == null) {
+      return;
     }
     }
+    final shouldAddScheme =
+        !['http', 'https'].any((pattern) => content.startsWith(pattern));
+    final url = shouldAddScheme ? 'http://$content' : content;
+    canLaunchUrlString(url).then((value) => launchUrlString(url));
   }
   }
 }
 }

+ 18 - 16
frontend/appflowy_flutter/lib/plugins/document/presentation/editor_page.dart

@@ -57,24 +57,24 @@ class _AppFlowyEditorPageState extends State<AppFlowyEditorPage> {
 
 
   late final Map<String, BlockComponentBuilder> blockComponentBuilders =
   late final Map<String, BlockComponentBuilder> blockComponentBuilders =
       _customAppFlowyBlockComponentBuilders();
       _customAppFlowyBlockComponentBuilders();
-  late final List<CharacterShortcutEvent> characterShortcutEvents = [
-    // code block
-    ...codeBlockCharacterEvents,
+  List<CharacterShortcutEvent> get characterShortcutEvents => [
+        // code block
+        ...codeBlockCharacterEvents,
 
 
-    // toggle list
-    // formatGreaterToToggleList,
+        // toggle list
+        // formatGreaterToToggleList,
 
 
-    // customize the slash menu command
-    customSlashCommand(
-      slashMenuItems,
-      style: styleCustomizer.selectionMenuStyleBuilder(),
-    ),
+        // customize the slash menu command
+        customSlashCommand(
+          slashMenuItems,
+          style: styleCustomizer.selectionMenuStyleBuilder(),
+        ),
 
 
-    ...standardCharacterShortcutEvents
-      ..removeWhere(
-        (element) => element == slashCommand,
-      ), // remove the default slash command.
-  ];
+        ...standardCharacterShortcutEvents
+          ..removeWhere(
+            (element) => element == slashCommand,
+          ), // remove the default slash command.
+      ];
 
 
   late final showSlashMenu = customSlashCommand(
   late final showSlashMenu = customSlashCommand(
     slashMenuItems,
     slashMenuItems,
@@ -82,7 +82,9 @@ class _AppFlowyEditorPageState extends State<AppFlowyEditorPage> {
     style: styleCustomizer.selectionMenuStyleBuilder(),
     style: styleCustomizer.selectionMenuStyleBuilder(),
   ).handler;
   ).handler;
 
 
-  late final styleCustomizer = EditorStyleCustomizer(context: context);
+  EditorStyleCustomizer get styleCustomizer => EditorStyleCustomizer(
+        context: context,
+      );
   DocumentBloc get documentBloc => context.read<DocumentBloc>();
   DocumentBloc get documentBloc => context.read<DocumentBloc>();
 
 
   @override
   @override

+ 1 - 1
frontend/appflowy_flutter/lib/plugins/document/presentation/editor_style.dart

@@ -140,7 +140,7 @@ class EditorStyleCustomizer {
   FloatingToolbarStyle floatingToolbarStyleBuilder() {
   FloatingToolbarStyle floatingToolbarStyleBuilder() {
     final theme = Theme.of(context);
     final theme = Theme.of(context);
     return FloatingToolbarStyle(
     return FloatingToolbarStyle(
-      backgroundColor: theme.cardColor,
+      backgroundColor: theme.colorScheme.onTertiary,
     );
     );
   }
   }
 }
 }

+ 7 - 4
frontend/appflowy_flutter/lib/user/presentation/folder/folder_widget.dart

@@ -218,10 +218,13 @@ Widget _buildTextButton(
   String title,
   String title,
   VoidCallback onPressed,
   VoidCallback onPressed,
 ) {
 ) {
-  return SecondaryTextButton(
-    title,
-    mode: SecondaryTextButtonMode.small,
-    onPressed: onPressed,
+  return SizedBox(
+    width: 60,
+    child: SecondaryTextButton(
+      title,
+      mode: SecondaryTextButtonMode.small,
+      onPressed: onPressed,
+    ),
   );
   );
 }
 }
 
 

+ 6 - 3
frontend/appflowy_flutter/lib/user/presentation/skip_log_in_screen.dart

@@ -53,6 +53,7 @@ class _SkipLogInScreenState extends State<SkipLogInScreen> {
       mainAxisAlignment: MainAxisAlignment.center,
       mainAxisAlignment: MainAxisAlignment.center,
       crossAxisAlignment: CrossAxisAlignment.center,
       crossAxisAlignment: CrossAxisAlignment.center,
       children: [
       children: [
+        const Spacer(),
         FlowyLogoTitle(
         FlowyLogoTitle(
           title: LocaleKeys.welcomeText.tr(),
           title: LocaleKeys.welcomeText.tr(),
           logoSize: const Size.square(40),
           logoSize: const Size.square(40),
@@ -68,8 +69,6 @@ class _SkipLogInScreenState extends State<SkipLogInScreen> {
           },
           },
         ),
         ),
         const VSpace(32),
         const VSpace(32),
-        _buildSubscribeButtons(context),
-        const VSpace(32),
         SizedBox(
         SizedBox(
           width: MediaQuery.of(context).size.width * 0.5,
           width: MediaQuery.of(context).size.width * 0.5,
           child: FolderWidget(
           child: FolderWidget(
@@ -78,7 +77,10 @@ class _SkipLogInScreenState extends State<SkipLogInScreen> {
             },
             },
           ),
           ),
         ),
         ),
-        const VSpace(64),
+        const Spacer(),
+        const VSpace(48),
+        _buildSubscribeButtons(context),
+        const VSpace(24),
       ],
       ],
     );
     );
   }
   }
@@ -182,6 +184,7 @@ class GoButton extends StatelessWidget {
         maxWidth: 340,
         maxWidth: 340,
         maxHeight: 48,
         maxHeight: 48,
       ),
       ),
+      radius: BorderRadius.circular(12),
       mainAxisAlignment: MainAxisAlignment.center,
       mainAxisAlignment: MainAxisAlignment.center,
       fontSize: FontSizes.s14,
       fontSize: FontSizes.s14,
       fontFamily: GoogleFonts.poppins(fontWeight: FontWeight.w500).fontFamily,
       fontFamily: GoogleFonts.poppins(fontWeight: FontWeight.w500).fontFamily,

+ 15 - 3
frontend/appflowy_flutter/lib/workspace/application/settings/settings_file_exporter_cubit.dart

@@ -55,6 +55,18 @@ class SettingsFileExporterCubit extends Cubit<SettingsFileExportState> {
     required List<ViewPB> views,
     required List<ViewPB> views,
   }) : super(SettingsFileExportState(views: views));
   }) : super(SettingsFileExportState(views: views));
 
 
+  void selectOrDeselectAllItems() {
+    final List<List<bool>> selectedItems = state.selectedItems;
+    final isSelectAll =
+        selectedItems.expand((element) => element).every((element) => element);
+    for (var i = 0; i < selectedItems.length; i++) {
+      for (var j = 0; j < selectedItems[i].length; j++) {
+        selectedItems[i][j] = !isSelectAll;
+      }
+    }
+    emit(state.copyWith(selectedItems: selectedItems));
+  }
+
   void selectOrDeselectItem(int outerIndex, int innerIndex) {
   void selectOrDeselectItem(int outerIndex, int innerIndex) {
     final selectedItems = state.selectedItems;
     final selectedItems = state.selectedItems;
     selectedItems[outerIndex][innerIndex] =
     selectedItems[outerIndex][innerIndex] =
@@ -69,7 +81,7 @@ class SettingsFileExporterCubit extends Cubit<SettingsFileExportState> {
   }
   }
 
 
   Map<String, List<String>> fetchSelectedPages() {
   Map<String, List<String>> fetchSelectedPages() {
-    final apps = state.views;
+    final views = state.views;
     final selectedItems = state.selectedItems;
     final selectedItems = state.selectedItems;
     final Map<String, List<String>> result = {};
     final Map<String, List<String>> result = {};
     for (var i = 0; i < selectedItems.length; i++) {
     for (var i = 0; i < selectedItems.length; i++) {
@@ -77,11 +89,11 @@ class SettingsFileExporterCubit extends Cubit<SettingsFileExportState> {
       final ids = <String>[];
       final ids = <String>[];
       for (var j = 0; j < selectedItem.length; j++) {
       for (var j = 0; j < selectedItem.length; j++) {
         if (selectedItem[j]) {
         if (selectedItem[j]) {
-          ids.add(apps[i].childViews[j].id);
+          ids.add(views[i].childViews[j].id);
         }
         }
       }
       }
       if (ids.isNotEmpty) {
       if (ids.isNotEmpty) {
-        result[apps[i].id] = ids;
+        result[views[i].id] = ids;
       }
       }
     }
     }
     return result;
     return result;

+ 4 - 2
frontend/appflowy_flutter/lib/workspace/presentation/settings/widgets/settings_export_file_widget.dart

@@ -3,6 +3,7 @@ import 'package:flowy_infra/image.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter/material.dart';
 import 'package:easy_localization/easy_localization.dart';
 import 'package:easy_localization/easy_localization.dart';
 import 'package:flowy_infra_ui/flowy_infra_ui.dart';
 import 'package:flowy_infra_ui/flowy_infra_ui.dart';
+import 'package:styled_widget/styled_widget.dart';
 
 
 import '../../../../generated/locale_keys.g.dart';
 import '../../../../generated/locale_keys.g.dart';
 
 
@@ -25,8 +26,9 @@ class SettingsExportFileWidgetState extends State<SettingsExportFileWidget> {
       children: [
       children: [
         FlowyText.medium(
         FlowyText.medium(
           LocaleKeys.settings_files_exportData.tr(),
           LocaleKeys.settings_files_exportData.tr(),
+          fontSize: 13,
           overflow: TextOverflow.ellipsis,
           overflow: TextOverflow.ellipsis,
-        ),
+        ).padding(horizontal: 5.0),
         const Spacer(),
         const Spacer(),
         _OpenExportedDirectoryButton(
         _OpenExportedDirectoryButton(
           onTap: () async {
           onTap: () async {
@@ -62,7 +64,7 @@ class _OpenExportedDirectoryButton extends StatelessWidget {
   Widget build(BuildContext context) {
   Widget build(BuildContext context) {
     return FlowyIconButton(
     return FlowyIconButton(
       hoverColor: Theme.of(context).colorScheme.secondaryContainer,
       hoverColor: Theme.of(context).colorScheme.secondaryContainer,
-      tooltipText: LocaleKeys.settings_files_open.tr(),
+      tooltipText: LocaleKeys.settings_files_export.tr(),
       icon: svgWidget(
       icon: svgWidget(
         'common/open_folder',
         'common/open_folder',
         color: Theme.of(context).iconTheme.color,
         color: Theme.of(context).iconTheme.color,

+ 4 - 2
frontend/appflowy_flutter/lib/workspace/presentation/settings/widgets/settings_file_customize_location_view.dart

@@ -129,12 +129,14 @@ class _CopyableText extends StatelessWidget {
                     overflow: TextOverflow.ellipsis,
                     overflow: TextOverflow.ellipsis,
                   ),
                   ),
                 ),
                 ),
-                if (onHover)
+                if (onHover) ...[
+                  const HSpace(5),
                   FlowyText.regular(
                   FlowyText.regular(
                     LocaleKeys.settings_files_copy.tr(),
                     LocaleKeys.settings_files_copy.tr(),
                     fontSize: 12,
                     fontSize: 12,
                     color: Theme.of(context).colorScheme.primary,
                     color: Theme.of(context).colorScheme.primary,
-                  )
+                  ),
+                ],
               ],
               ],
             ),
             ),
           ),
           ),

+ 23 - 3
frontend/appflowy_flutter/lib/workspace/presentation/settings/widgets/settings_file_exporter_widget.dart

@@ -49,9 +49,29 @@ class _FileExporterWidgetState extends State<FileExporterWidget> {
                 crossAxisAlignment: CrossAxisAlignment.start,
                 crossAxisAlignment: CrossAxisAlignment.start,
                 mainAxisSize: MainAxisSize.min,
                 mainAxisSize: MainAxisSize.min,
                 children: [
                 children: [
-                  FlowyText.medium(
-                    LocaleKeys.settings_files_selectFiles.tr(),
-                    fontSize: 16.0,
+                  Row(
+                    mainAxisAlignment: MainAxisAlignment.spaceBetween,
+                    children: [
+                      FlowyText.medium(
+                        LocaleKeys.settings_files_selectFiles.tr(),
+                        fontSize: 16.0,
+                      ),
+                      BlocBuilder<SettingsFileExporterCubit,
+                          SettingsFileExportState>(
+                        builder: (context, state) => FlowyTextButton(
+                          state.selectedItems
+                                  .expand((element) => element)
+                                  .every((element) => element)
+                              ? LocaleKeys.settings_files_deselectAll.tr()
+                              : LocaleKeys.settings_files_selectAll.tr(),
+                          onPressed: () {
+                            context
+                                .read<SettingsFileExporterCubit>()
+                                .selectOrDeselectAllItems();
+                          },
+                        ),
+                      )
+                    ],
                   ),
                   ),
                   const VSpace(8),
                   const VSpace(8),
                   const Expanded(child: _ExpandedList()),
                   const Expanded(child: _ExpandedList()),

+ 6 - 5
frontend/appflowy_flutter/packages/flowy_infra_ui/lib/style_widget/color_picker.dart

@@ -60,11 +60,12 @@ class FlowyColorPicker extends StatelessWidget {
     final colorIcon = SizedBox.square(
     final colorIcon = SizedBox.square(
       dimension: iconSize,
       dimension: iconSize,
       child: Container(
       child: Container(
-          decoration: BoxDecoration(
-        color: option.color,
-        shape: BoxShape.circle,
-        border: border,
-      )),
+        decoration: BoxDecoration(
+          color: option.color,
+          shape: BoxShape.circle,
+          // border: border,
+        ),
+      ),
     );
     );
 
 
     return SizedBox(
     return SizedBox(

+ 1 - 1
frontend/rust-lib/flowy-sqlite/src/kv/kv.rs

@@ -11,7 +11,7 @@ use serde::Serialize;
 use crate::kv::schema::{kv_table, kv_table::dsl, KV_SQL};
 use crate::kv::schema::{kv_table, kv_table::dsl, KV_SQL};
 use crate::sqlite::{DBConnection, Database, PoolConfig};
 use crate::sqlite::{DBConnection, Database, PoolConfig};
 
 
-const DB_NAME: &str = "kv.db";
+const DB_NAME: &str = "cache.db";
 lazy_static! {
 lazy_static! {
   static ref KV_HOLDER: RwLock<KV> = RwLock::new(KV::new());
   static ref KV_HOLDER: RwLock<KV> = RwLock::new(KV::new());
 }
 }