diff --git a/lib/controllers/miniPayerController.dart b/lib/controllers/miniPayerController.dart index 8b1bbfb2..2de3ed5f 100644 --- a/lib/controllers/miniPayerController.dart +++ b/lib/controllers/miniPayerController.dart @@ -14,6 +14,7 @@ import 'package:invidious/utils.dart'; import 'package:logging/logging.dart'; import 'package:back_button_interceptor/back_button_interceptor.dart'; +import '../main.dart'; import '../models/baseVideo.dart'; import '../models/video.dart'; import '../views/video.dart'; @@ -53,7 +54,7 @@ class MiniPlayerController extends GetxController { @override onReady() { super.onReady(); - BackButtonInterceptor.add(handleBackButton, name: 'miniPlayer'); + BackButtonInterceptor.add(handleBackButton, name: 'miniPlayer', zIndex: 2); // show(); } @@ -67,7 +68,8 @@ class MiniPlayerController extends GetxController { if (isFullScreen) { isFullScreen = false; update(); - return false; + globalNavigator.currentState?.pop(); + return true; } else if (!isMini) { // we block the backbutton behavior and we make the player small showMiniPlayer(); @@ -214,7 +216,7 @@ class MiniPlayerController extends GetxController { } playVideo(List videos, {bool? goBack}) { - if (goBack ?? false) Get.back(); + if (goBack ?? false) navigatorKey.currentState?.pop(); log.info('Playing ${videos.length} videos'); if (videos.isNotEmpty) { this.videos = List.from(videos, growable: true); @@ -303,15 +305,6 @@ class MiniPlayerController extends GetxController { return videos.indexWhere((element) => element.videoId == video.videoId) >= 0; } - void handleOverflowOpening(bool opened) { - log.info('overflow opened $opened'); - if (!isFullScreen) { - isShowingOverflow = opened; - } - - update(); - } - void handleVideoEvent(BetterPlayerEvent event) { switch (event.betterPlayerEventType) { case BetterPlayerEventType.progress: @@ -340,12 +333,7 @@ class MiniPlayerController extends GetxController { isFullScreen = false; update(); break; - case BetterPlayerEventType.overflowOpened: - case BetterPlayerEventType.overflowClosed: - handleOverflowOpening(event.betterPlayerEventType == BetterPlayerEventType.overflowOpened); - break; default: - handleOverflowOpening(false); break; } } diff --git a/lib/controllers/miniPlayerAwareController.dart b/lib/controllers/miniPlayerAwareController.dart index f5ffe0df..7462e761 100644 --- a/lib/controllers/miniPlayerAwareController.dart +++ b/lib/controllers/miniPlayerAwareController.dart @@ -1,12 +1,15 @@ import 'package:get/get.dart'; import 'package:invidious/controllers/miniPayerController.dart'; import 'package:invidious/utils.dart'; +import 'package:logging/logging.dart'; class MiniPlayerAwareController extends GetxController { + Logger log = Logger('MiniPlayerAwareController'); static MiniPlayerAwareController? to() => safeGet(); bool applyPadding = false; setPadding(bool apply) { + log.info('setting mini player padding $applyPadding'); applyPadding = apply; update(); } diff --git a/lib/controllers/playlistController.dart b/lib/controllers/playlistController.dart index f12ddd42..60205594 100644 --- a/lib/controllers/playlistController.dart +++ b/lib/controllers/playlistController.dart @@ -1,14 +1,11 @@ -import 'package:better_player/better_player.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:invidious/controllers/miniPayerController.dart'; import 'package:invidious/controllers/playlistListController.dart'; -import 'package:invidious/views/miniPlayer.dart'; import 'package:logging/logging.dart'; import '../globals.dart'; import '../models/playlist.dart'; -import '../models/video.dart'; import '../models/videoInList.dart'; class PlaylistController extends GetxController { @@ -33,14 +30,14 @@ class PlaylistController extends GetxController { Future removeVideoFromPlayList(VideoInList v) async { await service.deleteUserPlaylistVideo(playlist.playlistId, v.indexId ?? ''); PlaylistListController.to(tag: PlaylistListController.getTag(userPlayListTag))?.refreshPlaylists(); - + playlist.videos.remove(v); update(); return false; } - play(){ - MiniPlayerController.to()?.playVideo(playlist.videos, goBack: false); + play() { + MiniPlayerController.to()?.playVideo(playlist.videos, goBack: false); } getAllVideos() async { diff --git a/lib/controllers/serverListSettingsController.dart b/lib/controllers/serverListSettingsController.dart index 1bae3917..87b9ef54 100644 --- a/lib/controllers/serverListSettingsController.dart +++ b/lib/controllers/serverListSettingsController.dart @@ -118,8 +118,10 @@ class ServerListSettingsController extends GetxController { publicServersError = PublicServerErrors.none; update(); } catch (err) { + err.printError(); publicServersError = PublicServerErrors.couldNotGetList; update(); + rethrow; } } diff --git a/lib/globals.dart b/lib/globals.dart index 952e2314..f0ffaade 100644 --- a/lib/globals.dart +++ b/lib/globals.dart @@ -11,7 +11,7 @@ const BROADCAST_SERVER_CHANGED = 'server-changed'; const BROADCAST_STOP_PLAYING = 'stop-playing'; const BROADCAST_STOP_MINI_PLAYER = 'stop-mini-player'; const BROADCAST_MOVE_MINI_PLAYER = 'move-mini-player'; - +const NAVIGATOR_KEY =1; const YOUTUBE_HOSTS = ['youtube.com', 'www.youtube.com', 'm.youtube.com', 'youtu.be']; const animationDuration = Duration(milliseconds: 250); diff --git a/lib/main.dart b/lib/main.dart index 562b4e6e..2e3ed749 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,13 +1,13 @@ import 'dart:async'; import 'package:after_layout/after_layout.dart'; +import 'package:back_button_interceptor/back_button_interceptor.dart'; import 'package:dynamic_color/dynamic_color.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:get/get.dart'; import 'package:invidious/controllers/homeController.dart'; -import 'package:invidious/controllers/miniPayerController.dart'; import 'package:invidious/globals.dart'; import 'package:invidious/views/components/miniPlayerAware.dart'; import 'package:invidious/views/miniPlayer.dart'; @@ -27,6 +27,7 @@ const brandColor = Color(0xFF4f0096); final scaffoldKey = GlobalKey(); final GlobalKey navigatorKey = GlobalKey(); +final GlobalKey globalNavigator = GlobalKey(); final RouteObserver routeObserver = MyRouteObserver(); Future main() async { @@ -35,7 +36,7 @@ Future main() async { debugPrint('[${record.level.name}] [${record.loggerName}] ${record.message}'); }); - WidgetsBinding widgetsBinding = WidgetsFlutterBinding.ensureInitialized(); + WidgetsFlutterBinding.ensureInitialized(); db = await DbClient.create(); runApp(const MyApp()); @@ -89,15 +90,29 @@ class MyApp extends StatelessWidget { localizationsDelegates: AppLocalizations.localizationsDelegates, supportedLocales: AppLocalizations.supportedLocales, scaffoldMessengerKey: scaffoldKey, + navigatorKey: globalNavigator, title: 'Clipious', - navigatorObservers: [routeObserver], - navigatorKey: navigatorKey, theme: ThemeData( useMaterial3: true, colorScheme: lightColorScheme, ), darkTheme: ThemeData(useMaterial3: true, colorScheme: darkColorScheme), - home: showWizard ? const WelcomeWizard() : const Home()); + home: Stack( + children: [ + MiniPlayerAware( + child: Navigator( + observers: [MyRouteObserver()], + key: navigatorKey, + initialRoute: '/', + onGenerateRoute: (settings) { + if (settings.name == '/') { + return GetPageRoute(page: () => showWizard ? const WelcomeWizard() : const Home()); + } + }), + ), + const MiniPlayer() + ], + )); }); } } @@ -111,7 +126,26 @@ class Home extends StatefulWidget { class _HomeState extends State with AfterLayoutMixin { openSettings(BuildContext context) { - Navigator.push(context, MaterialPageRoute(settings: ROUTE_SETTINGS, builder: (context) => const Settings())); + navigatorKey.currentState?.push(MaterialPageRoute(settings: ROUTE_SETTINGS, builder: (context) => const Settings())); + } + + @override + void initState() { + super.initState(); + BackButtonInterceptor.add((stopDefaultButtonEvent, RouteInfo routeInfo) { + if (routeInfo.currentRoute(context)?.settings.name != null) { + navigatorKey.currentState?.pop(); + return true; + } else { + return false; + } + }, name: 'mainNavigator', zIndex: 0, ifNotYetIntercepted: true); + } + + @override + void dispose() { + BackButtonInterceptor.removeByName('mainNavigator'); + super.dispose(); } // This widget is the root of your application. @@ -133,77 +167,70 @@ class _HomeState extends State with AfterLayoutMixin { navigationWidgets.add(NavigationDestination(icon: const Icon(Icons.playlist_play), label: navigationLabels[3])); } - return MiniPlayerAware( - child: Scaffold( + return Scaffold( + backgroundColor: colorScheme.background, + bottomNavigationBar: NavigationBar( + labelBehavior: NavigationDestinationLabelBehavior.onlyShowSelected, + elevation: 0, + onDestinationSelected: _.selectIndex, + selectedIndex: _.selectedIndex, + destinations: navigationWidgets, + ), + floatingActionButton: _.selectedIndex == 3 ? AddPlayListButton() : null, + appBar: AppBar( + systemOverlayStyle: SystemUiOverlayStyle( + systemNavigationBarColor: colorScheme.background, + systemNavigationBarIconBrightness: colorScheme.brightness == Brightness.dark ? Brightness.light : Brightness.dark, + statusBarColor: colorScheme.background, + statusBarIconBrightness: colorScheme.brightness == Brightness.dark ? Brightness.light : Brightness.dark), + title: Text(navigationLabels[_.selectedIndex]), + scrolledUnderElevation: 0, + // backgroundColor: Colors.pink, backgroundColor: colorScheme.background, - bottomNavigationBar: NavigationBar( - labelBehavior: NavigationDestinationLabelBehavior.onlyShowSelected, - elevation: 0, - onDestinationSelected: _.selectIndex, - selectedIndex: _.selectedIndex, - destinations: navigationWidgets, - ), - floatingActionButton: _.selectedIndex == 3 ? AddPlayListButton() : null, - appBar: AppBar( - systemOverlayStyle: SystemUiOverlayStyle( - systemNavigationBarColor: colorScheme.background, - systemNavigationBarIconBrightness: colorScheme.brightness == Brightness.dark ? Brightness.light : Brightness.dark, - statusBarColor: colorScheme.background, - statusBarIconBrightness: colorScheme.brightness == Brightness.dark ? Brightness.light : Brightness.dark), - title: Text(navigationLabels[_.selectedIndex]), - scrolledUnderElevation: 0, - // backgroundColor: Colors.pink, - backgroundColor: colorScheme.background, - actions: [ - IconButton( - onPressed: () { - showSearch(context: context, delegate: MySearchDelegate()); + actions: [ + IconButton( + onPressed: () { + showSearch(context: context, delegate: MySearchDelegate()); + }, + icon: const Icon(Icons.search), + ), + IconButton( + onPressed: () => openSettings(context), + icon: const Icon(Icons.settings), + ), + ], + ), + body: SafeArea( + bottom: false, + child: Stack(children: [ + AnimatedSwitcher( + switchInCurve: Curves.easeInOutQuad, + switchOutCurve: Curves.easeInOutQuad, + transitionBuilder: (Widget child, Animation animation) { + return FadeTransition(opacity: animation, child: child); }, - icon: const Icon(Icons.search), - ), - IconButton( - onPressed: () => openSettings(context), - icon: const Icon(Icons.settings), - color: colorScheme.secondary, - ), - ], - ), - body: SafeArea( - bottom: false, - child: Stack(children: [ - AnimatedSwitcher( - switchInCurve: Curves.easeInOutQuad, - switchOutCurve: Curves.easeInOutQuad, - transitionBuilder: (Widget child, Animation animation) { - return FadeTransition(opacity: animation, child: child); - }, - duration: animationDuration, - child: [ - const Popular( - key: ValueKey(0), - ), - const Trending( - key: ValueKey(1), - ), - const Subscriptions( - key: ValueKey(2), - ), - const Playlists( - key: ValueKey(3), - canDeleteVideos: true, - ) - ][_.selectedIndex], - ) - ]))), - ); + duration: animationDuration, + child: [ + const Popular( + key: ValueKey(0), + ), + const Trending( + key: ValueKey(1), + ), + const Subscriptions( + key: ValueKey(2), + ), + const Playlists( + key: ValueKey(3), + canDeleteVideos: true, + ) + ][_.selectedIndex], + ) + ]))); }, ); } @override - FutureOr afterFirstLayout(BuildContext context) { - Overlay.of(context).insert(OverlayEntry( - builder: (context) => MiniPlayer(), - )); - } + FutureOr afterFirstLayout(BuildContext context) {} } diff --git a/lib/models/invidiousServerStats.dart b/lib/models/invidiousServerStats.dart index 05eff57f..6c3c366d 100644 --- a/lib/models/invidiousServerStats.dart +++ b/lib/models/invidiousServerStats.dart @@ -6,7 +6,7 @@ part 'invidiousServerStats.g.dart'; @JsonSerializable() class InvidiousServerStats { InvidiousServerSoftware software; - bool openRegistrations; + bool? openRegistrations; InvidiousServerStats(this.software, this.openRegistrations); diff --git a/lib/models/invidiousServerStats.g.dart b/lib/models/invidiousServerStats.g.dart index 6cd8ade9..871a6315 100644 --- a/lib/models/invidiousServerStats.g.dart +++ b/lib/models/invidiousServerStats.g.dart @@ -11,7 +11,7 @@ InvidiousServerStats _$InvidiousServerStatsFromJson( InvidiousServerStats( InvidiousServerSoftware.fromJson( json['software'] as Map), - json['openRegistrations'] as bool, + json['openRegistrations'] as bool?, ); Map _$InvidiousServerStatsToJson( diff --git a/lib/utils.dart b/lib/utils.dart index f45bf952..c4b821f0 100644 --- a/lib/utils.dart +++ b/lib/utils.dart @@ -70,30 +70,28 @@ void showSharingSheet(BuildContext context, ShareLinks links) { showModalBottomSheet( context: context, builder: (BuildContext context) { - return MiniPlayerAware( - child: Container( - height: 100, - child: Center( - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - mainAxisSize: MainAxisSize.min, - children: [ - FilledButton.tonal( - child: Text(locals.shareInvidiousLink), - onPressed: () { - Share.share(links.getInvidiousLink(db.getCurrentlySelectedServer())); - Navigator.of(context).pop(); - }, - ), - FilledButton.tonal( - child: Text(locals.shareYoutubeLink), - onPressed: () { - Share.share(links.getYoutubeLink()); - Navigator.of(context).pop(); - }, - ), - ], - ), + return Container( + height: 100, + child: Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + mainAxisSize: MainAxisSize.min, + children: [ + FilledButton.tonal( + child: Text(locals.shareInvidiousLink), + onPressed: () { + Share.share(links.getInvidiousLink(db.getCurrentlySelectedServer())); + Navigator.of(context).pop(); + }, + ), + FilledButton.tonal( + child: Text(locals.shareYoutubeLink), + onPressed: () { + Share.share(links.getYoutubeLink()); + Navigator.of(context).pop(); + }, + ), + ], ), ), ); @@ -160,6 +158,7 @@ T? safeGet({String? tag}) { try { return Get.find(tag: tag); } catch (err) { + err.printError(); log.info('could not find controller of class ${T.toString()}'); return null; } diff --git a/lib/views/channel.dart b/lib/views/channel.dart index d861357c..a1d5ffd0 100644 --- a/lib/views/channel.dart +++ b/lib/views/channel.dart @@ -78,66 +78,64 @@ class ChannelViewState extends State with TickerProviderStateMixin return GetBuilder( global: false, init: ChannelController(widget.channelId, colorScheme.background, this), - builder: (_) => MiniPlayerAware( - child: Scaffold( - extendBodyBehindAppBar: false, - appBar: buildAppBar(context, _), - backgroundColor: colorScheme.background, - bottomNavigationBar: _.loading - ? null - : NavigationBar( - labelBehavior: NavigationDestinationLabelBehavior.onlyShowSelected, - elevation: 0, - onDestinationSelected: _.selectIndex, - selectedIndex: _.selectedIndex, - destinations: [ - NavigationDestination(icon: const Icon(Icons.info), label: locals.info), - NavigationDestination(icon: const Icon(Icons.play_arrow), label: locals.videos), - NavigationDestination(icon: const Icon(Icons.stream), label: locals.streams), - NavigationDestination(icon: const Icon(Icons.playlist_play), label: locals.playlists) - ], - ), - body: SafeArea( - top: false, - bottom: false, - child: NotificationListener( - onNotification: _.onBodyScroll, - child: AnimatedSwitcher( - duration: animationDuration, - child: _.loading - ? Container(alignment: Alignment.center, child: const CircularProgressIndicator()) - : Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Padding( - padding: const EdgeInsets.all(8.0), - child: Row( - children: [ - SubscribeButton(channelId: _.channel!.authorId, subCount: compactCurrency.format(_.channel!.subCount)), - ], - ), + builder: (_) => Scaffold( + extendBodyBehindAppBar: false, + appBar: buildAppBar(context, _), + backgroundColor: colorScheme.background, + bottomNavigationBar: _.loading + ? null + : NavigationBar( + labelBehavior: NavigationDestinationLabelBehavior.onlyShowSelected, + elevation: 0, + onDestinationSelected: _.selectIndex, + selectedIndex: _.selectedIndex, + destinations: [ + NavigationDestination(icon: const Icon(Icons.info), label: locals.info), + NavigationDestination(icon: const Icon(Icons.play_arrow), label: locals.videos), + NavigationDestination(icon: const Icon(Icons.stream), label: locals.streams), + NavigationDestination(icon: const Icon(Icons.playlist_play), label: locals.playlists) + ], + ), + body: SafeArea( + top: false, + bottom: false, + child: NotificationListener( + onNotification: _.onBodyScroll, + child: AnimatedSwitcher( + duration: animationDuration, + child: _.loading + ? Container(alignment: Alignment.center, child: const CircularProgressIndicator()) + : Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: const EdgeInsets.all(8.0), + child: Row( + children: [ + SubscribeButton(channelId: _.channel!.authorId, subCount: compactCurrency.format(_.channel!.subCount)), + ], ), - Expanded( - child: [ - ChannelInfo(key: const ValueKey('info'), channel: _.channel!), - ChannelVideosView( - key: const ValueKey('videos'), - channel: _.channel!, - getVideos: service.getChannelVideos, - ), - ChannelVideosView( - key: const ValueKey('streams'), - channel: _.channel!, - getVideos: service.getChannelStreams, - ), - ChannelPlayListsView(key: const ValueKey('playlists'), channelId: _.channel!.authorId, canDeleteVideos: false) - ][_.selectedIndex], - ) - ], - ), - ), - )), - ), + ), + Expanded( + child: [ + ChannelInfo(key: const ValueKey('info'), channel: _.channel!), + ChannelVideosView( + key: const ValueKey('videos'), + channel: _.channel!, + getVideos: service.getChannelVideos, + ), + ChannelVideosView( + key: const ValueKey('streams'), + channel: _.channel!, + getVideos: service.getChannelStreams, + ), + ChannelPlayListsView(key: const ValueKey('playlists'), channelId: _.channel!.authorId, canDeleteVideos: false) + ][_.selectedIndex], + ) + ], + ), + ), + )), ), ); } diff --git a/lib/views/components/videoAddToPlaylistButton.dart b/lib/views/components/videoAddToPlaylistButton.dart index 0bfebeb6..698981ab 100644 --- a/lib/views/components/videoAddToPlaylistButton.dart +++ b/lib/views/components/videoAddToPlaylistButton.dart @@ -11,7 +11,6 @@ class VideoAddToPlaylistButton extends StatelessWidget { @override Widget build(BuildContext context) { - ColorScheme colors = Theme.of(context).colorScheme; return GetBuilder( tag: AddToPlaylistButtonController.tags(videoId ?? ''), init: AddToPlaylistButtonController(videoId: videoId), @@ -24,7 +23,6 @@ class VideoAddToPlaylistButton extends StatelessWidget { onPressed: () => AddToPlaylist.showAddToPlaylistDialog(context, _.videoId!), icon: Icon( Icons.add, - color: colors.secondary, ), ), _.playListCount > 0 @@ -33,7 +31,7 @@ class VideoAddToPlaylistButton extends StatelessWidget { right: 10, child: Text( _.playListCount.toString(), - style: TextStyle(color: colors.secondary, fontSize: 8), + style: const TextStyle(fontSize: 8), ), ) : const SizedBox.shrink() diff --git a/lib/views/components/videoLikeButton.dart b/lib/views/components/videoLikeButton.dart index bfb0d73e..d9a56209 100644 --- a/lib/views/components/videoLikeButton.dart +++ b/lib/views/components/videoLikeButton.dart @@ -11,7 +11,6 @@ class VideoLikeButton extends StatelessWidget { @override Widget build(BuildContext context) { - ColorScheme colors = Theme.of(context).colorScheme; return GetBuilder( init: VideoLikeButtonController(videoId: videoId), tag: VideoLikeButtonController.tags(videoId ?? ''), @@ -22,7 +21,6 @@ class VideoLikeButton extends StatelessWidget { iconSize: size, onPressed: _.toggleLike, icon: _.isVideoLiked ? const Icon(Icons.favorite) : const Icon(Icons.favorite_border), - color: colors.secondary, ), ), ); diff --git a/lib/views/miniPlayer.dart b/lib/views/miniPlayer.dart index 21338b2d..706addab 100644 --- a/lib/views/miniPlayer.dart +++ b/lib/views/miniPlayer.dart @@ -45,7 +45,7 @@ class MiniPlayer extends StatelessWidget { return AnimatedPositioned( left: 0, - top: _.isFullScreen || _.isShowingOverflow ? 3000 : _.top, + top: _.top, bottom: _.getBottom, right: 0, duration: _.isDragging ? Duration.zero : animationDuration, diff --git a/lib/views/playlistView.dart b/lib/views/playlistView.dart index 3496d04e..35489b6e 100644 --- a/lib/views/playlistView.dart +++ b/lib/views/playlistView.dart @@ -2,6 +2,7 @@ import 'package:fbroadcast/fbroadcast.dart'; import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:get/get.dart'; +import 'package:invidious/main.dart'; import 'package:invidious/models/errors/invidiousServiceError.dart'; import 'package:invidious/models/imageObject.dart'; import 'package:invidious/models/video.dart'; @@ -41,35 +42,33 @@ class PlaylistView extends StatelessWidget { context: context, builder: (BuildContext context) { var locals = AppLocalizations.of(context)!; - return MiniPlayerAware( - child: SizedBox( - height: 100, - child: Center( - child: Row( - mainAxisAlignment: MainAxisAlignment.center, - mainAxisSize: MainAxisSize.min, - children: [ - Padding( - padding: const EdgeInsets.all(8.0), - child: Column( - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - IconButton( - onPressed: () async { - removeVideoFromPlayList(context, controller, v); - Navigator.pop(context); - }, - icon: const Icon(Icons.delete), - ), - Text( - locals.removeFromPlayList, - style: const TextStyle(fontSize: 10), - ) - ], - ), + return SizedBox( + height: 100, + child: Center( + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + mainAxisSize: MainAxisSize.min, + children: [ + Padding( + padding: const EdgeInsets.all(8.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + IconButton( + onPressed: () async { + removeVideoFromPlayList(context, controller, v); + Navigator.pop(context); + }, + icon: const Icon(Icons.delete), + ), + Text( + locals.removeFromPlayList, + style: const TextStyle(fontSize: 10), + ) + ], ), - ], - ), + ), + ], ), ), ); @@ -77,8 +76,7 @@ class PlaylistView extends StatelessWidget { } openVideo(BuildContext context, String videoId) { - Navigator.push( - context, + navigatorKey.currentState?.push( MaterialPageRoute( settings: ROUTE_VIDEO, builder: (context) => VideoView( @@ -142,137 +140,135 @@ class PlaylistView extends StatelessWidget { global: false, init: PlaylistController(playlist: playlist, playlistItemHeight: 100), builder: (_) { - return MiniPlayerAware( - child: Scaffold( - appBar: AppBar( - title: Text( - _.playlist.title, - ), - scrolledUnderElevation: 0, - actions: [ - canDeleteVideos - ? InkWell( - onTap: () => deletePlayList(context, _), - child: Padding( - padding: const EdgeInsets.all(8.0), - child: Icon( - Icons.delete, - color: colorScheme.secondary, - ), - ), - ) - : const SizedBox.shrink() - ], + return Scaffold( + appBar: AppBar( + title: Text( + _.playlist.title, ), - backgroundColor: colorScheme.background, - body: SafeArea( - bottom: false, - child: !_.loading && _.playlist.videos.isNotEmpty - ? Center( - child: Container( - constraints: BoxConstraints(maxWidth: tabletMaxVideoWidth), - child: Column( - children: [ - AnimatedSwitcher( - duration: animationDuration, - child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 8.0), - child: Column(crossAxisAlignment: CrossAxisAlignment.start, children: [ - AspectRatio( - aspectRatio: 16 / 9, - child: Stack( - alignment: Alignment.center, - children: [ - ...buildThumbnails(context, _), - PlayButton( - onPressed: _.play, - ), - Positioned( - right: 5, - bottom: 3, - child: AddToQueueButton( - videos: _.playlist.videos, - )) - ], - )) - ]))), - Expanded( - child: ListView( - controller: _.scrollController, - children: _.playlist.videos - .map((v) => Container( - width: double.infinity, - height: _.playlistItemHeight, - alignment: Alignment.center, + scrolledUnderElevation: 0, + actions: [ + canDeleteVideos + ? InkWell( + onTap: () => deletePlayList(context, _), + child: Padding( + padding: const EdgeInsets.all(8.0), + child: Icon( + Icons.delete, + color: colorScheme.secondary, + ), + ), + ) + : const SizedBox.shrink() + ], + ), + backgroundColor: colorScheme.background, + body: SafeArea( + bottom: false, + child: !_.loading && _.playlist.videos.isNotEmpty + ? Center( + child: Container( + constraints: BoxConstraints(maxWidth: tabletMaxVideoWidth), + child: Column( + children: [ + AnimatedSwitcher( + duration: animationDuration, + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 8.0), + child: Column(crossAxisAlignment: CrossAxisAlignment.start, children: [ + AspectRatio( + aspectRatio: 16 / 9, child: Stack( + alignment: Alignment.center, children: [ - Padding( - padding: const EdgeInsets.all(8.0), - child: InkWell( - onTap: canDeleteVideos ? () => showPlayListVideoDialog(context, _, v) : null, - child: Row( - children: [ - Padding( - padding: const EdgeInsets.all(4.0), - child: SizedBox( - width: 100, - child: VideoThumbnailView( - cacheKey: 'v-worst/${v.videoId}', - videoId: v.videoId, - thumbnailUrl: ImageObject.getWorstThumbnail(v.videoThumbnails)?.url ?? '', - ), - ), - ), - Expanded( - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - v.title, - style: TextStyle(color: colorScheme.primary), - ), - Text( - v.author ?? '', - ) - ], + ...buildThumbnails(context, _), + PlayButton( + onPressed: _.play, + ), + Positioned( + right: 5, + bottom: 3, + child: AddToQueueButton( + videos: _.playlist.videos, + )) + ], + )) + ]))), + Expanded( + child: ListView( + controller: _.scrollController, + children: _.playlist.videos + .map((v) => Container( + width: double.infinity, + height: _.playlistItemHeight, + alignment: Alignment.center, + child: Stack( + children: [ + Padding( + padding: const EdgeInsets.all(8.0), + child: InkWell( + onTap: canDeleteVideos ? () => showPlayListVideoDialog(context, _, v) : null, + child: Row( + children: [ + Padding( + padding: const EdgeInsets.all(4.0), + child: SizedBox( + width: 100, + child: VideoThumbnailView( + cacheKey: 'v-worst/${v.videoId}', + videoId: v.videoId, + thumbnailUrl: ImageObject.getWorstThumbnail(v.videoThumbnails)?.url ?? '', ), ), - InkWell( - onTap: () => openVideo(context, v.videoId), - child: Padding( - padding: const EdgeInsets.all(8.0), - child: Icon( - Icons.exit_to_app, - color: colorScheme.primary, + ), + Expanded( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + v.title, + style: TextStyle(color: colorScheme.primary), ), + Text( + v.author ?? '', + ) + ], + ), + ), + InkWell( + onTap: () => openVideo(context, v.videoId), + child: Padding( + padding: const EdgeInsets.all(8.0), + child: Icon( + Icons.exit_to_app, + color: colorScheme.primary, ), - ) - ], - ), + ), + ) + ], ), - ) - ], - ), - )) - .toList(), - )) - ], - ), + ), + ) + ], + ), + )) + .toList(), + )) + ], ), - ) - : _.loading - ? Center( - child: TweenAnimationBuilder( - tween: Tween(begin: 0, end: _.loadingProgress), - duration: animationDuration, - curve: Curves.easeInOutQuad, - builder: (context, value, child) => CircularProgressIndicator( - value: value > 0 ? value : null, - ), - )) - : Container(alignment: Alignment.center, child: Text(locals.noVideoInPlayList)))), - ); + ), + ) + : _.loading + ? Center( + child: TweenAnimationBuilder( + tween: Tween(begin: 0, end: _.loadingProgress), + duration: animationDuration, + curve: Curves.easeInOutQuad, + builder: (context, value, child) => CircularProgressIndicator( + value: value > 0 ? value : null, + ), + )) + : Container(alignment: Alignment.center, child: Text(locals.noVideoInPlayList)))); }, ); } diff --git a/lib/views/playlists/playlist.dart b/lib/views/playlists/playlist.dart index 369174c3..f91b78c2 100644 --- a/lib/views/playlists/playlist.dart +++ b/lib/views/playlists/playlist.dart @@ -6,6 +6,7 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:get/get.dart'; import 'package:invidious/controllers/playlistItemController.dart'; import 'package:invidious/globals.dart'; +import 'package:invidious/main.dart'; import 'package:invidious/models/imageObject.dart'; import 'package:invidious/models/playlist.dart'; import 'package:invidious/models/videoInList.dart'; @@ -20,8 +21,7 @@ class PlaylistItem extends StatelessWidget { const PlaylistItem({super.key, required this.playlist, required this.canDeleteVideos}); openPlayList(BuildContext context) { - Navigator.push( - context, + navigatorKey.currentState?.push( MaterialPageRoute( settings: ROUTE_PLAYLIST, builder: (context) => PlaylistView( diff --git a/lib/views/search.dart b/lib/views/search.dart index e3d5be68..bc3cbe1f 100644 --- a/lib/views/search.dart +++ b/lib/views/search.dart @@ -2,6 +2,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:get/get.dart'; import 'package:invidious/controllers/searchController.dart'; +import 'package:invidious/globals.dart'; import 'package:invidious/models/searchResult.dart'; import 'package:invidious/utils.dart'; import 'package:invidious/views/channel.dart'; @@ -9,6 +10,7 @@ import 'package:invidious/views/components/miniPlayerAware.dart'; import 'package:invidious/views/playlistList.dart'; import '../controllers/playlistListController.dart'; +import '../main.dart'; import '../models/paginatedList.dart'; import 'videoList.dart'; @@ -26,88 +28,86 @@ class SearchState extends State with SingleTickerProviderStateMixin { Widget build(BuildContext context) { var colorScheme = Theme.of(context).colorScheme; var locals = AppLocalizations.of(context)!; - return MiniPlayerAware( - child: GetBuilder( - init: SearchController(this), - global: false, - builder: (_) => Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Material( - color: colorScheme.brightness == Brightness.dark ? Colors.grey[900] : Colors.white, - child: TabBar(controller: _.controller, tabs: [ - Tab( - text: locals.videos, - icon: const Icon(Icons.play_arrow), - ), - Tab( - text: locals.channels, - icon: const Icon(Icons.people), - ), - Tab( - text: locals.playlists, - icon: const Icon(Icons.playlist_play), - ) - ]), - ), - Expanded( - child: FractionallySizedBox( - widthFactor: 1, - child: TabBarView( - viewportFraction: 1, - controller: _.controller, - children: [ - widget.results.videos.isNotEmpty - ? VideoList( - paginatedVideoList: FixedItemList(widget.results.videos), - ) - : Center(child: Text(locals.nVideos(0))), - widget.results.channels.isNotEmpty - ? ListView( - children: widget.results.channels - .map((e) => InkWell( - onTap: () { - Navigator.of(context).push(MaterialPageRoute( - builder: (context) => ChannelView(channelId: e.authorId), - )); - }, - child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 8.0, vertical: 20), - child: Row( - children: [ - Expanded( - child: Text( - e.author, - style: TextStyle(color: colorScheme.primary), - )), - const Padding( - padding: EdgeInsets.only(right: 8.0), - child: Icon( - Icons.people, - size: 15, - ), + return GetBuilder( + init: SearchController(this), + global: false, + builder: (_) => Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Material( + color: colorScheme.brightness == Brightness.dark ? Colors.grey[900] : Colors.white, + child: TabBar(controller: _.controller, tabs: [ + Tab( + text: locals.videos, + icon: const Icon(Icons.play_arrow), + ), + Tab( + text: locals.channels, + icon: const Icon(Icons.people), + ), + Tab( + text: locals.playlists, + icon: const Icon(Icons.playlist_play), + ) + ]), + ), + Expanded( + child: FractionallySizedBox( + widthFactor: 1, + child: TabBarView( + viewportFraction: 1, + controller: _.controller, + children: [ + widget.results.videos.isNotEmpty + ? VideoList( + paginatedVideoList: FixedItemList(widget.results.videos), + ) + : Center(child: Text(locals.nVideos(0))), + widget.results.channels.isNotEmpty + ? ListView( + children: widget.results.channels + .map((e) => InkWell( + onTap: () { + navigatorKey.currentState?.push(MaterialPageRoute( + builder: (context) => ChannelView(channelId: e.authorId), + )); + }, + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 8.0, vertical: 20), + child: Row( + children: [ + Expanded( + child: Text( + e.author, + style: TextStyle(color: colorScheme.primary), + )), + const Padding( + padding: EdgeInsets.only(right: 8.0), + child: Icon( + Icons.people, + size: 15, ), - Text(compactCurrency.format(e.subCount)), - ], - ), + ), + Text(compactCurrency.format(e.subCount)), + ], ), - )) - .toList(), - ) - : Center( - child: Text(locals.noChannels), - ), - widget.results.playlists.isNotEmpty - ? FractionallySizedBox( - child: PlaylistList(tag: searchPlayListTag, paginatedList: FixedItemList(widget.results.playlists), canDeleteVideos: false), - ) - : Center(child: Text(locals.noPlaylists)) - ], - ), + ), + )) + .toList(), + ) + : Center( + child: Text(locals.noChannels), + ), + widget.results.playlists.isNotEmpty + ? FractionallySizedBox( + child: PlaylistList(tag: searchPlayListTag, paginatedList: FixedItemList(widget.results.playlists), canDeleteVideos: false), + ) + : Center(child: Text(locals.noPlaylists)) + ], ), ), - ], - ), + ), + ], ), ); } diff --git a/lib/views/settings.dart b/lib/views/settings.dart index 66699af6..c6f691d2 100644 --- a/lib/views/settings.dart +++ b/lib/views/settings.dart @@ -3,13 +3,13 @@ import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:get/get.dart'; import 'package:invidious/myRouteObserver.dart'; -import 'package:invidious/views/components/miniPlayerAware.dart'; import 'package:invidious/views/settings/sponsorBlockSettings.dart'; import 'package:select_dialog/select_dialog.dart'; import 'package:settings_ui/settings_ui.dart'; import '../controllers/settingsController.dart'; import '../globals.dart'; +import '../main.dart'; import 'settings/manageServers.dart'; settingsTheme(ColorScheme colorScheme) => SettingsThemeData( @@ -25,11 +25,11 @@ class Settings extends StatelessWidget { const Settings({super.key}); manageServers(BuildContext context) { - Navigator.push(context, MaterialPageRoute(settings: ROUTE_SETTINGS_MANAGE_SERVERS, builder: (context) => const ManageServers())); + navigatorKey.currentState?.push(MaterialPageRoute(settings: ROUTE_SETTINGS_MANAGE_SERVERS, builder: (context) => const ManageServers())); } openSponsorBlockSettings(BuildContext context) { - Navigator.push(context, MaterialPageRoute(settings: ROUTE_SETTINGS_SPONSOR_BLOCK, builder: (context) => const SponsorBlockSettings())); + navigatorKey.currentState?.push(MaterialPageRoute(settings: ROUTE_SETTINGS_SPONSOR_BLOCK, builder: (context) => const SponsorBlockSettings())); } searchCountry(BuildContext context, SettingsController controller) { @@ -73,86 +73,84 @@ class Settings extends StatelessWidget { return GetBuilder( init: SettingsController(), - builder: (_) => MiniPlayerAware( - child: Scaffold( - extendBody: true, - bottomNavigationBar: const SizedBox.shrink(), - appBar: AppBar( - scrolledUnderElevation: 0, - title: Text(locals.settings), - ), - backgroundColor: colorScheme.background, - body: SafeArea( - child: SettingsList( - lightTheme: theme, - darkTheme: theme, - sections: [ - SettingsSection( - title: Text(locals.browsing), - tiles: [ - SettingsTile( - title: Text(locals.country), - value: Text(_.country.name), - onPressed: (context) => searchCountry(context, _), - ), - SettingsTile( - title: Text(locals.whenAppStartsShow), - value: Text(getCategories(context)[_.onOpen]), - onPressed: (context) => selectOnOpen(context, _), - ) - ], - ), - SettingsSection(title: Text(locals.servers), tiles: [ - SettingsTile.navigation( - title: Text(locals.manageServers), - description: Text(locals.currentServer(db.getCurrentlySelectedServer().url)), - onPressed: manageServers, - ), - ]), - SettingsSection(title: Text(locals.videoPlayer), tiles: [ - SettingsTile.switchTile( - initialValue: _.useDash, - onToggle: _.toggleDash, - title: Text(locals.useDash), - description: Text(locals.useDashDescription), - ), - SettingsTile.switchTile( - initialValue: _.useProxy, - onToggle: _.toggleProxy, - title: Text(locals.useProxy), - description: Text(locals.useProxyDescription), - ), - SettingsTile.navigation( - title: Text('SponsorBlock'), - description: Text(locals.sponsorBlockDescription), - onPressed: openSponsorBlockSettings, - ) - ]), - SettingsSection( - title: Text(locals.appearance), - tiles: [ - SettingsTile.switchTile( - initialValue: _.useDynamicTheme, - onToggle: _.toggleDynamicTheme, - title: Text(locals.useDynamicTheme), - description: Text(locals.useDynamicThemeDescription), - ), - ], - ), - SettingsSection(title: (Text(locals.about)), tiles: [ - SettingsTile(title: const Center(child: SizedBox(height: 150, width: 150, child: AppIconImage()))), + builder: (_) => Scaffold( + extendBody: true, + bottomNavigationBar: const SizedBox.shrink(), + appBar: AppBar( + scrolledUnderElevation: 0, + title: Text(locals.settings), + ), + backgroundColor: colorScheme.background, + body: SafeArea( + child: SettingsList( + lightTheme: theme, + darkTheme: theme, + sections: [ + SettingsSection( + title: Text(locals.browsing), + tiles: [ SettingsTile( - title: Text('${locals.name}: ${_.packageInfo.appName}'), - description: Text('${locals.package}: ${_.packageInfo.packageName}'), + title: Text(locals.country), + value: Text(_.country.name), + onPressed: (context) => searchCountry(context, _), ), SettingsTile( - title: Text('${locals.version}: ${_.packageInfo.version}'), - description: Text('${locals.build}: ${_.packageInfo.buildNumber}'), + title: Text(locals.whenAppStartsShow), + value: Text(getCategories(context)[_.onOpen]), + onPressed: (context) => selectOnOpen(context, _), ) - ]) - ], - ))), - ), + ], + ), + SettingsSection(title: Text(locals.servers), tiles: [ + SettingsTile.navigation( + title: Text(locals.manageServers), + description: Text(locals.currentServer(db.getCurrentlySelectedServer().url)), + onPressed: manageServers, + ), + ]), + SettingsSection(title: Text(locals.videoPlayer), tiles: [ + SettingsTile.switchTile( + initialValue: _.useDash, + onToggle: _.toggleDash, + title: Text(locals.useDash), + description: Text(locals.useDashDescription), + ), + SettingsTile.switchTile( + initialValue: _.useProxy, + onToggle: _.toggleProxy, + title: Text(locals.useProxy), + description: Text(locals.useProxyDescription), + ), + SettingsTile.navigation( + title: Text('SponsorBlock'), + description: Text(locals.sponsorBlockDescription), + onPressed: openSponsorBlockSettings, + ) + ]), + SettingsSection( + title: Text(locals.appearance), + tiles: [ + SettingsTile.switchTile( + initialValue: _.useDynamicTheme, + onToggle: _.toggleDynamicTheme, + title: Text(locals.useDynamicTheme), + description: Text(locals.useDynamicThemeDescription), + ), + ], + ), + SettingsSection(title: (Text(locals.about)), tiles: [ + SettingsTile(title: const Center(child: SizedBox(height: 150, width: 150, child: AppIconImage()))), + SettingsTile( + title: Text('${locals.name}: ${_.packageInfo.appName}'), + description: Text('${locals.package}: ${_.packageInfo.packageName}'), + ), + SettingsTile( + title: Text('${locals.version}: ${_.packageInfo.version}'), + description: Text('${locals.build}: ${_.packageInfo.buildNumber}'), + ) + ]) + ], + ))), ); } } diff --git a/lib/views/settings/manageServerInner.dart b/lib/views/settings/manageServerInner.dart index 78871f28..ea1bcdd6 100644 --- a/lib/views/settings/manageServerInner.dart +++ b/lib/views/settings/manageServerInner.dart @@ -2,6 +2,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:get/get.dart'; import 'package:invidious/controllers/serverListSettingsController.dart'; +import 'package:invidious/main.dart'; import 'package:invidious/myRouteObserver.dart'; import 'package:invidious/views/components/miniPlayerAware.dart'; import 'package:invidious/views/settings/manageSingleServer.dart'; @@ -20,35 +21,33 @@ class ManagerServersView extends StatelessWidget { showModalBottomSheet( context: context, builder: (BuildContext context) { - return MiniPlayerAware( - child: SizedBox( - height: 100, - child: Center( - child: Row( - mainAxisAlignment: MainAxisAlignment.center, - mainAxisSize: MainAxisSize.min, - children: [ - Padding( - padding: const EdgeInsets.all(8.0), - child: Column( - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - IconButton( - onPressed: () { - controller.upsertServer(server); - Navigator.pop(context); - }, - icon: const Icon(Icons.add), - ), - Text( - locals.addServer, - style: const TextStyle(fontSize: 10), - ) - ], - ), + return SizedBox( + height: 100, + child: Center( + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + mainAxisSize: MainAxisSize.min, + children: [ + Padding( + padding: const EdgeInsets.all(8.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + IconButton( + onPressed: () { + controller.upsertServer(server); + Navigator.pop(context); + }, + icon: const Icon(Icons.add), + ), + Text( + locals.addServer, + style: const TextStyle(fontSize: 10), + ) + ], ), - ], - ), + ), + ], ), ), ); @@ -118,8 +117,7 @@ class ManagerServersView extends StatelessWidget { } openServer(BuildContext context, Server s) { - Navigator.push( - context, + navigatorKey.currentState?.push( MaterialPageRoute( settings: ROUTE_SETTINGS_MANAGE_ONE_SERVER, builder: (context) => ManageSingleServer( diff --git a/lib/views/settings/manageServers.dart b/lib/views/settings/manageServers.dart index 1bed3062..25ac90d5 100644 --- a/lib/views/settings/manageServers.dart +++ b/lib/views/settings/manageServers.dart @@ -1,6 +1,5 @@ import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; -import 'package:invidious/views/components/miniPlayerAware.dart'; import 'package:invidious/views/settings/manageServerInner.dart'; class ManageServers extends StatefulWidget { @@ -15,14 +14,12 @@ class ManageServerState extends State { Widget build(BuildContext context) { var locals = AppLocalizations.of(context)!; ColorScheme colorScheme = Theme.of(context).colorScheme; - return MiniPlayerAware( - child: Scaffold( - appBar: AppBar( - scrolledUnderElevation: 0, - title: Text(locals.manageServers), - ), - backgroundColor: colorScheme.background, - body: const SafeArea(bottom: false, child: ManagerServersView())), - ); + return Scaffold( + appBar: AppBar( + scrolledUnderElevation: 0, + title: Text(locals.manageServers), + ), + backgroundColor: colorScheme.background, + body: const SafeArea(bottom: false, child: ManagerServersView())); } } diff --git a/lib/views/settings/manageSingleServer.dart b/lib/views/settings/manageSingleServer.dart index 7a748463..23e98dff 100644 --- a/lib/views/settings/manageSingleServer.dart +++ b/lib/views/settings/manageSingleServer.dart @@ -3,7 +3,6 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:get/get.dart'; import 'package:invidious/controllers/serverSettingsController.dart'; import 'package:invidious/utils.dart'; -import 'package:invidious/views/components/miniPlayerAware.dart'; import 'package:settings_ui/settings_ui.dart'; import '../../models/db/server.dart'; @@ -75,68 +74,66 @@ class ManageSingleServer extends StatelessWidget { builder: (controller) { Server server = controller.server; bool isLoggedIn = (server.authToken != null && server.authToken!.isNotEmpty) || (server.sidCookie != null && server.sidCookie!.isNotEmpty); - return MiniPlayerAware( - child: Scaffold( - appBar: AppBar( - scrolledUnderElevation: 0, - title: Text(server.url), - ), - backgroundColor: colorScheme.background, - body: SafeArea( - bottom: false, - child: SettingsList(lightTheme: theme, darkTheme: theme, sections: [ - SettingsSection(tiles: [ - SettingsTile.switchTile( - initialValue: server.inUse, - onToggle: controller.useServer, - title: Text(locals.useThisServer), - enabled: !server.inUse, - ) - ]), - SettingsSection(title: Text(locals.authentication), tiles: [ - SettingsTile( - leading: server.authToken?.isNotEmpty ?? false ? const Icon(Icons.check) : const Icon(Icons.token), - enabled: !isLoggedIn, - title: Text(locals.tokenLogin), - value: Text(server.authToken?.isNotEmpty ?? false ? locals.loggedIn : locals.tokenLoginDescription), - onPressed: (context) async { - await controller.logInWithToken(); - }, + return Scaffold( + appBar: AppBar( + scrolledUnderElevation: 0, + title: Text(server.url), + ), + backgroundColor: colorScheme.background, + body: SafeArea( + bottom: false, + child: SettingsList(lightTheme: theme, darkTheme: theme, sections: [ + SettingsSection(tiles: [ + SettingsTile.switchTile( + initialValue: server.inUse, + onToggle: controller.useServer, + title: Text(locals.useThisServer), + enabled: !server.inUse, + ) + ]), + SettingsSection(title: Text(locals.authentication), tiles: [ + SettingsTile( + leading: server.authToken?.isNotEmpty ?? false ? const Icon(Icons.check) : const Icon(Icons.token), + enabled: !isLoggedIn, + title: Text(locals.tokenLogin), + value: Text(server.authToken?.isNotEmpty ?? false ? locals.loggedIn : locals.tokenLoginDescription), + onPressed: (context) async { + await controller.logInWithToken(); + }, + ), + SettingsTile( + leading: server.sidCookie?.isNotEmpty ?? false ? const Icon(Icons.check) : const Icon(Icons.cookie_outlined), + enabled: !isLoggedIn, + title: Text(locals.cookieLogin), + value: Text(server.sidCookie?.isNotEmpty ?? false ? locals.loggedIn : locals.cookieLoginDescription), + onPressed: showLogInWithCookiesDialog, + ), + SettingsTile( + leading: const Icon(Icons.exit_to_app), + enabled: isLoggedIn, + title: Text(locals.logout), + onPressed: (context) => controller.logOut(), + ) + ]), + SettingsSection(title: const Text(''), tiles: [ + SettingsTile( + enabled: controller.canDelete, + onPressed: (context) { + controller.deleteServer(); + Navigator.of(context).pop(); + }, + leading: Icon( + Icons.delete, + color: controller.canDelete ? Colors.red : Colors.red.withOpacity(0.5), ), - SettingsTile( - leading: server.sidCookie?.isNotEmpty ?? false ? const Icon(Icons.check) : const Icon(Icons.cookie_outlined), - enabled: !isLoggedIn, - title: Text(locals.cookieLogin), - value: Text(server.sidCookie?.isNotEmpty ?? false ? locals.loggedIn : locals.cookieLoginDescription), - onPressed: showLogInWithCookiesDialog, + title: Text( + locals.delete, + style: TextStyle(color: controller.canDelete ? Colors.red : Colors.red.withOpacity(0.5)), ), - SettingsTile( - leading: const Icon(Icons.exit_to_app), - enabled: isLoggedIn, - title: Text(locals.logout), - onPressed: (context) => controller.logOut(), - ) - ]), - SettingsSection(title: const Text(''), tiles: [ - SettingsTile( - enabled: controller.canDelete, - onPressed: (context) { - controller.deleteServer(); - Navigator.of(context).pop(); - }, - leading: Icon( - Icons.delete, - color: controller.canDelete ? Colors.red : Colors.red.withOpacity(0.5), - ), - title: Text( - locals.delete, - style: TextStyle(color: controller.canDelete ? Colors.red : Colors.red.withOpacity(0.5)), - ), - ) - ]) - ]), - )), - ); + ) + ]) + ]), + )); }, ); } diff --git a/lib/views/settings/sponsorBlockSettings.dart b/lib/views/settings/sponsorBlockSettings.dart index 1c191f4d..37f93715 100644 --- a/lib/views/settings/sponsorBlockSettings.dart +++ b/lib/views/settings/sponsorBlockSettings.dart @@ -5,7 +5,6 @@ import 'package:invidious/controllers/sponsorBlockSettingsController.dart'; import 'package:invidious/models/sponsorSegmentTypes.dart'; import 'package:settings_ui/settings_ui.dart'; -import '../components/miniPlayerAware.dart'; import '../settings.dart'; class SponsorBlockSettings extends StatelessWidget { @@ -21,29 +20,27 @@ class SponsorBlockSettings extends StatelessWidget { init: SponsorBlockSettingsController(), global: false, builder: (_) { - return MiniPlayerAware( - child: Scaffold( - appBar: AppBar( - scrolledUnderElevation: 0, - title: const Text('SponsorBlock'), - ), - backgroundColor: colorScheme.background, - body: SafeArea( - bottom: false, - child: SettingsList(lightTheme: theme, darkTheme: theme, sections: [ - SettingsSection( - title: Text(locals.sponsorBlockSettingsQuickDescription), - tiles: SponsorSegmentType.values - .map((t) => SettingsTile.switchTile( - initialValue: _.value(t), - onToggle: (bool value) => _.setValue(t, value), - title: Text(SponsorSegmentType.getLabel(t, locals)), - description: Text(SponsorSegmentType.getDescription(t, locals)), - )) - .toList()), - ]), - )), - ); + return Scaffold( + appBar: AppBar( + scrolledUnderElevation: 0, + title: const Text('SponsorBlock'), + ), + backgroundColor: colorScheme.background, + body: SafeArea( + bottom: false, + child: SettingsList(lightTheme: theme, darkTheme: theme, sections: [ + SettingsSection( + title: Text(locals.sponsorBlockSettingsQuickDescription), + tiles: SponsorSegmentType.values + .map((t) => SettingsTile.switchTile( + initialValue: _.value(t), + onToggle: (bool value) => _.setValue(t, value), + title: Text(SponsorSegmentType.getLabel(t, locals)), + description: Text(SponsorSegmentType.getDescription(t, locals)), + )) + .toList()), + ]), + )); }, ); } diff --git a/lib/views/video.dart b/lib/views/video.dart index 66170f9a..a303303b 100644 --- a/lib/views/video.dart +++ b/lib/views/video.dart @@ -4,7 +4,6 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:get/get.dart'; import 'package:invidious/controllers/videoController.dart'; import 'package:invidious/globals.dart'; -import 'package:invidious/views/components/miniPlayerAware.dart'; import 'package:invidious/views/components/videoAddToPlaylistButton.dart'; import 'package:invidious/views/components/videoLikeButton.dart'; import 'package:invidious/views/video/innverView.dart'; @@ -43,69 +42,66 @@ class VideoView extends StatelessWidget { builder: (_) => AnimatedOpacity( duration: animationDuration, opacity: _.opacity, - child: MiniPlayerAware( - child: Scaffold( - appBar: AppBar( - actions: _.loadingVideo - ? [] - : [ - Visibility( - visible: _.video != null, - child: IconButton( - onPressed: () => showSharingSheet(context, _.video!), - icon: const Icon(Icons.share), - color: colorScheme.secondary, - ), + child: Scaffold( + appBar: AppBar( + actions: _.loadingVideo + ? [] + : [ + Visibility( + visible: _.video != null, + child: IconButton( + onPressed: () => showSharingSheet(context, _.video!), + icon: const Icon(Icons.share), ), - VideoLikeButton(videoId: _.video?.videoId), - VideoAddToPlaylistButton(videoId: _.video?.videoId), - ], - scrolledUnderElevation: 0, - ), - backgroundColor: colorScheme.background, - bottomNavigationBar: _.loadingVideo - ? null - : NavigationBar( - labelBehavior: NavigationDestinationLabelBehavior.onlyShowSelected, - elevation: 0, - onDestinationSelected: _.selectIndex, - selectedIndex: _.selectedIndex, - destinations: destinations, - ), - body: SafeArea( - bottom: false, - child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 8.0), - child: Container( - color: colorScheme.background, - width: double.infinity, - height: double.infinity, - child: AnimatedSwitcher( - duration: animationDuration, - child: _.error.isNotEmpty - ? Container( - alignment: Alignment.center, - child: Text(_.error == coulnotLoadVideos ? locals.couldntLoadVideo : _.error), - ) - : _.loadingVideo - ? const CircularProgressIndicator() - : Padding( - padding: const EdgeInsets.symmetric(horizontal: 8.0), - child: show3Navigation - ? VideoInnerView( - video: _.video!, - selectedIndex: _.selectedIndex, - playNow: playNow, - videoController: _, - ) - : VideoTabletInnerView( - video: _.video!, - playNow: playNow, - selectedIndex: _.selectedIndex, - videoController: _, - ), - )), + ), + VideoLikeButton(videoId: _.video?.videoId), + VideoAddToPlaylistButton(videoId: _.video?.videoId), + ], + scrolledUnderElevation: 0, + ), + backgroundColor: colorScheme.background, + bottomNavigationBar: _.loadingVideo + ? null + : NavigationBar( + labelBehavior: NavigationDestinationLabelBehavior.onlyShowSelected, + elevation: 0, + onDestinationSelected: _.selectIndex, + selectedIndex: _.selectedIndex, + destinations: destinations, ), + body: SafeArea( + bottom: false, + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 8.0), + child: Container( + color: colorScheme.background, + width: double.infinity, + height: double.infinity, + child: AnimatedSwitcher( + duration: animationDuration, + child: _.error.isNotEmpty + ? Container( + alignment: Alignment.center, + child: Text(_.error == coulnotLoadVideos ? locals.couldntLoadVideo : _.error), + ) + : _.loadingVideo + ? const CircularProgressIndicator() + : Padding( + padding: const EdgeInsets.symmetric(horizontal: 8.0), + child: show3Navigation + ? VideoInnerView( + video: _.video!, + selectedIndex: _.selectedIndex, + playNow: playNow, + videoController: _, + ) + : VideoTabletInnerView( + video: _.video!, + playNow: playNow, + selectedIndex: _.selectedIndex, + videoController: _, + ), + )), ), ), ), diff --git a/lib/views/video/addToPlayList.dart b/lib/views/video/addToPlayList.dart index d782a8f2..6dd6a693 100644 --- a/lib/views/video/addToPlayList.dart +++ b/lib/views/video/addToPlayList.dart @@ -51,44 +51,42 @@ class AddToPlaylist extends StatelessWidget { Widget build(BuildContext context) { var locals = AppLocalizations.of(context)!; - return MiniPlayerAware( - child: GetBuilder( - init: AddToPlaylistController(videoId), - global: false, - builder: (_) => Padding( - padding: const EdgeInsets.all(8.0), - child: Column(mainAxisSize: MainAxisSize.min, children: [ - Text(locals.selectPlaylist), - _.loading ? const CircularProgressIndicator() : const SizedBox.shrink(), - Expanded( - child: ListView( - children: _.playlists - .map((p) { - bool inPlaylist = _.videoInPlaylist(p.playlistId); - return FilledButton.tonal( - onPressed: inPlaylist ? null : () => addToPlaylist(context, _, p.playlistId), - child: Row( - children: [ - Padding( - padding: const EdgeInsets.all(8.0), - child: SizedBox(width: 20, child: inPlaylist ? const Icon(Icons.check, size: 15,) : const SizedBox.shrink()), - ), - Expanded(child: Text(p.title)), - ], - )); - }) - .toList(), - ), + return GetBuilder( + init: AddToPlaylistController(videoId), + global: false, + builder: (_) => Padding( + padding: const EdgeInsets.all(8.0), + child: Column(mainAxisSize: MainAxisSize.min, children: [ + Text(locals.selectPlaylist), + _.loading ? const CircularProgressIndicator() : const SizedBox.shrink(), + Expanded( + child: ListView( + children: _.playlists + .map((p) { + bool inPlaylist = _.videoInPlaylist(p.playlistId); + return FilledButton.tonal( + onPressed: inPlaylist ? null : () => addToPlaylist(context, _, p.playlistId), + child: Row( + children: [ + Padding( + padding: const EdgeInsets.all(8.0), + child: SizedBox(width: 20, child: inPlaylist ? const Icon(Icons.check, size: 15,) : const SizedBox.shrink()), + ), + Expanded(child: Text(p.title)), + ], + )); + }) + .toList(), ), - FilledButton.tonal( - onPressed: () => newPlaylistAndAdd(context, _), - child: Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [const Icon(Icons.add), Text(locals.createNewPlaylist)], - ), - ) - ]), - ), + ), + FilledButton.tonal( + onPressed: () => newPlaylistAndAdd(context, _), + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [const Icon(Icons.add), Text(locals.createNewPlaylist)], + ), + ) + ]), ), ); } diff --git a/lib/views/video/comment.dart b/lib/views/video/comment.dart index 7c2df9bc..a9c64361 100644 --- a/lib/views/video/comment.dart +++ b/lib/views/video/comment.dart @@ -2,11 +2,13 @@ import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:get/get.dart'; import 'package:invidious/controllers/singleCommentController.dart'; +import 'package:invidious/globals.dart'; import 'package:invidious/myRouteObserver.dart'; import 'package:invidious/views/channel.dart'; import 'package:invidious/views/components/videoThumbnail.dart'; import 'package:invidious/views/video/comments.dart'; +import '../../main.dart'; import '../../models/comment.dart'; import '../../models/imageObject.dart'; @@ -17,7 +19,7 @@ class SingleCommentView extends StatelessWidget { const SingleCommentView({super.key, required this.comment, required this.videoId}); openChannel(BuildContext context, String authorId) { - Navigator.push(context, MaterialPageRoute(settings: ROUTE_CHANNEL, builder: (context) => ChannelView(channelId: authorId))); + navigatorKey.currentState?.push(MaterialPageRoute(settings: ROUTE_CHANNEL, builder: (context) => ChannelView(channelId: authorId))); } @override diff --git a/lib/views/video/info.dart b/lib/views/video/info.dart index 583f77a4..8a42dc23 100644 --- a/lib/views/video/info.dart +++ b/lib/views/video/info.dart @@ -1,6 +1,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:flutter_linkify/flutter_linkify.dart'; +import 'package:invidious/main.dart'; import 'package:invidious/models/video.dart'; import 'package:invidious/myRouteObserver.dart'; import 'package:invidious/views/channel.dart'; @@ -18,7 +19,7 @@ class VideoInfo extends StatelessWidget { VideoInfo({super.key, required this.video}); openChannel(BuildContext context) { - Navigator.push(context, MaterialPageRoute(settings: ROUTE_CHANNEL, builder: (context) => ChannelView(channelId: video.authorId ?? ''))); + navigatorKey.currentState?.push(MaterialPageRoute(settings: ROUTE_CHANNEL, builder: (context) => ChannelView(channelId: video.authorId ?? ''))); } showSearchWindow(BuildContext context, String query) { diff --git a/lib/views/videoList/singleVideo.dart b/lib/views/videoList/singleVideo.dart index afc9774b..5fcab126 100644 --- a/lib/views/videoList/singleVideo.dart +++ b/lib/views/videoList/singleVideo.dart @@ -3,6 +3,7 @@ import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:invidious/controllers/videoInListController.dart'; import 'package:invidious/globals.dart'; +import 'package:invidious/main.dart'; import 'package:invidious/models/videoInList.dart'; import 'package:invidious/myRouteObserver.dart'; import 'package:invidious/views/components/videoThumbnail.dart'; @@ -21,7 +22,7 @@ class VideoListItem extends StatelessWidget { final log = Logger('VideoInList'); openVideo(BuildContext context) { - Navigator.push(context, MaterialPageRoute(settings: ROUTE_VIDEO, builder: (context) => VideoView(videoId: video.videoId))); + navigatorKey.currentState?.push(MaterialPageRoute(settings: ROUTE_VIDEO, builder: (context) => VideoView(videoId: video.videoId))); } @override @@ -111,7 +112,7 @@ class VideoListItem extends StatelessWidget { child: InkWell( onTap: () { log.info('Opening channel ${video.authorId}'); - Navigator.push(context, MaterialPageRoute(settings: ROUTE_CHANNEL, builder: (context) => ChannelView(channelId: video.authorId!))); + navigatorKey.currentState?.push(MaterialPageRoute(settings: ROUTE_CHANNEL, builder: (context) => ChannelView(channelId: video.authorId!))); }, child: Row( children: [ diff --git a/lib/views/videoPlayer/miniPlayerControls.dart b/lib/views/videoPlayer/miniPlayerControls.dart index 6f7b099c..bc5d7f0e 100644 --- a/lib/views/videoPlayer/miniPlayerControls.dart +++ b/lib/views/videoPlayer/miniPlayerControls.dart @@ -2,7 +2,6 @@ import 'package:flutter/material.dart'; import 'package:get/get_state_manager/get_state_manager.dart'; import 'package:invidious/controllers/miniplayerControlsController.dart'; import 'package:invidious/utils.dart'; -import 'package:invidious/views/components/videoLikeButton.dart'; import '../../controllers/miniPayerController.dart'; @@ -23,12 +22,12 @@ class MiniPlayerControls extends StatelessWidget { decoration: BoxDecoration(borderRadius: BorderRadius.circular(20), color: colors.secondaryContainer), constraints: BoxConstraints(maxWidth: tabletMaxVideoWidth, ), child: GetBuilder( - global: false, + // global: false, init: MiniPlayerControlsController(), builder: (_) => Stack( alignment: Alignment.center, children: [ - Positioned(left: 0, child: VideoLikeButton(videoId: videoId, style: buttonStyle)), + // Positioned(left: 0, child: VideoLikeButton(videoId: videoId, style: buttonStyle)), Row( mainAxisAlignment: MainAxisAlignment.center, children: [ diff --git a/lib/views/welcomeWizard.dart b/lib/views/welcomeWizard.dart index 6790fe08..d01e684c 100644 --- a/lib/views/welcomeWizard.dart +++ b/lib/views/welcomeWizard.dart @@ -42,7 +42,7 @@ class WelcomeWizard extends StatelessWidget { child: FilledButton.tonal( onPressed: _.selected != null ? () { - Navigator.of(context).pushReplacement(MaterialPageRoute( + navigatorKey.currentState?.push(MaterialPageRoute( builder: (context) => const Home(), )); }