feat: add Cloud Save settings page (UI only)

- Add cloud upload settings to settings model (provider, URL, credentials, path)
- Create CloudSettingsPage with WebDAV and SFTP provider options
- Add Cloud Save menu item in main settings
- Add localization strings for cloud settings
- Actual upload implementation will come in v3.4.0

Settings fields added:
- cloudUploadEnabled: toggle auto-upload
- cloudProvider: 'webdav', 'sftp', or 'none'
- cloudServerUrl: server URL
- cloudUsername/cloudPassword: credentials
- cloudRemotePath: destination folder path
This commit is contained in:
zarzet
2026-02-02 07:20:15 +07:00
parent 5e19178bc0
commit 8c201b5b4a
21 changed files with 2793 additions and 3040 deletions
+29
View File
@@ -36,6 +36,14 @@ class AppSettings {
final bool useAllFilesAccess; // Android 13+ only: enable MANAGE_EXTERNAL_STORAGE
final bool autoExportFailedDownloads; // Auto export failed downloads to TXT file
final String downloadNetworkMode; // 'any' = WiFi + Mobile, 'wifi_only' = WiFi only
// Cloud Upload Settings
final bool cloudUploadEnabled; // Enable auto-upload after download
final String cloudProvider; // 'none', 'webdav', 'sftp', 'gdrive'
final String cloudServerUrl; // WebDAV/SFTP server URL
final String cloudUsername; // Server username
final String cloudPassword; // Server password (encrypted)
final String cloudRemotePath; // Remote folder path (e.g. /Music/SpotiFLAC)
const AppSettings({
this.defaultService = 'tidal',
@@ -70,6 +78,13 @@ class AppSettings {
this.useAllFilesAccess = false,
this.autoExportFailedDownloads = false,
this.downloadNetworkMode = 'any',
// Cloud Upload defaults
this.cloudUploadEnabled = false,
this.cloudProvider = 'none',
this.cloudServerUrl = '',
this.cloudUsername = '',
this.cloudPassword = '',
this.cloudRemotePath = '/Music/SpotiFLAC',
});
AppSettings copyWith({
@@ -106,6 +121,13 @@ class AppSettings {
bool? useAllFilesAccess,
bool? autoExportFailedDownloads,
String? downloadNetworkMode,
// Cloud Upload
bool? cloudUploadEnabled,
String? cloudProvider,
String? cloudServerUrl,
String? cloudUsername,
String? cloudPassword,
String? cloudRemotePath,
}) {
return AppSettings(
defaultService: defaultService ?? this.defaultService,
@@ -140,6 +162,13 @@ class AppSettings {
useAllFilesAccess: useAllFilesAccess ?? this.useAllFilesAccess,
autoExportFailedDownloads: autoExportFailedDownloads ?? this.autoExportFailedDownloads,
downloadNetworkMode: downloadNetworkMode ?? this.downloadNetworkMode,
// Cloud Upload
cloudUploadEnabled: cloudUploadEnabled ?? this.cloudUploadEnabled,
cloudProvider: cloudProvider ?? this.cloudProvider,
cloudServerUrl: cloudServerUrl ?? this.cloudServerUrl,
cloudUsername: cloudUsername ?? this.cloudUsername,
cloudPassword: cloudPassword ?? this.cloudPassword,
cloudRemotePath: cloudRemotePath ?? this.cloudRemotePath,
);
}
+12
View File
@@ -42,6 +42,12 @@ AppSettings _$AppSettingsFromJson(Map<String, dynamic> json) => AppSettings(
autoExportFailedDownloads:
json['autoExportFailedDownloads'] as bool? ?? false,
downloadNetworkMode: json['downloadNetworkMode'] as String? ?? 'any',
cloudUploadEnabled: json['cloudUploadEnabled'] as bool? ?? false,
cloudProvider: json['cloudProvider'] as String? ?? 'none',
cloudServerUrl: json['cloudServerUrl'] as String? ?? '',
cloudUsername: json['cloudUsername'] as String? ?? '',
cloudPassword: json['cloudPassword'] as String? ?? '',
cloudRemotePath: json['cloudRemotePath'] as String? ?? '/Music/SpotiFLAC',
);
Map<String, dynamic> _$AppSettingsToJson(AppSettings instance) =>
@@ -78,4 +84,10 @@ Map<String, dynamic> _$AppSettingsToJson(AppSettings instance) =>
'useAllFilesAccess': instance.useAllFilesAccess,
'autoExportFailedDownloads': instance.autoExportFailedDownloads,
'downloadNetworkMode': instance.downloadNetworkMode,
'cloudUploadEnabled': instance.cloudUploadEnabled,
'cloudProvider': instance.cloudProvider,
'cloudServerUrl': instance.cloudServerUrl,
'cloudUsername': instance.cloudUsername,
'cloudPassword': instance.cloudPassword,
'cloudRemotePath': instance.cloudRemotePath,
};