feat: fav article

Closes #727

Signed-off-by: bggRGjQaUbCoE <githubaccount56556@proton.me>
This commit is contained in:
bggRGjQaUbCoE
2025-04-23 11:59:48 +08:00
parent 0d27d88719
commit a0abd472e0
9 changed files with 120 additions and 15 deletions

View File

@@ -792,9 +792,9 @@ class _DynamicDetailPageState extends State<DynamicDetailPage>
_dynamicDetailController.onLoadMore();
return Container(
alignment: Alignment.center,
padding: EdgeInsets.only(
margin: EdgeInsets.only(
bottom: MediaQuery.of(context).padding.bottom),
height: MediaQuery.of(context).padding.bottom + 100,
height: 125,
child: Text(
_dynamicDetailController.isEnd.not
? '加载中...'

View File

@@ -1,6 +1,7 @@
import 'package:PiliPlus/grpc/app/main/community/reply/v1/reply.pb.dart';
import 'package:PiliPlus/http/dynamics.dart';
import 'package:PiliPlus/http/loading_state.dart';
import 'package:PiliPlus/http/user.dart';
import 'package:PiliPlus/http/video.dart';
import 'package:PiliPlus/models/dynamics/result.dart';
import 'package:PiliPlus/pages/common/reply_controller.dart';
@@ -8,6 +9,7 @@ import 'package:PiliPlus/pages/mine/controller.dart';
import 'package:PiliPlus/utils/storage.dart';
import 'package:PiliPlus/utils/url_utils.dart';
import 'package:flutter/material.dart';
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
import 'package:get/get.dart';
import 'package:PiliPlus/http/html.dart';
import 'package:PiliPlus/http/reply.dart';
@@ -24,7 +26,8 @@ class HtmlRenderController extends ReplyController<MainListReply> {
Rx<DynamicItemModel> item = DynamicItemModel().obs;
RxBool loaded = false.obs;
final RxMap favStat = <dynamic, dynamic>{'status': false}.obs;
final RxBool loaded = false.obs;
late final horizontalPreview = GStorage.horizontalPreview;
late final showDynActionBar = GStorage.showDynActionBar;
@@ -40,13 +43,22 @@ class HtmlRenderController extends ReplyController<MainListReply> {
type = dynamicType == 'picture' ? 11 : 12;
if (showDynActionBar) {
if (RegExp(r'^cv', caseSensitive: false).hasMatch(id)) {
if (dynamicType == 'read') {
UrlUtils.parseRedirectUrl('https://www.bilibili.com/read/$id/')
.then((url) {
if (url != null) {
_queryDyn(url.split('/').last);
}
});
DynamicsHttp.articleInfo(cvId: id.substring(2)).then((res) {
if (res['status']) {
favStat.value = {
'status': true,
'isFav': res['data']?['favorite'] ?? false,
'favNum': res['data']?['stats']?['favorite'] ?? 0,
};
}
});
} else {
_queryDyn(id);
}
@@ -72,6 +84,13 @@ class HtmlRenderController extends ReplyController<MainListReply> {
res = await HtmlHttp.reqHtml(id, dynamicType);
if (res != null) {
type = res['commentType'];
if (res['favorite'] != null) {
favStat.value = {
'status': true,
'isFav': res['favorite']['status'] ?? false,
'favNum': res['favorite']['count'] ?? 0,
};
}
}
} else {
res = await HtmlHttp.reqReadHtml(id, dynamicType);
@@ -80,7 +99,7 @@ class HtmlRenderController extends ReplyController<MainListReply> {
response = res;
mid = res['mid'];
oid.value = res['commentId'];
if (Accounts.main.isLogin && !MineController.anonymity.value) {
if (isLogin && !MineController.anonymity.value) {
VideoHttp.historyReport(aid: oid.value, type: 5);
}
queryData();
@@ -107,4 +126,24 @@ class HtmlRenderController extends ReplyController<MainListReply> {
antiGoodsReply: antiGoodsReply,
);
}
Future onFav() async {
bool isFav = favStat['isFav'] == true;
final res = dynamicType == 'read'
? isFav
? await UserHttp.delFavArticle(id: id.substring(2))
: await UserHttp.addFavArticle(id: id.substring(2))
: await UserHttp.communityAction(opusId: id, action: isFav ? 4 : 3);
if (res['status']) {
favStat['isFav'] = !isFav;
if (isFav) {
favStat['favNum'] -= 1;
} else {
favStat['favNum'] += 1;
}
SmartDialog.showToast('${isFav ? '取消' : ''}收藏成功');
} else {
SmartDialog.showToast(res['msg']);
}
}
}

View File

@@ -636,6 +636,46 @@ class _HtmlRenderPageState extends State<HtmlRenderPage>
label: const Text('分享'),
),
),
if (_htmlRenderCtr
.favStat['status'])
Expanded(
child: TextButton.icon(
onPressed: () {
_htmlRenderCtr.onFav();
},
icon: Icon(
_htmlRenderCtr.favStat[
'isFav'] ==
true
? FontAwesomeIcons
.solidStar
: FontAwesomeIcons.star,
size: 16,
color:
_htmlRenderCtr.favStat[
'isFav'] ==
true
? Theme.of(context)
.colorScheme
.primary
: Theme.of(context)
.colorScheme
.outline,
semanticLabel: "收藏",
),
style: TextButton.styleFrom(
padding: const EdgeInsets
.fromLTRB(15, 0, 15, 0),
foregroundColor:
Theme.of(context)
.colorScheme
.outline,
),
label: Text(_htmlRenderCtr
.favStat['favNum']
.toString()),
),
),
Expanded(
child: Builder(
builder: (context) =>
@@ -781,9 +821,9 @@ class _HtmlRenderPageState extends State<HtmlRenderPage>
_htmlRenderCtr.onLoadMore();
return Container(
alignment: Alignment.center,
padding: EdgeInsets.only(
margin: EdgeInsets.only(
bottom: MediaQuery.of(context).padding.bottom),
height: MediaQuery.of(context).padding.bottom + 100,
height: 125,
child: Text(
_htmlRenderCtr.isEnd.not
? '加载中...'

View File

@@ -407,9 +407,9 @@ class _VideoReplyReplyPanelState
_videoReplyReplyController.onLoadMore();
return Container(
alignment: Alignment.center,
padding: EdgeInsets.only(
margin: EdgeInsets.only(
bottom: MediaQuery.of(context).padding.bottom),
height: MediaQuery.of(context).padding.bottom + 100,
height: 125,
child: Text(
_videoReplyReplyController.isEnd.not
? '加载中...'