Skip to content

Commit

Permalink
add settings to force the TV ui, can be useful for some tv boxes
Browse files Browse the repository at this point in the history
fix #304
  • Loading branch information
lamarios committed Jan 31, 2025
1 parent cd849ae commit caf0168
Show file tree
Hide file tree
Showing 9 changed files with 64 additions and 18 deletions.
4 changes: 3 additions & 1 deletion lib/l10n/app_en.arb
Original file line number Diff line number Diff line change
Expand Up @@ -1383,5 +1383,7 @@
"premieresIn": "Premieres in {formattedDuration}",
"screenControls": "Screen controls",
"screenControlsExplanation": "When watching a video in full screen, Vertically dragging from the left or the right will adjust the brightness or volume respectively",
"retry": "Retry"
"retry": "Retry",
"forceTvUi": "Force TV interface",
"forceTvUiExplanation": "Force the interface to be the TV experience, can be useful for some devices that do not have the leanback system config. App restart required"
}
1 change: 1 addition & 0 deletions lib/settings/models/db/settings.dart
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ const dearrowSettingName = 'dearrow';
const dearrowThumbnailsSettingName = "dearrow-thumbnails";
const fullScreenOnLandscapeSettingName = "fullscreen-on-landscape";
const screenControlsSettingName = "screen-controls";
const forceTvUiSettingName = "force-tv-ui";

const onOpenSettingName = "on-open";

Expand Down
5 changes: 5 additions & 0 deletions lib/settings/states/settings.dart
Original file line number Diff line number Diff line change
Expand Up @@ -327,6 +327,8 @@ class SettingsCubit extends Cubit<SettingsState> {

setFillFullscreen(bool b) async => await _set(fillFullScreen, b);

setForceTvUi(bool b) async => await _set(forceTvUiSettingName, b);

_setLocale(String? s) async {
await _set(localeSettingName, s);
await fileDb.setLocale(s);
Expand Down Expand Up @@ -563,6 +565,9 @@ class SettingsState with _$SettingsState {
bool get screenControls =>
(_get(screenControlsSettingName)?.value ?? 'true') == 'true';

bool get forceTvUi =>
(_get(forceTvUiSettingName)?.value ?? 'false') == 'true';

List<HomeDataSource> get appLayout {
var savedLayout = _get(appLayoutSettingName)?.value;
// String? savedLayout;
Expand Down
7 changes: 7 additions & 0 deletions lib/settings/views/screens/appearance.dart
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,13 @@ class AppearanceSettingsScreen extends StatelessWidget {
context, state.navigationBarLabelBehavior)),
onPressed: (ctx) => customizeNavigationLabel(ctx),
),
SettingsTile.switchTile(
leading: const Icon(Icons.tv),
initialValue: state.forceTvUi,
onToggle: cubit.setForceTvUi,
title: Text(locals.forceTvUi),
description: Text(locals.forceTvUiExplanation),
),
],
),
],
Expand Down
19 changes: 13 additions & 6 deletions lib/settings/views/tv/screens/settings.dart
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import 'package:auto_route/auto_route.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:clipious/app/states/app.dart';
import 'package:clipious/extensions.dart';
import 'package:clipious/router.dart';
import 'package:clipious/utils.dart';
import 'package:clipious/utils/views/tv/components/tv_button.dart';
import 'package:clipious/utils/views/tv/components/tv_overscan.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:locale_names/locale_names.dart';
import 'package:logging/logging.dart';

Expand Down Expand Up @@ -340,6 +340,13 @@ class TVSettingsScreen extends StatelessWidget {
trailing: Switch(
onChanged: (value) {}, value: state.blackBackground),
),
SettingsTile(
title: locals.forceTvUi,
description: locals.forceTvUiExplanation,
onSelected: (context) => cubit.setForceTvUi(!state.forceTvUi),
trailing:
Switch(onChanged: (value) {}, value: state.forceTvUi),
),
SettingsTitle(title: locals.about),
SettingsTile(
title: '${locals.name}: ${state.packageInfo.appName}',
Expand Down Expand Up @@ -505,7 +512,7 @@ class SettingsTile extends StatelessWidget {
enabled: enabled ?? true,
leading: leading,
trailing: trailing,
selectedTileColor: colors.secondaryContainer.withOpacity(0.5),
selectedTileColor: colors.secondaryContainer.withValues(alpha: 0.5),
selected: hasFocus,
title: Column(
crossAxisAlignment: CrossAxisAlignment.start,
Expand All @@ -515,7 +522,7 @@ class SettingsTile extends StatelessWidget {
style: textTheme.headlineSmall!.copyWith(
color: enabled ?? true
? colors.primary
: colors.primary.withOpacity(0.5)),
: colors.primary.withValues(alpha: 0.5)),
),
description != null
? Text(
Expand Down
5 changes: 4 additions & 1 deletion lib/utils.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import 'dart:math';

import 'package:clipious/settings/models/db/settings.dart';
import 'package:device_info_plus/device_info_plus.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
Expand Down Expand Up @@ -203,9 +204,11 @@ DeviceType getDeviceType() {
}

Future<bool> isDeviceTv() async {
final forceTv = db.getSettings(forceTvUiSettingName);
DeviceInfoPlugin deviceInfo = DeviceInfoPlugin();
AndroidDeviceInfo androidInfo = await deviceInfo.androidInfo;
return androidInfo.systemFeatures.contains('android.software.leanback');
return forceTv?.value == 'true' ||
androidInfo.systemFeatures.contains('android.software.leanback');
}

int getGridCount(BuildContext context) {
Expand Down
3 changes: 1 addition & 2 deletions lib/videos/models/video.dart
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,7 @@ class Video with _$Video implements ShareLinks, IdedVideo {
const factory Video(
{required String videoId,
int? viewCount,
// not used in the code and causes issues
// @JsonKey(fromJson: _parsePublished) int? published,
@JsonKey(fromJson: _parsePublished) int? published,
int? index,
String? indexId,
String? publishedText,
Expand Down
36 changes: 28 additions & 8 deletions lib/videos/models/video.freezed.dart
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,9 @@ Video _$VideoFromJson(Map<String, dynamic> json) {
/// @nodoc
mixin _$Video {
String get videoId => throw _privateConstructorUsedError;
int? get viewCount =>
throw _privateConstructorUsedError; // not used in the code and causes issues
// @JsonKey(fromJson: _parsePublished) int? published,
int? get viewCount => throw _privateConstructorUsedError;
@JsonKey(fromJson: _parsePublished)
int? get published => throw _privateConstructorUsedError;
int? get index => throw _privateConstructorUsedError;
String? get indexId => throw _privateConstructorUsedError;
String? get publishedText => throw _privateConstructorUsedError;
Expand Down Expand Up @@ -88,6 +88,7 @@ abstract class $VideoCopyWith<$Res> {
$Res call(
{String videoId,
int? viewCount,
@JsonKey(fromJson: _parsePublished) int? published,
int? index,
String? indexId,
String? publishedText,
Expand Down Expand Up @@ -149,6 +150,7 @@ class _$VideoCopyWithImpl<$Res, $Val extends Video>
$Res call({
Object? videoId = null,
Object? viewCount = freezed,
Object? published = freezed,
Object? index = freezed,
Object? indexId = freezed,
Object? publishedText = freezed,
Expand Down Expand Up @@ -199,6 +201,10 @@ class _$VideoCopyWithImpl<$Res, $Val extends Video>
? _value.viewCount
: viewCount // ignore: cast_nullable_to_non_nullable
as int?,
published: freezed == published
? _value.published
: published // ignore: cast_nullable_to_non_nullable
as int?,
index: freezed == index
? _value.index
: index // ignore: cast_nullable_to_non_nullable
Expand Down Expand Up @@ -373,6 +379,7 @@ abstract class _$$VideoImplCopyWith<$Res> implements $VideoCopyWith<$Res> {
$Res call(
{String videoId,
int? viewCount,
@JsonKey(fromJson: _parsePublished) int? published,
int? index,
String? indexId,
String? publishedText,
Expand Down Expand Up @@ -432,6 +439,7 @@ class __$$VideoImplCopyWithImpl<$Res>
$Res call({
Object? videoId = null,
Object? viewCount = freezed,
Object? published = freezed,
Object? index = freezed,
Object? indexId = freezed,
Object? publishedText = freezed,
Expand Down Expand Up @@ -482,6 +490,10 @@ class __$$VideoImplCopyWithImpl<$Res>
? _value.viewCount
: viewCount // ignore: cast_nullable_to_non_nullable
as int?,
published: freezed == published
? _value.published
: published // ignore: cast_nullable_to_non_nullable
as int?,
index: freezed == index
? _value.index
: index // ignore: cast_nullable_to_non_nullable
Expand Down Expand Up @@ -652,6 +664,7 @@ class _$VideoImpl extends _Video {
const _$VideoImpl(
{required this.videoId,
this.viewCount,
@JsonKey(fromJson: _parsePublished) this.published,
this.index,
this.indexId,
this.publishedText,
Expand Down Expand Up @@ -715,8 +728,9 @@ class _$VideoImpl extends _Video {
final String videoId;
@override
final int? viewCount;
// not used in the code and causes issues
// @JsonKey(fromJson: _parsePublished) int? published,
@override
@JsonKey(fromJson: _parsePublished)
final int? published;
@override
final int? index;
@override
Expand Down Expand Up @@ -872,7 +886,7 @@ class _$VideoImpl extends _Video {

@override
String toString() {
return 'Video(videoId: $videoId, viewCount: $viewCount, index: $index, indexId: $indexId, publishedText: $publishedText, isUpcoming: $isUpcoming, premiereTimestamp: $premiereTimestamp, dashUrl: $dashUrl, description: $description, descriptionHtml: $descriptionHtml, keywords: $keywords, likeCount: $likeCount, dislikeCount: $dislikeCount, paid: $paid, premium: $premium, isFamilyFriendly: $isFamilyFriendly, allowedRegions: $allowedRegions, genre: $genre, genreUrl: $genreUrl, authorThumbnails: $authorThumbnails, subCountText: $subCountText, allowRatings: $allowRatings, rating: $rating, isListed: $isListed, liveNow: $liveNow, hlsUrl: $hlsUrl, adaptiveFormats: $adaptiveFormats, formatStreams: $formatStreams, captions: $captions, recommendedVideos: $recommendedVideos, title: $title, lengthSeconds: $lengthSeconds, author: $author, authorId: $authorId, authorUrl: $authorUrl, videoThumbnails: $videoThumbnails, filtered: $filtered, matchedFilters: $matchedFilters, filterHide: $filterHide, deArrowed: $deArrowed, deArrowThumbnailUrl: $deArrowThumbnailUrl, viewCountText: $viewCountText)';
return 'Video(videoId: $videoId, viewCount: $viewCount, published: $published, index: $index, indexId: $indexId, publishedText: $publishedText, isUpcoming: $isUpcoming, premiereTimestamp: $premiereTimestamp, dashUrl: $dashUrl, description: $description, descriptionHtml: $descriptionHtml, keywords: $keywords, likeCount: $likeCount, dislikeCount: $dislikeCount, paid: $paid, premium: $premium, isFamilyFriendly: $isFamilyFriendly, allowedRegions: $allowedRegions, genre: $genre, genreUrl: $genreUrl, authorThumbnails: $authorThumbnails, subCountText: $subCountText, allowRatings: $allowRatings, rating: $rating, isListed: $isListed, liveNow: $liveNow, hlsUrl: $hlsUrl, adaptiveFormats: $adaptiveFormats, formatStreams: $formatStreams, captions: $captions, recommendedVideos: $recommendedVideos, title: $title, lengthSeconds: $lengthSeconds, author: $author, authorId: $authorId, authorUrl: $authorUrl, videoThumbnails: $videoThumbnails, filtered: $filtered, matchedFilters: $matchedFilters, filterHide: $filterHide, deArrowed: $deArrowed, deArrowThumbnailUrl: $deArrowThumbnailUrl, viewCountText: $viewCountText)';
}

@override
Expand All @@ -883,6 +897,8 @@ class _$VideoImpl extends _Video {
(identical(other.videoId, videoId) || other.videoId == videoId) &&
(identical(other.viewCount, viewCount) ||
other.viewCount == viewCount) &&
(identical(other.published, published) ||
other.published == published) &&
(identical(other.index, index) || other.index == index) &&
(identical(other.indexId, indexId) || other.indexId == indexId) &&
(identical(other.publishedText, publishedText) ||
Expand Down Expand Up @@ -958,6 +974,7 @@ class _$VideoImpl extends _Video {
runtimeType,
videoId,
viewCount,
published,
index,
indexId,
publishedText,
Expand Down Expand Up @@ -1020,6 +1037,7 @@ abstract class _Video extends Video implements ShareLinks, IdedVideo {
const factory _Video(
{required final String videoId,
final int? viewCount,
@JsonKey(fromJson: _parsePublished) final int? published,
final int? index,
final String? indexId,
final String? publishedText,
Expand Down Expand Up @@ -1072,8 +1090,10 @@ abstract class _Video extends Video implements ShareLinks, IdedVideo {
@override
String get videoId;
@override
int? get viewCount; // not used in the code and causes issues
// @JsonKey(fromJson: _parsePublished) int? published,
int? get viewCount;
@override
@JsonKey(fromJson: _parsePublished)
int? get published;
@override
int? get index;
@override
Expand Down
2 changes: 2 additions & 0 deletions lib/videos/models/video.g.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit caf0168

Please sign in to comment.