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,129 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:drift/drift.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
|
||||
import '../data/database.dart';
|
||||
import '../services/cbz_store.dart';
|
||||
import '../services/download_queue.dart';
|
||||
import '../services/image_headers.dart';
|
||||
import '../services/ntfy_notifier.dart';
|
||||
import '../services/peek_mode.dart';
|
||||
import '../services/reader_direction.dart';
|
||||
import '../services/webdav_sync.dart';
|
||||
import '../sources/registry.dart';
|
||||
|
||||
final sourceRegistryProvider = Provider<SourceRegistry>((ref) {
|
||||
return SourceRegistry();
|
||||
});
|
||||
|
||||
final databaseProvider = Provider<AppDatabase>((ref) {
|
||||
final db = AppDatabase();
|
||||
ref.onDispose(db.close);
|
||||
return db;
|
||||
});
|
||||
|
||||
final cbzStoreProvider = Provider<CbzStore>((ref) => CbzStore());
|
||||
|
||||
final ntfyNotifierProvider = Provider<NtfyNotifier>((ref) {
|
||||
return NtfyNotifier(store: ref.watch(cbzStoreProvider));
|
||||
});
|
||||
|
||||
final downloadQueueProvider = ChangeNotifierProvider<DownloadQueue>((ref) {
|
||||
final queue = DownloadQueue(
|
||||
db: ref.watch(databaseProvider),
|
||||
sources: ref.watch(sourceRegistryProvider),
|
||||
store: ref.watch(cbzStoreProvider),
|
||||
ntfy: ref.watch(ntfyNotifierProvider),
|
||||
);
|
||||
// Clear leftover queue rows for chapters already on disk (e.g. older builds).
|
||||
unawaited(queue.reconcileStaleJobs());
|
||||
return queue;
|
||||
});
|
||||
|
||||
/// Per-request headers come from [ComicCover] / reader via `httpHeaders`.
|
||||
final imageCacheManagerProvider = Provider<HeaderCacheManager>((ref) {
|
||||
return HeaderCacheManager(const {});
|
||||
});
|
||||
|
||||
final libraryTitlesProvider = StreamProvider<List<Title>>((ref) {
|
||||
final db = ref.watch(databaseProvider);
|
||||
return (db.select(db.titles)
|
||||
..where((t) => t.inLibrary.equals(true))
|
||||
..orderBy([(t) => OrderingTerm.asc(t.title)]))
|
||||
.watch();
|
||||
});
|
||||
|
||||
final historyTitlesProvider = StreamProvider<List<Title>>((ref) {
|
||||
final db = ref.watch(databaseProvider);
|
||||
return (db.select(db.titles)
|
||||
..where((t) => t.lastReadAt.isNotNull())
|
||||
..orderBy([(t) => OrderingTerm.desc(t.lastReadAt)]))
|
||||
.watch();
|
||||
});
|
||||
|
||||
final queueJobsProvider = StreamProvider<List<QueueJobView>>((ref) {
|
||||
final db = ref.watch(databaseProvider);
|
||||
return db.watchQueueJobs();
|
||||
});
|
||||
|
||||
final downloadedSeriesProvider =
|
||||
StreamProvider<List<DownloadedSeriesGroup>>((ref) {
|
||||
final db = ref.watch(databaseProvider);
|
||||
return db.watchDownloadedSeries();
|
||||
});
|
||||
|
||||
class PeekModeNotifier extends StateNotifier<bool> {
|
||||
PeekModeNotifier() : super(false) {
|
||||
_load();
|
||||
}
|
||||
|
||||
Future<void> _load() async {
|
||||
state = await PeekMode.load();
|
||||
}
|
||||
|
||||
Future<void> toggle() async {
|
||||
state = !state;
|
||||
await PeekMode.save(state);
|
||||
}
|
||||
|
||||
Future<void> setEnabled(bool enabled) async {
|
||||
state = enabled;
|
||||
await PeekMode.save(enabled);
|
||||
}
|
||||
}
|
||||
|
||||
final peekModeProvider =
|
||||
StateNotifierProvider<PeekModeNotifier, bool>((ref) => PeekModeNotifier());
|
||||
|
||||
class ReadingDirectionNotifier extends StateNotifier<ReadingDirection> {
|
||||
ReadingDirectionNotifier() : super(ReadingDirection.ltr) {
|
||||
_load();
|
||||
}
|
||||
|
||||
Future<void> _load() async {
|
||||
state = await ReaderDirection.load();
|
||||
}
|
||||
|
||||
Future<void> setDirection(ReadingDirection direction) async {
|
||||
state = direction;
|
||||
await ReaderDirection.save(direction);
|
||||
}
|
||||
|
||||
Future<void> toggle() async {
|
||||
await setDirection(
|
||||
state == ReadingDirection.ltr
|
||||
? ReadingDirection.rtl
|
||||
: ReadingDirection.ltr,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
final readingDirectionProvider =
|
||||
StateNotifierProvider<ReadingDirectionNotifier, ReadingDirection>(
|
||||
(ref) => ReadingDirectionNotifier(),
|
||||
);
|
||||
|
||||
final webDavSyncProvider = Provider<WebDavSyncService>((ref) {
|
||||
return WebDavSyncService(ref.watch(databaseProvider));
|
||||
});
|
||||
Reference in New Issue
Block a user