Files
nsrb a7c6058540 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.
2026-08-29 17:50:31 +07:00

177 lines
3.7 KiB
Dart
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// Shared models and source-adapter contract (port of cxyz `sources.js`).
enum SourceId {
comicland,
mangaread,
mangatown;
String get id => name;
String get label {
switch (this) {
case SourceId.comicland:
return 'ComicLand';
case SourceId.mangaread:
return 'MangaRead';
case SourceId.mangatown:
return 'MangaTown';
}
}
/// Bundled favicon asset (not fetched at runtime).
String get logoAsset => 'assets/sources/$name.png';
static SourceId? tryParse(String raw) {
final key = raw.trim().toLowerCase();
for (final id in SourceId.values) {
if (id.name == key) return id;
}
return null;
}
}
/// Browse menus a source may expose on its Catalog home.
enum CatalogMenuKind {
popular,
latest,
official,
uncensored,
recommended,
search,
hotToday,
hotWeek,
hotMonth,
directory;
String get pathSegment => name;
}
/// Optional directory filters (MangaTown). Segment `0` means All.
class CatalogBrowseParams {
const CatalogBrowseParams({
this.demographic = '0',
this.genre = '0',
this.status = '0',
this.initial = '0',
});
final String demographic;
final String genre;
final String status;
final String initial;
CatalogBrowseParams copyWith({
String? demographic,
String? genre,
String? status,
String? initial,
}) {
return CatalogBrowseParams(
demographic: demographic ?? this.demographic,
genre: genre ?? this.genre,
status: status ?? this.status,
initial: initial ?? this.initial,
);
}
@override
bool operator ==(Object other) {
return other is CatalogBrowseParams &&
other.demographic == demographic &&
other.genre == genre &&
other.status == status &&
other.initial == initial;
}
@override
int get hashCode => Object.hash(demographic, genre, status, initial);
}
class CatalogMenu {
const CatalogMenu({required this.kind, required this.title});
final CatalogMenuKind kind;
final String title;
}
class CatalogComic {
const CatalogComic({
required this.source,
required this.slug,
required this.title,
required this.listingUrl,
this.coverUrl,
this.description,
this.rating,
});
final SourceId source;
final String slug;
final String title;
final String listingUrl;
final String? coverUrl;
final String? description;
final double? rating;
}
class ChapterLink {
const ChapterLink({
required this.url,
required this.title,
required this.chapterKey,
this.chapterNumber,
});
final String url;
final String title;
final String chapterKey;
final String? chapterNumber;
}
class SeriesDetail {
const SeriesDetail({
required this.source,
required this.listingUrl,
required this.slug,
required this.title,
required this.chapters,
this.coverUrl,
this.description,
});
final SourceId source;
final String listingUrl;
final String slug;
final String title;
final String? coverUrl;
final String? description;
final List<ChapterLink> chapters;
}
/// Site adapter: per-source catalog menus + series + page URLs.
abstract class ComicSource {
SourceId get id;
String get displayName;
String get blurb;
/// Menus on this source’s Catalog home. Omit unsupported feeds (e.g. no search).
List<CatalogMenu> get catalogMenus;
/// Headers for page/CDN image requests.
Map<String, String> get imageHeaders;
Future<List<CatalogComic>> loadCatalog(
CatalogMenuKind kind, {
String query = '',
int offset = 0,
int limit = 30,
CatalogBrowseParams? browse,
});
Future<SeriesDetail> fetchSeries(String listingUrl);
Future<List<String>> fetchPageUrls(String chapterUrl);
}