mirror of
https://github.com/bggRGjQaUbCoE/PiliPlus.git
synced 2026-07-20 10:30:13 +08:00
@@ -2,10 +2,12 @@ import 'package:PiliPlus/grpc/bilibili/main/community/reply/v1.pb.dart';
|
|||||||
import 'package:PiliPlus/grpc/reply.dart';
|
import 'package:PiliPlus/grpc/reply.dart';
|
||||||
import 'package:PiliPlus/http/loading_state.dart';
|
import 'package:PiliPlus/http/loading_state.dart';
|
||||||
import 'package:PiliPlus/pages/common/reply_controller.dart';
|
import 'package:PiliPlus/pages/common/reply_controller.dart';
|
||||||
|
import 'package:PiliPlus/pages/video/reply/vote/reply_vote_mixin.dart';
|
||||||
import 'package:PiliPlus/utils/storage_pref.dart';
|
import 'package:PiliPlus/utils/storage_pref.dart';
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
|
|
||||||
abstract class CommonDynController extends ReplyController<MainListReply> {
|
abstract class CommonDynController extends ReplyController<MainListReply>
|
||||||
|
with ReplyVoteMixin {
|
||||||
int get oid;
|
int get oid;
|
||||||
int get replyType;
|
int get replyType;
|
||||||
|
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import 'package:PiliPlus/http/loading_state.dart';
|
|||||||
import 'package:PiliPlus/models/common/enum_with_label.dart';
|
import 'package:PiliPlus/models/common/enum_with_label.dart';
|
||||||
import 'package:PiliPlus/pages/common/dyn/common_dyn_controller.dart';
|
import 'package:PiliPlus/pages/common/dyn/common_dyn_controller.dart';
|
||||||
import 'package:PiliPlus/pages/common/fab_mixin.dart';
|
import 'package:PiliPlus/pages/common/fab_mixin.dart';
|
||||||
|
import 'package:PiliPlus/pages/video/reply/vote/reply_vote_item.dart';
|
||||||
import 'package:PiliPlus/pages/video/reply/widgets/reply_item_grpc.dart';
|
import 'package:PiliPlus/pages/video/reply/widgets/reply_item_grpc.dart';
|
||||||
import 'package:PiliPlus/pages/video/reply_reply/view.dart';
|
import 'package:PiliPlus/pages/video/reply_reply/view.dart';
|
||||||
import 'package:PiliPlus/utils/extension/num_ext.dart';
|
import 'package:PiliPlus/utils/extension/num_ext.dart';
|
||||||
@@ -120,62 +121,78 @@ mixin CommonDynPageMixin<T extends StatefulWidget>
|
|||||||
}
|
}
|
||||||
|
|
||||||
Widget replyList(LoadingState<List<ReplyInfo>?> loadingState) {
|
Widget replyList(LoadingState<List<ReplyInfo>?> loadingState) {
|
||||||
return switch (loadingState) {
|
switch (loadingState) {
|
||||||
Loading() => SliverList.builder(
|
case Loading():
|
||||||
itemCount: 12,
|
return SliverList.builder(
|
||||||
itemBuilder: (context, index) => const VideoReplySkeleton(),
|
itemCount: 12,
|
||||||
),
|
itemBuilder: (context, index) => const VideoReplySkeleton(),
|
||||||
Success(:final response) =>
|
);
|
||||||
response != null && response.isNotEmpty
|
case Success(:final response):
|
||||||
? SliverList.builder(
|
if (response != null && response.isNotEmpty) {
|
||||||
itemCount: response.length + 1,
|
var count = response.length + 1;
|
||||||
itemBuilder: (context, index) {
|
final voteCard = controller.voteCard;
|
||||||
if (index == response.length) {
|
final hasVote = voteCard != null;
|
||||||
controller.onLoadMore();
|
if (hasVote) {
|
||||||
return Container(
|
count++;
|
||||||
alignment: Alignment.center,
|
}
|
||||||
margin: EdgeInsets.only(bottom: padding.bottom),
|
return SliverList.builder(
|
||||||
height: 125,
|
itemCount: count,
|
||||||
child: Text(
|
itemBuilder: (context, index) {
|
||||||
controller.isEnd ? '没有更多了' : '加载中...',
|
if (hasVote) {
|
||||||
style: TextStyle(
|
if (index == 0) {
|
||||||
fontSize: 12,
|
return buildVoteCard(context, theme.colorScheme, voteCard);
|
||||||
color: theme.colorScheme.outline,
|
} else {
|
||||||
),
|
index--;
|
||||||
),
|
}
|
||||||
);
|
}
|
||||||
} else {
|
if (index == response.length) {
|
||||||
return ReplyItemGrpc(
|
controller.onLoadMore();
|
||||||
replyItem: response[index],
|
return Container(
|
||||||
replyLevel: 1,
|
alignment: Alignment.center,
|
||||||
replyReply: (replyItem, id) =>
|
margin: EdgeInsets.only(bottom: padding.bottom),
|
||||||
replyReply(context, replyItem, id),
|
height: 125,
|
||||||
onReply: controller.onReply,
|
child: Text(
|
||||||
onDelete: (item, subIndex) =>
|
controller.isEnd ? '没有更多了' : '加载中...',
|
||||||
controller.onRemove(index, item, subIndex),
|
style: TextStyle(
|
||||||
upMid: controller.upMid,
|
fontSize: 12,
|
||||||
onViewImage: hideFab,
|
color: theme.colorScheme.outline,
|
||||||
onCheckReply: (item) =>
|
),
|
||||||
controller.onCheckReply(item, isManual: true),
|
),
|
||||||
onToggleTop: (item) => controller.onToggleTop(
|
);
|
||||||
item,
|
} else {
|
||||||
index,
|
return ReplyItemGrpc(
|
||||||
controller.oid,
|
replyItem: response[index],
|
||||||
controller.replyType,
|
replyLevel: 1,
|
||||||
),
|
replyReply: (replyItem, id) =>
|
||||||
);
|
replyReply(context, replyItem, id),
|
||||||
}
|
onReply: controller.onReply,
|
||||||
},
|
onDelete: (item, subIndex) =>
|
||||||
)
|
controller.onRemove(index, item, subIndex),
|
||||||
: HttpError(
|
upMid: controller.upMid,
|
||||||
errMsg: '还没有评论',
|
onViewImage: hideFab,
|
||||||
onReload: controller.onReload,
|
onCheckReply: (item) =>
|
||||||
),
|
controller.onCheckReply(item, isManual: true),
|
||||||
Error(:final errMsg) => HttpError(
|
onToggleTop: (item) => controller.onToggleTop(
|
||||||
errMsg: errMsg,
|
item,
|
||||||
onReload: controller.onReload,
|
index,
|
||||||
),
|
controller.oid,
|
||||||
};
|
controller.replyType,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return HttpError(
|
||||||
|
errMsg: '还没有评论',
|
||||||
|
onReload: controller.onReload,
|
||||||
|
);
|
||||||
|
case Error(:final errMsg):
|
||||||
|
return HttpError(
|
||||||
|
errMsg: errMsg,
|
||||||
|
onReload: controller.onReload,
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void replyReply(BuildContext context, ReplyInfo replyItem, int? id) {
|
void replyReply(BuildContext context, ReplyInfo replyItem, int? id) {
|
||||||
|
|||||||
@@ -57,16 +57,15 @@ abstract class ReplyController<R> extends CommonListController<R, ReplyInfo> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
bool customHandleResponse(bool isRefresh, Success response) {
|
bool customHandleResponse(bool isRefresh, Success<R> response) {
|
||||||
MainListReply data = response.response;
|
final data = response.response as MainListReply;
|
||||||
cursorNext = data.cursor.next;
|
cursorNext = data.cursor.next;
|
||||||
paginationReply = data.paginationReply;
|
paginationReply = data.paginationReply;
|
||||||
count.value = data.subjectControl.count.toInt();
|
count.value = data.subjectControl.count.toInt();
|
||||||
if (isRefresh) {
|
if (isRefresh) {
|
||||||
subjectControl = data.subjectControl;
|
subjectControl = data.subjectControl;
|
||||||
upMid ??= data.subjectControl.upMid;
|
upMid ??= data.subjectControl.upMid;
|
||||||
hasUpTop = data.hasUpTop();
|
if (hasUpTop = data.hasUpTop()) {
|
||||||
if (data.hasUpTop()) {
|
|
||||||
data.replies.insert(0, data.upTop);
|
data.replies.insert(0, data.upTop);
|
||||||
}
|
}
|
||||||
if (subjectControl?.title == ReplySortType.select.title) {
|
if (subjectControl?.title == ReplySortType.select.title) {
|
||||||
|
|||||||
@@ -566,9 +566,7 @@ class _DynamicDetailPageState
|
|||||||
color: theme.colorScheme.surface,
|
color: theme.colorScheme.surface,
|
||||||
border: Border(
|
border: Border(
|
||||||
top: BorderSide(
|
top: BorderSide(
|
||||||
color: theme.colorScheme.outline.withValues(
|
color: theme.colorScheme.outline.withValues(alpha: 0.08),
|
||||||
alpha: 0.08,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -5,10 +5,12 @@ import 'package:PiliPlus/http/loading_state.dart';
|
|||||||
import 'package:PiliPlus/models/common/video/video_type.dart';
|
import 'package:PiliPlus/models/common/video/video_type.dart';
|
||||||
import 'package:PiliPlus/pages/common/reply_controller.dart';
|
import 'package:PiliPlus/pages/common/reply_controller.dart';
|
||||||
import 'package:PiliPlus/pages/video/controller.dart';
|
import 'package:PiliPlus/pages/video/controller.dart';
|
||||||
|
import 'package:PiliPlus/pages/video/reply/vote/reply_vote_mixin.dart';
|
||||||
import 'package:PiliPlus/utils/id_utils.dart';
|
import 'package:PiliPlus/utils/id_utils.dart';
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
|
|
||||||
class VideoReplyController extends ReplyController<MainListReply> {
|
class VideoReplyController extends ReplyController<MainListReply>
|
||||||
|
with ReplyVoteMixin {
|
||||||
VideoReplyController({
|
VideoReplyController({
|
||||||
required this.aid,
|
required this.aid,
|
||||||
required this.videoType,
|
required this.videoType,
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import 'package:PiliPlus/grpc/bilibili/main/community/reply/v1.pb.dart'
|
|||||||
import 'package:PiliPlus/http/loading_state.dart';
|
import 'package:PiliPlus/http/loading_state.dart';
|
||||||
import 'package:PiliPlus/pages/common/fab_mixin.dart';
|
import 'package:PiliPlus/pages/common/fab_mixin.dart';
|
||||||
import 'package:PiliPlus/pages/video/reply/controller.dart';
|
import 'package:PiliPlus/pages/video/reply/controller.dart';
|
||||||
|
import 'package:PiliPlus/pages/video/reply/vote/reply_vote_item.dart';
|
||||||
import 'package:PiliPlus/pages/video/reply/widgets/reply_item_grpc.dart';
|
import 'package:PiliPlus/pages/video/reply/widgets/reply_item_grpc.dart';
|
||||||
import 'package:PiliPlus/pages/video/reply_reply/view.dart';
|
import 'package:PiliPlus/pages/video/reply_reply/view.dart';
|
||||||
import 'package:PiliPlus/utils/feed_back.dart';
|
import 'package:PiliPlus/utils/feed_back.dart';
|
||||||
@@ -125,9 +126,7 @@ class _VideoReplyPanelState extends State<VideoReplyPanel>
|
|||||||
}),
|
}),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Obx(
|
Obx(() => _buildBody(_videoReplyController.loadingState.value)),
|
||||||
() => _buildBody(_videoReplyController.loadingState.value),
|
|
||||||
),
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
Positioned(
|
Positioned(
|
||||||
@@ -170,62 +169,75 @@ class _VideoReplyPanelState extends State<VideoReplyPanel>
|
|||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildBody(LoadingState<List<ReplyInfo>?> loadingState) {
|
Widget _buildBody(LoadingState<List<ReplyInfo>?> loadingState) {
|
||||||
return switch (loadingState) {
|
switch (loadingState) {
|
||||||
Loading() => SliverList.builder(
|
case Loading():
|
||||||
itemBuilder: (context, index) => const VideoReplySkeleton(),
|
return SliverList.builder(
|
||||||
itemCount: 5,
|
itemBuilder: (context, index) => const VideoReplySkeleton(),
|
||||||
),
|
itemCount: 5,
|
||||||
Success(:final response) =>
|
);
|
||||||
response != null && response.isNotEmpty
|
case Success(:final response):
|
||||||
? SliverList.builder(
|
if (response != null && response.isNotEmpty) {
|
||||||
itemBuilder: (context, index) {
|
var count = response.length + 1;
|
||||||
if (index == response.length) {
|
final voteCard = _videoReplyController.voteCard;
|
||||||
_videoReplyController.onLoadMore();
|
final hasVote = voteCard != null;
|
||||||
return Container(
|
if (hasVote) {
|
||||||
height: 125,
|
count++;
|
||||||
alignment: .center,
|
}
|
||||||
margin: .only(bottom: bottom),
|
return SliverList.builder(
|
||||||
child: Text(
|
itemBuilder: (context, index) {
|
||||||
_videoReplyController.isEnd ? '没有更多了' : '加载中...',
|
if (hasVote) {
|
||||||
textAlign: .center,
|
if (index == 0) {
|
||||||
style: TextStyle(
|
return buildVoteCard(context, colorScheme, voteCard);
|
||||||
fontSize: 12,
|
} else {
|
||||||
color: colorScheme.outline,
|
index--;
|
||||||
),
|
}
|
||||||
),
|
}
|
||||||
);
|
if (index == response.length) {
|
||||||
} else {
|
_videoReplyController.onLoadMore();
|
||||||
return ReplyItemGrpc(
|
return Container(
|
||||||
replyItem: response[index],
|
height: 125,
|
||||||
replyLevel: widget.replyLevel,
|
alignment: .center,
|
||||||
replyReply: replyReply,
|
margin: .only(bottom: bottom),
|
||||||
onReply: _videoReplyController.onReply,
|
child: Text(
|
||||||
onDelete: (item, subIndex) =>
|
_videoReplyController.isEnd ? '没有更多了' : '加载中...',
|
||||||
_videoReplyController.onRemove(index, item, subIndex),
|
textAlign: .center,
|
||||||
upMid: _videoReplyController.upMid,
|
style: TextStyle(fontSize: 12, color: colorScheme.outline),
|
||||||
getTag: () => heroTag,
|
),
|
||||||
onCheckReply: (item) => _videoReplyController
|
);
|
||||||
.onCheckReply(item, isManual: true),
|
} else {
|
||||||
onToggleTop: (item) => _videoReplyController.onToggleTop(
|
return ReplyItemGrpc(
|
||||||
item,
|
replyItem: response[index],
|
||||||
index,
|
replyLevel: widget.replyLevel,
|
||||||
_videoReplyController.aid,
|
replyReply: replyReply,
|
||||||
_videoReplyController.videoType.replyType,
|
onReply: _videoReplyController.onReply,
|
||||||
),
|
onDelete: (item, subIndex) =>
|
||||||
);
|
_videoReplyController.onRemove(index, item, subIndex),
|
||||||
}
|
upMid: _videoReplyController.upMid,
|
||||||
},
|
getTag: () => heroTag,
|
||||||
itemCount: response.length + 1,
|
onCheckReply: (item) =>
|
||||||
)
|
_videoReplyController.onCheckReply(item, isManual: true),
|
||||||
: HttpError(
|
onToggleTop: (item) => _videoReplyController.onToggleTop(
|
||||||
errMsg: '还没有评论',
|
item,
|
||||||
onReload: _videoReplyController.onReload,
|
index,
|
||||||
),
|
_videoReplyController.aid,
|
||||||
Error(:final errMsg) => HttpError(
|
_videoReplyController.videoType.replyType,
|
||||||
errMsg: errMsg,
|
),
|
||||||
onReload: _videoReplyController.onReload,
|
);
|
||||||
),
|
}
|
||||||
};
|
},
|
||||||
|
itemCount: count,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return HttpError(
|
||||||
|
errMsg: '还没有评论',
|
||||||
|
onReload: _videoReplyController.onReload,
|
||||||
|
);
|
||||||
|
case Error(:final errMsg):
|
||||||
|
return HttpError(
|
||||||
|
errMsg: errMsg,
|
||||||
|
onReload: _videoReplyController.onReload,
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 展示二级回复
|
// 展示二级回复
|
||||||
|
|||||||
49
lib/pages/video/reply/vote/reply_vote_item.dart
Normal file
49
lib/pages/video/reply/vote/reply_vote_item.dart
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
import 'package:PiliPlus/grpc/bilibili/main/community/reply/v1.pb.dart'
|
||||||
|
show VoteCard;
|
||||||
|
import 'package:PiliPlus/pages/dynamics/widgets/vote.dart';
|
||||||
|
import 'package:PiliPlus/utils/num_utils.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
Widget buildVoteCard(
|
||||||
|
BuildContext context,
|
||||||
|
ColorScheme colorScheme,
|
||||||
|
VoteCard voteCard,
|
||||||
|
) {
|
||||||
|
return InkWell(
|
||||||
|
onTap: () => showVoteDialog(context, voteCard.voteId.toInt()),
|
||||||
|
child: Padding(
|
||||||
|
padding: const .symmetric(horizontal: 12, vertical: 6),
|
||||||
|
child: Row(
|
||||||
|
spacing: 10,
|
||||||
|
children: [
|
||||||
|
Container(
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: colorScheme.onInverseSurface,
|
||||||
|
borderRadius: const .all(.circular(8)),
|
||||||
|
),
|
||||||
|
width: 60,
|
||||||
|
height: 42,
|
||||||
|
child: Icon(
|
||||||
|
Icons.bar_chart_rounded,
|
||||||
|
color: colorScheme.onSurfaceVariant,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: .start,
|
||||||
|
children: [
|
||||||
|
Text(voteCard.title, maxLines: 1, overflow: .ellipsis),
|
||||||
|
Text(
|
||||||
|
'${NumUtils.numFormat(voteCard.count.toInt())}人参与',
|
||||||
|
maxLines: 1,
|
||||||
|
overflow: .ellipsis,
|
||||||
|
style: TextStyle(fontSize: 13, color: colorScheme.outline),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
19
lib/pages/video/reply/vote/reply_vote_mixin.dart
Normal file
19
lib/pages/video/reply/vote/reply_vote_mixin.dart
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
import 'package:PiliPlus/grpc/bilibili/main/community/reply/v1.pb.dart'
|
||||||
|
show MainListReply, VoteCard, ReplyInfo;
|
||||||
|
import 'package:PiliPlus/http/loading_state.dart';
|
||||||
|
import 'package:PiliPlus/pages/common/common_list_controller.dart';
|
||||||
|
|
||||||
|
mixin ReplyVoteMixin on CommonListController<MainListReply, ReplyInfo> {
|
||||||
|
VoteCard? voteCard;
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool customHandleResponse(bool isRefresh, Success<MainListReply> response) {
|
||||||
|
if (isRefresh) {
|
||||||
|
final res = response.response;
|
||||||
|
if (res.hasVoteCard()) {
|
||||||
|
voteCard = res.voteCard;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return super.customHandleResponse(isRefresh, response);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -14,7 +14,7 @@ import 'package:PiliPlus/common/widgets/image/network_img_layer.dart';
|
|||||||
import 'package:PiliPlus/common/widgets/image_grid/image_grid_view.dart';
|
import 'package:PiliPlus/common/widgets/image_grid/image_grid_view.dart';
|
||||||
import 'package:PiliPlus/common/widgets/pendant_avatar.dart';
|
import 'package:PiliPlus/common/widgets/pendant_avatar.dart';
|
||||||
import 'package:PiliPlus/grpc/bilibili/main/community/reply/v1.pb.dart'
|
import 'package:PiliPlus/grpc/bilibili/main/community/reply/v1.pb.dart'
|
||||||
show ReplyInfo, ReplyControl, Content, Url;
|
show ReplyInfo, ReplyControl, Content, Url, ReplyControl_VoteOption;
|
||||||
import 'package:PiliPlus/grpc/reply.dart';
|
import 'package:PiliPlus/grpc/reply.dart';
|
||||||
import 'package:PiliPlus/http/loading_state.dart';
|
import 'package:PiliPlus/http/loading_state.dart';
|
||||||
import 'package:PiliPlus/http/reply.dart';
|
import 'package:PiliPlus/http/reply.dart';
|
||||||
@@ -92,7 +92,7 @@ class ReplyItemGrpc extends StatelessWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final ThemeData theme = Theme.of(context);
|
final colorScheme = ColorScheme.of(context);
|
||||||
|
|
||||||
void showMore() => showModalBottomSheet(
|
void showMore() => showModalBottomSheet(
|
||||||
context: context,
|
context: context,
|
||||||
@@ -113,7 +113,7 @@ class ReplyItemGrpc extends StatelessWidget {
|
|||||||
|
|
||||||
Widget child = Padding(
|
Widget child = Padding(
|
||||||
padding: const .fromLTRB(12, 14, 8, 5),
|
padding: const .fromLTRB(12, 14, 8, 5),
|
||||||
child: _buildContent(context, theme),
|
child: _buildContent(context, colorScheme),
|
||||||
);
|
);
|
||||||
if (needDivider) {
|
if (needDivider) {
|
||||||
child = Column(
|
child = Column(
|
||||||
@@ -124,7 +124,7 @@ class ReplyItemGrpc extends StatelessWidget {
|
|||||||
indent: 55,
|
indent: 55,
|
||||||
endIndent: 15,
|
endIndent: 15,
|
||||||
height: 0.3,
|
height: 0.3,
|
||||||
color: theme.colorScheme.outline.withValues(alpha: 0.08),
|
color: colorScheme.outline.withValues(alpha: 0.08),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
@@ -140,7 +140,7 @@ class ReplyItemGrpc extends StatelessWidget {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildHeader(BuildContext context, ThemeData theme) {
|
Widget _buildHeader(BuildContext context, ColorScheme colorScheme) {
|
||||||
final member = replyItem.member;
|
final member = replyItem.member;
|
||||||
Widget header = GestureDetector(
|
Widget header = GestureDetector(
|
||||||
onTap: () {
|
onTap: () {
|
||||||
@@ -178,8 +178,8 @@ class ReplyItemGrpc extends StatelessWidget {
|
|||||||
overflow: .ellipsis,
|
overflow: .ellipsis,
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
color: (member.vipStatus > 0 && member.vipType == 2)
|
color: (member.vipStatus > 0 && member.vipType == 2)
|
||||||
? theme.colorScheme.vipColor
|
? colorScheme.vipColor
|
||||||
: theme.colorScheme.outline,
|
: colorScheme.outline,
|
||||||
fontSize: 13,
|
fontSize: 13,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -227,16 +227,16 @@ class ReplyItemGrpc extends StatelessWidget {
|
|||||||
replyItem.ctime.toInt(),
|
replyItem.ctime.toInt(),
|
||||||
),
|
),
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontSize: theme.textTheme.labelSmall!.fontSize,
|
fontSize: 11,
|
||||||
color: theme.colorScheme.outline,
|
color: colorScheme.outline,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
if (replyItem.replyControl.hasLocation())
|
if (replyItem.replyControl.hasLocation())
|
||||||
Text(
|
Text(
|
||||||
' • ${replyItem.replyControl.location}',
|
' • ${replyItem.replyControl.location}',
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontSize: theme.textTheme.labelSmall!.fontSize,
|
fontSize: 11,
|
||||||
color: theme.colorScheme.outline,
|
color: colorScheme.outline,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@@ -293,23 +293,56 @@ class ReplyItemGrpc extends StatelessWidget {
|
|||||||
return header;
|
return header;
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildContent(BuildContext context, ThemeData theme) {
|
Widget _buildVoteOption(
|
||||||
|
ColorScheme colorScheme,
|
||||||
|
ReplyControl_VoteOption voteOption,
|
||||||
|
) {
|
||||||
|
return Text.rich(
|
||||||
|
TextSpan(
|
||||||
|
children: [
|
||||||
|
switch (voteOption.labelKind) {
|
||||||
|
.RED => TextSpan(
|
||||||
|
text: '红队 ',
|
||||||
|
style: TextStyle(color: colorScheme.vipColor),
|
||||||
|
),
|
||||||
|
.BLUE => TextSpan(
|
||||||
|
text: '蓝队 ',
|
||||||
|
style: TextStyle(color: colorScheme.blue),
|
||||||
|
),
|
||||||
|
_ => TextSpan(
|
||||||
|
text: '投票 ',
|
||||||
|
style: TextStyle(color: colorScheme.outline),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
TextSpan(text: voteOption.desc),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 12,
|
||||||
|
color: colorScheme.onSurfaceVariant,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _buildContent(BuildContext context, ColorScheme colorScheme) {
|
||||||
final replyControl = replyItem.replyControl;
|
final replyControl = replyItem.replyControl;
|
||||||
final padding = EdgeInsets.only(left: replyLevel == 0 ? 6 : 45, right: 6);
|
final padding = EdgeInsets.only(left: replyLevel == 0 ? 6 : 45, right: 6);
|
||||||
return Column(
|
return Column(
|
||||||
mainAxisSize: .min,
|
mainAxisSize: .min,
|
||||||
crossAxisAlignment: .start,
|
crossAxisAlignment: .start,
|
||||||
children: [
|
children: [
|
||||||
_buildHeader(context, theme),
|
_buildHeader(context, colorScheme),
|
||||||
const SizedBox(height: 10),
|
const SizedBox(height: 10),
|
||||||
|
if (replyControl.hasVoteOption())
|
||||||
|
Padding(
|
||||||
|
padding: padding,
|
||||||
|
child: _buildVoteOption(colorScheme, replyControl.voteOption),
|
||||||
|
),
|
||||||
Padding(
|
Padding(
|
||||||
padding: padding,
|
padding: padding,
|
||||||
child: custom_text.Text.rich(
|
child: custom_text.Text.rich(
|
||||||
primary: theme.colorScheme.primary,
|
primary: colorScheme.primary,
|
||||||
style: TextStyle(
|
style: const TextStyle(height: 1.75, fontSize: 14),
|
||||||
height: 1.75,
|
|
||||||
fontSize: theme.textTheme.bodyMedium!.fontSize,
|
|
||||||
),
|
|
||||||
maxLines: replyLevel == 1 ? replyLengthLimit : null,
|
maxLines: replyLevel == 1 ? replyLengthLimit : null,
|
||||||
TextSpan(
|
TextSpan(
|
||||||
children: [
|
children: [
|
||||||
@@ -329,7 +362,7 @@ class ReplyItemGrpc extends StatelessWidget {
|
|||||||
],
|
],
|
||||||
_buildMessage(
|
_buildMessage(
|
||||||
context,
|
context,
|
||||||
theme,
|
colorScheme,
|
||||||
replyControl.showTranslation
|
replyControl.showTranslation
|
||||||
? replyItem.translatedContent
|
? replyItem.translatedContent
|
||||||
: replyItem.content,
|
: replyItem.content,
|
||||||
@@ -359,12 +392,12 @@ class ReplyItemGrpc extends StatelessWidget {
|
|||||||
],
|
],
|
||||||
if (replyLevel != 0) ...[
|
if (replyLevel != 0) ...[
|
||||||
const SizedBox(height: 4),
|
const SizedBox(height: 4),
|
||||||
buttonAction(context, theme, replyControl),
|
buttonAction(context, colorScheme, replyControl),
|
||||||
],
|
],
|
||||||
if (replyLevel == 1 && replyItem.count > Int64.ZERO) ...[
|
if (replyLevel == 1 && replyItem.count > Int64.ZERO) ...[
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.only(top: 5, bottom: 12),
|
padding: const EdgeInsets.only(top: 5, bottom: 12),
|
||||||
child: replyItemRow(context, theme, replyItem.replies),
|
child: replyItemRow(context, colorScheme, replyItem.replies),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
@@ -373,15 +406,15 @@ class ReplyItemGrpc extends StatelessWidget {
|
|||||||
|
|
||||||
Widget _buildTranslateBtn(
|
Widget _buildTranslateBtn(
|
||||||
BuildContext context,
|
BuildContext context,
|
||||||
ThemeData theme,
|
ColorScheme colorScheme,
|
||||||
ReplyControl replyControl,
|
ReplyControl replyControl,
|
||||||
TextStyle textStyle,
|
TextStyle textStyle,
|
||||||
ButtonStyle buttonStyle,
|
ButtonStyle buttonStyle,
|
||||||
) {
|
) {
|
||||||
late bool isProcessing = false;
|
late bool isProcessing = false;
|
||||||
final color = replyControl.showTranslation
|
final color = replyControl.showTranslation
|
||||||
? theme.colorScheme.primary
|
? colorScheme.primary
|
||||||
: theme.colorScheme.outline.withValues(alpha: 0.8);
|
: colorScheme.outline.withValues(alpha: 0.8);
|
||||||
return SizedBox(
|
return SizedBox(
|
||||||
height: 32,
|
height: 32,
|
||||||
child: TextButton(
|
child: TextButton(
|
||||||
@@ -439,14 +472,14 @@ class ReplyItemGrpc extends StatelessWidget {
|
|||||||
|
|
||||||
Widget buttonAction(
|
Widget buttonAction(
|
||||||
BuildContext context,
|
BuildContext context,
|
||||||
ThemeData theme,
|
ColorScheme colorScheme,
|
||||||
ReplyControl replyControl,
|
ReplyControl replyControl,
|
||||||
) {
|
) {
|
||||||
final textStyle = TextStyle(
|
final textStyle = TextStyle(
|
||||||
height: 1,
|
height: 1,
|
||||||
|
fontSize: 12,
|
||||||
fontWeight: .normal,
|
fontWeight: .normal,
|
||||||
color: theme.colorScheme.outline,
|
color: colorScheme.outline,
|
||||||
fontSize: theme.textTheme.labelMedium!.fontSize,
|
|
||||||
);
|
);
|
||||||
const buttonStyle = ButtonStyle(
|
const buttonStyle = ButtonStyle(
|
||||||
visualDensity: .compact,
|
visualDensity: .compact,
|
||||||
@@ -492,7 +525,7 @@ class ReplyItemGrpc extends StatelessWidget {
|
|||||||
Icon(
|
Icon(
|
||||||
Icons.reply,
|
Icons.reply,
|
||||||
size: 18,
|
size: 18,
|
||||||
color: theme.colorScheme.outline.withValues(alpha: 0.8),
|
color: colorScheme.outline.withValues(alpha: 0.8),
|
||||||
),
|
),
|
||||||
Text('回复', style: textStyle),
|
Text('回复', style: textStyle),
|
||||||
],
|
],
|
||||||
@@ -504,7 +537,7 @@ class ReplyItemGrpc extends StatelessWidget {
|
|||||||
.TRANSLATION_SWITCH_SHOW_TRANSLATION) ...[
|
.TRANSLATION_SWITCH_SHOW_TRANSLATION) ...[
|
||||||
_buildTranslateBtn(
|
_buildTranslateBtn(
|
||||||
context,
|
context,
|
||||||
theme,
|
colorScheme,
|
||||||
replyControl,
|
replyControl,
|
||||||
textStyle,
|
textStyle,
|
||||||
buttonStyle,
|
buttonStyle,
|
||||||
@@ -515,7 +548,7 @@ class ReplyItemGrpc extends StatelessWidget {
|
|||||||
dialogBtn != null
|
dialogBtn != null
|
||||||
? replyControl.cardLabels.first.textContent
|
? replyControl.cardLabels.first.textContent
|
||||||
: replyControl.cardLabels.map((e) => e.textContent).join(' '),
|
: replyControl.cardLabels.map((e) => e.textContent).join(' '),
|
||||||
style: textStyle.copyWith(color: theme.colorScheme.secondary),
|
style: textStyle.copyWith(color: colorScheme.secondary),
|
||||||
),
|
),
|
||||||
const SizedBox(width: 2),
|
const SizedBox(width: 2),
|
||||||
],
|
],
|
||||||
@@ -529,7 +562,7 @@ class ReplyItemGrpc extends StatelessWidget {
|
|||||||
|
|
||||||
Widget replyItemRow(
|
Widget replyItemRow(
|
||||||
BuildContext context,
|
BuildContext context,
|
||||||
ThemeData theme,
|
ColorScheme colorScheme,
|
||||||
List<ReplyInfo> replies,
|
List<ReplyInfo> replies,
|
||||||
) {
|
) {
|
||||||
final extraRow = replies.length < replyItem.count.toInt();
|
final extraRow = replies.length < replyItem.count.toInt();
|
||||||
@@ -537,7 +570,7 @@ class ReplyItemGrpc extends StatelessWidget {
|
|||||||
return Padding(
|
return Padding(
|
||||||
padding: const EdgeInsets.only(left: 42, right: 4),
|
padding: const EdgeInsets.only(left: 42, right: 4),
|
||||||
child: Material(
|
child: Material(
|
||||||
color: theme.colorScheme.onInverseSurface,
|
color: colorScheme.onInverseSurface,
|
||||||
borderRadius: const BorderRadius.all(Radius.circular(6)),
|
borderRadius: const BorderRadius.all(Radius.circular(6)),
|
||||||
clipBehavior: Clip.hardEdge,
|
clipBehavior: Clip.hardEdge,
|
||||||
animationDuration: Duration.zero,
|
animationDuration: Duration.zero,
|
||||||
@@ -584,11 +617,9 @@ class ReplyItemGrpc extends StatelessWidget {
|
|||||||
padding: padding,
|
padding: padding,
|
||||||
child: Text.rich(
|
child: Text.rich(
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontSize: theme.textTheme.bodyMedium!.fontSize,
|
|
||||||
color: theme.colorScheme.onSurface.withValues(
|
|
||||||
alpha: 0.85,
|
|
||||||
),
|
|
||||||
height: 1.6,
|
height: 1.6,
|
||||||
|
fontSize: 14,
|
||||||
|
color: colorScheme.onSurface.withValues(alpha: 0.85),
|
||||||
),
|
),
|
||||||
overflow: TextOverflow.ellipsis,
|
overflow: TextOverflow.ellipsis,
|
||||||
maxLines: 2,
|
maxLines: 2,
|
||||||
@@ -596,9 +627,7 @@ class ReplyItemGrpc extends StatelessWidget {
|
|||||||
children: [
|
children: [
|
||||||
TextSpan(
|
TextSpan(
|
||||||
text: childReply.member.name,
|
text: childReply.member.name,
|
||||||
style: TextStyle(
|
style: TextStyle(color: colorScheme.primary),
|
||||||
color: theme.colorScheme.primary,
|
|
||||||
),
|
|
||||||
recognizer: NoDeadlineTapGestureRecognizer()
|
recognizer: NoDeadlineTapGestureRecognizer()
|
||||||
..onTap = () {
|
..onTap = () {
|
||||||
feedBack();
|
feedBack();
|
||||||
@@ -630,7 +659,7 @@ class ReplyItemGrpc extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
_buildMessage(
|
_buildMessage(
|
||||||
context,
|
context,
|
||||||
theme,
|
colorScheme,
|
||||||
childReply.content,
|
childReply.content,
|
||||||
childReply.replyControl,
|
childReply.replyControl,
|
||||||
),
|
),
|
||||||
@@ -649,15 +678,13 @@ class ReplyItemGrpc extends StatelessWidget {
|
|||||||
: const EdgeInsets.fromLTRB(8, 5, 8, 8),
|
: const EdgeInsets.fromLTRB(8, 5, 8, 8),
|
||||||
child: Text.rich(
|
child: Text.rich(
|
||||||
TextSpan(
|
TextSpan(
|
||||||
style: TextStyle(
|
style: const TextStyle(fontSize: 12),
|
||||||
fontSize: theme.textTheme.labelMedium!.fontSize,
|
|
||||||
),
|
|
||||||
children: [
|
children: [
|
||||||
if (replyItem.replyControl.upReply)
|
if (replyItem.replyControl.upReply)
|
||||||
TextSpan(
|
TextSpan(
|
||||||
text: 'UP主等人 ',
|
text: 'UP主等人 ',
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
color: theme.colorScheme.onSurface.withValues(
|
color: colorScheme.onSurface.withValues(
|
||||||
alpha: 0.85,
|
alpha: 0.85,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -665,7 +692,7 @@ class ReplyItemGrpc extends StatelessWidget {
|
|||||||
TextSpan(
|
TextSpan(
|
||||||
text: '共${replyItem.count}条回复',
|
text: '共${replyItem.count}条回复',
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
color: theme.colorScheme.primary,
|
color: colorScheme.primary,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@@ -681,7 +708,7 @@ class ReplyItemGrpc extends StatelessWidget {
|
|||||||
|
|
||||||
InlineSpan _buildMessage(
|
InlineSpan _buildMessage(
|
||||||
BuildContext context,
|
BuildContext context,
|
||||||
ThemeData theme,
|
ColorScheme colorScheme,
|
||||||
Content content,
|
Content content,
|
||||||
ReplyControl replyControl,
|
ReplyControl replyControl,
|
||||||
) {
|
) {
|
||||||
@@ -727,16 +754,14 @@ class ReplyItemGrpc extends StatelessWidget {
|
|||||||
child: CachedNetworkImage(
|
child: CachedNetworkImage(
|
||||||
height: 19,
|
height: 19,
|
||||||
memCacheHeight: 19.cacheSize(context),
|
memCacheHeight: 19.cacheSize(context),
|
||||||
color: theme.colorScheme.primary,
|
color: colorScheme.primary,
|
||||||
imageUrl: ImageUtils.thumbnailUrl(url.prefixIcon),
|
imageUrl: ImageUtils.thumbnailUrl(url.prefixIcon),
|
||||||
placeholder: (_, _) => const SizedBox.shrink(),
|
placeholder: (_, _) => const SizedBox.shrink(),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
TextSpan(
|
TextSpan(
|
||||||
text: isCv ? '[笔记] ' : url.title,
|
text: isCv ? '[笔记] ' : url.title,
|
||||||
style: TextStyle(
|
style: TextStyle(color: colorScheme.primary),
|
||||||
color: theme.colorScheme.primary,
|
|
||||||
),
|
|
||||||
recognizer: NoDeadlineTapGestureRecognizer()
|
recognizer: NoDeadlineTapGestureRecognizer()
|
||||||
..onTap = () {
|
..onTap = () {
|
||||||
if (url.appUrlSchema.isEmpty) {
|
if (url.appUrlSchema.isEmpty) {
|
||||||
@@ -815,7 +840,7 @@ class ReplyItemGrpc extends StatelessWidget {
|
|||||||
spanChildren.add(
|
spanChildren.add(
|
||||||
TextSpan(
|
TextSpan(
|
||||||
text: matchStr,
|
text: matchStr,
|
||||||
style: TextStyle(color: theme.colorScheme.primary),
|
style: TextStyle(color: colorScheme.primary),
|
||||||
recognizer: NoDeadlineTapGestureRecognizer()
|
recognizer: NoDeadlineTapGestureRecognizer()
|
||||||
..onTap = () =>
|
..onTap = () =>
|
||||||
Get.toNamed('/member?mid=${content.atNameToMid[name]}'),
|
Get.toNamed('/member?mid=${content.atNameToMid[name]}'),
|
||||||
@@ -825,7 +850,7 @@ class ReplyItemGrpc extends StatelessWidget {
|
|||||||
spanChildren.add(
|
spanChildren.add(
|
||||||
TextSpan(
|
TextSpan(
|
||||||
text: '投票: ${content.vote.title}',
|
text: '投票: ${content.vote.title}',
|
||||||
style: TextStyle(color: theme.colorScheme.primary),
|
style: TextStyle(color: colorScheme.primary),
|
||||||
recognizer: NoDeadlineTapGestureRecognizer()
|
recognizer: NoDeadlineTapGestureRecognizer()
|
||||||
..onTap = () =>
|
..onTap = () =>
|
||||||
showVoteDialog(context, content.vote.id.toInt()),
|
showVoteDialog(context, content.vote.id.toInt()),
|
||||||
@@ -847,9 +872,7 @@ class ReplyItemGrpc extends StatelessWidget {
|
|||||||
spanChildren.add(
|
spanChildren.add(
|
||||||
TextSpan(
|
TextSpan(
|
||||||
text: isValid ? ' $matchStr ' : matchStr,
|
text: isValid ? ' $matchStr ' : matchStr,
|
||||||
style: isValid
|
style: isValid ? TextStyle(color: colorScheme.primary) : null,
|
||||||
? TextStyle(color: theme.colorScheme.primary)
|
|
||||||
: null,
|
|
||||||
recognizer: isValid
|
recognizer: isValid
|
||||||
? (NoDeadlineTapGestureRecognizer()
|
? (NoDeadlineTapGestureRecognizer()
|
||||||
..onTap = () {
|
..onTap = () {
|
||||||
@@ -881,7 +904,7 @@ class ReplyItemGrpc extends StatelessWidget {
|
|||||||
spanChildren.add(
|
spanChildren.add(
|
||||||
TextSpan(
|
TextSpan(
|
||||||
text: matchStr,
|
text: matchStr,
|
||||||
style: TextStyle(color: theme.colorScheme.primary),
|
style: TextStyle(color: colorScheme.primary),
|
||||||
recognizer: NoDeadlineTapGestureRecognizer()
|
recognizer: NoDeadlineTapGestureRecognizer()
|
||||||
..onTap = () {
|
..onTap = () {
|
||||||
Get.toNamed(
|
Get.toNamed(
|
||||||
@@ -895,7 +918,7 @@ class ReplyItemGrpc extends StatelessWidget {
|
|||||||
spanChildren.add(
|
spanChildren.add(
|
||||||
TextSpan(
|
TextSpan(
|
||||||
text: matchStr,
|
text: matchStr,
|
||||||
style: TextStyle(color: theme.colorScheme.primary),
|
style: TextStyle(color: colorScheme.primary),
|
||||||
recognizer: NoDeadlineTapGestureRecognizer()
|
recognizer: NoDeadlineTapGestureRecognizer()
|
||||||
..onTap = () => PageUtils.handleWebview(matchStr),
|
..onTap = () => PageUtils.handleWebview(matchStr),
|
||||||
),
|
),
|
||||||
@@ -929,7 +952,7 @@ class ReplyItemGrpc extends StatelessWidget {
|
|||||||
|
|
||||||
final hasClickUrl = content.richText.note.hasClickUrl();
|
final hasClickUrl = content.richText.note.hasClickUrl();
|
||||||
if (hasClickUrl || content.richText.opus.hasOpusId()) {
|
if (hasClickUrl || content.richText.opus.hasOpusId()) {
|
||||||
color = theme.colorScheme.primary;
|
color = colorScheme.primary;
|
||||||
recognizer = NoDeadlineTapGestureRecognizer()
|
recognizer = NoDeadlineTapGestureRecognizer()
|
||||||
..onTap = () => hasClickUrl
|
..onTap = () => hasClickUrl
|
||||||
? PiliScheme.routePushFromUrl(content.richText.note.clickUrl)
|
? PiliScheme.routePushFromUrl(content.richText.note.clickUrl)
|
||||||
@@ -941,7 +964,7 @@ class ReplyItemGrpc extends StatelessWidget {
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
color = theme.colorScheme.secondary;
|
color = colorScheme.secondary;
|
||||||
}
|
}
|
||||||
spanChildren.insert(
|
spanChildren.insert(
|
||||||
0,
|
0,
|
||||||
@@ -965,11 +988,12 @@ class ReplyItemGrpc extends StatelessWidget {
|
|||||||
late String message = item.content.message;
|
late String message = item.content.message;
|
||||||
final ownerMid = Int64(Accounts.main.mid);
|
final ownerMid = Int64(Accounts.main.mid);
|
||||||
final theme = Theme.of(context);
|
final theme = Theme.of(context);
|
||||||
final errorColor = theme.colorScheme.error;
|
final colorScheme = theme.colorScheme;
|
||||||
|
final errorColor = colorScheme.error;
|
||||||
final style = theme.textTheme.titleSmall!;
|
final style = theme.textTheme.titleSmall!;
|
||||||
|
|
||||||
return Padding(
|
return Padding(
|
||||||
padding: EdgeInsets.only(
|
padding: .only(
|
||||||
bottom: MediaQuery.viewPaddingOf(context).bottom + 20,
|
bottom: MediaQuery.viewPaddingOf(context).bottom + 20,
|
||||||
),
|
),
|
||||||
child: Column(
|
child: Column(
|
||||||
@@ -985,7 +1009,7 @@ class ReplyItemGrpc extends StatelessWidget {
|
|||||||
width: 32,
|
width: 32,
|
||||||
height: 3,
|
height: 3,
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: theme.colorScheme.outline,
|
color: colorScheme.outline,
|
||||||
borderRadius: const BorderRadius.all(Radius.circular(3)),
|
borderRadius: const BorderRadius.all(Radius.circular(3)),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -1007,7 +1031,7 @@ class ReplyItemGrpc extends StatelessWidget {
|
|||||||
},
|
},
|
||||||
title: Text(
|
title: Text(
|
||||||
'save to local',
|
'save to local',
|
||||||
style: style.copyWith(color: theme.colorScheme.primary),
|
style: style.copyWith(color: colorScheme.primary),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
ListTile(
|
ListTile(
|
||||||
@@ -1018,7 +1042,7 @@ class ReplyItemGrpc extends StatelessWidget {
|
|||||||
},
|
},
|
||||||
title: Text(
|
title: Text(
|
||||||
'remove from local',
|
'remove from local',
|
||||||
style: style.copyWith(color: theme.colorScheme.primary),
|
style: style.copyWith(color: colorScheme.primary),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
ListTile(
|
ListTile(
|
||||||
@@ -1037,7 +1061,7 @@ class ReplyItemGrpc extends StatelessWidget {
|
|||||||
},
|
},
|
||||||
title: Text(
|
title: Text(
|
||||||
'save to local (x1000)',
|
'save to local (x1000)',
|
||||||
style: style.copyWith(color: theme.colorScheme.primary),
|
style: style.copyWith(color: colorScheme.primary),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@@ -1048,7 +1072,7 @@ class ReplyItemGrpc extends StatelessWidget {
|
|||||||
bool? isDelete = await showDialog<bool>(
|
bool? isDelete = await showDialog<bool>(
|
||||||
context: context,
|
context: context,
|
||||||
builder: (context) {
|
builder: (context) {
|
||||||
final theme = Theme.of(context);
|
final colorScheme = ColorScheme.of(context);
|
||||||
return AlertDialog(
|
return AlertDialog(
|
||||||
title: const Text('删除评论'),
|
title: const Text('删除评论'),
|
||||||
content: Text.rich(
|
content: Text.rich(
|
||||||
@@ -1059,7 +1083,7 @@ class ReplyItemGrpc extends StatelessWidget {
|
|||||||
TextSpan(
|
TextSpan(
|
||||||
text: '@${item.member.name}',
|
text: '@${item.member.name}',
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
color: theme.colorScheme.primary,
|
color: colorScheme.primary,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
const TextSpan(text: ':\n'),
|
const TextSpan(text: ':\n'),
|
||||||
@@ -1074,7 +1098,7 @@ class ReplyItemGrpc extends StatelessWidget {
|
|||||||
child: Text(
|
child: Text(
|
||||||
'取消',
|
'取消',
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
color: theme.colorScheme.outline,
|
color: colorScheme.outline,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -5,6 +5,9 @@ import 'package:flutter/material.dart'
|
|||||||
const _pinkLight = Color(0xFFFF6699);
|
const _pinkLight = Color(0xFFFF6699);
|
||||||
const _pinkDark = Color(0xFFD44E7D);
|
const _pinkDark = Color(0xFFD44E7D);
|
||||||
|
|
||||||
|
const _blueLight = Color(0xFF008AC5);
|
||||||
|
const _blueDark = Color(0xFF2C9CC8);
|
||||||
|
|
||||||
extension ThemeDataExt on ThemeData {
|
extension ThemeDataExt on ThemeData {
|
||||||
bool get isLight => brightness.isLight;
|
bool get isLight => brightness.isLight;
|
||||||
|
|
||||||
@@ -14,6 +17,8 @@ extension ThemeDataExt on ThemeData {
|
|||||||
extension ColorSchemeExt on ColorScheme {
|
extension ColorSchemeExt on ColorScheme {
|
||||||
Color get vipColor => brightness.isLight ? _pinkLight : _pinkDark;
|
Color get vipColor => brightness.isLight ? _pinkLight : _pinkDark;
|
||||||
|
|
||||||
|
Color get blue => brightness.isLight ? _blueLight : _blueDark;
|
||||||
|
|
||||||
Color get btnColor =>
|
Color get btnColor =>
|
||||||
brightness.isLight ? _pinkLight : const Color(0xFF8F0030);
|
brightness.isLight ? _pinkLight : const Color(0xFF8F0030);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user