mirror of
				https://github.com/AppFlowy-IO/AppFlowy.git
				synced 2025-10-31 18:15:09 +00:00 
			
		
		
		
	feat: support settings on sign in page (#6342)
* feat: support settings on sign in page * feat: add settings entry in sign in page * feat: support exporting log files on desktop * chore: remove openfile dependency
This commit is contained in:
		
							parent
							
								
									d189c1ca4e
								
							
						
					
					
						commit
						c5afbb97a0
					
				| @ -56,6 +56,8 @@ PODS: | |||||||
|     - Flutter |     - Flutter | ||||||
|   - keyboard_height_plugin (0.0.1): |   - keyboard_height_plugin (0.0.1): | ||||||
|     - Flutter |     - Flutter | ||||||
|  |   - open_file_ios (0.0.1): | ||||||
|  |     - Flutter | ||||||
|   - open_filex (0.0.2): |   - open_filex (0.0.2): | ||||||
|     - Flutter |     - Flutter | ||||||
|   - package_info_plus (0.4.5): |   - package_info_plus (0.4.5): | ||||||
| @ -102,6 +104,7 @@ DEPENDENCIES: | |||||||
|   - integration_test (from `.symlinks/plugins/integration_test/ios`) |   - integration_test (from `.symlinks/plugins/integration_test/ios`) | ||||||
|   - irondash_engine_context (from `.symlinks/plugins/irondash_engine_context/ios`) |   - irondash_engine_context (from `.symlinks/plugins/irondash_engine_context/ios`) | ||||||
|   - keyboard_height_plugin (from `.symlinks/plugins/keyboard_height_plugin/ios`) |   - keyboard_height_plugin (from `.symlinks/plugins/keyboard_height_plugin/ios`) | ||||||
|  |   - open_file_ios (from `.symlinks/plugins/open_file_ios/ios`) | ||||||
|   - open_filex (from `.symlinks/plugins/open_filex/ios`) |   - open_filex (from `.symlinks/plugins/open_filex/ios`) | ||||||
|   - package_info_plus (from `.symlinks/plugins/package_info_plus/ios`) |   - package_info_plus (from `.symlinks/plugins/package_info_plus/ios`) | ||||||
|   - path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/darwin`) |   - path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/darwin`) | ||||||
| @ -148,6 +151,8 @@ EXTERNAL SOURCES: | |||||||
|     :path: ".symlinks/plugins/irondash_engine_context/ios" |     :path: ".symlinks/plugins/irondash_engine_context/ios" | ||||||
|   keyboard_height_plugin: |   keyboard_height_plugin: | ||||||
|     :path: ".symlinks/plugins/keyboard_height_plugin/ios" |     :path: ".symlinks/plugins/keyboard_height_plugin/ios" | ||||||
|  |   open_file_ios: | ||||||
|  |     :path: ".symlinks/plugins/open_file_ios/ios" | ||||||
|   open_filex: |   open_filex: | ||||||
|     :path: ".symlinks/plugins/open_filex/ios" |     :path: ".symlinks/plugins/open_filex/ios" | ||||||
|   package_info_plus: |   package_info_plus: | ||||||
| @ -184,6 +189,7 @@ SPEC CHECKSUMS: | |||||||
|   integration_test: ce0a3ffa1de96d1a89ca0ac26fca7ea18a749ef4 |   integration_test: ce0a3ffa1de96d1a89ca0ac26fca7ea18a749ef4 | ||||||
|   irondash_engine_context: 3458bf979b90d616ffb8ae03a150bafe2e860cc9 |   irondash_engine_context: 3458bf979b90d616ffb8ae03a150bafe2e860cc9 | ||||||
|   keyboard_height_plugin: 43fa8bba20fd5c4fdeed5076466b8b9d43cc6b86 |   keyboard_height_plugin: 43fa8bba20fd5c4fdeed5076466b8b9d43cc6b86 | ||||||
|  |   open_file_ios: 461db5853723763573e140de3193656f91990d9e | ||||||
|   open_filex: 6e26e659846ec990262224a12ef1c528bb4edbe4 |   open_filex: 6e26e659846ec990262224a12ef1c528bb4edbe4 | ||||||
|   package_info_plus: 58f0028419748fad15bf008b270aaa8e54380b1c |   package_info_plus: 58f0028419748fad15bf008b270aaa8e54380b1c | ||||||
|   path_provider_foundation: 2b6b4c569c0fb62ec74538f866245ac84301af46 |   path_provider_foundation: 2b6b4c569c0fb62ec74538f866245ac84301af46 | ||||||
|  | |||||||
| @ -0,0 +1,67 @@ | |||||||
|  | import 'package:appflowy/plugins/document/application/document_appearance_cubit.dart'; | ||||||
|  | import 'package:appflowy/startup/startup.dart'; | ||||||
|  | import 'package:appflowy/workspace/application/settings/settings_dialog_bloc.dart'; | ||||||
|  | import 'package:appflowy/workspace/application/user/user_workspace_bloc.dart'; | ||||||
|  | import 'package:appflowy/workspace/presentation/home/af_focus_manager.dart'; | ||||||
|  | import 'package:appflowy/workspace/presentation/settings/settings_dialog.dart'; | ||||||
|  | import 'package:appflowy_backend/log.dart'; | ||||||
|  | import 'package:appflowy_backend/protobuf/flowy-user/protobuf.dart' | ||||||
|  |     show UserProfilePB; | ||||||
|  | import 'package:flutter/material.dart'; | ||||||
|  | import 'package:flutter_bloc/flutter_bloc.dart'; | ||||||
|  | 
 | ||||||
|  | final GlobalKey _settingsDialogKey = GlobalKey(); | ||||||
|  | 
 | ||||||
|  | // show settings dialog with user profile for fully customized settings dialog | ||||||
|  | void showSettingsDialog( | ||||||
|  |   BuildContext context, | ||||||
|  |   UserProfilePB userProfile, [ | ||||||
|  |   UserWorkspaceBloc? bloc, | ||||||
|  |   SettingsPage? initPage, | ||||||
|  | ]) { | ||||||
|  |   AFFocusManager.of(context).notifyLoseFocus(); | ||||||
|  |   showDialog( | ||||||
|  |     context: context, | ||||||
|  |     builder: (dialogContext) => MultiBlocProvider( | ||||||
|  |       key: _settingsDialogKey, | ||||||
|  |       providers: [ | ||||||
|  |         BlocProvider<DocumentAppearanceCubit>.value( | ||||||
|  |           value: BlocProvider.of<DocumentAppearanceCubit>(dialogContext), | ||||||
|  |         ), | ||||||
|  |         BlocProvider.value(value: bloc ?? context.read<UserWorkspaceBloc>()), | ||||||
|  |       ], | ||||||
|  |       child: SettingsDialog( | ||||||
|  |         userProfile, | ||||||
|  |         initPage: initPage, | ||||||
|  |         didLogout: () async { | ||||||
|  |           // Pop the dialog using the dialog context | ||||||
|  |           Navigator.of(dialogContext).pop(); | ||||||
|  |           await runAppFlowy(); | ||||||
|  |         }, | ||||||
|  |         dismissDialog: () { | ||||||
|  |           if (Navigator.of(dialogContext).canPop()) { | ||||||
|  |             return Navigator.of(dialogContext).pop(); | ||||||
|  |           } | ||||||
|  |           Log.warn("Can't pop dialog context"); | ||||||
|  |         }, | ||||||
|  |         restartApp: () async { | ||||||
|  |           // Pop the dialog using the dialog context | ||||||
|  |           Navigator.of(dialogContext).pop(); | ||||||
|  |           await runAppFlowy(); | ||||||
|  |         }, | ||||||
|  |       ), | ||||||
|  |     ), | ||||||
|  |   ); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // show settings dialog without user profile for simple settings dialog | ||||||
|  | // only support | ||||||
|  | //  - language | ||||||
|  | //  - self-host | ||||||
|  | //  - support | ||||||
|  | void showSimpleSettingsDialog(BuildContext context) { | ||||||
|  |   showDialog( | ||||||
|  |     context: context, | ||||||
|  |     builder: (dialogContext) => const SimpleSettingsDialog(), | ||||||
|  |   ); | ||||||
|  | } | ||||||
| @ -1,6 +1,7 @@ | |||||||
| import 'package:appflowy/core/frameless_window.dart'; | import 'package:appflowy/core/frameless_window.dart'; | ||||||
| import 'package:appflowy/env/cloud_env.dart'; | import 'package:appflowy/env/cloud_env.dart'; | ||||||
| import 'package:appflowy/generated/locale_keys.g.dart'; | import 'package:appflowy/generated/locale_keys.g.dart'; | ||||||
|  | import 'package:appflowy/shared/settings/show_settings.dart'; | ||||||
| import 'package:appflowy/shared/window_title_bar.dart'; | import 'package:appflowy/shared/window_title_bar.dart'; | ||||||
| import 'package:appflowy/user/application/sign_in_bloc.dart'; | import 'package:appflowy/user/application/sign_in_bloc.dart'; | ||||||
| import 'package:appflowy/user/presentation/screens/sign_in_screen/widgets/widgets.dart'; | import 'package:appflowy/user/presentation/screens/sign_in_screen/widgets/widgets.dart'; | ||||||
| @ -63,8 +64,15 @@ class DesktopSignInScreen extends StatelessWidget { | |||||||
| 
 | 
 | ||||||
|                 const Spacer(), |                 const Spacer(), | ||||||
| 
 | 
 | ||||||
|                 // anonymous sign in |                 // anonymous sign in and settings | ||||||
|                 const SignInAnonymousButtonV2(), |                 const Row( | ||||||
|  |                   mainAxisSize: MainAxisSize.min, | ||||||
|  |                   children: [ | ||||||
|  |                     _SettingsButton(), | ||||||
|  |                     HSpace(42), | ||||||
|  |                     SignInAnonymousButtonV2(), | ||||||
|  |                   ], | ||||||
|  |                 ), | ||||||
|                 const VSpace(16), |                 const VSpace(16), | ||||||
|               ], |               ], | ||||||
|             ), |             ), | ||||||
| @ -84,6 +92,28 @@ class DesktopSignInScreen extends StatelessWidget { | |||||||
|   } |   } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | class _SettingsButton extends StatelessWidget { | ||||||
|  |   const _SettingsButton(); | ||||||
|  | 
 | ||||||
|  |   @override | ||||||
|  |   Widget build(BuildContext context) { | ||||||
|  |     return FlowyButton( | ||||||
|  |       useIntrinsicWidth: true, | ||||||
|  |       text: FlowyText( | ||||||
|  |         LocaleKeys.signIn_settings.tr(), | ||||||
|  |         textAlign: TextAlign.center, | ||||||
|  |         fontSize: 12.0, | ||||||
|  |         // fontWeight: FontWeight.w500, | ||||||
|  |         color: Colors.grey, | ||||||
|  |         decoration: TextDecoration.underline, | ||||||
|  |       ), | ||||||
|  |       onTap: () { | ||||||
|  |         showSimpleSettingsDialog(context); | ||||||
|  |       }, | ||||||
|  |     ); | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | 
 | ||||||
| class _OrDivider extends StatelessWidget { | class _OrDivider extends StatelessWidget { | ||||||
|   const _OrDivider(); |   const _OrDivider(); | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -118,16 +118,7 @@ class MobileSignInScreen extends StatelessWidget { | |||||||
|           }, |           }, | ||||||
|         ), |         ), | ||||||
|         const HSpace(24), |         const HSpace(24), | ||||||
|         SignInAnonymousButtonV2( |         const SignInAnonymousButtonV2(), | ||||||
|           child: FlowyText( |  | ||||||
|             LocaleKeys.signIn_anonymous.tr(), |  | ||||||
|             textAlign: TextAlign.center, |  | ||||||
|             fontSize: 12.0, |  | ||||||
|             // fontWeight: FontWeight.w500, |  | ||||||
|             color: Colors.grey, |  | ||||||
|             decoration: TextDecoration.underline, |  | ||||||
|           ), |  | ||||||
|         ), |  | ||||||
|       ], |       ], | ||||||
|     ); |     ); | ||||||
|   } |   } | ||||||
|  | |||||||
| @ -89,11 +89,8 @@ class SignInAnonymousButton extends StatelessWidget { | |||||||
| class SignInAnonymousButtonV2 extends StatelessWidget { | class SignInAnonymousButtonV2 extends StatelessWidget { | ||||||
|   const SignInAnonymousButtonV2({ |   const SignInAnonymousButtonV2({ | ||||||
|     super.key, |     super.key, | ||||||
|     this.child, |  | ||||||
|   }); |   }); | ||||||
| 
 | 
 | ||||||
|   final Widget? child; |  | ||||||
| 
 |  | ||||||
|   @override |   @override | ||||||
|   Widget build(BuildContext context) { |   Widget build(BuildContext context) { | ||||||
|     return BlocBuilder<SignInBloc, SignInState>( |     return BlocBuilder<SignInBloc, SignInState>( | ||||||
| @ -111,9 +108,7 @@ class SignInAnonymousButtonV2 extends StatelessWidget { | |||||||
|             }, |             }, | ||||||
|             child: BlocBuilder<AnonUserBloc, AnonUserState>( |             child: BlocBuilder<AnonUserBloc, AnonUserState>( | ||||||
|               builder: (context, state) { |               builder: (context, state) { | ||||||
|                 final text = state.anonUsers.isEmpty |                 final text = LocaleKeys.signIn_anonymous.tr(); | ||||||
|                     ? LocaleKeys.signIn_loginStartWithAnonymous.tr() |  | ||||||
|                     : LocaleKeys.signIn_continueAnonymousUser.tr(); |  | ||||||
|                 final onTap = state.anonUsers.isEmpty |                 final onTap = state.anonUsers.isEmpty | ||||||
|                     ? () { |                     ? () { | ||||||
|                         context |                         context | ||||||
| @ -125,16 +120,14 @@ class SignInAnonymousButtonV2 extends StatelessWidget { | |||||||
|                         final user = bloc.state.anonUsers.first; |                         final user = bloc.state.anonUsers.first; | ||||||
|                         bloc.add(AnonUserEvent.openAnonUser(user)); |                         bloc.add(AnonUserEvent.openAnonUser(user)); | ||||||
|                       }; |                       }; | ||||||
|                 return MouseRegion( |                 return FlowyButton( | ||||||
|                   cursor: SystemMouseCursors.click, |                   useIntrinsicWidth: true, | ||||||
|                   child: GestureDetector( |                   onTap: onTap, | ||||||
|                     onTap: onTap, |                   text: FlowyText( | ||||||
|                     child: child ?? |                     text, | ||||||
|                         FlowyText( |                     color: Colors.grey, | ||||||
|                           text, |                     decoration: TextDecoration.underline, | ||||||
|                           color: Colors.blue, |                     fontSize: 12, | ||||||
|                           fontSize: 12, |  | ||||||
|                         ), |  | ||||||
|                   ), |                   ), | ||||||
|                 ); |                 ); | ||||||
|               }, |               }, | ||||||
|  | |||||||
| @ -99,17 +99,20 @@ class _DesktopThirdPartySignInState extends State<_DesktopThirdPartySignIn> { | |||||||
|   List<Widget> _buildCollapsedButtons() { |   List<Widget> _buildCollapsedButtons() { | ||||||
|     return [ |     return [ | ||||||
|       const VSpace(padding), |       const VSpace(padding), | ||||||
|       GestureDetector( |       MouseRegion( | ||||||
|         onTap: () { |         cursor: SystemMouseCursors.click, | ||||||
|           setState(() { |         child: GestureDetector( | ||||||
|             isExpanded = !isExpanded; |           onTap: () { | ||||||
|           }); |             setState(() { | ||||||
|         }, |               isExpanded = !isExpanded; | ||||||
|         child: FlowyText( |             }); | ||||||
|           LocaleKeys.signIn_continueAnotherWay.tr(), |           }, | ||||||
|           color: Theme.of(context).colorScheme.onSurface, |           child: FlowyText( | ||||||
|           decoration: TextDecoration.underline, |             LocaleKeys.signIn_continueAnotherWay.tr(), | ||||||
|           fontSize: 14, |             color: Theme.of(context).colorScheme.onSurface, | ||||||
|  |             decoration: TextDecoration.underline, | ||||||
|  |             fontSize: 14, | ||||||
|  |           ), | ||||||
|         ), |         ), | ||||||
|       ), |       ), | ||||||
|     ]; |     ]; | ||||||
|  | |||||||
| @ -5,6 +5,7 @@ import 'package:appflowy/workspace/presentation/widgets/dialogs.dart'; | |||||||
| import 'package:archive/archive_io.dart'; | import 'package:archive/archive_io.dart'; | ||||||
| import 'package:easy_localization/easy_localization.dart'; | import 'package:easy_localization/easy_localization.dart'; | ||||||
| import 'package:flutter/material.dart'; | import 'package:flutter/material.dart'; | ||||||
|  | import 'package:open_filex/open_filex.dart'; | ||||||
| import 'package:path/path.dart' as p; | import 'package:path/path.dart' as p; | ||||||
| import 'package:path_provider/path_provider.dart'; | import 'package:path_provider/path_provider.dart'; | ||||||
| import 'package:share_plus/share_plus.dart'; | import 'package:share_plus/share_plus.dart'; | ||||||
| @ -59,12 +60,16 @@ Future<void> shareLogFiles(BuildContext? context) async { | |||||||
| 
 | 
 | ||||||
|     if (Platform.isIOS) { |     if (Platform.isIOS) { | ||||||
|       await Share.shareUri(zipFile.uri); |       await Share.shareUri(zipFile.uri); | ||||||
|     } else { |       // delete the zipped appflowy logs file | ||||||
|  |       await zipFile.delete(); | ||||||
|  |     } else if (Platform.isAndroid) { | ||||||
|       await Share.shareXFiles([XFile(zipFile.path)]); |       await Share.shareXFiles([XFile(zipFile.path)]); | ||||||
|  |       // delete the zipped appflowy logs file | ||||||
|  |       await zipFile.delete(); | ||||||
|  |     } else { | ||||||
|  |       // open the directory | ||||||
|  |       await OpenFilex.open(zipFile.path); | ||||||
|     } |     } | ||||||
| 
 |  | ||||||
|     // delete the zipped appflowy logs file |  | ||||||
|     await zipFile.delete(); |  | ||||||
|   } catch (e) { |   } catch (e) { | ||||||
|     if (context != null && context.mounted) { |     if (context != null && context.mounted) { | ||||||
|       showToastNotification( |       showToastNotification( | ||||||
|  | |||||||
| @ -6,6 +6,7 @@ import 'package:appflowy/generated/locale_keys.g.dart'; | |||||||
| import 'package:appflowy/shared/appflowy_cache_manager.dart'; | import 'package:appflowy/shared/appflowy_cache_manager.dart'; | ||||||
| import 'package:appflowy/startup/startup.dart'; | import 'package:appflowy/startup/startup.dart'; | ||||||
| import 'package:appflowy/startup/tasks/rust_sdk.dart'; | import 'package:appflowy/startup/tasks/rust_sdk.dart'; | ||||||
|  | import 'package:appflowy/util/share_log_files.dart'; | ||||||
| import 'package:appflowy/util/theme_extension.dart'; | import 'package:appflowy/util/theme_extension.dart'; | ||||||
| import 'package:appflowy/workspace/application/settings/setting_file_importer_bloc.dart'; | import 'package:appflowy/workspace/application/settings/setting_file_importer_bloc.dart'; | ||||||
| import 'package:appflowy/workspace/application/settings/settings_location_cubit.dart'; | import 'package:appflowy/workspace/application/settings/settings_location_cubit.dart'; | ||||||
| @ -112,6 +113,20 @@ class SettingsManageDataView extends StatelessWidget { | |||||||
|                   ], |                   ], | ||||||
|                 ), |                 ), | ||||||
|               ], |               ], | ||||||
|  |               SettingsCategory( | ||||||
|  |                 title: LocaleKeys.workspace_errorActions_exportLogFiles.tr(), | ||||||
|  |                 children: [ | ||||||
|  |                   SingleSettingAction( | ||||||
|  |                     labelMaxLines: 4, | ||||||
|  |                     label: | ||||||
|  |                         LocaleKeys.workspace_errorActions_exportLogFiles.tr(), | ||||||
|  |                     buttonLabel: LocaleKeys.settings_files_export.tr(), | ||||||
|  |                     onPressed: () { | ||||||
|  |                       shareLogFiles(context); | ||||||
|  |                     }, | ||||||
|  |                   ), | ||||||
|  |                 ], | ||||||
|  |               ), | ||||||
|               SettingsCategory( |               SettingsCategory( | ||||||
|                 title: LocaleKeys.settings_manageDataPage_cache_title.tr(), |                 title: LocaleKeys.settings_manageDataPage_cache_title.tr(), | ||||||
|                 children: [ |                 children: [ | ||||||
|  | |||||||
| @ -1,5 +1,9 @@ | |||||||
| import 'package:flutter/material.dart'; | import 'package:appflowy/env/cloud_env.dart'; | ||||||
| 
 | import 'package:appflowy/generated/locale_keys.g.dart'; | ||||||
|  | import 'package:appflowy/shared/appflowy_cache_manager.dart'; | ||||||
|  | import 'package:appflowy/startup/startup.dart'; | ||||||
|  | import 'package:appflowy/util/share_log_files.dart'; | ||||||
|  | import 'package:appflowy/workspace/application/settings/appflowy_cloud_urls_bloc.dart'; | ||||||
| import 'package:appflowy/workspace/application/settings/settings_dialog_bloc.dart'; | import 'package:appflowy/workspace/application/settings/settings_dialog_bloc.dart'; | ||||||
| import 'package:appflowy/workspace/application/user/user_workspace_bloc.dart'; | import 'package:appflowy/workspace/application/user/user_workspace_bloc.dart'; | ||||||
| import 'package:appflowy/workspace/presentation/settings/pages/setting_ai_view/settings_ai_view.dart'; | import 'package:appflowy/workspace/presentation/settings/pages/setting_ai_view/settings_ai_view.dart'; | ||||||
| @ -9,12 +13,18 @@ import 'package:appflowy/workspace/presentation/settings/pages/settings_manage_d | |||||||
| import 'package:appflowy/workspace/presentation/settings/pages/settings_plan_view.dart'; | import 'package:appflowy/workspace/presentation/settings/pages/settings_plan_view.dart'; | ||||||
| import 'package:appflowy/workspace/presentation/settings/pages/settings_shortcuts_view.dart'; | import 'package:appflowy/workspace/presentation/settings/pages/settings_shortcuts_view.dart'; | ||||||
| import 'package:appflowy/workspace/presentation/settings/pages/settings_workspace_view.dart'; | import 'package:appflowy/workspace/presentation/settings/pages/settings_workspace_view.dart'; | ||||||
|  | import 'package:appflowy/workspace/presentation/settings/shared/settings_category.dart'; | ||||||
|  | import 'package:appflowy/workspace/presentation/settings/shared/settings_category_spacer.dart'; | ||||||
| import 'package:appflowy/workspace/presentation/settings/widgets/feature_flags/feature_flag_page.dart'; | import 'package:appflowy/workspace/presentation/settings/widgets/feature_flags/feature_flag_page.dart'; | ||||||
| import 'package:appflowy/workspace/presentation/settings/widgets/members/workspace_member_page.dart'; | import 'package:appflowy/workspace/presentation/settings/widgets/members/workspace_member_page.dart'; | ||||||
| import 'package:appflowy/workspace/presentation/settings/widgets/settings_menu.dart'; | import 'package:appflowy/workspace/presentation/settings/widgets/settings_menu.dart'; | ||||||
| import 'package:appflowy/workspace/presentation/settings/widgets/settings_notifications_view.dart'; | import 'package:appflowy/workspace/presentation/settings/widgets/settings_notifications_view.dart'; | ||||||
|  | import 'package:appflowy/workspace/presentation/widgets/dialogs.dart'; | ||||||
|  | import 'package:appflowy_backend/log.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: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 'widgets/setting_cloud.dart'; | import 'widgets/setting_cloud.dart'; | ||||||
| @ -28,11 +38,11 @@ class SettingsDialog extends StatelessWidget { | |||||||
|     this.initPage, |     this.initPage, | ||||||
|   }) : super(key: ValueKey(user.id)); |   }) : super(key: ValueKey(user.id)); | ||||||
| 
 | 
 | ||||||
|  |   final UserProfilePB user; | ||||||
|  |   final SettingsPage? initPage; | ||||||
|   final VoidCallback dismissDialog; |   final VoidCallback dismissDialog; | ||||||
|   final VoidCallback didLogout; |   final VoidCallback didLogout; | ||||||
|   final VoidCallback restartApp; |   final VoidCallback restartApp; | ||||||
|   final UserProfilePB user; |  | ||||||
|   final SettingsPage? initPage; |  | ||||||
| 
 | 
 | ||||||
|   @override |   @override | ||||||
|   Widget build(BuildContext context) { |   Widget build(BuildContext context) { | ||||||
| @ -144,3 +154,164 @@ class SettingsDialog extends StatelessWidget { | |||||||
|     } |     } | ||||||
|   } |   } | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | class SimpleSettingsDialog extends StatefulWidget { | ||||||
|  |   const SimpleSettingsDialog({super.key}); | ||||||
|  | 
 | ||||||
|  |   @override | ||||||
|  |   State<SimpleSettingsDialog> createState() => _SimpleSettingsDialogState(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | class _SimpleSettingsDialogState extends State<SimpleSettingsDialog> { | ||||||
|  |   SettingsPage page = SettingsPage.cloud; | ||||||
|  | 
 | ||||||
|  |   @override | ||||||
|  |   Widget build(BuildContext context) { | ||||||
|  |     return FlowyDialog( | ||||||
|  |       width: MediaQuery.of(context).size.width * 0.7, | ||||||
|  |       constraints: const BoxConstraints(maxWidth: 784, minWidth: 564), | ||||||
|  |       child: const Padding( | ||||||
|  |         padding: EdgeInsets.all(24.0), | ||||||
|  |         child: Column( | ||||||
|  |           mainAxisSize: MainAxisSize.min, | ||||||
|  |           children: [ | ||||||
|  |             // language | ||||||
|  |             _LanguageSettings(), | ||||||
|  |             SettingsCategorySpacer(), | ||||||
|  |             // self-host cloud | ||||||
|  |             _SelfHostSettings(), | ||||||
|  |             SettingsCategorySpacer(), | ||||||
|  |             // support | ||||||
|  |             _SupportSettings(), | ||||||
|  |           ], | ||||||
|  |         ), | ||||||
|  |       ), | ||||||
|  |     ); | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | class _LanguageSettings extends StatelessWidget { | ||||||
|  |   const _LanguageSettings(); | ||||||
|  | 
 | ||||||
|  |   @override | ||||||
|  |   Widget build(BuildContext context) { | ||||||
|  |     return SettingsCategory( | ||||||
|  |       title: LocaleKeys.settings_workspacePage_language_title.tr(), | ||||||
|  |       children: const [LanguageDropdown()], | ||||||
|  |     ); | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | class _SelfHostSettings extends StatefulWidget { | ||||||
|  |   const _SelfHostSettings(); | ||||||
|  | 
 | ||||||
|  |   @override | ||||||
|  |   State<_SelfHostSettings> createState() => _SelfHostSettingsState(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | class _SelfHostSettingsState extends State<_SelfHostSettings> { | ||||||
|  |   final textController = TextEditingController(); | ||||||
|  | 
 | ||||||
|  |   @override | ||||||
|  |   void initState() { | ||||||
|  |     super.initState(); | ||||||
|  | 
 | ||||||
|  |     getAppFlowyCloudUrl().then((url) { | ||||||
|  |       textController.text = url; | ||||||
|  |     }); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   @override | ||||||
|  |   void dispose() { | ||||||
|  |     textController.dispose(); | ||||||
|  |     super.dispose(); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   @override | ||||||
|  |   Widget build(BuildContext context) { | ||||||
|  |     return SettingsCategory( | ||||||
|  |       title: LocaleKeys.settings_menu_cloudAppFlowySelfHost.tr(), | ||||||
|  |       children: [ | ||||||
|  |         SizedBox( | ||||||
|  |           height: 48, | ||||||
|  |           child: FlowyTextField( | ||||||
|  |             controller: textController, | ||||||
|  |             autoFocus: false, | ||||||
|  |             textStyle: const TextStyle( | ||||||
|  |               fontSize: 14, | ||||||
|  |               fontWeight: FontWeight.w400, | ||||||
|  |             ), | ||||||
|  |             onEditingComplete: _saveSelfHostUrl, | ||||||
|  |           ), | ||||||
|  |         ), | ||||||
|  |       ], | ||||||
|  |     ); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   void _saveSelfHostUrl() { | ||||||
|  |     final url = textController.text; | ||||||
|  |     if (url.isEmpty) { | ||||||
|  |       return; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     validateUrl(url).fold( | ||||||
|  |       (url) async { | ||||||
|  |         Navigator.of(context).pop(); | ||||||
|  |         await useSelfHostedAppFlowyCloudWithURL(url); | ||||||
|  |         await runAppFlowy(); | ||||||
|  |       }, | ||||||
|  |       (err) => Log.error(err), | ||||||
|  |     ); | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | class _SupportSettings extends StatelessWidget { | ||||||
|  |   const _SupportSettings(); | ||||||
|  | 
 | ||||||
|  |   @override | ||||||
|  |   Widget build(BuildContext context) { | ||||||
|  |     return SettingsCategory( | ||||||
|  |       title: LocaleKeys.settings_mobile_support.tr(), | ||||||
|  |       children: [ | ||||||
|  |         // export logs | ||||||
|  |         Row( | ||||||
|  |           children: [ | ||||||
|  |             FlowyText( | ||||||
|  |               LocaleKeys.workspace_errorActions_exportLogFiles.tr(), | ||||||
|  |             ), | ||||||
|  |             const Spacer(), | ||||||
|  |             OutlinedRoundedButton( | ||||||
|  |               text: LocaleKeys.settings_files_export.tr(), | ||||||
|  |               onTap: () { | ||||||
|  |                 shareLogFiles(context); | ||||||
|  |               }, | ||||||
|  |             ), | ||||||
|  |           ], | ||||||
|  |         ), | ||||||
|  |         // clear cache | ||||||
|  |         Row( | ||||||
|  |           children: [ | ||||||
|  |             FlowyText( | ||||||
|  |               LocaleKeys.settings_files_clearCache.tr(), | ||||||
|  |             ), | ||||||
|  |             const Spacer(), | ||||||
|  |             OutlinedRoundedButton( | ||||||
|  |               text: LocaleKeys.button_clear.tr(), | ||||||
|  |               onTap: () async { | ||||||
|  |                 await getIt<FlowyCacheManager>().clearAllCache(); | ||||||
|  |                 if (context.mounted) { | ||||||
|  |                   showToastNotification( | ||||||
|  |                     context, | ||||||
|  |                     message: LocaleKeys | ||||||
|  |                         .settings_manageDataPage_cache_dialog_successHint | ||||||
|  |                         .tr(), | ||||||
|  |                   ); | ||||||
|  |                 } | ||||||
|  |               }, | ||||||
|  |             ), | ||||||
|  |           ], | ||||||
|  |         ), | ||||||
|  |       ], | ||||||
|  |     ); | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | |||||||
| @ -23,7 +23,10 @@ import 'package:universal_platform/universal_platform.dart'; | |||||||
| import 'setting_appflowy_cloud.dart'; | import 'setting_appflowy_cloud.dart'; | ||||||
| 
 | 
 | ||||||
| class SettingCloud extends StatelessWidget { | class SettingCloud extends StatelessWidget { | ||||||
|   const SettingCloud({required this.restartAppFlowy, super.key}); |   const SettingCloud({ | ||||||
|  |     super.key, | ||||||
|  |     required this.restartAppFlowy, | ||||||
|  |   }); | ||||||
| 
 | 
 | ||||||
|   final VoidCallback restartAppFlowy; |   final VoidCallback restartAppFlowy; | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -1,6 +1,3 @@ | |||||||
| import 'package:flutter/foundation.dart'; |  | ||||||
| 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/shared/feature_flags.dart'; | import 'package:appflowy/shared/feature_flags.dart'; | ||||||
| @ -9,6 +6,8 @@ import 'package:appflowy/workspace/presentation/settings/widgets/settings_menu_e | |||||||
| 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/foundation.dart'; | ||||||
|  | import 'package:flutter/material.dart'; | ||||||
| 
 | 
 | ||||||
| class SettingsMenu extends StatelessWidget { | class SettingsMenu extends StatelessWidget { | ||||||
|   const SettingsMenu({ |   const SettingsMenu({ | ||||||
| @ -147,3 +146,56 @@ class SettingsMenu extends StatelessWidget { | |||||||
|     ); |     ); | ||||||
|   } |   } | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | class SimpleSettingsMenu extends StatelessWidget { | ||||||
|  |   const SimpleSettingsMenu({super.key}); | ||||||
|  | 
 | ||||||
|  |   @override | ||||||
|  |   Widget build(BuildContext context) { | ||||||
|  |     return Column( | ||||||
|  |       children: [ | ||||||
|  |         Expanded( | ||||||
|  |           child: Container( | ||||||
|  |             padding: const EdgeInsets.symmetric(vertical: 8) + | ||||||
|  |                 const EdgeInsets.only(left: 8, right: 4), | ||||||
|  |             decoration: BoxDecoration( | ||||||
|  |               color: Theme.of(context).colorScheme.surfaceContainerHighest, | ||||||
|  |               borderRadius: const BorderRadius.only( | ||||||
|  |                 topLeft: Radius.circular(8), | ||||||
|  |                 bottomLeft: Radius.circular(8), | ||||||
|  |               ), | ||||||
|  |             ), | ||||||
|  |             child: SingleChildScrollView( | ||||||
|  |               // Right padding is added to make the scrollbar centered | ||||||
|  |               // in the space between the menu and the content | ||||||
|  |               padding: const EdgeInsets.only(right: 4) + | ||||||
|  |                   const EdgeInsets.symmetric(vertical: 16), | ||||||
|  |               physics: const ClampingScrollPhysics(), | ||||||
|  |               child: SeparatedColumn( | ||||||
|  |                 separatorBuilder: () => const VSpace(16), | ||||||
|  |                 children: [ | ||||||
|  |                   SettingsMenuElement( | ||||||
|  |                     page: SettingsPage.cloud, | ||||||
|  |                     selectedPage: SettingsPage.cloud, | ||||||
|  |                     label: LocaleKeys.settings_menu_cloudSettings.tr(), | ||||||
|  |                     icon: const Icon(Icons.sync), | ||||||
|  |                     changeSelectedPage: () {}, | ||||||
|  |                   ), | ||||||
|  |                   if (kDebugMode) | ||||||
|  |                     SettingsMenuElement( | ||||||
|  |                       // no need to translate this page | ||||||
|  |                       page: SettingsPage.featureFlags, | ||||||
|  |                       selectedPage: SettingsPage.cloud, | ||||||
|  |                       label: 'Feature Flags', | ||||||
|  |                       icon: const Icon(Icons.flag), | ||||||
|  |                       changeSelectedPage: () {}, | ||||||
|  |                     ), | ||||||
|  |                 ], | ||||||
|  |               ), | ||||||
|  |             ), | ||||||
|  |           ), | ||||||
|  |         ), | ||||||
|  |       ], | ||||||
|  |     ); | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | |||||||
| @ -25,6 +25,8 @@ PODS: | |||||||
|     - FlutterMacOS |     - FlutterMacOS | ||||||
|   - local_notifier (0.1.0): |   - local_notifier (0.1.0): | ||||||
|     - FlutterMacOS |     - FlutterMacOS | ||||||
|  |   - open_file_mac (0.0.1): | ||||||
|  |     - FlutterMacOS | ||||||
|   - package_info_plus (0.0.1): |   - package_info_plus (0.0.1): | ||||||
|     - FlutterMacOS |     - FlutterMacOS | ||||||
|   - path_provider_foundation (0.0.1): |   - path_provider_foundation (0.0.1): | ||||||
| @ -66,6 +68,7 @@ DEPENDENCIES: | |||||||
|   - hotkey_manager (from `Flutter/ephemeral/.symlinks/plugins/hotkey_manager/macos`) |   - hotkey_manager (from `Flutter/ephemeral/.symlinks/plugins/hotkey_manager/macos`) | ||||||
|   - irondash_engine_context (from `Flutter/ephemeral/.symlinks/plugins/irondash_engine_context/macos`) |   - irondash_engine_context (from `Flutter/ephemeral/.symlinks/plugins/irondash_engine_context/macos`) | ||||||
|   - local_notifier (from `Flutter/ephemeral/.symlinks/plugins/local_notifier/macos`) |   - local_notifier (from `Flutter/ephemeral/.symlinks/plugins/local_notifier/macos`) | ||||||
|  |   - open_file_mac (from `Flutter/ephemeral/.symlinks/plugins/open_file_mac/macos`) | ||||||
|   - package_info_plus (from `Flutter/ephemeral/.symlinks/plugins/package_info_plus/macos`) |   - package_info_plus (from `Flutter/ephemeral/.symlinks/plugins/package_info_plus/macos`) | ||||||
|   - path_provider_foundation (from `Flutter/ephemeral/.symlinks/plugins/path_provider_foundation/darwin`) |   - path_provider_foundation (from `Flutter/ephemeral/.symlinks/plugins/path_provider_foundation/darwin`) | ||||||
|   - screen_retriever (from `Flutter/ephemeral/.symlinks/plugins/screen_retriever/macos`) |   - screen_retriever (from `Flutter/ephemeral/.symlinks/plugins/screen_retriever/macos`) | ||||||
| @ -108,6 +111,8 @@ EXTERNAL SOURCES: | |||||||
|     :path: Flutter/ephemeral/.symlinks/plugins/irondash_engine_context/macos |     :path: Flutter/ephemeral/.symlinks/plugins/irondash_engine_context/macos | ||||||
|   local_notifier: |   local_notifier: | ||||||
|     :path: Flutter/ephemeral/.symlinks/plugins/local_notifier/macos |     :path: Flutter/ephemeral/.symlinks/plugins/local_notifier/macos | ||||||
|  |   open_file_mac: | ||||||
|  |     :path: Flutter/ephemeral/.symlinks/plugins/open_file_mac/macos | ||||||
|   package_info_plus: |   package_info_plus: | ||||||
|     :path: Flutter/ephemeral/.symlinks/plugins/package_info_plus/macos |     :path: Flutter/ephemeral/.symlinks/plugins/package_info_plus/macos | ||||||
|   path_provider_foundation: |   path_provider_foundation: | ||||||
| @ -143,6 +148,7 @@ SPEC CHECKSUMS: | |||||||
|   hotkey_manager: c32bf0bfe8f934b7bc17ab4ad5c4c142960b023c |   hotkey_manager: c32bf0bfe8f934b7bc17ab4ad5c4c142960b023c | ||||||
|   irondash_engine_context: da62996ee25616d2f01bbeb85dc115d813359478 |   irondash_engine_context: da62996ee25616d2f01bbeb85dc115d813359478 | ||||||
|   local_notifier: e9506bc66fc70311e8bc7291fb70f743c081e4ff |   local_notifier: e9506bc66fc70311e8bc7291fb70f743c081e4ff | ||||||
|  |   open_file_mac: 0e554648e2a87ce59e9438e3e5ca3e552e90d89a | ||||||
|   package_info_plus: fa739dd842b393193c5ca93c26798dff6e3d0e0c |   package_info_plus: fa739dd842b393193c5ca93c26798dff6e3d0e0c | ||||||
|   path_provider_foundation: 2b6b4c569c0fb62ec74538f866245ac84301af46 |   path_provider_foundation: 2b6b4c569c0fb62ec74538f866245ac84301af46 | ||||||
|   ReachabilitySwift: 7f151ff156cea1481a8411701195ac6a984f4979 |   ReachabilitySwift: 7f151ff156cea1481a8411701195ac6a984f4979 | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Lucas
						Lucas