Skip to content

Commit 5c6fddc

Browse files
committed
feat: compact settings
1 parent 469dc19 commit 5c6fddc

File tree

13 files changed

+653
-259
lines changed

13 files changed

+653
-259
lines changed

assets/translations/app_en.arb

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
"animeDescription": "Personalize and manage your anime preferences",
99
"anilist": "AniList",
1010
"appName": "Dartotsu",
11+
"chapters": "Chapters",
12+
"episodes": "Episodes",
1113
"appTagline": "The NEW Best App For\nTracking Anime & Manga",
1214
"backgroundColor": "Background Color",
1315
"backgroundColorDescription": "Subtitle background color",
@@ -81,5 +83,14 @@
8183
"supportMaintainer": "Want to support Dartotsu's Maintainer?\nConsider Donating",
8284
"theme": "Theme",
8385
"themeDescription": "Customize the appearance and vibe of your app",
84-
"yes": "Yes"
86+
"yes": "Yes",
87+
"options": "Options",
88+
"layout": "Layout",
89+
"grid": "Grid",
90+
"list": "List",
91+
"compact": "Compact",
92+
"sort": "Sort",
93+
"utd": "Up to Down",
94+
"dtu": "Down to Up",
95+
"scanlators": "Scanlators"
8596
}

lib/DataClass/Manga.dart

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
1+
2+
import 'package:dantotsu/DataClass/Chapter.dart';
3+
14
import 'Author.dart';
2-
import 'MangaChapter.dart';
35

46
class Manga {
57
int? totalChapters;
68
String? selectedChapter;
7-
Map<String, MangaChapter>? chapters;
9+
List<Chapter>? chapters;
810
String? slug;
911
author? mediaAuthor;
1012

lib/Screens/Info/Tabs/Watch/Anime/AnimeParser.dart

Lines changed: 46 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,11 @@
11
import 'package:collection/collection.dart';
22
import 'package:dantotsu/Functions/string_extensions.dart';
33
import 'package:dantotsu/Screens/Info/Tabs/Watch/BaseParser.dart';
4+
import 'package:flutter/cupertino.dart';
45
import 'package:get/get_rx/src/rx_types/rx_types.dart';
56

67
import '../../../../../DataClass/Episode.dart';
78
import '../../../../../DataClass/Media.dart';
8-
import '../../../../../Preferences/PrefManager.dart';
9-
import '../../../../../Preferences/Preferences.dart';
109
import '../../../../../api/EpisodeDetails/Anify/Anify.dart';
1110
import '../../../../../api/EpisodeDetails/Jikan/Jikan.dart';
1211
import '../../../../../api/EpisodeDetails/Kitsu/Kitsu.dart';
@@ -15,25 +14,42 @@ import '../../../../../api/Mangayomi/Eval/dart/model/m_manga.dart';
1514
import '../../../../../api/Mangayomi/Model/Source.dart';
1615
import '../../../../../api/Mangayomi/Search/get_detail.dart';
1716
import '../Functions/ParseChapterNumber.dart';
17+
import 'Widget/AnimeCompactSettings.dart';
1818

1919
class AnimeParser extends BaseParser {
2020
var episodeList = Rxn<Map<String, Episode>>(null);
2121
var anifyEpisodeList = Rxn<Map<String, Episode>>(null);
2222
var kitsuEpisodeList = Rxn<Map<String, Episode>>(null);
2323
var fillerEpisodesList = Rxn<Map<String, Episode>>(null);
2424
var viewType = 0.obs;
25-
var dataLoaded = false.obs;
2625

2726
void init(Media mediaData) async {
2827
if (dataLoaded.value) return;
29-
viewType.value = mediaData.selected?.recyclerStyle ??
30-
PrefManager.getVal(PrefName.AnimeDefaultView);
28+
29+
initSettings(mediaData);
3130
await Future.wait([
3231
getEpisodeData(mediaData),
3332
getFillerEpisodes(mediaData),
3433
]);
3534
}
3635

36+
var dataLoaded = false.obs;
37+
var reversed = false.obs;
38+
void initSettings(Media mediaData) {
39+
var selected = loadSelected(mediaData);
40+
viewType.value = selected.recyclerStyle!;
41+
reversed.value = selected.recyclerReversed;
42+
}
43+
void settingsDialog(BuildContext context, Media media) =>
44+
AnimeCompactSettings(
45+
context,
46+
media,
47+
(s) {
48+
viewType.value = s.recyclerStyle!;
49+
reversed.value = s.recyclerReversed;
50+
},
51+
).showDialog();
52+
3753
@override
3854
Future<void> wrongTitle(
3955
context,
@@ -70,30 +86,33 @@ class AnimeParser extends BaseParser {
7086
var chapters = m.chapters;
7187
var isFirst = true;
7288
var shouldNormalize = false;
73-
var additionalIndex=0;
89+
var additionalIndex = 0;
7490
episodeList.value = Map.fromEntries(
7591
chapters?.reversed.mapIndexed((index, chapter) {
76-
final episode = MChapterToEpisode(chapter, media);
77-
78-
if (isFirst) {
79-
isFirst = false;
80-
if (episode.number.toDouble() > 3.0) {
81-
shouldNormalize = true;
82-
}
83-
}
84-
85-
if (shouldNormalize) {
86-
if (episode.number.toDouble() % 1 != 0) {
87-
additionalIndex--;
88-
var remainder = (episode.number.toDouble() % 1).toStringAsFixed(2).toDouble();
89-
episode.number = (index + 1 + remainder + additionalIndex).toString();
90-
} else {
91-
episode.number = (index + 1 + additionalIndex).toString();
92-
}
93-
}
94-
95-
return MapEntry(episode.number, episode);
96-
}) ??
92+
final episode = MChapterToEpisode(chapter, media);
93+
94+
if (isFirst) {
95+
isFirst = false;
96+
if (episode.number.toDouble() > 3.0) {
97+
shouldNormalize = true;
98+
}
99+
}
100+
101+
if (shouldNormalize) {
102+
if (episode.number.toDouble() % 1 != 0) {
103+
additionalIndex--;
104+
var remainder = (episode.number.toDouble() % 1)
105+
.toStringAsFixed(2)
106+
.toDouble();
107+
episode.number =
108+
(index + 1 + remainder + additionalIndex).toString();
109+
} else {
110+
episode.number = (index + 1 + additionalIndex).toString();
111+
}
112+
}
113+
114+
return MapEntry(episode.number, episode);
115+
}) ??
97116
[],
98117
);
99118
}

lib/Screens/Info/Tabs/Watch/Anime/AnimeWatchScreen.dart

Lines changed: 47 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import 'package:collection/collection.dart';
12
import 'package:dantotsu/DataClass/Media.dart';
23
import 'package:dantotsu/Screens/Info/Tabs/Watch/BaseParser.dart';
34
import 'package:dantotsu/Screens/Info/Tabs/Watch/BaseWatchScreen.dart';
@@ -6,9 +7,10 @@ import 'package:get/get.dart';
67

78
import '../../../../../Adaptor/Episode/EpisodeAdaptor.dart';
89
import '../../../../../DataClass/Episode.dart';
10+
import '../../../../../Theme/LanguageSwitcher.dart';
11+
import 'AnimeParser.dart';
912
import 'Widget/BuildChunkSelector.dart';
1013
import 'Widget/ContinueCard.dart';
11-
import 'AnimeParser.dart';
1214

1315
class AnimeWatchScreen extends StatefulWidget {
1416
final Media mediaData;
@@ -49,17 +51,22 @@ class AnimeWatchScreenState extends BaseWatchScreen<AnimeWatchScreen> {
4951
if (episodeList == null || episodeList.isEmpty) {
5052
return const Center(child: CircularProgressIndicator());
5153
}
52-
5354
if (!_viewModel.episodeDataLoaded.value) {
5455
return const Center(child: CircularProgressIndicator());
5556
}
56-
5757
updateEpisodeDetails(episodeList);
5858

59-
var (chunks, selectedChunkIndex) = buildChunks(
59+
var (chunks, initChunkIndex) = buildChunks(
6060
context, episodeList, widget.mediaData.userProgress.toString());
6161

62-
var selectedEpisode = episodeList[((widget.mediaData.userProgress ?? 0) + 1).toString()];
62+
var selectedEpisode = episodeList.values.firstWhereOrNull((element) =>
63+
element.number ==
64+
((widget.mediaData.userProgress ?? 0) + 1).toString());
65+
66+
RxInt selectedChunkIndex = (-1).obs;
67+
68+
selectedChunkIndex =
69+
selectedChunkIndex.value == -1 ? initChunkIndex : selectedChunkIndex;
6370
return Column(
6471
mainAxisSize: MainAxisSize.min,
6572
crossAxisAlignment: CrossAxisAlignment.start,
@@ -70,15 +77,26 @@ class AnimeWatchScreenState extends BaseWatchScreen<AnimeWatchScreen> {
7077
episode: selectedEpisode,
7178
source: _viewModel.source.value!,
7279
),
73-
buildChunkSelector(context, chunks, selectedChunkIndex),
80+
ChunkSelector(
81+
context,
82+
chunks,
83+
selectedChunkIndex,
84+
_viewModel.reversed,
85+
),
7486
Container(
7587
margin: const EdgeInsets.symmetric(horizontal: 18, vertical: 4),
76-
child: Obx(() => EpisodeAdaptor(
77-
type: _viewModel.viewType.value,
78-
source: _viewModel.source.value!,
79-
episodeList: chunks[selectedChunkIndex.value],
80-
mediaData: widget.mediaData,
81-
)),
88+
child: Obx(() {
89+
List<List<Episode>> reversed = _viewModel.reversed.value
90+
? chunks.map((element) => element.reversed.toList())
91+
.toList()
92+
: chunks;
93+
return EpisodeAdaptor(
94+
type: _viewModel.viewType.value,
95+
source: _viewModel.source.value!,
96+
episodeList: reversed[selectedChunkIndex.value],
97+
mediaData: widget.mediaData,
98+
);
99+
}),
82100
)
83101
],
84102
);
@@ -91,63 +109,30 @@ class AnimeWatchScreenState extends BaseWatchScreen<AnimeWatchScreen> {
91109
child: Row(
92110
mainAxisAlignment: MainAxisAlignment.spaceBetween,
93111
children: [
94-
const Text(
95-
'Episodes',
96-
style: TextStyle(
97-
fontFamily: 'Poppins',
98-
fontWeight: FontWeight.bold,
99-
fontSize: 16,
112+
Expanded(
113+
child: Text(
114+
getString.episodes,
115+
style: TextStyle(
116+
fontFamily: 'Poppins',
117+
fontWeight: FontWeight.bold,
118+
fontSize: 16,
119+
),
120+
overflow: TextOverflow.ellipsis,
121+
maxLines: 1,
122+
),
123+
),
124+
IconButton(
125+
onPressed: () => _viewModel.settingsDialog(context, mediaData),
126+
icon: Icon(
127+
Icons.menu_rounded,
128+
color: Theme.of(context).colorScheme.onSurface,
100129
),
101-
overflow: TextOverflow.ellipsis,
102-
maxLines: 1,
103130
),
104-
_buildIconButtons(),
105131
],
106132
),
107133
);
108134
}
109135

110-
Widget _buildIconButtons() {
111-
final theme = Theme.of(context).colorScheme;
112-
final icons = [
113-
Icons.view_list_sharp,
114-
Icons.grid_view_rounded,
115-
Icons.view_comfy_rounded,
116-
];
117-
var viewType = _viewModel.viewType;
118-
119-
return Obx(() {
120-
return Row(
121-
children: List.generate(icons.length, (index) {
122-
return Padding(
123-
padding: const EdgeInsets.only(left: 10),
124-
child: IconButton(
125-
icon: Transform(
126-
alignment: Alignment.center,
127-
transform: index == 0
128-
? Matrix4.rotationY(3.14159)
129-
: Matrix4.identity(),
130-
child: Icon(icons[index]),
131-
),
132-
iconSize: 24,
133-
color: viewType.value == index
134-
? theme.onSurface
135-
: theme.onSurface.withValues(alpha: 0.33),
136-
onPressed: () => changeViewType(viewType, index),
137-
),
138-
);
139-
}),
140-
);
141-
});
142-
}
143-
144-
void changeViewType(RxInt viewType, int index) {
145-
var type = _viewModel.loadSelected(mediaData);
146-
viewType.value = index;
147-
type.recyclerStyle = index;
148-
_viewModel.saveSelected(mediaData.id, type);
149-
}
150-
151136
void updateEpisodeDetails(Map<String, Episode> episodeList) {
152137
widget.mediaData.anime?.episodes = episodeList;
153138
widget.mediaData.anime?.fillerEpisodes =

0 commit comments

Comments
 (0)