mirror of
https://github.com/kodjodevf/mangayomi.git
synced 2026-04-20 23:22:07 +00:00
added mpv config for Anime4K
This commit is contained in:
parent
5b56578029
commit
1450641f16
36 changed files with 1571 additions and 77 deletions
|
|
@ -12,6 +12,11 @@ class MChapterBridge {
|
|||
url: namedArgs.get<String?>('url'),
|
||||
dateUpload: namedArgs.get<String?>('dateUpload'),
|
||||
scanlator: namedArgs.get<String?>('scanlator'),
|
||||
isFiller: namedArgs.get<bool?>('isFiller'),
|
||||
thumbnailUrl: namedArgs.get<String?>('scanlator'),
|
||||
description: namedArgs.get<String?>('scanlator'),
|
||||
downloadSize: namedArgs.get<String?>('scanlator'),
|
||||
duration: namedArgs.get<String?>('scanlator'),
|
||||
);
|
||||
},
|
||||
},
|
||||
|
|
@ -20,6 +25,11 @@ class MChapterBridge {
|
|||
'url': (visitor, target) => (target as MChapter).url,
|
||||
'dateUpload': (visitor, target) => (target as MChapter).dateUpload,
|
||||
'scanlator': (visitor, target) => (target as MChapter).scanlator,
|
||||
'isFiller': (visitor, target) => (target as MChapter).isFiller,
|
||||
'thumbnailUrl': (visitor, target) => (target as MChapter).thumbnailUrl,
|
||||
'description': (visitor, target) => (target as MChapter).description,
|
||||
'downloadSize': (visitor, target) => (target as MChapter).downloadSize,
|
||||
'duration': (visitor, target) => (target as MChapter).duration,
|
||||
},
|
||||
setters: {
|
||||
'name': (visitor, target, value) =>
|
||||
|
|
@ -30,6 +40,16 @@ class MChapterBridge {
|
|||
(target as MChapter).dateUpload = value as String?,
|
||||
'scanlator': (visitor, target, value) =>
|
||||
(target as MChapter).scanlator = value as String?,
|
||||
'isFiller': (visitor, target, value) =>
|
||||
(target as MChapter).isFiller = value as bool?,
|
||||
'thumbnailUrl': (visitor, target, value) =>
|
||||
(target as MChapter).thumbnailUrl = value as String?,
|
||||
'description': (visitor, target, value) =>
|
||||
(target as MChapter).description = value as String?,
|
||||
'downloadSize': (visitor, target, value) =>
|
||||
(target as MChapter).downloadSize = value as String?,
|
||||
'duration': (visitor, target, value) =>
|
||||
(target as MChapter).duration = value as String?,
|
||||
},
|
||||
);
|
||||
void registerBridgedClasses(D4rt interpreter) {
|
||||
|
|
|
|||
|
|
@ -6,13 +6,41 @@ class MChapter {
|
|||
String? dateUpload;
|
||||
|
||||
String? scanlator;
|
||||
MChapter({this.name, this.url, this.dateUpload, this.scanlator});
|
||||
|
||||
bool? isFiller;
|
||||
|
||||
String? thumbnailUrl;
|
||||
|
||||
String? description;
|
||||
|
||||
/// video size
|
||||
String? downloadSize;
|
||||
|
||||
/// video duration
|
||||
String? duration;
|
||||
|
||||
MChapter({
|
||||
this.name,
|
||||
this.url,
|
||||
this.dateUpload,
|
||||
this.scanlator,
|
||||
this.isFiller = false,
|
||||
this.thumbnailUrl,
|
||||
this.description,
|
||||
this.downloadSize,
|
||||
this.duration,
|
||||
});
|
||||
factory MChapter.fromJson(Map<String, dynamic> json) {
|
||||
return MChapter(
|
||||
name: json['name'],
|
||||
url: json['url'],
|
||||
dateUpload: json['dateUpload'],
|
||||
scanlator: json['scanlator'],
|
||||
isFiller: json['isFiller'] ?? false,
|
||||
thumbnailUrl: json['thumbnailUrl'],
|
||||
description: json['description'],
|
||||
downloadSize: json['downloadSize'],
|
||||
duration: json['duration'],
|
||||
);
|
||||
}
|
||||
Map<String, dynamic> toJson() => {
|
||||
|
|
@ -20,5 +48,10 @@ class MChapter {
|
|||
'url': url,
|
||||
'dateUpload': dateUpload,
|
||||
'scanlator': scanlator,
|
||||
'isFiller': isFiller,
|
||||
'thumbnailUrl': thumbnailUrl,
|
||||
'description': description,
|
||||
'downloadSize': downloadSize,
|
||||
'duration': duration,
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -468,5 +468,8 @@
|
|||
"hide_discord_rpc_incognito": "Hide Discord RPC while in Incognito",
|
||||
"rpc_show_reading_watching_progress": "Show current chapter in Discord (requires a restart)",
|
||||
"rpc_show_title": "Show current title in Discord",
|
||||
"rpc_show_cover_image": "Show current cover image in Discord"
|
||||
"rpc_show_cover_image": "Show current cover image in Discord",
|
||||
"anime4K": "Enable Anime4K",
|
||||
"anime4K_info": "Supports .js scripts under /mpv/scripts/",
|
||||
"anime4K_download": "MPV config files are required!\nDownload now?"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2884,6 +2884,24 @@ abstract class AppLocalizations {
|
|||
/// In en, this message translates to:
|
||||
/// **'Show current cover image in Discord'**
|
||||
String get rpc_show_cover_image;
|
||||
|
||||
/// No description provided for @anime4K.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Enable Anime4K'**
|
||||
String get anime4K;
|
||||
|
||||
/// No description provided for @anime4K_info.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Supports .js scripts under /mpv/scripts/'**
|
||||
String get anime4K_info;
|
||||
|
||||
/// No description provided for @anime4K_download.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'MPV config files are required!\nDownload now?'**
|
||||
String get anime4K_download;
|
||||
}
|
||||
|
||||
class _AppLocalizationsDelegate
|
||||
|
|
|
|||
|
|
@ -1485,4 +1485,14 @@ class AppLocalizationsAr extends AppLocalizations {
|
|||
|
||||
@override
|
||||
String get rpc_show_cover_image => 'Show current cover image in Discord';
|
||||
|
||||
@override
|
||||
String get anime4K => 'Enable Anime4K';
|
||||
|
||||
@override
|
||||
String get anime4K_info => 'Supports .js scripts under /mpv/scripts/';
|
||||
|
||||
@override
|
||||
String get anime4K_download =>
|
||||
'MPV config files are required!\nDownload now?';
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1498,4 +1498,14 @@ class AppLocalizationsDe extends AppLocalizations {
|
|||
|
||||
@override
|
||||
String get rpc_show_cover_image => 'Show current cover image in Discord';
|
||||
|
||||
@override
|
||||
String get anime4K => 'Enable Anime4K';
|
||||
|
||||
@override
|
||||
String get anime4K_info => 'Supports .js scripts under /mpv/scripts/';
|
||||
|
||||
@override
|
||||
String get anime4K_download =>
|
||||
'MPV config files are required!\nDownload now?';
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1486,4 +1486,14 @@ class AppLocalizationsEn extends AppLocalizations {
|
|||
|
||||
@override
|
||||
String get rpc_show_cover_image => 'Show current cover image in Discord';
|
||||
|
||||
@override
|
||||
String get anime4K => 'Enable Anime4K';
|
||||
|
||||
@override
|
||||
String get anime4K_info => 'Supports .js scripts under /mpv/scripts/';
|
||||
|
||||
@override
|
||||
String get anime4K_download =>
|
||||
'MPV config files are required!\nDownload now?';
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1503,6 +1503,16 @@ class AppLocalizationsEs extends AppLocalizations {
|
|||
|
||||
@override
|
||||
String get rpc_show_cover_image => 'Show current cover image in Discord';
|
||||
|
||||
@override
|
||||
String get anime4K => 'Enable Anime4K';
|
||||
|
||||
@override
|
||||
String get anime4K_info => 'Supports .js scripts under /mpv/scripts/';
|
||||
|
||||
@override
|
||||
String get anime4K_download =>
|
||||
'MPV config files are required!\nDownload now?';
|
||||
}
|
||||
|
||||
/// The translations for Spanish Castilian, as used in Latin America and the Caribbean (`es_419`).
|
||||
|
|
|
|||
|
|
@ -1504,4 +1504,14 @@ class AppLocalizationsFr extends AppLocalizations {
|
|||
|
||||
@override
|
||||
String get rpc_show_cover_image => 'Show current cover image in Discord';
|
||||
|
||||
@override
|
||||
String get anime4K => 'Enable Anime4K';
|
||||
|
||||
@override
|
||||
String get anime4K_info => 'Supports .js scripts under /mpv/scripts/';
|
||||
|
||||
@override
|
||||
String get anime4K_download =>
|
||||
'MPV config files are required!\nDownload now?';
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1492,4 +1492,14 @@ class AppLocalizationsId extends AppLocalizations {
|
|||
|
||||
@override
|
||||
String get rpc_show_cover_image => 'Show current cover image in Discord';
|
||||
|
||||
@override
|
||||
String get anime4K => 'Enable Anime4K';
|
||||
|
||||
@override
|
||||
String get anime4K_info => 'Supports .js scripts under /mpv/scripts/';
|
||||
|
||||
@override
|
||||
String get anime4K_download =>
|
||||
'MPV config files are required!\nDownload now?';
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1501,4 +1501,14 @@ class AppLocalizationsIt extends AppLocalizations {
|
|||
|
||||
@override
|
||||
String get rpc_show_cover_image => 'Show current cover image in Discord';
|
||||
|
||||
@override
|
||||
String get anime4K => 'Enable Anime4K';
|
||||
|
||||
@override
|
||||
String get anime4K_info => 'Supports .js scripts under /mpv/scripts/';
|
||||
|
||||
@override
|
||||
String get anime4K_download =>
|
||||
'MPV config files are required!\nDownload now?';
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1500,6 +1500,16 @@ class AppLocalizationsPt extends AppLocalizations {
|
|||
|
||||
@override
|
||||
String get rpc_show_cover_image => 'Show current cover image in Discord';
|
||||
|
||||
@override
|
||||
String get anime4K => 'Enable Anime4K';
|
||||
|
||||
@override
|
||||
String get anime4K_info => 'Supports .js scripts under /mpv/scripts/';
|
||||
|
||||
@override
|
||||
String get anime4K_download =>
|
||||
'MPV config files are required!\nDownload now?';
|
||||
}
|
||||
|
||||
/// The translations for Portuguese, as used in Brazil (`pt_BR`).
|
||||
|
|
|
|||
|
|
@ -1502,4 +1502,14 @@ class AppLocalizationsRu extends AppLocalizations {
|
|||
|
||||
@override
|
||||
String get rpc_show_cover_image => 'Show current cover image in Discord';
|
||||
|
||||
@override
|
||||
String get anime4K => 'Enable Anime4K';
|
||||
|
||||
@override
|
||||
String get anime4K_info => 'Supports .js scripts under /mpv/scripts/';
|
||||
|
||||
@override
|
||||
String get anime4K_download =>
|
||||
'MPV config files are required!\nDownload now?';
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1486,4 +1486,14 @@ class AppLocalizationsTh extends AppLocalizations {
|
|||
|
||||
@override
|
||||
String get rpc_show_cover_image => 'Show current cover image in Discord';
|
||||
|
||||
@override
|
||||
String get anime4K => 'Enable Anime4K';
|
||||
|
||||
@override
|
||||
String get anime4K_info => 'Supports .js scripts under /mpv/scripts/';
|
||||
|
||||
@override
|
||||
String get anime4K_download =>
|
||||
'MPV config files are required!\nDownload now?';
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1492,4 +1492,14 @@ class AppLocalizationsTr extends AppLocalizations {
|
|||
|
||||
@override
|
||||
String get rpc_show_cover_image => 'Show current cover image in Discord';
|
||||
|
||||
@override
|
||||
String get anime4K => 'Enable Anime4K';
|
||||
|
||||
@override
|
||||
String get anime4K_info => 'Supports .js scripts under /mpv/scripts/';
|
||||
|
||||
@override
|
||||
String get anime4K_download =>
|
||||
'MPV config files are required!\nDownload now?';
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1457,4 +1457,14 @@ class AppLocalizationsZh extends AppLocalizations {
|
|||
|
||||
@override
|
||||
String get rpc_show_cover_image => 'Show current cover image in Discord';
|
||||
|
||||
@override
|
||||
String get anime4K => 'Enable Anime4K';
|
||||
|
||||
@override
|
||||
String get anime4K_info => 'Supports .js scripts under /mpv/scripts/';
|
||||
|
||||
@override
|
||||
String get anime4K_download =>
|
||||
'MPV config files are required!\nDownload now?';
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@ import 'package:mangayomi/utils/discord_rpc.dart';
|
|||
import 'package:mangayomi/utils/url_protocol/api.dart';
|
||||
import 'package:mangayomi/modules/more/settings/appearance/providers/theme_provider.dart';
|
||||
import 'package:mangayomi/modules/library/providers/file_scanner.dart';
|
||||
// ignore: depend_on_referenced_packages
|
||||
import 'package:media_kit/media_kit.dart';
|
||||
import 'package:path_provider/path_provider.dart';
|
||||
import 'package:window_manager/window_manager.dart';
|
||||
|
|
|
|||
|
|
@ -26,6 +26,18 @@ class Chapter {
|
|||
///Only for local archive Comic
|
||||
String? archivePath;
|
||||
|
||||
bool? isFiller;
|
||||
|
||||
String? thumbnailUrl;
|
||||
|
||||
String? description;
|
||||
|
||||
/// video size
|
||||
String? downloadSize;
|
||||
|
||||
/// video duration
|
||||
String? duration;
|
||||
|
||||
int? updatedAt;
|
||||
|
||||
final manga = IsarLink<Manga>();
|
||||
|
|
@ -41,6 +53,11 @@ class Chapter {
|
|||
this.isRead = false,
|
||||
this.lastPageRead = '',
|
||||
this.archivePath = '',
|
||||
this.isFiller = false,
|
||||
this.thumbnailUrl,
|
||||
this.description,
|
||||
this.downloadSize,
|
||||
this.duration,
|
||||
this.updatedAt = 0,
|
||||
});
|
||||
|
||||
|
|
@ -55,6 +72,11 @@ class Chapter {
|
|||
name = json['name'];
|
||||
scanlator = json['scanlator'];
|
||||
url = json['url'];
|
||||
isFiller = json['isFiller'] ?? false;
|
||||
thumbnailUrl = json['thumbnailUrl'];
|
||||
description = json['description'];
|
||||
downloadSize = json['downloadSize'];
|
||||
duration = json['duration'];
|
||||
updatedAt = json['updatedAt'];
|
||||
}
|
||||
|
||||
|
|
@ -69,6 +91,11 @@ class Chapter {
|
|||
'name': name,
|
||||
'scanlator': scanlator,
|
||||
'url': url,
|
||||
'isFiller': isFiller,
|
||||
'thumbnailUrl': thumbnailUrl,
|
||||
'description': description,
|
||||
'downloadSize': downloadSize,
|
||||
'duration': duration,
|
||||
'updatedAt': updatedAt ?? 0,
|
||||
};
|
||||
}
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -256,6 +256,8 @@ class Settings {
|
|||
|
||||
bool? rpcShowCoverImage;
|
||||
|
||||
bool? useAnime4K;
|
||||
|
||||
Settings({
|
||||
this.id = 227,
|
||||
this.displayType = DisplayType.compactGrid,
|
||||
|
|
@ -370,6 +372,7 @@ class Settings {
|
|||
this.rpcShowReadingWatchingProgress = true,
|
||||
this.rpcShowTitle = true,
|
||||
this.rpcShowCoverImage = true,
|
||||
this.useAnime4K = false,
|
||||
});
|
||||
|
||||
Settings.fromJson(Map<String, dynamic> json) {
|
||||
|
|
@ -590,6 +593,7 @@ class Settings {
|
|||
rpcShowReadingWatchingProgress = json['rpcShowReadingWatchingProgress'];
|
||||
rpcShowTitle = json['rpcShowTitle'];
|
||||
rpcShowCoverImage = json['rpcShowCoverImage'];
|
||||
useAnime4K = json['useAnime4K'];
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() => {
|
||||
|
|
@ -727,6 +731,7 @@ class Settings {
|
|||
'rpcShowReadingWatchingProgress': rpcShowReadingWatchingProgress,
|
||||
'rpcShowTitle': rpcShowTitle,
|
||||
'rpcShowCoverImage': rpcShowCoverImage,
|
||||
'useAnime4K': useAnime4K,
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -623,18 +623,23 @@ const SettingsSchema = CollectionSchema(
|
|||
name: r'updateProgressAfterReading',
|
||||
type: IsarType.bool,
|
||||
),
|
||||
r'useLibass': PropertySchema(
|
||||
r'useAnime4K': PropertySchema(
|
||||
id: 115,
|
||||
name: r'useAnime4K',
|
||||
type: IsarType.bool,
|
||||
),
|
||||
r'useLibass': PropertySchema(
|
||||
id: 116,
|
||||
name: r'useLibass',
|
||||
type: IsarType.bool,
|
||||
),
|
||||
r'usePageTapZones': PropertySchema(
|
||||
id: 116,
|
||||
id: 117,
|
||||
name: r'usePageTapZones',
|
||||
type: IsarType.bool,
|
||||
),
|
||||
r'userAgent': PropertySchema(
|
||||
id: 117,
|
||||
id: 118,
|
||||
name: r'userAgent',
|
||||
type: IsarType.string,
|
||||
)
|
||||
|
|
@ -1238,9 +1243,10 @@ void _settingsSerialize(
|
|||
writer.writeLong(offsets[112], object.startDatebackup);
|
||||
writer.writeBool(offsets[113], object.themeIsDark);
|
||||
writer.writeBool(offsets[114], object.updateProgressAfterReading);
|
||||
writer.writeBool(offsets[115], object.useLibass);
|
||||
writer.writeBool(offsets[116], object.usePageTapZones);
|
||||
writer.writeString(offsets[117], object.userAgent);
|
||||
writer.writeBool(offsets[115], object.useAnime4K);
|
||||
writer.writeBool(offsets[116], object.useLibass);
|
||||
writer.writeBool(offsets[117], object.usePageTapZones);
|
||||
writer.writeString(offsets[118], object.userAgent);
|
||||
}
|
||||
|
||||
Settings _settingsDeserialize(
|
||||
|
|
@ -1455,9 +1461,10 @@ Settings _settingsDeserialize(
|
|||
startDatebackup: reader.readLongOrNull(offsets[112]),
|
||||
themeIsDark: reader.readBoolOrNull(offsets[113]),
|
||||
updateProgressAfterReading: reader.readBoolOrNull(offsets[114]),
|
||||
useLibass: reader.readBoolOrNull(offsets[115]),
|
||||
usePageTapZones: reader.readBoolOrNull(offsets[116]),
|
||||
userAgent: reader.readStringOrNull(offsets[117]),
|
||||
useAnime4K: reader.readBoolOrNull(offsets[115]),
|
||||
useLibass: reader.readBoolOrNull(offsets[116]),
|
||||
usePageTapZones: reader.readBoolOrNull(offsets[117]),
|
||||
userAgent: reader.readStringOrNull(offsets[118]),
|
||||
);
|
||||
object.chapterFilterBookmarkedList =
|
||||
reader.readObjectList<ChapterFilterBookmarked>(
|
||||
|
|
@ -1850,6 +1857,8 @@ P _settingsDeserializeProp<P>(
|
|||
case 116:
|
||||
return (reader.readBoolOrNull(offset)) as P;
|
||||
case 117:
|
||||
return (reader.readBoolOrNull(offset)) as P;
|
||||
case 118:
|
||||
return (reader.readStringOrNull(offset)) as P;
|
||||
default:
|
||||
throw IsarError('Unknown property with id $propertyId');
|
||||
|
|
@ -9504,6 +9513,33 @@ extension SettingsQueryFilter
|
|||
});
|
||||
}
|
||||
|
||||
QueryBuilder<Settings, Settings, QAfterFilterCondition> useAnime4KIsNull() {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addFilterCondition(const FilterCondition.isNull(
|
||||
property: r'useAnime4K',
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<Settings, Settings, QAfterFilterCondition>
|
||||
useAnime4KIsNotNull() {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addFilterCondition(const FilterCondition.isNotNull(
|
||||
property: r'useAnime4K',
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<Settings, Settings, QAfterFilterCondition> useAnime4KEqualTo(
|
||||
bool? value) {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addFilterCondition(FilterCondition.equalTo(
|
||||
property: r'useAnime4K',
|
||||
value: value,
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<Settings, Settings, QAfterFilterCondition> useLibassIsNull() {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addFilterCondition(const FilterCondition.isNull(
|
||||
|
|
@ -11113,6 +11149,18 @@ extension SettingsQuerySortBy on QueryBuilder<Settings, Settings, QSortBy> {
|
|||
});
|
||||
}
|
||||
|
||||
QueryBuilder<Settings, Settings, QAfterSortBy> sortByUseAnime4K() {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addSortBy(r'useAnime4K', Sort.asc);
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<Settings, Settings, QAfterSortBy> sortByUseAnime4KDesc() {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addSortBy(r'useAnime4K', Sort.desc);
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<Settings, Settings, QAfterSortBy> sortByUseLibass() {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addSortBy(r'useLibass', Sort.asc);
|
||||
|
|
@ -12358,6 +12406,18 @@ extension SettingsQuerySortThenBy
|
|||
});
|
||||
}
|
||||
|
||||
QueryBuilder<Settings, Settings, QAfterSortBy> thenByUseAnime4K() {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addSortBy(r'useAnime4K', Sort.asc);
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<Settings, Settings, QAfterSortBy> thenByUseAnime4KDesc() {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addSortBy(r'useAnime4K', Sort.desc);
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<Settings, Settings, QAfterSortBy> thenByUseLibass() {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addSortBy(r'useLibass', Sort.asc);
|
||||
|
|
@ -13016,6 +13076,12 @@ extension SettingsQueryWhereDistinct
|
|||
});
|
||||
}
|
||||
|
||||
QueryBuilder<Settings, Settings, QDistinct> distinctByUseAnime4K() {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addDistinctBy(r'useAnime4K');
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<Settings, Settings, QDistinct> distinctByUseLibass() {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addDistinctBy(r'useLibass');
|
||||
|
|
@ -13813,6 +13879,12 @@ extension SettingsQueryProperty
|
|||
});
|
||||
}
|
||||
|
||||
QueryBuilder<Settings, bool?, QQueryOperations> useAnime4KProperty() {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addPropertyName(r'useAnime4K');
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<Settings, bool?, QQueryOperations> useLibassProperty() {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addPropertyName(r'useLibass');
|
||||
|
|
|
|||
|
|
@ -1,7 +1,10 @@
|
|||
import 'dart:async';
|
||||
import 'dart:ffi';
|
||||
import 'dart:io';
|
||||
import 'package:bot_toast/bot_toast.dart';
|
||||
import 'package:ffi/ffi.dart';
|
||||
import 'package:file_picker/file_picker.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
|
|
@ -31,6 +34,7 @@ import 'package:mangayomi/services/torrent_server.dart';
|
|||
import 'package:mangayomi/utils/extensions/build_context_extensions.dart';
|
||||
import 'package:mangayomi/utils/language.dart';
|
||||
import 'package:media_kit/media_kit.dart';
|
||||
import 'package:media_kit/generated/libmpv/bindings.dart' as generated;
|
||||
import 'package:media_kit_video/media_kit_video.dart';
|
||||
import 'package:media_kit_video/media_kit_video_controls/src/controls/extensions/duration.dart';
|
||||
import 'package:path/path.dart' as p;
|
||||
|
|
@ -71,7 +75,7 @@ class _AnimePlayerViewState extends riv.ConsumerState<AnimePlayerView> {
|
|||
SystemChrome.setEnabledSystemUIMode(SystemUiMode.immersive);
|
||||
return serversData.when(
|
||||
data: (data) {
|
||||
final (videos, isLocal, infoHashList) = data;
|
||||
final (videos, isLocal, infoHashList, mpvDirectory) = data;
|
||||
_infoHashList = infoHashList;
|
||||
if (videos.isEmpty && !(episode.manga.value!.isLocalArchive ?? false)) {
|
||||
return Scaffold(
|
||||
|
|
@ -99,6 +103,7 @@ class _AnimePlayerViewState extends riv.ConsumerState<AnimePlayerView> {
|
|||
desktopFullScreenPlayer: (value) {
|
||||
desktopFullScreenPlayer = value;
|
||||
},
|
||||
mpvDirectory: mpvDirectory,
|
||||
);
|
||||
},
|
||||
error: (error, stackTrace) => Scaffold(
|
||||
|
|
@ -147,6 +152,7 @@ class AnimeStreamPage extends riv.ConsumerStatefulWidget {
|
|||
final String defaultSubtitle;
|
||||
final bool isLocal;
|
||||
final bool isTorrent;
|
||||
final Directory? mpvDirectory;
|
||||
final void Function(bool) desktopFullScreenPlayer;
|
||||
const AnimeStreamPage({
|
||||
super.key,
|
||||
|
|
@ -156,6 +162,7 @@ class AnimeStreamPage extends riv.ConsumerStatefulWidget {
|
|||
required this.episode,
|
||||
required this.isTorrent,
|
||||
required this.desktopFullScreenPlayer,
|
||||
required this.mpvDirectory,
|
||||
});
|
||||
|
||||
@override
|
||||
|
|
@ -172,8 +179,15 @@ class _AnimeStreamPageState extends riv.ConsumerState<AnimeStreamPage>
|
|||
with TickerProviderStateMixin, WidgetsBindingObserver {
|
||||
late final GlobalKey<VideoState> _key = GlobalKey<VideoState>();
|
||||
late final useLibass = ref.read(useLibassStateProvider);
|
||||
late final useAnime4K = ref.read(useAnime4KStateProvider);
|
||||
late final Player _player = Player(
|
||||
configuration: PlayerConfiguration(libass: useLibass),
|
||||
configuration: PlayerConfiguration(
|
||||
libass: useLibass,
|
||||
config: true,
|
||||
configDir: useAnime4K ? widget.mpvDirectory?.path ?? "" : "",
|
||||
observeProperties: {},
|
||||
eventHandler: _handleMpvEvents,
|
||||
),
|
||||
);
|
||||
late final hwdecMode = ref.read(hwdecModeStateProvider());
|
||||
late final VideoController _controller = VideoController(
|
||||
|
|
@ -246,6 +260,25 @@ class _AnimeStreamPageState extends riv.ConsumerState<AnimeStreamPage>
|
|||
}
|
||||
});
|
||||
|
||||
Future<void> _handleMpvEvents(Pointer<generated.mpv_event> event) async {
|
||||
try {
|
||||
if (event.ref.event_id ==
|
||||
generated.mpv_event_id.MPV_EVENT_PROPERTY_CHANGE) {
|
||||
final prop = event.ref.data.cast<generated.mpv_event_property>();
|
||||
if (prop.ref.name.cast<Utf8>().toDartString() ==
|
||||
"user-data/aniyomi/dummy_number" &&
|
||||
prop.ref.format == generated.mpv_format.MPV_FORMAT_INT64) {
|
||||
final number = prop.ref.data.cast<Int64>().value;
|
||||
botToast("Dummy number: $number");
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
if (kDebugMode) {
|
||||
debugPrint(e.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void pushToNewEpisode(BuildContext context, Chapter episode) {
|
||||
widget.desktopFullScreenPlayer.call(ref.read(fullscreenProvider));
|
||||
if (context.mounted) {
|
||||
|
|
@ -1030,6 +1063,34 @@ class _AnimeStreamPageState extends riv.ConsumerState<AnimeStreamPage>
|
|||
onPressed: () => _videoSettingDraggableMenu(context),
|
||||
icon: const Icon(Icons.video_settings, color: Colors.white),
|
||||
),
|
||||
if (useAnime4K)
|
||||
PopupMenuButton<String>(
|
||||
tooltip: '', // Remove default tooltip "Show menu" for consistency
|
||||
icon: const Icon(Icons.high_quality, color: Colors.white),
|
||||
itemBuilder: (context) =>
|
||||
[
|
||||
("Anime4K: Mode A (Fast)", "CTRL+1"),
|
||||
("Anime4K: Mode B (Fast)", "CTRL+2"),
|
||||
("Anime4K: Mode C (Fast)", "CTRL+3"),
|
||||
("Anime4K: Mode A+A (Fast)", "CTRL+4"),
|
||||
("Anime4K: Mode B+B (Fast)", "CTRL+5"),
|
||||
("Anime4K: Mode C+A (Fast)", "CTRL+6"),
|
||||
("Clear GLSL shaders", "CTRL+0"),
|
||||
]
|
||||
.map(
|
||||
(mode) => PopupMenuItem<String>(
|
||||
value: mode.$1,
|
||||
child: Text(mode.$1),
|
||||
onTap: () {
|
||||
(_player.platform as dynamic).command([
|
||||
"keydown",
|
||||
mode.$2,
|
||||
]);
|
||||
},
|
||||
),
|
||||
)
|
||||
.toList(),
|
||||
),
|
||||
PopupMenuButton<double>(
|
||||
tooltip: '', // Remove default tooltip "Show menu" for consistency
|
||||
icon: const Icon(Icons.speed, color: Colors.white),
|
||||
|
|
|
|||
|
|
@ -215,6 +215,27 @@ class _DesktopControllerWidgetState
|
|||
final desktopFullScreenPlayer = widget.desktopFullScreenPlayer;
|
||||
await _changeFullScreen(ref, desktopFullScreenPlayer, value: false);
|
||||
},
|
||||
const SingleActivator(LogicalKeyboardKey.digit0, control: true): () {
|
||||
(widget.videoController.player.platform as dynamic).command(["keydown", "CTRL+0"]);
|
||||
},
|
||||
const SingleActivator(LogicalKeyboardKey.digit1, control: true): () {
|
||||
(widget.videoController.player.platform as dynamic).command(["keydown", "CTRL+1"]);
|
||||
},
|
||||
const SingleActivator(LogicalKeyboardKey.digit2, control: true): () {
|
||||
(widget.videoController.player.platform as dynamic).command(["keydown", "CTRL+2"]);
|
||||
},
|
||||
const SingleActivator(LogicalKeyboardKey.digit3, control: true): () {
|
||||
(widget.videoController.player.platform as dynamic).command(["keydown", "CTRL+3"]);
|
||||
},
|
||||
const SingleActivator(LogicalKeyboardKey.digit4, control: true): () {
|
||||
(widget.videoController.player.platform as dynamic).command(["keydown", "CTRL+4"]);
|
||||
},
|
||||
const SingleActivator(LogicalKeyboardKey.digit5, control: true): () {
|
||||
(widget.videoController.player.platform as dynamic).command(["keydown", "CTRL+5"]);
|
||||
},
|
||||
const SingleActivator(LogicalKeyboardKey.digit6, control: true): () {
|
||||
(widget.videoController.player.platform as dynamic).command(["keydown", "CTRL+6"]);
|
||||
},
|
||||
},
|
||||
child: Stack(
|
||||
children: [
|
||||
|
|
|
|||
|
|
@ -81,6 +81,11 @@ Future<dynamic> updateMangaDetail(
|
|||
scanlator: chaps[i].scanlator ?? '',
|
||||
mangaId: mangaId,
|
||||
updatedAt: DateTime.now().millisecondsSinceEpoch,
|
||||
isFiller: chaps[i].isFiller,
|
||||
thumbnailUrl: chaps[i].thumbnailUrl,
|
||||
description: chaps[i].description,
|
||||
downloadSize: chaps[i].downloadSize,
|
||||
duration: chaps[i].duration,
|
||||
)..manga.value = manga;
|
||||
chapters.add(chapter);
|
||||
}
|
||||
|
|
@ -115,6 +120,11 @@ Future<dynamic> updateMangaDetail(
|
|||
oldChap.url = newChap.url;
|
||||
oldChap.scanlator = newChap.scanlator;
|
||||
oldChap.updatedAt = DateTime.now().millisecondsSinceEpoch;
|
||||
oldChap.isFiller = newChap.isFiller;
|
||||
oldChap.thumbnailUrl = newChap.thumbnailUrl;
|
||||
oldChap.description = newChap.description;
|
||||
oldChap.downloadSize = newChap.downloadSize;
|
||||
oldChap.duration = newChap.duration;
|
||||
isar.chapters.putSync(oldChap);
|
||||
oldChap.manga.saveSync();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ part of 'update_manga_detail_providers.dart';
|
|||
// RiverpodGenerator
|
||||
// **************************************************************************
|
||||
|
||||
String _$updateMangaDetailHash() => r'ce51918a48b315c3555b3de4e602bd998e00a992';
|
||||
String _$updateMangaDetailHash() => r'f75938777640ae0cfee181a2df7a12a56c42db41';
|
||||
|
||||
/// Copied from Dart SDK
|
||||
class _SystemHash {
|
||||
|
|
|
|||
|
|
@ -1,18 +1,43 @@
|
|||
import 'dart:async';
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:archive/archive.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:http/http.dart' as http;
|
||||
import 'package:mangayomi/modules/more/settings/player/providers/player_state_provider.dart';
|
||||
import 'package:mangayomi/providers/l10n_providers.dart';
|
||||
import 'package:mangayomi/providers/storage_provider.dart';
|
||||
import 'package:mangayomi/utils/extensions/build_context_extensions.dart';
|
||||
import 'package:mangayomi/utils/language.dart';
|
||||
import 'package:numberpicker/numberpicker.dart';
|
||||
import 'package:path/path.dart' as path;
|
||||
import 'package:permission_handler/permission_handler.dart';
|
||||
import 'package:super_sliver_list/super_sliver_list.dart';
|
||||
import 'package:mangayomi/l10n/generated/app_localizations.dart';
|
||||
|
||||
class PlayerScreen extends ConsumerWidget {
|
||||
class PlayerScreen extends ConsumerStatefulWidget {
|
||||
const PlayerScreen({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
ConsumerState<PlayerScreen> createState() => _PlayerScreenState();
|
||||
}
|
||||
|
||||
class _PlayerScreenState extends ConsumerState<PlayerScreen> {
|
||||
int _total = 0;
|
||||
int _received = 0;
|
||||
late http.StreamedResponse _response;
|
||||
final List<int> _bytes = [];
|
||||
late StreamSubscription<List<int>>? _subscription;
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_subscription?.cancel();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final defaultSubtitleLang = ref.watch(defaultSubtitleLangStateProvider);
|
||||
final markEpisodeAsSeenType = ref.watch(markEpisodeAsSeenTypeStateProvider);
|
||||
final defaultSkipIntroLength = ref.watch(
|
||||
|
|
@ -26,6 +51,7 @@ class PlayerScreen extends ConsumerWidget {
|
|||
final enableAutoSkip = ref.watch(enableAutoSkipStateProvider);
|
||||
final aniSkipTimeoutLength = ref.watch(aniSkipTimeoutLengthStateProvider);
|
||||
final useLibass = ref.watch(useLibassStateProvider);
|
||||
final useAnime4K = ref.watch(useAnime4KStateProvider);
|
||||
final hwdecMode = ref.watch(hwdecModeStateProvider(rawValue: true));
|
||||
|
||||
final fullScreenPlayer = ref.watch(fullScreenPlayerStateProvider);
|
||||
|
|
@ -457,6 +483,20 @@ class PlayerScreen extends ConsumerWidget {
|
|||
),
|
||||
],
|
||||
),
|
||||
SwitchListTile(
|
||||
value: useAnime4K,
|
||||
title: Text(context.l10n.anime4K),
|
||||
subtitle: Text(
|
||||
context.l10n.anime4K_info,
|
||||
style: TextStyle(fontSize: 11, color: context.secondaryColor),
|
||||
),
|
||||
onChanged: (value) async {
|
||||
if (value && !(await _checkAnime4K(context))) {
|
||||
return;
|
||||
}
|
||||
ref.read(useAnime4KStateProvider.notifier).set(value);
|
||||
},
|
||||
),
|
||||
SwitchListTile(
|
||||
value: fullScreenPlayer,
|
||||
title: Text(context.l10n.full_screen_player),
|
||||
|
|
@ -501,7 +541,11 @@ class PlayerScreen extends ConsumerWidget {
|
|||
groupValue: hwdecMode,
|
||||
onChanged: (value) {
|
||||
ref
|
||||
.read(hwdecModeStateProvider(rawValue: true).notifier)
|
||||
.read(
|
||||
hwdecModeStateProvider(
|
||||
rawValue: true,
|
||||
).notifier,
|
||||
)
|
||||
.set(value!);
|
||||
Navigator.pop(context);
|
||||
},
|
||||
|
|
@ -547,4 +591,130 @@ class PlayerScreen extends ConsumerWidget {
|
|||
),
|
||||
);
|
||||
}
|
||||
|
||||
Future<bool> _checkAnime4K(BuildContext context) async {
|
||||
var status = await Permission.storage.status;
|
||||
if (!status.isGranted) {
|
||||
await Permission.storage.request();
|
||||
}
|
||||
final provider = StorageProvider();
|
||||
final dir = await provider.getMpvDirectory();
|
||||
final mpvFile = File('${dir!.path}/mpv.conf');
|
||||
final inputFile = File('${dir.path}/input.conf');
|
||||
if (!(await mpvFile.exists()) &&
|
||||
!(await inputFile.exists()) &&
|
||||
context.mounted) {
|
||||
final res = await showDialog(
|
||||
context: context,
|
||||
builder: (context) {
|
||||
return AlertDialog(
|
||||
content: SingleChildScrollView(
|
||||
child: Column(
|
||||
children: [
|
||||
Text(context.l10n.anime4K_download),
|
||||
_total > 0
|
||||
? Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
||||
children: [
|
||||
Flexible(
|
||||
child: LinearProgressIndicator(
|
||||
value: _total > 0
|
||||
? (_received * 1.0) / _total
|
||||
: 0.0,
|
||||
),
|
||||
),
|
||||
Flexible(
|
||||
child: Text(
|
||||
'${(_received / 1048576.0).toStringAsFixed(2)}/${(_total / 1048576.0).toStringAsFixed(2)} MB',
|
||||
),
|
||||
),
|
||||
],
|
||||
)
|
||||
: SizedBox.shrink(),
|
||||
],
|
||||
),
|
||||
),
|
||||
actions: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.end,
|
||||
children: [
|
||||
TextButton(
|
||||
onPressed: () async {
|
||||
try {
|
||||
await _subscription?.cancel();
|
||||
} catch (_) {}
|
||||
if (context.mounted) {
|
||||
Navigator.pop(context);
|
||||
}
|
||||
},
|
||||
child: Text(context.l10n.cancel),
|
||||
),
|
||||
const SizedBox(width: 15),
|
||||
ElevatedButton(
|
||||
onPressed: _total == 0
|
||||
? () async {
|
||||
_response = await http.Client().send(
|
||||
http.Request(
|
||||
'GET',
|
||||
Uri.parse(
|
||||
"https://github.com/Tama47/Anime4K/releases/download/v4.0.1/GLSL_Windows_Low-end.zip",
|
||||
),
|
||||
),
|
||||
);
|
||||
_total = _response.contentLength ?? 0;
|
||||
_subscription = _response.stream.listen((value) {
|
||||
setState(() {
|
||||
_bytes.addAll(value);
|
||||
_received += value.length;
|
||||
});
|
||||
});
|
||||
_subscription?.onDone(() async {
|
||||
final archive = ZipDecoder().decodeBytes(_bytes);
|
||||
String shadersDir = path.join(
|
||||
dir.path,
|
||||
'shaders',
|
||||
);
|
||||
await Directory(
|
||||
shadersDir,
|
||||
).create(recursive: true);
|
||||
String scriptsDir = path.join(
|
||||
dir.path,
|
||||
'scripts',
|
||||
);
|
||||
await Directory(
|
||||
scriptsDir,
|
||||
).create(recursive: true);
|
||||
for (final file in archive.files) {
|
||||
if (file.name == "mpv.conf") {
|
||||
await mpvFile.writeAsBytes(file.content);
|
||||
} else if (file.name == "input.conf") {
|
||||
await inputFile.writeAsBytes(file.content);
|
||||
} else if (file.name.endsWith(".glsl")) {
|
||||
final shaderFile = File(
|
||||
'$shadersDir/${file.name.split("/").last}',
|
||||
);
|
||||
await shaderFile.writeAsBytes(file.content);
|
||||
}
|
||||
}
|
||||
_total = 0;
|
||||
_received = 0;
|
||||
_bytes.clear();
|
||||
if (context.mounted) {
|
||||
Navigator.pop(context, "ok");
|
||||
}
|
||||
});
|
||||
}
|
||||
: null,
|
||||
child: Text(context.l10n.download),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
);
|
||||
return res != null && res == "ok";
|
||||
}
|
||||
return context.mounted;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -183,6 +183,22 @@ class UseLibassState extends _$UseLibassState {
|
|||
}
|
||||
}
|
||||
|
||||
@riverpod
|
||||
class UseAnime4KState extends _$UseAnime4KState {
|
||||
@override
|
||||
bool build() {
|
||||
return isar.settings.getSync(227)!.useAnime4K ?? false;
|
||||
}
|
||||
|
||||
void set(bool value) {
|
||||
final settings = isar.settings.getSync(227);
|
||||
state = value;
|
||||
isar.writeTxnSync(
|
||||
() => isar.settings.putSync(settings!..useAnime4K = value),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
final hwdecs = {
|
||||
"no": ["all"],
|
||||
"auto": ["all"],
|
||||
|
|
|
|||
|
|
@ -175,6 +175,22 @@ final useLibassStateProvider =
|
|||
);
|
||||
|
||||
typedef _$UseLibassState = AutoDisposeNotifier<bool>;
|
||||
String _$useAnime4KStateHash() => r'3902552d399794bf7c78d5f18adcf59f267b3cf6';
|
||||
|
||||
/// See also [UseAnime4KState].
|
||||
@ProviderFor(UseAnime4KState)
|
||||
final useAnime4KStateProvider =
|
||||
AutoDisposeNotifierProvider<UseAnime4KState, bool>.internal(
|
||||
UseAnime4KState.new,
|
||||
name: r'useAnime4KStateProvider',
|
||||
debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product')
|
||||
? null
|
||||
: _$useAnime4KStateHash,
|
||||
dependencies: null,
|
||||
allTransitiveDependencies: null,
|
||||
);
|
||||
|
||||
typedef _$UseAnime4KState = AutoDisposeNotifier<bool>;
|
||||
String _$hwdecModeStateHash() => r'e8b8e2b378eb9ac687bd8dad5637a816ad33fedb';
|
||||
|
||||
/// Copied from Dart SDK
|
||||
|
|
|
|||
|
|
@ -61,6 +61,13 @@ class StorageProvider {
|
|||
return directory;
|
||||
}
|
||||
|
||||
Future<Directory?> getMpvDirectory() async {
|
||||
final defaultDirectory = await getDefaultDirectory();
|
||||
String dbDir = path.join(defaultDirectory!.path, 'mpv');
|
||||
await Directory(dbDir).create(recursive: true);
|
||||
return Directory(dbDir);
|
||||
}
|
||||
|
||||
Future<Directory?> getBtDirectory() async {
|
||||
final gefaultDirectory = await getDefaultDirectory();
|
||||
String dbDir = path.join(gefaultDirectory!.path, 'torrents');
|
||||
|
|
|
|||
|
|
@ -13,11 +13,12 @@ import 'package:path/path.dart' as p;
|
|||
part 'get_video_list.g.dart';
|
||||
|
||||
@riverpod
|
||||
Future<(List<Video>, bool, List<String>)> getVideoList(
|
||||
Future<(List<Video>, bool, List<String>, Directory?)> getVideoList(
|
||||
Ref ref, {
|
||||
required Chapter episode,
|
||||
}) async {
|
||||
final storageProvider = StorageProvider();
|
||||
final mpvDirectory = await storageProvider.getMpvDirectory();
|
||||
final mangaDirectory = await storageProvider.getMangaMainDirectory(episode);
|
||||
final isLocalArchive =
|
||||
episode.manga.value!.isLocalArchive! &&
|
||||
|
|
@ -52,6 +53,7 @@ Future<(List<Video>, bool, List<String>)> getVideoList(
|
|||
[Video(path!, episode.name!, path, subtitles: subtitles)],
|
||||
true,
|
||||
infoHashes,
|
||||
mpvDirectory
|
||||
);
|
||||
}
|
||||
final source = getSource(
|
||||
|
|
@ -68,7 +70,7 @@ Future<(List<Video>, bool, List<String>)> getVideoList(
|
|||
episode.url,
|
||||
episode.archivePath,
|
||||
);
|
||||
return (videos, false, [infohash ?? ""]);
|
||||
return (videos, false, [infohash ?? ""], mpvDirectory);
|
||||
}
|
||||
|
||||
try {
|
||||
|
|
@ -91,7 +93,7 @@ Future<(List<Video>, bool, List<String>)> getVideoList(
|
|||
}
|
||||
}
|
||||
}
|
||||
return (torrentList, false, infoHashes);
|
||||
return (torrentList, false, infoHashes, mpvDirectory);
|
||||
}
|
||||
|
||||
List<Video> list = await getExtensionService(
|
||||
|
|
@ -105,5 +107,5 @@ Future<(List<Video>, bool, List<String>)> getVideoList(
|
|||
}
|
||||
}
|
||||
|
||||
return (videos, false, infoHashes);
|
||||
return (videos, false, infoHashes, mpvDirectory);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ part of 'get_video_list.dart';
|
|||
// RiverpodGenerator
|
||||
// **************************************************************************
|
||||
|
||||
String _$getVideoListHash() => r'74838334ee25412c4a3f151bc598705145bb659c';
|
||||
String _$getVideoListHash() => r'140ac1ca572d6220b7791c4350a0b32e275535a4';
|
||||
|
||||
/// Copied from Dart SDK
|
||||
class _SystemHash {
|
||||
|
|
@ -35,7 +35,7 @@ const getVideoListProvider = GetVideoListFamily();
|
|||
|
||||
/// See also [getVideoList].
|
||||
class GetVideoListFamily
|
||||
extends Family<AsyncValue<(List<Video>, bool, List<String>)>> {
|
||||
extends Family<AsyncValue<(List<Video>, bool, List<String>, Directory?)>> {
|
||||
/// See also [getVideoList].
|
||||
const GetVideoListFamily();
|
||||
|
||||
|
|
@ -73,8 +73,8 @@ class GetVideoListFamily
|
|||
}
|
||||
|
||||
/// See also [getVideoList].
|
||||
class GetVideoListProvider
|
||||
extends AutoDisposeFutureProvider<(List<Video>, bool, List<String>)> {
|
||||
class GetVideoListProvider extends AutoDisposeFutureProvider<
|
||||
(List<Video>, bool, List<String>, Directory?)> {
|
||||
/// See also [getVideoList].
|
||||
GetVideoListProvider({
|
||||
required Chapter episode,
|
||||
|
|
@ -109,7 +109,7 @@ class GetVideoListProvider
|
|||
|
||||
@override
|
||||
Override overrideWith(
|
||||
FutureOr<(List<Video>, bool, List<String>)> Function(
|
||||
FutureOr<(List<Video>, bool, List<String>, Directory?)> Function(
|
||||
GetVideoListRef provider)
|
||||
create,
|
||||
) {
|
||||
|
|
@ -128,8 +128,8 @@ class GetVideoListProvider
|
|||
}
|
||||
|
||||
@override
|
||||
AutoDisposeFutureProviderElement<(List<Video>, bool, List<String>)>
|
||||
createElement() {
|
||||
AutoDisposeFutureProviderElement<
|
||||
(List<Video>, bool, List<String>, Directory?)> createElement() {
|
||||
return _GetVideoListProviderElement(this);
|
||||
}
|
||||
|
||||
|
|
@ -149,15 +149,14 @@ class GetVideoListProvider
|
|||
|
||||
@Deprecated('Will be removed in 3.0. Use Ref instead')
|
||||
// ignore: unused_element
|
||||
mixin GetVideoListRef
|
||||
on AutoDisposeFutureProviderRef<(List<Video>, bool, List<String>)> {
|
||||
mixin GetVideoListRef on AutoDisposeFutureProviderRef<
|
||||
(List<Video>, bool, List<String>, Directory?)> {
|
||||
/// The parameter `episode` of this provider.
|
||||
Chapter get episode;
|
||||
}
|
||||
|
||||
class _GetVideoListProviderElement
|
||||
extends AutoDisposeFutureProviderElement<(List<Video>, bool, List<String>)>
|
||||
with GetVideoListRef {
|
||||
class _GetVideoListProviderElement extends AutoDisposeFutureProviderElement<
|
||||
(List<Video>, bool, List<String>, Directory?)> with GetVideoListRef {
|
||||
_GetVideoListProviderElement(super.provider);
|
||||
|
||||
@override
|
||||
|
|
|
|||
|
|
@ -1,3 +1,6 @@
|
|||
import 'dart:ffi';
|
||||
import 'package:ffi/ffi.dart';
|
||||
|
||||
extension StringExtensions on String {
|
||||
String substringAfter(String pattern) {
|
||||
final startIndex = indexOf(pattern);
|
||||
|
|
@ -73,3 +76,22 @@ extension StringExtensions on String {
|
|||
].any((extension) => toLowerCase().endsWith(extension));
|
||||
}
|
||||
}
|
||||
|
||||
extension NativeStringExtensions on List<String> {
|
||||
Pointer<Pointer<Int8>> strListToPointer() {
|
||||
final strings = this;
|
||||
List<Pointer<Int8>> int8PointerList = strings
|
||||
.map((str) => str.toNativeUtf8().cast<Int8>())
|
||||
.toList();
|
||||
|
||||
final Pointer<Pointer<Int8>> pointerPointer = malloc.allocate(
|
||||
int8PointerList.length,
|
||||
);
|
||||
|
||||
strings.asMap().forEach((index, utf) {
|
||||
pointerPointer[index] = int8PointerList[index];
|
||||
});
|
||||
|
||||
return pointerPointer;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@
|
|||
#include <media_kit_video/media_kit_video_plugin.h>
|
||||
#include <screen_retriever_linux/screen_retriever_linux_plugin.h>
|
||||
#include <url_launcher_linux/url_launcher_plugin.h>
|
||||
#include <volume_controller/volume_controller_plugin.h>
|
||||
#include <window_manager/window_manager_plugin.h>
|
||||
#include <window_to_front/window_to_front_plugin.h>
|
||||
|
||||
|
|
@ -42,6 +43,9 @@ void fl_register_plugins(FlPluginRegistry* registry) {
|
|||
g_autoptr(FlPluginRegistrar) url_launcher_linux_registrar =
|
||||
fl_plugin_registry_get_registrar_for_plugin(registry, "UrlLauncherPlugin");
|
||||
url_launcher_plugin_register_with_registrar(url_launcher_linux_registrar);
|
||||
g_autoptr(FlPluginRegistrar) volume_controller_registrar =
|
||||
fl_plugin_registry_get_registrar_for_plugin(registry, "VolumeControllerPlugin");
|
||||
volume_controller_plugin_register_with_registrar(volume_controller_registrar);
|
||||
g_autoptr(FlPluginRegistrar) window_manager_registrar =
|
||||
fl_plugin_registry_get_registrar_for_plugin(registry, "WindowManagerPlugin");
|
||||
window_manager_plugin_register_with_registrar(window_manager_registrar);
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ list(APPEND FLUTTER_PLUGIN_LIST
|
|||
media_kit_video
|
||||
screen_retriever_linux
|
||||
url_launcher_linux
|
||||
volume_controller
|
||||
window_manager
|
||||
window_to_front
|
||||
)
|
||||
|
|
|
|||
21
pubspec.lock
21
pubspec.lock
|
|
@ -1160,12 +1160,13 @@ packages:
|
|||
source: hosted
|
||||
version: "0.5.3"
|
||||
media_kit:
|
||||
dependency: "direct main"
|
||||
dependency: transitive
|
||||
description:
|
||||
name: media_kit
|
||||
sha256: "48c10c3785df5d88f0eef970743f8c99b2e5da2b34b9d8f9876e598f62d9e776"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
path: media_kit
|
||||
ref: HEAD
|
||||
resolved-ref: "746465b7914fa524781813dc6e50ea87dcd686e5"
|
||||
url: "https://github.com/Schnitzel5/media-kit.git"
|
||||
source: git
|
||||
version: "1.2.0"
|
||||
media_kit_libs_android_video:
|
||||
dependency: transitive
|
||||
|
|
@ -1219,9 +1220,9 @@ packages:
|
|||
dependency: "direct main"
|
||||
description:
|
||||
path: media_kit_video
|
||||
ref: aeb29faa8ea93a386ad1185b69fd6225fa331c74
|
||||
resolved-ref: aeb29faa8ea93a386ad1185b69fd6225fa331c74
|
||||
url: "https://github.com/media-kit/media-kit.git"
|
||||
ref: HEAD
|
||||
resolved-ref: "746465b7914fa524781813dc6e50ea87dcd686e5"
|
||||
url: "https://github.com/Schnitzel5/media-kit.git"
|
||||
source: git
|
||||
version: "1.3.0"
|
||||
meta:
|
||||
|
|
@ -2081,10 +2082,10 @@ packages:
|
|||
dependency: transitive
|
||||
description:
|
||||
name: volume_controller
|
||||
sha256: e82fd689bb8e1fe8e64be3fa5946ff8699058f8cf9f4c1679acdba20cda7f5bd
|
||||
sha256: d75039e69c0d90e7810bfd47e3eedf29ff8543ea7a10392792e81f9bded7edf5
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.3.3"
|
||||
version: "3.4.0"
|
||||
wakelock_plus:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
|
|||
|
|
@ -41,12 +41,10 @@ dependencies:
|
|||
flutter_web_auth_2: ^3.1.2
|
||||
numberpicker: ^2.1.2
|
||||
encrypt: ^5.0.3
|
||||
media_kit: ^1.2.0
|
||||
media_kit_video:
|
||||
git:
|
||||
url: https://github.com/media-kit/media-kit.git
|
||||
url: https://github.com/Schnitzel5/media-kit.git
|
||||
path: media_kit_video
|
||||
ref: aeb29faa8ea93a386ad1185b69fd6225fa331c74
|
||||
media_kit_libs_video: ^1.0.6
|
||||
crypto: ^3.0.6
|
||||
cupertino_icons: ^1.0.8
|
||||
|
|
@ -157,4 +155,3 @@ inno_bundle:
|
|||
- german
|
||||
admin: false
|
||||
version: 0.6.3
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue