mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-09-11 19:17:43 +03:00
fix: launch review improvements (#5263)
* fix: recent views fix * fix: text button font color * fix: sidebar scrollbar inset * fix: account settings launch review * fix: open + menu on mobile provider issue * fix: code review * fix: push view improvement
This commit is contained in:
parent
3bdc8c222c
commit
c4f6703b76
@ -1,5 +1,6 @@
|
|||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
|
|
||||||
|
import 'package:appflowy/workspace/presentation/home/menu/menu_shared_state.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
import 'package:appflowy/mobile/presentation/database/board/mobile_board_screen.dart';
|
import 'package:appflowy/mobile/presentation/database/board/mobile_board_screen.dart';
|
||||||
@ -19,6 +20,7 @@ extension MobileRouter on BuildContext {
|
|||||||
queryParameters: view.queryParameters(arguments),
|
queryParameters: view.queryParameters(arguments),
|
||||||
).toString(),
|
).toString(),
|
||||||
).then((value) {
|
).then((value) {
|
||||||
|
getIt<MenuSharedState>().latestOpenView = view;
|
||||||
getIt<CachedRecentService>().updateRecentViews([view.id], true);
|
getIt<CachedRecentService>().updateRecentViews([view.id], true);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
import 'package:appflowy/generated/locale_keys.g.dart';
|
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||||
import 'package:appflowy/mobile/application/mobile_router.dart';
|
import 'package:appflowy/mobile/application/mobile_router.dart';
|
||||||
import 'package:appflowy/mobile/presentation/home/favorite_folder/mobile_home_favorite_folder.dart';
|
import 'package:appflowy/mobile/presentation/home/favorite_folder/mobile_home_favorite_folder.dart';
|
||||||
@ -8,7 +10,6 @@ import 'package:appflowy/workspace/application/user/user_workspace_bloc.dart';
|
|||||||
import 'package:appflowy_backend/protobuf/flowy-user/user_profile.pb.dart';
|
import 'package:appflowy_backend/protobuf/flowy-user/user_profile.pb.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:flutter/material.dart';
|
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:flutter_slidable/flutter_slidable.dart';
|
import 'package:flutter_slidable/flutter_slidable.dart';
|
||||||
|
|
||||||
@ -28,23 +29,15 @@ class MobileFavoritePageFolder extends StatelessWidget {
|
|||||||
providers: [
|
providers: [
|
||||||
BlocProvider(
|
BlocProvider(
|
||||||
create: (_) => SidebarSectionsBloc()
|
create: (_) => SidebarSectionsBloc()
|
||||||
..add(
|
..add(SidebarSectionsEvent.initial(userProfile, workspaceId)),
|
||||||
SidebarSectionsEvent.initial(
|
|
||||||
userProfile,
|
|
||||||
workspaceId,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
BlocProvider(
|
BlocProvider(
|
||||||
create: (_) => FavoriteBloc()..add(const FavoriteEvent.initial()),
|
create: (_) => FavoriteBloc()..add(const FavoriteEvent.initial()),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
child: BlocListener<UserWorkspaceBloc, UserWorkspaceState>(
|
child: BlocListener<UserWorkspaceBloc, UserWorkspaceState>(
|
||||||
listener: (context, state) {
|
listener: (context, state) =>
|
||||||
context.read<FavoriteBloc>().add(
|
context.read<FavoriteBloc>().add(const FavoriteEvent.initial()),
|
||||||
const FavoriteEvent.initial(),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
child: MultiBlocListener(
|
child: MultiBlocListener(
|
||||||
listeners: [
|
listeners: [
|
||||||
BlocListener<SidebarSectionsBloc, SidebarSectionsState>(
|
BlocListener<SidebarSectionsBloc, SidebarSectionsState>(
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
import 'package:appflowy/mobile/application/mobile_router.dart';
|
import 'package:appflowy/mobile/application/mobile_router.dart';
|
||||||
import 'package:appflowy/mobile/presentation/bottom_sheet/default_mobile_action_pane.dart';
|
import 'package:appflowy/mobile/presentation/bottom_sheet/default_mobile_action_pane.dart';
|
||||||
import 'package:appflowy/mobile/presentation/home/favorite_folder/mobile_home_favorite_folder_header.dart';
|
import 'package:appflowy/mobile/presentation/home/favorite_folder/mobile_home_favorite_folder_header.dart';
|
||||||
@ -5,7 +7,6 @@ import 'package:appflowy/mobile/presentation/page_item/mobile_view_item.dart';
|
|||||||
import 'package:appflowy/workspace/application/sidebar/folder/folder_bloc.dart';
|
import 'package:appflowy/workspace/application/sidebar/folder/folder_bloc.dart';
|
||||||
import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart';
|
import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart';
|
||||||
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
|
||||||
class MobileFavoriteFolder extends StatelessWidget {
|
class MobileFavoriteFolder extends StatelessWidget {
|
||||||
@ -62,9 +63,7 @@ class MobileFavoriteFolder extends StatelessWidget {
|
|||||||
isFeedback: false,
|
isFeedback: false,
|
||||||
view: view,
|
view: view,
|
||||||
level: 0,
|
level: 0,
|
||||||
onSelected: (view) async {
|
onSelected: context.pushView,
|
||||||
await context.pushView(view);
|
|
||||||
},
|
|
||||||
endActionPane: (context) => buildEndActionPane(context, [
|
endActionPane: (context) => buildEndActionPane(context, [
|
||||||
view.isFavorite
|
view.isFavorite
|
||||||
? MobilePaneActionType.removeFromFavorites
|
? MobilePaneActionType.removeFromFavorites
|
||||||
|
@ -24,16 +24,16 @@ class _MobileRecentFolderState extends State<MobileRecentFolder> {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return BlocProvider(
|
return BlocProvider(
|
||||||
create: (context) => RecentViewsBloc()
|
create: (context) =>
|
||||||
..add(
|
RecentViewsBloc()..add(const RecentViewsEvent.initial()),
|
||||||
const RecentViewsEvent.initial(),
|
|
||||||
),
|
|
||||||
child: BlocListener<UserWorkspaceBloc, UserWorkspaceState>(
|
child: BlocListener<UserWorkspaceBloc, UserWorkspaceState>(
|
||||||
listener: (context, state) {
|
listenWhen: (previous, current) =>
|
||||||
context.read<RecentViewsBloc>().add(
|
current.currentWorkspace != null &&
|
||||||
const RecentViewsEvent.fetchRecentViews(),
|
previous.currentWorkspace?.workspaceId !=
|
||||||
);
|
current.currentWorkspace!.workspaceId,
|
||||||
},
|
listener: (context, state) => context
|
||||||
|
.read<RecentViewsBloc>()
|
||||||
|
.add(const RecentViewsEvent.resetRecentViews()),
|
||||||
child: BlocBuilder<RecentViewsBloc, RecentViewsState>(
|
child: BlocBuilder<RecentViewsBloc, RecentViewsState>(
|
||||||
builder: (context, state) {
|
builder: (context, state) {
|
||||||
final ids = <String>{};
|
final ids = <String>{};
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
import 'package:appflowy/generated/locale_keys.g.dart';
|
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||||
import 'package:appflowy/mobile/application/mobile_router.dart';
|
import 'package:appflowy/mobile/application/mobile_router.dart';
|
||||||
import 'package:appflowy/mobile/presentation/bottom_sheet/default_mobile_action_pane.dart';
|
import 'package:appflowy/mobile/presentation/bottom_sheet/default_mobile_action_pane.dart';
|
||||||
@ -9,7 +11,6 @@ import 'package:appflowy/workspace/application/view/view_bloc.dart';
|
|||||||
import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart';
|
import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.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:flutter/material.dart';
|
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
|
||||||
class MobileSectionFolder extends StatelessWidget {
|
class MobileSectionFolder extends StatelessWidget {
|
||||||
@ -71,9 +72,7 @@ class MobileSectionFolder extends StatelessWidget {
|
|||||||
level: 0,
|
level: 0,
|
||||||
leftPadding: 16,
|
leftPadding: 16,
|
||||||
isFeedback: false,
|
isFeedback: false,
|
||||||
onSelected: (view) async {
|
onSelected: context.pushView,
|
||||||
await context.pushView(view);
|
|
||||||
},
|
|
||||||
endActionPane: (context) {
|
endActionPane: (context) {
|
||||||
final view = context.read<ViewBloc>().state.view;
|
final view = context.read<ViewBloc>().state.view;
|
||||||
return buildEndActionPane(context, [
|
return buildEndActionPane(context, [
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
import 'package:appflowy/generated/locale_keys.g.dart';
|
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||||
import 'package:appflowy/mobile/application/mobile_router.dart';
|
import 'package:appflowy/mobile/application/mobile_router.dart';
|
||||||
import 'package:appflowy/mobile/presentation/bottom_sheet/bottom_sheet.dart';
|
import 'package:appflowy/mobile/presentation/bottom_sheet/bottom_sheet.dart';
|
||||||
@ -10,7 +12,6 @@ import 'package:appflowy/workspace/presentation/home/menu/view/draggable_view_it
|
|||||||
import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart';
|
import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.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:flutter/material.dart';
|
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:flutter_slidable/flutter_slidable.dart';
|
import 'package:flutter_slidable/flutter_slidable.dart';
|
||||||
|
|
||||||
|
@ -11,10 +11,7 @@ import 'package:flowy_infra/theme_extension.dart';
|
|||||||
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
||||||
|
|
||||||
class SettingButton extends StatefulWidget {
|
class SettingButton extends StatefulWidget {
|
||||||
const SettingButton({
|
const SettingButton({super.key, required this.databaseController});
|
||||||
super.key,
|
|
||||||
required this.databaseController,
|
|
||||||
});
|
|
||||||
|
|
||||||
final DatabaseController databaseController;
|
final DatabaseController databaseController;
|
||||||
|
|
||||||
@ -44,9 +41,8 @@ class _SettingButtonState extends State<SettingButton> {
|
|||||||
radius: Corners.s4Border,
|
radius: Corners.s4Border,
|
||||||
onPressed: _popoverController.show,
|
onPressed: _popoverController.show,
|
||||||
),
|
),
|
||||||
popupBuilder: (BuildContext context) => DatabaseSettingsList(
|
popupBuilder: (_) =>
|
||||||
databaseController: widget.databaseController,
|
DatabaseSettingsList(databaseController: widget.databaseController),
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -325,24 +325,20 @@ class _AppFlowyEditorPageState extends State<AppFlowyEditorPage> {
|
|||||||
final editorState = widget.editorState;
|
final editorState = widget.editorState;
|
||||||
|
|
||||||
if (PlatformExtension.isMobile) {
|
if (PlatformExtension.isMobile) {
|
||||||
return BlocProvider.value(
|
return AppFlowyMobileToolbar(
|
||||||
value: documentBloc,
|
toolbarHeight: 42.0,
|
||||||
child: AppFlowyMobileToolbar(
|
editorState: editorState,
|
||||||
toolbarHeight: 42.0,
|
toolbarItemsBuilder: (sel) => buildMobileToolbarItems(editorState, sel),
|
||||||
|
child: MobileFloatingToolbar(
|
||||||
editorState: editorState,
|
editorState: editorState,
|
||||||
toolbarItemsBuilder: (selection) =>
|
editorScrollController: editorScrollController,
|
||||||
buildMobileToolbarItems(editorState, selection),
|
toolbarBuilder: (_, anchor, closeToolbar) =>
|
||||||
child: MobileFloatingToolbar(
|
CustomMobileFloatingToolbar(
|
||||||
editorState: editorState,
|
editorState: editorState,
|
||||||
editorScrollController: editorScrollController,
|
anchor: anchor,
|
||||||
toolbarBuilder: (_, anchor, closeToolbar) =>
|
closeToolbar: closeToolbar,
|
||||||
CustomMobileFloatingToolbar(
|
|
||||||
editorState: editorState,
|
|
||||||
anchor: anchor,
|
|
||||||
closeToolbar: closeToolbar,
|
|
||||||
),
|
|
||||||
child: editor,
|
|
||||||
),
|
),
|
||||||
|
child: editor,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,11 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
import 'package:appflowy/plugins/base/emoji/emoji_picker_screen.dart';
|
import 'package:appflowy/plugins/base/emoji/emoji_picker_screen.dart';
|
||||||
import 'package:appflowy/plugins/base/icon/icon_picker.dart';
|
import 'package:appflowy/plugins/base/icon/icon_picker.dart';
|
||||||
import 'package:appflowy/workspace/presentation/settings/widgets/emoji_picker/emoji_picker.dart';
|
import 'package:appflowy/workspace/presentation/settings/widgets/emoji_picker/emoji_picker.dart';
|
||||||
import 'package:appflowy_editor/appflowy_editor.dart';
|
import 'package:appflowy_editor/appflowy_editor.dart';
|
||||||
import 'package:appflowy_popover/appflowy_popover.dart';
|
import 'package:appflowy_popover/appflowy_popover.dart';
|
||||||
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:go_router/go_router.dart';
|
import 'package:go_router/go_router.dart';
|
||||||
|
|
||||||
class EmojiPickerButton extends StatelessWidget {
|
class EmojiPickerButton extends StatelessWidget {
|
||||||
@ -41,7 +42,7 @@ class EmojiPickerButton extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
offset: offset,
|
offset: offset,
|
||||||
direction: direction ?? PopoverDirection.rightWithTopAligned,
|
direction: direction ?? PopoverDirection.rightWithTopAligned,
|
||||||
popupBuilder: (context) => Container(
|
popupBuilder: (_) => Container(
|
||||||
width: emojiPickerSize.width,
|
width: emojiPickerSize.width,
|
||||||
height: emojiPickerSize.height,
|
height: emojiPickerSize.height,
|
||||||
padding: const EdgeInsets.all(4.0),
|
padding: const EdgeInsets.all(4.0),
|
||||||
@ -54,7 +55,7 @@ class EmojiPickerButton extends StatelessWidget {
|
|||||||
? FlowyButton(
|
? FlowyButton(
|
||||||
useIntrinsicWidth: true,
|
useIntrinsicWidth: true,
|
||||||
text: defaultIcon!,
|
text: defaultIcon!,
|
||||||
onTap: () => popoverController.show(),
|
onTap: popoverController.show,
|
||||||
)
|
)
|
||||||
: FlowyTextButton(
|
: FlowyTextButton(
|
||||||
emoji,
|
emoji,
|
||||||
@ -64,37 +65,29 @@ class EmojiPickerButton extends StatelessWidget {
|
|||||||
constraints: const BoxConstraints(minWidth: 35.0),
|
constraints: const BoxConstraints(minWidth: 35.0),
|
||||||
fillColor: Colors.transparent,
|
fillColor: Colors.transparent,
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
onPressed: () {
|
onPressed: popoverController.show,
|
||||||
popoverController.show();
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
} else {
|
|
||||||
return FlowyTextButton(
|
|
||||||
emoji,
|
|
||||||
overflow: TextOverflow.visible,
|
|
||||||
fontSize: emojiSize,
|
|
||||||
padding: EdgeInsets.zero,
|
|
||||||
constraints: const BoxConstraints(minWidth: 35.0),
|
|
||||||
fillColor: Colors.transparent,
|
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
|
||||||
onPressed: () async {
|
|
||||||
final result = await context.push<EmojiPickerResult>(
|
|
||||||
Uri(
|
|
||||||
path: MobileEmojiPickerScreen.routeName,
|
|
||||||
queryParameters: {
|
|
||||||
MobileEmojiPickerScreen.pageTitle: title,
|
|
||||||
},
|
|
||||||
).toString(),
|
|
||||||
);
|
|
||||||
if (result != null) {
|
|
||||||
onSubmitted(
|
|
||||||
result.emoji,
|
|
||||||
null,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
return FlowyTextButton(
|
||||||
|
emoji,
|
||||||
|
overflow: TextOverflow.visible,
|
||||||
|
fontSize: emojiSize,
|
||||||
|
padding: EdgeInsets.zero,
|
||||||
|
constraints: const BoxConstraints(minWidth: 35.0),
|
||||||
|
fillColor: Colors.transparent,
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
onPressed: () async {
|
||||||
|
final result = await context.push<EmojiPickerResult>(
|
||||||
|
Uri(
|
||||||
|
path: MobileEmojiPickerScreen.routeName,
|
||||||
|
queryParameters: {MobileEmojiPickerScreen.pageTitle: title},
|
||||||
|
).toString(),
|
||||||
|
);
|
||||||
|
if (result != null) {
|
||||||
|
onSubmitted(result.emoji, null);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,11 +16,11 @@ class MobileCodeLanguagePickerScreen extends StatelessWidget {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: FlowyAppBar(
|
appBar: FlowyAppBar(titleText: LocaleKeys.titleBar_language.tr()),
|
||||||
titleText: LocaleKeys.titleBar_language.tr(),
|
|
||||||
),
|
|
||||||
body: SafeArea(
|
body: SafeArea(
|
||||||
child: ListView.separated(
|
child: ListView.separated(
|
||||||
|
separatorBuilder: (_, __) => const Divider(),
|
||||||
|
itemCount: defaultCodeBlockSupportedLanguages.length,
|
||||||
itemBuilder: (context, index) {
|
itemBuilder: (context, index) {
|
||||||
final language = defaultCodeBlockSupportedLanguages[index];
|
final language = defaultCodeBlockSupportedLanguages[index];
|
||||||
return SizedBox(
|
return SizedBox(
|
||||||
@ -35,8 +35,6 @@ class MobileCodeLanguagePickerScreen extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
separatorBuilder: (_, __) => const Divider(),
|
|
||||||
itemCount: defaultCodeBlockSupportedLanguages.length,
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
import 'package:appflowy/generated/flowy_svgs.g.dart';
|
import 'package:appflowy/generated/flowy_svgs.g.dart';
|
||||||
import 'package:appflowy/generated/locale_keys.g.dart';
|
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||||
import 'package:appflowy/workspace/presentation/settings/widgets/settings_appearance/font_family_setting.dart';
|
import 'package:appflowy/workspace/presentation/settings/widgets/settings_appearance/font_family_setting.dart';
|
||||||
@ -6,7 +8,6 @@ import 'package:appflowy_editor/appflowy_editor.dart' hide Log;
|
|||||||
import 'package:appflowy_popover/appflowy_popover.dart';
|
import 'package:appflowy_popover/appflowy_popover.dart';
|
||||||
import 'package:easy_localization/easy_localization.dart';
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
import 'package:flowy_infra_ui/widget/flowy_tooltip.dart';
|
import 'package:flowy_infra_ui/widget/flowy_tooltip.dart';
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
|
|
||||||
final customizeFontToolbarItem = ToolbarItem(
|
final customizeFontToolbarItem = ToolbarItem(
|
||||||
id: 'editor.font',
|
id: 'editor.font',
|
||||||
@ -34,9 +35,8 @@ final customizeFontToolbarItem = ToolbarItem(
|
|||||||
Log.error('Failed to set font family: $e');
|
Log.error('Failed to set font family: $e');
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onResetFont: () async => editorState.formatDelta(selection, {
|
onResetFont: () async => editorState
|
||||||
AppFlowyRichTextKeys.fontFamily: null,
|
.formatDelta(selection, {AppFlowyRichTextKeys.fontFamily: null}),
|
||||||
}),
|
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 4.0),
|
padding: const EdgeInsets.symmetric(horizontal: 4.0),
|
||||||
child: FlowyTooltip(
|
child: FlowyTooltip(
|
||||||
|
@ -6,7 +6,6 @@ import 'package:appflowy/generated/flowy_svgs.g.dart';
|
|||||||
import 'package:appflowy/generated/locale_keys.g.dart';
|
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||||
import 'package:appflowy/mobile/presentation/base/type_option_menu_item.dart';
|
import 'package:appflowy/mobile/presentation/base/type_option_menu_item.dart';
|
||||||
import 'package:appflowy/mobile/presentation/bottom_sheet/bottom_sheet.dart';
|
import 'package:appflowy/mobile/presentation/bottom_sheet/bottom_sheet.dart';
|
||||||
import 'package:appflowy/plugins/document/application/document_bloc.dart';
|
|
||||||
import 'package:appflowy/plugins/document/presentation/editor_plugins/image/image_placeholder.dart';
|
import 'package:appflowy/plugins/document/presentation/editor_plugins/image/image_placeholder.dart';
|
||||||
import 'package:appflowy/plugins/document/presentation/editor_plugins/mention/mention_block.dart';
|
import 'package:appflowy/plugins/document/presentation/editor_plugins/mention/mention_block.dart';
|
||||||
import 'package:appflowy/plugins/document/presentation/editor_plugins/mention/mention_page_block.dart';
|
import 'package:appflowy/plugins/document/presentation/editor_plugins/mention/mention_page_block.dart';
|
||||||
@ -14,11 +13,12 @@ import 'package:appflowy/plugins/document/presentation/editor_plugins/mention/mo
|
|||||||
import 'package:appflowy/plugins/document/presentation/editor_plugins/mobile_toolbar_item/mobile_add_block_toolbar_item.dart';
|
import 'package:appflowy/plugins/document/presentation/editor_plugins/mobile_toolbar_item/mobile_add_block_toolbar_item.dart';
|
||||||
import 'package:appflowy/plugins/document/presentation/editor_plugins/mobile_toolbar_v3/aa_menu/_toolbar_theme.dart';
|
import 'package:appflowy/plugins/document/presentation/editor_plugins/mobile_toolbar_v3/aa_menu/_toolbar_theme.dart';
|
||||||
import 'package:appflowy/plugins/document/presentation/editor_plugins/plugins.dart';
|
import 'package:appflowy/plugins/document/presentation/editor_plugins/plugins.dart';
|
||||||
|
import 'package:appflowy/startup/startup.dart';
|
||||||
import 'package:appflowy/startup/tasks/app_widget.dart';
|
import 'package:appflowy/startup/tasks/app_widget.dart';
|
||||||
|
import 'package:appflowy/workspace/presentation/home/menu/menu_shared_state.dart';
|
||||||
import 'package:appflowy_editor/appflowy_editor.dart';
|
import 'package:appflowy_editor/appflowy_editor.dart';
|
||||||
import 'package:appflowy_editor_plugins/appflowy_editor_plugins.dart';
|
import 'package:appflowy_editor_plugins/appflowy_editor_plugins.dart';
|
||||||
import 'package:easy_localization/easy_localization.dart';
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
|
||||||
import 'package:go_router/go_router.dart';
|
import 'package:go_router/go_router.dart';
|
||||||
|
|
||||||
final addBlockToolbarItem = AppFlowyMobileToolbarItem(
|
final addBlockToolbarItem = AppFlowyMobileToolbarItem(
|
||||||
@ -45,7 +45,6 @@ final addBlockToolbarItem = AppFlowyMobileToolbarItem(
|
|||||||
keepEditorFocusNotifier.increase();
|
keepEditorFocusNotifier.increase();
|
||||||
final didAddBlock = await showAddBlockMenu(
|
final didAddBlock = await showAddBlockMenu(
|
||||||
AppGlobals.rootNavKey.currentContext!,
|
AppGlobals.rootNavKey.currentContext!,
|
||||||
documentBloc: context.read<DocumentBloc>(),
|
|
||||||
editorState: editorState,
|
editorState: editorState,
|
||||||
selection: selection!,
|
selection: selection!,
|
||||||
);
|
);
|
||||||
@ -60,33 +59,25 @@ final addBlockToolbarItem = AppFlowyMobileToolbarItem(
|
|||||||
|
|
||||||
Future<bool?> showAddBlockMenu(
|
Future<bool?> showAddBlockMenu(
|
||||||
BuildContext context, {
|
BuildContext context, {
|
||||||
required DocumentBloc documentBloc,
|
|
||||||
required EditorState editorState,
|
required EditorState editorState,
|
||||||
required Selection selection,
|
required Selection selection,
|
||||||
}) async {
|
}) async =>
|
||||||
final theme = ToolbarColorExtension.of(context);
|
showMobileBottomSheet<bool>(
|
||||||
return showMobileBottomSheet<bool>(
|
context,
|
||||||
context,
|
showHeader: true,
|
||||||
showHeader: true,
|
showDragHandle: true,
|
||||||
showDragHandle: true,
|
showCloseButton: true,
|
||||||
showCloseButton: true,
|
title: LocaleKeys.button_add.tr(),
|
||||||
title: LocaleKeys.button_add.tr(),
|
barrierColor: Colors.transparent,
|
||||||
barrierColor: Colors.transparent,
|
backgroundColor:
|
||||||
backgroundColor: theme.toolbarMenuBackgroundColor,
|
ToolbarColorExtension.of(context).toolbarMenuBackgroundColor,
|
||||||
elevation: 20,
|
elevation: 20,
|
||||||
enableDraggableScrollable: true,
|
enableDraggableScrollable: true,
|
||||||
builder: (_) => Padding(
|
builder: (_) => Padding(
|
||||||
padding: EdgeInsets.all(16 * context.scale),
|
padding: EdgeInsets.all(16 * context.scale),
|
||||||
child: BlocProvider.value(
|
child: _AddBlockMenu(selection: selection, editorState: editorState),
|
||||||
value: documentBloc,
|
|
||||||
child: _AddBlockMenu(
|
|
||||||
selection: selection,
|
|
||||||
editorState: editorState,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
),
|
);
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
class _AddBlockMenu extends StatelessWidget {
|
class _AddBlockMenu extends StatelessWidget {
|
||||||
const _AddBlockMenu({
|
const _AddBlockMenu({
|
||||||
@ -99,12 +90,9 @@ class _AddBlockMenu extends StatelessWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return BlocProvider.value(
|
return TypeOptionMenu<String>(
|
||||||
value: context.read<DocumentBloc>(),
|
values: buildTypeOptionMenuItemValues(context),
|
||||||
child: TypeOptionMenu<String>(
|
scaleFactor: context.scale,
|
||||||
values: buildTypeOptionMenuItemValues(context),
|
|
||||||
scaleFactor: context.scale,
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -226,7 +214,7 @@ class _AddBlockMenu extends StatelessWidget {
|
|||||||
onTap: (_, __) async {
|
onTap: (_, __) async {
|
||||||
AppGlobals.rootNavKey.currentContext?.pop(true);
|
AppGlobals.rootNavKey.currentContext?.pop(true);
|
||||||
|
|
||||||
final currentViewId = context.read<DocumentBloc>().documentId;
|
final currentViewId = getIt<MenuSharedState>().latestOpenView?.id;
|
||||||
final viewId = await showPageSelectorSheet(
|
final viewId = await showPageSelectorSheet(
|
||||||
context,
|
context,
|
||||||
currentViewId: currentViewId,
|
currentViewId: currentViewId,
|
||||||
|
@ -24,7 +24,10 @@ class CachedRecentService {
|
|||||||
Completer<void> _completer = Completer();
|
Completer<void> _completer = Completer();
|
||||||
|
|
||||||
ValueNotifier<List<ViewPB>> notifier = ValueNotifier(const []);
|
ValueNotifier<List<ViewPB>> notifier = ValueNotifier(const []);
|
||||||
List<ViewPB> _recentViews = const [];
|
|
||||||
|
List<ViewPB> get _recentViews => notifier.value;
|
||||||
|
set _recentViews(List<ViewPB> value) => notifier.value = value;
|
||||||
|
|
||||||
final _listener = RecentViewsListener();
|
final _listener = RecentViewsListener();
|
||||||
|
|
||||||
Future<List<ViewPB>> recentViews() async {
|
Future<List<ViewPB>> recentViews() async {
|
||||||
@ -35,7 +38,6 @@ class CachedRecentService {
|
|||||||
_listener.start(recentViewsUpdated: _recentViewsUpdated);
|
_listener.start(recentViewsUpdated: _recentViewsUpdated);
|
||||||
final result = await _readRecentViews();
|
final result = await _readRecentViews();
|
||||||
_recentViews = result.toNullable()?.items ?? const [];
|
_recentViews = result.toNullable()?.items ?? const [];
|
||||||
notifier.value = _recentViews;
|
|
||||||
_completer.complete();
|
_completer.complete();
|
||||||
|
|
||||||
return _recentViews;
|
return _recentViews;
|
||||||
@ -64,6 +66,7 @@ class CachedRecentService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<void> dispose() async {
|
Future<void> dispose() async {
|
||||||
|
notifier.dispose();
|
||||||
await _listener.stop();
|
await _listener.stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,6 +37,10 @@ class RecentViewsBloc extends Bloc<RecentViewsEvent, RecentViewsState> {
|
|||||||
fetchRecentViews: (e) async {
|
fetchRecentViews: (e) async {
|
||||||
emit(state.copyWith(views: await _service.recentViews()));
|
emit(state.copyWith(views: await _service.recentViews()));
|
||||||
},
|
},
|
||||||
|
resetRecentViews: (e) async {
|
||||||
|
await _service.reset();
|
||||||
|
add(const RecentViewsEvent.fetchRecentViews());
|
||||||
|
},
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
@ -54,13 +58,13 @@ class RecentViewsEvent with _$RecentViewsEvent {
|
|||||||
const factory RecentViewsEvent.removeRecentViews(List<String> viewIds) =
|
const factory RecentViewsEvent.removeRecentViews(List<String> viewIds) =
|
||||||
RemoveRecentViews;
|
RemoveRecentViews;
|
||||||
const factory RecentViewsEvent.fetchRecentViews() = FetchRecentViews;
|
const factory RecentViewsEvent.fetchRecentViews() = FetchRecentViews;
|
||||||
|
const factory RecentViewsEvent.resetRecentViews() = ResetRecentViews;
|
||||||
}
|
}
|
||||||
|
|
||||||
@freezed
|
@freezed
|
||||||
class RecentViewsState with _$RecentViewsState {
|
class RecentViewsState with _$RecentViewsState {
|
||||||
const factory RecentViewsState({
|
const factory RecentViewsState({required List<ViewPB> views}) =
|
||||||
required List<ViewPB> views,
|
_RecentViewsState;
|
||||||
}) = _RecentViewsState;
|
|
||||||
|
|
||||||
factory RecentViewsState.initial() => const RecentViewsState(views: []);
|
factory RecentViewsState.initial() => const RecentViewsState(views: []);
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter/scheduler.dart';
|
||||||
|
|
||||||
import 'package:appflowy/core/frameless_window.dart';
|
import 'package:appflowy/core/frameless_window.dart';
|
||||||
import 'package:appflowy/plugins/blank/blank.dart';
|
import 'package:appflowy/plugins/blank/blank.dart';
|
||||||
@ -110,9 +111,7 @@ class FadingIndexedStack extends StatefulWidget {
|
|||||||
super.key,
|
super.key,
|
||||||
required this.index,
|
required this.index,
|
||||||
required this.children,
|
required this.children,
|
||||||
this.duration = const Duration(
|
this.duration = const Duration(milliseconds: 250),
|
||||||
milliseconds: 250,
|
|
||||||
),
|
|
||||||
});
|
});
|
||||||
|
|
||||||
final int index;
|
final int index;
|
||||||
@ -135,8 +134,10 @@ class FadingIndexedStackState extends State<FadingIndexedStack> {
|
|||||||
@override
|
@override
|
||||||
void didUpdateWidget(FadingIndexedStack oldWidget) {
|
void didUpdateWidget(FadingIndexedStack oldWidget) {
|
||||||
if (oldWidget.index == widget.index) return;
|
if (oldWidget.index == widget.index) return;
|
||||||
setState(() => _targetOpacity = 0);
|
_targetOpacity = 0;
|
||||||
Future.delayed(1.milliseconds, () => setState(() => _targetOpacity = 1));
|
SchedulerBinding.instance.addPostFrameCallback(
|
||||||
|
(_) => setState(() => _targetOpacity = 1),
|
||||||
|
);
|
||||||
super.didUpdateWidget(oldWidget);
|
super.didUpdateWidget(oldWidget);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,12 +1,14 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter/services.dart';
|
||||||
|
|
||||||
import 'package:appflowy/generated/locale_keys.g.dart';
|
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||||
import 'package:appflowy/workspace/application/sidebar/folder/folder_bloc.dart';
|
import 'package:appflowy/workspace/application/sidebar/folder/folder_bloc.dart';
|
||||||
import 'package:appflowy/workspace/application/tabs/tabs_bloc.dart';
|
import 'package:appflowy/workspace/application/tabs/tabs_bloc.dart';
|
||||||
import 'package:appflowy/workspace/presentation/home/menu/view/view_item.dart';
|
import 'package:appflowy/workspace/presentation/home/menu/view/view_item.dart';
|
||||||
import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart';
|
import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart';
|
||||||
import 'package:easy_localization/easy_localization.dart';
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
|
import 'package:flowy_infra/theme_extension.dart';
|
||||||
import 'package:flowy_infra_ui/style_widget/button.dart';
|
import 'package:flowy_infra_ui/style_widget/button.dart';
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:flutter/services.dart';
|
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
|
||||||
class FavoriteFolder extends StatelessWidget {
|
class FavoriteFolder extends StatelessWidget {
|
||||||
@ -98,6 +100,8 @@ class _FavoriteHeaderState extends State<FavoriteHeader> {
|
|||||||
children: [
|
children: [
|
||||||
FlowyTextButton(
|
FlowyTextButton(
|
||||||
LocaleKeys.sideBar_favorites.tr(),
|
LocaleKeys.sideBar_favorites.tr(),
|
||||||
|
fontColor: AFThemeExtension.of(context).textColor,
|
||||||
|
fontHoverColor: Theme.of(context).colorScheme.onSurface,
|
||||||
tooltip: LocaleKeys.sideBar_clickToHideFavorites.tr(),
|
tooltip: LocaleKeys.sideBar_clickToHideFavorites.tr(),
|
||||||
constraints: const BoxConstraints(maxHeight: iconSize),
|
constraints: const BoxConstraints(maxHeight: iconSize),
|
||||||
padding: const EdgeInsets.all(4),
|
padding: const EdgeInsets.all(4),
|
||||||
|
@ -43,6 +43,7 @@ class _FolderHeaderState extends State<FolderHeader> {
|
|||||||
minHeight: iconSize + textPadding * 2,
|
minHeight: iconSize + textPadding * 2,
|
||||||
),
|
),
|
||||||
fontColor: AFThemeExtension.of(context).textColor,
|
fontColor: AFThemeExtension.of(context).textColor,
|
||||||
|
fontHoverColor: Theme.of(context).colorScheme.onSurface,
|
||||||
padding: const EdgeInsets.all(textPadding),
|
padding: const EdgeInsets.all(textPadding),
|
||||||
fillColor: Colors.transparent,
|
fillColor: Colors.transparent,
|
||||||
onPressed: widget.onPressed,
|
onPressed: widget.onPressed,
|
||||||
|
@ -178,9 +178,7 @@ class HomeSideBar extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class _Sidebar extends StatefulWidget {
|
class _Sidebar extends StatefulWidget {
|
||||||
const _Sidebar({
|
const _Sidebar({required this.userProfile});
|
||||||
required this.userProfile,
|
|
||||||
});
|
|
||||||
|
|
||||||
final UserProfilePB userProfile;
|
final UserProfilePB userProfile;
|
||||||
|
|
||||||
@ -222,10 +220,7 @@ class _SidebarState extends State<_Sidebar> {
|
|||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: [
|
children: [
|
||||||
// top menu
|
// top menu
|
||||||
const Padding(
|
const Padding(padding: menuHorizontalInset, child: SidebarTopMenu()),
|
||||||
padding: menuHorizontalInset,
|
|
||||||
child: SidebarTopMenu(),
|
|
||||||
),
|
|
||||||
// user or workspace, setting
|
// user or workspace, setting
|
||||||
Padding(
|
Padding(
|
||||||
padding: menuHorizontalInset,
|
padding: menuHorizontalInset,
|
||||||
@ -245,8 +240,9 @@ class _SidebarState extends State<_Sidebar> {
|
|||||||
// scrollable document list
|
// scrollable document list
|
||||||
Expanded(
|
Expanded(
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: menuHorizontalInset,
|
padding: menuHorizontalInset - const EdgeInsets.only(right: 6),
|
||||||
child: SingleChildScrollView(
|
child: SingleChildScrollView(
|
||||||
|
padding: const EdgeInsets.only(right: 6),
|
||||||
controller: _scrollController,
|
controller: _scrollController,
|
||||||
physics: const ClampingScrollPhysics(),
|
physics: const ClampingScrollPhysics(),
|
||||||
child: SidebarFolder(
|
child: SidebarFolder(
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
import 'package:appflowy/generated/locale_keys.g.dart';
|
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||||
import 'package:appflowy/startup/startup.dart';
|
import 'package:appflowy/startup/startup.dart';
|
||||||
import 'package:appflowy/workspace/application/favorite/favorite_bloc.dart';
|
import 'package:appflowy/workspace/application/favorite/favorite_bloc.dart';
|
||||||
@ -10,7 +12,6 @@ import 'package:appflowy/workspace/presentation/home/menu/sidebar/folder/_sectio
|
|||||||
import 'package:appflowy_backend/protobuf/flowy-user/protobuf.dart';
|
import 'package:appflowy_backend/protobuf/flowy-user/protobuf.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:flutter/material.dart';
|
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
|
||||||
class SidebarFolder extends StatelessWidget {
|
class SidebarFolder extends StatelessWidget {
|
||||||
@ -38,10 +39,7 @@ class SidebarFolder extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
return Padding(
|
return Padding(
|
||||||
padding: const EdgeInsets.only(bottom: 10),
|
padding: const EdgeInsets.only(bottom: 10),
|
||||||
child: FavoriteFolder(
|
child: FavoriteFolder(views: state.views),
|
||||||
// remove the duplicate views
|
|
||||||
views: state.views,
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
@ -52,30 +50,27 @@ class SidebarFolder extends StatelessWidget {
|
|||||||
final isCollaborativeWorkspace =
|
final isCollaborativeWorkspace =
|
||||||
context.read<UserWorkspaceBloc>().state.isCollabWorkspaceOn;
|
context.read<UserWorkspaceBloc>().state.isCollabWorkspaceOn;
|
||||||
|
|
||||||
|
// only show public and private section if the workspace is collaborative
|
||||||
return Column(
|
return Column(
|
||||||
children:
|
children: isCollaborativeWorkspace
|
||||||
// only show public and private section if the workspace is collaborative
|
? [
|
||||||
isCollaborativeWorkspace
|
// public
|
||||||
? [
|
const VSpace(10),
|
||||||
// public
|
PublicSectionFolder(views: state.section.publicViews),
|
||||||
const VSpace(10),
|
|
||||||
PublicSectionFolder(
|
|
||||||
views: state.section.publicViews,
|
|
||||||
),
|
|
||||||
|
|
||||||
// private
|
// private
|
||||||
const VSpace(10),
|
const VSpace(10),
|
||||||
PrivateSectionFolder(
|
PrivateSectionFolder(
|
||||||
views: state.section.privateViews,
|
views: state.section.privateViews,
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
: [
|
: [
|
||||||
// personal
|
// personal
|
||||||
const VSpace(10),
|
const VSpace(10),
|
||||||
PersonalSectionFolder(
|
PersonalSectionFolder(
|
||||||
views: state.section.publicViews,
|
views: state.section.publicViews,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
@ -87,10 +82,8 @@ class SidebarFolder extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class PrivateSectionFolder extends SectionFolder {
|
class PrivateSectionFolder extends SectionFolder {
|
||||||
PrivateSectionFolder({
|
PrivateSectionFolder({super.key, required super.views})
|
||||||
super.key,
|
: super(
|
||||||
required super.views,
|
|
||||||
}) : super(
|
|
||||||
title: LocaleKeys.sideBar_private.tr(),
|
title: LocaleKeys.sideBar_private.tr(),
|
||||||
categoryType: FolderCategoryType.private,
|
categoryType: FolderCategoryType.private,
|
||||||
expandButtonTooltip: LocaleKeys.sideBar_clickToHidePrivate.tr(),
|
expandButtonTooltip: LocaleKeys.sideBar_clickToHidePrivate.tr(),
|
||||||
@ -99,10 +92,8 @@ class PrivateSectionFolder extends SectionFolder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class PublicSectionFolder extends SectionFolder {
|
class PublicSectionFolder extends SectionFolder {
|
||||||
PublicSectionFolder({
|
PublicSectionFolder({super.key, required super.views})
|
||||||
super.key,
|
: super(
|
||||||
required super.views,
|
|
||||||
}) : super(
|
|
||||||
title: LocaleKeys.sideBar_workspace.tr(),
|
title: LocaleKeys.sideBar_workspace.tr(),
|
||||||
categoryType: FolderCategoryType.public,
|
categoryType: FolderCategoryType.public,
|
||||||
expandButtonTooltip: LocaleKeys.sideBar_clickToHideWorkspace.tr(),
|
expandButtonTooltip: LocaleKeys.sideBar_clickToHideWorkspace.tr(),
|
||||||
@ -111,10 +102,8 @@ class PublicSectionFolder extends SectionFolder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class PersonalSectionFolder extends SectionFolder {
|
class PersonalSectionFolder extends SectionFolder {
|
||||||
PersonalSectionFolder({
|
PersonalSectionFolder({super.key, required super.views})
|
||||||
super.key,
|
: super(
|
||||||
required super.views,
|
|
||||||
}) : super(
|
|
||||||
title: LocaleKeys.sideBar_personal.tr(),
|
title: LocaleKeys.sideBar_personal.tr(),
|
||||||
categoryType: FolderCategoryType.public,
|
categoryType: FolderCategoryType.public,
|
||||||
expandButtonTooltip: LocaleKeys.sideBar_clickToHidePersonal.tr(),
|
expandButtonTooltip: LocaleKeys.sideBar_clickToHidePersonal.tr(),
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
import 'package:appflowy/generated/flowy_svgs.g.dart';
|
import 'package:appflowy/generated/flowy_svgs.g.dart';
|
||||||
import 'package:appflowy/generated/locale_keys.g.dart';
|
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||||
import 'package:appflowy/plugins/base/emoji/emoji_text.dart';
|
import 'package:appflowy/plugins/base/emoji/emoji_text.dart';
|
||||||
@ -24,7 +26,6 @@ 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:flowy_infra_ui/style_widget/hover.dart';
|
import 'package:flowy_infra_ui/style_widget/hover.dart';
|
||||||
import 'package:flowy_infra_ui/widget/flowy_tooltip.dart';
|
import 'package:flowy_infra_ui/widget/flowy_tooltip.dart';
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
|
||||||
typedef ViewItemOnSelected = void Function(ViewPB, BuildContext);
|
typedef ViewItemOnSelected = void Function(ViewPB, BuildContext);
|
||||||
|
@ -1,10 +1,9 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
|
|
||||||
import 'package:appflowy/env/cloud_env.dart';
|
|
||||||
import 'package:appflowy/generated/flowy_svgs.g.dart';
|
import 'package:appflowy/generated/flowy_svgs.g.dart';
|
||||||
import 'package:appflowy/generated/locale_keys.g.dart';
|
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||||
import 'package:appflowy/plugins/base/emoji/emoji_picker.dart';
|
import 'package:appflowy/plugins/base/icon/icon_picker.dart';
|
||||||
import 'package:appflowy/startup/startup.dart';
|
import 'package:appflowy/startup/startup.dart';
|
||||||
import 'package:appflowy/user/application/auth/auth_service.dart';
|
import 'package:appflowy/user/application/auth/auth_service.dart';
|
||||||
import 'package:appflowy/workspace/application/user/settings_user_bloc.dart';
|
import 'package:appflowy/workspace/application/user/settings_user_bloc.dart';
|
||||||
@ -14,18 +13,16 @@ import 'package:appflowy/workspace/presentation/settings/shared/settings_categor
|
|||||||
import 'package:appflowy/workspace/presentation/settings/shared/settings_category_spacer.dart';
|
import 'package:appflowy/workspace/presentation/settings/shared/settings_category_spacer.dart';
|
||||||
import 'package:appflowy/workspace/presentation/settings/shared/settings_header.dart';
|
import 'package:appflowy/workspace/presentation/settings/shared/settings_header.dart';
|
||||||
import 'package:appflowy/workspace/presentation/settings/shared/settings_input_field.dart';
|
import 'package:appflowy/workspace/presentation/settings/shared/settings_input_field.dart';
|
||||||
import 'package:appflowy/workspace/presentation/settings/shared/single_setting_action.dart';
|
|
||||||
import 'package:appflowy/workspace/presentation/settings/widgets/setting_third_party_login.dart';
|
import 'package:appflowy/workspace/presentation/settings/widgets/setting_third_party_login.dart';
|
||||||
import 'package:appflowy/workspace/presentation/widgets/dialogs.dart';
|
import 'package:appflowy/workspace/presentation/widgets/dialogs.dart';
|
||||||
import 'package:appflowy/workspace/presentation/widgets/user_avatar.dart';
|
import 'package:appflowy/workspace/presentation/widgets/user_avatar.dart';
|
||||||
import 'package:appflowy_backend/protobuf/flowy-user/auth.pbenum.dart';
|
import 'package:appflowy_backend/protobuf/flowy-user/auth.pbenum.dart';
|
||||||
import 'package:appflowy_backend/protobuf/flowy-user/user_profile.pb.dart';
|
import 'package:appflowy_backend/protobuf/flowy-user/user_profile.pb.dart';
|
||||||
import 'package:easy_localization/easy_localization.dart';
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
import 'package:flowy_infra/size.dart';
|
|
||||||
import 'package:flowy_infra/theme_extension.dart';
|
|
||||||
import 'package:flowy_infra_ui/style_widget/button.dart';
|
import 'package:flowy_infra_ui/style_widget/button.dart';
|
||||||
import 'package:flowy_infra_ui/style_widget/hover.dart';
|
import 'package:flowy_infra_ui/style_widget/hover.dart';
|
||||||
import 'package:flowy_infra_ui/style_widget/text.dart';
|
import 'package:flowy_infra_ui/style_widget/text.dart';
|
||||||
|
import 'package:flowy_infra_ui/widget/flowy_tooltip.dart';
|
||||||
import 'package:flowy_infra_ui/widget/spacing.dart';
|
import 'package:flowy_infra_ui/widget/spacing.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
|
||||||
@ -51,15 +48,6 @@ class SettingsAccountView extends StatefulWidget {
|
|||||||
|
|
||||||
class _SettingsAccountViewState extends State<SettingsAccountView> {
|
class _SettingsAccountViewState extends State<SettingsAccountView> {
|
||||||
late String userName = widget.userProfile.name;
|
late String userName = widget.userProfile.name;
|
||||||
late final TextEditingController _emailController = TextEditingController(
|
|
||||||
text: widget.userProfile.email,
|
|
||||||
);
|
|
||||||
|
|
||||||
@override
|
|
||||||
void dispose() {
|
|
||||||
_emailController.dispose();
|
|
||||||
super.dispose();
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
@ -67,11 +55,7 @@ class _SettingsAccountViewState extends State<SettingsAccountView> {
|
|||||||
create: (context) =>
|
create: (context) =>
|
||||||
getIt<SettingsUserViewBloc>(param1: widget.userProfile)
|
getIt<SettingsUserViewBloc>(param1: widget.userProfile)
|
||||||
..add(const SettingsUserEvent.initial()),
|
..add(const SettingsUserEvent.initial()),
|
||||||
child: BlocConsumer<SettingsUserViewBloc, SettingsUserState>(
|
child: BlocBuilder<SettingsUserViewBloc, SettingsUserState>(
|
||||||
listenWhen: (previous, current) =>
|
|
||||||
previous.userProfile.email != current.userProfile.email,
|
|
||||||
listener: (context, state) =>
|
|
||||||
_emailController.text = state.userProfile.email,
|
|
||||||
builder: (context, state) {
|
builder: (context, state) {
|
||||||
return SettingsBody(
|
return SettingsBody(
|
||||||
children: [
|
children: [
|
||||||
@ -97,45 +81,47 @@ class _SettingsAccountViewState extends State<SettingsAccountView> {
|
|||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
// Only show change email if the user is authenticated and not using local auth
|
|
||||||
if (isAuthEnabled &&
|
// Enable when/if we need change email feature
|
||||||
state.userProfile.authenticator != AuthenticatorPB.Local) ...[
|
// // Only show change email if the user is authenticated and not using local auth
|
||||||
const SettingsCategorySpacer(),
|
// if (isAuthEnabled &&
|
||||||
SettingsCategory(
|
// state.userProfile.authenticator != AuthenticatorPB.Local) ...[
|
||||||
title: LocaleKeys.settings_accountPage_email_title.tr(),
|
// const SettingsCategorySpacer(),
|
||||||
children: [
|
// SettingsCategory(
|
||||||
SingleSettingAction(
|
// title: LocaleKeys.settings_accountPage_email_title.tr(),
|
||||||
label: state.userProfile.email,
|
// children: [
|
||||||
buttonLabel: LocaleKeys
|
// SingleSettingAction(
|
||||||
.settings_accountPage_email_actions_change
|
// label: state.userProfile.email,
|
||||||
.tr(),
|
// buttonLabel: LocaleKeys
|
||||||
onPressed: () => SettingsAlertDialog(
|
// .settings_accountPage_email_actions_change
|
||||||
title: LocaleKeys
|
// .tr(),
|
||||||
.settings_accountPage_email_actions_change
|
// onPressed: () => SettingsAlertDialog(
|
||||||
.tr(),
|
// title: LocaleKeys
|
||||||
confirmLabel: LocaleKeys.button_save.tr(),
|
// .settings_accountPage_email_actions_change
|
||||||
confirm: () {
|
// .tr(),
|
||||||
context.read<SettingsUserViewBloc>().add(
|
// confirmLabel: LocaleKeys.button_save.tr(),
|
||||||
SettingsUserEvent.updateUserEmail(
|
// confirm: () {
|
||||||
_emailController.text,
|
// context.read<SettingsUserViewBloc>().add(
|
||||||
),
|
// SettingsUserEvent.updateUserEmail(
|
||||||
);
|
// _emailController.text,
|
||||||
Navigator.of(context).pop();
|
// ),
|
||||||
},
|
// );
|
||||||
children: [
|
// Navigator.of(context).pop();
|
||||||
SettingsInputField(
|
// },
|
||||||
label: LocaleKeys.settings_accountPage_email_title
|
// children: [
|
||||||
.tr(),
|
// SettingsInputField(
|
||||||
value: state.userProfile.email,
|
// label: LocaleKeys.settings_accountPage_email_title
|
||||||
hideActions: true,
|
// .tr(),
|
||||||
textController: _emailController,
|
// value: state.userProfile.email,
|
||||||
),
|
// hideActions: true,
|
||||||
],
|
// textController: _emailController,
|
||||||
).show(context),
|
// ),
|
||||||
),
|
// ],
|
||||||
],
|
// ).show(context),
|
||||||
),
|
// ),
|
||||||
],
|
// ],
|
||||||
|
// ),
|
||||||
|
// ],
|
||||||
|
|
||||||
/// Enable when we have change password feature and 2FA
|
/// Enable when we have change password feature and 2FA
|
||||||
// const SettingsCategorySpacer(),
|
// const SettingsCategorySpacer(),
|
||||||
@ -259,7 +245,9 @@ class SignInOutButton extends StatelessWidget {
|
|||||||
hoverColor: const Color(0xFF005483),
|
hoverColor: const Color(0xFF005483),
|
||||||
fontHoverColor: Colors.white,
|
fontHoverColor: Colors.white,
|
||||||
onPressed: () => SettingsAlertDialog(
|
onPressed: () => SettingsAlertDialog(
|
||||||
title: LocaleKeys.settings_accountPage_login_loginLabel.tr(),
|
title: signIn
|
||||||
|
? LocaleKeys.settings_accountPage_login_loginLabel.tr()
|
||||||
|
: LocaleKeys.settings_accountPage_login_logoutLabel.tr(),
|
||||||
subtitle: signIn
|
subtitle: signIn
|
||||||
? null
|
? null
|
||||||
: switch (userProfile.encryptionType) {
|
: switch (userProfile.encryptionType) {
|
||||||
@ -303,6 +291,7 @@ class UserProfileSetting extends StatefulWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class _UserProfileSettingState extends State<UserProfileSetting> {
|
class _UserProfileSettingState extends State<UserProfileSetting> {
|
||||||
|
late final _nameController = TextEditingController(text: widget.name);
|
||||||
late final FocusNode focusNode;
|
late final FocusNode focusNode;
|
||||||
bool isEditing = false;
|
bool isEditing = false;
|
||||||
bool isHovering = false;
|
bool isHovering = false;
|
||||||
@ -314,14 +303,20 @@ class _UserProfileSettingState extends State<UserProfileSetting> {
|
|||||||
onKeyEvent: (_, event) {
|
onKeyEvent: (_, event) {
|
||||||
if (event is KeyDownEvent &&
|
if (event is KeyDownEvent &&
|
||||||
event.logicalKey == LogicalKeyboardKey.escape &&
|
event.logicalKey == LogicalKeyboardKey.escape &&
|
||||||
isEditing) {
|
isEditing &&
|
||||||
|
mounted) {
|
||||||
setState(() => isEditing = false);
|
setState(() => isEditing = false);
|
||||||
return KeyEventResult.handled;
|
return KeyEventResult.handled;
|
||||||
}
|
}
|
||||||
|
|
||||||
return KeyEventResult.ignored;
|
return KeyEventResult.ignored;
|
||||||
},
|
},
|
||||||
);
|
)..addListener(() {
|
||||||
|
if (!focusNode.hasFocus && isEditing && mounted) {
|
||||||
|
widget.onSave?.call(_nameController.text);
|
||||||
|
setState(() => isEditing = false);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -335,69 +330,28 @@ class _UserProfileSettingState extends State<UserProfileSetting> {
|
|||||||
return Row(
|
return Row(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Stack(
|
GestureDetector(
|
||||||
children: [
|
behavior: HitTestBehavior.opaque,
|
||||||
GestureDetector(
|
onTap: () => _showIconPickerDialog(context),
|
||||||
behavior: HitTestBehavior.opaque,
|
child: FlowyHover(
|
||||||
onTap: () => _showIconPickerDialog(context),
|
resetHoverOnRebuild: false,
|
||||||
child: FlowyHover(
|
onHover: (state) => setState(() => isHovering = state),
|
||||||
resetHoverOnRebuild: false,
|
style: HoverStyle(
|
||||||
onHover: (state) => setState(() => isHovering = state),
|
hoverColor: Colors.transparent,
|
||||||
style: HoverStyle(
|
borderRadius: BorderRadius.circular(100),
|
||||||
hoverColor: Colors.transparent,
|
),
|
||||||
borderRadius: BorderRadius.circular(100),
|
child: FlowyTooltip(
|
||||||
),
|
message: LocaleKeys
|
||||||
child: Column(
|
.settings_accountPage_general_changeProfilePicture
|
||||||
mainAxisSize: MainAxisSize.min,
|
.tr(),
|
||||||
children: [
|
child: UserAvatar(
|
||||||
UserAvatar(
|
iconUrl: widget.iconUrl,
|
||||||
iconUrl: widget.iconUrl,
|
name: widget.name,
|
||||||
name: widget.name,
|
isLarge: true,
|
||||||
isLarge: true,
|
isHovering: isHovering,
|
||||||
isHovering: isHovering,
|
|
||||||
),
|
|
||||||
const VSpace(4),
|
|
||||||
FlowyText.regular(
|
|
||||||
LocaleKeys
|
|
||||||
.settings_accountPage_general_changeProfilePicture
|
|
||||||
.tr(),
|
|
||||||
color: AFThemeExtension.of(context).textColor,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
if (widget.iconUrl.isNotEmpty)
|
),
|
||||||
Positioned(
|
|
||||||
right: 0,
|
|
||||||
child: GestureDetector(
|
|
||||||
behavior: HitTestBehavior.opaque,
|
|
||||||
onTap: () => context
|
|
||||||
.read<SettingsUserViewBloc>()
|
|
||||||
.add(const SettingsUserEvent.removeUserIcon()),
|
|
||||||
child: DecoratedBox(
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
color: Theme.of(context).colorScheme.primary,
|
|
||||||
shape: BoxShape.circle,
|
|
||||||
),
|
|
||||||
child: FlowyHover(
|
|
||||||
resetHoverOnRebuild: false,
|
|
||||||
style: const HoverStyle(
|
|
||||||
borderRadius: BorderRadius.all(Radius.circular(24)),
|
|
||||||
hoverColor: Color(0xFF005483),
|
|
||||||
),
|
|
||||||
builder: (_, __) => Padding(
|
|
||||||
padding: const EdgeInsets.all(4),
|
|
||||||
child: FlowySvg(
|
|
||||||
FlowySvgs.close_s,
|
|
||||||
color: Theme.of(context).colorScheme.onPrimary,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
const HSpace(16),
|
const HSpace(16),
|
||||||
if (!isEditing) ...[
|
if (!isEditing) ...[
|
||||||
@ -430,6 +384,7 @@ class _UserProfileSettingState extends State<UserProfileSetting> {
|
|||||||
] else ...[
|
] else ...[
|
||||||
Flexible(
|
Flexible(
|
||||||
child: SettingsInputField(
|
child: SettingsInputField(
|
||||||
|
textController: _nameController,
|
||||||
value: widget.name,
|
value: widget.name,
|
||||||
focusNode: focusNode..requestFocus(),
|
focusNode: focusNode..requestFocus(),
|
||||||
onCancel: () => setState(() => isEditing = false),
|
onCancel: () => setState(() => isEditing = false),
|
||||||
@ -448,20 +403,16 @@ class _UserProfileSettingState extends State<UserProfileSetting> {
|
|||||||
return showDialog(
|
return showDialog(
|
||||||
context: context,
|
context: context,
|
||||||
builder: (dialogContext) => SimpleDialog(
|
builder: (dialogContext) => SimpleDialog(
|
||||||
title: FlowyText.medium(
|
|
||||||
LocaleKeys.settings_user_selectAnIcon.tr(),
|
|
||||||
fontSize: FontSizes.s16,
|
|
||||||
),
|
|
||||||
children: [
|
children: [
|
||||||
Container(
|
Container(
|
||||||
height: 380,
|
height: 380,
|
||||||
width: 360,
|
width: 360,
|
||||||
margin: const EdgeInsets.symmetric(horizontal: 12),
|
margin: const EdgeInsets.symmetric(horizontal: 12),
|
||||||
child: FlowyEmojiPicker(
|
child: FlowyIconPicker(
|
||||||
onEmojiSelected: (_, emoji) {
|
onSelected: (result) {
|
||||||
context
|
context.read<SettingsUserViewBloc>().add(
|
||||||
.read<SettingsUserViewBloc>()
|
SettingsUserEvent.updateUserIcon(iconUrl: result.emoji),
|
||||||
.add(SettingsUserEvent.updateUserIcon(iconUrl: emoji));
|
);
|
||||||
Navigator.of(dialogContext).pop();
|
Navigator.of(dialogContext).pop();
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
|
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
import 'package:appflowy/startup/startup.dart';
|
import 'package:appflowy/startup/startup.dart';
|
||||||
import 'package:appflowy/workspace/application/export/document_exporter.dart';
|
import 'package:appflowy/workspace/application/export/document_exporter.dart';
|
||||||
import 'package:appflowy/workspace/application/settings/settings_file_exporter_cubit.dart';
|
import 'package:appflowy/workspace/application/settings/settings_file_exporter_cubit.dart';
|
||||||
@ -13,8 +15,8 @@ import 'package:appflowy_backend/protobuf/flowy-folder/workspace.pb.dart';
|
|||||||
import 'package:appflowy_result/appflowy_result.dart';
|
import 'package:appflowy_result/appflowy_result.dart';
|
||||||
import 'package:easy_localization/easy_localization.dart';
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
import 'package:flowy_infra/file_picker/file_picker_service.dart';
|
import 'package:flowy_infra/file_picker/file_picker_service.dart';
|
||||||
|
import 'package:flowy_infra/theme_extension.dart';
|
||||||
import 'package:flowy_infra_ui/flowy_infra_ui.dart' hide WidgetBuilder;
|
import 'package:flowy_infra_ui/flowy_infra_ui.dart' hide WidgetBuilder;
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:path/path.dart' as p;
|
import 'package:path/path.dart' as p;
|
||||||
|
|
||||||
@ -64,6 +66,7 @@ class _FileExporterWidgetState extends State<FileExporterWidget> {
|
|||||||
.every((element) => element)
|
.every((element) => element)
|
||||||
? LocaleKeys.settings_files_deselectAll.tr()
|
? LocaleKeys.settings_files_deselectAll.tr()
|
||||||
: LocaleKeys.settings_files_selectAll.tr(),
|
: LocaleKeys.settings_files_selectAll.tr(),
|
||||||
|
fontColor: AFThemeExtension.of(context).textColor,
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
context
|
context
|
||||||
.read<SettingsFileExporterCubit>()
|
.read<SettingsFileExporterCubit>()
|
||||||
@ -93,13 +96,13 @@ class _FileExporterWidgetState extends State<FileExporterWidget> {
|
|||||||
const Spacer(),
|
const Spacer(),
|
||||||
FlowyTextButton(
|
FlowyTextButton(
|
||||||
LocaleKeys.button_cancel.tr(),
|
LocaleKeys.button_cancel.tr(),
|
||||||
onPressed: () {
|
fontColor: AFThemeExtension.of(context).textColor,
|
||||||
Navigator.of(context).pop();
|
onPressed: () => Navigator.of(context).pop(),
|
||||||
},
|
|
||||||
),
|
),
|
||||||
const HSpace(8),
|
const HSpace(8),
|
||||||
FlowyTextButton(
|
FlowyTextButton(
|
||||||
LocaleKeys.button_ok.tr(),
|
LocaleKeys.button_ok.tr(),
|
||||||
|
fontColor: AFThemeExtension.of(context).textColor,
|
||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
await getIt<FilePickerService>()
|
await getIt<FilePickerService>()
|
||||||
.getDirectoryPath()
|
.getDirectoryPath()
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
import 'package:appflowy/generated/flowy_svgs.g.dart';
|
import 'package:appflowy/generated/flowy_svgs.g.dart';
|
||||||
import 'package:appflowy/generated/locale_keys.g.dart';
|
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||||
import 'package:appflowy/plugins/document/application/document_appearance_cubit.dart';
|
import 'package:appflowy/plugins/document/application/document_appearance_cubit.dart';
|
||||||
@ -8,8 +10,8 @@ import 'package:appflowy/workspace/application/settings/appearance/appearance_cu
|
|||||||
import 'package:appflowy_popover/appflowy_popover.dart';
|
import 'package:appflowy_popover/appflowy_popover.dart';
|
||||||
import 'package:collection/collection.dart';
|
import 'package:collection/collection.dart';
|
||||||
import 'package:easy_localization/easy_localization.dart';
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
|
import 'package:flowy_infra/theme_extension.dart';
|
||||||
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:google_fonts/google_fonts.dart';
|
import 'package:google_fonts/google_fonts.dart';
|
||||||
|
|
||||||
@ -208,9 +210,7 @@ class _FontFamilyDropDownState extends State<FontFamilyDropDown> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class _ResetFontButton extends SliverPersistentHeaderDelegate {
|
class _ResetFontButton extends SliverPersistentHeaderDelegate {
|
||||||
_ResetFontButton({
|
_ResetFontButton({this.onPressed});
|
||||||
this.onPressed,
|
|
||||||
});
|
|
||||||
|
|
||||||
final VoidCallback? onPressed;
|
final VoidCallback? onPressed;
|
||||||
|
|
||||||
@ -224,6 +224,9 @@ class _ResetFontButton extends SliverPersistentHeaderDelegate {
|
|||||||
padding: const EdgeInsets.only(right: 8, bottom: 8.0),
|
padding: const EdgeInsets.only(right: 8, bottom: 8.0),
|
||||||
child: FlowyTextButton(
|
child: FlowyTextButton(
|
||||||
LocaleKeys.document_toolbar_resetToDefaultFont.tr(),
|
LocaleKeys.document_toolbar_resetToDefaultFont.tr(),
|
||||||
|
fontColor: AFThemeExtension.of(context).textColor,
|
||||||
|
fontHoverColor: Theme.of(context).colorScheme.onSurface,
|
||||||
|
fontSize: 12,
|
||||||
onPressed: onPressed,
|
onPressed: onPressed,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
@ -9,6 +9,7 @@ import 'package:appflowy/workspace/presentation/settings/shared/settings_body.da
|
|||||||
import 'package:appflowy/workspace/presentation/settings/shared/settings_header.dart';
|
import 'package:appflowy/workspace/presentation/settings/shared/settings_header.dart';
|
||||||
import 'package:appflowy_editor/appflowy_editor.dart';
|
import 'package:appflowy_editor/appflowy_editor.dart';
|
||||||
import 'package:easy_localization/easy_localization.dart';
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
|
import 'package:flowy_infra/theme_extension.dart';
|
||||||
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
|
||||||
@ -75,6 +76,7 @@ class ShortcutsListView extends StatelessWidget {
|
|||||||
const Spacer(),
|
const Spacer(),
|
||||||
FlowyTextButton(
|
FlowyTextButton(
|
||||||
LocaleKeys.settings_shortcuts_resetToDefault.tr(),
|
LocaleKeys.settings_shortcuts_resetToDefault.tr(),
|
||||||
|
fontColor: AFThemeExtension.of(context).textColor,
|
||||||
onPressed: () => context.read<ShortcutsCubit>().resetToDefault(),
|
onPressed: () => context.read<ShortcutsCubit>().resetToDefault(),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@ -109,9 +111,8 @@ class ShortcutsListTile extends StatelessWidget {
|
|||||||
FlowyTextButton(
|
FlowyTextButton(
|
||||||
shortcutEvent.command,
|
shortcutEvent.command,
|
||||||
fillColor: Colors.transparent,
|
fillColor: Colors.transparent,
|
||||||
onPressed: () {
|
fontColor: AFThemeExtension.of(context).textColor,
|
||||||
showKeyListenerDialog(context);
|
onPressed: () => showKeyListenerDialog(context),
|
||||||
},
|
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
@ -8,7 +8,6 @@ import 'package:appflowy/workspace/application/settings/settings_dialog_bloc.dar
|
|||||||
import 'package:appflowy/workspace/presentation/settings/widgets/settings_menu_element.dart';
|
import 'package:appflowy/workspace/presentation/settings/widgets/settings_menu_element.dart';
|
||||||
import 'package:appflowy_backend/protobuf/flowy-user/protobuf.dart';
|
import 'package:appflowy_backend/protobuf/flowy-user/protobuf.dart';
|
||||||
import 'package:easy_localization/easy_localization.dart';
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
import 'package:flowy_infra/theme_extension.dart';
|
|
||||||
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
||||||
|
|
||||||
class SettingsMenu extends StatelessWidget {
|
class SettingsMenu extends StatelessWidget {
|
||||||
@ -59,60 +58,42 @@ class SettingsMenu extends StatelessWidget {
|
|||||||
page: SettingsPage.appearance,
|
page: SettingsPage.appearance,
|
||||||
selectedPage: currentPage,
|
selectedPage: currentPage,
|
||||||
label: LocaleKeys.settings_menu_appearance.tr(),
|
label: LocaleKeys.settings_menu_appearance.tr(),
|
||||||
icon: Icon(
|
icon: const Icon(Icons.brightness_4),
|
||||||
Icons.brightness_4,
|
|
||||||
color: AFThemeExtension.of(context).textColor,
|
|
||||||
),
|
|
||||||
changeSelectedPage: changeSelectedPage,
|
changeSelectedPage: changeSelectedPage,
|
||||||
),
|
),
|
||||||
SettingsMenuElement(
|
SettingsMenuElement(
|
||||||
page: SettingsPage.language,
|
page: SettingsPage.language,
|
||||||
selectedPage: currentPage,
|
selectedPage: currentPage,
|
||||||
label: LocaleKeys.settings_menu_language.tr(),
|
label: LocaleKeys.settings_menu_language.tr(),
|
||||||
icon: Icon(
|
icon: const Icon(Icons.translate),
|
||||||
Icons.translate,
|
|
||||||
color: AFThemeExtension.of(context).textColor,
|
|
||||||
),
|
|
||||||
changeSelectedPage: changeSelectedPage,
|
changeSelectedPage: changeSelectedPage,
|
||||||
),
|
),
|
||||||
SettingsMenuElement(
|
SettingsMenuElement(
|
||||||
page: SettingsPage.files,
|
page: SettingsPage.files,
|
||||||
selectedPage: currentPage,
|
selectedPage: currentPage,
|
||||||
label: LocaleKeys.settings_menu_files.tr(),
|
label: LocaleKeys.settings_menu_files.tr(),
|
||||||
icon: Icon(
|
icon: const Icon(Icons.file_present_outlined),
|
||||||
Icons.file_present_outlined,
|
|
||||||
color: AFThemeExtension.of(context).textColor,
|
|
||||||
),
|
|
||||||
changeSelectedPage: changeSelectedPage,
|
changeSelectedPage: changeSelectedPage,
|
||||||
),
|
),
|
||||||
SettingsMenuElement(
|
SettingsMenuElement(
|
||||||
page: SettingsPage.notifications,
|
page: SettingsPage.notifications,
|
||||||
selectedPage: currentPage,
|
selectedPage: currentPage,
|
||||||
label: LocaleKeys.settings_menu_notifications.tr(),
|
label: LocaleKeys.settings_menu_notifications.tr(),
|
||||||
icon: Icon(
|
icon: const Icon(Icons.notifications_outlined),
|
||||||
Icons.notifications_outlined,
|
|
||||||
color: AFThemeExtension.of(context).textColor,
|
|
||||||
),
|
|
||||||
changeSelectedPage: changeSelectedPage,
|
changeSelectedPage: changeSelectedPage,
|
||||||
),
|
),
|
||||||
SettingsMenuElement(
|
SettingsMenuElement(
|
||||||
page: SettingsPage.cloud,
|
page: SettingsPage.cloud,
|
||||||
selectedPage: currentPage,
|
selectedPage: currentPage,
|
||||||
label: LocaleKeys.settings_menu_cloudSettings.tr(),
|
label: LocaleKeys.settings_menu_cloudSettings.tr(),
|
||||||
icon: Icon(
|
icon: const Icon(Icons.sync),
|
||||||
Icons.sync,
|
|
||||||
color: AFThemeExtension.of(context).textColor,
|
|
||||||
),
|
|
||||||
changeSelectedPage: changeSelectedPage,
|
changeSelectedPage: changeSelectedPage,
|
||||||
),
|
),
|
||||||
SettingsMenuElement(
|
SettingsMenuElement(
|
||||||
page: SettingsPage.shortcuts,
|
page: SettingsPage.shortcuts,
|
||||||
selectedPage: currentPage,
|
selectedPage: currentPage,
|
||||||
label: LocaleKeys.settings_shortcuts_shortcutsLabel.tr(),
|
label: LocaleKeys.settings_shortcuts_shortcutsLabel.tr(),
|
||||||
icon: Icon(
|
icon: const Icon(Icons.cut),
|
||||||
Icons.cut,
|
|
||||||
color: AFThemeExtension.of(context).textColor,
|
|
||||||
),
|
|
||||||
changeSelectedPage: changeSelectedPage,
|
changeSelectedPage: changeSelectedPage,
|
||||||
),
|
),
|
||||||
if (FeatureFlag.membersSettings.isOn &&
|
if (FeatureFlag.membersSettings.isOn &&
|
||||||
@ -122,10 +103,7 @@ class SettingsMenu extends StatelessWidget {
|
|||||||
page: SettingsPage.member,
|
page: SettingsPage.member,
|
||||||
selectedPage: currentPage,
|
selectedPage: currentPage,
|
||||||
label: LocaleKeys.settings_appearance_members_label.tr(),
|
label: LocaleKeys.settings_appearance_members_label.tr(),
|
||||||
icon: Icon(
|
icon: const Icon(Icons.people),
|
||||||
Icons.people,
|
|
||||||
color: AFThemeExtension.of(context).textColor,
|
|
||||||
),
|
|
||||||
changeSelectedPage: changeSelectedPage,
|
changeSelectedPage: changeSelectedPage,
|
||||||
),
|
),
|
||||||
if (kDebugMode)
|
if (kDebugMode)
|
||||||
@ -134,10 +112,7 @@ class SettingsMenu extends StatelessWidget {
|
|||||||
page: SettingsPage.featureFlags,
|
page: SettingsPage.featureFlags,
|
||||||
selectedPage: currentPage,
|
selectedPage: currentPage,
|
||||||
label: 'Feature Flags',
|
label: 'Feature Flags',
|
||||||
icon: Icon(
|
icon: const Icon(Icons.flag),
|
||||||
Icons.flag,
|
|
||||||
color: AFThemeExtension.of(context).textColor,
|
|
||||||
),
|
|
||||||
changeSelectedPage: changeSelectedPage,
|
changeSelectedPage: changeSelectedPage,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
@ -31,9 +31,13 @@ class SettingsMenuElement extends StatelessWidget {
|
|||||||
hoverColor: AFThemeExtension.of(context).greySelect,
|
hoverColor: AFThemeExtension.of(context).greySelect,
|
||||||
borderRadius: BorderRadius.circular(4),
|
borderRadius: BorderRadius.circular(4),
|
||||||
),
|
),
|
||||||
child: ListTile(
|
builder: (_, isHovering) => ListTile(
|
||||||
dense: true,
|
dense: true,
|
||||||
leading: icon,
|
leading: iconWidget(
|
||||||
|
isHovering || page == selectedPage
|
||||||
|
? Theme.of(context).colorScheme.onSurface
|
||||||
|
: AFThemeExtension.of(context).textColor,
|
||||||
|
),
|
||||||
onTap: () => changeSelectedPage(page),
|
onTap: () => changeSelectedPage(page),
|
||||||
selected: page == selectedPage,
|
selected: page == selectedPage,
|
||||||
selectedColor: Theme.of(context).colorScheme.onSurface,
|
selectedColor: Theme.of(context).colorScheme.onSurface,
|
||||||
@ -53,4 +57,9 @@ class SettingsMenuElement extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Widget iconWidget(Color color) => IconTheme(
|
||||||
|
data: IconThemeData(color: color),
|
||||||
|
child: icon,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
@ -324,7 +324,7 @@
|
|||||||
"description": "Customize your profile, manage account security and AI API keys, or login into your account.",
|
"description": "Customize your profile, manage account security and AI API keys, or login into your account.",
|
||||||
"general": {
|
"general": {
|
||||||
"title": "Account name & profile image",
|
"title": "Account name & profile image",
|
||||||
"changeProfilePicture": "Change"
|
"changeProfilePicture": "Change profile picture"
|
||||||
},
|
},
|
||||||
"email": {
|
"email": {
|
||||||
"title": "Email",
|
"title": "Email",
|
||||||
|
Loading…
Reference in New Issue
Block a user