Merge branch 'design'
This commit is contained in:
@ -606,4 +606,7 @@ class Api {
|
|||||||
|
|
||||||
/// 番剧点赞投币收藏状态
|
/// 番剧点赞投币收藏状态
|
||||||
static const String bangumiActionStatus = '/pgc/season/episode/community';
|
static const String bangumiActionStatus = '/pgc/season/episode/community';
|
||||||
|
|
||||||
|
/// @我的
|
||||||
|
static const String messageAtAPi = '/x/msgfeed/at?';
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
import 'dart:math';
|
import 'dart:math';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:pilipala/models/msg/at.dart';
|
||||||
import 'package:pilipala/models/msg/like.dart';
|
import 'package:pilipala/models/msg/like.dart';
|
||||||
import 'package:pilipala/models/msg/reply.dart';
|
import 'package:pilipala/models/msg/reply.dart';
|
||||||
import 'package:pilipala/models/msg/system.dart';
|
import 'package:pilipala/models/msg/system.dart';
|
||||||
@ -350,4 +351,24 @@ class MsgHttp {
|
|||||||
return {'status': false, 'date': [], 'msg': res.data['message']};
|
return {'status': false, 'date': [], 'msg': res.data['message']};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// @我的
|
||||||
|
static Future messageAt() async {
|
||||||
|
var res = await Request().get(Api.messageAtAPi, data: {
|
||||||
|
'build': 0,
|
||||||
|
'mobi_app': 'web',
|
||||||
|
});
|
||||||
|
if (res.data['code'] == 0) {
|
||||||
|
try {
|
||||||
|
return {
|
||||||
|
'status': true,
|
||||||
|
'data': MessageAtModel.fromJson(res.data['data']),
|
||||||
|
};
|
||||||
|
} catch (err) {
|
||||||
|
return {'status': false, 'data': [], 'msg': err.toString()};
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return {'status': false, 'data': [], 'msg': res.data['message']};
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -136,13 +136,13 @@ class ReplyHttp {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 图片上传
|
// 图片上传
|
||||||
static Future uploadImage({required XFile xFile, String type = 'im'}) async {
|
static Future uploadImage(
|
||||||
|
{required XFile xFile, String type = 'new_dyn'}) async {
|
||||||
var formData = FormData.fromMap({
|
var formData = FormData.fromMap({
|
||||||
'file_up': await xFileToMultipartFile(xFile),
|
'file_up': await xFileToMultipartFile(xFile),
|
||||||
'biz': type,
|
'biz': type,
|
||||||
'csrf': await Request.getCsrf(),
|
'csrf': await Request.getCsrf(),
|
||||||
'build': 0,
|
'category': 'daily',
|
||||||
'mobi_app': 'web',
|
|
||||||
});
|
});
|
||||||
var res = await Request().post(
|
var res = await Request().post(
|
||||||
Api.uploadImage,
|
Api.uploadImage,
|
||||||
|
|||||||
140
lib/models/msg/at.dart
Normal file
140
lib/models/msg/at.dart
Normal file
@ -0,0 +1,140 @@
|
|||||||
|
class MessageAtModel {
|
||||||
|
Cursor? cursor;
|
||||||
|
List<MessageAtItems>? items;
|
||||||
|
|
||||||
|
MessageAtModel({this.cursor, this.items});
|
||||||
|
|
||||||
|
MessageAtModel.fromJson(Map<String, dynamic> json) {
|
||||||
|
cursor = json['cursor'] != null ? Cursor.fromJson(json['cursor']) : null;
|
||||||
|
if (json['items'] != null) {
|
||||||
|
items = <MessageAtItems>[];
|
||||||
|
json['items'].forEach((v) {
|
||||||
|
items!.add(MessageAtItems.fromJson(v));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Cursor {
|
||||||
|
Cursor({
|
||||||
|
this.id,
|
||||||
|
this.isEnd,
|
||||||
|
this.time,
|
||||||
|
});
|
||||||
|
|
||||||
|
int? id;
|
||||||
|
bool? isEnd;
|
||||||
|
int? time;
|
||||||
|
|
||||||
|
Cursor.fromJson(Map<String, dynamic> json) {
|
||||||
|
id = json['id'];
|
||||||
|
isEnd = json['isEnd'];
|
||||||
|
time = json['time'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class MessageAtItems {
|
||||||
|
int? id;
|
||||||
|
int? atTime;
|
||||||
|
User? user;
|
||||||
|
MessageAtItem? item;
|
||||||
|
|
||||||
|
MessageAtItems({this.id, this.atTime, this.user, this.item});
|
||||||
|
|
||||||
|
MessageAtItems.fromJson(Map<String, dynamic> json) {
|
||||||
|
id = json['id'];
|
||||||
|
atTime = json['at_time'];
|
||||||
|
user = json['user'] != null ? User.fromJson(json['user']) : null;
|
||||||
|
item = json['item'] != null ? MessageAtItem.fromJson(json['item']) : null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class MessageAtItem {
|
||||||
|
String? type;
|
||||||
|
String? business;
|
||||||
|
int? businessId;
|
||||||
|
String? title;
|
||||||
|
String? image;
|
||||||
|
String? uri;
|
||||||
|
int? subjectId;
|
||||||
|
int? rootId;
|
||||||
|
int? targetId;
|
||||||
|
int? sourceId;
|
||||||
|
String? sourceContent;
|
||||||
|
String? nativeUri;
|
||||||
|
List<User>? atDetails;
|
||||||
|
List<dynamic>? topicDetails;
|
||||||
|
bool? hideReplyButton;
|
||||||
|
|
||||||
|
MessageAtItem({
|
||||||
|
this.type,
|
||||||
|
this.business,
|
||||||
|
this.businessId,
|
||||||
|
this.title,
|
||||||
|
this.image,
|
||||||
|
this.uri,
|
||||||
|
this.subjectId,
|
||||||
|
this.rootId,
|
||||||
|
this.targetId,
|
||||||
|
this.sourceId,
|
||||||
|
this.sourceContent,
|
||||||
|
this.nativeUri,
|
||||||
|
this.atDetails,
|
||||||
|
this.topicDetails,
|
||||||
|
this.hideReplyButton,
|
||||||
|
});
|
||||||
|
|
||||||
|
MessageAtItem.fromJson(Map<String, dynamic> json) {
|
||||||
|
type = json['type'];
|
||||||
|
business = json['business'];
|
||||||
|
businessId = json['business_id'];
|
||||||
|
title = json['title'];
|
||||||
|
image = json['image'];
|
||||||
|
uri = json['uri'];
|
||||||
|
subjectId = json['subject_id'];
|
||||||
|
rootId = json['root_id'];
|
||||||
|
targetId = json['target_id'];
|
||||||
|
sourceId = json['source_id'];
|
||||||
|
sourceContent = json['source_content'];
|
||||||
|
nativeUri = json['native_uri'];
|
||||||
|
if (json['at_details'] != null) {
|
||||||
|
atDetails = <User>[];
|
||||||
|
json['at_details'].forEach((v) {
|
||||||
|
atDetails!.add(User.fromJson(v));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (json['topic_details'] != null) {
|
||||||
|
topicDetails = <dynamic>[];
|
||||||
|
json['topic_details'].forEach((v) {
|
||||||
|
topicDetails!.add(v);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
hideReplyButton = json['hide_reply_button'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class User {
|
||||||
|
int? mid;
|
||||||
|
int? fans;
|
||||||
|
String? nickname;
|
||||||
|
String? avatar;
|
||||||
|
String? midLink;
|
||||||
|
bool? follow;
|
||||||
|
|
||||||
|
User(
|
||||||
|
{this.mid,
|
||||||
|
this.fans,
|
||||||
|
this.nickname,
|
||||||
|
this.avatar,
|
||||||
|
this.midLink,
|
||||||
|
this.follow});
|
||||||
|
|
||||||
|
User.fromJson(Map<String, dynamic> json) {
|
||||||
|
mid = json['mid'];
|
||||||
|
fans = json['fans'];
|
||||||
|
nickname = json['nickname'];
|
||||||
|
avatar = json['avatar'];
|
||||||
|
midLink = json['mid_link'];
|
||||||
|
follow = json['follow'];
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
|
|||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
import 'package:pilipala/http/member.dart';
|
import 'package:pilipala/http/member.dart';
|
||||||
import 'package:pilipala/models/member/archive.dart';
|
import 'package:pilipala/models/member/archive.dart';
|
||||||
|
import 'package:pilipala/utils/global_data_cache.dart';
|
||||||
|
|
||||||
class MemberArchiveController extends GetxController {
|
class MemberArchiveController extends GetxController {
|
||||||
final ScrollController scrollController = ScrollController();
|
final ScrollController scrollController = ScrollController();
|
||||||
@ -17,12 +18,18 @@ class MemberArchiveController extends GetxController {
|
|||||||
].obs;
|
].obs;
|
||||||
RxList<VListItemModel> archivesList = <VListItemModel>[].obs;
|
RxList<VListItemModel> archivesList = <VListItemModel>[].obs;
|
||||||
RxBool isLoading = false.obs;
|
RxBool isLoading = false.obs;
|
||||||
|
late int ownerMid;
|
||||||
|
RxBool isOwner = false.obs;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void onInit() {
|
void onInit() {
|
||||||
super.onInit();
|
super.onInit();
|
||||||
mid = int.parse(Get.parameters['mid']!);
|
mid = int.parse(Get.parameters['mid']!);
|
||||||
currentOrder.value = orderList.first;
|
currentOrder.value = orderList.first;
|
||||||
|
ownerMid = GlobalDataCache().userInfo != null
|
||||||
|
? GlobalDataCache().userInfo!.mid!
|
||||||
|
: -1;
|
||||||
|
isOwner.value = mid == -1 || mid == ownerMid;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取用户投稿
|
// 获取用户投稿
|
||||||
|
|||||||
@ -51,8 +51,9 @@ class _MemberArchivePageState extends State<MemberArchivePage> {
|
|||||||
centerTitle: false,
|
centerTitle: false,
|
||||||
title: Obx(
|
title: Obx(
|
||||||
() => Text(
|
() => Text(
|
||||||
'他的投稿 - ${_memberArchivesController.currentOrder['label']}',
|
'${_memberArchivesController.isOwner.value ? '我' : 'Ta'}的投稿 - ${_memberArchivesController.currentOrder['label']}',
|
||||||
style: Theme.of(context).textTheme.titleMedium),
|
style: Theme.of(context).textTheme.titleMedium,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
actions: [
|
actions: [
|
||||||
// Obx(
|
// Obx(
|
||||||
|
|||||||
@ -3,6 +3,7 @@ import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
|
|||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
import 'package:pilipala/http/member.dart';
|
import 'package:pilipala/http/member.dart';
|
||||||
import 'package:pilipala/models/member/article.dart';
|
import 'package:pilipala/models/member/article.dart';
|
||||||
|
import 'package:pilipala/utils/global_data_cache.dart';
|
||||||
|
|
||||||
class MemberArticleController extends GetxController {
|
class MemberArticleController extends GetxController {
|
||||||
final ScrollController scrollController = ScrollController();
|
final ScrollController scrollController = ScrollController();
|
||||||
@ -12,11 +13,17 @@ class MemberArticleController extends GetxController {
|
|||||||
bool hasMore = true;
|
bool hasMore = true;
|
||||||
RxBool isLoading = false.obs;
|
RxBool isLoading = false.obs;
|
||||||
RxList<MemberArticleItemModel> articleList = <MemberArticleItemModel>[].obs;
|
RxList<MemberArticleItemModel> articleList = <MemberArticleItemModel>[].obs;
|
||||||
|
late int ownerMid;
|
||||||
|
RxBool isOwner = false.obs;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void onInit() {
|
void onInit() {
|
||||||
super.onInit();
|
super.onInit();
|
||||||
mid = int.parse(Get.parameters['mid']!);
|
mid = int.parse(Get.parameters['mid']!);
|
||||||
|
ownerMid = GlobalDataCache().userInfo != null
|
||||||
|
? GlobalDataCache().userInfo!.mid!
|
||||||
|
: -1;
|
||||||
|
isOwner.value = mid == -1 || mid == ownerMid;
|
||||||
}
|
}
|
||||||
|
|
||||||
Future getMemberArticle(type) async {
|
Future getMemberArticle(type) async {
|
||||||
|
|||||||
@ -50,7 +50,12 @@ class _MemberArticlePageState extends State<MemberArticlePage> {
|
|||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
titleSpacing: 0,
|
titleSpacing: 0,
|
||||||
centerTitle: false,
|
centerTitle: false,
|
||||||
title: const Text('Ta的图文', style: TextStyle(fontSize: 16)),
|
title: Obx(
|
||||||
|
() => Text(
|
||||||
|
'${_memberArticleController.isOwner.value ? '我' : 'Ta'}的图文',
|
||||||
|
style: Theme.of(context).textTheme.titleMedium,
|
||||||
|
),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
body: FutureBuilder(
|
body: FutureBuilder(
|
||||||
future: _futureBuilderFuture,
|
future: _futureBuilderFuture,
|
||||||
|
|||||||
@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
|
|||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
import 'package:pilipala/http/member.dart';
|
import 'package:pilipala/http/member.dart';
|
||||||
import 'package:pilipala/models/dynamics/result.dart';
|
import 'package:pilipala/models/dynamics/result.dart';
|
||||||
|
import 'package:pilipala/utils/global_data_cache.dart';
|
||||||
|
|
||||||
class MemberDynamicsController extends GetxController {
|
class MemberDynamicsController extends GetxController {
|
||||||
final ScrollController scrollController = ScrollController();
|
final ScrollController scrollController = ScrollController();
|
||||||
@ -10,11 +11,17 @@ class MemberDynamicsController extends GetxController {
|
|||||||
int count = 0;
|
int count = 0;
|
||||||
bool hasMore = true;
|
bool hasMore = true;
|
||||||
RxList<DynamicItemModel> dynamicsList = <DynamicItemModel>[].obs;
|
RxList<DynamicItemModel> dynamicsList = <DynamicItemModel>[].obs;
|
||||||
|
late int ownerMid;
|
||||||
|
RxBool isOwner = false.obs;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void onInit() {
|
void onInit() {
|
||||||
super.onInit();
|
super.onInit();
|
||||||
mid = int.parse(Get.parameters['mid']!);
|
mid = int.parse(Get.parameters['mid']!);
|
||||||
|
ownerMid = GlobalDataCache().userInfo != null
|
||||||
|
? GlobalDataCache().userInfo!.mid!
|
||||||
|
: -1;
|
||||||
|
isOwner.value = mid == -1 || mid == ownerMid;
|
||||||
}
|
}
|
||||||
|
|
||||||
Future getMemberDynamic(type) async {
|
Future getMemberDynamic(type) async {
|
||||||
|
|||||||
@ -56,7 +56,12 @@ class _MemberDynamicsPageState extends State<MemberDynamicsPage> {
|
|||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
titleSpacing: 0,
|
titleSpacing: 0,
|
||||||
centerTitle: false,
|
centerTitle: false,
|
||||||
title: Text('他的动态', style: Theme.of(context).textTheme.titleMedium),
|
title: Obx(
|
||||||
|
() => Text(
|
||||||
|
'${_memberDynamicController.isOwner.value ? '我' : 'Ta'}的动态',
|
||||||
|
style: Theme.of(context).textTheme.titleMedium,
|
||||||
|
),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
body: CustomScrollView(
|
body: CustomScrollView(
|
||||||
controller: _memberDynamicController.scrollController,
|
controller: _memberDynamicController.scrollController,
|
||||||
|
|||||||
@ -1,3 +1,27 @@
|
|||||||
|
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
|
import 'package:pilipala/http/msg.dart';
|
||||||
|
import 'package:pilipala/models/msg/at.dart';
|
||||||
|
|
||||||
class MessageAtController extends GetxController {}
|
class MessageAtController extends GetxController {
|
||||||
|
Cursor? cursor;
|
||||||
|
RxList<MessageAtItems> atItems = <MessageAtItems>[].obs;
|
||||||
|
|
||||||
|
Future queryMessageAt({String type = 'init'}) async {
|
||||||
|
if (cursor != null && cursor!.isEnd == true) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
var res = await MsgHttp.messageAt();
|
||||||
|
if (res['status']) {
|
||||||
|
cursor = res['data'].cursor;
|
||||||
|
if (type == 'init') {
|
||||||
|
atItems.value = res['data'].items;
|
||||||
|
} else {
|
||||||
|
atItems.addAll(res['data'].items);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
SmartDialog.showToast(res['msg']);
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -1,4 +1,14 @@
|
|||||||
|
import 'package:easy_debounce/easy_throttle.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:get/get.dart';
|
||||||
|
import 'package:pilipala/common/widgets/http_error.dart';
|
||||||
|
import 'package:pilipala/common/widgets/network_img_layer.dart';
|
||||||
|
import 'package:pilipala/common/widgets/no_data.dart';
|
||||||
|
import 'package:pilipala/models/msg/at.dart';
|
||||||
|
import 'package:pilipala/pages/message/utils/index.dart';
|
||||||
|
import 'package:pilipala/utils/utils.dart';
|
||||||
|
|
||||||
|
import 'controller.dart';
|
||||||
|
|
||||||
class MessageAtPage extends StatefulWidget {
|
class MessageAtPage extends StatefulWidget {
|
||||||
const MessageAtPage({super.key});
|
const MessageAtPage({super.key});
|
||||||
@ -8,12 +18,179 @@ class MessageAtPage extends StatefulWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class _MessageAtPageState extends State<MessageAtPage> {
|
class _MessageAtPageState extends State<MessageAtPage> {
|
||||||
|
final MessageAtController _messageAtCtr = Get.put(MessageAtController());
|
||||||
|
late Future _futureBuilderFuture;
|
||||||
|
final ScrollController scrollController = ScrollController();
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
_futureBuilderFuture = _messageAtCtr.queryMessageAt();
|
||||||
|
scrollController.addListener(
|
||||||
|
() async {
|
||||||
|
if (scrollController.position.pixels >=
|
||||||
|
scrollController.position.maxScrollExtent - 200) {
|
||||||
|
EasyThrottle.throttle('follow', const Duration(seconds: 1), () {
|
||||||
|
_messageAtCtr.queryMessageAt(type: 'onLoad');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
scrollController.dispose();
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
title: const Text('@我的'),
|
title: const Text('@我的'),
|
||||||
),
|
),
|
||||||
|
body: RefreshIndicator(
|
||||||
|
onRefresh: () async {
|
||||||
|
await _messageAtCtr.queryMessageAt(type: 'init');
|
||||||
|
},
|
||||||
|
child: FutureBuilder(
|
||||||
|
future: _futureBuilderFuture,
|
||||||
|
builder: (BuildContext context, AsyncSnapshot snapshot) {
|
||||||
|
if (snapshot.connectionState == ConnectionState.done) {
|
||||||
|
final Map<String, dynamic>? data = snapshot.data;
|
||||||
|
if (data != null && data['status']) {
|
||||||
|
final RxList<MessageAtItems> atItems = _messageAtCtr.atItems;
|
||||||
|
return Obx(
|
||||||
|
() => atItems.isEmpty
|
||||||
|
? const CustomScrollView(slivers: [NoData()])
|
||||||
|
: ListView.separated(
|
||||||
|
controller: scrollController,
|
||||||
|
itemBuilder: (context, index) => AtItem(
|
||||||
|
item: atItems[index],
|
||||||
|
index: index,
|
||||||
|
messageAtCtr: _messageAtCtr,
|
||||||
|
),
|
||||||
|
itemCount: atItems.length,
|
||||||
|
separatorBuilder: (BuildContext context, int index) {
|
||||||
|
return Divider(
|
||||||
|
indent: 66,
|
||||||
|
endIndent: 14,
|
||||||
|
height: 1,
|
||||||
|
color: Colors.grey.withOpacity(0.1),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
// 请求错误
|
||||||
|
return HttpError(
|
||||||
|
errMsg: data?['msg'] ?? '请求异常',
|
||||||
|
fn: () {
|
||||||
|
setState(() {
|
||||||
|
_futureBuilderFuture = _messageAtCtr.queryMessageAt();
|
||||||
|
});
|
||||||
|
},
|
||||||
|
isInSliver: false,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return const SizedBox();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class AtItem extends StatelessWidget {
|
||||||
|
final MessageAtItems item;
|
||||||
|
final int index;
|
||||||
|
final MessageAtController messageAtCtr;
|
||||||
|
|
||||||
|
const AtItem({
|
||||||
|
super.key,
|
||||||
|
required this.item,
|
||||||
|
required this.index,
|
||||||
|
required this.messageAtCtr,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
Color outline = Theme.of(context).colorScheme.outline;
|
||||||
|
final User user = item.user!;
|
||||||
|
final String heroTag = Utils.makeHeroTag(user.mid);
|
||||||
|
final Uri uri = Uri.parse(item.item!.uri!);
|
||||||
|
|
||||||
|
/// bilibili://
|
||||||
|
final Uri nativeUri = Uri.parse(item.item!.nativeUri!);
|
||||||
|
final String type = item.item!.type!;
|
||||||
|
|
||||||
|
return InkWell(
|
||||||
|
onTap: () async {
|
||||||
|
MessageUtils.onClickMessage(context, uri, nativeUri, type);
|
||||||
|
},
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.all(14),
|
||||||
|
child: Row(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
GestureDetector(
|
||||||
|
onTap: () {
|
||||||
|
Get.toNamed('/member?mid=${item.user!.mid}',
|
||||||
|
arguments: {'face': item.user!.avatar, 'heroTag': heroTag});
|
||||||
|
},
|
||||||
|
child: Hero(
|
||||||
|
tag: heroTag,
|
||||||
|
child: NetworkImgLayer(
|
||||||
|
width: 42,
|
||||||
|
height: 42,
|
||||||
|
type: 'avatar',
|
||||||
|
src: item.user!.avatar,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(width: 10),
|
||||||
|
Expanded(
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text.rich(TextSpan(children: [
|
||||||
|
TextSpan(text: item.user!.nickname!),
|
||||||
|
const TextSpan(text: ' '),
|
||||||
|
if (item.item!.type! == 'reply')
|
||||||
|
TextSpan(
|
||||||
|
text: '在评论中@了我',
|
||||||
|
style: TextStyle(color: outline),
|
||||||
|
),
|
||||||
|
])),
|
||||||
|
const SizedBox(height: 6),
|
||||||
|
Text(item.item!.sourceContent!),
|
||||||
|
const SizedBox(height: 4),
|
||||||
|
Text(
|
||||||
|
Utils.dateFormat(item.atTime!, formatType: 'detail'),
|
||||||
|
style: TextStyle(color: outline),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(width: 25),
|
||||||
|
if (item.item!.type! == 'reply')
|
||||||
|
Container(
|
||||||
|
width: 60,
|
||||||
|
height: 80,
|
||||||
|
padding: const EdgeInsets.all(4),
|
||||||
|
child: Text(
|
||||||
|
item.item!.title!,
|
||||||
|
maxLines: 3,
|
||||||
|
style: const TextStyle(fontSize: 12, letterSpacing: 0.3),
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -18,8 +18,12 @@ class MessageLikeController extends GetxController {
|
|||||||
id: params['id'], likeTime: params['likeTime']);
|
id: params['id'], likeTime: params['likeTime']);
|
||||||
if (res['status']) {
|
if (res['status']) {
|
||||||
cursor = res['data'].total.cursor;
|
cursor = res['data'].total.cursor;
|
||||||
|
if (type == 'init') {
|
||||||
|
likeItems.value = res['data'].total.items;
|
||||||
|
} else {
|
||||||
likeItems.addAll(res['data'].total.items);
|
likeItems.addAll(res['data'].total.items);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -13,13 +13,20 @@ class MessageUtils {
|
|||||||
BuildContext context, Uri uri, Uri nativeUri, String type) async {
|
BuildContext context, Uri uri, Uri nativeUri, String type) async {
|
||||||
final String path = uri.path;
|
final String path = uri.path;
|
||||||
final String bvid = path.split('/').last;
|
final String bvid = path.split('/').last;
|
||||||
|
String? sourceType;
|
||||||
final String nativePath = nativeUri.path;
|
final String nativePath = nativeUri.path;
|
||||||
final String oid = nativePath.split('/').last;
|
String oid = nativePath.split('/').last;
|
||||||
final Map<String, String> queryParameters = nativeUri.queryParameters;
|
final Map<String, String> queryParameters = nativeUri.queryParameters;
|
||||||
final String? argCid = queryParameters['cid'];
|
final String? argCid = queryParameters['cid'];
|
||||||
// final String? page = queryParameters['page'];
|
// final String? page = queryParameters['page'];
|
||||||
final String? commentRootId = queryParameters['comment_root_id'];
|
String? commentRootId = queryParameters['comment_root_id'];
|
||||||
// final String? commentSecondaryId = queryParameters['comment_secondary_id'];
|
// final String? commentSecondaryId = queryParameters['comment_secondary_id'];
|
||||||
|
if (nativePath.contains('detail')) {
|
||||||
|
// 动态详情
|
||||||
|
sourceType = 'opus';
|
||||||
|
oid = nativePath.split('/')[3];
|
||||||
|
commentRootId = nativePath.split('/')[4];
|
||||||
|
}
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case 'video':
|
case 'video':
|
||||||
case 'danmu':
|
case 'danmu':
|
||||||
@ -42,7 +49,12 @@ class MessageUtils {
|
|||||||
case 'reply':
|
case 'reply':
|
||||||
debugPrint('commentRootId: $oid, $commentRootId');
|
debugPrint('commentRootId: $oid, $commentRootId');
|
||||||
navigateToComment(
|
navigateToComment(
|
||||||
context, oid, commentRootId!, ReplyType.video, nativeUri);
|
context,
|
||||||
|
oid,
|
||||||
|
commentRootId!,
|
||||||
|
sourceType == 'opus' ? ReplyType.dynamics : ReplyType.video,
|
||||||
|
nativeUri,
|
||||||
|
);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
|||||||
@ -11,7 +11,7 @@ class VideoReplyReplyController extends GetxController {
|
|||||||
int? aid;
|
int? aid;
|
||||||
// rpid 请求楼中楼回复
|
// rpid 请求楼中楼回复
|
||||||
String? rpid;
|
String? rpid;
|
||||||
ReplyType replyType = ReplyType.video;
|
ReplyType? replyType;
|
||||||
bool showRoot = false;
|
bool showRoot = false;
|
||||||
ReplyItemModel? rootReply;
|
ReplyItemModel? rootReply;
|
||||||
RxList<ReplyItemModel> replyList = <ReplyItemModel>[].obs;
|
RxList<ReplyItemModel> replyList = <ReplyItemModel>[].obs;
|
||||||
@ -40,7 +40,7 @@ class VideoReplyReplyController extends GetxController {
|
|||||||
oid: aid!,
|
oid: aid!,
|
||||||
root: rpid!,
|
root: rpid!,
|
||||||
pageNum: currentPage + 1,
|
pageNum: currentPage + 1,
|
||||||
type: replyType.index,
|
type: (replyType ?? ReplyType.video).index,
|
||||||
);
|
);
|
||||||
if (res['status']) {
|
if (res['status']) {
|
||||||
final List<ReplyItemModel> replies = res['data'].replies;
|
final List<ReplyItemModel> replies = res['data'].replies;
|
||||||
|
|||||||
@ -73,11 +73,6 @@ class _WhisperPageState extends State<WhisperPage> {
|
|||||||
..._whisperController.noticesList.map((element) {
|
..._whisperController.noticesList.map((element) {
|
||||||
return InkWell(
|
return InkWell(
|
||||||
onTap: () {
|
onTap: () {
|
||||||
if (['/messageAt']
|
|
||||||
.contains(element['path'])) {
|
|
||||||
SmartDialog.showToast('功能开发中');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
Get.toNamed(element['path']);
|
Get.toNamed(element['path']);
|
||||||
|
|
||||||
if (element['count'] > 0) {
|
if (element['count'] > 0) {
|
||||||
|
|||||||
Reference in New Issue
Block a user