mirror of
https://github.com/feeddeck/feeddeck.git
synced 2026-03-09 07:02:01 -05:00
Fix the audio playback on Windows and Linux for the podcast player by adding the missing initialization for `JustAudioMediaKit`.
220 lines
8.5 KiB
Dart
220 lines
8.5 KiB
Dart
import 'dart:io' show Platform;
|
|
|
|
import 'package:flutter/foundation.dart';
|
|
import 'package:flutter/gestures.dart';
|
|
import 'package:flutter/material.dart';
|
|
|
|
import 'package:flutter_native_splash/flutter_native_splash.dart';
|
|
import 'package:flutter_web_plugins/url_strategy.dart';
|
|
import 'package:just_audio_background/just_audio_background.dart';
|
|
import 'package:just_audio_media_kit/just_audio_media_kit.dart';
|
|
import 'package:media_kit/media_kit.dart';
|
|
import 'package:provider/provider.dart';
|
|
import 'package:window_manager/window_manager.dart';
|
|
|
|
import 'package:feeddeck/repositories/app_repository.dart';
|
|
import 'package:feeddeck/repositories/layout_repository.dart';
|
|
import 'package:feeddeck/repositories/profile_repository.dart';
|
|
import 'package:feeddeck/repositories/settings_repository.dart';
|
|
import 'package:feeddeck/utils/constants.dart';
|
|
import 'package:feeddeck/widgets/confirmation/confirmation.dart';
|
|
import 'package:feeddeck/widgets/home/home.dart';
|
|
import 'package:feeddeck/widgets/reset_password/reset_password.dart';
|
|
|
|
/// Before we are calling [runApp] we have to ensure that the widget bindings
|
|
/// are initialized, so that we can preserve the splash screen until we are done
|
|
/// with the initalization of the app.
|
|
void main() async {
|
|
WidgetsBinding widgetsBinding = WidgetsFlutterBinding.ensureInitialized();
|
|
FlutterNativeSplash.preserve(widgetsBinding: widgetsBinding);
|
|
|
|
/// We have to initialize the [windowManager] before we are calling [runApp]
|
|
/// on all desktop platforms, so we can set the window size, title and so on.
|
|
if (!kIsWeb && (Platform.isLinux || Platform.isMacOS || Platform.isWindows)) {
|
|
await windowManager.ensureInitialized();
|
|
|
|
WindowOptions windowOptions = const WindowOptions(
|
|
size: Size(1024, 768),
|
|
center: true,
|
|
backgroundColor: Colors.transparent,
|
|
skipTaskbar: false,
|
|
titleBarStyle: TitleBarStyle.normal,
|
|
);
|
|
|
|
windowManager.waitUntilReadyToShow(windowOptions, () async {
|
|
await windowManager.setTitle('FeedDeck');
|
|
await windowManager.show();
|
|
await windowManager.focus();
|
|
});
|
|
}
|
|
|
|
/// Initialize the [media_kit] packages, so that we can play audio and video
|
|
/// files.
|
|
MediaKit.ensureInitialized();
|
|
JustAudioMediaKit.ensureInitialized();
|
|
|
|
/// Initialize the [just_audio_background] package, so that we can play audio
|
|
/// files in the background.
|
|
///
|
|
/// We can not initialize the [just_audio_background] package on Windows and
|
|
/// Linux, because then the returned duration in the `_player.durationStream`
|
|
/// isn't working correctly in the [ItemAudioPlayer] widget.
|
|
if (kIsWeb || Platform.isAndroid || Platform.isIOS || Platform.isMacOS) {
|
|
await JustAudioBackground.init(
|
|
androidNotificationChannelId: 'com.ryanheise.bg_demo.channel.audio',
|
|
androidNotificationChannelName: 'Audio playback',
|
|
androidNotificationOngoing: true,
|
|
);
|
|
}
|
|
|
|
/// For the ewb we have to use the path url strategy, so that the redirect
|
|
/// within Supabase is working in all cases. On all other platforms this is a
|
|
/// noop.
|
|
usePathUrlStrategy();
|
|
|
|
/// We also have to initialize the [SettingsRepository], which contains all
|
|
/// the settings, to use the app with Supabase. This way a user can also use
|
|
/// his own Supabase backend.
|
|
await SettingsRepository().init();
|
|
|
|
runApp(const FeedDeckApp());
|
|
}
|
|
|
|
/// [FeedDeckScrollBehavior] changes the scrolling behavior of the app. This is
|
|
/// required to enable scrolling on desktop via drag, which is the only way that
|
|
/// a user can scroll vertically with a mouse via drag.
|
|
///
|
|
/// E.g. this is required for the [ColumnLayoutSources] widget, where we rely on
|
|
/// the drag gesture to scroll the list of sources.
|
|
class FeedDeckScrollBehavior extends MaterialScrollBehavior {
|
|
@override
|
|
Set<PointerDeviceKind> get dragDevices => {
|
|
PointerDeviceKind.touch,
|
|
PointerDeviceKind.mouse,
|
|
PointerDeviceKind.trackpad,
|
|
PointerDeviceKind.stylus,
|
|
PointerDeviceKind.unknown,
|
|
};
|
|
}
|
|
|
|
/// [onGenerateRoute] is used in `onGenerateRoute` and `onGenerateInitialRoutes`
|
|
/// of the [MaterialApp] to add handling for some special routes were do not
|
|
/// want to render the [Home] widget (e.g. set a new password).
|
|
///
|
|
/// For that we have to check the current path and when the user call one of
|
|
/// this "special" routes we render the corresponding widget and pass all the
|
|
/// required values from the query paramters to this widget.
|
|
Route onGenerateRoute(RouteSettings settings) {
|
|
if (settings.name != null) {
|
|
var uriData = Uri.parse(settings.name!);
|
|
|
|
switch (uriData.path) {
|
|
case '/confirmation':
|
|
return MaterialPageRoute(
|
|
builder: (_) => Confirmation(
|
|
template: uriData.queryParameters['template'] ?? '',
|
|
confirmationUrl: uriData.queryParameters['confirmation_url'] ?? '',
|
|
),
|
|
);
|
|
case '/reset-password':
|
|
return MaterialPageRoute(
|
|
builder: (_) => const ResetPassword(),
|
|
);
|
|
}
|
|
}
|
|
|
|
return MaterialPageRoute(
|
|
builder: (_) => const Home(),
|
|
);
|
|
}
|
|
|
|
/// The [FeedDeckApp] is the root widget of the app. The widget is used to
|
|
/// initialize some of our providers via the [MultiProvider] widget and to set
|
|
/// the theme for the app.
|
|
class FeedDeckApp extends StatelessWidget {
|
|
const FeedDeckApp({super.key});
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return MultiProvider(
|
|
providers: [
|
|
ChangeNotifierProvider(create: (_) => LayoutRepository()),
|
|
ChangeNotifierProvider(create: (_) => AppRepository()),
|
|
ChangeNotifierProvider(create: (_) => ProfileRepository()),
|
|
],
|
|
child: TooltipVisibility(
|
|
visible: false,
|
|
child: MaterialApp(
|
|
title: 'FeedDeck',
|
|
debugShowCheckedModeBanner: false,
|
|
theme: ThemeData(
|
|
useMaterial3: true,
|
|
colorScheme: const ColorScheme(
|
|
brightness: Constants.brightness,
|
|
primary: Constants.primary,
|
|
onPrimary: Constants.onPrimary,
|
|
secondary: Constants.secondary,
|
|
onSecondary: Constants.onSecondary,
|
|
error: Constants.error,
|
|
onError: Constants.onError,
|
|
background: Constants.background,
|
|
onBackground: Constants.onBackground,
|
|
surface: Constants.surface,
|
|
onSurface: Constants.onSurface,
|
|
),
|
|
canvasColor: Constants.canvasColor,
|
|
appBarTheme: const AppBarTheme(
|
|
centerTitle: true,
|
|
backgroundColor: Constants.appBarBackgroundColor,
|
|
scrolledUnderElevation: Constants.scrolledUnderElevation,
|
|
elevation: Constants.appBarElevation,
|
|
),
|
|
snackBarTheme: const SnackBarThemeData(
|
|
backgroundColor: Constants.surface,
|
|
contentTextStyle: TextStyle(
|
|
color: Constants.onSurface,
|
|
),
|
|
),
|
|
dialogTheme: const DialogTheme(
|
|
backgroundColor: Constants.background,
|
|
surfaceTintColor: Constants.background,
|
|
contentTextStyle: TextStyle(
|
|
color: Constants.onBackground,
|
|
),
|
|
),
|
|
popupMenuTheme: const PopupMenuThemeData(
|
|
color: Constants.background,
|
|
surfaceTintColor: Constants.background,
|
|
textStyle: TextStyle(
|
|
color: Constants.onBackground,
|
|
),
|
|
),
|
|
drawerTheme: const DrawerThemeData(
|
|
backgroundColor: Constants.background,
|
|
surfaceTintColor: Constants.background,
|
|
),
|
|
bottomSheetTheme: const BottomSheetThemeData(
|
|
backgroundColor: Constants.background,
|
|
surfaceTintColor: Constants.background,
|
|
),
|
|
pageTransitionsTheme: const PageTransitionsTheme(
|
|
builders: {
|
|
TargetPlatform.android: CupertinoPageTransitionsBuilder(),
|
|
TargetPlatform.iOS: CupertinoPageTransitionsBuilder(),
|
|
TargetPlatform.linux: CupertinoPageTransitionsBuilder(),
|
|
TargetPlatform.macOS: CupertinoPageTransitionsBuilder(),
|
|
TargetPlatform.windows: CupertinoPageTransitionsBuilder(),
|
|
},
|
|
),
|
|
),
|
|
scrollBehavior: FeedDeckScrollBehavior(),
|
|
onGenerateInitialRoutes: (initialRoute) =>
|
|
[onGenerateRoute(RouteSettings(name: initialRoute))],
|
|
onGenerateRoute: (RouteSettings settings) =>
|
|
onGenerateRoute(settings),
|
|
),
|
|
),
|
|
);
|
|
}
|
|
}
|