diff --git a/lib/controllers/playerController.dart b/lib/controllers/playerController.dart index c0d7ce05..fd99f0e2 100644 --- a/lib/controllers/playerController.dart +++ b/lib/controllers/playerController.dart @@ -3,6 +3,7 @@ import 'package:fbroadcast/fbroadcast.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:get/get.dart'; +import 'package:invidious/controllers/settingsController.dart'; import 'package:invidious/controllers/tvPlayerController.dart'; import 'package:invidious/controllers/videoInListController.dart'; import 'package:invidious/utils.dart'; @@ -70,7 +71,6 @@ class PlayerController extends GetxController { videoController?.removeEventsListener(onVideoListener); videoController?.dispose(); videoController = null; - update(); } saveProgress(int timeInSeconds) { @@ -235,6 +235,9 @@ class PlayerController extends GetxController { autoPlay: true, allowedScreenSleep: false, fit: BoxFit.contain, + subtitlesConfiguration: BetterPlayerSubtitlesConfiguration( + fontSize: double.parse(db.getSettings(SUBTITLE_SIZE)?.value ?? subtitleDefaultSize), + ), controlsConfiguration: BetterPlayerControlsConfiguration( showControls: !(disableControls ?? false), enablePlayPause: false, diff --git a/lib/controllers/settingsController.dart b/lib/controllers/settingsController.dart index b0cae5cd..6e6b2b5b 100644 --- a/lib/controllers/settingsController.dart +++ b/lib/controllers/settingsController.dart @@ -10,6 +10,8 @@ import '../models/db/server.dart'; import '../models/db/settings.dart'; import '../utils.dart'; +const String subtitleDefaultSize = '14'; + class SettingsController extends GetxController { static SettingsController? to() => safeGet(); var log = Logger('SettingsController'); @@ -22,7 +24,8 @@ class SettingsController extends GetxController { bool useDynamicTheme = db.getSettings(DYNAMIC_THEME)?.value == 'true'; bool useDash = db.getSettings(USE_DASH)?.value == 'true'; bool useProxy = db.getSettings(USE_PROXY)?.value == 'true'; - bool blackBackground = db.getSettings(BLACK_BACKGROUND)?.value =='true'; + bool blackBackground = db.getSettings(BLACK_BACKGROUND)?.value == 'true'; + double subtitleSize = double.parse(db.getSettings(SUBTITLE_SIZE)?.value ?? subtitleDefaultSize); @override onReady() { @@ -85,4 +88,16 @@ class SettingsController extends GetxController { blackBackground = value; update(); } + + changeSubtitleSize({required bool increase}) { + if(increase){ + subtitleSize++; + }else { + if (subtitleSize > 1) { + subtitleSize--; + } + } + update(); + db.saveSetting(SettingsValue(SUBTITLE_SIZE, subtitleSize.toString())); + } } diff --git a/lib/database.dart b/lib/database.dart index 3813a9f3..8bb9029c 100644 --- a/lib/database.dart +++ b/lib/database.dart @@ -19,6 +19,7 @@ const PLAYER_SHUFFLE = 'player-shuffle'; const PLAY_RECOMMENDED_NEXT = 'play-recommended-next'; const USE_PROXY = 'use-proxy'; const BLACK_BACKGROUND = 'black-background'; +const SUBTITLE_SIZE = 'subtitles-size'; const ON_OPEN = "on-open"; diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index a623a969..473c4bc3 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -509,6 +509,14 @@ "@search": { "description": "search title" }, + "subtitleFontSize": "Subtitles font size", + "@subtitleFontSize": { + "description": "Settings label for the size of the subtitles" + }, + "subtitleFontSizeDescription": "Change the size of the subtitles if it is too small or too big on your device", + "@subtitleFontSizeDescription": { + "description": "Settings description for subtitle size" + }, "nVideos": "{count, plural, =0{No videos} =1{1 video} other{{count} videos}}", "@nVideos": { "description": "One or more videos", diff --git a/lib/views/settings.dart b/lib/views/settings.dart index 480529b3..ec14f046 100644 --- a/lib/views/settings.dart +++ b/lib/views/settings.dart @@ -22,6 +22,8 @@ settingsTheme(ColorScheme colorScheme) => SettingsThemeData( leadingIconsColor: colorScheme.secondary, tileHighlightColor: colorScheme.secondaryContainer); + + class Settings extends StatelessWidget { const Settings({super.key}); @@ -123,6 +125,12 @@ class Settings extends StatelessWidget { title: Text(locals.useProxy), description: Text(locals.useProxyDescription), ), + SettingsTile(title: Text(locals.subtitleFontSize), description: Text(locals.subtitleFontSizeDescription), + trailing: Row(mainAxisSize: MainAxisSize.min, children: [ + IconButton(onPressed: () => _.changeSubtitleSize(increase: false), icon: const Icon(Icons.remove)), + Text(_.subtitleSize.floor().toString()), + IconButton(onPressed: () => _.changeSubtitleSize(increase: true), icon: const Icon(Icons.add)), + ],),), SettingsTile.navigation( title: Text('SponsorBlock'), description: Text(locals.sponsorBlockDescription), diff --git a/lib/views/tv/tvSettings.dart b/lib/views/tv/tvSettings.dart index 96dc5875..2c969c15 100644 --- a/lib/views/tv/tvSettings.dart +++ b/lib/views/tv/tvSettings.dart @@ -5,6 +5,7 @@ import 'package:invidious/utils.dart'; import 'package:invidious/views/tv/settings/tvManageServers.dart'; import 'package:invidious/views/tv/settings/tvSelectFromList.dart'; import 'package:invidious/views/tv/settings/tvSponsorBlockSettings.dart'; +import 'package:invidious/views/tv/tvButton.dart'; import 'package:invidious/views/tv/tvOverScan.dart'; import '../../controllers/settingsController.dart'; @@ -104,6 +105,27 @@ class TVSettings extends StatelessWidget { onSelected: (context) => _.toggleProxy(!_.useProxy), trailing: Switch(onChanged: (value) {}, value: _.useProxy), ), + SettingsTile( + title: locals.subtitleFontSize, + description: locals.subtitleFontSizeDescription, + trailing: Row(mainAxisSize: MainAxisSize.min, children: [ + Padding( + padding: const EdgeInsets.only(right: 8.0), + child: TvButton(onPressed: (ctx) => _.changeSubtitleSize(increase: false), child: const Padding( + padding: EdgeInsets.all(8.0), + child: Icon(Icons.remove), + )), + ), + Text(_.subtitleSize.floor().toString(), style: textTheme.bodyLarge,), + Padding( + padding: const EdgeInsets.only(left:8.0), + child: TvButton(onPressed: (ctx) => _.changeSubtitleSize(increase: true), child: const Padding( + padding: EdgeInsets.all(8.0), + child: Icon(Icons.add), + )), + ), + ],), + ), SettingsTile( title: 'SponsorBlock', description: locals.sponsorBlockDescription, diff --git a/lib/views/tv/tvVideoView.dart b/lib/views/tv/tvVideoView.dart index 613af897..4435c394 100644 --- a/lib/views/tv/tvVideoView.dart +++ b/lib/views/tv/tvVideoView.dart @@ -43,104 +43,111 @@ class TvVideoView extends StatelessWidget { builder: (_) => TvOverscan( child: DefaultTextStyle( style: textTheme.bodyLarge!, - child: _.loadingVideo - ? const Center( - child: CircularProgressIndicator(), - ) - : Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - SizedBox( - height: 190, - child: Row( - crossAxisAlignment: CrossAxisAlignment.end, - children: [ - VideoThumbnailView(videoId: _.video!.videoId, thumbnailUrl: ImageObject.getBestThumbnail(_.video?.videoThumbnails)?.url ?? ''), - Expanded( - child: Column(crossAxisAlignment: CrossAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.end, children: [ - Padding( - padding: const EdgeInsets.all(16.0), - child: TvButton( - autofocus: true, - onPressed: (context) => playVideo(context, _.video!), - child: const Padding( - padding: EdgeInsets.all(15.0), - child: Icon( - Icons.play_arrow, - size: 50, + child: _.error.isNotEmpty + ? Center( + child: Container( + alignment: Alignment.center, + child: Text(_.error == coulnotLoadVideos ? locals.couldntLoadVideo : _.error, style: textTheme.bodyLarge,), + ), + ) + : _.loadingVideo + ? const Center( + child: CircularProgressIndicator(), + ) + : Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + SizedBox( + height: 190, + child: Row( + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + VideoThumbnailView(videoId: _.video!.videoId, thumbnailUrl: ImageObject.getBestThumbnail(_.video?.videoThumbnails)?.url ?? ''), + Expanded( + child: Column(crossAxisAlignment: CrossAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.end, children: [ + Padding( + padding: const EdgeInsets.all(16.0), + child: TvButton( + autofocus: true, + onPressed: (context) => playVideo(context, _.video!), + child: const Padding( + padding: EdgeInsets.all(15.0), + child: Icon( + Icons.play_arrow, + size: 50, + ), + ), ), ), - ), + ]), ), - ]), + ], ), - ], - ), - ), - Padding( - padding: const EdgeInsets.only(top: 8), - child: Text( - _.video!.title, - maxLines: 2, - style: textTheme.headlineMedium!.copyWith(color: colors.primary), - overflow: TextOverflow.ellipsis, - ), - ), - Expanded( - child: Padding( - padding: const EdgeInsets.only(bottom: 10.0), - child: ListView(children: [ - Row( - children: [ - TvButton( - onPressed: (context) => showChannel(context, _.video?.authorId ?? ''), - unfocusedColor: colors.background, - focusedColor: colors.secondaryContainer, - child: Row( - mainAxisSize: MainAxisSize.min, - children: [ - Thumbnail( - thumbnailUrl: ImageObject.getBestThumbnail(_.video?.authorThumbnails)?.url ?? '', - width: 40, - height: 40, - id: 'author-small-${_.video?.authorId}', - decoration: BoxDecoration(borderRadius: BorderRadius.circular(20)), + ), + Padding( + padding: const EdgeInsets.only(top: 8), + child: Text( + _.video!.title, + maxLines: 2, + style: textTheme.headlineMedium!.copyWith(color: colors.primary), + overflow: TextOverflow.ellipsis, + ), + ), + Expanded( + child: Padding( + padding: const EdgeInsets.only(bottom: 10.0), + child: ListView(children: [ + Row( + children: [ + TvButton( + onPressed: (context) => showChannel(context, _.video?.authorId ?? ''), + unfocusedColor: colors.background, + focusedColor: colors.secondaryContainer, + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + Thumbnail( + thumbnailUrl: ImageObject.getBestThumbnail(_.video?.authorThumbnails)?.url ?? '', + width: 40, + height: 40, + id: 'author-small-${_.video?.authorId}', + decoration: BoxDecoration(borderRadius: BorderRadius.circular(20)), + ), + Padding( + padding: const EdgeInsets.only(left: 8.0, right: 20), + child: Text(_.video?.author ?? ''), + ) + ], ), - Padding( - padding: const EdgeInsets.only(left: 8.0, right: 20), - child: Text(_.video?.author ?? ''), - ) - ], + ), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 16.0), + child: TvSubscribeButton(channelId: _.video?.authorId ?? '', subCount: _.video?.subCountText ?? ''), + ) + ], + ), + Padding( + padding: const EdgeInsets.only(right: 40.0), + child: TvExpandableText( + text: _.video?.description ?? '', + maxLines: 3, ), ), Padding( - padding: const EdgeInsets.symmetric(horizontal: 16.0), - child: TvSubscribeButton(channelId: _.video?.authorId ?? '', subCount: _.video?.subCountText ?? ''), - ) - ], - ), - Padding( - padding: const EdgeInsets.only(right: 40.0), - child: TvExpandableText( - text: _.video?.description ?? '', - maxLines: 3, - ), - ), - Padding( - padding: const EdgeInsets.only(top: 10.0), - child: Text( - locals.recommended, - style: textTheme.titleLarge!, - ), + padding: const EdgeInsets.only(top: 10.0), + child: Text( + locals.recommended, + style: textTheme.titleLarge!, + ), + ), + TvHorizontalVideoList( + paginatedVideoList: FixedItemList( + _.video?.recommendedVideos.map((e) => VideoInList(e.title, e.videoId, e.lengthSeconds, 0, e.author, '', 'authorUrl', 0, '', e.videoThumbnails)).toList() ?? [])) + ]), ), - TvHorizontalVideoList( - paginatedVideoList: FixedItemList( - _.video?.recommendedVideos.map((e) => VideoInList(e.title, e.videoId, e.lengthSeconds, 0, e.author, '', 'authorUrl', 0, '', e.videoThumbnails)).toList() ?? [])) - ]), - ), - ) - ], - ), + ) + ], + ), ), ), ));