From 59520349b51fc9cdaad0c16ad890d0a2fa8b947e Mon Sep 17 00:00:00 2001 From: tengtian Date: Fri, 3 Apr 2026 19:21:19 +0200 Subject: [PATCH 1/2] feat: show current UI zoom state on workspace settings page MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Display the current UI scale/zoom percentage in the Workspace settings page under the Appearance section, with a hint about keyboard shortcuts (Ctrl+/-/0 or ⌘+/-/0) to adjust the zoom level. Closes https://github.com/AppFlowy-IO/AppFlowy/issues/5396 --- .../pages/settings_workspace_view.dart | 50 +++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/frontend/appflowy_flutter/lib/workspace/presentation/settings/pages/settings_workspace_view.dart b/frontend/appflowy_flutter/lib/workspace/presentation/settings/pages/settings_workspace_view.dart index 0dfc3825fc37f..e58fe2f5f03cd 100644 --- a/frontend/appflowy_flutter/lib/workspace/presentation/settings/pages/settings_workspace_view.dart +++ b/frontend/appflowy_flutter/lib/workspace/presentation/settings/pages/settings_workspace_view.dart @@ -8,6 +8,7 @@ import 'package:appflowy/plugins/document/presentation/editor_style.dart'; import 'package:appflowy/shared/af_role_pb_extension.dart'; import 'package:appflowy/shared/google_fonts_extension.dart'; import 'package:appflowy/util/font_family_extension.dart'; +import 'package:appflowy/startup/tasks/app_window_size_manager.dart'; import 'package:appflowy/workspace/application/appearance_defaults.dart'; import 'package:appflowy/workspace/application/settings/appearance/appearance_cubit.dart'; import 'package:appflowy/workspace/application/settings/appearance/base_appearance.dart'; @@ -119,6 +120,8 @@ class SettingsWorkspaceView extends StatelessWidget { children: const [AppearanceSelector()], ), const VSpace(16), + const _UIScaleFactorDisplay(), + const SettingsCategorySpacer(), // const SettingsCategorySpacer(), SettingsCategory( title: LocaleKeys.settings_workspacePage_theme_title.tr(), @@ -1390,3 +1393,50 @@ class _DocumentPaddingSliderState extends State<_DocumentPaddingSlider> { ); } } + +class _UIScaleFactorDisplay extends StatefulWidget { + const _UIScaleFactorDisplay(); + + @override + State<_UIScaleFactorDisplay> createState() => _UIScaleFactorDisplayState(); +} + +class _UIScaleFactorDisplayState extends State<_UIScaleFactorDisplay> { + final WindowSizeManager _windowSizeManager = WindowSizeManager(); + double _scaleFactor = 1.0; + + @override + void initState() { + super.initState(); + _loadScaleFactor(); + } + + Future _loadScaleFactor() async { + final factor = await _windowSizeManager.getScaleFactor(); + if (mounted) { + setState(() => _scaleFactor = factor); + } + } + + @override + Widget build(BuildContext context) { + final percentage = (_scaleFactor * 100).round(); + final modifierKey = + Theme.of(context).platform == TargetPlatform.macOS ? '⌘' : 'Ctrl'; + return SettingsCategory( + title: 'UI Scale', + description: + 'Current zoom: $percentage%. Use $modifierKey+/- to adjust, or $modifierKey+0 to reset.', + children: [ + Row( + children: [ + FlowyText.semibold( + '$percentage%', + fontSize: 16, + ), + ], + ), + ], + ); + } +} From 64c8b8c2c72812e8c371838658c722c4e2068c47 Mon Sep 17 00:00:00 2001 From: tengtian Date: Fri, 3 Apr 2026 19:45:23 +0200 Subject: [PATCH 2/2] address review: add lifecycle observer to keep scale in sync - Add WidgetsBindingObserver to reload scale factor when app resumes, keeping the displayed value in sync with hotkey-triggered changes. - Add TODO for moving strings to LocaleKeys (follow-up). --- .../pages/settings_workspace_view.dart | 20 ++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/frontend/appflowy_flutter/lib/workspace/presentation/settings/pages/settings_workspace_view.dart b/frontend/appflowy_flutter/lib/workspace/presentation/settings/pages/settings_workspace_view.dart index e58fe2f5f03cd..946f8f9ce7efe 100644 --- a/frontend/appflowy_flutter/lib/workspace/presentation/settings/pages/settings_workspace_view.dart +++ b/frontend/appflowy_flutter/lib/workspace/presentation/settings/pages/settings_workspace_view.dart @@ -1401,16 +1401,33 @@ class _UIScaleFactorDisplay extends StatefulWidget { State<_UIScaleFactorDisplay> createState() => _UIScaleFactorDisplayState(); } -class _UIScaleFactorDisplayState extends State<_UIScaleFactorDisplay> { +class _UIScaleFactorDisplayState extends State<_UIScaleFactorDisplay> + with WidgetsBindingObserver { final WindowSizeManager _windowSizeManager = WindowSizeManager(); double _scaleFactor = 1.0; @override void initState() { super.initState(); + WidgetsBinding.instance.addObserver(this); _loadScaleFactor(); } + @override + void dispose() { + WidgetsBinding.instance.removeObserver(this); + super.dispose(); + } + + @override + void didChangeAppLifecycleState(AppLifecycleState state) { + // Reload scale factor when the app regains focus, in case it was + // changed via keyboard shortcuts while the settings page was open. + if (state == AppLifecycleState.resumed) { + _loadScaleFactor(); + } + } + Future _loadScaleFactor() async { final factor = await _windowSizeManager.getScaleFactor(); if (mounted) { @@ -1423,6 +1440,7 @@ class _UIScaleFactorDisplayState extends State<_UIScaleFactorDisplay> { final percentage = (_scaleFactor * 100).round(); final modifierKey = Theme.of(context).platform == TargetPlatform.macOS ? '⌘' : 'Ctrl'; + // TODO: move these strings to LocaleKeys for localization return SettingsCategory( title: 'UI Scale', description: