mirror of
https://github.com/gabehf/Fladder.git
synced 2026-03-08 23:18:16 -07:00
feature: HTPC mode startup argument (#358)
Co-authored-by: PartyDonut <PartyDonut@users.noreply.github.com>
This commit is contained in:
parent
a8795cf0c9
commit
69a5e3db7a
24 changed files with 416 additions and 151 deletions
|
|
@ -20,9 +20,8 @@ import 'package:fladder/util/input_handler.dart';
|
|||
import 'package:fladder/util/list_padding.dart';
|
||||
import 'package:fladder/util/localization_helper.dart';
|
||||
import 'package:fladder/util/throttler.dart';
|
||||
import 'package:fladder/widgets/full_screen_helpers/full_screen_wrapper.dart';
|
||||
import 'package:fladder/widgets/shared/elevated_icon.dart';
|
||||
import 'package:fladder/widgets/shared/full_screen_button.dart'
|
||||
if (dart.library.html) 'package:fladder/widgets/shared/full_screen_button_web.dart';
|
||||
import 'package:fladder/widgets/shared/progress_floating_button.dart';
|
||||
|
||||
class PhotoViewerControls extends ConsumerStatefulWidget {
|
||||
|
|
@ -131,7 +130,7 @@ class _PhotoViewerControllsState extends ConsumerState<PhotoViewerControls> with
|
|||
@override
|
||||
void dispose() {
|
||||
timerController.dispose();
|
||||
closeFullScreen();
|
||||
fullScreenHelper.closeFullScreen(ref);
|
||||
windowManager.removeListener(this);
|
||||
super.dispose();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,7 +25,6 @@ import 'package:fladder/util/adaptive_layout/adaptive_layout.dart';
|
|||
import 'package:fladder/util/bitrate_helper.dart';
|
||||
import 'package:fladder/util/box_fit_extension.dart';
|
||||
import 'package:fladder/util/localization_helper.dart';
|
||||
import 'package:fladder/util/option_dialogue.dart';
|
||||
import 'package:fladder/widgets/shared/enum_selection.dart';
|
||||
|
||||
@RoutePage()
|
||||
|
|
@ -74,22 +73,18 @@ class _PlayerSettingsPageState extends ConsumerState<PlayerSettingsPage> {
|
|||
],
|
||||
),
|
||||
SettingsListTile(
|
||||
label: Text(context.localized.videoScalingFillScreenTitle),
|
||||
subLabel: Text(videoSettings.videoFit.label(context)),
|
||||
onTap: () => openMultiSelectOptions(
|
||||
context,
|
||||
label: context.localized.videoScalingFillScreenTitle,
|
||||
items: BoxFit.values,
|
||||
selected: [ref.read(videoPlayerSettingsProvider.select((value) => value.videoFit))],
|
||||
onChanged: (values) => ref.read(videoPlayerSettingsProvider.notifier).setFitType(values.first),
|
||||
itemBuilder: (type, selected, tap) => RadioListTile(
|
||||
groupValue: ref.read(videoPlayerSettingsProvider.select((value) => value.videoFit)),
|
||||
title: Text(type.label(context)),
|
||||
value: type,
|
||||
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16)),
|
||||
contentPadding: EdgeInsets.zero,
|
||||
onChanged: (value) => tap(),
|
||||
),
|
||||
label: Text(context.localized.videoScaling),
|
||||
trailing: EnumBox(
|
||||
current: videoSettings.videoFit.label(context),
|
||||
itemBuilder: (context) => BoxFit.values
|
||||
.map(
|
||||
(entry) => PopupMenuItem(
|
||||
value: entry,
|
||||
child: Text(entry.label(context)),
|
||||
onTap: () => ref.read(videoPlayerSettingsProvider.notifier).setFitType(entry),
|
||||
),
|
||||
)
|
||||
.toList(),
|
||||
),
|
||||
),
|
||||
SettingsListTile(
|
||||
|
|
@ -363,7 +358,7 @@ class _StatusIndicator extends StatelessWidget {
|
|||
),
|
||||
const SizedBox(width: 6),
|
||||
],
|
||||
label,
|
||||
Flexible(child: label),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ class SettingsListTile extends StatelessWidget {
|
|||
final Widget? trailing;
|
||||
final bool selected;
|
||||
final IconData? icon;
|
||||
final Widget? suffix;
|
||||
final Widget? leading;
|
||||
final Color? contentColor;
|
||||
final Function()? onTap;
|
||||
const SettingsListTile({
|
||||
|
|
@ -16,7 +16,7 @@ class SettingsListTile extends StatelessWidget {
|
|||
this.subLabel,
|
||||
this.trailing,
|
||||
this.selected = false,
|
||||
this.suffix,
|
||||
this.leading,
|
||||
this.icon,
|
||||
this.contentColor,
|
||||
this.onTap,
|
||||
|
|
@ -27,7 +27,7 @@ class SettingsListTile extends StatelessWidget {
|
|||
Widget build(BuildContext context) {
|
||||
final iconWidget = icon != null ? Icon(icon) : null;
|
||||
|
||||
final leadingWidget = (suffix ?? iconWidget) != null
|
||||
final leadingWidget = (leading ?? iconWidget) != null
|
||||
? Padding(
|
||||
padding: const EdgeInsets.only(left: 8, right: 16.0),
|
||||
child: AnimatedContainer(
|
||||
|
|
@ -38,11 +38,11 @@ class SettingsListTile extends StatelessWidget {
|
|||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 12.0, vertical: 12),
|
||||
child: (suffix ?? iconWidget),
|
||||
child: (leading ?? iconWidget),
|
||||
),
|
||||
),
|
||||
)
|
||||
: suffix ?? const SizedBox();
|
||||
: leading ?? const SizedBox();
|
||||
return Card(
|
||||
elevation: selected ? 2 : 0,
|
||||
color: selected ? Theme.of(context).colorScheme.surfaceContainerLow : Colors.transparent,
|
||||
|
|
@ -57,7 +57,7 @@ class SettingsListTile extends StatelessWidget {
|
|||
horizontal: 16,
|
||||
vertical: 12,
|
||||
).copyWith(
|
||||
left: (suffix ?? iconWidget) != null ? 0 : null,
|
||||
left: (leading ?? iconWidget) != null ? 0 : null,
|
||||
),
|
||||
child: ConstrainedBox(
|
||||
constraints: const BoxConstraints(
|
||||
|
|
|
|||
|
|
@ -3,7 +3,9 @@ import 'package:flutter/material.dart';
|
|||
import 'package:auto_route/auto_route.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:iconsax_plus/iconsax_plus.dart';
|
||||
import 'package:window_manager/window_manager.dart';
|
||||
|
||||
import 'package:fladder/providers/arguments_provider.dart';
|
||||
import 'package:fladder/providers/auth_provider.dart';
|
||||
import 'package:fladder/providers/user_provider.dart';
|
||||
import 'package:fladder/routes/auto_router.gr.dart';
|
||||
|
|
@ -11,6 +13,7 @@ import 'package:fladder/screens/settings/quick_connect_window.dart';
|
|||
import 'package:fladder/screens/settings/settings_list_tile.dart';
|
||||
import 'package:fladder/screens/settings/settings_scaffold.dart';
|
||||
import 'package:fladder/screens/shared/fladder_icon.dart';
|
||||
import 'package:fladder/screens/shared/fladder_snackbar.dart';
|
||||
import 'package:fladder/util/adaptive_layout/adaptive_layout.dart';
|
||||
import 'package:fladder/util/localization_helper.dart';
|
||||
import 'package:fladder/util/theme_extensions.dart';
|
||||
|
|
@ -137,7 +140,7 @@ class _SettingsScreenState extends ConsumerState<SettingsScreen> {
|
|||
label: Text(context.localized.about),
|
||||
subLabel: const Text("Fladder"),
|
||||
selected: containsRoute(const AboutSettingsRoute()),
|
||||
suffix: Opacity(
|
||||
leading: Opacity(
|
||||
opacity: 1,
|
||||
child: FladderIconOutlined(
|
||||
size: 24,
|
||||
|
|
@ -146,6 +149,20 @@ class _SettingsScreenState extends ConsumerState<SettingsScreen> {
|
|||
),
|
||||
onTap: () => navigateTo(const AboutSettingsRoute()),
|
||||
),
|
||||
if (ref.watch(argumentsStateProvider.select((value) => value.htpcMode))) ...[
|
||||
SettingsListTile(
|
||||
label: Text(context.localized.exitFladderTitle),
|
||||
icon: IconsaxPlusLinear.close_square,
|
||||
onTap: () async {
|
||||
final manager = WindowManager.instance;
|
||||
if (await manager.isClosable()) {
|
||||
manager.close();
|
||||
} else {
|
||||
fladderSnackbar(context, title: context.localized.somethingWentWrong);
|
||||
}
|
||||
},
|
||||
),
|
||||
],
|
||||
],
|
||||
floatingActionButton: Padding(
|
||||
padding: EdgeInsets.symmetric(horizontal: MediaQuery.paddingOf(context).horizontal),
|
||||
|
|
|
|||
|
|
@ -4,7 +4,9 @@ import 'package:flutter/material.dart';
|
|||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:window_manager/window_manager.dart';
|
||||
|
||||
import 'package:fladder/providers/arguments_provider.dart';
|
||||
import 'package:fladder/util/adaptive_layout/adaptive_layout.dart';
|
||||
import 'package:fladder/widgets/full_screen_helpers/full_screen_wrapper.dart';
|
||||
|
||||
class DefaultTitleBar extends ConsumerStatefulWidget {
|
||||
final String? label;
|
||||
|
|
@ -33,6 +35,7 @@ class _DefaultTitleBarState extends ConsumerState<DefaultTitleBar> with WindowLi
|
|||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
if (ref.watch(argumentsStateProvider.select((value) => value.htpcMode))) return const SizedBox.shrink();
|
||||
final brightness = widget.brightness ?? Theme.of(context).brightness;
|
||||
final iconColor = Theme.of(context).colorScheme.onSurface.withValues(alpha: 0.65);
|
||||
return MouseRegion(
|
||||
|
|
@ -77,11 +80,9 @@ class _DefaultTitleBarState extends ConsumerState<DefaultTitleBar> with WindowLi
|
|||
children: [
|
||||
FutureBuilder<List<bool>>(future: Future.microtask(() async {
|
||||
final isMinimized = await windowManager.isMinimized();
|
||||
final isFullScreen = await windowManager.isFullScreen();
|
||||
return [isMinimized, isFullScreen];
|
||||
return [isMinimized];
|
||||
}), builder: (context, snapshot) {
|
||||
final isMinimized = snapshot.data?.firstOrNull ?? false;
|
||||
final fullScreen = snapshot.data?.lastOrNull ?? false;
|
||||
return IconButton(
|
||||
style: IconButton.styleFrom(
|
||||
hoverColor: brightness == Brightness.light
|
||||
|
|
@ -89,9 +90,7 @@ class _DefaultTitleBarState extends ConsumerState<DefaultTitleBar> with WindowLi
|
|||
: Colors.white.withValues(alpha: 0.2),
|
||||
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(2))),
|
||||
onPressed: () async {
|
||||
if (fullScreen) {
|
||||
await windowManager.setFullScreen(false);
|
||||
}
|
||||
fullScreenHelper.closeFullScreen(ref);
|
||||
if (isMinimized) {
|
||||
windowManager.restore();
|
||||
} else {
|
||||
|
|
@ -111,12 +110,10 @@ class _DefaultTitleBarState extends ConsumerState<DefaultTitleBar> with WindowLi
|
|||
FutureBuilder<List<bool>>(
|
||||
future: Future.microtask(() async {
|
||||
final isMaximized = await windowManager.isMaximized();
|
||||
final isFullScreen = await windowManager.isFullScreen();
|
||||
return [isMaximized, isFullScreen];
|
||||
return [isMaximized];
|
||||
}),
|
||||
builder: (BuildContext context, AsyncSnapshot<List<bool>> snapshot) {
|
||||
final maximized = snapshot.data?.firstOrNull ?? false;
|
||||
final fullScreen = snapshot.data?.lastOrNull ?? false;
|
||||
return IconButton(
|
||||
style: IconButton.styleFrom(
|
||||
hoverColor: brightness == Brightness.light
|
||||
|
|
@ -125,15 +122,12 @@ class _DefaultTitleBarState extends ConsumerState<DefaultTitleBar> with WindowLi
|
|||
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(2)),
|
||||
),
|
||||
onPressed: () async {
|
||||
if (fullScreen && maximized) {
|
||||
await windowManager.setFullScreen(false);
|
||||
fullScreenHelper.closeFullScreen(ref);
|
||||
if (maximized) {
|
||||
await windowManager.unmaximize();
|
||||
return;
|
||||
}
|
||||
|
||||
if (fullScreen) {
|
||||
await windowManager.setFullScreen(false);
|
||||
} else if (!maximized) {
|
||||
if (!maximized) {
|
||||
await windowManager.maximize();
|
||||
} else {
|
||||
await windowManager.unmaximize();
|
||||
|
|
|
|||
|
|
@ -20,9 +20,8 @@ import 'package:fladder/util/adaptive_layout/adaptive_layout.dart';
|
|||
import 'package:fladder/util/fladder_image.dart';
|
||||
import 'package:fladder/util/list_padding.dart';
|
||||
import 'package:fladder/util/localization_helper.dart';
|
||||
import 'package:fladder/widgets/full_screen_helpers/full_screen_wrapper.dart';
|
||||
import 'package:fladder/widgets/navigation_scaffold/components/floating_player_bar.dart';
|
||||
import 'package:fladder/widgets/shared/full_screen_button.dart'
|
||||
if (dart.library.html) 'package:fladder/widgets/shared/full_screen_button_web.dart';
|
||||
import 'package:fladder/widgets/shared/progress_floating_button.dart';
|
||||
|
||||
class VideoPlayerNextWrapper extends ConsumerStatefulWidget {
|
||||
|
|
@ -132,7 +131,7 @@ class _VideoPlayerNextWrapperState extends ConsumerState<VideoPlayerNextWrapper>
|
|||
if (AdaptiveLayout.of(context).inputDevice != InputDevice.pointer) {
|
||||
ScreenBrightness().resetApplicationScreenBrightness();
|
||||
} else {
|
||||
closeFullScreen();
|
||||
fullScreenHelper.closeFullScreen(ref);
|
||||
}
|
||||
|
||||
SystemChrome.setSystemUIOverlayStyle(SystemUiOverlayStyle(
|
||||
|
|
|
|||
|
|
@ -31,8 +31,7 @@ import 'package:fladder/util/input_handler.dart';
|
|||
import 'package:fladder/util/list_padding.dart';
|
||||
import 'package:fladder/util/localization_helper.dart';
|
||||
import 'package:fladder/util/string_extensions.dart';
|
||||
import 'package:fladder/widgets/shared/full_screen_button.dart'
|
||||
if (dart.library.html) 'package:fladder/widgets/shared/full_screen_button_web.dart';
|
||||
import 'package:fladder/widgets/full_screen_helpers/full_screen_wrapper.dart';
|
||||
|
||||
class DesktopControls extends ConsumerStatefulWidget {
|
||||
const DesktopControls({super.key});
|
||||
|
|
@ -86,7 +85,7 @@ class _DesktopControlsState extends ConsumerState<DesktopControls> {
|
|||
return true;
|
||||
}
|
||||
if (value.logicalKey == LogicalKeyboardKey.keyF) {
|
||||
toggleFullScreen(ref);
|
||||
fullScreenHelper.toggleFullScreen(ref);
|
||||
return true;
|
||||
}
|
||||
if (value.logicalKey == LogicalKeyboardKey.arrowUp) {
|
||||
|
|
@ -137,7 +136,7 @@ class _DesktopControlsState extends ConsumerState<DesktopControls> {
|
|||
? () => player.playOrPause()
|
||||
: () => toggleOverlay(),
|
||||
onDoubleTap: AdaptiveLayout.of(context).inputDevice == InputDevice.pointer
|
||||
? () => toggleFullScreen(ref)
|
||||
? () => fullScreenHelper.toggleFullScreen(ref)
|
||||
: null,
|
||||
),
|
||||
),
|
||||
|
|
@ -665,6 +664,6 @@ class _DesktopControlsState extends ConsumerState<DesktopControls> {
|
|||
|
||||
Future<void> disableFullScreen() async {
|
||||
resetTimer();
|
||||
closeFullScreen();
|
||||
fullScreenHelper.closeFullScreen(ref);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue