import 'package:json_annotation/json_annotation.dart'; part 'downloader_config.g.dart'; @JsonSerializable(explicitToJson: true) class DownloaderConfig { String downloadDir; int maxRunning; ProtocolConfig protocolConfig = ProtocolConfig(); ExtraConfig extra = ExtraConfig(); ProxyConfig proxy = ProxyConfig(); WebhookConfig webhook = WebhookConfig(); ScriptConfig script = ScriptConfig(); AutoTorrentConfig autoTorrent = AutoTorrentConfig(); ArchiveConfig archive = ArchiveConfig(); ApiServerConfig api = ApiServerConfig(); bool autoStartTasks; bool autoDeleteMissingFileTasks; DownloaderConfig({ this.downloadDir = '', this.maxRunning = 0, this.autoStartTasks = false, this.autoDeleteMissingFileTasks = false, }); factory DownloaderConfig.fromJson(Map json) => _$DownloaderConfigFromJson(json); Map toJson() => _$DownloaderConfigToJson(this); } @JsonSerializable() class ApiServerConfig { bool enable; bool mcpEnable; String network; String address; String token; ApiServerConfig({ this.enable = false, this.mcpEnable = false, this.network = 'tcp', this.address = '127.0.0.1:9999', this.token = '', }); factory ApiServerConfig.fromJson(Map? json) => json == null ? ApiServerConfig() : _$ApiServerConfigFromJson(json); Map toJson() => _$ApiServerConfigToJson(this); } @JsonSerializable(explicitToJson: true) class ProtocolConfig { HttpConfig http = HttpConfig(); BtConfig bt = BtConfig(); Ed2kConfig ed2k = Ed2kConfig(); ProtocolConfig(); factory ProtocolConfig.fromJson(Map? json) => json == null ? ProtocolConfig() : _$ProtocolConfigFromJson(json); Map toJson() => _$ProtocolConfigToJson(this); } @JsonSerializable() class HttpConfig { String userAgent; int connections; bool useServerCtime; HttpConfig({this.userAgent = '', this.connections = 0, this.useServerCtime = false}); factory HttpConfig.fromJson(Map json) => _$HttpConfigFromJson(json); Map toJson() => _$HttpConfigToJson(this); } @JsonSerializable() class BtConfig { int listenPort; List trackers; bool seedKeep; double seedRatio; int seedTime; BtConfig({ this.listenPort = 0, this.trackers = const [], this.seedKeep = false, this.seedRatio = 0, this.seedTime = 0, }); factory BtConfig.fromJson(Map json) => _$BtConfigFromJson(json); Map toJson() => _$BtConfigToJson(this); } @JsonSerializable() class Ed2kConfig { int listenPort; int udpPort; String serverAddr; String serverMet; String nodesDat; Ed2kConfig({this.listenPort = 0, this.udpPort = 0, this.serverAddr = '', this.serverMet = '', this.nodesDat = ''}); factory Ed2kConfig.fromJson(Map json) => _$Ed2kConfigFromJson(json); Map toJson() => _$Ed2kConfigToJson(this); } @JsonSerializable(explicitToJson: true) class ExtraConfig { String themeMode; String themeColor; String locale; bool lastDeleteTaskKeep; bool defaultDirectDownload; bool defaultBtClient; bool notifyWhenNewVersion; bool desktopNotification; bool backgroundLocationKeepAlive; WindowStateConfig windowState; Map bookmarks; List createHistory; bool runAsMenubarApp; bool analyticsEnabled; String analyticsClientId; List downloadCategories; ExtraConfigBt bt = ExtraConfigBt(); ExtraConfigGithubMirror githubMirror = ExtraConfigGithubMirror(); ExtraConfig({ this.themeMode = '', this.themeColor = 'green', this.locale = '', this.lastDeleteTaskKeep = false, this.defaultDirectDownload = false, this.defaultBtClient = true, this.notifyWhenNewVersion = true, this.desktopNotification = true, this.backgroundLocationKeepAlive = false, WindowStateConfig? windowState, this.bookmarks = const {}, this.createHistory = const [], this.runAsMenubarApp = false, this.analyticsEnabled = true, this.analyticsClientId = '', this.downloadCategories = const [], }) : windowState = windowState ?? WindowStateConfig(); factory ExtraConfig.fromJson(Map? json) => json == null ? ExtraConfig() : _$ExtraConfigFromJson(json); Map toJson() => _$ExtraConfigToJson(this); } @JsonSerializable() class WindowStateConfig { bool isMaximized; double? width; double? height; WindowStateConfig({this.isMaximized = false, this.width, this.height}); factory WindowStateConfig.fromJson(Map? json) => json == null ? WindowStateConfig() : _$WindowStateConfigFromJson(json); Map toJson() => _$WindowStateConfigToJson(this); } @JsonSerializable() class DownloadCategory { String name; String path; bool isBuiltIn; String? nameKey; // i18n key for built-in categories (e.g., 'categoryMusic') bool isDeleted; // Mark built-in categories as deleted instead of removing them DownloadCategory({ required this.name, required this.path, this.isBuiltIn = false, this.nameKey, this.isDeleted = false, }); factory DownloadCategory.fromJson(Map json) => _$DownloadCategoryFromJson(json); Map toJson() => _$DownloadCategoryToJson(this); } @JsonSerializable() class WebhookConfig { bool enable; List urls; WebhookConfig({this.enable = false, this.urls = const []}); factory WebhookConfig.fromJson(Map? json) => json == null ? WebhookConfig() : _$WebhookConfigFromJson(json); Map toJson() => _$WebhookConfigToJson(this); } @JsonSerializable() class ScriptConfig { bool enable; List paths; ScriptConfig({this.enable = false, this.paths = const []}); factory ScriptConfig.fromJson(Map? json) => json == null ? ScriptConfig() : _$ScriptConfigFromJson(json); Map toJson() => _$ScriptConfigToJson(this); } @JsonSerializable() class ProxyConfig { bool enable; bool system; String scheme; String host; String usr; String pwd; ProxyConfig({ this.enable = false, this.system = false, this.scheme = '', this.host = '', this.usr = '', this.pwd = '', }); factory ProxyConfig.fromJson(Map json) => _$ProxyConfigFromJson(json); Map toJson() => _$ProxyConfigToJson(this); } @JsonSerializable() class ExtraConfigBt { List trackerSubscribeUrls = []; List subscribeTrackers = []; bool autoUpdateTrackers = true; DateTime? lastTrackerUpdateTime; List customTrackers = []; ExtraConfigBt(); factory ExtraConfigBt.fromJson(Map json) => _$ExtraConfigBtFromJson(json); Map toJson() => _$ExtraConfigBtToJson(this); } enum GithubMirrorType { jsdelivr, ghProxy } @JsonSerializable() class GithubMirror { GithubMirrorType type; String url; bool isBuiltIn; bool isDeleted; GithubMirror({required this.type, required this.url, this.isBuiltIn = false, this.isDeleted = false}); factory GithubMirror.fromJson(Map json) => _$GithubMirrorFromJson(json); Map toJson() => _$GithubMirrorToJson(this); } @JsonSerializable(explicitToJson: true) class ExtraConfigGithubMirror { bool enabled; List mirrors; ExtraConfigGithubMirror({this.enabled = true, this.mirrors = const []}); factory ExtraConfigGithubMirror.fromJson(Map? json) => json == null ? ExtraConfigGithubMirror() : _$ExtraConfigGithubMirrorFromJson(json); Map toJson() => _$ExtraConfigGithubMirrorToJson(this); } @JsonSerializable() class AutoTorrentConfig { bool enable; bool deleteAfterDownload; AutoTorrentConfig({this.enable = false, this.deleteAfterDownload = false}); factory AutoTorrentConfig.fromJson(Map? json) => json == null ? AutoTorrentConfig() : _$AutoTorrentConfigFromJson(json); Map toJson() => _$AutoTorrentConfigToJson(this); } @JsonSerializable() class ArchiveConfig { bool autoExtract; bool deleteAfterExtract; ArchiveConfig({this.autoExtract = true, this.deleteAfterExtract = true}); factory ArchiveConfig.fromJson(Map? json) => json == null ? ArchiveConfig() : _$ArchiveConfigFromJson(json); Map toJson() => _$ArchiveConfigToJson(this); }