mirror of
https://github.com/kodjodevf/mangayomi.git
synced 2026-04-20 19:12:04 +00:00
added default subtitle lang + statistics screen
This commit is contained in:
parent
f0aab34f0c
commit
301220a6a4
12 changed files with 618 additions and 257 deletions
|
|
@ -66,6 +66,7 @@
|
|||
"incognito_mode_description": "Pausiert den Leseverlauf",
|
||||
"download_queue": "Download-Warteschlange",
|
||||
"categories": "Kategorien",
|
||||
"statistics": "Statistiken",
|
||||
"settings": "Einstellungen",
|
||||
"about": "Über",
|
||||
"help": "Hilfe",
|
||||
|
|
@ -83,6 +84,7 @@
|
|||
"general": "Allgemein",
|
||||
"general_subtitle": "App-Sprache",
|
||||
"app_language": "App-Sprache",
|
||||
"default_subtitle_language": "Standard Untertitel-Sprache",
|
||||
"appearance": "Aussehen",
|
||||
"appearance_subtitle": "Thema, Datum- & Zeitformat",
|
||||
"theme": "Thema",
|
||||
|
|
|
|||
|
|
@ -66,6 +66,7 @@
|
|||
"incognito_mode_description": "Pauses reading history",
|
||||
"download_queue": "Download Queue",
|
||||
"categories": "Categories",
|
||||
"statistics": "Statistics",
|
||||
"settings": "Settings",
|
||||
"about": "About",
|
||||
"help": "Help",
|
||||
|
|
@ -83,6 +84,7 @@
|
|||
"general": "General",
|
||||
"general_subtitle": "App language",
|
||||
"app_language": "App language",
|
||||
"default_subtitle_language": "Default subtitle language",
|
||||
"appearance": "Appearance",
|
||||
"appearance_subtitle": "Theme, date & time format",
|
||||
"theme": "Theme",
|
||||
|
|
|
|||
|
|
@ -92,6 +92,8 @@ class Settings {
|
|||
|
||||
L10nLocale? locale;
|
||||
|
||||
L10nLocale? defaultSubtitleLang;
|
||||
|
||||
@enumerated
|
||||
late DisplayType animeDisplayType;
|
||||
|
||||
|
|
@ -427,6 +429,8 @@ class Settings {
|
|||
libraryShowNumbersOfItems = json['libraryShowNumbersOfItems'];
|
||||
locale =
|
||||
json['locale'] != null ? L10nLocale.fromJson(json['locale']) : null;
|
||||
defaultSubtitleLang =
|
||||
json['defaultSubtitleLang'] != null ? L10nLocale.fromJson(json['defaultSubtitleLang']) : null;
|
||||
onlyIncludePinnedSources = json['onlyIncludePinnedSources'];
|
||||
pagePreloadAmount = json['pagePreloadAmount'];
|
||||
if (json['personalPageModeList'] != null) {
|
||||
|
|
@ -616,6 +620,7 @@ class Settings {
|
|||
'libraryShowLanguage': libraryShowLanguage,
|
||||
'libraryShowNumbersOfItems': libraryShowNumbersOfItems,
|
||||
'locale': locale?.toJson(),
|
||||
'defaultSubtitleLang': defaultSubtitleLang?.toJson(),
|
||||
'onlyIncludePinnedSources': onlyIncludePinnedSources,
|
||||
'pagePreloadAmount': pagePreloadAmount,
|
||||
'personalPageModeList':
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -70,7 +70,7 @@ class _AnimePlayerViewState extends riv.ConsumerState<AnimePlayerView> {
|
|||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final l10nLocale = ref.watch(l10nLocaleStateProvider);
|
||||
final defaultSubtitleLang = ref.watch(defaultSubtitleLangStateProvider);
|
||||
final serversData = ref.watch(getVideoListProvider(episode: episode));
|
||||
SystemChrome.setEnabledSystemUIMode(SystemUiMode.immersive);
|
||||
return serversData.when(
|
||||
|
|
@ -94,7 +94,7 @@ class _AnimePlayerViewState extends riv.ConsumerState<AnimePlayerView> {
|
|||
|
||||
return AnimeStreamPage(
|
||||
defaultSubtitle: completeLanguageNameEnglish(
|
||||
l10nLocale.toLanguageTag(),
|
||||
defaultSubtitleLang.toLanguageTag(),
|
||||
),
|
||||
episode: episode,
|
||||
videos: videos,
|
||||
|
|
|
|||
|
|
@ -54,6 +54,13 @@ class MoreScreen extends StatelessWidget {
|
|||
icon: Icons.label_outline_rounded,
|
||||
title: l10n.categories,
|
||||
),
|
||||
ListTileWidget(
|
||||
onTap: () {
|
||||
context.push('/statistics');
|
||||
},
|
||||
icon: Icons.query_stats_outlined,
|
||||
title: l10n.statistics,
|
||||
),
|
||||
ListTileWidget(
|
||||
onTap: () {
|
||||
context.push('/dataAndStorage');
|
||||
|
|
|
|||
|
|
@ -3,14 +3,17 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
|
|||
import 'package:mangayomi/modules/more/settings/player/providers/player_state_provider.dart';
|
||||
import 'package:mangayomi/providers/l10n_providers.dart';
|
||||
import 'package:mangayomi/utils/extensions/build_context_extensions.dart';
|
||||
import 'package:mangayomi/utils/language.dart';
|
||||
import 'package:numberpicker/numberpicker.dart';
|
||||
import 'package:super_sliver_list/super_sliver_list.dart';
|
||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||
|
||||
class PlayerScreen extends ConsumerWidget {
|
||||
const PlayerScreen({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final defaultSubtitleLang = ref.watch(defaultSubtitleLangStateProvider);
|
||||
final markEpisodeAsSeenType = ref.watch(markEpisodeAsSeenTypeStateProvider);
|
||||
final defaultSkipIntroLength = ref.watch(
|
||||
defaultSkipIntroLengthStateProvider,
|
||||
|
|
@ -30,6 +33,67 @@ class PlayerScreen extends ConsumerWidget {
|
|||
body: SingleChildScrollView(
|
||||
child: Column(
|
||||
children: [
|
||||
ListTile(
|
||||
onTap: () {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (context) {
|
||||
return AlertDialog(
|
||||
title: Text(context.l10n.default_subtitle_language),
|
||||
content: SizedBox(
|
||||
width: context.width(0.8),
|
||||
child: SuperListView.builder(
|
||||
shrinkWrap: true,
|
||||
itemCount: AppLocalizations.supportedLocales.length,
|
||||
itemBuilder: (context, index) {
|
||||
final locale =
|
||||
AppLocalizations.supportedLocales[index];
|
||||
return RadioListTile(
|
||||
dense: true,
|
||||
contentPadding: const EdgeInsets.all(0),
|
||||
value: locale,
|
||||
groupValue: defaultSubtitleLang,
|
||||
onChanged: (value) {
|
||||
ref
|
||||
.read(
|
||||
defaultSubtitleLangStateProvider.notifier,
|
||||
)
|
||||
.setLocale(locale);
|
||||
Navigator.pop(context);
|
||||
},
|
||||
title: Text(
|
||||
completeLanguageName(locale.toLanguageTag()),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
actions: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.end,
|
||||
children: [
|
||||
TextButton(
|
||||
onPressed: () async {
|
||||
Navigator.pop(context);
|
||||
},
|
||||
child: Text(
|
||||
context.l10n.cancel,
|
||||
style: TextStyle(color: context.primaryColor),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
);
|
||||
},
|
||||
title: Text(context.l10n.default_subtitle_language),
|
||||
subtitle: Text(
|
||||
completeLanguageName(defaultSubtitleLang.toLanguageTag()),
|
||||
style: TextStyle(fontSize: 11, color: context.secondaryColor),
|
||||
),
|
||||
),
|
||||
ListTile(
|
||||
onTap: () {
|
||||
final values = [100, 95, 90, 85, 80, 75, 70];
|
||||
|
|
|
|||
|
|
@ -1,8 +1,40 @@
|
|||
import 'dart:ui';
|
||||
|
||||
import 'package:mangayomi/main.dart';
|
||||
import 'package:mangayomi/models/settings.dart';
|
||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||
part 'player_state_provider.g.dart';
|
||||
|
||||
@riverpod
|
||||
class DefaultSubtitleLangState extends _$DefaultSubtitleLangState {
|
||||
@override
|
||||
Locale build() {
|
||||
return Locale(
|
||||
_getLocale()!.languageCode ?? "en",
|
||||
_getLocale()!.countryCode ?? "",
|
||||
);
|
||||
}
|
||||
|
||||
L10nLocale? _getLocale() {
|
||||
return isar.settings.getSync(227)!.defaultSubtitleLang ??
|
||||
L10nLocale(languageCode: "en", countryCode: "");
|
||||
}
|
||||
|
||||
void setLocale(Locale locale) async {
|
||||
final settings = isar.settings.getSync(227)!;
|
||||
isar.writeTxnSync(() {
|
||||
isar.settings.putSync(
|
||||
settings
|
||||
..defaultSubtitleLang = L10nLocale(
|
||||
languageCode: locale.languageCode,
|
||||
countryCode: locale.countryCode,
|
||||
),
|
||||
);
|
||||
});
|
||||
state = locale;
|
||||
}
|
||||
}
|
||||
|
||||
@riverpod
|
||||
class MarkEpisodeAsSeenTypeState extends _$MarkEpisodeAsSeenTypeState {
|
||||
@override
|
||||
|
|
|
|||
|
|
@ -6,6 +6,23 @@ part of 'player_state_provider.dart';
|
|||
// RiverpodGenerator
|
||||
// **************************************************************************
|
||||
|
||||
String _$defaultSubtitleLangStateHash() =>
|
||||
r'bec45a4fbd70922b767dbef7c98a423d908ed9d3';
|
||||
|
||||
/// See also [DefaultSubtitleLangState].
|
||||
@ProviderFor(DefaultSubtitleLangState)
|
||||
final defaultSubtitleLangStateProvider =
|
||||
AutoDisposeNotifierProvider<DefaultSubtitleLangState, Locale>.internal(
|
||||
DefaultSubtitleLangState.new,
|
||||
name: r'defaultSubtitleLangStateProvider',
|
||||
debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product')
|
||||
? null
|
||||
: _$defaultSubtitleLangStateHash,
|
||||
dependencies: null,
|
||||
allTransitiveDependencies: null,
|
||||
);
|
||||
|
||||
typedef _$DefaultSubtitleLangState = AutoDisposeNotifier<Locale>;
|
||||
String _$markEpisodeAsSeenTypeStateHash() =>
|
||||
r'94ae90e6bc51bbd4f88dfc9780cc5e9eb4ed5770';
|
||||
|
||||
|
|
|
|||
157
lib/modules/more/statistics/statistics_screen.dart
Normal file
157
lib/modules/more/statistics/statistics_screen.dart
Normal file
|
|
@ -0,0 +1,157 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:isar/isar.dart';
|
||||
import 'package:mangayomi/main.dart';
|
||||
import 'package:mangayomi/models/chapter.dart';
|
||||
import 'package:mangayomi/models/manga.dart';
|
||||
import 'package:mangayomi/providers/l10n_providers.dart';
|
||||
|
||||
class StatisticsScreen extends ConsumerStatefulWidget {
|
||||
const StatisticsScreen({super.key});
|
||||
|
||||
@override
|
||||
ConsumerState<StatisticsScreen> createState() => _StatisticsScreenState();
|
||||
}
|
||||
|
||||
class _StatisticsScreenState extends ConsumerState<StatisticsScreen> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final l10n = context.l10n;
|
||||
final items = isar.mangas.filter().idIsNotNull().findAllSync();
|
||||
final chapters = isar.chapters.filter().idIsNotNull().findAllSync();
|
||||
return Scaffold(
|
||||
appBar: AppBar(title: Text(l10n.statistics)),
|
||||
body: SingleChildScrollView(
|
||||
child: Column(
|
||||
spacing: 3,
|
||||
children: [
|
||||
SizedBox(height: 20,),
|
||||
Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: Card(
|
||||
child: ListTile(
|
||||
title: Text("Total manga", textAlign: TextAlign.center),
|
||||
subtitle: Text(
|
||||
"${items.where((i) => i.itemType == ItemType.manga).length}",
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: Card(
|
||||
child: ListTile(
|
||||
title: Text(
|
||||
"Total chapters",
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
subtitle: Text(
|
||||
"${chapters.where((i) => i.manga.value!.itemType == ItemType.manga).length}",
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: Card(
|
||||
child: ListTile(
|
||||
title: Text("Read chapters", textAlign: TextAlign.center),
|
||||
subtitle: Text(
|
||||
"${chapters.where((i) => i.manga.value!.itemType == ItemType.manga && (i.isRead ?? false)).length}",
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: Card(
|
||||
child: ListTile(
|
||||
title: Text("Total anime", textAlign: TextAlign.center),
|
||||
subtitle: Text(
|
||||
"${items.where((i) => i.itemType == ItemType.anime).length}",
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: Card(
|
||||
child: ListTile(
|
||||
title: Text(
|
||||
"Total episodes",
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
subtitle: Text(
|
||||
"${chapters.where((i) => i.manga.value!.itemType == ItemType.anime).length}",
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: Card(
|
||||
child: ListTile(
|
||||
title: Text(
|
||||
"Watched episodes",
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
subtitle: Text(
|
||||
"${chapters.where((i) => i.manga.value!.itemType == ItemType.anime && (i.isRead ?? false)).length}",
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: Card(
|
||||
child: ListTile(
|
||||
title: Text("Total novels", textAlign: TextAlign.center),
|
||||
subtitle: Text(
|
||||
"${items.where((i) => i.itemType == ItemType.novel).length}",
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: Card(
|
||||
child: ListTile(
|
||||
title: Text(
|
||||
"Total chapters",
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
subtitle: Text(
|
||||
"${chapters.where((i) => i.manga.value!.itemType == ItemType.novel).length}",
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: Card(
|
||||
child: ListTile(
|
||||
title: Text("Read chapters", textAlign: TextAlign.center),
|
||||
subtitle: Text(
|
||||
"${chapters.where((i) => i.manga.value!.itemType == ItemType.novel && (i.isRead ?? false)).length}",
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -16,6 +16,7 @@ import 'package:mangayomi/modules/more/data_and_storage/data_and_storage.dart';
|
|||
import 'package:mangayomi/modules/more/settings/appearance/custom_navigation_settings.dart';
|
||||
import 'package:mangayomi/modules/more/settings/browse/source_repositories.dart';
|
||||
import 'package:mangayomi/modules/more/settings/reader/providers/reader_state_provider.dart';
|
||||
import 'package:mangayomi/modules/more/statistics/statistics_screen.dart';
|
||||
import 'package:mangayomi/modules/novel/novel_reader_view.dart';
|
||||
import 'package:mangayomi/modules/updates/updates_screen.dart';
|
||||
import 'package:mangayomi/modules/more/categories/categories_screen.dart';
|
||||
|
|
@ -430,6 +431,16 @@ class RouterNotifier extends ChangeNotifier {
|
|||
);
|
||||
},
|
||||
),
|
||||
GoRoute(
|
||||
path: "/statistics",
|
||||
name: "statistics",
|
||||
builder: (context, state) {
|
||||
return StatisticsScreen();
|
||||
},
|
||||
pageBuilder: (context, state) {
|
||||
return transitionPage(key: state.pageKey, child: StatisticsScreen());
|
||||
},
|
||||
),
|
||||
GoRoute(
|
||||
path: "/general",
|
||||
name: "general",
|
||||
|
|
|
|||
|
|
@ -121,6 +121,7 @@ final languagesMap = {
|
|||
"Tagalog": "tl",
|
||||
};
|
||||
|
||||
/// this might not always work depending on how every extension provides its subtitles
|
||||
completeLanguageNameEnglish(String lang) {
|
||||
lang = lang.toLowerCase();
|
||||
for (var element in languagesMapEnglish.entries) {
|
||||
|
|
|
|||
Loading…
Reference in a new issue