Files
2026-07-14 11:11:36 +08:00

281 lines
9.0 KiB
Dart

import 'package:freezed_annotation/freezed_annotation.dart';
part 'script_widget.freezed.dart';
part 'script_widget.g.dart';
@freezed
abstract class ScriptWidgetOption with _$ScriptWidgetOption {
const factory ScriptWidgetOption({
@Default('') String title,
@JsonKey(fromJson: _stringFromAny) @Default('') String value,
}) = _ScriptWidgetOption;
factory ScriptWidgetOption.fromJson(Map<String, dynamic> json) =>
_$ScriptWidgetOptionFromJson(json);
}
@freezed
abstract class ScriptWidgetBelongTo with _$ScriptWidgetBelongTo {
const factory ScriptWidgetBelongTo({
@Default('') String paramName,
@JsonKey(fromJson: _stringListFromAny)
@Default(<String>[])
List<String> value,
}) = _ScriptWidgetBelongTo;
factory ScriptWidgetBelongTo.fromJson(Map<String, dynamic> json) =>
_$ScriptWidgetBelongToFromJson(json);
}
@freezed
abstract class ScriptWidgetParam with _$ScriptWidgetParam {
const factory ScriptWidgetParam({
required String name,
@Default('') String title,
@Default('input') String type,
@Default('') String description,
Object? value,
ScriptWidgetBelongTo? belongTo,
@Default(<ScriptWidgetOption>[]) List<ScriptWidgetOption> placeholders,
@Default(<ScriptWidgetOption>[]) List<ScriptWidgetOption> enumOptions,
}) = _ScriptWidgetParam;
factory ScriptWidgetParam.fromJson(Map<String, dynamic> json) =>
_$ScriptWidgetParamFromJson(json);
}
Map<String, Object?> buildScriptWidgetParameterDefaults(
List<ScriptWidgetParam> parameters,
) {
return <String, Object?>{
for (final parameter in parameters)
parameter.name: _resolveScriptWidgetParameterDefault(parameter),
};
}
Object? _resolveScriptWidgetParameterDefault(ScriptWidgetParam parameter) {
if (parameter.value != null) return parameter.value;
if (parameter.enumOptions.isNotEmpty) {
return parameter.enumOptions.first.value;
}
if (parameter.placeholders.isNotEmpty) {
return parameter.placeholders.first.value;
}
return '';
}
@freezed
abstract class ScriptWidgetModule with _$ScriptWidgetModule {
const factory ScriptWidgetModule({
@Default('') String id,
required String title,
@Default('') String description,
@Default(false) bool requiresWebView,
required String functionName,
@Default(false) bool sectionMode,
@Default(3600) int cacheDuration,
@Default('list') String type,
@Default(<ScriptWidgetParam>[]) List<ScriptWidgetParam> params,
}) = _ScriptWidgetModule;
factory ScriptWidgetModule.fromJson(Map<String, dynamic> json) =>
_$ScriptWidgetModuleFromJson(json);
}
@freezed
abstract class ScriptWidgetManifest with _$ScriptWidgetManifest {
const factory ScriptWidgetManifest({
required String id,
required String title,
@Default('') String description,
@Default('') String author,
@Default('') String site,
@Default('0.0.0') String version,
@Default('0.0.1') String requiredVersion,
@Default(60) int detailCacheDuration,
@Default(<ScriptWidgetParam>[]) List<ScriptWidgetParam> globalParams,
@Default(<ScriptWidgetModule>[]) List<ScriptWidgetModule> modules,
ScriptWidgetModule? search,
}) = _ScriptWidgetManifest;
factory ScriptWidgetManifest.fromJson(Map<String, dynamic> json) =>
_$ScriptWidgetManifestFromJson(json);
}
@freezed
abstract class ScriptVideoPerson with _$ScriptVideoPerson {
const factory ScriptVideoPerson({
@JsonKey(fromJson: _stringFromAny) @Default('') String id,
@Default('') String title,
@Default('') String avatar,
@Default('') String role,
}) = _ScriptVideoPerson;
factory ScriptVideoPerson.fromJson(Map<String, dynamic> json) =>
_$ScriptVideoPersonFromJson(json);
}
@freezed
abstract class ScriptVideoGenre with _$ScriptVideoGenre {
const factory ScriptVideoGenre({
@JsonKey(fromJson: _stringFromAny) @Default('') String id,
@Default('') String title,
}) = _ScriptVideoGenre;
factory ScriptVideoGenre.fromJson(Map<String, dynamic> json) =>
_$ScriptVideoGenreFromJson(json);
}
@freezed
abstract class ScriptVideoTrailer with _$ScriptVideoTrailer {
const factory ScriptVideoTrailer({
@Default('') String coverUrl,
@Default('') String url,
}) = _ScriptVideoTrailer;
factory ScriptVideoTrailer.fromJson(Map<String, dynamic> json) =>
_$ScriptVideoTrailerFromJson(json);
}
@freezed
abstract class ScriptVideoItem with _$ScriptVideoItem {
const factory ScriptVideoItem({
@JsonKey(fromJson: _stringFromAny) required String id,
@Default('link') String type,
@Default('') String title,
@Default('') String coverUrl,
@JsonKey(readValue: _readPosterPath) @Default('') String posterPath,
@Default('') String detailPoster,
@Default('') String backdropPath,
@Default(<String>[]) List<String> backdropPaths,
@Default('') String releaseDate,
@Default('') String mediaType,
@JsonKey(fromJson: _doubleFromAny) double? rating,
@Default('') String genreTitle,
@Default(<ScriptVideoGenre>[]) List<ScriptVideoGenre> genreItems,
@Default(<ScriptVideoPerson>[]) List<ScriptVideoPerson> peoples,
@JsonKey(fromJson: _intFromAny) int? duration,
@Default('') String durationText,
@Default('') String previewUrl,
@Default(<ScriptVideoTrailer>[]) List<ScriptVideoTrailer> trailers,
@Default('') String videoUrl,
@Default('') String link,
@JsonKey(fromJson: _intFromAny) int? episode,
@Default('') String description,
@Default('app') String playerType,
@Default(<ScriptVideoItem>[]) List<ScriptVideoItem> childItems,
@Default(<ScriptVideoItem>[]) List<ScriptVideoItem> episodeItems,
@Default(<ScriptVideoItem>[]) List<ScriptVideoItem> relatedItems,
}) = _ScriptVideoItem;
factory ScriptVideoItem.fromJson(Map<String, dynamic> json) =>
_$ScriptVideoItemFromJson(json);
}
@freezed
abstract class ScriptVideoResource with _$ScriptVideoResource {
const factory ScriptVideoResource({
@Default('') String name,
@Default('') String description,
required String url,
@JsonKey(readValue: _readResourceHeaders)
@Default(<String, String>{})
Map<String, String> customHeaders,
@Default('app') String playerType,
}) = _ScriptVideoResource;
factory ScriptVideoResource.fromJson(Map<String, dynamic> json) =>
_$ScriptVideoResourceFromJson(json);
}
@freezed
abstract class InstalledScriptWidget with _$InstalledScriptWidget {
const factory InstalledScriptWidget({
required ScriptWidgetManifest manifest,
required String scriptSource,
@Default('') String sourceUrl,
@Default(true) bool enabled,
@Default(<String, Object?>{}) Map<String, Object?> globalParams,
required DateTime installedAt,
required DateTime updatedAt,
}) = _InstalledScriptWidget;
factory InstalledScriptWidget.fromJson(Map<String, dynamic> json) =>
_$InstalledScriptWidgetFromJson(json);
}
@freezed
abstract class ScriptWidgetCatalogEntry with _$ScriptWidgetCatalogEntry {
const factory ScriptWidgetCatalogEntry({
required String id,
required String title,
@Default('') String description,
@Default('') String requiredVersion,
@Default('') String version,
@Default('') String author,
required String url,
}) = _ScriptWidgetCatalogEntry;
factory ScriptWidgetCatalogEntry.fromJson(Map<String, dynamic> json) =>
_$ScriptWidgetCatalogEntryFromJson(json);
}
@freezed
abstract class ScriptWidgetCatalog with _$ScriptWidgetCatalog {
const factory ScriptWidgetCatalog({
required String title,
@Default('') String description,
@Default('') String icon,
@Default(<ScriptWidgetCatalogEntry>[])
List<ScriptWidgetCatalogEntry> widgets,
}) = _ScriptWidgetCatalog;
factory ScriptWidgetCatalog.fromJson(Map<String, dynamic> json) =>
_$ScriptWidgetCatalogFromJson(json);
}
@freezed
abstract class ScriptWidgetSubscription with _$ScriptWidgetSubscription {
const factory ScriptWidgetSubscription({
required String url,
required ScriptWidgetCatalog catalog,
required DateTime refreshedAt,
}) = _ScriptWidgetSubscription;
factory ScriptWidgetSubscription.fromJson(Map<String, dynamic> json) =>
_$ScriptWidgetSubscriptionFromJson(json);
}
String _stringFromAny(Object? value) => value?.toString() ?? '';
int? _intFromAny(Object? value) {
if (value is num) return value.toInt();
return int.tryParse(value?.toString() ?? '');
}
double? _doubleFromAny(Object? value) {
if (value is num) return value.toDouble();
return double.tryParse(value?.toString() ?? '');
}
List<String> _stringListFromAny(Object? value) {
if (value is List) {
return value.map((item) => item.toString()).toList(growable: false);
}
if (value == null) return const <String>[];
return <String>[value.toString()];
}
Object? _readPosterPath(Map<dynamic, dynamic> json, String key) {
return json[key] ?? json['posterUrl'] ?? json['poster_url'];
}
Object? _readResourceHeaders(Map<dynamic, dynamic> json, String key) {
final value = json[key] ?? json['headers'];
if (value is! Map) return const <String, String>{};
return <String, String>{
for (final entry in value.entries)
entry.key.toString(): entry.value.toString(),
};
}