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