chore: Update MPV package to latest version (#165)

Co-authored-by: PartyDonut <PartyDonut@users.noreply.github.com>
This commit is contained in:
PartyDonut 2024-11-28 21:42:40 +01:00 committed by GitHub
parent da354437e3
commit a518ae457e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
28 changed files with 209 additions and 133 deletions

View file

@ -10,6 +10,7 @@
<application android:label="Fladder" android:name="${applicationName}" android:icon="@mipmap/ic_launcher" android:usesCleartextTraffic="true"> <application android:label="Fladder" android:name="${applicationName}" android:icon="@mipmap/ic_launcher" android:usesCleartextTraffic="true">
<meta-data android:name="io.flutter.embedding.android.EnableImpeller" android:value="true" />
<activity android:name=".MainActivity" android:exported="true" android:launchMode="singleTop" android:theme="@style/LaunchTheme" android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode" android:hardwareAccelerated="true" android:windowSoftInputMode="adjustResize"> <activity android:name=".MainActivity" android:exported="true" android:launchMode="singleTop" android:theme="@style/LaunchTheme" android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode" android:hardwareAccelerated="true" android:windowSoftInputMode="adjustResize">
<!-- Specifies an Android theme to apply to this Activity as soon as <!-- Specifies an Android theme to apply to this Activity as soon as
the Android process has started. This theme is visible to the user the Android process has started. This theme is visible to the user

View file

@ -8,7 +8,6 @@ import 'package:flutter/services.dart';
import 'package:collection/collection.dart'; import 'package:collection/collection.dart';
import 'package:dynamic_color/dynamic_color.dart'; import 'package:dynamic_color/dynamic_color.dart';
import 'package:flutter_cache_manager/flutter_cache_manager.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:isar/isar.dart'; import 'package:isar/isar.dart';
@ -45,19 +44,6 @@ bool get _isDesktop {
].contains(defaultTargetPlatform); ].contains(defaultTargetPlatform);
} }
class CustomCacheManager {
static const key = 'customCacheKey';
static CacheManager instance = CacheManager(
Config(
key,
stalePeriod: const Duration(days: 3),
maxNrOfCacheObjects: 500,
repo: JsonCacheInfoRepository(databaseName: key),
fileService: HttpFileService(),
),
);
}
Future<Map<String, dynamic>> loadConfig() async { Future<Map<String, dynamic>> loadConfig() async {
final configString = await rootBundle.loadString('config/config.json'); final configString = await rootBundle.loadString('config/config.json');
return jsonDecode(configString); return jsonDecode(configString);
@ -310,6 +296,7 @@ class _MainState extends ConsumerState<Main> with WindowListener, WidgetsBinding
), ),
child: ScaffoldMessenger(child: child ?? Container()), child: ScaffoldMessenger(child: child ?? Container()),
), ),
debugShowCheckedModeBanner: false,
darkTheme: darkTheme.copyWith( darkTheme: darkTheme.copyWith(
scaffoldBackgroundColor: amoledOverwrite, scaffoldBackgroundColor: amoledOverwrite,
cardColor: amoledOverwrite, cardColor: amoledOverwrite,

View file

@ -2,14 +2,15 @@ import 'dart:convert';
import 'dart:io'; import 'dart:io';
import 'dart:typed_data'; import 'dart:typed_data';
import 'package:flutter/material.dart';
import 'package:cached_network_image/cached_network_image.dart'; import 'package:cached_network_image/cached_network_image.dart';
import 'package:collection/collection.dart'; import 'package:collection/collection.dart';
import 'package:fladder/main.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:fladder/jellyfin/jellyfin_open_api.swagger.dart' as dto; import 'package:fladder/jellyfin/jellyfin_open_api.swagger.dart' as dto;
import 'package:fladder/providers/image_provider.dart'; import 'package:fladder/providers/image_provider.dart';
import 'package:fladder/util/custom_cache_manager.dart';
class Chapter { class Chapter {
final String name; final String name;

View file

@ -1,16 +1,17 @@
import 'dart:convert'; import 'dart:convert';
import 'dart:io'; import 'dart:io';
import 'package:cached_network_image/cached_network_image.dart';
import 'package:collection/collection.dart';
import 'package:fladder/main.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart'; import 'package:flutter/widgets.dart';
import 'package:cached_network_image/cached_network_image.dart';
import 'package:collection/collection.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:fladder/jellyfin/jellyfin_open_api.enums.swagger.dart' as enums; import 'package:fladder/jellyfin/jellyfin_open_api.enums.swagger.dart' as enums;
import 'package:fladder/jellyfin/jellyfin_open_api.swagger.dart' as dto; import 'package:fladder/jellyfin/jellyfin_open_api.swagger.dart' as dto;
import 'package:fladder/providers/image_provider.dart'; import 'package:fladder/providers/image_provider.dart';
import 'package:fladder/util/custom_cache_manager.dart';
import 'package:fladder/util/jelly_id.dart'; import 'package:fladder/util/jelly_id.dart';
class ImagesData { class ImagesData {

View file

@ -1,16 +1,16 @@
import 'package:cached_network_image/cached_network_image.dart';
import 'package:ficonsax/ficonsax.dart';
import 'package:fladder/main.dart';
import 'package:fladder/theme.dart';
import 'package:fladder/util/localization_helper.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:ficonsax/ficonsax.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_typeahead/flutter_typeahead.dart'; import 'package:flutter_typeahead/flutter_typeahead.dart';
import 'package:page_transition/page_transition.dart'; import 'package:page_transition/page_transition.dart';
import 'package:fladder/models/item_base_model.dart'; import 'package:fladder/models/item_base_model.dart';
import 'package:fladder/providers/library_search_provider.dart'; import 'package:fladder/providers/library_search_provider.dart';
import 'package:fladder/theme.dart';
import 'package:fladder/util/debouncer.dart'; import 'package:fladder/util/debouncer.dart';
import 'package:fladder/util/fladder_image.dart';
import 'package:fladder/util/localization_helper.dart';
class SuggestionSearchBar extends ConsumerStatefulWidget { class SuggestionSearchBar extends ConsumerStatefulWidget {
final String? title; final String? title;
@ -141,9 +141,8 @@ class _SearchBarState extends ConsumerState<SuggestionSearchBar> {
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(5)), shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(5)),
child: AspectRatio( child: AspectRatio(
aspectRatio: 0.8, aspectRatio: 0.8,
child: CachedNetworkImage( child: FladderImage(
cacheManager: CustomCacheManager.instance, image: suggestion.images?.primary,
imageUrl: suggestion.images?.primary?.path ?? "",
fit: BoxFit.cover, fit: BoxFit.cover,
), ),
), ),

View file

@ -26,7 +26,7 @@ import 'package:fladder/util/fladder_config.dart';
import 'package:fladder/util/list_padding.dart'; import 'package:fladder/util/list_padding.dart';
import 'package:fladder/util/localization_helper.dart'; import 'package:fladder/util/localization_helper.dart';
import 'package:fladder/util/string_extensions.dart'; import 'package:fladder/util/string_extensions.dart';
import 'package:fladder/widgets/navigation_scaffold/components/fladder_appbar.dart'; import 'package:fladder/widgets/navigation_scaffold/components/fladder_app_bar.dart';
@RoutePage() @RoutePage()
class LoginScreen extends ConsumerStatefulWidget { class LoginScreen extends ConsumerStatefulWidget {
@ -82,7 +82,7 @@ class _LoginPageState extends ConsumerState<LoginScreen> {
final loggedInUsers = ref.watch(authProvider.select((value) => value.accounts)); final loggedInUsers = ref.watch(authProvider.select((value) => value.accounts));
final authLoading = ref.watch(authProvider.select((value) => value.loading)); final authLoading = ref.watch(authProvider.select((value) => value.loading));
return Scaffold( return Scaffold(
appBar: const FladderAppbar(), appBar: const FladderAppBar(),
floatingActionButton: !addingNewUser floatingActionButton: !addingNewUser
? Row( ? Row(
mainAxisAlignment: MainAxisAlignment.end, mainAxisAlignment: MainAxisAlignment.end,

View file

@ -128,7 +128,6 @@ class _CardHolder extends StatelessWidget {
const _CardHolder({ const _CardHolder({
required this.content, required this.content,
super.key,
}); });
@override @override

View file

@ -161,6 +161,7 @@ class _IdentifyScreenState extends ConsumerState<IdentifyScreen> with TickerProv
final externalId = state.externalIds final externalId = state.externalIds
.firstWhereOrNull((element) => element.key == providerKey) .firstWhereOrNull((element) => element.key == providerKey)
// ignore: deprecated_member_use_from_same_package
?.urlFormatString; ?.urlFormatString;
final url = externalId?.replaceAll("{0}", providerValue?.toString() ?? ""); final url = externalId?.replaceAll("{0}", providerValue?.toString() ?? "");

View file

@ -1,31 +1,33 @@
import 'dart:async'; import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:cached_network_image/cached_network_image.dart'; import 'package:cached_network_image/cached_network_image.dart';
import 'package:extended_image/extended_image.dart'; import 'package:extended_image/extended_image.dart';
import 'package:ficonsax/ficonsax.dart'; import 'package:ficonsax/ficonsax.dart';
import 'package:fladder/main.dart'; import 'package:flutter_blurhash/flutter_blurhash.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:fladder/models/item_base_model.dart'; import 'package:fladder/models/item_base_model.dart';
import 'package:fladder/models/items/photos_model.dart'; import 'package:fladder/models/items/photos_model.dart';
import 'package:fladder/providers/settings/photo_view_settings_provider.dart';
import 'package:fladder/providers/user_provider.dart'; import 'package:fladder/providers/user_provider.dart';
import 'package:fladder/screens/photo_viewer/photo_viewer_controls.dart'; import 'package:fladder/screens/photo_viewer/photo_viewer_controls.dart';
import 'package:fladder/providers/settings/photo_view_settings_provider.dart';
import 'package:fladder/screens/photo_viewer/simple_video_player.dart'; import 'package:fladder/screens/photo_viewer/simple_video_player.dart';
import 'package:fladder/screens/shared/default_title_bar.dart'; import 'package:fladder/screens/shared/default_title_bar.dart';
import 'package:fladder/util/adaptive_layout.dart'; import 'package:fladder/util/adaptive_layout.dart';
import 'package:fladder/util/custom_cache_manager.dart';
import 'package:fladder/util/item_base_model/item_base_model_extensions.dart'; import 'package:fladder/util/item_base_model/item_base_model_extensions.dart';
import 'package:fladder/util/list_padding.dart'; import 'package:fladder/util/list_padding.dart';
import 'package:fladder/util/localization_helper.dart'; import 'package:fladder/util/localization_helper.dart';
import 'package:fladder/util/themes_data.dart'; import 'package:fladder/util/themes_data.dart';
import 'package:fladder/widgets/navigation_scaffold/components/fladder_appbar.dart'; import 'package:fladder/widgets/navigation_scaffold/components/fladder_app_bar.dart';
import 'package:fladder/widgets/shared/animated_icon.dart'; import 'package:fladder/widgets/shared/animated_icon.dart';
import 'package:fladder/widgets/shared/elevated_icon.dart'; import 'package:fladder/widgets/shared/elevated_icon.dart';
import 'package:fladder/widgets/shared/hover_widget.dart'; import 'package:fladder/widgets/shared/hover_widget.dart';
import 'package:fladder/widgets/shared/item_actions.dart'; import 'package:fladder/widgets/shared/item_actions.dart';
import 'package:fladder/widgets/shared/modal_bottom_sheet.dart'; import 'package:fladder/widgets/shared/modal_bottom_sheet.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_blurhash/flutter_blurhash.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
class PhotoViewerScreen extends ConsumerStatefulWidget { class PhotoViewerScreen extends ConsumerStatefulWidget {
final List<PhotoModel>? items; final List<PhotoModel>? items;
@ -151,7 +153,7 @@ class _PhotoViewerScreenState extends ConsumerState<PhotoViewerScreen> with Widg
onExit: (event) => setState(() => _showOverlay(show: false)), onExit: (event) => setState(() => _showOverlay(show: false)),
child: Scaffold( child: Scaffold(
appBar: photos.isEmpty appBar: photos.isEmpty
? const FladderAppbar( ? const FladderAppBar(
automaticallyImplyLeading: true, automaticallyImplyLeading: true,
) )
: null, : null,

View file

@ -15,6 +15,7 @@ import 'package:fladder/providers/user_provider.dart';
import 'package:fladder/util/duration_extensions.dart'; import 'package:fladder/util/duration_extensions.dart';
import 'package:fladder/util/fladder_image.dart'; import 'package:fladder/util/fladder_image.dart';
import 'package:fladder/widgets/shared/fladder_slider.dart'; import 'package:fladder/widgets/shared/fladder_slider.dart';
import 'package:fladder/wrappers/players/base_player.dart';
import 'package:fladder/wrappers/players/lib_mdk.dart' import 'package:fladder/wrappers/players/lib_mdk.dart'
if (dart.library.html) 'package:fladder/stubs/web/lib_mdk_web.dart'; if (dart.library.html) 'package:fladder/stubs/web/lib_mdk_web.dart';
import 'package:fladder/wrappers/players/lib_mpv.dart'; import 'package:fladder/wrappers/players/lib_mpv.dart';
@ -30,7 +31,7 @@ class SimpleVideoPlayer extends ConsumerStatefulWidget {
} }
class _SimpleVideoPlayerState extends ConsumerState<SimpleVideoPlayer> with WindowListener, WidgetsBindingObserver { class _SimpleVideoPlayerState extends ConsumerState<SimpleVideoPlayer> with WindowListener, WidgetsBindingObserver {
late final player = switch (ref.read(videoPlayerSettingsProvider.select((value) => value.wantedPlayer))) { late final BasePlayer player = switch (ref.read(videoPlayerSettingsProvider.select((value) => value.wantedPlayer))) {
PlayerOptions.libMDK => LibMDK(), PlayerOptions.libMDK => LibMDK(),
PlayerOptions.libMPV => LibMPV(), PlayerOptions.libMPV => LibMPV(),
}; };
@ -68,7 +69,10 @@ class _SimpleVideoPlayerState extends ConsumerState<SimpleVideoPlayer> with Wind
playing = player.lastState.playing; playing = player.lastState.playing;
position = player.lastState.position; position = player.lastState.position;
duration = player.lastState.duration; duration = player.lastState.duration;
Future.microtask(() async => {_init()}); WidgetsBinding.instance.addPostFrameCallback((value) async {
await Future.delayed(const Duration(milliseconds: 500));
if (mounted) _init();
});
} }
@override @override
@ -86,6 +90,8 @@ class _SimpleVideoPlayerState extends ConsumerState<SimpleVideoPlayer> with Wind
final params = Uri(queryParameters: directOptions).query; final params = Uri(queryParameters: directOptions).query;
player.init(ref.read(videoPlayerSettingsProvider));
videoUrl = '${ref.read(userProvider)?.server ?? ""}/Videos/${widget.video.id}/stream?$params'; videoUrl = '${ref.read(userProvider)?.server ?? ""}/Videos/${widget.video.id}/stream?$params';
subscriptions.add(player.stateStream.listen((event) { subscriptions.add(player.stateStream.listen((event) {
@ -101,8 +107,8 @@ class _SimpleVideoPlayerState extends ConsumerState<SimpleVideoPlayer> with Wind
} }
})); }));
await player.open(videoUrl, !ref.watch(photoViewSettingsProvider).autoPlay); await player.open(videoUrl, !ref.watch(photoViewSettingsProvider).autoPlay);
await player.loop(ref.watch(photoViewSettingsProvider.select((value) => value.repeat)));
await player.setVolume(ref.watch(photoViewSettingsProvider.select((value) => value.mute)) ? 0 : 100); await player.setVolume(ref.watch(photoViewSettingsProvider.select((value) => value.mute)) ? 0 : 100);
await player.loop(ref.watch(photoViewSettingsProvider.select((value) => value.repeat)));
} }
@override @override
@ -124,16 +130,13 @@ class _SimpleVideoPlayerState extends ConsumerState<SimpleVideoPlayer> with Wind
.textTheme .textTheme
.titleMedium .titleMedium
?.copyWith(fontWeight: FontWeight.bold, shadows: [const Shadow(blurRadius: 2)]); ?.copyWith(fontWeight: FontWeight.bold, shadows: [const Shadow(blurRadius: 2)]);
ref.listen(photoViewSettingsProvider.select((value) => value.repeat), (previous, next) { ref.listen(
player.loop(next); photoViewSettingsProvider.select((value) => value.repeat),
}); (previous, next) => player.loop(next),
);
ref.listen( ref.listen(
photoViewSettingsProvider.select((value) => value.mute), photoViewSettingsProvider.select((value) => value.mute),
(previous, next) { (previous, next) => player.setVolume(next ? 0 : 100),
if (previous != next) {
player.setVolume(next ? 0 : 100);
}
},
); );
return GestureDetector( return GestureDetector(
onTap: widget.onTapped, onTap: widget.onTapped,
@ -154,13 +157,6 @@ class _SimpleVideoPlayerState extends ConsumerState<SimpleVideoPlayer> with Wind
UniqueKey(), UniqueKey(),
BoxFit.contain, BoxFit.contain,
), ),
// child: Video(
// fit: BoxFit.contain,
// fill: const Color.fromARGB(0, 123, 62, 62),
// controller: controller,
// controls: NoVideoControls,
// wakelock: false,
// ),
), ),
IgnorePointer( IgnorePointer(
ignoring: !widget.showOverlay, ignoring: !widget.showOverlay,

View file

@ -9,7 +9,7 @@ import 'package:fladder/providers/settings/video_player_settings_provider.dart';
import 'package:fladder/screens/video_player/components/video_subtitle_controls.dart'; import 'package:fladder/screens/video_player/components/video_subtitle_controls.dart';
import 'package:fladder/util/adaptive_layout.dart'; import 'package:fladder/util/adaptive_layout.dart';
import 'package:fladder/util/localization_helper.dart'; import 'package:fladder/util/localization_helper.dart';
import 'package:fladder/widgets/navigation_scaffold/components/fladder_appbar.dart'; import 'package:fladder/widgets/navigation_scaffold/components/fladder_app_bar.dart';
class SubtitleEditor extends ConsumerStatefulWidget { class SubtitleEditor extends ConsumerStatefulWidget {
const SubtitleEditor({super.key}); const SubtitleEditor({super.key});
@ -73,7 +73,7 @@ class _SubtitleEditorState extends ConsumerState<SubtitleEditor> {
padding: MediaQuery.paddingOf(context), padding: MediaQuery.paddingOf(context),
child: Column( child: Column(
children: [ children: [
if (AdaptiveLayout.of(context).isDesktop) const FladderAppbar(), if (AdaptiveLayout.of(context).isDesktop) const FladderAppBar(),
Row( Row(
children: [ children: [
const BackButton(), const BackButton(),

View file

@ -1,9 +1,11 @@
import 'package:flutter/material.dart';
import 'package:cached_network_image/cached_network_image.dart'; import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:fladder/models/account_model.dart'; import 'package:fladder/models/account_model.dart';
import 'package:fladder/screens/shared/flat_button.dart'; import 'package:fladder/screens/shared/flat_button.dart';
import 'package:fladder/util/string_extensions.dart'; import 'package:fladder/util/string_extensions.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
class UserIcon extends ConsumerWidget { class UserIcon extends ConsumerWidget {
final AccountModel? user; final AccountModel? user;

View file

@ -1,7 +1,7 @@
import 'package:fladder/models/item_base_model.dart'; import 'package:fladder/models/item_base_model.dart';
import 'package:fladder/screens/shared/media/item_detail_list_widget.dart'; import 'package:fladder/screens/shared/media/item_detail_list_widget.dart';
import 'package:fladder/util/widget_extensions.dart'; import 'package:fladder/util/widget_extensions.dart';
import 'package:fladder/widgets/navigation_scaffold/components/fladder_appbar.dart'; import 'package:fladder/widgets/navigation_scaffold/components/fladder_app_bar.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart';
@ -46,7 +46,7 @@ class _VideoPlayerQueueState extends ConsumerState<VideoPlayerQueue> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(
appBar: const FladderAppbar( appBar: const FladderAppBar(
label: "", label: "",
automaticallyImplyLeading: true, automaticallyImplyLeading: true,
), ),

View file

@ -2,10 +2,9 @@ import 'dart:async';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:fladder/models/items/media_streams_model.dart'; import 'package:fladder/models/items/media_streams_model.dart';
import 'package:fladder/models/playback/playback_model.dart'; import 'package:fladder/models/playback/playback_model.dart';
import 'package:fladder/models/settings/video_player_settings.dart';
import 'package:fladder/wrappers/players/base_player.dart'; import 'package:fladder/wrappers/players/base_player.dart';
import 'package:fladder/wrappers/players/player_states.dart'; import 'package:fladder/wrappers/players/player_states.dart';
@ -18,7 +17,7 @@ class LibMDK extends BasePlayer {
Stream<PlayerState> get stateStream => _stateController.stream; Stream<PlayerState> get stateStream => _stateController.stream;
@override @override
Future<void> init(Ref ref) async {} Future<void> init(VideoPlayerSettingsModel settings) async {}
@override @override
Future<void> dispose() async {} Future<void> dispose() async {}

View file

@ -14,7 +14,7 @@ class SMTCWindows {
bool? enabled, bool? enabled,
}); });
get buttonPressStream => null; late final Stream<PressedButton> buttonPressStream;
Future<void> updateConfig(SMTCConfig config) async {} Future<void> updateConfig(SMTCConfig config) async {}

View file

@ -4,6 +4,7 @@ import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:fladder/routes/auto_router.dart'; import 'package:fladder/routes/auto_router.dart';
import 'package:fladder/util/debug_banner.dart';
import 'package:fladder/util/poster_defaults.dart'; import 'package:fladder/util/poster_defaults.dart';
enum LayoutState { enum LayoutState {
@ -202,7 +203,7 @@ class _AdaptiveLayoutBuilderState extends ConsumerState<AdaptiveLayoutBuilder> {
LayoutState.tablet => const PosterDefaults(size: 350, ratio: 0.55), LayoutState.tablet => const PosterDefaults(size: 350, ratio: 0.55),
LayoutState.desktop => const PosterDefaults(size: 400, ratio: 0.55), LayoutState.desktop => const PosterDefaults(size: 400, ratio: 0.55),
}, },
child: widget.child, child: DebugBanner(child: widget.child),
), ),
); );
} }

View file

@ -0,0 +1,13 @@
import 'package:flutter_cache_manager/flutter_cache_manager.dart';
class CustomCacheManager {
static const key = 'customCacheKey';
static CacheManager instance = CacheManager(
Config(
key,
stalePeriod: const Duration(days: 3),
maxNrOfCacheObjects: 250,
fileService: HttpFileService(),
),
);
}

View file

@ -0,0 +1,52 @@
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:fladder/providers/video_player_provider.dart';
class DebugBanner extends ConsumerWidget {
final Widget child;
const DebugBanner({required this.child, super.key});
@override
Widget build(BuildContext context, WidgetRef ref) {
final isPlaying = ref.watch(mediaPlaybackProvider.select((value) => value.playing));
if (!kDebugMode) return child;
return Directionality(
textDirection: TextDirection.ltr,
child: Stack(
fit: StackFit.expand,
children: [
child,
Align(
alignment: Alignment.bottomRight,
child: AnimatedOpacity(
opacity: isPlaying ? 0 : 1,
duration: const Duration(milliseconds: 500),
child: IgnorePointer(
child: Padding(
padding: const EdgeInsets.all(4.0),
child: Card(
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(6)),
color: Colors.purpleAccent.withOpacity(0.8),
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 6, vertical: 2),
child: Text(
"Debug",
style: Theme.of(context).textTheme.bodyMedium?.copyWith(
fontWeight: FontWeight.bold,
color: Colors.white,
),
),
),
),
),
),
),
)
],
),
);
}
}

View file

@ -1,10 +1,12 @@
import 'package:auto_route/auto_route.dart';
import 'package:fladder/screens/shared/default_title_bar.dart';
import 'package:fladder/util/adaptive_layout.dart';
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'package:auto_route/auto_route.dart';
import 'package:fladder/screens/shared/default_title_bar.dart';
import 'package:fladder/util/adaptive_layout.dart';
bool get _isDesktop { bool get _isDesktop {
if (kIsWeb) return false; if (kIsWeb) return false;
return [ return [
@ -14,11 +16,11 @@ bool get _isDesktop {
].contains(defaultTargetPlatform); ].contains(defaultTargetPlatform);
} }
class FladderAppbar extends StatelessWidget implements PreferredSize { class FladderAppBar extends StatelessWidget implements PreferredSize {
final double height; final double height;
final String? label; final String? label;
final bool automaticallyImplyLeading; final bool automaticallyImplyLeading;
const FladderAppbar({this.height = 35, this.automaticallyImplyLeading = false, this.label, super.key}); const FladderAppBar({this.height = 35, this.automaticallyImplyLeading = false, this.label, super.key});
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {

View file

@ -8,7 +8,7 @@ import 'package:fladder/providers/views_provider.dart';
import 'package:fladder/screens/shared/nested_bottom_appbar.dart'; import 'package:fladder/screens/shared/nested_bottom_appbar.dart';
import 'package:fladder/util/adaptive_layout.dart'; import 'package:fladder/util/adaptive_layout.dart';
import 'package:fladder/widgets/navigation_scaffold/components/destination_model.dart'; import 'package:fladder/widgets/navigation_scaffold/components/destination_model.dart';
import 'package:fladder/widgets/navigation_scaffold/components/fladder_appbar.dart'; import 'package:fladder/widgets/navigation_scaffold/components/fladder_app_bar.dart';
import 'package:fladder/widgets/navigation_scaffold/components/floating_player_bar.dart'; import 'package:fladder/widgets/navigation_scaffold/components/floating_player_bar.dart';
import 'package:fladder/widgets/navigation_scaffold/components/navigation_body.dart'; import 'package:fladder/widgets/navigation_scaffold/components/navigation_body.dart';
import 'package:fladder/widgets/navigation_scaffold/components/navigation_drawer.dart'; import 'package:fladder/widgets/navigation_scaffold/components/navigation_drawer.dart';
@ -60,7 +60,7 @@ class _NavigationScaffoldState extends ConsumerState<NavigationScaffold> {
}, },
child: Scaffold( child: Scaffold(
key: _key, key: _key,
appBar: const FladderAppbar(), appBar: const FladderAppBar(),
extendBodyBehindAppBar: true, extendBodyBehindAppBar: true,
extendBody: true, extendBody: true,
floatingActionButtonLocation: floatingActionButtonLocation:

View file

@ -78,7 +78,7 @@ class MediaControlsWrapper extends BaseAudioHandler {
Future<void> setup(BasePlayer newPlayer) async { Future<void> setup(BasePlayer newPlayer) async {
_player = newPlayer; _player = newPlayer;
await newPlayer.init(ref); await newPlayer.init(ref.read(videoPlayerSettingsProvider));
_initPlayer(); _initPlayer();
} }

View file

@ -2,10 +2,9 @@ import 'dart:async';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:fladder/models/items/media_streams_model.dart'; import 'package:fladder/models/items/media_streams_model.dart';
import 'package:fladder/models/playback/playback_model.dart'; import 'package:fladder/models/playback/playback_model.dart';
import 'package:fladder/models/settings/video_player_settings.dart';
import 'package:fladder/wrappers/players/player_states.dart'; import 'package:fladder/wrappers/players/player_states.dart';
const libassFallbackFont = "assets/mp-font.ttf"; const libassFallbackFont = "assets/mp-font.ttf";
@ -14,7 +13,7 @@ abstract class BasePlayer {
Stream<PlayerState> get stateStream; Stream<PlayerState> get stateStream;
PlayerState lastState = PlayerState(); PlayerState lastState = PlayerState();
Future<void> init(Ref ref); Future<void> init(VideoPlayerSettingsModel settings);
Widget? videoWidget( Widget? videoWidget(
Key key, Key key,
BoxFit fit, BoxFit fit,

View file

@ -3,13 +3,13 @@ import 'dart:io';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:fvp/fvp.dart' as fvp; import 'package:fvp/fvp.dart' as fvp;
import 'package:fvp/mdk.dart'; import 'package:fvp/mdk.dart';
import 'package:video_player/video_player.dart'; import 'package:video_player/video_player.dart';
import 'package:fladder/models/items/media_streams_model.dart'; import 'package:fladder/models/items/media_streams_model.dart';
import 'package:fladder/models/playback/playback_model.dart'; import 'package:fladder/models/playback/playback_model.dart';
import 'package:fladder/models/settings/video_player_settings.dart';
import 'package:fladder/wrappers/players/base_player.dart'; import 'package:fladder/wrappers/players/base_player.dart';
import 'package:fladder/wrappers/players/player_states.dart'; import 'package:fladder/wrappers/players/player_states.dart';
@ -25,7 +25,7 @@ class LibMDK extends BasePlayer {
Stream<PlayerState> get stateStream => _stateController.stream; Stream<PlayerState> get stateStream => _stateController.stream;
@override @override
Future<void> init(Ref ref) async { Future<void> init(VideoPlayerSettingsModel settings) async {
dispose(); dispose();
fvp.registerWith(options: { fvp.registerWith(options: {
'global': {'log': 'off'}, 'global': {'log': 'off'},
@ -41,19 +41,26 @@ class LibMDK extends BasePlayer {
@override @override
Future<void> open(String url, bool play) async { Future<void> open(String url, bool play) async {
if (_controller != null) {
_controller?.dispose();
}
final validUrl = isValidUrl(url); final validUrl = isValidUrl(url);
if (validUrl != null) { if (validUrl != null) {
_controller = VideoPlayerController.networkUrl(validUrl); _controller = VideoPlayerController.networkUrl(validUrl);
} else { } else {
_controller = VideoPlayerController.file(File(url)); _controller = VideoPlayerController.file(File(url));
} }
await _controller?.initialize();
await _controller?.initialize();
_controller?.addListener(() => updateState()); _controller?.addListener(() => updateState());
if (play) { if (play) {
await _controller?.play(); await _controller?.play();
} }
_controller?.setBufferRange(
min: const Duration(seconds: 15).inMilliseconds,
max: const Duration(seconds: 30).inMilliseconds,
);
return setState(lastState.update( return setState(lastState.update(
buffering: true, buffering: true,
)); ));
@ -73,10 +80,21 @@ class LibMDK extends BasePlayer {
volume: (_controller?.value.volume ?? 1.0) * 100, volume: (_controller?.value.volume ?? 1.0) * 100,
rate: _controller?.value.playbackSpeed ?? 1.0, rate: _controller?.value.playbackSpeed ?? 1.0,
buffering: _controller?.value.isBuffering ?? true, buffering: _controller?.value.isBuffering ?? true,
buffer: _controller?.value.buffered.last.end ?? Duration.zero, buffer: calculateBufferedDuration(_controller?.value),
)); ));
} }
Duration calculateBufferedDuration(VideoPlayerValue? value) {
if (value == null) return Duration.zero;
if (value.buffered.isEmpty) {
return Duration.zero;
}
return value.buffered.fold(value.position, (total, range) {
return (total + (range.end - range.start));
});
}
@override @override
Future<void> pause() async => _controller?.pause(); Future<void> pause() async => _controller?.pause();
@override @override

View file

@ -11,8 +11,8 @@ import 'package:media_kit_video/media_kit_video.dart';
import 'package:fladder/models/items/media_streams_model.dart'; import 'package:fladder/models/items/media_streams_model.dart';
import 'package:fladder/models/playback/playback_model.dart'; import 'package:fladder/models/playback/playback_model.dart';
import 'package:fladder/models/settings/subtitle_settings_model.dart'; import 'package:fladder/models/settings/subtitle_settings_model.dart';
import 'package:fladder/models/settings/video_player_settings.dart';
import 'package:fladder/providers/settings/subtitle_settings_provider.dart'; import 'package:fladder/providers/settings/subtitle_settings_provider.dart';
import 'package:fladder/providers/settings/video_player_settings_provider.dart';
import 'package:fladder/wrappers/players/base_player.dart'; import 'package:fladder/wrappers/players/base_player.dart';
import 'package:fladder/wrappers/players/player_states.dart'; import 'package:fladder/wrappers/players/player_states.dart';
@ -27,7 +27,7 @@ class LibMPV extends BasePlayer {
StreamSubscription<bool>? _onCompleted; StreamSubscription<bool>? _onCompleted;
@override @override
Future<void> init(Ref ref) async { Future<void> init(VideoPlayerSettingsModel settings) async {
dispose(); dispose();
mpv.MediaKit.ensureInitialized(); mpv.MediaKit.ensureInitialized();
@ -36,10 +36,7 @@ class LibMPV extends BasePlayer {
configuration: mpv.PlayerConfiguration( configuration: mpv.PlayerConfiguration(
title: "nl.jknaapen.fladder", title: "nl.jknaapen.fladder",
libassAndroidFont: libassFallbackFont, libassAndroidFont: libassFallbackFont,
libass: !kIsWeb && libass: !kIsWeb && settings.useLibass,
ref.read(
videoPlayerSettingsProvider.select((value) => value.useLibass),
),
), ),
); );
@ -47,9 +44,7 @@ class LibMPV extends BasePlayer {
_controller = VideoController( _controller = VideoController(
_player!, _player!,
configuration: VideoControllerConfiguration( configuration: VideoControllerConfiguration(
enableHardwareAcceleration: ref.read( enableHardwareAcceleration: settings.hardwareAccel,
videoPlayerSettingsProvider.select((value) => value.hardwareAccel),
),
), ),
); );

View file

@ -15,7 +15,6 @@ list(APPEND FLUTTER_PLUGIN_LIST
) )
list(APPEND FLUTTER_FFI_PLUGIN_LIST list(APPEND FLUTTER_FFI_PLUGIN_LIST
media_kit_native_event_loop
) )
set(PLUGIN_BUNDLED_LIBRARIES) set(PLUGIN_BUNDLED_LIBRARIES)

View file

@ -907,13 +907,13 @@ packages:
source: hosted source: hosted
version: "4.0.0-dev.14" version: "4.0.0-dev.14"
js: js:
dependency: transitive dependency: "direct overridden"
description: description:
name: js name: js
sha256: f2c445dce49627136094980615a031419f7f3eb393237e4ecd97ac15dea343f3 sha256: c1b2e9b5ea78c45e1a0788d29606ba27dc5f71f019f32ca5140f61ef071838cf
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.6.7" version: "0.7.1"
json_annotation: json_annotation:
dependency: "direct main" dependency: "direct main"
description: description:
@ -1069,10 +1069,11 @@ packages:
media_kit: media_kit:
dependency: "direct main" dependency: "direct main"
description: description:
name: media_kit path: media_kit
sha256: "1f1deee148533d75129a6f38251ff8388e33ee05fc2d20a6a80e57d6051b7b62" ref: HEAD
url: "https://pub.dev" resolved-ref: "4afa396e89543141bc9c72e643981ada67aae232"
source: hosted url: "https://github.com/DonutWare/media-kit"
source: git
version: "1.1.11" version: "1.1.11"
media_kit_libs_android_video: media_kit_libs_android_video:
dependency: transitive dependency: transitive
@ -1109,10 +1110,11 @@ packages:
media_kit_libs_video: media_kit_libs_video:
dependency: "direct main" dependency: "direct main"
description: description:
name: media_kit_libs_video path: "libs/universal/media_kit_libs_video"
sha256: "20bb4aefa8fece282b59580e1cd8528117297083a6640c98c2e98cfc96b93288" ref: HEAD
url: "https://pub.dev" resolved-ref: "4afa396e89543141bc9c72e643981ada67aae232"
source: hosted url: "https://github.com/DonutWare/media-kit"
source: git
version: "1.0.5" version: "1.0.5"
media_kit_libs_windows_video: media_kit_libs_windows_video:
dependency: transitive dependency: transitive
@ -1122,21 +1124,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.0.10" version: "1.0.10"
media_kit_native_event_loop:
dependency: transitive
description:
name: media_kit_native_event_loop
sha256: "7d82e3b3e9ded5c35c3146c5ba1da3118d1dd8ac3435bac7f29f458181471b40"
url: "https://pub.dev"
source: hosted
version: "1.0.9"
media_kit_video: media_kit_video:
dependency: "direct main" dependency: "direct main"
description: description:
name: media_kit_video path: media_kit_video
sha256: "2cc3b966679963ba25a4ce5b771e532a521ebde7c6aa20e9802bec95d9916c8f" ref: HEAD
url: "https://pub.dev" resolved-ref: "4afa396e89543141bc9c72e643981ada67aae232"
source: hosted url: "https://github.com/DonutWare/media-kit"
source: git
version: "1.2.5" version: "1.2.5"
meta: meta:
dependency: transitive dependency: transitive
@ -1494,58 +1489,58 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: safe_local_storage name: safe_local_storage
sha256: ede4eb6cb7d88a116b3d3bf1df70790b9e2038bc37cb19112e381217c74d9440 sha256: e9a21b6fec7a8aa62cc2585ff4c1b127df42f3185adbd2aca66b47abe2e80236
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.0.2" version: "2.0.1"
screen_brightness: screen_brightness:
dependency: "direct main" dependency: "direct main"
description: description:
name: screen_brightness name: screen_brightness
sha256: ed8da4a4511e79422fc1aa88138e920e4008cd312b72cdaa15ccb426c0faaedd sha256: "7d4ac84ae26b37c01d6f5db7123a72db7933e1f2a2a8c369a51e08f81b3178d8"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.2.2+1" version: "1.0.1"
screen_brightness_android: screen_brightness_android:
dependency: transitive dependency: transitive
description: description:
name: screen_brightness_android name: screen_brightness_android
sha256: "3df10961e3a9e968a5e076fe27e7f4741fa8a1d3950bdeb48cf121ed529d0caf" sha256: "8c69d3ac475e4d625e7fa682a3a51a69ff59abe5b4a9e57f6ec7d830a6c69bd6"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.1.0+2" version: "1.0.1"
screen_brightness_ios: screen_brightness_ios:
dependency: transitive dependency: transitive
description: description:
name: screen_brightness_ios name: screen_brightness_ios
sha256: "99adc3ca5490b8294284aad5fcc87f061ad685050e03cf45d3d018fe398fd9a2" sha256: f08f70ca1ac3e30719764b5cfb8b3fe1e28163065018a41b3e6f243ab146c2f1
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.1.0" version: "1.0.1"
screen_brightness_macos: screen_brightness_macos:
dependency: transitive dependency: transitive
description: description:
name: screen_brightness_macos name: screen_brightness_macos
sha256: "64b34e7e3f4900d7687c8e8fb514246845a73ecec05ab53483ed025bd4a899fd" sha256: "70c2efa4534e22b927e82693488f127dd4a0f008469fccf4f0eefe9061bbdd6a"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.1.0+1" version: "1.0.1"
screen_brightness_platform_interface: screen_brightness_platform_interface:
dependency: transitive dependency: transitive
description: description:
name: screen_brightness_platform_interface name: screen_brightness_platform_interface
sha256: b211d07f0c96637a15fb06f6168617e18030d5d74ad03795dd8547a52717c171 sha256: "9f3ebf7f22d5487e7676fe9ddaf3fc55b6ff8057707cf6dc0121c7dfda346a16"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.1.0" version: "1.0.1"
screen_brightness_windows: screen_brightness_windows:
dependency: transitive dependency: transitive
description: description:
name: screen_brightness_windows name: screen_brightness_windows
sha256: "9261bf33d0fc2707d8cf16339ce25768100a65e70af0fcabaf032fc12408ba86" sha256: c8e12a91cf6dd912a48bd41fcf749282a51afa17f536c3460d8d05702fb89ffa
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.1.3" version: "1.0.1"
screen_retriever: screen_retriever:
dependency: transitive dependency: transitive
description: description:
@ -1907,10 +1902,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: uri_parser name: uri_parser
sha256: "6543c9fd86d2862fac55d800a43e67c0dcd1a41677cb69c2f8edfe73bbcf1835" sha256: ff4d2c720aca3f4f7d5445e23b11b2d15ef8af5ddce5164643f38ff962dcb270
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.0.2" version: "3.0.0"
url_launcher: url_launcher:
dependency: "direct main" dependency: "direct main"
description: description:

View file

@ -109,7 +109,7 @@ dependencies:
package_info_plus: ^8.0.0 package_info_plus: ^8.0.0
open_app_file: ^4.0.2 open_app_file: ^4.0.2
wakelock_plus: ^1.1.4 wakelock_plus: ^1.1.4
screen_brightness: ^0.2.2+1 screen_brightness: ^1.0.1
window_manager: ^0.3.9 window_manager: ^0.3.9
smtc_windows: ^0.1.1 smtc_windows: ^0.1.1
background_downloader: ^8.5.2 background_downloader: ^8.5.2
@ -149,6 +149,21 @@ dev_dependencies:
dart_mappable_builder: ^4.2.3 dart_mappable_builder: ^4.2.3
auto_route_generator: ^9.0.0 auto_route_generator: ^9.0.0
dependency_overrides:
js: ^0.7.1
media_kit:
git:
url: https://github.com/DonutWare/media-kit
path: media_kit
media_kit_video:
git:
url: https://github.com/DonutWare/media-kit
path: media_kit_video
media_kit_libs_video:
git:
url: https://github.com/DonutWare/media-kit
path: libs/universal/media_kit_libs_video
flutter: flutter:
# The following line ensures that the Material Icons font is # The following line ensures that the Material Icons font is
# included with your application, so that you can use the icons in # included with your application, so that you can use the icons in

View file

@ -19,7 +19,6 @@ list(APPEND FLUTTER_PLUGIN_LIST
) )
list(APPEND FLUTTER_FFI_PLUGIN_LIST list(APPEND FLUTTER_FFI_PLUGIN_LIST
media_kit_native_event_loop
smtc_windows smtc_windows
) )