Add cxyz Android project structure and initial configuration
- Introduced a new Flutter project for the cxyz Android manga/comic reader, including essential files such as pubspec.yaml, AndroidManifest.xml, and Gradle configuration. - Added .gitignore files to exclude unnecessary files and directories for both the main project and Android-specific files. - Implemented initial README.md with project description, features, setup instructions, and API details for ComicLand, MangaRead, and MangaTown. - Configured analysis options and dependencies in pubspec.yaml to support Flutter development. - Established a pnpm workspace and lockfile for dependency management. - Included various Android resources such as icons, styles, and launch backgrounds for a complete application setup.
This commit is contained in:
@@ -0,0 +1,92 @@
|
||||
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
|
||||
class WebDavSettings {
|
||||
static const _kEnabled = 'webdav_enabled';
|
||||
static const _kUrl = 'webdav_url';
|
||||
static const _kUsername = 'webdav_username';
|
||||
static const _kPath = 'webdav_path';
|
||||
static const _kLastSync = 'webdav_last_sync';
|
||||
static const _kLastError = 'webdav_last_error';
|
||||
static const _kLastStatus = 'webdav_last_status';
|
||||
static const _passwordKey = 'webdav_password';
|
||||
|
||||
static const defaultPath = '/cxyz/progress.json';
|
||||
|
||||
static const _secure = FlutterSecureStorage();
|
||||
|
||||
final bool enabled;
|
||||
final String url;
|
||||
final String username;
|
||||
final String password;
|
||||
final String path;
|
||||
final DateTime? lastSyncAt;
|
||||
final String? lastError;
|
||||
final String? lastStatus;
|
||||
|
||||
const WebDavSettings({
|
||||
required this.enabled,
|
||||
required this.url,
|
||||
required this.username,
|
||||
required this.password,
|
||||
required this.path,
|
||||
this.lastSyncAt,
|
||||
this.lastError,
|
||||
this.lastStatus,
|
||||
});
|
||||
|
||||
bool get isConfigured =>
|
||||
url.trim().isNotEmpty && username.trim().isNotEmpty;
|
||||
|
||||
static Future<WebDavSettings> load() async {
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
final password = await _secure.read(key: _passwordKey) ?? '';
|
||||
final lastSyncRaw = prefs.getString(_kLastSync);
|
||||
return WebDavSettings(
|
||||
enabled: prefs.getBool(_kEnabled) ?? false,
|
||||
url: prefs.getString(_kUrl) ?? '',
|
||||
username: prefs.getString(_kUsername) ?? '',
|
||||
password: password,
|
||||
path: prefs.getString(_kPath) ?? defaultPath,
|
||||
lastSyncAt:
|
||||
lastSyncRaw == null ? null : DateTime.tryParse(lastSyncRaw),
|
||||
lastError: prefs.getString(_kLastError),
|
||||
lastStatus: prefs.getString(_kLastStatus),
|
||||
);
|
||||
}
|
||||
|
||||
static Future<void> save({
|
||||
required bool enabled,
|
||||
required String url,
|
||||
required String username,
|
||||
required String password,
|
||||
required String path,
|
||||
}) async {
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
await prefs.setBool(_kEnabled, enabled);
|
||||
await prefs.setString(_kUrl, url.trim());
|
||||
await prefs.setString(_kUsername, username.trim());
|
||||
await prefs.setString(
|
||||
_kPath,
|
||||
path.trim().isEmpty ? defaultPath : path.trim(),
|
||||
);
|
||||
await _secure.write(key: _passwordKey, value: password);
|
||||
}
|
||||
|
||||
static Future<void> setSyncResult({
|
||||
String? status,
|
||||
String? error,
|
||||
DateTime? syncedAt,
|
||||
}) async {
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
if (status != null) await prefs.setString(_kLastStatus, status);
|
||||
if (error != null) {
|
||||
await prefs.setString(_kLastError, error);
|
||||
} else {
|
||||
await prefs.remove(_kLastError);
|
||||
}
|
||||
if (syncedAt != null) {
|
||||
await prefs.setString(_kLastSync, syncedAt.toUtc().toIso8601String());
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user