Add following novels page.

Close #13
This commit is contained in:
2025-01-30 14:52:00 +08:00
parent 37f84efe05
commit 47ebe9deec
3 changed files with 103 additions and 0 deletions

View File

@@ -149,4 +149,17 @@ extension NovelExt on Network {
} }
return Res(Novel.fromJson(res.data["novel"])); return Res(Novel.fromJson(res.data["novel"]));
} }
Future<Res<List<Novel>>> getFollowingNovels(String restrict,
[String? nextUrl]) async {
var res = await apiGet(nextUrl ?? "/v1/novel/follow?restrict=$restrict");
if (res.success) {
return Res(
(res.data["novels"] as List).map((e) => Novel.fromJson(e)).toList(),
subData: res.data["next_url"],
);
} else {
return Res.error(res.errorMessage);
}
}
} }

View File

@@ -0,0 +1,83 @@
import 'package:fluent_ui/fluent_ui.dart';
import 'package:pixes/components/grid.dart';
import 'package:pixes/components/loading.dart';
import 'package:pixes/components/novel.dart';
import 'package:pixes/components/segmented_button.dart';
import 'package:pixes/components/title_bar.dart';
import 'package:pixes/foundation/widget_utils.dart';
import 'package:pixes/network/network.dart';
import 'package:pixes/utils/translation.dart';
class FollowingNovelsPage extends StatefulWidget {
const FollowingNovelsPage({super.key});
@override
State<FollowingNovelsPage> createState() => _FollowingNovelsPageState();
}
class _FollowingNovelsPageState
extends MultiPageLoadingState<FollowingNovelsPage, Novel> {
bool public = true;
@override
Widget? buildFrame(BuildContext context, Widget child) {
return Column(
children: [
TitleBar(
title: "Following".tl,
action: SegmentedButton(
options: [
SegmentedButtonOption("public", "Public".tl),
SegmentedButtonOption("private", "Private".tl),
],
onPressed: (key) {
var newPublic = key == "public";
if (newPublic != public) {
public = newPublic;
nextUrl = null;
reset();
}
},
value: public ? "public" : "private",
),
),
Expanded(
child: child,
)
],
);
}
@override
Widget buildContent(BuildContext context, List<Novel> data) {
return Column(
children: [
Expanded(
child: GridViewWithFixedItemHeight(
itemCount: data.length,
itemHeight: 164,
minCrossAxisExtent: 400,
builder: (context, index) {
if (index == data.length - 1) {
nextPage();
}
return NovelWidget(data[index]);
},
).paddingHorizontal(8),
)
],
);
}
String? nextUrl;
@override
Future<Res<List<Novel>>> loadData(int page) async {
if (nextUrl == "end") return Res.error("No more data");
var res = nextUrl == null
? await Network().getFollowingNovels(public ? "public" : "private")
: await Network().getNovelsWithNextUrl(nextUrl!);
nextUrl = res.subData ?? "end";
return res;
}
}

View File

@@ -11,6 +11,7 @@ import "package:pixes/network/network.dart";
import "package:pixes/pages/bookmarks.dart"; import "package:pixes/pages/bookmarks.dart";
import "package:pixes/pages/downloaded_page.dart"; import "package:pixes/pages/downloaded_page.dart";
import "package:pixes/pages/following_artworks.dart"; import "package:pixes/pages/following_artworks.dart";
import "package:pixes/pages/following_novels_page.dart";
import "package:pixes/pages/history.dart"; import "package:pixes/pages/history.dart";
import "package:pixes/pages/novel_bookmarks_page.dart"; import "package:pixes/pages/novel_bookmarks_page.dart";
import "package:pixes/pages/novel_ranking_page.dart"; import "package:pixes/pages/novel_ranking_page.dart";
@@ -213,6 +214,11 @@ class _MainPageState extends State<MainPage>
title: Text('Bookmarks'.tl), title: Text('Bookmarks'.tl),
body: const SizedBox.shrink(), body: const SizedBox.shrink(),
), ),
PaneItem(
icon: const Icon(MdIcons.interests_outlined, size: 20),
title: Text('Following'.tl),
body: const SizedBox.shrink(),
),
PaneItem( PaneItem(
icon: const Icon(MdIcons.leaderboard_outlined, size: 20), icon: const Icon(MdIcons.leaderboard_outlined, size: 20),
title: Text('Ranking'.tl), title: Text('Ranking'.tl),
@@ -253,6 +259,7 @@ class _MainPageState extends State<MainPage>
() => const RankingPage(), () => const RankingPage(),
() => const NovelRecommendationPage(), () => const NovelRecommendationPage(),
() => const NovelBookmarksPage(), () => const NovelBookmarksPage(),
() => const FollowingNovelsPage(),
() => const NovelRankingPage(), () => const NovelRankingPage(),
() => const SettingsPage(), () => const SettingsPage(),
]; ];