feat: 动态点赞/取消赞
This commit is contained in:
@ -145,6 +145,10 @@ class Api {
|
||||
// https://api.bilibili.com/x/polymer/web-dynamic/v1/feed/all?host_mid=548196587&offset=&page=1&features=itemOpusStyle
|
||||
static const String followDynamic = '/x/polymer/web-dynamic/v1/feed/all';
|
||||
|
||||
// 动态点赞
|
||||
static const String likeDynamic =
|
||||
'https://api.vc.bilibili.com/dynamic_like/v1/dynamic_like/thumb';
|
||||
|
||||
// 获取稍后再看
|
||||
static const String seeYouLater = '/x/v2/history/toview';
|
||||
|
||||
|
@ -1,4 +1,5 @@
|
||||
class HttpString {
|
||||
static const String baseUrl = 'https://www.bilibili.com';
|
||||
static const String baseApiUrl = 'https://api.bilibili.com';
|
||||
static const String tUrl = 'https://api.vc.bilibili.com';
|
||||
}
|
||||
|
@ -50,4 +50,31 @@ class DynamicsHttp {
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// 动态点赞
|
||||
static Future likeDynamic({
|
||||
required String? dynamicId,
|
||||
required int? up,
|
||||
}) async {
|
||||
var res = await Request().post(
|
||||
Api.likeDynamic,
|
||||
queryParameters: {
|
||||
'dynamic_id': dynamicId,
|
||||
'up': up,
|
||||
'csrf': await Request.getCsrf(),
|
||||
},
|
||||
);
|
||||
if (res.data['code'] == 0) {
|
||||
return {
|
||||
'status': true,
|
||||
'data': res.data['data'],
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
'status': false,
|
||||
'data': [],
|
||||
'msg': res.data['message'],
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -38,6 +38,8 @@ class Request {
|
||||
dio.interceptors.add(cookieManager);
|
||||
var cookie = await cookieManager.cookieJar
|
||||
.loadForRequest(Uri.parse(HttpString.baseUrl));
|
||||
var cookie2 = await cookieManager.cookieJar
|
||||
.loadForRequest(Uri.parse(HttpString.tUrl));
|
||||
if (cookie.isEmpty) {
|
||||
try {
|
||||
await Request().get(HttpString.baseUrl);
|
||||
@ -45,6 +47,13 @@ class Request {
|
||||
log("setCookie, ${e.toString()}");
|
||||
}
|
||||
}
|
||||
if (cookie2.isEmpty) {
|
||||
try {
|
||||
await Request().get(HttpString.tUrl);
|
||||
} catch (e) {
|
||||
log("setCookie, ${e.toString()}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 移除cookie
|
||||
@ -99,7 +108,6 @@ class Request {
|
||||
options.headers['x-bili-mid'] = user.get(UserBoxKey.userMid).toString();
|
||||
}
|
||||
dio.options = options;
|
||||
|
||||
//添加拦截器
|
||||
dio.interceptors
|
||||
..add(ApiInterceptor())
|
||||
|
@ -46,9 +46,9 @@ class DynamicsController extends GetxController {
|
||||
RxInt initialValue = 1.obs;
|
||||
|
||||
Future queryFollowDynamic({type = 'init'}) async {
|
||||
// if (type == 'init') {
|
||||
// dynamicsList!.value = [];
|
||||
// }
|
||||
if (type == 'init') {
|
||||
dynamicsList.clear();
|
||||
}
|
||||
var res = await DynamicsHttp.followDynamic(
|
||||
page: type == 'init' ? 1 : page,
|
||||
type: dynamicsType.value.values,
|
||||
|
@ -236,7 +236,7 @@ class _DynamicsPageState extends State<DynamicsPage>
|
||||
List<DynamicItemModel> list =
|
||||
_dynamicsController.dynamicsList;
|
||||
return Obx(
|
||||
() => list.length == 1
|
||||
() => list.isEmpty
|
||||
? skeleton()
|
||||
: SliverList(
|
||||
delegate:
|
||||
|
@ -1,55 +1,118 @@
|
||||
// 操作栏
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
|
||||
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:pilipala/http/dynamics.dart';
|
||||
import 'package:pilipala/models/dynamics/result.dart';
|
||||
import 'package:pilipala/pages/dynamics/index.dart';
|
||||
|
||||
final DynamicsController _dynamicsController = Get.put(DynamicsController());
|
||||
class ActionPanel extends StatefulWidget {
|
||||
ActionPanel({
|
||||
super.key,
|
||||
this.item,
|
||||
});
|
||||
var item;
|
||||
|
||||
Widget action(item, context) {
|
||||
ModuleStatModel stat = item.modules.moduleStat;
|
||||
|
||||
return Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||
children: [
|
||||
TextButton.icon(
|
||||
onPressed: () {},
|
||||
icon: const Icon(
|
||||
FontAwesomeIcons.shareFromSquare,
|
||||
size: 16,
|
||||
),
|
||||
style: TextButton.styleFrom(
|
||||
padding: const EdgeInsets.fromLTRB(15, 0, 15, 0),
|
||||
foregroundColor: Theme.of(context).colorScheme.outline,
|
||||
),
|
||||
label: Text(stat.forward!.count ?? '转发'),
|
||||
),
|
||||
TextButton.icon(
|
||||
onPressed: () =>
|
||||
_dynamicsController.pushDetail(item, 1, action: 'comment'),
|
||||
icon: const Icon(
|
||||
FontAwesomeIcons.comment,
|
||||
size: 16,
|
||||
),
|
||||
style: TextButton.styleFrom(
|
||||
padding: const EdgeInsets.fromLTRB(15, 0, 15, 0),
|
||||
foregroundColor: Theme.of(context).colorScheme.outline,
|
||||
),
|
||||
label: Text(stat.comment!.count ?? '评论'),
|
||||
),
|
||||
TextButton.icon(
|
||||
onPressed: () {},
|
||||
icon: const Icon(
|
||||
FontAwesomeIcons.thumbsUp,
|
||||
size: 16,
|
||||
),
|
||||
style: TextButton.styleFrom(
|
||||
padding: const EdgeInsets.fromLTRB(15, 0, 15, 0),
|
||||
foregroundColor: Theme.of(context).colorScheme.outline,
|
||||
),
|
||||
label: Text(stat.like!.count ?? '点赞'),
|
||||
)
|
||||
],
|
||||
);
|
||||
@override
|
||||
State<ActionPanel> createState() => _ActionPanelState();
|
||||
}
|
||||
|
||||
class _ActionPanelState extends State<ActionPanel> {
|
||||
final DynamicsController _dynamicsController = Get.put(DynamicsController());
|
||||
late ModuleStatModel stat;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
stat = widget.item!.modules.moduleStat;
|
||||
}
|
||||
|
||||
// 动态点赞
|
||||
onLikeDynamic() async {
|
||||
var item = widget.item!;
|
||||
String dynamicId = item.idStr!;
|
||||
// 1 已点赞 2 不喜欢 0 未操作
|
||||
Like like = item.modules.moduleStat.like;
|
||||
int count = int.parse(like.count!);
|
||||
bool status = like.status!;
|
||||
int up = status ? 2 : 1;
|
||||
var res = await DynamicsHttp.likeDynamic(dynamicId: dynamicId, up: up);
|
||||
if (res['status']) {
|
||||
SmartDialog.showToast(!status ? '点赞成功' : '取消赞');
|
||||
if (up == 1) {
|
||||
item.modules.moduleStat.like.count = (count + 1).toString();
|
||||
item.modules.moduleStat.like.status = true;
|
||||
} else {
|
||||
item.modules.moduleStat.like.count = (count - 1).toString();
|
||||
item.modules.moduleStat.like.status = false;
|
||||
}
|
||||
setState(() {});
|
||||
} else {
|
||||
SmartDialog.showToast(res['msg']);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
var color = Theme.of(context).colorScheme.outline;
|
||||
var primary = Theme.of(context).colorScheme.primary;
|
||||
return Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||
children: [
|
||||
TextButton.icon(
|
||||
onPressed: () {},
|
||||
icon: const Icon(
|
||||
FontAwesomeIcons.shareFromSquare,
|
||||
size: 16,
|
||||
),
|
||||
style: TextButton.styleFrom(
|
||||
padding: const EdgeInsets.fromLTRB(15, 0, 15, 0),
|
||||
foregroundColor: Theme.of(context).colorScheme.outline,
|
||||
),
|
||||
label: Text(stat.forward!.count ?? '转发'),
|
||||
),
|
||||
TextButton.icon(
|
||||
onPressed: () =>
|
||||
_dynamicsController.pushDetail(widget.item, 1, action: 'comment'),
|
||||
icon: const Icon(
|
||||
FontAwesomeIcons.comment,
|
||||
size: 16,
|
||||
),
|
||||
style: TextButton.styleFrom(
|
||||
padding: const EdgeInsets.fromLTRB(15, 0, 15, 0),
|
||||
foregroundColor: Theme.of(context).colorScheme.outline,
|
||||
),
|
||||
label: Text(stat.comment!.count ?? '评论'),
|
||||
),
|
||||
TextButton.icon(
|
||||
onPressed: () => onLikeDynamic(),
|
||||
icon: Icon(
|
||||
stat.like!.status!
|
||||
? FontAwesomeIcons.solidThumbsUp
|
||||
: FontAwesomeIcons.thumbsUp,
|
||||
size: 16,
|
||||
color: stat.like!.status! ? primary : color,
|
||||
),
|
||||
style: TextButton.styleFrom(
|
||||
padding: const EdgeInsets.fromLTRB(15, 0, 15, 0),
|
||||
foregroundColor: Theme.of(context).colorScheme.outline,
|
||||
),
|
||||
label: AnimatedSwitcher(
|
||||
duration: const Duration(milliseconds: 400),
|
||||
transitionBuilder: (Widget child, Animation<double> animation) {
|
||||
return ScaleTransition(scale: animation, child: child);
|
||||
},
|
||||
child: Text(
|
||||
stat.like!.count ?? '点赞',
|
||||
key: ValueKey<String>(stat.like!.count!),
|
||||
style: TextStyle(
|
||||
color: stat.like!.status! ? primary : color,
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -42,7 +42,7 @@ class DynamicPanel extends StatelessWidget {
|
||||
content(item, context, source),
|
||||
forWard(item, context, _dynamicsController, source),
|
||||
const SizedBox(height: 2),
|
||||
if (source == null) action(item, context),
|
||||
if (source == null) ActionPanel(item: item),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
@ -58,10 +58,13 @@ class WebviewController extends GetxController {
|
||||
try {
|
||||
var cookies =
|
||||
await WebviewCookieManager().getCookies(HttpString.baseUrl);
|
||||
var apiCookies =
|
||||
await WebviewCookieManager().getCookies(HttpString.baseUrl);
|
||||
var apiCookies = await WebviewCookieManager()
|
||||
.getCookies(HttpString.baseApiUrl);
|
||||
var tCookies =
|
||||
await WebviewCookieManager().getCookies(HttpString.tUrl);
|
||||
await SetCookie.onSet(cookies, HttpString.baseUrl);
|
||||
await SetCookie.onSet(apiCookies, HttpString.baseApiUrl);
|
||||
await SetCookie.onSet(tCookies, HttpString.tUrl);
|
||||
await UserHttp.userInfo();
|
||||
var result = await UserHttp.userInfo();
|
||||
print('网页登录: $result');
|
||||
|
Reference in New Issue
Block a user