diff --git a/.dart_tool/flutter_gen/gen_l10n/l10n.dart b/.dart_tool/flutter_gen/gen_l10n/l10n.dart index 8c3a4835..04e7d58d 100644 --- a/.dart_tool/flutter_gen/gen_l10n/l10n.dart +++ b/.dart_tool/flutter_gen/gen_l10n/l10n.dart @@ -966,6 +966,12 @@ abstract class S { /// **'Result'** String get result; + /// No description provided for @rotateAngel. + /// + /// In en, this message translates to: + /// **'Rotation angle'** + String get rotateAngel; + /// No description provided for @run. /// /// In en, this message translates to: diff --git a/.dart_tool/flutter_gen/gen_l10n/l10n_de.dart b/.dart_tool/flutter_gen/gen_l10n/l10n_de.dart index ecf988dd..15b4184f 100644 --- a/.dart_tool/flutter_gen/gen_l10n/l10n_de.dart +++ b/.dart_tool/flutter_gen/gen_l10n/l10n_de.dart @@ -465,6 +465,9 @@ class SDe extends S { @override String get result => 'Result'; + @override + String get rotateAngel => 'Rotation angle'; + @override String get run => 'Ausführen'; diff --git a/.dart_tool/flutter_gen/gen_l10n/l10n_en.dart b/.dart_tool/flutter_gen/gen_l10n/l10n_en.dart index 925c4609..c46cf127 100644 --- a/.dart_tool/flutter_gen/gen_l10n/l10n_en.dart +++ b/.dart_tool/flutter_gen/gen_l10n/l10n_en.dart @@ -465,6 +465,9 @@ class SEn extends S { @override String get result => 'Result'; + @override + String get rotateAngel => 'Rotation angle'; + @override String get run => 'Run'; diff --git a/.dart_tool/flutter_gen/gen_l10n/l10n_zh.dart b/.dart_tool/flutter_gen/gen_l10n/l10n_zh.dart index af1c473b..cf13789f 100644 --- a/.dart_tool/flutter_gen/gen_l10n/l10n_zh.dart +++ b/.dart_tool/flutter_gen/gen_l10n/l10n_zh.dart @@ -465,6 +465,9 @@ class SZh extends S { @override String get result => '结果'; + @override + String get rotateAngel => '旋转角度'; + @override String get run => '运行'; @@ -1099,6 +1102,9 @@ class SZhTw extends SZh { @override String get result => '結果'; + @override + String get rotateAngel => '旋轉角度'; + @override String get run => '運行'; diff --git a/lib/data/store/setting.dart b/lib/data/store/setting.dart index 487c8886..9a187f8e 100644 --- a/lib/data/store/setting.dart +++ b/lib/data/store/setting.dart @@ -68,7 +68,7 @@ class SettingStore extends PersistentStore { // Editor theme StoreProperty get editorTheme => property('editorTheme', defaultValue: defaultEditorTheme); - + StoreProperty get editorDarkTheme => property('editorDarkTheme', defaultValue: defaultEditorDarkTheme); @@ -78,6 +78,9 @@ class SettingStore extends PersistentStore { StoreProperty get fullScreenJitter => property('fullScreenJitter', defaultValue: true); + StoreProperty get fullScreenRotateQuarter => + property('fullScreenRotateQuarter', defaultValue: 1); + StoreProperty get keyboardType => property('keyboardType', defaultValue: TextInputType.text.index); diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index 85e218b9..2065ab7b 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -145,6 +145,7 @@ "restoreSuccess": "Restore success. Restart app to apply.", "restoreSureWithDate": "Are you sure to restore from {date} ?", "result": "Result", + "rotateAngel": "Rotation angle", "run": "Run", "save": "Save", "saved": "Saved", diff --git a/lib/l10n/app_zh.arb b/lib/l10n/app_zh.arb index 55d180a7..bb11c001 100644 --- a/lib/l10n/app_zh.arb +++ b/lib/l10n/app_zh.arb @@ -145,6 +145,7 @@ "restoreSuccess": "恢复成功,需要重启App来应用更改", "restoreSureWithDate": "确定恢复 {date} 的备份吗?", "result": "结果", + "rotateAngel": "旋转角度", "run": "运行", "save": "保存", "saved": "已保存", diff --git a/lib/l10n/app_zh_tw.arb b/lib/l10n/app_zh_tw.arb index 79d54c81..e655216c 100644 --- a/lib/l10n/app_zh_tw.arb +++ b/lib/l10n/app_zh_tw.arb @@ -142,6 +142,7 @@ "restoreSuccess": "恢復成功,需要重啓App來應用更改", "restoreSureWithDate": "確定恢復 {date} 的備份嗎?", "result": "結果", + "rotateAngel": "旋轉角度", "run": "運行", "save": "保存", "saved": "已保存", diff --git a/lib/view/page/full_screen.dart b/lib/view/page/full_screen.dart index 3cc75025..2985cc14 100644 --- a/lib/view/page/full_screen.dart +++ b/lib/view/page/full_screen.dart @@ -10,6 +10,7 @@ import 'package:provider/provider.dart'; import 'package:toolbox/core/route.dart'; import 'package:toolbox/data/provider/server.dart'; import 'package:toolbox/data/res/ui.dart'; +import 'package:toolbox/data/store/setting.dart'; import 'package:toolbox/locator.dart'; import '../../core/analysis.dart'; @@ -35,14 +36,17 @@ class _FullScreenPageState extends State with AfterLayoutMixin { late MediaQueryData _media; late ThemeData _theme; late Timer _timer; + late int _rotateQuarter; final _pageController = PageController(initialPage: 0); final _serverProvider = locator(); + final _setting = locator(); @override void initState() { super.initState(); switchStatusBar(hide: true); + _rotateQuarter = _setting.fullScreenRotateQuarter.fetch()!; _timer = Timer.periodic(const Duration(minutes: 1), (_) { if (mounted) { setState(() {}); @@ -68,7 +72,7 @@ class _FullScreenPageState extends State with AfterLayoutMixin { double get _offset { // based on screen width - final x = _media.size.width * 0.03; + final x = _screenWidth * 0.03; var r = Random().nextDouble(); final n = Random().nextBool() ? -1 : 1; return n * x * r; @@ -79,26 +83,36 @@ class _FullScreenPageState extends State with AfterLayoutMixin { final offset = Offset(_offset, _offset); return Scaffold( body: SafeArea( - child: RotatedBox( - quarterTurns: 3, - child: Transform.translate( - offset: offset, - child: Stack( - children: [ - _buildMain(), - Positioned( - top: 0, - left: 0, - child: _buildSettingBtn(), + child: ValueListenableBuilder( + valueListenable: _setting.fullScreenRotateQuarter.listenable(), + builder: (_, val, __) { + _rotateQuarter = val; + return RotatedBox( + quarterTurns: val, + child: Transform.translate( + offset: offset, + child: Stack( + children: [ + _buildMain(), + Positioned( + top: 0, + left: 0, + child: _buildSettingBtn(), + ), + ], + ), ), - ], - ), - ), - ), + ); + }), ), ); } + double get _screenWidth => + _rotateQuarter % 2 == 0 ? _media.size.width : _media.size.height; + double get _screenHeight => + _rotateQuarter % 2 == 0 ? _media.size.height : _media.size.width; + Widget _buildSettingBtn() { return IconButton( onPressed: () => AppRoute( @@ -161,7 +175,7 @@ class _FullScreenPageState extends State with AfterLayoutMixin { crossAxisAlignment: CrossAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center, children: [ - SizedBox(height: _media.size.width * 0.1), + SizedBox(height: _screenWidth * 0.1), Row( mainAxisAlignment: MainAxisAlignment.spaceAround, children: [ @@ -175,7 +189,7 @@ class _FullScreenPageState extends State with AfterLayoutMixin { ) ], ), - SizedBox(height: _media.size.width * 0.1), + SizedBox(height: _screenWidth * 0.1), Row( mainAxisAlignment: MainAxisAlignment.spaceAround, children: [ @@ -198,7 +212,7 @@ class _FullScreenPageState extends State with AfterLayoutMixin { ServerPrivateInfo spi, ) { return Padding( - padding: EdgeInsets.symmetric(vertical: _media.size.width * 0.05), + padding: EdgeInsets.symmetric(vertical: _screenWidth * 0.05), child: Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.center, @@ -245,7 +259,7 @@ class _FullScreenPageState extends State with AfterLayoutMixin { Widget _buildExplainText(String text) { return SizedBox( - width: _media.size.height * 0.2, + width: _screenHeight * 0.2, child: Text( text, style: const TextStyle(fontSize: 13), @@ -289,7 +303,7 @@ class _FullScreenPageState extends State with AfterLayoutMixin { final statusTextStyle = TextStyle( fontSize: 13, color: _theme.textTheme.bodyLarge!.color!.withAlpha(177)); return SizedBox( - width: _media.size.height * 0.23, + width: _screenHeight * 0.23, child: Column( children: [ const SizedBox(height: 5), @@ -315,7 +329,7 @@ class _FullScreenPageState extends State with AfterLayoutMixin { if (percent <= 0) percent = 0.01; if (percent >= 100) percent = 99.9; return SizedBox( - width: _media.size.height * 0.23, + width: _screenHeight * 0.23, child: Stack( children: [ Center( @@ -324,8 +338,8 @@ class _FullScreenPageState extends State with AfterLayoutMixin { progressNumber: percent, animationDuration: const Duration(milliseconds: 377), maxNumber: 100, - width: _media.size.width * 0.22, - height: _media.size.width * 0.22, + width: _screenWidth * 0.22, + height: _screenWidth * 0.22, ), ), Positioned.fill( diff --git a/lib/view/page/setting.dart b/lib/view/page/setting.dart index 6dfbf6ba..99384330 100644 --- a/lib/view/page/setting.dart +++ b/lib/view/page/setting.dart @@ -45,6 +45,7 @@ class _SettingPageState extends State { final _editorThemeKey = GlobalKey>(); final _editorDarkThemeKey = GlobalKey>(); final _keyboardTypeKey = GlobalKey>(); + final _rotateQuarterKey = GlobalKey>(); late final SettingStore _setting; late final ServerProvider _serverProvider; @@ -61,6 +62,7 @@ class _SettingPageState extends State { final _editorTheme = ValueNotifier(''); final _editorDarkTheme = ValueNotifier(''); final _keyboardType = ValueNotifier(0); + final _rotateQuarter = ValueNotifier(0); final _pushToken = ValueNotifier(null); @@ -86,6 +88,7 @@ class _SettingPageState extends State { _editorTheme.value = _setting.editorTheme.fetch()!; _editorDarkTheme.value = _setting.editorDarkTheme.fetch()!; _keyboardType.value = _setting.keyboardType.fetch()!; + _rotateQuarter.value = _setting.fullScreenRotateQuarter.fetch()!; } @override @@ -149,6 +152,7 @@ class _SettingPageState extends State { children: [ _buildFullScreenSwitch(), _buildFullScreenJitter(), + _buildFulScreenRotateQuarter(), ].map((e) => RoundRectCard(e)).toList(), ); } @@ -730,6 +734,39 @@ class _SettingPageState extends State { ); } + Widget _buildFulScreenRotateQuarter() { + final degrees = List.generate(4, (idx) => '${idx * 90}°').toList(); + final items = List.generate(4, (idx) { + return PopupMenuItem( + value: idx, + child: Text(degrees[idx]), + ); + }).toList(); + + return ListTile( + title: Text(_s.rotateAngel), + onTap: () { + _rotateQuarterKey.currentState?.showButtonMenu(); + }, + trailing: ValueBuilder( + listenable: _rotateQuarter, + build: () => PopupMenuButton( + key: _rotateQuarterKey, + itemBuilder: (BuildContext context) => items, + initialValue: _rotateQuarter.value, + onSelected: (int idx) { + _rotateQuarter.value = idx; + _setting.fullScreenRotateQuarter.put(idx); + }, + child: Text( + degrees[_rotateQuarter.value], + style: textSize15, + ), + ), + ), + ); + } + Widget _buildKeyboardType() { const List names = [ 'text',