diff --git a/app/lib/cubits/settings.dart b/app/lib/cubits/settings.dart index 78f748d63061..51c1e1c85cf3 100644 --- a/app/lib/cubits/settings.dart +++ b/app/lib/cubits/settings.dart @@ -132,6 +132,7 @@ class ButterflySettings with _$ButterflySettings { @Default([]) List remotes, @Default('') String defaultRemote, @Default(false) bool nativeWindowTitleBar, + @Default(false) bool startInFullScreen, @Default(SyncMode.noMobile) SyncMode syncMode}) = _ButterflySettings; factory ButterflySettings.fromPrefs(SharedPreferences prefs) { @@ -172,6 +173,7 @@ class ButterflySettings with _$ButterflySettings { remotes: remotes, defaultRemote: prefs.getString('default_remote') ?? '', nativeWindowTitleBar: prefs.getBool('native_window_title_bar') ?? false, + startInFullScreen: prefs.getBool('start_in_full_screen') ?? false, syncMode: SyncMode.values.byName(prefs.getString('sync_mode') ?? 'noMobile'), ); @@ -213,6 +215,7 @@ class ButterflySettings with _$ButterflySettings { 'remotes', remotes.map((e) => json.encode(e.toJson())).toList()); await prefs.setString('default_remote', defaultRemote); await prefs.setBool('native_window_title_bar', nativeWindowTitleBar); + await prefs.setBool('start_in_full_screen', startInFullScreen); } RemoteStorage? getRemote(String identifier) { @@ -384,6 +387,11 @@ class SettingsCubit extends Cubit { Future resetColorEnabled() => changeColorEnabled(true); + Future changeStartInFullScreen(bool value) { + emit(state.copyWith(startInFullScreen: value)); + return save(); + } + bool isFirstStart() { return state.lastVersion == null; } diff --git a/app/lib/cubits/settings.freezed.dart b/app/lib/cubits/settings.freezed.dart index e23e2432b218..4d435d11df6e 100644 --- a/app/lib/cubits/settings.freezed.dart +++ b/app/lib/cubits/settings.freezed.dart @@ -480,6 +480,7 @@ mixin _$ButterflySettings { List get remotes => throw _privateConstructorUsedError; String get defaultRemote => throw _privateConstructorUsedError; bool get nativeWindowTitleBar => throw _privateConstructorUsedError; + bool get startInFullScreen => throw _privateConstructorUsedError; SyncMode get syncMode => throw _privateConstructorUsedError; @JsonKey(ignore: true) @@ -511,6 +512,7 @@ abstract class $ButterflySettingsCopyWith<$Res> { List remotes, String defaultRemote, bool nativeWindowTitleBar, + bool startInFullScreen, SyncMode syncMode}); } @@ -543,6 +545,7 @@ class _$ButterflySettingsCopyWithImpl<$Res> Object? remotes = freezed, Object? defaultRemote = freezed, Object? nativeWindowTitleBar = freezed, + Object? startInFullScreen = freezed, Object? syncMode = freezed, }) { return _then(_value.copyWith( @@ -618,6 +621,10 @@ class _$ButterflySettingsCopyWithImpl<$Res> ? _value.nativeWindowTitleBar : nativeWindowTitleBar // ignore: cast_nullable_to_non_nullable as bool, + startInFullScreen: startInFullScreen == freezed + ? _value.startInFullScreen + : startInFullScreen // ignore: cast_nullable_to_non_nullable + as bool, syncMode: syncMode == freezed ? _value.syncMode : syncMode // ignore: cast_nullable_to_non_nullable @@ -652,6 +659,7 @@ abstract class _$$_ButterflySettingsCopyWith<$Res> List remotes, String defaultRemote, bool nativeWindowTitleBar, + bool startInFullScreen, SyncMode syncMode}); } @@ -686,6 +694,7 @@ class __$$_ButterflySettingsCopyWithImpl<$Res> Object? remotes = freezed, Object? defaultRemote = freezed, Object? nativeWindowTitleBar = freezed, + Object? startInFullScreen = freezed, Object? syncMode = freezed, }) { return _then(_$_ButterflySettings( @@ -761,6 +770,10 @@ class __$$_ButterflySettingsCopyWithImpl<$Res> ? _value.nativeWindowTitleBar : nativeWindowTitleBar // ignore: cast_nullable_to_non_nullable as bool, + startInFullScreen: startInFullScreen == freezed + ? _value.startInFullScreen + : startInFullScreen // ignore: cast_nullable_to_non_nullable + as bool, syncMode: syncMode == freezed ? _value.syncMode : syncMode // ignore: cast_nullable_to_non_nullable @@ -791,6 +804,7 @@ class _$_ButterflySettings extends _ButterflySettings { final List remotes = const [], this.defaultRemote = '', this.nativeWindowTitleBar = false, + this.startInFullScreen = false, this.syncMode = SyncMode.noMobile}) : _history = history, _remotes = remotes, @@ -861,11 +875,14 @@ class _$_ButterflySettings extends _ButterflySettings { final bool nativeWindowTitleBar; @override @JsonKey() + final bool startInFullScreen; + @override + @JsonKey() final SyncMode syncMode; @override String toString() { - return 'ButterflySettings(theme: $theme, localeTag: $localeTag, documentPath: $documentPath, dateFormat: $dateFormat, touchSensitivity: $touchSensitivity, mouseSensitivity: $mouseSensitivity, penSensitivity: $penSensitivity, selectSensitivity: $selectSensitivity, penOnlyInput: $penOnlyInput, inputGestures: $inputGestures, design: $design, history: $history, startEnabled: $startEnabled, colorEnabled: $colorEnabled, lastVersion: $lastVersion, remotes: $remotes, defaultRemote: $defaultRemote, nativeWindowTitleBar: $nativeWindowTitleBar, syncMode: $syncMode)'; + return 'ButterflySettings(theme: $theme, localeTag: $localeTag, documentPath: $documentPath, dateFormat: $dateFormat, touchSensitivity: $touchSensitivity, mouseSensitivity: $mouseSensitivity, penSensitivity: $penSensitivity, selectSensitivity: $selectSensitivity, penOnlyInput: $penOnlyInput, inputGestures: $inputGestures, design: $design, history: $history, startEnabled: $startEnabled, colorEnabled: $colorEnabled, lastVersion: $lastVersion, remotes: $remotes, defaultRemote: $defaultRemote, nativeWindowTitleBar: $nativeWindowTitleBar, startInFullScreen: $startInFullScreen, syncMode: $syncMode)'; } @override @@ -904,6 +921,8 @@ class _$_ButterflySettings extends _ButterflySettings { .equals(other.defaultRemote, defaultRemote) && const DeepCollectionEquality() .equals(other.nativeWindowTitleBar, nativeWindowTitleBar) && + const DeepCollectionEquality() + .equals(other.startInFullScreen, startInFullScreen) && const DeepCollectionEquality().equals(other.syncMode, syncMode)); } @@ -928,6 +947,7 @@ class _$_ButterflySettings extends _ButterflySettings { const DeepCollectionEquality().hash(_remotes), const DeepCollectionEquality().hash(defaultRemote), const DeepCollectionEquality().hash(nativeWindowTitleBar), + const DeepCollectionEquality().hash(startInFullScreen), const DeepCollectionEquality().hash(syncMode) ]); @@ -958,6 +978,7 @@ abstract class _ButterflySettings extends ButterflySettings { final List remotes, final String defaultRemote, final bool nativeWindowTitleBar, + final bool startInFullScreen, final SyncMode syncMode}) = _$_ButterflySettings; const _ButterflySettings._() : super._(); @@ -998,6 +1019,8 @@ abstract class _ButterflySettings extends ButterflySettings { @override bool get nativeWindowTitleBar; @override + bool get startInFullScreen; + @override SyncMode get syncMode; @override @JsonKey(ignore: true) diff --git a/app/lib/l10n/app_en.arb b/app/lib/l10n/app_en.arb index 210793f8af15..6af29734e62c 100644 --- a/app/lib/l10n/app_en.arb +++ b/app/lib/l10n/app_en.arb @@ -385,5 +385,6 @@ "example": "1" } } - } + }, + "startInFullScreen": "Start in full screen" } \ No newline at end of file diff --git a/app/lib/main.dart b/app/lib/main.dart index 39d0ca76c7ab..442a38cfcec8 100644 --- a/app/lib/main.dart +++ b/app/lib/main.dart @@ -10,6 +10,7 @@ import 'package:shared_preferences/shared_preferences.dart'; import 'package:window_manager/window_manager.dart'; import 'api/file_system.dart'; +import 'api/full_screen.dart'; import 'cubits/settings.dart'; import 'embed/embedding.dart'; import 'models/converter.dart'; @@ -224,6 +225,7 @@ class ButterflyApp extends StatelessWidget { ? TitleBarStyle.normal : TitleBarStyle.hidden); } + setFullScreen(settings.startInFullScreen); return RepositoryProvider( create: (context) => SyncService(context, context.read()), diff --git a/app/lib/settings/personalization.dart b/app/lib/settings/personalization.dart index 6f158d9eab88..dc6ceabd1acb 100644 --- a/app/lib/settings/personalization.dart +++ b/app/lib/settings/personalization.dart @@ -132,6 +132,13 @@ class PersonalizationSettingsPage extends StatelessWidget { .read() .changeColorEnabled(value ?? true), ), + CheckboxListTile( + value: state.startInFullScreen, + onChanged: (value) {}, + title: Text( + AppLocalizations.of(context)!.startInFullScreen), + secondary: const Icon(PhosphorIcons.arrowsOutLight), + ), ]), ), ), diff --git a/app/lib/views/main.dart b/app/lib/views/main.dart index f6ddcf22de2d..98f8387f8485 100644 --- a/app/lib/views/main.dart +++ b/app/lib/views/main.dart @@ -480,67 +480,70 @@ class _WindowButtonsState extends State with WindowListener { if (!kIsWeb && isWindow() && !settings.nativeWindowTitleBar) { return LayoutBuilder( builder: (context, constraints) => Padding( - padding: const EdgeInsets.all(8.0), - child: Row( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - if (widget.divider) const VerticalDivider(), - if (!fullScreen) - IconButton( - icon: Icon(alwaysOnTop - ? PhosphorIcons.pushPinFill - : PhosphorIcons.pushPinLight), - tooltip: alwaysOnTop - ? AppLocalizations.of(context)!.exitAlwaysOnTop - : AppLocalizations.of(context)!.alwaysOnTop, - onPressed: () async { - await windowManager.setAlwaysOnTop(!alwaysOnTop); - setState(() => alwaysOnTop = !alwaysOnTop); - }, - ), - IconButton( - icon: Icon(fullScreen - ? PhosphorIcons.arrowsInLight - : PhosphorIcons.arrowsOutLight), - tooltip: fullScreen - ? AppLocalizations.of(context)!.exitFullScreen - : AppLocalizations.of(context)!.enterFullScreen, - onPressed: () async { - setState(() => fullScreen = !fullScreen); - await windowManager.setFullScreen(fullScreen); - }, - ), - if (!fullScreen) ...[ - const VerticalDivider(), - IconButton( - icon: const Icon(PhosphorIcons.minusLight), - tooltip: AppLocalizations.of(context)!.minimize, - iconSize: 16, - splashRadius: 20, - onPressed: () => windowManager.minimize(), - ), - IconButton( - icon: Icon(PhosphorIcons.squareLight, - size: maximized ? 14 : 20), - tooltip: maximized - ? AppLocalizations.of(context)!.restore - : AppLocalizations.of(context)!.maximize, - iconSize: 16, - splashRadius: 20, - onPressed: () async => await windowManager.isMaximized() - ? windowManager.unmaximize() - : windowManager.maximize(), - ), - IconButton( - icon: const Icon(PhosphorIcons.xLight), - tooltip: AppLocalizations.of(context)!.close, - hoverColor: Colors.red, - iconSize: 16, - splashRadius: 20, - onPressed: () => windowManager.close(), - ) - ] - ], + padding: const EdgeInsets.symmetric(horizontal: 8.0), + child: ConstrainedBox( + constraints: const BoxConstraints(maxHeight: 42), + child: Row( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + if (widget.divider) const VerticalDivider(), + ...[ + if (!fullScreen) + IconButton( + icon: Icon(alwaysOnTop + ? PhosphorIcons.pushPinFill + : PhosphorIcons.pushPinLight), + tooltip: alwaysOnTop + ? AppLocalizations.of(context)!.exitAlwaysOnTop + : AppLocalizations.of(context)!.alwaysOnTop, + onPressed: () async { + await windowManager.setAlwaysOnTop(!alwaysOnTop); + setState(() => alwaysOnTop = !alwaysOnTop); + }, + ), + IconButton( + icon: Icon(fullScreen + ? PhosphorIcons.arrowsInLight + : PhosphorIcons.arrowsOutLight), + tooltip: fullScreen + ? AppLocalizations.of(context)!.exitFullScreen + : AppLocalizations.of(context)!.enterFullScreen, + onPressed: () async { + setState(() => fullScreen = !fullScreen); + await windowManager.setFullScreen(fullScreen); + }, + ), + if (!fullScreen) ...[ + const VerticalDivider(), + IconButton( + icon: const Icon(PhosphorIcons.minusLight), + tooltip: AppLocalizations.of(context)!.minimize, + splashRadius: 20, + onPressed: () => windowManager.minimize(), + ), + IconButton( + icon: Icon(PhosphorIcons.squareLight, + size: maximized ? 14 : 20), + tooltip: maximized + ? AppLocalizations.of(context)!.restore + : AppLocalizations.of(context)!.maximize, + splashRadius: 20, + onPressed: () async => + await windowManager.isMaximized() + ? windowManager.unmaximize() + : windowManager.maximize(), + ), + IconButton( + icon: const Icon(PhosphorIcons.xLight), + tooltip: AppLocalizations.of(context)!.close, + hoverColor: Colors.red, + splashRadius: 20, + onPressed: () => windowManager.close(), + ) + ] + ].map((e) => AspectRatio(aspectRatio: 1, child: e)) + ], + ), ), ), ); diff --git a/app/pubspec.lock b/app/pubspec.lock index 63b4173b8eeb..bd866f88a976 100644 --- a/app/pubspec.lock +++ b/app/pubspec.lock @@ -7,7 +7,7 @@ packages: name: _fe_analyzer_shared url: "https://pub.dartlang.org" source: hosted - version: "46.0.0" + version: "47.0.0" adwaita: dependency: "direct main" description: @@ -21,7 +21,7 @@ packages: name: analyzer url: "https://pub.dartlang.org" source: hosted - version: "4.6.0" + version: "4.7.0" animations: dependency: "direct main" description: diff --git a/app/pubspec.yaml b/app/pubspec.yaml index ad0dd4ea137c..b791daf8d47c 100644 --- a/app/pubspec.yaml +++ b/app/pubspec.yaml @@ -66,7 +66,7 @@ dev_dependencies: sdk: flutter flutter_driver: sdk: flutter - analyzer: ^4.6.0 + analyzer: ^4.7.0 freezed: ^2.1.0+1 build_runner: ^2.2.0 json_serializable: ^6.3.1 diff --git a/fastlane/metadata/android/en-US/changelogs/42.txt b/fastlane/metadata/android/en-US/changelogs/42.txt index 479aeaf5e83d..558bb64d67dd 100644 --- a/fastlane/metadata/android/en-US/changelogs/42.txt +++ b/fastlane/metadata/android/en-US/changelogs/42.txt @@ -8,6 +8,7 @@ * Reset pointer on app hide * Add default behavior to not ask for area name * Add option to load images, pdfs and svgs from open dialog +* Add option to start the app in full screen mode * Fix gesture issues on area and shape painter * Fix area change problem * Fix divider on top right in native title bar mode \ No newline at end of file