feat: support scale up/down the app (#5300)

This commit is contained in:
Lucas.Xu 2024-05-10 10:09:25 +08:00 committed by GitHub
parent f3b8ec8a04
commit c732438f8a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 95 additions and 17 deletions

View File

@ -70,4 +70,9 @@ class KVKeys {
/// The workspace id is a string.
@Deprecated('deprecated in version 0.5.5')
static const String lastOpenedWorkspaceId = 'lastOpenedWorkspaceId';
/// The key for saving the scale factor
///
/// The value is a double string.
static const String scaleFactor = 'scaleFactor';
}

View File

@ -1,9 +1,9 @@
import 'package:flutter/material.dart';
import 'package:scaled_app/scaled_app.dart';
import 'startup/startup.dart';
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
ScaledWidgetsFlutterBinding.ensureInitialized(scaleFactor: (_) => 1.0);
await runAppFlowy();
}

View File

@ -1,13 +1,12 @@
import 'dart:async';
import 'dart:io';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:appflowy/env/cloud_env.dart';
import 'package:appflowy/startup/tasks/feature_flag_task.dart';
import 'package:appflowy/workspace/application/settings/prelude.dart';
import 'package:appflowy_backend/appflowy_backend.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:get_it/get_it.dart';
import 'package:package_info_plus/package_info_plus.dart';
@ -120,7 +119,7 @@ class FlowyRunner {
// localization
const InitLocalizationTask(),
// init the app window
const InitAppWindowTask(),
InitAppWindowTask(),
// Init Rust SDK
InitRustSDKTask(customApplicationPath: applicationDataDirectory),
// Load Plugins, like document, grid ...

View File

@ -1,8 +1,5 @@
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:appflowy/mobile/application/mobile_router.dart';
import 'package:appflowy/plugins/document/application/document_appearance_cubit.dart';
import 'package:appflowy/shared/feature_flags.dart';
@ -24,6 +21,8 @@ import 'package:appflowy_editor/appflowy_editor.dart' hide Log;
import 'package:easy_localization/easy_localization.dart';
import 'package:flowy_infra/theme.dart';
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:go_router/go_router.dart';

View File

@ -12,6 +12,9 @@ class WindowSizeManager {
static const double maxWindowHeight = 8192.0;
static const double maxWindowWidth = 8192.0;
static const double maxScaleFactor = 2.0;
static const double minScaleFactor = 0.5;
static const width = 'width';
static const height = 'height';
@ -64,4 +67,20 @@ class WindowSizeManager {
final offset = json.decode(position);
return Offset(offset[dx], offset[dy]);
}
Future<double> getScaleFactor() async {
final scaleFactor = await getIt<KeyValueStorage>().getWithFormat<double>(
KVKeys.scaleFactor,
(value) => double.tryParse(value) ?? 1.0,
) ??
1.0;
return scaleFactor.clamp(minScaleFactor, maxScaleFactor);
}
Future<void> setScaleFactor(double scaleFactor) async {
await getIt<KeyValueStorage>().set(
KVKeys.scaleFactor,
'${scaleFactor.clamp(minScaleFactor, maxScaleFactor)}',
);
}
}

View File

@ -1,3 +1,4 @@
import 'dart:async';
import 'dart:ui';
import 'package:appflowy/core/helpers/helpers.dart';
@ -5,15 +6,18 @@ import 'package:appflowy/startup/startup.dart';
import 'package:appflowy/startup/tasks/app_window_size_manager.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:scaled_app/scaled_app.dart';
import 'package:window_manager/window_manager.dart';
class InitAppWindowTask extends LaunchTask with WindowListener {
const InitAppWindowTask({
InitAppWindowTask({
this.title = 'AppFlowy',
});
final String title;
final windowsManager = WindowSizeManager();
@override
Future<void> initialize(LaunchContext context) async {
// Don't initialize on mobile or web.
@ -24,7 +28,7 @@ class InitAppWindowTask extends LaunchTask with WindowListener {
await windowManager.ensureInitialized();
windowManager.addListener(this);
final windowSize = await WindowSizeManager().getSize();
final windowSize = await windowsManager.getSize();
final windowOptions = WindowOptions(
size: windowSize,
minimumSize: const Size(
@ -42,11 +46,18 @@ class InitAppWindowTask extends LaunchTask with WindowListener {
await windowManager.show();
await windowManager.focus();
final position = await WindowSizeManager().getPosition();
final position = await windowsManager.getPosition();
if (position != null) {
await windowManager.setPosition(position);
}
});
unawaited(
windowsManager.getScaleFactor().then(
(value) =>
ScaledWidgetsFlutterBinding.instance.scaleFactor = (_) => value,
),
);
}
@override
@ -54,7 +65,7 @@ class InitAppWindowTask extends LaunchTask with WindowListener {
super.onWindowResize();
final currentWindowSize = await windowManager.getSize();
return WindowSizeManager().setSize(currentWindowSize);
return windowsManager.setSize(currentWindowSize);
}
@override
@ -62,7 +73,7 @@ class InitAppWindowTask extends LaunchTask with WindowListener {
super.onWindowMaximize();
final currentWindowSize = await windowManager.getSize();
return WindowSizeManager().setSize(currentWindowSize);
return windowsManager.setSize(currentWindowSize);
}
@override
@ -70,7 +81,7 @@ class InitAppWindowTask extends LaunchTask with WindowListener {
super.onWindowMoved();
final position = await windowManager.getPosition();
return WindowSizeManager().setPosition(position);
return windowsManager.setPosition(position);
}
@override

View File

@ -1,16 +1,18 @@
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:appflowy/startup/startup.dart';
import 'package:appflowy/startup/tasks/app_window_size_manager.dart';
import 'package:appflowy/workspace/application/home/home_setting_bloc.dart';
import 'package:appflowy/workspace/application/settings/appearance/appearance_cubit.dart';
import 'package:appflowy/workspace/application/sidebar/rename_view/rename_view_bloc.dart';
import 'package:appflowy/workspace/application/tabs/tabs_bloc.dart';
import 'package:appflowy/workspace/presentation/home/menu/sidebar/sidebar_setting.dart';
import 'package:appflowy_backend/log.dart';
import 'package:appflowy_backend/protobuf/flowy-user/user_profile.pb.dart';
import 'package:flutter/material.dart';
import 'package:hotkey_manager/hotkey_manager.dart';
import 'package:provider/provider.dart';
import 'package:scaled_app/scaled_app.dart';
typedef KeyDownHandler = void Function(HotKey hotKey);
@ -49,6 +51,8 @@ class HomeHotKeys extends StatefulWidget {
}
class _HomeHotKeysState extends State<HomeHotKeys> {
final windowSizeManager = WindowSizeManager();
late final items = [
// Collapse sidebar menu
HotKeyItem(
@ -118,6 +122,25 @@ class _HomeHotKeysState extends State<HomeHotKeys> {
getIt<RenameViewBloc>().add(const RenameViewEvent.open()),
),
// Scale up/down the app
HotKeyItem(
hotKey: HotKey(
KeyCode.equal,
modifiers: [Platform.isMacOS ? KeyModifier.meta : KeyModifier.control],
scope: HotKeyScope.inapp,
),
keyDownHandler: (_) => _scaleWithStep(0.1),
),
HotKeyItem(
hotKey: HotKey(
KeyCode.minus,
modifiers: [Platform.isMacOS ? KeyModifier.meta : KeyModifier.control],
scope: HotKeyScope.inapp,
),
keyDownHandler: (_) => _scaleWithStep(-0.1),
),
// Open settings dialog
openSettingsHotKey(context, widget.userProfile),
];
@ -149,4 +172,17 @@ class _HomeHotKeysState extends State<HomeHotKeys> {
final bloc = context.read<TabsBloc>();
bloc.add(TabsEvent.selectTab(bloc.state.currentIndex + change));
}
Future<void> _scaleWithStep(double step) async {
final currentScaleFactor = await windowSizeManager.getScaleFactor();
final textScale = (currentScaleFactor + step).clamp(
WindowSizeManager.minScaleFactor,
WindowSizeManager.maxScaleFactor,
);
Log.info('scale the app from $currentScaleFactor to $textScale');
ScaledWidgetsFlutterBinding.instance.scaleFactor = (_) => textScale;
await windowSizeManager.setScaleFactor(textScale);
}
}

View File

@ -1521,6 +1521,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "0.27.7"
scaled_app:
dependency: "direct main"
description:
name: scaled_app
sha256: "3415fad16d1cf283112988985ccd14c4cd28bf48cbe6432d59e158f3b632d58d"
url: "https://pub.dev"
source: hosted
version: "2.2.0"
screen_retriever:
dependency: transitive
description:

View File

@ -135,6 +135,7 @@ dependencies:
numerus: ^2.1.2
flutter_animate: ^4.5.0
permission_handler: ^11.3.1
scaled_app: ^2.2.0
dev_dependencies:
flutter_lints: ^3.0.1