diff --git a/violet/assets/locale/en.json b/violet/assets/locale/en.json index 98058f24e..897e7ce66 100644 --- a/violet/assets/locale/en.json +++ b/violet/assets/locale/en.json @@ -66,8 +66,8 @@ "useinnerstorage": "Use Inner Storage", "default": "Default", "read": "Read", - "artists": "Artists", - "groups": "Groups", + "artist": "Artists", + "group": "Groups", "tags": "Tags", "series": "Series", "character": "Character", diff --git a/violet/assets/locale/eo.json b/violet/assets/locale/eo.json index 24a099fe7..27b8336f6 100644 --- a/violet/assets/locale/eo.json +++ b/violet/assets/locale/eo.json @@ -66,8 +66,8 @@ "useinnerstorage": "Use Inner Storage", "default": "Default", "read": "Leer", - "artists": "Artistas", - "groups": "Grupos", + "artist": "Artistas", + "group": "Grupos", "tags": "Etiquetas", "series": "Series", "character": "Personajes", diff --git a/violet/assets/locale/it.json b/violet/assets/locale/it.json index 9f73e184a..2cd9588b8 100644 --- a/violet/assets/locale/it.json +++ b/violet/assets/locale/it.json @@ -66,8 +66,8 @@ "useinnerstorage": "Use Inner Storage", "default": "Default", "read": "Leggi", - "artists": "Artisti", - "groups": "Gruppi", + "artist": "Artisti", + "group": "Gruppi", "tags": "Tags", "series": "Serie", "character": "Personaggi", diff --git a/violet/assets/locale/ja.json b/violet/assets/locale/ja.json index 78ec97fdd..d28790966 100644 --- a/violet/assets/locale/ja.json +++ b/violet/assets/locale/ja.json @@ -66,8 +66,8 @@ "useinnerstorage": "内部ストレージを使う", "default": "Default", "read": "読む", - "artists": "アーティスト", - "groups": "グループ", + "artist": "アーティスト", + "group": "グループ", "tags": "タグ", "series": "シリーズ", "character": "キャラクター", diff --git a/violet/assets/locale/ko.json b/violet/assets/locale/ko.json index 07e990cd1..d4f8ff58f 100644 --- a/violet/assets/locale/ko.json +++ b/violet/assets/locale/ko.json @@ -66,8 +66,8 @@ "useinnerstorage": "내부 저장소 사용", "default": "기본값", "read": "읽기", - "artists": "작가", - "groups": "그룹", + "artist": "작가", + "group": "그룹", "tags": "태그", "series": "시리즈", "character": "캐릭터", diff --git a/violet/assets/locale/pt.json b/violet/assets/locale/pt.json index 9228e0506..70fd3ba5a 100644 --- a/violet/assets/locale/pt.json +++ b/violet/assets/locale/pt.json @@ -66,8 +66,8 @@ "useinnerstorage": "Usar armazenamento interno", "default": "Padrão", "read": "Ler", - "artists": "Artistas", - "groups": "Grupos", + "artist": "Artistas", + "group": "Grupos", "tags": "Tags", "series": "Series", "character": "Personagem", diff --git a/violet/assets/locale/zh.json b/violet/assets/locale/zh.json index 2224d9d80..4c586b2d5 100644 --- a/violet/assets/locale/zh.json +++ b/violet/assets/locale/zh.json @@ -66,8 +66,8 @@ "useinnerstorage": "Use Inner Storage", "default": "Default", "read": "Read", - "artists": "Artists", - "groups": "Groups", + "artist": "Artists", + "group": "Groups", "tags": "Tags", "series": "Series", "character": "Character", diff --git a/violet/assets/locale/zh_Hans.json b/violet/assets/locale/zh_Hans.json index 24cca0f17..bd909793d 100644 --- a/violet/assets/locale/zh_Hans.json +++ b/violet/assets/locale/zh_Hans.json @@ -66,8 +66,8 @@ "useinnerstorage": "Use Inner Storage", "default": "Default", "read": "阅读", - "artists": "作者", - "groups": "团体", + "artist": "作者", + "group": "团体", "tags": "标签", "series": "系列", "character": "角色", diff --git a/violet/assets/locale/zh_Hant.json b/violet/assets/locale/zh_Hant.json index 53ff783a3..e9d06cae6 100644 --- a/violet/assets/locale/zh_Hant.json +++ b/violet/assets/locale/zh_Hant.json @@ -66,8 +66,8 @@ "useinnerstorage": "Use Inner Storage", "default": "Default", "read": "Read", - "artists": "Artists", - "groups": "Groups", + "artist": "Artists", + "group": "Groups", "tags": "Tags", "series": "Series", "character": "Character", diff --git a/violet/lib/database/user/bookmark.dart b/violet/lib/database/user/bookmark.dart index c82088508..a98f6eb44 100644 --- a/violet/lib/database/user/bookmark.dart +++ b/violet/lib/database/user/bookmark.dart @@ -61,6 +61,42 @@ class BookmarkArticle { } } +enum ArtistType { artist, group, uploader, series, character } + +extension ArtistTypeExtension on ArtistType { + bool get isGroup => this == ArtistType.group; + bool get isUploader => this == ArtistType.uploader; + bool get isCharacter => this == ArtistType.character; + bool get isSeries => this == ArtistType.series; +} + +class ArtistTypeHelper { + static ArtistType? fromString(String name) { + switch (name.toLowerCase()) { + case 'artist': + case 'artists': + return ArtistType.artist; + + case 'group': + case 'groups': + return ArtistType.group; + + case 'uploader': + case 'uploaders': + return ArtistType.uploader; + + case 'series': + return ArtistType.series; + + case 'character': + case 'characters': + return ArtistType.character; + } + + return null; + } +} + class BookmarkArtist { Map result; BookmarkArtist({required this.result}); @@ -72,7 +108,8 @@ class BookmarkArtist { // 2: uploader // 3: series // 4: character - int type() => result['IsGroup']; // backward compatibility + ArtistType type() => + ArtistType.values[result['IsGroup']]; // backward compatibility String datetime() => result['DateTime']; int group() => result['GroupId']; @@ -233,17 +270,17 @@ class Bookmark { bookmarkSet!.add(int.parse(article)); } - Future insertArtist(String artist, int isgroup, + Future insertArtist(String artist, ArtistType type, [DateTime? datetime, int group = 1]) async { datetime ??= DateTime.now(); var db = await CommonUserDatabase.getInstance(); await db.insert('BookmarkArtist', { 'Artist': artist, - 'IsGroup': isgroup, + 'IsGroup': type.index, 'DateTime': datetime.toString(), 'GroupId': group, }); - bookmarkArtistSet![isgroup]!.add(artist); + bookmarkArtistSet![type]!.add(artist); } Future insertUser(String user, @@ -454,17 +491,15 @@ class Bookmark { bookmarkSet!.remove(id); } - Map>? bookmarkArtistSet; - Future isBookmarkArtist(String name, int type) async { + Map>? bookmarkArtistSet; + Future isBookmarkArtist(String name, ArtistType type) async { if (bookmarkArtistSet == null) { - var artist = await getArtist(); - bookmarkArtistSet = >{}; - bookmarkArtistSet![0] = HashSet(); - bookmarkArtistSet![1] = HashSet(); - bookmarkArtistSet![2] = HashSet(); - bookmarkArtistSet![3] = HashSet(); - bookmarkArtistSet![4] = HashSet(); - for (var element in artist) { + final artist = await getArtist(); + bookmarkArtistSet = >{}; + for (final type in ArtistType.values) { + bookmarkArtistSet![type] = HashSet(); + } + for (final element in artist) { bookmarkArtistSet![element.type()]!.add(element.artist()); } } @@ -498,19 +533,18 @@ class Bookmark { return historyUserSet!.contains(user); } - Future bookmarkArtist(String name, int type, [int group = 1]) async { + Future bookmarkArtist(String name, ArtistType type, + [int group = 1]) async { if (await isBookmarkArtist(name, type)) return; bookmarkArtistSet![type]!.add(name); await insertArtist(name, type, null, group); } - Future unbookmarkArtist(String name, int type) async { + Future unbookmarkArtist(String name, ArtistType type) async { if (!await isBookmarkArtist(name, type)) return; var db = await CommonUserDatabase.getInstance(); await db.delete('BookmarkArtist', 'Artist=? AND IsGroup=?', [name, type]); bookmarkArtistSet![type]!.remove(name); - - print('delete $name, $type'); } Future bookmarkUser(String user, [int group = 1]) async { diff --git a/violet/lib/pages/article_info/article_info_page.dart b/violet/lib/pages/article_info/article_info_page.dart index c8ed8f4fc..afafd29dc 100644 --- a/violet/lib/pages/article_info/article_info_page.dart +++ b/violet/lib/pages/article_info/article_info_page.dart @@ -22,6 +22,7 @@ import 'package:violet/component/eh/eh_parser.dart'; import 'package:violet/component/hitomi/related.dart'; import 'package:violet/component/hitomi/tag_translate.dart'; import 'package:violet/database/query.dart'; +import 'package:violet/database/user/bookmark.dart'; import 'package:violet/database/user/download.dart'; import 'package:violet/database/user/record.dart'; import 'package:violet/locale/locale.dart'; @@ -372,22 +373,22 @@ class TagInfoAreaWidget extends StatelessWidget { 'language'), MultiChipWidget( queryResult.artists(), - Translations.of(context).trans('artists'), + Translations.of(context).trans('artist'), queryResult.artists() != null ? (queryResult.artists() as String) .split('|') .where((element) => element != '') - .map((e) => Tuple2('artists', e)) + .map((e) => Tuple2('artist', e)) .toList() : []), MultiChipWidget( queryResult.groups(), - Translations.of(context).trans('groups'), + Translations.of(context).trans('group'), queryResult.groups() != null ? (queryResult.groups() as String) .split('|') .where((element) => element != '') - .map((e) => Tuple2('groups', e)) + .map((e) => Tuple2('group', e)) .toList() : []), MultiChipWidget( @@ -924,14 +925,14 @@ class _Chip extends StatelessWidget { size: 18.0, color: Colors.white, ); - } else if (group == 'artists') { + } else if (group == 'artist') { mustHasMorePad = false; avatar = const Icon( MdiIcons.account, size: 18.0, color: Colors.white, ); - } else if (group == 'groups') { + } else if (group == 'group') { mustHasMorePad = false; avatar = const Icon( MdiIcons.accountGroup, @@ -989,21 +990,11 @@ class _Chip extends StatelessWidget { } }, onTap: () async { - if ((group == 'groups' || - group == 'artists' || - group == 'uploader' || - group == 'series' || - group == 'character') && - name.toLowerCase() != 'n/a') { + final type = ArtistTypeHelper.fromString(group); + if (type != null && name.toLowerCase() != 'n/a') { PlatformNavigator.navigateSlide( context, - ArtistInfoPage( - isGroup: group == 'groups', - isUploader: group == 'uploader', - isCharacter: group == 'character', - isSeries: group == 'series', - artist: name, - ), + ArtistInfoPage(name: name, type: type), ); } else if (group == 'id') { Clipboard.setData(ClipboardData(text: name)); diff --git a/violet/lib/pages/artist_info/artist_info_page.dart b/violet/lib/pages/artist_info/artist_info_page.dart index 0674784ce..ce87727a4 100644 --- a/violet/lib/pages/artist_info/artist_info_page.dart +++ b/violet/lib/pages/artist_info/artist_info_page.dart @@ -33,22 +33,17 @@ import 'package:violet/pages/segment/three_article_panel.dart'; import 'package:violet/server/community/anon.dart'; import 'package:violet/settings/settings.dart'; import 'package:violet/style/palette.dart'; +import 'package:violet/util/strings.dart'; import 'package:violet/widgets/article_item/article_list_item_widget.dart'; class ArtistInfoPage extends StatefulWidget { - final String artist; - final bool isGroup; - final bool isUploader; - final bool isSeries; - final bool isCharacter; + final String name; + final ArtistType type; const ArtistInfoPage({ super.key, - required this.artist, - this.isGroup = false, - this.isUploader = false, - this.isSeries = false, - this.isCharacter = false, + required this.name, + required this.type, }); @override @@ -61,8 +56,6 @@ class _ArtistInfoPageState extends State { int femaleTags = 0; int maleTags = 0; int tags = 0; - // Artist? Group? Uploader? - late String prefix; // Artist Articles late List cc; // Chart component lists @@ -95,28 +88,13 @@ class _ArtistInfoPageState extends State { // // Check bookmark // - var type = widget.isGroup - ? 1 - : widget.isUploader - ? 2 - : widget.isSeries - ? 3 - : widget.isCharacter - ? 4 - : 0; isBookmarked = await (await Bookmark.getInstance()) - .isBookmarkArtist(widget.artist, type); + .isBookmarkArtist(widget.name, widget.type); // // Get query // - cc = await query([ - widget.artist, - widget.isGroup, - widget.isUploader, - widget.isSeries, - widget.isCharacter - ]); + cc = await query(); // // Title based article clustering @@ -162,58 +140,51 @@ class _ArtistInfoPageState extends State { // // Similar Artists (or group, uploader) // - - if (widget.isGroup) { - similars = HitomiIndexs.calculateSimilarGroups(widget.artist); - } else if (widget.isUploader) { - similars = HitomiIndexs.calculateSimilarUploaders(widget.artist); - } else if (widget.isSeries) { - similars = HitomiIndexs.calculateSimilarSeries(widget.artist); - } else if (widget.isCharacter) { - similars = HitomiIndexs.calculateSimilarCharacter(widget.artist); - } else { - similars = HitomiIndexs.calculateSimilarArtists(widget.artist); + switch (widget.type) { + case ArtistType.artist: + similars = HitomiIndexs.calculateSimilarArtists(widget.name); + break; + case ArtistType.group: + similars = HitomiIndexs.calculateSimilarGroups(widget.name); + break; + case ArtistType.uploader: + similars = HitomiIndexs.calculateSimilarUploaders(widget.name); + break; + case ArtistType.series: + similars = HitomiIndexs.calculateSimilarSeries(widget.name); + break; + case ArtistType.character: + similars = HitomiIndexs.calculateSimilarCharacter(widget.name); + break; } similarsAll = similars; similars = similars.take(6).toList(); - prefix = 'artist:'; - if (widget.isGroup) { - prefix = 'group:'; - } else if (widget.isUploader) { - prefix = 'uploader:'; - } else if (widget.isSeries) { - prefix = 'series:'; - } else if (widget.isCharacter) { - prefix = 'character:'; - } - - await querySimilars(similars, prefix, qrs); + await querySimilars(similars, widget.type.name, qrs); - if (widget.isCharacter || widget.isSeries) { - if (widget.isCharacter) { + if (widget.type.isCharacter || widget.type.isSeries) { + if (widget.type.isCharacter) { relatedCharacterOrSeriesAll = - HitomiIndexs.calculateRelatedSeriesCharacter(widget.artist); - relatedCOSSingleAll = HitomiIndexs.getRelatedSeries(widget.artist); + HitomiIndexs.calculateRelatedSeriesCharacter(widget.name); + relatedCOSSingleAll = HitomiIndexs.getRelatedSeries(widget.name); } else { relatedCharacterOrSeriesAll = - HitomiIndexs.calculateRelatedCharacterSeries(widget.artist); - relatedCOSSingleAll = - HitomiIndexs.getRelatedCharacters(widget.artist); + HitomiIndexs.calculateRelatedCharacterSeries(widget.name); + relatedCOSSingleAll = HitomiIndexs.getRelatedCharacters(widget.name); } relatedCharacterOrSeries = relatedCharacterOrSeriesAll.take(6).toList(); relatedCOSSingle = relatedCOSSingleAll.take(6).toList(); await querySimilars( relatedCharacterOrSeries, - widget.isCharacter ? 'character:' : 'series:', + widget.type.name, qrsCharacterOrSeries, ); await querySimilars( relatedCOSSingle, - widget.isCharacter ? 'series:' : 'character:', + widget.type.name, qrsCOSSingle, ); } @@ -233,17 +204,8 @@ class _ArtistInfoPageState extends State { } Future readComments() async { - var tcomments = - (await VioletCommunityAnonymous.getArtistComments((widget.isGroup - ? 'group:' - : widget.isUploader - ? 'uploader:' - : widget.isSeries - ? 'series:' - : widget.isCharacter - ? 'character:' - : 'artist:') + - widget.artist))['result'] as List; + final tcomments = (await VioletCommunityAnonymous.getArtistComments( + '${widget.type.name}:${widget.name}'))['result'] as List; comments = tcomments .map((e) => Tuple3( @@ -261,7 +223,7 @@ class _ArtistInfoPageState extends State { for (int i = 0; i < similars.length; i++) { var postfix = similars[i].item1.toLowerCase().replaceAll(' ', '_'); var queryString = HitomiManager.translate2query( - '$prefix$postfix ${Settings.includeTags} ${Settings.excludeTags.where((e) => e.trim() != '').map((e) => '-$e').join(' ')}'); + '$prefix:$postfix ${Settings.includeTags} ${Settings.excludeTags.where((e) => e.trim() != '').map((e) => '-$e').join(' ')}'); final qm = QueryManager.queryPagination(queryString); qm.itemsPerPage = 10; @@ -306,20 +268,15 @@ class _ArtistInfoPageState extends State { } } - Future> query(dynamic obj) async { - var artist = obj[0] as String; - var isGroup = obj[1] as bool; - var isUploader = obj[2] as bool; - var isSeries = obj[3] as bool; - var isCharacter = obj[4] as bool; - - var query = HitomiManager.translate2query( - '${isGroup ? 'group:' : isUploader ? 'uploader:' : isSeries ? 'series:' : isCharacter ? 'character:' : 'artist:'}${artist.replaceAll(' ', '_')} ${Settings.includeTags} ${Settings.excludeTags.where((e) => e.trim() != '').map((e) => '-$e').join(' ')}'); - - // DateTime dt = DateTime.now(); - QueryManager qm = await QueryManager.query('$query ORDER BY Id DESC'); - // print((DateTime.now().difference(dt)).inSeconds); - + Future> query() async { + final token = '${widget.type.name}:${widget.name.replaceAll(' ', '_')}'; + final excludes = Settings.excludeTags + .where((e) => e.trim() != '') + .map((e) => '-$e') + .join(' '); + final query = HitomiManager.translate2query( + '$token ${Settings.includeTags} $excludes'); + final qm = await QueryManager.query('$query ORDER BY Id DESC'); return qm.results!; } @@ -402,17 +359,7 @@ class _ArtistInfoPageState extends State { controller: flareController, ), ), - Text( - (widget.isGroup - ? 'Groups: ' - : widget.isUploader - ? 'Uploader: ' - : widget.isSeries - ? 'Series: ' - : widget.isCharacter - ? 'Character: ' - : 'Artist: ') + - widget.artist, + Text('${widget.type.name.titlecase()}: ${widget.name}', style: const TextStyle(fontSize: 20, fontWeight: FontWeight.bold)), ], @@ -420,28 +367,19 @@ class _ArtistInfoPageState extends State { onTap: () async { isBookmarked = !isBookmarked; - var type = widget.isGroup - ? 1 - : widget.isUploader - ? 2 - : widget.isSeries - ? 3 - : widget.isCharacter - ? 4 - : 0; showToast( level: ToastLevel.check, message: - '${widget.artist}${Translations.of(context).trans(isBookmarked ? 'addtobookmark' : 'removetobookmark')}', + '${widget.name}${Translations.of(context).trans(isBookmarked ? 'addtobookmark' : 'removetobookmark')}', ); if (!isBookmarked) { await (await Bookmark.getInstance()) - .unbookmarkArtist(widget.artist, type); + .unbookmarkArtist(widget.name, widget.type); flareController.play('Unlike'); } else { await (await Bookmark.getInstance()) - .bookmarkArtist(widget.artist, type); + .bookmarkArtist(widget.name, widget.type); flareController.play('Like'); } }, @@ -560,16 +498,8 @@ class _ArtistInfoPageState extends State { visible: cc.length > maxItemCount, child: more(() => ArticleListPage( cc: cc, - name: (widget.isGroup - ? 'Groups: ' - : widget.isUploader - ? 'Uploader: ' - : widget.isSeries - ? 'Series: ' - : widget.isCharacter - ? 'Character: ' - : 'Artist: ') + - widget.artist))) + name: + '${widget.type.name.titlecase()}: ${widget.name}'))) ]), collapsed: Container(), ), @@ -595,7 +525,7 @@ class _ArtistInfoPageState extends State { ), ), ), - widget.isCharacter || widget.isSeries + widget.type.isCharacter || widget.type.isSeries ? ExpandableNotifier( child: Padding( padding: const EdgeInsets.symmetric(vertical: 4.0), @@ -608,7 +538,7 @@ class _ArtistInfoPageState extends State { header: Padding( padding: const EdgeInsets.fromLTRB(12, 12, 0, 0), child: Text( - '${Translations.of(context).trans('related')} ${widget.isSeries ? Translations.of(context).trans('iseries') : Translations.of(context).trans('icharacter')}'), + '${Translations.of(context).trans('related')} ${widget.type.isSeries ? Translations.of(context).trans('iseries') : Translations.of(context).trans('icharacter')}'), ), expanded: relatedArea(), collapsed: Container(), @@ -617,7 +547,7 @@ class _ArtistInfoPageState extends State { ), ) : Container(), - widget.isCharacter || widget.isSeries + widget.type.isCharacter || widget.type.isSeries ? ExpandableNotifier( child: Padding( padding: const EdgeInsets.symmetric(vertical: 4.0), @@ -630,7 +560,7 @@ class _ArtistInfoPageState extends State { header: Padding( padding: const EdgeInsets.fromLTRB(12, 12, 0, 0), child: Text( - '${Translations.of(context).trans('related')} ${widget.isCharacter ? Translations.of(context).trans('iseries') : Translations.of(context).trans('icharacter')}'), + '${Translations.of(context).trans('related')} ${widget.type.isCharacter ? Translations.of(context).trans('iseries') : Translations.of(context).trans('icharacter')}'), ), expanded: relatedSingleArea(), collapsed: Container(), @@ -650,7 +580,7 @@ class _ArtistInfoPageState extends State { header: Padding( padding: const EdgeInsets.fromLTRB(12, 12, 0, 0), child: Text( - '${Translations.of(context).trans('similar')} ${widget.isGroup ? Translations.of(context).trans('igroups') : widget.isUploader ? Translations.of(context).trans('iuploader') : widget.isSeries ? Translations.of(context).trans('iseries') : widget.isCharacter ? Translations.of(context).trans('icharacter') : Translations.of(context).trans('iartists')}'), + '${Translations.of(context).trans('similar')} ${widget.type.isGroup ? Translations.of(context).trans('igroups') : widget.type.isUploader ? Translations.of(context).trans('iuploader') : widget.type.isSeries ? Translations.of(context).trans('iseries') : widget.type.isCharacter ? Translations.of(context).trans('icharacter') : Translations.of(context).trans('iartists')}'), ), expanded: similarArea(), collapsed: Container(), @@ -765,38 +695,20 @@ class _ArtistInfoPageState extends State { itemBuilder: (BuildContext ctxt, int index) { if (index == similars.length) { return more(() => SimilarListPage( - prefix: prefix, similarsAll: similarsAll, - isGroup: widget.isGroup, - isUploader: widget.isUploader, - isCharacter: widget.isCharacter, - isSeries: widget.isSeries, + type: widget.type, )); } var e = similars[index]; var qq = qrs[index]; - var type = 'artist'; - if (widget.isGroup) { - type = 'group'; - } else if (widget.isUploader) { - type = 'uploader'; - } else if (widget.isSeries) { - type = 'series'; - } else if (widget.isCharacter) { - type = 'character'; - } - return ThreeArticlePanel( tappedRoute: () => ArtistInfoPage( - isGroup: widget.isGroup, - isUploader: widget.isUploader, - isCharacter: widget.isCharacter, - isSeries: widget.isSeries, - artist: e.item1, + type: widget.type, + name: e.item1, ), title: - ' ${e.item1} (${HitomiManager.getArticleCount(type, e.item1).toString()})', + ' ${e.item1} (${HitomiManager.getArticleCount(widget.type.name, e.item1).toString()})', count: '${Translations.of(context).trans('score')}: ${e.item2.toStringAsFixed(1)} ', articles: qq, @@ -816,7 +728,6 @@ class _ArtistInfoPageState extends State { if (index == 6) { return more(() => SeriesListPage( cc: cc, - prefix: prefix, series: series, )); } @@ -916,18 +827,7 @@ class _ArtistInfoPageState extends State { return; } await VioletCommunityAnonymous.postArtistComment( - null, - (widget.isGroup - ? 'group:' - : widget.isUploader - ? 'uploader:' - : widget.isSeries - ? 'series:' - : widget.isCharacter - ? 'character:' - : 'artist:') + - widget.artist, - text.text); + null, '${widget.type.name}:${widget.name}', text.text); await readComments(); Navigator.pop(context, true); }, @@ -973,30 +873,21 @@ class _ArtistInfoPageState extends State { itemBuilder: (BuildContext ctxt, int index) { if (index == relatedCharacterOrSeries.length) { return more(() => SimilarListPage( - prefix: prefix, similarsAll: relatedCharacterOrSeriesAll, - isGroup: widget.isGroup, - isUploader: widget.isUploader, - isCharacter: widget.isCharacter, - isSeries: widget.isSeries, + type: widget.type, )); } var e = relatedCharacterOrSeries[index]; var qq = qrsCharacterOrSeries[index]; - var cls = 'character'; - if (widget.isSeries) cls = 'series'; - return ThreeArticlePanel( tappedRoute: () => ArtistInfoPage( - isGroup: widget.isGroup, - isUploader: widget.isUploader, - isCharacter: widget.isCharacter, - isSeries: widget.isSeries, - artist: e.item1, + type: widget.type, + name: e.item1, ), - title: ' ${e.item1} (${HitomiManager.getArticleCount(cls, e.item1)})', + title: + ' ${e.item1} (${HitomiManager.getArticleCount(widget.type.name, e.item1)})', count: '${Translations.of(context).trans('score')}: ${e.item2.toStringAsFixed(1)} ', articles: qq, @@ -1014,29 +905,20 @@ class _ArtistInfoPageState extends State { itemBuilder: (BuildContext ctxt, int index) { if (index == relatedCOSSingle.length) { return more(() => SimilarListPage( - prefix: widget.isCharacter ? 'series:' : 'character:', similarsAll: relatedCOSSingleAll, - isGroup: widget.isGroup, - isUploader: widget.isUploader, - isSeries: widget.isCharacter, - isCharacter: widget.isSeries, + type: widget.type, )); } var e = relatedCOSSingle[index]; var qq = qrsCOSSingle[index]; - var cls = 'character'; - if (widget.isCharacter) cls = 'series'; - return ThreeArticlePanel( tappedRoute: () => ArtistInfoPage( - isGroup: widget.isGroup, - isUploader: widget.isUploader, - isSeries: widget.isCharacter, - isCharacter: widget.isSeries, - artist: e.item1, + type: widget.type, + name: e.item1, ), - title: ' ${e.item1} (${HitomiManager.getArticleCount(cls, e.item1)})', + title: + ' ${e.item1} (${HitomiManager.getArticleCount(widget.type.name, e.item1)})', count: '${Translations.of(context).trans('score')}: ${e.item2.toStringAsFixed(1)} ', articles: qq, diff --git a/violet/lib/pages/artist_info/series_list_page.dart b/violet/lib/pages/artist_info/series_list_page.dart index d76a6e3a6..d11368c4c 100644 --- a/violet/lib/pages/artist_info/series_list_page.dart +++ b/violet/lib/pages/artist_info/series_list_page.dart @@ -11,13 +11,11 @@ import 'package:violet/pages/segment/three_article_panel.dart'; import 'package:violet/settings/settings.dart'; class SeriesListPage extends StatelessWidget { - final String prefix; final List> series; final List cc; const SeriesListPage({ super.key, - required this.prefix, required this.series, required this.cc, }); diff --git a/violet/lib/pages/artist_info/similar_list_page.dart b/violet/lib/pages/artist_info/similar_list_page.dart index f848ce244..284b89e39 100644 --- a/violet/lib/pages/artist_info/similar_list_page.dart +++ b/violet/lib/pages/artist_info/similar_list_page.dart @@ -8,6 +8,7 @@ import 'package:tuple/tuple.dart'; import 'package:violet/algorithm/distance.dart'; import 'package:violet/component/hitomi/hitomi.dart'; import 'package:violet/database/query.dart'; +import 'package:violet/database/user/bookmark.dart'; import 'package:violet/locale/locale.dart'; import 'package:violet/pages/artist_info/artist_info_page.dart'; import 'package:violet/pages/segment/card_panel.dart'; @@ -15,29 +16,21 @@ import 'package:violet/pages/segment/three_article_panel.dart'; import 'package:violet/settings/settings.dart'; class SimilarListPage extends StatelessWidget { - final String prefix; - final bool isGroup; - final bool isUploader; - final bool isSeries; - final bool isCharacter; + final ArtistType type; final List> similarsAll; const SimilarListPage({ super.key, - required this.prefix, required this.similarsAll, - required this.isGroup, - required this.isUploader, - required this.isSeries, - required this.isCharacter, + required this.type, }); Future> _future(String e) async { var unescape = HtmlUnescape(); var postfix = e.toLowerCase().replaceAll(' ', '_'); - if (isUploader) postfix = e; + if (type.isUploader) postfix = e; var queryString = HitomiManager.translate2query( - '$prefix$postfix ${Settings.includeTags} ${Settings.excludeTags.where((e) => e.trim() != '').map((e) => '-$e').join(' ')}'); + '${type.name}:$postfix ${Settings.includeTags} ${Settings.excludeTags.where((e) => e.trim() != '').map((e) => '-$e').join(' ')}'); final qm = QueryManager.queryPagination(queryString); qm.itemsPerPage = 10; @@ -98,27 +91,13 @@ class SimilarListPage extends StatelessWidget { ); } - var type = 'artist'; - if (isGroup) { - type = 'group'; - } else if (isUploader) { - type = 'uploader'; - } else if (isSeries) { - type = 'series'; - } else if (isCharacter) { - type = 'character'; - } - return ThreeArticlePanel( tappedRoute: () => ArtistInfoPage( - isGroup: isGroup, - isUploader: isUploader, - isCharacter: isCharacter, - isSeries: isSeries, - artist: e.item1, + type: type, + name: e.item1, ), title: - ' ${e.item1} (${HitomiManager.getArticleCount(type, e.item1)})', + ' ${e.item1} (${HitomiManager.getArticleCount(type.name, e.item1)})', count: '${Translations.of(context).trans('score')}: ${e.item2.toStringAsFixed(1)} ', articles: snapshot.data!, diff --git a/violet/lib/pages/bookmark/group/group_artist_article_list.dart b/violet/lib/pages/bookmark/group/group_artist_article_list.dart index 35437572b..f17a46127 100644 --- a/violet/lib/pages/bookmark/group/group_artist_article_list.dart +++ b/violet/lib/pages/bookmark/group/group_artist_article_list.dart @@ -51,13 +51,8 @@ class _GroupArtistArticleListState extends State if (artists.isEmpty) return []; final queryString = HitomiManager.translate2query(artists - .map((e) => '${[ - 'artist', - 'group', - 'uploader', - 'series', - 'character' - ][e.type()]}:${e.artist().toLowerCase().replaceAll(' ', '_')} ${Settings.includeTags}') + .map((e) => + '${e.type().name}:${e.artist().toLowerCase().replaceAll(' ', '_')} ${Settings.includeTags}') .join(' or ')); final qm = QueryManager.queryPagination(queryString); diff --git a/violet/lib/pages/bookmark/group/group_artist_list.dart b/violet/lib/pages/bookmark/group/group_artist_list.dart index 60d72cec3..49649ce01 100644 --- a/violet/lib/pages/bookmark/group/group_artist_list.dart +++ b/violet/lib/pages/bookmark/group/group_artist_list.dart @@ -48,13 +48,8 @@ class _GroupArtistListState extends State var ids = >[]; for (int i = 0; i < artists.length; i++) { var postfix = artists[i].artist().toLowerCase().replaceAll(' ', '_'); - var queryString = HitomiManager.translate2query('${[ - 'artist', - 'group', - 'uploader', - 'series', - 'character' - ][artists[i].type()]}:$postfix ${Settings.includeTags}'); + var queryString = HitomiManager.translate2query( + '${artists[i].type().name}:$postfix ${Settings.includeTags}'); final qm = QueryManager.queryPagination(queryString); qm.itemsPerPage = 1; var query = (await qm.next())[0].id(); @@ -70,15 +65,10 @@ class _GroupArtistListState extends State artists = newedList; } - Future> _future(String e, int type) async { + Future> _future(String e, ArtistType type) async { var postfix = e.toLowerCase().replaceAll(' ', '_'); - var queryString = HitomiManager.translate2query('${[ - 'artist', - 'group', - 'uploader', - 'series', - 'character' - ][type]}:$postfix ${Settings.includeTags}'); + var queryString = HitomiManager.translate2query( + '${type.name}:$postfix ${Settings.includeTags}'); final qm = QueryManager.queryPagination(queryString); qm.itemsPerPage = 4; return await qm.next(); @@ -244,7 +234,7 @@ class _GroupArtistListState extends State color: checkMode && checked .where((element) => - element.item1 == e.type() && element.item2 == e.artist()) + element.$1 == e.type() && element.$2 == e.artist()) .isNotEmpty ? Colors.amber : Colors.transparent, @@ -256,8 +246,7 @@ class _GroupArtistListState extends State e.artist(), checked .where((element) => - element.item1 == e.type() && - element.item2 == e.artist()) + element.$1 == e.type() && element.$2 == e.artist()) .isEmpty); setState(() {}); return; @@ -266,11 +255,8 @@ class _GroupArtistListState extends State PlatformNavigator.navigateSlide( context, ArtistInfoPage( - isGroup: e.type() == 1, - isUploader: e.type() == 2, - isSeries: e.type() == 3, - isCharacter: e.type() == 4, - artist: e.artist(), + name: e.artist(), + type: e.type(), ), ); }, @@ -290,19 +276,7 @@ class _GroupArtistListState extends State mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( - ' ${[ - 'artist', - 'group', - 'uploader', - 'series', - 'character' - ][e.type()]}:${e.artist()} (${HitomiManager.getArticleCount([ - 'artist', - 'group', - 'uploader', - 'series', - 'character' - ][e.type()], e.artist())})', + ' ${e.type().name}:${e.artist()} (${HitomiManager.getArticleCount(e.type().name, e.artist())})', style: const TextStyle(fontSize: 17)), ], ), @@ -357,8 +331,7 @@ class _GroupArtistListState extends State FloatingActionButton( onPressed: () { for (var element in artists) { - checked - .add(Tuple2(element.type(), element.artist())); + checked.add((element.type(), element.artist())); } setState(() {}); }, @@ -376,7 +349,7 @@ class _GroupArtistListState extends State Translations.of(context).trans('bookmark'))) { var bookmark = await Bookmark.getInstance(); for (var element in checked) { - await bookmark.unbookmarkArtist(element.item2, element.item1); + await bookmark.unbookmarkArtist(element.$2, element.$1); } checked.clear(); refresh(); @@ -419,23 +392,23 @@ class _GroupArtistListState extends State bool checkMode = false; bool checkModePre = false; - List> checked = []; + List<(ArtistType, String)> checked = []; - void longpress(int type, String artist) { + void longpress(ArtistType type, String artist) { if (!checkMode) { checkMode = true; checkModePre = true; - checked.add(Tuple2(type, artist)); + checked.add((type, artist)); setState(() {}); } } - void check(int type, String artist, bool check) { + void check(ArtistType type, String artist, bool check) { if (check) { - checked.add(Tuple2(type, artist)); + checked.add((type, artist)); } else { - checked.removeWhere( - (element) => element.item1 == type && element.item2 == artist); + checked + .removeWhere((element) => element.$1 == type && element.$2 == artist); if (checked.isEmpty) { setState(() { checkModePre = false; @@ -506,8 +479,8 @@ class _GroupArtistListState extends State for (int i = 0; i < artists.length; i++) { invIdIndex['${artists[i].artist()}|${artists[i].type()}'] = i; } - checked.sort((x, y) => invIdIndex['${x.item2}|${x.item1}']! - .compareTo(invIdIndex['${y.item2}|${y.item1}']!)); + checked.sort((x, y) => invIdIndex['${x.$2}|${x.$1}']! + .compareTo(invIdIndex['${y.$2}|${y.$1}']!)); // 1. Get bookmark articles on source groupid var bm = await Bookmark.getInstance(); @@ -523,10 +496,10 @@ class _GroupArtistListState extends State for (var e in checked.reversed) { // 3. Delete source bookmarks - await bm.unbookmarkArtist(e.item2, e.item1); + await bm.unbookmarkArtist(e.$2, e.$1); // 4. Add src bookmarks with new groupid await bm.insertArtist( - e.item2, e.item1, DateTime.now(), groups[choose].id()); + e.$2, e.$1, DateTime.now(), groups[choose].id()); } // 5. Update UI diff --git a/violet/lib/pages/download/download_page.dart b/violet/lib/pages/download/download_page.dart index 386947938..c995b36bd 100644 --- a/violet/lib/pages/download/download_page.dart +++ b/violet/lib/pages/download/download_page.dart @@ -41,6 +41,7 @@ import 'package:violet/script/script_manager.dart'; import 'package:violet/settings/settings.dart'; import 'package:violet/style/palette.dart'; import 'package:violet/util/helper.dart'; +import 'package:violet/util/strings.dart'; import 'package:violet/widgets/debounce_widget.dart'; import 'package:violet/widgets/search_bar.dart'; import 'package:violet/widgets/theme_switchable_state.dart'; @@ -632,7 +633,7 @@ class _DownloadPageState extends ThemeSwitchableState child: Container( padding: const EdgeInsets.fromLTRB(8, 8, 8, 8), child: Text( - e.$1.split(' ').map((e) => e.capitalize()).join(' '), + e.$1.split(' ').map((e) => e.titlecase()).join(' '), style: const TextStyle( fontWeight: FontWeight.bold, fontSize: 20.0), ), @@ -1239,9 +1240,3 @@ class _DownloadPageState extends ThemeSwitchableState queryResults[int.parse(url)] = qm.results!.first; } } - -extension StringExtension on String { - String capitalize() { - return '${this[0].toUpperCase()}${substring(1).toLowerCase()}'; - } -} diff --git a/violet/lib/pages/main/artist_collection/artist_list_page.dart b/violet/lib/pages/main/artist_collection/artist_list_page.dart index 3fa442b28..e9283ad35 100644 --- a/violet/lib/pages/main/artist_collection/artist_list_page.dart +++ b/violet/lib/pages/main/artist_collection/artist_list_page.dart @@ -8,6 +8,7 @@ import 'package:uuid/uuid.dart'; import 'package:violet/algorithm/distance.dart'; import 'package:violet/component/hitomi/hitomi.dart'; import 'package:violet/database/query.dart'; +import 'package:violet/database/user/bookmark.dart'; import 'package:violet/model/article_list_item.dart'; import 'package:violet/pages/artist_info/artist_info_page.dart'; import 'package:violet/pages/segment/platform_navigator.dart'; @@ -134,14 +135,20 @@ class ArtistListPage extends StatelessWidget { final articleCount = HitomiManager.getArticleCount(classification, name); + late final ArtistType type; + if (isLast && classification == 'group') { + type = ArtistType.group; + } else { + type = ArtistType.artist; + } + return InkWell( onTap: () async { PlatformNavigator.navigateSlide( context, ArtistInfoPage( - isGroup: isLast && classification == 'group', - isUploader: false, - artist: name, + type: type, + name: name, ), ); }, diff --git a/violet/lib/pages/main/info/lab/artist_search/artist_search.dart b/violet/lib/pages/main/info/lab/artist_search/artist_search.dart index c9dadd91e..4cb1fa62a 100644 --- a/violet/lib/pages/main/info/lab/artist_search/artist_search.dart +++ b/violet/lib/pages/main/info/lab/artist_search/artist_search.dart @@ -11,6 +11,7 @@ import 'package:violet/algorithm/distance.dart'; import 'package:violet/component/hitomi/hitomi.dart'; import 'package:violet/component/hitomi/indexs.dart'; import 'package:violet/database/query.dart'; +import 'package:violet/database/user/bookmark.dart'; import 'package:violet/locale/locale.dart'; import 'package:violet/pages/artist_info/artist_info_page.dart'; import 'package:violet/pages/main/info/lab/artist_search/tag_group_modify.dart'; @@ -29,7 +30,7 @@ class ArtistSearch extends StatefulWidget { } class _ArtistSearchState extends State { - String selectedType = 'artists'; + ArtistType selectedType = ArtistType.artist; Map tagGroup = { 'female:sole_female': 10, @@ -47,11 +48,11 @@ class _ArtistSearchState extends State { final tagGroup = {}; final tagSrcs = { - 'artists': HitomiIndexs.tagArtist, - 'groups': HitomiIndexs.tagGroup, - 'series': HitomiIndexs.tagSeries, - 'character': HitomiIndexs.tagCharacter, - 'uploader': HitomiIndexs.tagUploader, + ArtistType.artist: HitomiIndexs.tagArtist, + ArtistType.group: HitomiIndexs.tagGroup, + ArtistType.series: HitomiIndexs.tagSeries, + ArtistType.character: HitomiIndexs.tagCharacter, + ArtistType.uploader: HitomiIndexs.tagUploader, }; for (var element in this.tagGroup.entries) { @@ -217,19 +218,19 @@ class _ArtistSearchState extends State { } typeSelector() { - final dropDown = DropdownButton( + final dropDown = DropdownButton( value: selectedType, - items: ['artists', 'groups', 'series', 'character', 'uploader'] - .map>((String value) { - return DropdownMenuItem( + items: ArtistType.values + .map>((ArtistType value) { + return DropdownMenuItem( value: value, child: Text( - Translations.instance!.trans(value), + Translations.instance!.trans(value.name), style: const TextStyle(fontSize: 16), ), ); }).toList(), - onChanged: (String? newValue) { + onChanged: (ArtistType? newValue) { similarsAll = []; setState(() { @@ -245,15 +246,6 @@ class _ArtistSearchState extends State { return dropDown; } - String getNormalizedType() { - if (selectedType == 'artists') { - return 'artist'; - } else if (selectedType == 'groups') { - return 'group'; - } - return selectedType; - } - artistListArea() { return ListView.builder( key: listViewKey, @@ -272,18 +264,13 @@ class _ArtistSearchState extends State { ); } - final type = getNormalizedType(); - return ThreeArticlePanel( tappedRoute: () => ArtistInfoPage( - isGroup: type == 'group', - isUploader: type == 'uploader', - isCharacter: type == 'character', - isSeries: type == 'series', - artist: e.item1, + type: selectedType, + name: e.item1, ), title: - ' ${e.item1} (${HitomiManager.getArticleCount(type, e.item1)})', + ' ${e.item1} (${HitomiManager.getArticleCount(selectedType.name, e.item1)})', count: '${Translations.of(context).trans('score')}: ${e.item2.toStringAsFixed(1)} ', articles: snapshot.data!, @@ -297,11 +284,10 @@ class _ArtistSearchState extends State { Future> artistListfuture(String e) async { final unescape = HtmlUnescape(); - final prefix = getNormalizedType(); final postfix = e.toLowerCase().replaceAll(' ', '_'); final queryString = HitomiManager.translate2query( - '$prefix:$postfix ${Settings.includeTags} ${Settings.excludeTags.where((e) => e.trim() != '').map((e) => '-$e').join(' ')}'); + '${selectedType.name}:$postfix ${Settings.includeTags} ${Settings.excludeTags.where((e) => e.trim() != '').map((e) => '-$e').join(' ')}'); final qm = QueryManager.queryPagination(queryString); qm.itemsPerPage = 10; diff --git a/violet/lib/pages/main/info/lab/bookmark/bookmarks_artist_list.dart b/violet/lib/pages/main/info/lab/bookmark/bookmarks_artist_list.dart index 84ca53394..085ec0724 100644 --- a/violet/lib/pages/main/info/lab/bookmark/bookmarks_artist_list.dart +++ b/violet/lib/pages/main/info/lab/bookmark/bookmarks_artist_list.dart @@ -48,14 +48,9 @@ class _GroupArtistListState extends State Future _sortByLatest() async { var ids = >[]; for (int i = 0; i < artists.length; i++) { - var postfix = artists[i].artist().toLowerCase().replaceAll(' ', '_'); - var queryString = HitomiManager.translate2query('${[ - 'artist', - 'group', - 'uploader', - 'series', - 'character' - ][artists[i].type()]}:$postfix ${Settings.includeTags}'); + final postfix = artists[i].artist().toLowerCase().replaceAll(' ', '_'); + final queryString = HitomiManager.translate2query( + '${artists[i].type().name}:$postfix ${Settings.includeTags}'); final qm = QueryManager.queryPagination(queryString); qm.itemsPerPage = 1; var query = (await qm.next())[0].id(); @@ -71,15 +66,10 @@ class _GroupArtistListState extends State artists = newedList; } - Future> _future(String e, int type) async { + Future> _future(String e, ArtistType type) async { var postfix = e.toLowerCase().replaceAll(' ', '_'); - var queryString = HitomiManager.translate2query('${[ - 'artist', - 'group', - 'uploader', - 'series', - 'character' - ][type]}:$postfix ${Settings.includeTags}'); + var queryString = HitomiManager.translate2query( + '${type.name}:$postfix ${Settings.includeTags}'); final qm = QueryManager.queryPagination(queryString); qm.itemsPerPage = 3; return await qm.next(); @@ -222,11 +212,8 @@ class _GroupArtistListState extends State PlatformNavigator.navigateSlide( context, ArtistInfoPage( - isGroup: e.type() == 1, - isUploader: e.type() == 2, - isSeries: e.type() == 3, - isCharacter: e.type() == 4, - artist: e.artist(), + type: e.type(), + name: e.artist(), ), ); }, @@ -241,19 +228,7 @@ class _GroupArtistListState extends State mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( - ' ${[ - 'artist', - 'group', - 'uploader', - 'series', - 'character' - ][e.type()]}:${e.artist()} (${HitomiManager.getArticleCount([ - 'artist', - 'group', - 'uploader', - 'series', - 'character' - ][e.type()], e.artist())})', + ' ${e.type().name}:${e.artist()} (${HitomiManager.getArticleCount(e.type().name, e.artist())})', style: const TextStyle(fontSize: 17)), ], ), diff --git a/violet/lib/pages/main/info/lab/recent_comments.dart b/violet/lib/pages/main/info/lab/recent_comments.dart index 0213d1842..955f4e9e7 100644 --- a/violet/lib/pages/main/info/lab/recent_comments.dart +++ b/violet/lib/pages/main/info/lab/recent_comments.dart @@ -4,6 +4,7 @@ import 'package:flutter/material.dart'; import 'package:intl/intl.dart'; import 'package:tuple/tuple.dart'; +import 'package:violet/database/user/bookmark.dart'; import 'package:violet/pages/artist_info/artist_info_page.dart'; import 'package:violet/pages/segment/card_panel.dart'; import 'package:violet/pages/segment/platform_navigator.dart'; @@ -52,14 +53,11 @@ class _LabRecentCommentsState extends State { var e = comments[index]; return InkWell( onTap: () async { - var group = e.item4.split(':').first; - var name = e.item4.split(':').last; + final group = e.item4.split(':').first; + final name = e.item4.split(':').last; _navigate(ArtistInfoPage( - isGroup: group == 'groups' || group == 'group', - isUploader: group == 'uploader', - isCharacter: group == 'character', - isSeries: group == 'series', - artist: name, + type: ArtistTypeHelper.fromString(group)!, + name: name, )); }, splashColor: Colors.white, diff --git a/violet/lib/pages/settings/settings_page.dart b/violet/lib/pages/settings/settings_page.dart index 9f1289959..82cd61dd0 100644 --- a/violet/lib/pages/settings/settings_page.dart +++ b/violet/lib/pages/settings/settings_page.dart @@ -2153,8 +2153,12 @@ class _SettingsPageState extends State await bookmark.insertArticle(tar, DateTime.now(), group); } else if (tar.contains(':') && ['artist', 'group'].contains(tar.split(':')[0])) { - await bookmark.bookmarkArtist(tar.split(':')[1], - tar.split(':')[0] == 'artist' ? 0 : 1, group); + await bookmark.bookmarkArtist( + tar.split(':')[1], + tar.split(':')[0] == 'artist' + ? ArtistType.artist + : ArtistType.group, + group); } } diff --git a/violet/lib/util/strings.dart b/violet/lib/util/strings.dart new file mode 100644 index 000000000..68870c3ea --- /dev/null +++ b/violet/lib/util/strings.dart @@ -0,0 +1,5 @@ +extension StringExtension on String { + String titlecase() { + return '${this[0].toUpperCase()}${substring(1).toLowerCase()}'; + } +}