diff --git a/lib/app/views/components/player_placeholder.dart b/lib/app/views/components/player_placeholder.dart index f3e49221..559ca869 100644 --- a/lib/app/views/components/player_placeholder.dart +++ b/lib/app/views/components/player_placeholder.dart @@ -24,7 +24,7 @@ class PlayerPlaceHolder extends StatelessWidget { padding: const EdgeInsets.symmetric(horizontal: 7), child: Container( decoration: BoxDecoration( - color: colors.secondaryContainer.withOpacity(0.5), + color: colors.secondaryContainer.withValues(alpha: 0.5), borderRadius: BorderRadius.circular(10), ), child: Center( @@ -33,7 +33,8 @@ class PlayerPlaceHolder extends StatelessWidget { opacity: showPlaceHolder ? 1 : 0, child: Icon( Icons.play_arrow_outlined, - color: colors.onSecondaryContainer.withOpacity(0.3), + color: + colors.onSecondaryContainer.withValues(alpha: 0.3), )), ), )), diff --git a/lib/app/views/tv/screens/tv_home.dart b/lib/app/views/tv/screens/tv_home.dart index 3755e4d7..9cde6534 100644 --- a/lib/app/views/tv/screens/tv_home.dart +++ b/lib/app/views/tv/screens/tv_home.dart @@ -99,7 +99,7 @@ class TvHomeScreen extends StatelessWidget { curve: Curves.easeInOutQuad, decoration: BoxDecoration( color: homeState - ? colors.secondaryContainer.withOpacity(0.5) + ? colors.secondaryContainer.withValues(alpha: 0.5) : Colors.transparent), child: Padding( padding: EdgeInsets.only( @@ -161,7 +161,7 @@ class TvHomeScreen extends StatelessWidget { }, unfocusedColor: colors .secondaryContainer - .withOpacity(0.0), + .withValues(alpha: 0.0), child: Padding( padding: const EdgeInsets.all(8), @@ -188,7 +188,7 @@ class TvHomeScreen extends StatelessWidget { homeCubit.menuItemFocusChanged, onPressed: (context) => openSettings(context), unfocusedColor: colors.secondaryContainer - .withOpacity(0.0), + .withValues(alpha: 0.0), child: Padding( padding: const EdgeInsets.all(8), child: Row( diff --git a/lib/channels/models/channel.dart b/lib/channels/models/channel.dart index 515d1c14..61e43f17 100644 --- a/lib/channels/models/channel.dart +++ b/lib/channels/models/channel.dart @@ -45,17 +45,17 @@ class Channel implements ShareLinks { Map toJson() => _$ChannelToJson(this); @override - String getInvidiousLink(Server server, int? timestamp) { - return '${server.url}/channel/$authorId'; + Uri getInvidiousLink(Server server, int? timestamp) { + return Uri.parse('${server.url}/channel/$authorId'); } @override - getRedirectLink(int? timestamp) { - return 'https://redirect.invidious.io/channel/$authorId'; + Uri getRedirectLink(int? timestamp) { + return Uri.parse('https://redirect.invidious.io/channel/$authorId'); } @override - String getYoutubeLink(int? timestamp) { - return 'https://www.youtube.com/channel/$authorId'; + Uri getYoutubeLink(int? timestamp) { + return Uri.parse('https://www.youtube.com/channel/$authorId'); } } diff --git a/lib/channels/views/tv/screens/channel.dart b/lib/channels/views/tv/screens/channel.dart index 9e5374ea..75d45d21 100644 --- a/lib/channels/views/tv/screens/channel.dart +++ b/lib/channels/views/tv/screens/channel.dart @@ -85,8 +85,8 @@ class TvChannelScreen extends StatelessWidget { sigmaY: value, ), child: AnimatedContainer( - color: colors.surface.withOpacity( - tv.showBackground + color: colors.surface.withValues( + alpha: tv.showBackground ? overlayBackgroundOpacity : 0), duration: animationDuration, @@ -107,9 +107,11 @@ class TvChannelScreen extends StatelessWidget { decoration: BoxDecoration( color: tv.showBackground ? colors.surface - .withOpacity(0) + .withValues( + alpha: 0) : colors.surface - .withOpacity(1), + .withValues( + alpha: 1), borderRadius: BorderRadius.circular( 35)), diff --git a/lib/downloads/views/components/downloaded_video.dart b/lib/downloads/views/components/downloaded_video.dart index 59f96346..094b1286 100644 --- a/lib/downloads/views/components/downloaded_video.dart +++ b/lib/downloads/views/components/downloaded_video.dart @@ -1,3 +1,4 @@ +import 'package:clipious/utils.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:clipious/l10n/generated/app_localizations.dart'; @@ -17,7 +18,7 @@ class DownloadedVideoView extends StatelessWidget { openVideoSheet(BuildContext context, DownloadedVideo v) { var cubit = context.read(); final locals = AppLocalizations.of(context)!; - showModalBottomSheet( + showSafeModalBottomSheet( enableDrag: true, showDragHandle: true, context: context, diff --git a/lib/home/views/screens/edit_layout.dart b/lib/home/views/screens/edit_layout.dart index 83c61198..db8cdae2 100644 --- a/lib/home/views/screens/edit_layout.dart +++ b/lib/home/views/screens/edit_layout.dart @@ -229,7 +229,7 @@ class SourceSwitcher extends StatelessWidget { child: Text( e.getLabel(locals), style: !enabled - ? TextStyle(color: colors.secondary.withOpacity(0.5)) + ? TextStyle(color: colors.secondary.withValues(alpha: 0.5)) : null, )); }).toList(), diff --git a/lib/main.dart b/lib/main.dart index 9b68c05e..676e5bc3 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -262,7 +262,7 @@ class MyApp extends StatelessWidget { inactiveTrackColor: lightColorScheme.secondaryContainer), progressIndicatorTheme: ProgressIndicatorThemeData( circularTrackColor: lightColorScheme.secondaryContainer - .withOpacity(0.8))), + .withValues(alpha: 0.8))), darkTheme: ThemeData( useMaterial3: true, colorScheme: darkColorScheme, @@ -272,8 +272,8 @@ class MyApp extends StatelessWidget { sliderTheme: sliderTheme.copyWith( inactiveTrackColor: darkColorScheme.secondaryContainer), progressIndicatorTheme: ProgressIndicatorThemeData( - circularTrackColor: - darkColorScheme.secondaryContainer.withOpacity(0.8))), + circularTrackColor: darkColorScheme.secondaryContainer + .withValues(alpha: 0.8))), ); }); }); diff --git a/lib/player/states/video_player.dart b/lib/player/states/video_player.dart index 74f432e3..99f7eefc 100644 --- a/lib/player/states/video_player.dart +++ b/lib/player/states/video_player.dart @@ -355,7 +355,7 @@ class VideoPlayerCubit extends MediaPlayerCubit { fit: fillVideo ? BoxFit.cover : BoxFit.contain, subtitlesConfiguration: BetterPlayerSubtitlesConfiguration( backgroundColor: settings.state.subtitlesBackground - ? Colors.black.withOpacity(0.8) + ? Colors.black.withValues(alpha: 0.8) : Colors.transparent, fontSize: settings.state.subtitleSize, outlineEnabled: true, diff --git a/lib/player/views/components/mini_player_progress.dart b/lib/player/views/components/mini_player_progress.dart index 9de7d277..03527532 100644 --- a/lib/player/views/components/mini_player_progress.dart +++ b/lib/player/views/components/mini_player_progress.dart @@ -25,7 +25,7 @@ class MiniPlayerProgress extends StatelessWidget { constraints: const BoxConstraints(maxWidth: 300), height: 2, decoration: BoxDecoration( - color: colors.primary.withOpacity(0.2), + color: colors.primary.withValues(alpha: 0.2), borderRadius: BorderRadius.circular(20), ), child: AnimatedFractionallySizedBox( diff --git a/lib/player/views/components/player_controls.dart b/lib/player/views/components/player_controls.dart index 5351cfd6..e35cd0fb 100644 --- a/lib/player/views/components/player_controls.dart +++ b/lib/player/views/components/player_controls.dart @@ -23,9 +23,10 @@ class PlayerControls extends StatelessWidget { const PlayerControls({super.key, this.mediaPlayerCubit}); - showPlaybackSpeedSelection(BuildContext context, MediaPlayerCubit player) { + Future showPlaybackSpeedSelection( + BuildContext context, MediaPlayerCubit player) async { Navigator.of(context).pop(); - showModalBottomSheet( + showSafeModalBottomSheet( isScrollControlled: true, showDragHandle: true, context: context, @@ -69,10 +70,11 @@ class PlayerControls extends StatelessWidget { ); } - showPlayerTrackSelection(BuildContext context, PlayerControlsState _, + Future showPlayerTrackSelection( + BuildContext context, PlayerControlsState _, {required List tracks, required int selected, - required Function(int index) onSelected}) { + required Function(int index) onSelected}) async { List widgets = []; for (int i = 0; i < tracks.length; i++) { @@ -86,7 +88,7 @@ class PlayerControls extends StatelessWidget { title: Text(tracks[i]))); } - showModalBottomSheet( + showSafeModalBottomSheet( showDragHandle: true, isScrollControlled: true, context: context, @@ -101,7 +103,7 @@ class PlayerControls extends StatelessWidget { ); } - showOptionMenu(BuildContext context, PlayerControlsState controls) { + void showOptionMenu(BuildContext context, PlayerControlsState controls) { late MediaPlayerCubit pc; var player = context.read(); if (mediaPlayerCubit != null) { @@ -116,7 +118,7 @@ class PlayerControls extends StatelessWidget { var audioTracks = pc.getAudioTracks(); var subtitles = pc.getSubtitles(); - showModalBottomSheet( + showSafeModalBottomSheet( isScrollControlled: true, showDragHandle: true, context: context, @@ -227,7 +229,7 @@ class PlayerControls extends StatelessWidget { inactiveTrackColor: darkColorScheme.secondaryContainer), progressIndicatorTheme: ProgressIndicatorThemeData( circularTrackColor: - darkColorScheme.secondaryContainer.withOpacity(0.8))), + darkColorScheme.secondaryContainer.withValues(alpha: 0.8))), child: BlocProvider( create: (context) => PlayerControlsCubit(const PlayerControlsState(), player), @@ -308,7 +310,7 @@ class PlayerControls extends StatelessWidget { child: Container( padding: const EdgeInsets.all(8), decoration: BoxDecoration( - color: Colors.black.withOpacity(0.5), + color: Colors.black.withValues(alpha: 0.5), borderRadius: BorderRadius.circular(20)), child: Row( children: [ @@ -426,7 +428,7 @@ class PlayerControls extends StatelessWidget { )), if (playerState.errored) Container( - color: Colors.black.withOpacity(0.8), + color: Colors.black.withValues(alpha: 0.8), child: const Center( child: Icon(Icons.error), ), @@ -445,7 +447,8 @@ class PlayerControls extends StatelessWidget { decoration: BoxDecoration( borderRadius: BorderRadius.circular(0), - color: Colors.black.withOpacity(0.4)), + color: Colors.black + .withValues(alpha: 0.4)), child: Column( children: [ Row( @@ -467,8 +470,9 @@ class PlayerControls extends StatelessWidget { style: textTheme.bodyMedium ?.copyWith( color: Colors.white - .withOpacity( - 0.8)), + .withValues( + alpha: + 0.8)), ), )), IconButton( @@ -552,8 +556,8 @@ class PlayerControls extends StatelessWidget { begin: Alignment.bottomCenter, end: Alignment.topCenter, colors: [ - Colors.black.withOpacity(1), - Colors.black.withOpacity(0) + Colors.black.withValues(alpha: 1), + Colors.black.withValues(alpha: 0) ])) : null, child: Padding( @@ -772,7 +776,7 @@ class DoubleTapButton extends StatelessWidget { curve: Curves.easeInOutQuad, margin: EdgeInsets.all(opacity == 1 ? 50 : 0), decoration: BoxDecoration( - color: Colors.black.withOpacity(opacity == 1 ? 0.3 : 0), + color: Colors.black.withValues(alpha: opacity == 1 ? 0.3 : 0), shape: BoxShape.circle), duration: const Duration(milliseconds: 150), height: double.infinity, @@ -790,7 +794,7 @@ class DoubleTapButton extends StatelessWidget { Text( stepText, style: textTheme.bodySmall - ?.copyWith(color: Colors.white.withOpacity(0.8)), + ?.copyWith(color: Colors.white.withValues(alpha: 0.8)), ) ], ), diff --git a/lib/player/views/components/sleep_timer.dart b/lib/player/views/components/sleep_timer.dart index 7015c62b..18f6f70a 100644 --- a/lib/player/views/components/sleep_timer.dart +++ b/lib/player/views/components/sleep_timer.dart @@ -13,7 +13,7 @@ class SleepTimerSheet extends StatelessWidget { const SleepTimerSheet({super.key}); static Future show(BuildContext context) { - return showModalBottomSheet( + return showSafeModalBottomSheet( showDragHandle: true, context: context, builder: (context) => const SleepTimerSheet()); diff --git a/lib/player/views/components/system_setting_slider.dart b/lib/player/views/components/system_setting_slider.dart index 388a30e8..1b233adc 100644 --- a/lib/player/views/components/system_setting_slider.dart +++ b/lib/player/views/components/system_setting_slider.dart @@ -53,7 +53,7 @@ class SystemSettingsSlider extends StatelessWidget { child: Container( decoration: BoxDecoration( borderRadius: BorderRadius.circular(20), - color: colors.primary.withOpacity(0.1)), + color: colors.primary.withValues(alpha: 0.1)), child: FractionallySizedBox( alignment: Alignment.bottomCenter, heightFactor: value, diff --git a/lib/player/views/tv/components/player_controls.dart b/lib/player/views/tv/components/player_controls.dart index c3b14013..ab55dd90 100644 --- a/lib/player/views/tv/components/player_controls.dart +++ b/lib/player/views/tv/components/player_controls.dart @@ -69,9 +69,9 @@ class TvPlayerControls extends StatelessWidget { begin: Alignment.topCenter, end: Alignment.bottomCenter, colors: [ - Colors.black.withOpacity(1), - Colors.black.withOpacity(0), - Colors.black.withOpacity(1) + Colors.black.withValues(alpha: 1), + Colors.black.withValues(alpha: 0), + Colors.black.withValues(alpha: 1) ])), ), ), @@ -323,7 +323,7 @@ class TvPlayerControls extends StatelessWidget { ? Container( decoration: BoxDecoration( color: Colors.black - .withOpacity(0.5), + .withValues(alpha: 0.5), borderRadius: BorderRadius.circular( 5)), diff --git a/lib/playlists/views/components/playlist_inner_view.dart b/lib/playlists/views/components/playlist_inner_view.dart index e6b5c808..6f54e067 100644 --- a/lib/playlists/views/components/playlist_inner_view.dart +++ b/lib/playlists/views/components/playlist_inner_view.dart @@ -48,8 +48,8 @@ class PlaylistInnerView extends StatelessWidget { child: Container( padding: const EdgeInsets.all(5), decoration: BoxDecoration( - color: - colors.surface.withOpacity(0.5), + color: colors.surface + .withValues(alpha: 0.5), shape: BoxShape.circle), child: TweenAnimationBuilder( tween: Tween( diff --git a/lib/playlists/views/tablet/playlist_inner_view.dart b/lib/playlists/views/tablet/playlist_inner_view.dart index 7a67fd43..b00f5c5c 100644 --- a/lib/playlists/views/tablet/playlist_inner_view.dart +++ b/lib/playlists/views/tablet/playlist_inner_view.dart @@ -25,7 +25,7 @@ class TabletPlaylistInnerView extends StatelessWidget { required this.openVideo}); void showVideoModalSheet(BuildContext parentContext, Video video) { - showModalBottomSheet( + showSafeModalBottomSheet( context: parentContext, showDragHandle: true, builder: (BuildContext context) { @@ -93,7 +93,8 @@ class TabletPlaylistInnerView extends StatelessWidget { child: Container( padding: const EdgeInsets.all(5), decoration: BoxDecoration( - color: colors.surface.withOpacity(0.5), + color: colors.surface + .withValues(alpha: 0.5), shape: BoxShape.circle), child: TweenAnimationBuilder( tween: Tween( diff --git a/lib/playlists/views/tv/screens/playlist.dart b/lib/playlists/views/tv/screens/playlist.dart index e32e4f2f..346f1cbe 100644 --- a/lib/playlists/views/tv/screens/playlist.dart +++ b/lib/playlists/views/tv/screens/playlist.dart @@ -93,8 +93,8 @@ class TvPlaylistScreen extends PlaylistViewScreen { child: Container( decoration: BoxDecoration( borderRadius: BorderRadius.circular(20), - color: colors.surface - .withOpacity(overlayBackgroundOpacity), + color: colors.surface.withValues( + alpha: overlayBackgroundOpacity), ), child: Padding( padding: const EdgeInsets.all(16.0), diff --git a/lib/settings/views/components/channel_notifications.dart b/lib/settings/views/components/channel_notifications.dart index 5c7c9ca9..ae2d1530 100644 --- a/lib/settings/views/components/channel_notifications.dart +++ b/lib/settings/views/components/channel_notifications.dart @@ -39,7 +39,7 @@ class ChannelNotificationList extends StatelessWidget { const EdgeInsets.symmetric(vertical: 5, horizontal: 10), decoration: BoxDecoration( color: index % 2 != 0 - ? colors.secondaryContainer.withOpacity(0.5) + ? colors.secondaryContainer.withValues(alpha: 0.5) : colors.surface, borderRadius: BorderRadius.circular(10)), child: InkWell( diff --git a/lib/settings/views/components/manager_server_inner.dart b/lib/settings/views/components/manager_server_inner.dart index 0de319bb..0b04fbd4 100644 --- a/lib/settings/views/components/manager_server_inner.dart +++ b/lib/settings/views/components/manager_server_inner.dart @@ -24,7 +24,7 @@ class ManagerServersView extends StatelessWidget { var locals = AppLocalizations.of(context)!; ServerListSettingsCubit cubit = context.read(); - showModalBottomSheet( + showSafeModalBottomSheet( showDragHandle: true, context: context, builder: (BuildContext context) { diff --git a/lib/settings/views/components/playlist_notifications.dart b/lib/settings/views/components/playlist_notifications.dart index bb3abf32..0a4bc732 100644 --- a/lib/settings/views/components/playlist_notifications.dart +++ b/lib/settings/views/components/playlist_notifications.dart @@ -50,7 +50,7 @@ class PlaylistNotificationList extends StatelessWidget { const EdgeInsets.symmetric(vertical: 5, horizontal: 10), decoration: BoxDecoration( color: index % 2 != 0 - ? colors.secondaryContainer.withOpacity(0.5) + ? colors.secondaryContainer.withValues(alpha: 0.5) : colors.surface, borderRadius: BorderRadius.circular(10)), child: InkWell( diff --git a/lib/settings/views/screens/manage_single_server.dart b/lib/settings/views/screens/manage_single_server.dart index f197a4ec..66f185af 100644 --- a/lib/settings/views/screens/manage_single_server.dart +++ b/lib/settings/views/screens/manage_single_server.dart @@ -260,14 +260,14 @@ class ManageSingleServerScreen extends StatelessWidget { Icons.delete, color: state.canDelete ? Colors.red - : Colors.red.withOpacity(0.5), + : Colors.red.withValues(alpha: 0.5), ), title: Text( locals.delete, style: TextStyle( color: state.canDelete ? Colors.red - : Colors.red.withOpacity(0.5)), + : Colors.red.withValues(alpha: 0.5)), ), ) ]), diff --git a/lib/settings/views/screens/video_filter_setup.dart b/lib/settings/views/screens/video_filter_setup.dart index edcc417f..32b79c55 100644 --- a/lib/settings/views/screens/video_filter_setup.dart +++ b/lib/settings/views/screens/video_filter_setup.dart @@ -233,7 +233,7 @@ class VideoFilterSetupScreen extends StatelessWidget { color: isSelected ? colors.primaryContainer : colors.primaryContainer - .withOpacity(0.4)), + .withValues(alpha: 0.4)), duration: animationDuration, curve: Curves.easeInOutQuad, child: Row( diff --git a/lib/subscription_management/view/components/subscribe_button.dart b/lib/subscription_management/view/components/subscribe_button.dart index affad935..e152f0fe 100644 --- a/lib/subscription_management/view/components/subscribe_button.dart +++ b/lib/subscription_management/view/components/subscribe_button.dart @@ -1,3 +1,4 @@ +import 'package:clipious/utils.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:clipious/l10n/generated/app_localizations.dart'; @@ -17,7 +18,7 @@ class SubscribeButton extends StatelessWidget { final locals = AppLocalizations.of(context)!; if (cubit.state.isLoggedIn) { - showModalBottomSheet( + showSafeModalBottomSheet( context: context, builder: (context) { return Column( diff --git a/lib/subscription_management/view/tv/tv_subscribe_button.dart b/lib/subscription_management/view/tv/tv_subscribe_button.dart index f2293da9..a09ad1a0 100644 --- a/lib/subscription_management/view/tv/tv_subscribe_button.dart +++ b/lib/subscription_management/view/tv/tv_subscribe_button.dart @@ -34,7 +34,7 @@ class TvSubscribeButton extends StatelessWidget { child: TvButton( autofocus: autoFocus, onFocusChanged: onFocusChanged, - unfocusedColor: colors.surface.withOpacity(0.0), + unfocusedColor: colors.surface.withValues(alpha: 0.0), onPressed: (context) { if (state.isSubscribed) { cubit.unsubscribe(); diff --git a/lib/utils.dart b/lib/utils.dart index 7279d4a0..d5d62165 100644 --- a/lib/utils.dart +++ b/lib/utils.dart @@ -114,7 +114,7 @@ void showSharingSheet(BuildContext context, ShareLinks links, return null; } - showModalBottomSheet( + showSafeModalBottomSheet( context: context, showDragHandle: true, builder: (BuildContext context) { @@ -138,9 +138,10 @@ void showSharingSheet(BuildContext context, ShareLinks links, onPressed: () async { final timestamp = await getTimestamp(); - Share.share(links.getInvidiousLink( - await db.getCurrentlySelectedServer(), - timestamp?.inSeconds)); + SharePlus.instance.share(ShareParams( + uri: links.getInvidiousLink( + await db.getCurrentlySelectedServer(), + timestamp?.inSeconds))); if (context.mounted) { Navigator.of(context).pop(); } @@ -151,7 +152,8 @@ void showSharingSheet(BuildContext context, ShareLinks links, onPressed: () async { final timestamp = await getTimestamp(); - Share.share(links.getRedirectLink(timestamp?.inSeconds)); + SharePlus.instance.share(ShareParams( + uri: links.getRedirectLink(timestamp?.inSeconds))); if (context.mounted) { Navigator.of(context).pop(); } @@ -162,7 +164,8 @@ void showSharingSheet(BuildContext context, ShareLinks links, onPressed: () async { final timestamp = await getTimestamp(); - Share.share(links.getYoutubeLink(timestamp?.inSeconds)); + SharePlus.instance.share(ShareParams( + uri: links.getYoutubeLink(timestamp?.inSeconds))); if (context.mounted) { Navigator.of(context).pop(); } @@ -392,3 +395,32 @@ Size getFractionOfAvailableSpace(BuildContext context, double fraction) { var size = MediaQuery.of(context).size; return Size(size.width * fraction, size.height * fraction); } + +Future showSafeModalBottomSheet({ + required BuildContext context, + required WidgetBuilder builder, + bool isScrollControlled = false, + bool enableDrag = true, + bool isDismissible = true, + Color? backgroundColor, + double? elevation, + ShapeBorder? shape, + bool? showDragHandle, + Clip? clipBehavior, + RouteSettings? routeSettings, +}) { + return showModalBottomSheet( + context: context, + builder: (context) => SafeArea(child: builder(context)), + useSafeArea: true, // ✅ Always enforced + isScrollControlled: isScrollControlled, + enableDrag: enableDrag, + isDismissible: isDismissible, + backgroundColor: backgroundColor, + showDragHandle: showDragHandle, + elevation: elevation, + shape: shape, + clipBehavior: clipBehavior, + routeSettings: routeSettings, + ); +} diff --git a/lib/utils/models/sharelink.dart b/lib/utils/models/sharelink.dart index bd2c83b0..0bd69d01 100644 --- a/lib/utils/models/sharelink.dart +++ b/lib/utils/models/sharelink.dart @@ -1,9 +1,9 @@ import '../../settings/models/db/server.dart'; abstract class ShareLinks { - String getYoutubeLink(int? timestamp); + Uri getYoutubeLink(int? timestamp); - String getInvidiousLink(Server server, int? timestamp); + Uri getInvidiousLink(Server server, int? timestamp); - String getRedirectLink(int? timestamp); + Uri getRedirectLink(int? timestamp); } diff --git a/lib/utils/views/components/simple_list_item.dart b/lib/utils/views/components/simple_list_item.dart index 43cb38de..a38a3501 100644 --- a/lib/utils/views/components/simple_list_item.dart +++ b/lib/utils/views/components/simple_list_item.dart @@ -13,7 +13,7 @@ class SimpleListItem extends StatelessWidget { padding: const EdgeInsets.symmetric(vertical: 5, horizontal: 10), decoration: BoxDecoration( color: index % 2 != 0 - ? colors.secondaryContainer.withOpacity(0.5) + ? colors.secondaryContainer.withValues(alpha: 0.5) : colors.surface, borderRadius: BorderRadius.circular(10)), child: child, diff --git a/lib/utils/views/components/thumbnail.dart b/lib/utils/views/components/thumbnail.dart index d4178619..e6001d93 100644 --- a/lib/utils/views/components/thumbnail.dart +++ b/lib/utils/views/components/thumbnail.dart @@ -118,7 +118,7 @@ class _ErrorWidget extends StatelessWidget { width: 20, child: Icon( Icons.error_outline, - color: colors.onSecondaryContainer.withOpacity(0.5), + color: colors.onSecondaryContainer.withValues(alpha: 0.5), )), ); } diff --git a/lib/utils/views/tv/components/tv_expandable_text.dart b/lib/utils/views/tv/components/tv_expandable_text.dart index 70847ca0..9407af36 100644 --- a/lib/utils/views/tv/components/tv_expandable_text.dart +++ b/lib/utils/views/tv/components/tv_expandable_text.dart @@ -35,7 +35,7 @@ class TvExpandableText extends StatelessWidget { decoration: BoxDecoration( color: hasFocus ? colors.primaryContainer - : colors.surface.withOpacity(0), + : colors.surface.withValues(alpha: 0), borderRadius: BorderRadius.circular(10), ), child: Padding( diff --git a/lib/utils/views/tv/components/tv_time_picker.dart b/lib/utils/views/tv/components/tv_time_picker.dart index bbcb0b97..2b9cf6f9 100644 --- a/lib/utils/views/tv/components/tv_time_picker.dart +++ b/lib/utils/views/tv/components/tv_time_picker.dart @@ -95,7 +95,8 @@ class TvTimePickerScreen extends StatelessWidget { width: 8, ), TvButton( - unfocusedColor: colors.secondaryContainer.withOpacity(0), + unfocusedColor: + colors.secondaryContainer.withValues(alpha: 0), focusedColor: colors.secondaryContainer, child: const Padding( padding: EdgeInsets.all(8.0), @@ -159,7 +160,7 @@ class TimeChanger extends StatelessWidget { borderRadius: BorderRadius.circular(10), color: hasFocus ? colors.secondaryContainer - : colors.secondaryContainer.withOpacity(0), + : colors.secondaryContainer.withValues(alpha: 0), ), padding: const EdgeInsets.all(8), duration: animationDuration, diff --git a/lib/videos/models/video.dart b/lib/videos/models/video.dart index 2da03d08..7b016597 100644 --- a/lib/videos/models/video.dart +++ b/lib/videos/models/video.dart @@ -99,30 +99,30 @@ sealed class Video with _$Video implements ShareLinks, IdedVideo { factory Video.fromJson(Map json) => _$VideoFromJson(json); @override - String getInvidiousLink(Server server, int? timestamp) { + Uri getInvidiousLink(Server server, int? timestamp) { String link = '${server.url}/watch?v=$videoId'; if (timestamp != null) link += '&t=$timestamp'; - return link; + return Uri.parse(link); } @override - String getRedirectLink(int? timestamp) { + Uri getRedirectLink(int? timestamp) { String link = 'https://redirect.invidious.io/watch?v=$videoId'; if (timestamp != null) link += '&t=$timestamp'; - return link; + return Uri.parse(link); } @override - String getYoutubeLink(int? timestamp) { + Uri getYoutubeLink(int? timestamp) { String link = 'https://youtu.be/$videoId'; if (timestamp != null) link += '?t=$timestamp'; - return link; + return Uri.parse(link); } List get thumbnails { diff --git a/lib/videos/views/components/add_to_playlist_dialog.dart b/lib/videos/views/components/add_to_playlist_dialog.dart index 169168ea..95ab07ad 100644 --- a/lib/videos/views/components/add_to_playlist_dialog.dart +++ b/lib/videos/views/components/add_to_playlist_dialog.dart @@ -1,4 +1,5 @@ import 'package:auto_route/auto_route.dart'; +import 'package:clipious/utils.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:clipious/l10n/generated/app_localizations.dart'; @@ -27,10 +28,9 @@ class AddToPlaylistDialog extends StatelessWidget { {required String videoId, required List playlists, required Function(String selectedPlaylistId) onAdd}) { - showModalBottomSheet( + showSafeModalBottomSheet( showDragHandle: true, isScrollControlled: true, - useSafeArea: true, context: context, builder: (BuildContext context) { return AddToPlaylistDialog( diff --git a/lib/videos/views/components/compact_video.dart b/lib/videos/views/components/compact_video.dart index 9797bfa9..6ded4dd6 100644 --- a/lib/videos/views/components/compact_video.dart +++ b/lib/videos/views/components/compact_video.dart @@ -86,8 +86,8 @@ class CompactVideo extends StatelessWidget { borderRadius: BorderRadius.circular(10)), child: Icon(Icons.visibility_off_outlined, - color: - colors.secondary.withOpacity(0.7), + color: colors.secondary + .withValues(alpha: 0.7), size: 15), ), ) diff --git a/lib/videos/views/components/download_modal_sheet.dart b/lib/videos/views/components/download_modal_sheet.dart index 0dfafc90..b6ec6584 100644 --- a/lib/videos/views/components/download_modal_sheet.dart +++ b/lib/videos/views/components/download_modal_sheet.dart @@ -1,3 +1,4 @@ +import 'package:clipious/utils.dart'; import 'package:clipious/videos/models/video.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; @@ -28,7 +29,7 @@ class DownloadModalSheet extends StatelessWidget { static void showVideoModalSheet(BuildContext context, Video video, {Function(bool isDownloadStarted)? onDownloadStarted, Function()? onDownload}) { - showModalBottomSheet( + showSafeModalBottomSheet( enableDrag: true, showDragHandle: true, context: context, diff --git a/lib/videos/views/components/play_button.dart b/lib/videos/views/components/play_button.dart index 9a331517..864069ab 100644 --- a/lib/videos/views/components/play_button.dart +++ b/lib/videos/views/components/play_button.dart @@ -25,7 +25,7 @@ class PlayButton extends StatelessWidget { }, style: ButtonStyle( backgroundColor: WidgetStateProperty.resolveWith( - (states) => colorScheme.primary.withOpacity(1))), + (states) => colorScheme.primary.withValues(alpha: 1))), icon: const Icon( Icons.music_note, size: 35, @@ -39,8 +39,8 @@ class PlayButton extends StatelessWidget { AutoRouter.of(context).maybePop(); }, style: ButtonStyle( - backgroundColor: WidgetStateColor.resolveWith( - (states) => colorScheme.primaryContainer.withOpacity(1))), + backgroundColor: WidgetStateColor.resolveWith((states) => + colorScheme.primaryContainer.withValues(alpha: 1))), icon: Icon( icon ?? Icons.play_arrow, size: 75, diff --git a/lib/videos/views/components/video_in_list.dart b/lib/videos/views/components/video_in_list.dart index 7e416f39..5d0135cb 100644 --- a/lib/videos/views/components/video_in_list.dart +++ b/lib/videos/views/components/video_in_list.dart @@ -69,7 +69,7 @@ class VideoListItem extends StatelessWidget { var textTheme = Theme.of(context).textTheme; TextStyle filterStyle = (textTheme.bodySmall ?? const TextStyle()) - .copyWith(color: colorScheme.secondary.withOpacity(0.7)); + .copyWith(color: colorScheme.secondary.withValues(alpha: 0.7)); String title = video?.title ?? offlineVideo?.title ?? ''; String author = video?.author ?? offlineVideo?.author ?? ''; @@ -283,7 +283,8 @@ class VideoListItem extends StatelessWidget { height: 25, decoration: BoxDecoration( color: Colors.black - .withOpacity(0.75), + .withValues( + alpha: 0.75), borderRadius: BorderRadius .circular(5)), diff --git a/lib/videos/views/components/video_modal_sheet.dart b/lib/videos/views/components/video_modal_sheet.dart index f5e9b0df..69aaef3a 100644 --- a/lib/videos/views/components/video_modal_sheet.dart +++ b/lib/videos/views/components/video_modal_sheet.dart @@ -16,12 +16,14 @@ class VideoModalSheet extends StatelessWidget { const VideoModalSheet({super.key, required this.video}); static void showVideoModalSheet(BuildContext context, Video video) { - showModalBottomSheet( + showSafeModalBottomSheet( context: context, showDragHandle: true, builder: (BuildContext context) { - return VideoModalSheet( - video: video, + return SafeArea( + child: VideoModalSheet( + video: video, + ), ); }); } diff --git a/lib/videos/views/tv/components/video_item.dart b/lib/videos/views/tv/components/video_item.dart index ad2ae81e..33f106f0 100644 --- a/lib/videos/views/tv/components/video_item.dart +++ b/lib/videos/views/tv/components/video_item.dart @@ -51,7 +51,7 @@ class TvVideoItem extends StatelessWidget { TextTheme textTheme = Theme.of(context).textTheme; var locals = AppLocalizations.of(context)!; TextStyle filterStyle = (textTheme.bodySmall ?? const TextStyle()) - .copyWith(color: colors.secondary.withOpacity(0.7)); + .copyWith(color: colors.secondary.withValues(alpha: 0.7)); return BlocProvider( create: (context) => @@ -78,7 +78,7 @@ class TvVideoItem extends StatelessWidget { decoration: BoxDecoration( borderRadius: BorderRadius.circular(15), color: colors.primaryContainer - .withOpacity(hasFocus ? 1 : 0), + .withValues(alpha: hasFocus ? 1 : 0), ), duration: animationDuration, child: AspectRatio( @@ -224,8 +224,9 @@ class TvVideoItem extends StatelessWidget { decoration: BoxDecoration( color: Colors .black - .withOpacity( - 0.5), + .withValues( + alpha: + 0.5), borderRadius: BorderRadius .circular( diff --git a/lib/videos/views/tv/screens/video.dart b/lib/videos/views/tv/screens/video.dart index ffe7b819..e055f95c 100644 --- a/lib/videos/views/tv/screens/video.dart +++ b/lib/videos/views/tv/screens/video.dart @@ -123,8 +123,8 @@ class TvVideoScreen extends StatelessWidget { child: Container( decoration: BoxDecoration( borderRadius: BorderRadius.circular(20), - color: colors.surface.withOpacity( - overlayBackgroundOpacity)), + color: colors.surface.withValues( + alpha: overlayBackgroundOpacity)), child: Padding( padding: const EdgeInsets.all(16.0), child: SingleChildScrollView( @@ -236,7 +236,8 @@ class TvVideoScreen extends StatelessWidget { ''), unfocusedColor: colors .surface - .withOpacity(0), + .withValues( + alpha: 0), child: Row( mainAxisSize: MainAxisSize @@ -302,8 +303,8 @@ class TvVideoScreen extends StatelessWidget { size: 50, color: colors .primary - .withOpacity( - 0.2), + .withValues( + alpha: 0.2), ), ) ], diff --git a/lib/welcome_wizard/views/tv/screens/welcome_wizard.dart b/lib/welcome_wizard/views/tv/screens/welcome_wizard.dart index 0f036b78..628fc24c 100644 --- a/lib/welcome_wizard/views/tv/screens/welcome_wizard.dart +++ b/lib/welcome_wizard/views/tv/screens/welcome_wizard.dart @@ -62,7 +62,7 @@ class TvWelcomeWizardScreen extends StatelessWidget { locals.startUsingClipious, style: textTheme.titleLarge!.copyWith( color: server == null - ? Colors.white.withOpacity(0.5) + ? Colors.white.withValues(alpha: 0.5) : Colors.white), ), ), diff --git a/pubspec.yaml b/pubspec.yaml index 820c6ed7..6b59fe94 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,5 +1,5 @@ name: clipious -version: 1.22.11+4074 +version: 1.22.12+4075 publish_to: none description: Client for invidious. environment: