mirror of
https://github.com/HChaZZY/PiliPlus.git
synced 2025-12-06 09:13:48 +08:00
mod: 无障碍语义适配
This commit is contained in:
@@ -50,9 +50,10 @@ class _AboutPageState extends State<AboutPage> {
|
||||
children: [
|
||||
ConstrainedBox(
|
||||
constraints: const BoxConstraints(maxHeight: 150),
|
||||
child: Image.asset(
|
||||
child: ExcludeSemantics(
|
||||
child: Image.asset(
|
||||
'assets/images/logo/logo_android_2.png',
|
||||
),
|
||||
)),
|
||||
),
|
||||
ListTile(
|
||||
title: Text('PiliPalaX',
|
||||
@@ -65,6 +66,7 @@ class _AboutPageState extends State<AboutPage> {
|
||||
'使用Flutter开发的哔哩哔哩第三方客户端',
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(color: Theme.of(context).colorScheme.outline),
|
||||
semanticsLabel: '与你一起,发现不一样的世界',
|
||||
),
|
||||
),
|
||||
Obx(
|
||||
@@ -156,7 +158,7 @@ class _AboutPageState extends State<AboutPage> {
|
||||
var cleanStatus = await CacheManage().clearCacheAll();
|
||||
if (cleanStatus) {
|
||||
getCacheSize();
|
||||
SmartDialog.showToast('清除成功');
|
||||
SmartDialog.showToast('清除成功');
|
||||
}
|
||||
},
|
||||
title: const Text('清除缓存'),
|
||||
@@ -207,7 +209,7 @@ class AboutController extends GetxController {
|
||||
String buildNumber = currentInfo.buildNumber;
|
||||
//if is android
|
||||
if (Platform.isAndroid) {
|
||||
buildNumber = buildNumber.substring(0,buildNumber.length - 1);
|
||||
buildNumber = buildNumber.substring(0, buildNumber.length - 1);
|
||||
}
|
||||
currentVersion.value = "${currentInfo.version}+$buildNumber";
|
||||
}
|
||||
@@ -265,6 +267,7 @@ class AboutController extends GetxController {
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
// 问题反馈
|
||||
feedback() {
|
||||
launchUrl(
|
||||
|
||||
@@ -15,6 +15,7 @@ import 'package:PiliPalaX/pages/video/detail/introduction/widgets/action_row_ite
|
||||
import 'package:PiliPalaX/pages/video/detail/introduction/widgets/fav_panel.dart';
|
||||
import 'package:PiliPalaX/utils/feed_back.dart';
|
||||
|
||||
import '../../../utils/utils.dart';
|
||||
import 'controller.dart';
|
||||
import 'widgets/intro_detail.dart';
|
||||
|
||||
@@ -192,6 +193,7 @@ class _BangumiInfoState extends State<BangumiInfo> {
|
||||
src: !widget.loadingStatus
|
||||
? widget.bangumiDetail!.cover!
|
||||
: bangumiItem!.cover!,
|
||||
semanticsLabel: '封面',
|
||||
),
|
||||
if (bangumiItem != null &&
|
||||
bangumiItem!.rating != null)
|
||||
@@ -235,6 +237,7 @@ class _BangumiInfoState extends State<BangumiInfo> {
|
||||
width: 34,
|
||||
height: 34,
|
||||
child: IconButton(
|
||||
tooltip: '收藏',
|
||||
style: ButtonStyle(
|
||||
padding: MaterialStateProperty.all(
|
||||
EdgeInsets.zero),
|
||||
@@ -394,18 +397,19 @@ class _BangumiInfoState extends State<BangumiInfo> {
|
||||
crossAxisCount: 5,
|
||||
childAspectRatio: 1.25,
|
||||
children: <Widget>[
|
||||
Obx(
|
||||
() => ActionItem(
|
||||
Obx(() => ActionItem(
|
||||
icon: const Icon(FontAwesomeIcons.thumbsUp),
|
||||
selectIcon: const Icon(FontAwesomeIcons.solidThumbsUp),
|
||||
onTap:
|
||||
handleState(bangumiIntroController.actionLikeVideo),
|
||||
selectStatus: bangumiIntroController.hasLike.value,
|
||||
loadingStatus: false,
|
||||
semanticsLabel: '点赞',
|
||||
text: !widget.loadingStatus
|
||||
? widget.bangumiDetail!.stat!['likes']!.toString()
|
||||
: bangumiItem!.stat!['likes']!.toString()),
|
||||
),
|
||||
? Utils.numFormat(
|
||||
widget.bangumiDetail!.stat!['likes']!)
|
||||
: Utils.numFormat(bangumiItem!.stat!['likes']!),
|
||||
)),
|
||||
Obx(
|
||||
() => ActionItem(
|
||||
icon: const Icon(FontAwesomeIcons.b),
|
||||
@@ -414,9 +418,10 @@ class _BangumiInfoState extends State<BangumiInfo> {
|
||||
handleState(bangumiIntroController.actionCoinVideo),
|
||||
selectStatus: bangumiIntroController.hasCoin.value,
|
||||
loadingStatus: false,
|
||||
semanticsLabel: '投币',
|
||||
text: !widget.loadingStatus
|
||||
? widget.bangumiDetail!.stat!['coins']!.toString()
|
||||
: bangumiItem!.stat!['coins']!.toString()),
|
||||
? Utils.numFormat(widget.bangumiDetail!.stat!['coins']!)
|
||||
: Utils.numFormat(bangumiItem!.stat!['coins']!)),
|
||||
),
|
||||
Obx(
|
||||
() => ActionItem(
|
||||
@@ -425,9 +430,10 @@ class _BangumiInfoState extends State<BangumiInfo> {
|
||||
onTap: () => showFavBottomSheet(),
|
||||
selectStatus: bangumiIntroController.hasFav.value,
|
||||
loadingStatus: false,
|
||||
semanticsLabel: '收藏',
|
||||
text: !widget.loadingStatus
|
||||
? widget.bangumiDetail!.stat!['favorite']!.toString()
|
||||
: bangumiItem!.stat!['favorite']!.toString()),
|
||||
? Utils.numFormat(widget.bangumiDetail!.stat!['favorite']!)
|
||||
: Utils.numFormat(bangumiItem!.stat!['favorite']!)),
|
||||
),
|
||||
ActionItem(
|
||||
icon: const Icon(FontAwesomeIcons.comment),
|
||||
@@ -435,18 +441,20 @@ class _BangumiInfoState extends State<BangumiInfo> {
|
||||
onTap: () => videoDetailCtr.tabCtr.animateTo(1),
|
||||
selectStatus: false,
|
||||
loadingStatus: false,
|
||||
semanticsLabel: '评论',
|
||||
text: !widget.loadingStatus
|
||||
? widget.bangumiDetail!.stat!['reply']!.toString()
|
||||
: bangumiItem!.stat!['reply']!.toString(),
|
||||
? Utils.numFormat(widget.bangumiDetail!.stat!['reply']!)
|
||||
: Utils.numFormat(bangumiItem!.stat!['reply']!),
|
||||
),
|
||||
ActionItem(
|
||||
icon: const Icon(FontAwesomeIcons.shareFromSquare),
|
||||
onTap: () => bangumiIntroController.actionShareVideo(),
|
||||
selectStatus: false,
|
||||
loadingStatus: false,
|
||||
semanticsLabel: '转发',
|
||||
text: !widget.loadingStatus
|
||||
? widget.bangumiDetail!.stat!['share']!.toString()
|
||||
: bangumiItem!.stat!['share']!.toString()),
|
||||
? Utils.numFormat(widget.bangumiDetail!.stat!['share']!)
|
||||
: Utils.numFormat(bangumiItem!.stat!['share']!)),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
@@ -98,6 +98,7 @@ class _BangumiPageState extends State<BangumiPage>
|
||||
style: Theme.of(context).textTheme.titleMedium,
|
||||
),
|
||||
IconButton(
|
||||
tooltip: '刷新',
|
||||
onPressed: () {
|
||||
setState(() {
|
||||
_futureBuilderFutureFollow =
|
||||
|
||||
@@ -95,6 +95,7 @@ class _BangumiPanelState extends State<BangumiPanel> {
|
||||
style: Theme.of(context).textTheme.titleMedium,
|
||||
),
|
||||
IconButton(
|
||||
tooltip: '关闭',
|
||||
icon: const Icon(Icons.close),
|
||||
onPressed: () => Navigator.pop(context),
|
||||
),
|
||||
|
||||
@@ -25,12 +25,15 @@ class _ActionPanelState extends State<ActionPanel> {
|
||||
late ModuleStatModel stat;
|
||||
bool isProcessing = false;
|
||||
void Function()? handleState(Future Function() action) {
|
||||
return isProcessing ? null : () async {
|
||||
setState(() => isProcessing = true);
|
||||
await action();
|
||||
setState(() => isProcessing = false);
|
||||
};
|
||||
return isProcessing
|
||||
? null
|
||||
: () async {
|
||||
setState(() => isProcessing = true);
|
||||
await action();
|
||||
setState(() => isProcessing = false);
|
||||
};
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
@@ -83,12 +86,13 @@ class _ActionPanelState extends State<ActionPanel> {
|
||||
icon: const Icon(
|
||||
FontAwesomeIcons.shareFromSquare,
|
||||
size: 16,
|
||||
semanticLabel: "转发",
|
||||
),
|
||||
style: TextButton.styleFrom(
|
||||
padding: const EdgeInsets.fromLTRB(15, 0, 15, 0),
|
||||
foregroundColor: Theme.of(context).colorScheme.outline,
|
||||
),
|
||||
label: Text(stat.forward!.count ?? '转发'),
|
||||
label: Text(stat.forward!.count ?? ''),
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
@@ -99,12 +103,13 @@ class _ActionPanelState extends State<ActionPanel> {
|
||||
icon: const Icon(
|
||||
FontAwesomeIcons.comment,
|
||||
size: 16,
|
||||
semanticLabel: "评论",
|
||||
),
|
||||
style: TextButton.styleFrom(
|
||||
padding: const EdgeInsets.fromLTRB(15, 0, 15, 0),
|
||||
foregroundColor: Theme.of(context).colorScheme.outline,
|
||||
),
|
||||
label: Text(stat.comment!.count ?? '评论'),
|
||||
label: Text(stat.comment!.count ?? ''),
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
@@ -117,6 +122,7 @@ class _ActionPanelState extends State<ActionPanel> {
|
||||
: FontAwesomeIcons.thumbsUp,
|
||||
size: 16,
|
||||
color: stat.like!.status! ? primary : color,
|
||||
semanticLabel: stat.like!.status! ? "已赞": "点赞",
|
||||
),
|
||||
style: TextButton.styleFrom(
|
||||
padding: const EdgeInsets.fromLTRB(15, 0, 15, 0),
|
||||
@@ -128,7 +134,7 @@ class _ActionPanelState extends State<ActionPanel> {
|
||||
return ScaleTransition(scale: animation, child: child);
|
||||
},
|
||||
child: Text(
|
||||
stat.like!.count ?? '点赞',
|
||||
stat.like!.count ?? '',
|
||||
key: ValueKey<String>(stat.like!.count ?? '点赞'),
|
||||
style: TextStyle(
|
||||
color: stat.like!.status! ? primary : color,
|
||||
|
||||
@@ -48,6 +48,7 @@ class AuthorPanel extends StatelessWidget {
|
||||
children: [
|
||||
Text(
|
||||
item.modules.moduleAuthor.name,
|
||||
// semanticsLabel: "Up主:${item.modules.moduleAuthor.name}",
|
||||
style: TextStyle(
|
||||
color: item.modules.moduleAuthor!.vip != null &&
|
||||
item.modules.moduleAuthor!.vip['status'] > 0
|
||||
@@ -81,6 +82,7 @@ class AuthorPanel extends StatelessWidget {
|
||||
width: 32,
|
||||
height: 32,
|
||||
child: IconButton(
|
||||
tooltip: '更多',
|
||||
style: ButtonStyle(
|
||||
padding: MaterialStateProperty.all(EdgeInsets.zero),
|
||||
),
|
||||
|
||||
@@ -87,6 +87,7 @@ Widget videoSeasonWidget(item, context, type, {floor = 1}) {
|
||||
width: width,
|
||||
height: width / StyleString.aspectRatio,
|
||||
src: content.cover,
|
||||
semanticsLabel: content.title,
|
||||
),
|
||||
),
|
||||
if (content.badge != null && type == 'pgc')
|
||||
@@ -133,7 +134,7 @@ Widget videoSeasonWidget(item, context, type, {floor = 1}) {
|
||||
const SizedBox(width: 10),
|
||||
Text(content.stat.play + '次围观'),
|
||||
const SizedBox(width: 10),
|
||||
Text(content.stat.danmaku + '条弹幕')
|
||||
Text(content.stat.danmu + '条弹幕')
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
@@ -78,10 +78,11 @@ class _EmotePanelState extends State<EmotePanel>
|
||||
overflow: TextOverflow.clip,
|
||||
maxLines: 1,
|
||||
)
|
||||
: Image.network(
|
||||
e.emote![index].url!,
|
||||
: NetworkImgLayer(
|
||||
src: e.emote![index].url!,
|
||||
width: size * 38,
|
||||
height: size * 38,
|
||||
semanticsLabel: e.emote![index].text!,
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
@@ -49,6 +49,7 @@ class _FavPageState extends State<FavPage> {
|
||||
onPressed: () => Get.toNamed(
|
||||
'/favSearch?searchType=1&mediaId=${_favController.favFolderData.value.list!.first.id}'),
|
||||
icon: const Icon(Icons.search_outlined),
|
||||
tooltip: '搜索',
|
||||
),
|
||||
const SizedBox(width: 6),
|
||||
],
|
||||
|
||||
@@ -96,6 +96,7 @@ class _FavDetailPageState extends State<FavDetailPage> {
|
||||
),
|
||||
actions: [
|
||||
IconButton(
|
||||
tooltip: '搜索',
|
||||
onPressed: () =>
|
||||
Get.toNamed('/favSearch?searchType=0&mediaId=$mediaId'),
|
||||
icon: const Icon(Icons.search_outlined),
|
||||
|
||||
@@ -209,6 +209,7 @@ class VideoContent extends StatelessWidget {
|
||||
right: 0,
|
||||
bottom: -4,
|
||||
child: IconButton(
|
||||
tooltip: '取消收藏',
|
||||
style: ButtonStyle(
|
||||
padding: MaterialStateProperty.all(EdgeInsets.zero),
|
||||
),
|
||||
|
||||
@@ -50,6 +50,7 @@ class _FavSearchPageState extends State<FavSearchPage> {
|
||||
titleSpacing: 0,
|
||||
actions: [
|
||||
IconButton(
|
||||
tooltip: '搜索',
|
||||
onPressed: () => _favSearchCtr.submit(),
|
||||
icon: const Icon(Icons.search_outlined, size: 22)),
|
||||
const SizedBox(width: 10)
|
||||
@@ -65,6 +66,7 @@ class _FavSearchPageState extends State<FavSearchPage> {
|
||||
hintText: _favSearchCtr.hintText,
|
||||
border: InputBorder.none,
|
||||
suffixIcon: IconButton(
|
||||
tooltip: '清空',
|
||||
icon: Icon(
|
||||
Icons.clear,
|
||||
size: 22,
|
||||
|
||||
@@ -41,6 +41,7 @@ class _FollowPageState extends State<FollowPage> {
|
||||
IconButton(
|
||||
onPressed: () => Get.toNamed('/followSearch?mid=$mid'),
|
||||
icon: const Icon(Icons.search_outlined),
|
||||
tooltip: '搜索'
|
||||
),
|
||||
PopupMenuButton(
|
||||
icon: const Icon(Icons.more_vert),
|
||||
|
||||
@@ -50,6 +50,7 @@ class _FollowSearchPageState extends State<FollowSearchPage> {
|
||||
titleSpacing: 0,
|
||||
actions: [
|
||||
IconButton(
|
||||
tooltip: '搜索',
|
||||
onPressed: reRequest,
|
||||
icon: const Icon(CupertinoIcons.search, size: 22),
|
||||
),
|
||||
@@ -65,6 +66,7 @@ class _FollowSearchPageState extends State<FollowSearchPage> {
|
||||
hintText: _followSearchController.hintText,
|
||||
border: InputBorder.none,
|
||||
suffixIcon: IconButton(
|
||||
tooltip: '清空',
|
||||
icon: Icon(
|
||||
Icons.clear,
|
||||
size: 22,
|
||||
|
||||
@@ -76,6 +76,7 @@ class _HistoryPageState extends State<HistoryPage> {
|
||||
),
|
||||
actions: [
|
||||
IconButton(
|
||||
tooltip: '搜索',
|
||||
onPressed: () => Get.toNamed('/historySearch'),
|
||||
icon: const Icon(Icons.search_outlined),
|
||||
),
|
||||
@@ -129,6 +130,7 @@ class _HistoryPageState extends State<HistoryPage> {
|
||||
titleSpacing: 0,
|
||||
centerTitle: false,
|
||||
leading: IconButton(
|
||||
tooltip: '取消',
|
||||
onPressed: () {
|
||||
_historyController.enableMultiple.value = false;
|
||||
for (var item in _historyController.historyList) {
|
||||
|
||||
@@ -230,6 +230,7 @@ class HistoryItem extends StatelessWidget {
|
||||
const Duration(milliseconds: 250),
|
||||
curve: Curves.easeInOut,
|
||||
child: IconButton(
|
||||
tooltip: '取消选择',
|
||||
style: ButtonStyle(
|
||||
padding: MaterialStateProperty.all(
|
||||
EdgeInsets.zero),
|
||||
|
||||
@@ -50,6 +50,7 @@ class _HistorySearchPageState extends State<HistorySearchPage> {
|
||||
titleSpacing: 0,
|
||||
actions: [
|
||||
IconButton(
|
||||
tooltip: '搜索',
|
||||
onPressed: () => _historySearchCtr.submit(),
|
||||
icon: const Icon(Icons.search_outlined, size: 22)),
|
||||
const SizedBox(width: 10)
|
||||
@@ -65,6 +66,7 @@ class _HistorySearchPageState extends State<HistorySearchPage> {
|
||||
hintText: _historySearchCtr.hintText,
|
||||
border: InputBorder.none,
|
||||
suffixIcon: IconButton(
|
||||
tooltip: '清空',
|
||||
icon: Icon(
|
||||
Icons.clear,
|
||||
size: 22,
|
||||
|
||||
@@ -220,41 +220,46 @@ class UserInfoWidget extends StatelessWidget {
|
||||
const SizedBox(width: 4),
|
||||
ClipRect(
|
||||
child: IconButton(
|
||||
tooltip: '消息',
|
||||
onPressed: () => Get.toNamed('/whisper'),
|
||||
icon: const Icon(Icons.notifications_none),
|
||||
icon: const Icon(
|
||||
Icons.notifications_none,
|
||||
),
|
||||
),
|
||||
)
|
||||
],
|
||||
const SizedBox(width: 8),
|
||||
Obx(
|
||||
() => userLogin.value
|
||||
? Stack(
|
||||
children: [
|
||||
NetworkImgLayer(
|
||||
type: 'avatar',
|
||||
width: 34,
|
||||
height: 34,
|
||||
src: userFace,
|
||||
),
|
||||
Positioned.fill(
|
||||
child: Material(
|
||||
color: Colors.transparent,
|
||||
child: InkWell(
|
||||
onTap: () => callback?.call(),
|
||||
splashColor: Theme.of(context)
|
||||
.colorScheme
|
||||
.primaryContainer
|
||||
.withOpacity(0.3),
|
||||
borderRadius: const BorderRadius.all(
|
||||
Radius.circular(50),
|
||||
),
|
||||
Semantics(
|
||||
label: "我的",
|
||||
child: Obx(
|
||||
() => userLogin.value
|
||||
? Stack(
|
||||
children: [
|
||||
NetworkImgLayer(
|
||||
type: 'avatar',
|
||||
width: 34,
|
||||
height: 34,
|
||||
src: userFace,
|
||||
),
|
||||
),
|
||||
Positioned.fill(
|
||||
child: Material(
|
||||
color: Colors.transparent,
|
||||
child: InkWell(
|
||||
onTap: () => callback?.call(),
|
||||
splashColor: Theme.of(context)
|
||||
.colorScheme
|
||||
.primaryContainer
|
||||
.withOpacity(0.3),
|
||||
borderRadius: const BorderRadius.all(
|
||||
Radius.circular(50),
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
],
|
||||
)
|
||||
],
|
||||
)
|
||||
: DefaultUser(callback: () => callback!()),
|
||||
),
|
||||
: DefaultUser(callback: () => callback!()),
|
||||
)),
|
||||
],
|
||||
);
|
||||
}
|
||||
@@ -270,6 +275,7 @@ class DefaultUser extends StatelessWidget {
|
||||
width: 38,
|
||||
height: 38,
|
||||
child: IconButton(
|
||||
tooltip: '默认用户头像',
|
||||
style: ButtonStyle(
|
||||
padding: MaterialStateProperty.all(EdgeInsets.zero),
|
||||
backgroundColor: MaterialStateProperty.resolveWith((states) {
|
||||
@@ -409,6 +415,7 @@ class SearchBar extends StatelessWidget {
|
||||
Icon(
|
||||
Icons.search_outlined,
|
||||
color: colorScheme.onSecondaryContainer,
|
||||
semanticLabel: '搜索',
|
||||
),
|
||||
const SizedBox(width: 10),
|
||||
Expanded(
|
||||
|
||||
@@ -43,6 +43,7 @@ class HomeAppBar extends StatelessWidget {
|
||||
Hero(
|
||||
tag: 'searchTag',
|
||||
child: IconButton(
|
||||
tooltip: '搜索',
|
||||
onPressed: () {
|
||||
Get.toNamed('/search');
|
||||
},
|
||||
@@ -72,11 +73,13 @@ class HomeAppBar extends StatelessWidget {
|
||||
width: 32,
|
||||
height: 32,
|
||||
src: userInfo.face,
|
||||
semanticsLabel: '我的',
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 10),
|
||||
] else ...[
|
||||
IconButton(
|
||||
tooltip: '登录',
|
||||
onPressed: () => showModalBottomSheet(
|
||||
context: context,
|
||||
builder: (_) => const SizedBox(
|
||||
|
||||
@@ -136,6 +136,7 @@ class _HtmlRenderPageState extends State<HtmlRenderPage>
|
||||
actions: [
|
||||
const SizedBox(width: 4),
|
||||
IconButton(
|
||||
tooltip: '用内置浏览器打开',
|
||||
onPressed: () {
|
||||
Get.toNamed('/webview', parameters: {
|
||||
'url': url.startsWith('http') ? url : 'https:$url',
|
||||
@@ -148,6 +149,36 @@ class _HtmlRenderPageState extends State<HtmlRenderPage>
|
||||
PopupMenuButton(
|
||||
icon: const Icon(Icons.more_vert),
|
||||
itemBuilder: (BuildContext context) => <PopupMenuEntry>[
|
||||
PopupMenuItem(
|
||||
onTap: () => {
|
||||
_htmlRenderCtr.reqHtml(id),
|
||||
},
|
||||
child: const Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Icon(Icons.refresh, size: 19),
|
||||
SizedBox(width: 10),
|
||||
Text('刷新'),
|
||||
],
|
||||
),
|
||||
),
|
||||
PopupMenuItem(
|
||||
onTap: () => {
|
||||
Get.toNamed('/webview', parameters: {
|
||||
'url': url.startsWith('http') ? url : 'https:$url',
|
||||
'type': 'url',
|
||||
'pageTitle': title,
|
||||
}),
|
||||
},
|
||||
child: const Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Icon(Icons.open_in_new, size: 19),
|
||||
SizedBox(width: 10),
|
||||
Text('内置浏览器打开'),
|
||||
],
|
||||
),
|
||||
),
|
||||
PopupMenuItem(
|
||||
onTap: () => {
|
||||
Clipboard.setData(ClipboardData(text: url)),
|
||||
|
||||
@@ -89,6 +89,7 @@ class _BottomControlState extends State<BottomControl> {
|
||||
width: 34,
|
||||
height: 34,
|
||||
child: IconButton(
|
||||
tooltip: '画中画',
|
||||
style: ButtonStyle(
|
||||
padding: MaterialStateProperty.all(EdgeInsets.zero),
|
||||
),
|
||||
@@ -114,6 +115,7 @@ class _BottomControlState extends State<BottomControl> {
|
||||
const SizedBox(width: 4),
|
||||
],
|
||||
ComBtn(
|
||||
tooltip: '全屏切换',
|
||||
icon: const Icon(
|
||||
Icons.fullscreen,
|
||||
size: 20,
|
||||
|
||||
@@ -25,6 +25,7 @@ class _LoginPageState extends State<LoginPage> {
|
||||
leading: Obx(
|
||||
() => _loginPageCtr.currentIndex.value == 0
|
||||
? IconButton(
|
||||
tooltip: '关闭',
|
||||
onPressed: () async {
|
||||
_loginPageCtr.mobTextFieldNode.unfocus();
|
||||
await Future.delayed(const Duration(milliseconds: 200));
|
||||
@@ -33,6 +34,7 @@ class _LoginPageState extends State<LoginPage> {
|
||||
icon: const Icon(Icons.close_outlined),
|
||||
)
|
||||
: IconButton(
|
||||
tooltip: '返回',
|
||||
onPressed: () => _loginPageCtr.previousPage(),
|
||||
icon: const Icon(Icons.arrow_back),
|
||||
),
|
||||
@@ -174,6 +176,7 @@ class _LoginPageState extends State<LoginPage> {
|
||||
),
|
||||
const SizedBox(width: 4),
|
||||
IconButton(
|
||||
tooltip: '切换至验证码登录',
|
||||
style: ButtonStyle(
|
||||
backgroundColor:
|
||||
MaterialStateProperty.resolveWith(
|
||||
@@ -265,6 +268,7 @@ class _LoginPageState extends State<LoginPage> {
|
||||
),
|
||||
const SizedBox(width: 4),
|
||||
IconButton(
|
||||
tooltip: '切换至密码登录',
|
||||
style: ButtonStyle(
|
||||
backgroundColor:
|
||||
MaterialStateProperty.resolveWith(
|
||||
|
||||
@@ -149,6 +149,7 @@ class _MediaPageState extends State<MediaPage>
|
||||
),
|
||||
),
|
||||
trailing: IconButton(
|
||||
tooltip: '刷新',
|
||||
onPressed: () {
|
||||
setState(() {
|
||||
_futureBuilderFuture = mediaController.queryFavFolder();
|
||||
@@ -189,6 +190,7 @@ class _MediaPageState extends State<MediaPage>
|
||||
right: 14, bottom: 35),
|
||||
child: Center(
|
||||
child: IconButton(
|
||||
tooltip: '查看更多',
|
||||
style: ButtonStyle(
|
||||
padding: MaterialStateProperty.all(
|
||||
EdgeInsets.zero),
|
||||
|
||||
@@ -104,6 +104,7 @@ class _MemberPageState extends State<MemberPage>
|
||||
),
|
||||
actions: [
|
||||
IconButton(
|
||||
tooltip: '搜索',
|
||||
onPressed: () => Get.toNamed(
|
||||
'/memberSearch?mid=$mid&uname=${_memberController.memberInfo.value.name!}'),
|
||||
icon: const Icon(Icons.search_outlined),
|
||||
@@ -310,17 +311,20 @@ class _MemberPageState extends State<MemberPage>
|
||||
FontAwesomeIcons.venus,
|
||||
size: 14,
|
||||
color: Colors.pink,
|
||||
semanticLabel: _memberController.memberInfo.value.sex,
|
||||
),
|
||||
if (_memberController.memberInfo.value.sex == '男')
|
||||
const Icon(
|
||||
FontAwesomeIcons.mars,
|
||||
size: 14,
|
||||
color: Colors.blue,
|
||||
semanticLabel: _memberController.memberInfo.value.sex,
|
||||
),
|
||||
const SizedBox(width: 4),
|
||||
Image.asset(
|
||||
'assets/images/lv/lv${_memberController.memberInfo.value.level}.png',
|
||||
height: 11,
|
||||
semanticLabel: '等级${_memberController.memberInfo.value.level}',
|
||||
),
|
||||
const SizedBox(width: 6),
|
||||
if (_memberController
|
||||
@@ -333,6 +337,7 @@ class _MemberPageState extends State<MemberPage>
|
||||
_memberController.memberInfo.value.vip!
|
||||
.label!['img_label_uri_hans'],
|
||||
height: 20,
|
||||
semanticLabel: _memberController.memberInfo.value.vip!.label!['text'],
|
||||
),
|
||||
] else if (_memberController
|
||||
.memberInfo.value.vip!.status ==
|
||||
@@ -344,6 +349,7 @@ class _MemberPageState extends State<MemberPage>
|
||||
_memberController.memberInfo.value.vip!
|
||||
.label!['img_label_uri_hans_static'],
|
||||
height: 20,
|
||||
semanticLabel: _memberController.memberInfo.value.vip!.label!['text'],
|
||||
),
|
||||
]
|
||||
],
|
||||
|
||||
@@ -147,28 +147,30 @@ class ProfilePanel extends StatelessWidget {
|
||||
],
|
||||
),
|
||||
),
|
||||
Column(
|
||||
children: [
|
||||
Text(
|
||||
!loadingStatus
|
||||
? ctr.userStat!['likes'] != null
|
||||
? Utils.numFormat(
|
||||
ctr.userStat!['likes'],
|
||||
)
|
||||
: '-'
|
||||
: '-',
|
||||
style: const TextStyle(
|
||||
fontWeight: FontWeight.bold)),
|
||||
Text(
|
||||
'获赞',
|
||||
style: TextStyle(
|
||||
fontSize: Theme.of(context)
|
||||
.textTheme
|
||||
.labelMedium!
|
||||
.fontSize),
|
||||
)
|
||||
],
|
||||
),
|
||||
InkWell(
|
||||
onTap: null,
|
||||
child: Column(
|
||||
children: [
|
||||
Text(
|
||||
!loadingStatus
|
||||
? ctr.userStat!['likes'] != null
|
||||
? Utils.numFormat(
|
||||
ctr.userStat!['likes'],
|
||||
)
|
||||
: '-'
|
||||
: '-',
|
||||
style: const TextStyle(
|
||||
fontWeight: FontWeight.bold)),
|
||||
Text(
|
||||
'获赞',
|
||||
style: TextStyle(
|
||||
fontSize: Theme.of(context)
|
||||
.textTheme
|
||||
.labelMedium!
|
||||
.fontSize),
|
||||
)
|
||||
],
|
||||
)),
|
||||
],
|
||||
),
|
||||
),
|
||||
@@ -221,8 +223,7 @@ class ProfilePanel extends StatelessWidget {
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
Get.toNamed('/webview', parameters: {
|
||||
'url':
|
||||
'https://account.bilibili.com/account/home',
|
||||
'url': 'https://account.bilibili.com/account/home',
|
||||
'pageTitle': '编辑资料(建议浏览器打开)',
|
||||
'type': 'url'
|
||||
});
|
||||
|
||||
@@ -43,6 +43,7 @@ class MemberSeasonsPanel extends StatelessWidget {
|
||||
width: 35,
|
||||
height: 35,
|
||||
child: IconButton(
|
||||
tooltip: '前往',
|
||||
onPressed: () => Get.toNamed(
|
||||
'/memberSeasons?mid=${item.meta!.mid}&seasonId=${item.meta!.seasonId}'),
|
||||
style: ButtonStyle(
|
||||
|
||||
@@ -52,6 +52,7 @@ class _MemberSearchPageState extends State<MemberSearchPage>
|
||||
titleSpacing: 0,
|
||||
actions: [
|
||||
IconButton(
|
||||
tooltip: '搜索',
|
||||
onPressed: () => _memberSearchCtr.submit(),
|
||||
icon: const Icon(CupertinoIcons.search, size: 22)),
|
||||
const SizedBox(width: 10)
|
||||
@@ -67,6 +68,7 @@ class _MemberSearchPageState extends State<MemberSearchPage>
|
||||
hintText: _memberSearchCtr.hintText,
|
||||
border: InputBorder.none,
|
||||
suffixIcon: IconButton(
|
||||
tooltip: '清空',
|
||||
icon: Icon(
|
||||
Icons.clear,
|
||||
size: 22,
|
||||
|
||||
@@ -44,46 +44,54 @@ class _MinePageState extends State<MinePage> {
|
||||
toolbarHeight: kTextTabBarHeight + 20,
|
||||
backgroundColor: Colors.transparent,
|
||||
centerTitle: false,
|
||||
title: //logo
|
||||
Row(
|
||||
children: [
|
||||
Image.asset(
|
||||
'assets/images/logo/logo_android_2.png',
|
||||
width: 40,
|
||||
),
|
||||
const SizedBox(width: 5),
|
||||
Text(
|
||||
'PiliPalaX',
|
||||
style: Theme.of(context).textTheme.titleMedium,
|
||||
),
|
||||
],
|
||||
title: ExcludeSemantics(
|
||||
child: Row(
|
||||
children: [
|
||||
Image.asset(
|
||||
'assets/images/logo/logo_android_2.png',
|
||||
width: 40,
|
||||
),
|
||||
const SizedBox(width: 5),
|
||||
Text(
|
||||
'PiliPalaX',
|
||||
style: Theme.of(context).textTheme.titleMedium,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
actions: [
|
||||
IconButton(
|
||||
tooltip: "${MineController.anonymity ? '退出' : '进入'}无痕模式",
|
||||
onPressed: () {
|
||||
MineController.onChangeAnonymity(context);
|
||||
setState(() {});
|
||||
},
|
||||
icon: Icon(
|
||||
MineController.anonymity
|
||||
? Icons.visibility_off
|
||||
: Icons.visibility,
|
||||
? CupertinoIcons.checkmark_shield
|
||||
: CupertinoIcons.shield_slash,
|
||||
size: 22,
|
||||
),
|
||||
),
|
||||
IconButton(
|
||||
onPressed: () => mineController.onChangeTheme(),
|
||||
tooltip:
|
||||
'切换至${mineController.themeType.value == ThemeType.dark ? '浅色' : '深色'}主题',
|
||||
onPressed: () {
|
||||
mineController.onChangeTheme();
|
||||
setState(() {});
|
||||
},
|
||||
icon: Icon(
|
||||
mineController.themeType.value == ThemeType.dark
|
||||
? Icons.light_mode
|
||||
: Icons.mode_night,
|
||||
? CupertinoIcons.moon
|
||||
: CupertinoIcons.sun_min,
|
||||
size: 22,
|
||||
),
|
||||
),
|
||||
IconButton(
|
||||
tooltip: '设置',
|
||||
onPressed: () => Get.toNamed('/setting', preventDuplicates: false),
|
||||
icon: const Icon(
|
||||
Icons.settings,
|
||||
CupertinoIcons.gear,
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 10),
|
||||
@@ -140,6 +148,7 @@ class _MinePageState extends State<MinePage> {
|
||||
child: _mineController.userInfo.value.face != null
|
||||
? NetworkImgLayer(
|
||||
src: _mineController.userInfo.value.face,
|
||||
semanticsLabel: '头像',
|
||||
width: 85,
|
||||
height: 85)
|
||||
: Image.asset('assets/images/noface.jpeg'),
|
||||
@@ -159,6 +168,8 @@ class _MinePageState extends State<MinePage> {
|
||||
Image.asset(
|
||||
'assets/images/lv/lv${_mineController.userInfo.value.levelInfo != null ? _mineController.userInfo.value.levelInfo!.currentLevel : '0'}.png',
|
||||
height: 10,
|
||||
semanticLabel:
|
||||
'等级:${_mineController.userInfo.value.levelInfo != null ? _mineController.userInfo.value.levelInfo!.currentLevel : '0'}',
|
||||
),
|
||||
],
|
||||
),
|
||||
@@ -207,6 +218,8 @@ class _MinePageState extends State<MinePage> {
|
||||
color: Theme.of(context).colorScheme.onPrimary,
|
||||
fontSize: 12,
|
||||
),
|
||||
semanticsLabel:
|
||||
'当前经验${levelInfo.currentExp!},升级需要${levelInfo.nextExp!}',
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
@@ -64,7 +64,10 @@ class SSearchController extends GetxController {
|
||||
void submit() {
|
||||
// ignore: unrelated_type_equality_checks
|
||||
if (searchKeyWord == '') {
|
||||
return;
|
||||
if (hintText == ''){
|
||||
return;
|
||||
}
|
||||
searchKeyWord.value = hintText;
|
||||
}
|
||||
List arr = historyCacheList.where((e) => e != searchKeyWord.value).toList();
|
||||
arr.insert(0, searchKeyWord.value);
|
||||
|
||||
@@ -53,6 +53,7 @@ class _SearchPageState extends State<SearchPage> with RouteAware {
|
||||
titleSpacing: 0,
|
||||
actions: [
|
||||
IconButton(
|
||||
tooltip: '搜索',
|
||||
onPressed: () => _searchController.submit(),
|
||||
icon: const Icon(CupertinoIcons.search, size: 22),
|
||||
),
|
||||
@@ -69,6 +70,7 @@ class _SearchPageState extends State<SearchPage> with RouteAware {
|
||||
hintText: _searchController.hintText,
|
||||
border: InputBorder.none,
|
||||
suffixIcon: IconButton(
|
||||
tooltip: '清空',
|
||||
icon: Icon(
|
||||
Icons.clear,
|
||||
size: 22,
|
||||
|
||||
@@ -87,6 +87,7 @@ class SearchVideoPanel extends StatelessWidget {
|
||||
width: 32,
|
||||
height: 32,
|
||||
child: IconButton(
|
||||
tooltip: '筛选',
|
||||
style: ButtonStyle(
|
||||
padding: MaterialStateProperty.all(EdgeInsets.zero),
|
||||
),
|
||||
|
||||
@@ -87,7 +87,7 @@ class _VideoIntroPanelState extends State<VideoIntroPanel>
|
||||
errMsg: snapshot.data['msg'],
|
||||
btnText: snapshot.data['code'] == -404 ||
|
||||
snapshot.data['code'] == 62002
|
||||
? '返回上一页'
|
||||
? '上一页'
|
||||
: null,
|
||||
fn: () => Get.back(),
|
||||
);
|
||||
@@ -285,8 +285,8 @@ class _VideoInfoState extends State<VideoInfo> with TickerProviderStateMixin {
|
||||
StatDanMu(
|
||||
theme: 'gray',
|
||||
danmu: !loadingStatus
|
||||
? widget.videoDetail!.stat!.danmaku
|
||||
: videoItem['stat'].danmaku,
|
||||
? widget.videoDetail!.stat!.danmu
|
||||
: videoItem['stat'].danmu,
|
||||
size: 'medium',
|
||||
),
|
||||
const SizedBox(width: 10),
|
||||
@@ -335,17 +335,19 @@ class _VideoInfoState extends State<VideoInfo> with TickerProviderStateMixin {
|
||||
Positioned(
|
||||
right: 10,
|
||||
top: 6,
|
||||
child: GestureDetector(
|
||||
onTap: () async {
|
||||
final res =
|
||||
await videoIntroController.aiConclusion();
|
||||
if (res['status']) {
|
||||
showAiBottomSheet();
|
||||
}
|
||||
},
|
||||
child:
|
||||
Image.asset('assets/images/ai.png', height: 22),
|
||||
),
|
||||
child: Semantics(
|
||||
label: 'AI总结',
|
||||
child: GestureDetector(
|
||||
onTap: () async {
|
||||
final res =
|
||||
await videoIntroController.aiConclusion();
|
||||
if (res['status']) {
|
||||
showAiBottomSheet();
|
||||
}
|
||||
},
|
||||
child: Image.asset('assets/images/ai.png',
|
||||
height: 22),
|
||||
)),
|
||||
)
|
||||
],
|
||||
),
|
||||
@@ -406,11 +408,15 @@ class _VideoInfoState extends State<VideoInfo> with TickerProviderStateMixin {
|
||||
fadeOutDuration: Duration.zero,
|
||||
),
|
||||
const SizedBox(width: 10),
|
||||
Text(owner.name,
|
||||
style: const TextStyle(fontSize: 13)),
|
||||
Text(
|
||||
owner.name,
|
||||
style: const TextStyle(fontSize: 13),
|
||||
// semanticsLabel: "Up主:${owner.name}",
|
||||
),
|
||||
const SizedBox(width: 6),
|
||||
Text(
|
||||
follower,
|
||||
semanticsLabel: "粉丝数:$follower",
|
||||
style: TextStyle(
|
||||
fontSize: t.textTheme.labelSmall!.fontSize,
|
||||
color: outline,
|
||||
@@ -498,8 +504,9 @@ class _VideoInfoState extends State<VideoInfo> with TickerProviderStateMixin {
|
||||
onTap: handleState(videoIntroController.actionLikeVideo),
|
||||
selectStatus: videoIntroController.hasLike.value,
|
||||
loadingStatus: loadingStatus,
|
||||
semanticsLabel: '点赞',
|
||||
text: !loadingStatus
|
||||
? widget.videoDetail!.stat!.like!.toString()
|
||||
? Utils.numFormat(widget.videoDetail!.stat!.like!)
|
||||
: '-'),
|
||||
),
|
||||
// ActionItem(
|
||||
@@ -515,8 +522,9 @@ class _VideoInfoState extends State<VideoInfo> with TickerProviderStateMixin {
|
||||
onTap: handleState(videoIntroController.actionCoinVideo),
|
||||
selectStatus: videoIntroController.hasCoin.value,
|
||||
loadingStatus: loadingStatus,
|
||||
semanticsLabel: '投币',
|
||||
text: !loadingStatus
|
||||
? widget.videoDetail!.stat!.coin!.toString()
|
||||
? Utils.numFormat(widget.videoDetail!.stat!.coin!)
|
||||
: '-'),
|
||||
),
|
||||
Obx(
|
||||
@@ -527,8 +535,9 @@ class _VideoInfoState extends State<VideoInfo> with TickerProviderStateMixin {
|
||||
onLongPress: () => showFavBottomSheet(type: 'longPress'),
|
||||
selectStatus: videoIntroController.hasFav.value,
|
||||
loadingStatus: loadingStatus,
|
||||
semanticsLabel: '收藏',
|
||||
text: !loadingStatus
|
||||
? widget.videoDetail!.stat!.favorite!.toString()
|
||||
? Utils.numFormat(widget.videoDetail!.stat!.favorite!)
|
||||
: '-'),
|
||||
),
|
||||
ActionItem(
|
||||
@@ -536,15 +545,19 @@ class _VideoInfoState extends State<VideoInfo> with TickerProviderStateMixin {
|
||||
onTap: () => videoDetailCtr.tabCtr.animateTo(1),
|
||||
selectStatus: false,
|
||||
loadingStatus: loadingStatus,
|
||||
semanticsLabel: '评论',
|
||||
text: !loadingStatus
|
||||
? widget.videoDetail!.stat!.reply!.toString()
|
||||
? Utils.numFormat(widget.videoDetail!.stat!.reply!)
|
||||
: '评论'),
|
||||
ActionItem(
|
||||
icon: const Icon(FontAwesomeIcons.shareFromSquare),
|
||||
onTap: () => videoIntroController.actionShareVideo(),
|
||||
selectStatus: false,
|
||||
loadingStatus: loadingStatus,
|
||||
text: '分享'),
|
||||
semanticsLabel: '分享',
|
||||
text: !loadingStatus
|
||||
? Utils.numFormat(widget.videoDetail!.stat!.share!)
|
||||
: '分享'),
|
||||
],
|
||||
),
|
||||
);
|
||||
|
||||
@@ -10,6 +10,7 @@ class ActionItem extends StatelessWidget {
|
||||
final bool? loadingStatus;
|
||||
final String? text;
|
||||
final bool selectStatus;
|
||||
final String semanticsLabel;
|
||||
|
||||
const ActionItem({
|
||||
Key? key,
|
||||
@@ -20,11 +21,15 @@ class ActionItem extends StatelessWidget {
|
||||
this.loadingStatus,
|
||||
this.text,
|
||||
this.selectStatus = false,
|
||||
required this.semanticsLabel,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return InkWell(
|
||||
return Semantics(
|
||||
label: (text ?? "") + (selectStatus ? "已" :"") + semanticsLabel,
|
||||
child:
|
||||
InkWell(
|
||||
onTap: () => {
|
||||
feedBack(),
|
||||
onTap!(),
|
||||
@@ -37,11 +42,15 @@ class ActionItem extends StatelessWidget {
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
const SizedBox(height: 4),
|
||||
selectStatus
|
||||
? Icon(selectIcon!.icon!,
|
||||
size: 18, color: Theme.of(context).colorScheme.primary)
|
||||
: Icon(icon!.icon!,
|
||||
size: 18, color: Theme.of(context).colorScheme.outline),
|
||||
Icon(
|
||||
selectStatus
|
||||
? selectIcon!.icon!
|
||||
: icon!.icon!,
|
||||
size: 18,
|
||||
color: selectStatus
|
||||
? Theme.of(context).colorScheme.primary
|
||||
: Theme.of(context).colorScheme.outline,
|
||||
),
|
||||
const SizedBox(height: 6),
|
||||
AnimatedOpacity(
|
||||
opacity: loadingStatus! ? 0 : 1,
|
||||
@@ -59,11 +68,12 @@ class ActionItem extends StatelessWidget {
|
||||
? Theme.of(context).colorScheme.primary
|
||||
: Theme.of(context).colorScheme.outline,
|
||||
fontSize: Theme.of(context).textTheme.labelSmall!.fontSize),
|
||||
semanticsLabel: "",
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,6 +33,7 @@ class _FavPanelState extends State<FavPanel> {
|
||||
centerTitle: false,
|
||||
elevation: 0,
|
||||
leading: IconButton(
|
||||
tooltip: '关闭',
|
||||
onPressed: () => Get.back(),
|
||||
icon: const Icon(Icons.close_outlined)),
|
||||
title:
|
||||
|
||||
@@ -61,6 +61,7 @@ class _GroupPanelState extends State<GroupPanel> {
|
||||
centerTitle: false,
|
||||
elevation: 0,
|
||||
leading: IconButton(
|
||||
tooltip: '关闭',
|
||||
onPressed: () => Get.back(),
|
||||
icon: const Icon(Icons.close_outlined)),
|
||||
title:
|
||||
|
||||
@@ -61,7 +61,7 @@ class IntroDetail extends StatelessWidget {
|
||||
const SizedBox(width: 10),
|
||||
StatDanMu(
|
||||
theme: 'gray',
|
||||
danmu: videoDetail!.stat!.danmaku,
|
||||
danmu: videoDetail!.stat!.danmu,
|
||||
size: 'medium',
|
||||
),
|
||||
const SizedBox(width: 10),
|
||||
|
||||
@@ -115,6 +115,7 @@ class _PagesPanelState extends State<PagesPanel> {
|
||||
.titleMedium,
|
||||
),
|
||||
IconButton(
|
||||
tooltip: '关闭',
|
||||
icon: const Icon(Icons.close),
|
||||
onPressed: () => Navigator.pop(context),
|
||||
),
|
||||
|
||||
@@ -210,28 +210,30 @@ class ReplyItem extends StatelessWidget {
|
||||
// title
|
||||
Container(
|
||||
margin: const EdgeInsets.only(top: 10, left: 45, right: 6, bottom: 4),
|
||||
child: Text.rich(
|
||||
style: const TextStyle(height: 1.75),
|
||||
maxLines:
|
||||
replyItem!.content!.isText! && replyLevel == '1' ? 3 : 999,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
TextSpan(
|
||||
children: [
|
||||
if (replyItem!.isTop!)
|
||||
const WidgetSpan(
|
||||
alignment: PlaceholderAlignment.top,
|
||||
child: PBadge(
|
||||
text: 'TOP',
|
||||
size: 'small',
|
||||
stack: 'normal',
|
||||
type: 'line',
|
||||
fs: 9,
|
||||
),
|
||||
),
|
||||
buildContent(context, replyItem!, replyReply, null),
|
||||
],
|
||||
),
|
||||
),
|
||||
child: Semantics(
|
||||
label: replyItem?.content?.message ?? "",
|
||||
child: Text.rich(
|
||||
style: const TextStyle(height: 1.75),
|
||||
maxLines:
|
||||
replyItem!.content!.isText! && replyLevel == '1' ? 3 : 999,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
TextSpan(
|
||||
children: [
|
||||
if (replyItem!.isTop!)
|
||||
const WidgetSpan(
|
||||
alignment: PlaceholderAlignment.top,
|
||||
child: PBadge(
|
||||
text: 'TOP',
|
||||
size: 'small',
|
||||
stack: 'normal',
|
||||
type: 'line',
|
||||
fs: 9,
|
||||
),
|
||||
),
|
||||
buildContent(context, replyItem!, replyReply, null),
|
||||
],
|
||||
),
|
||||
)),
|
||||
),
|
||||
// 操作区域
|
||||
bottonAction(context, replyItem!.replyControl),
|
||||
|
||||
@@ -76,6 +76,7 @@ class _ZanButtonState extends State<ZanButton> {
|
||||
: FontAwesomeIcons.thumbsUp,
|
||||
size: 16,
|
||||
color: widget.replyItem!.action == 1 ? primary : color,
|
||||
semanticLabel: widget.replyItem!.action == 1 ? '已赞' : '点赞',
|
||||
),
|
||||
const SizedBox(width: 4),
|
||||
AnimatedSwitcher(
|
||||
|
||||
@@ -5,6 +5,7 @@ class ToolbarIconButton extends StatelessWidget {
|
||||
final Icon icon;
|
||||
final String toolbarType;
|
||||
final bool selected;
|
||||
final String tooltip;
|
||||
|
||||
const ToolbarIconButton({
|
||||
super.key,
|
||||
@@ -12,6 +13,7 @@ class ToolbarIconButton extends StatelessWidget {
|
||||
required this.icon,
|
||||
required this.toolbarType,
|
||||
required this.selected,
|
||||
required this.tooltip,
|
||||
});
|
||||
|
||||
@override
|
||||
@@ -20,6 +22,7 @@ class ToolbarIconButton extends StatelessWidget {
|
||||
width: 36,
|
||||
height: 36,
|
||||
child: IconButton(
|
||||
tooltip: tooltip,
|
||||
onPressed: onPressed,
|
||||
icon: icon,
|
||||
highlightColor: Theme.of(context).colorScheme.secondaryContainer,
|
||||
|
||||
@@ -192,6 +192,7 @@ class _VideoReplyNewDialogState extends State<VideoReplyNewDialog>
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
ToolbarIconButton(
|
||||
tooltip: '输入',
|
||||
onPressed: () {
|
||||
if (toolbarType == 'emote') {
|
||||
setState(() {
|
||||
@@ -206,6 +207,7 @@ class _VideoReplyNewDialogState extends State<VideoReplyNewDialog>
|
||||
),
|
||||
const SizedBox(width: 20),
|
||||
ToolbarIconButton(
|
||||
tooltip: '表情',
|
||||
onPressed: () {
|
||||
if (toolbarType == 'input') {
|
||||
setState(() {
|
||||
|
||||
@@ -85,6 +85,7 @@ class _VideoReplyReplyPanelState extends State<VideoReplyReplyPanel> {
|
||||
children: <Widget>[
|
||||
const Text('评论详情'),
|
||||
IconButton(
|
||||
tooltip: '关闭',
|
||||
icon: const Icon(Icons.close, size: 20),
|
||||
onPressed: () {
|
||||
_videoReplyReplyController.currentPage = 0;
|
||||
|
||||
@@ -1027,6 +1027,7 @@ class _HeaderControlState extends State<HeaderControl> {
|
||||
children: [
|
||||
// SizedBox(width: MediaQuery.of(context).padding.left,),
|
||||
ComBtn(
|
||||
tooltip: '上一页',
|
||||
icon: const Icon(
|
||||
FontAwesomeIcons.arrowLeft,
|
||||
size: 15,
|
||||
@@ -1048,8 +1049,9 @@ class _HeaderControlState extends State<HeaderControl> {
|
||||
},
|
||||
),
|
||||
SizedBox(width: buttonSpace),
|
||||
if ((videoIntroController.videoDetail.value.title != null) && (isFullScreen ||
|
||||
(!isFullScreen && isLandscape && !horizontalScreen))) ...[
|
||||
if ((videoIntroController.videoDetail.value.title != null) &&
|
||||
(isFullScreen ||
|
||||
(!isFullScreen && isLandscape && !horizontalScreen))) ...[
|
||||
Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
@@ -1090,6 +1092,7 @@ class _HeaderControlState extends State<HeaderControl> {
|
||||
)
|
||||
] else ...[
|
||||
ComBtn(
|
||||
tooltip: '返回主页',
|
||||
icon: const Icon(
|
||||
FontAwesomeIcons.house,
|
||||
size: 15,
|
||||
@@ -1118,12 +1121,13 @@ class _HeaderControlState extends State<HeaderControl> {
|
||||
width: 34,
|
||||
height: 34,
|
||||
child: IconButton(
|
||||
tooltip: '发弹幕',
|
||||
style: ButtonStyle(
|
||||
padding: MaterialStateProperty.all(EdgeInsets.zero),
|
||||
),
|
||||
onPressed: () => showShootDanmakuSheet(),
|
||||
icon: const Icon(
|
||||
Icons.add_card_outlined,
|
||||
Icons.add_comment_outlined,
|
||||
size: 19,
|
||||
color: Colors.white,
|
||||
),
|
||||
@@ -1135,6 +1139,7 @@ class _HeaderControlState extends State<HeaderControl> {
|
||||
height: 34,
|
||||
child: Obx(
|
||||
() => IconButton(
|
||||
tooltip: "${_.isOpenDanmu.value ? '关闭' : '开启'}弹幕",
|
||||
style: ButtonStyle(
|
||||
padding: MaterialStateProperty.all(EdgeInsets.zero),
|
||||
),
|
||||
@@ -1143,8 +1148,8 @@ class _HeaderControlState extends State<HeaderControl> {
|
||||
},
|
||||
icon: Icon(
|
||||
_.isOpenDanmu.value
|
||||
? Icons.subtitles_outlined
|
||||
: Icons.subtitles_off_outlined,
|
||||
? Icons.comment_outlined
|
||||
: Icons.comments_disabled_outlined,
|
||||
size: 19,
|
||||
color: Colors.white,
|
||||
),
|
||||
@@ -1157,6 +1162,7 @@ class _HeaderControlState extends State<HeaderControl> {
|
||||
width: 34,
|
||||
height: 34,
|
||||
child: IconButton(
|
||||
tooltip: '画中画',
|
||||
style: ButtonStyle(
|
||||
padding: MaterialStateProperty.all(EdgeInsets.zero),
|
||||
),
|
||||
@@ -1182,6 +1188,7 @@ class _HeaderControlState extends State<HeaderControl> {
|
||||
SizedBox(width: buttonSpace),
|
||||
],
|
||||
ComBtn(
|
||||
tooltip: '更多设置',
|
||||
icon: const Icon(
|
||||
Icons.more_vert_outlined,
|
||||
size: 18,
|
||||
|
||||
@@ -27,6 +27,7 @@ class _WebviewPageState extends State<WebviewPage> {
|
||||
actions: [
|
||||
const SizedBox(width: 4),
|
||||
IconButton(
|
||||
tooltip: '刷新',
|
||||
onPressed: () {
|
||||
_webviewController.controller.reload();
|
||||
},
|
||||
@@ -34,6 +35,7 @@ class _WebviewPageState extends State<WebviewPage> {
|
||||
color: Theme.of(context).colorScheme.primary),
|
||||
),
|
||||
IconButton(
|
||||
tooltip: '用外部浏览器打开',
|
||||
onPressed: () {
|
||||
launchUrl(Uri.parse(_webviewController.url));
|
||||
},
|
||||
|
||||
@@ -90,6 +90,7 @@ class _WhisperDetailPageState extends State<WhisperDetailPage>
|
||||
width: 34,
|
||||
height: 34,
|
||||
child: IconButton(
|
||||
tooltip: '返回',
|
||||
style: ButtonStyle(
|
||||
padding: MaterialStateProperty.all(EdgeInsets.zero),
|
||||
backgroundColor: MaterialStateProperty.resolveWith(
|
||||
@@ -160,7 +161,8 @@ class _WhisperDetailPageState extends State<WhisperDetailPage>
|
||||
reverse: true,
|
||||
itemBuilder: (_, int i) {
|
||||
return ChatItem(
|
||||
item: messageList[i], e_infos: _whisperDetailController.eInfos);
|
||||
item: messageList[i],
|
||||
e_infos: _whisperDetailController.eInfos);
|
||||
},
|
||||
);
|
||||
}),
|
||||
@@ -197,6 +199,7 @@ class _WhisperDetailPageState extends State<WhisperDetailPage>
|
||||
// ),
|
||||
// ),
|
||||
IconButton(
|
||||
tooltip: '表情',
|
||||
onPressed: () {
|
||||
// if (toolbarType == 'input') {
|
||||
// setState(() {
|
||||
@@ -220,22 +223,25 @@ class _WhisperDetailPageState extends State<WhisperDetailPage>
|
||||
.withOpacity(0.08),
|
||||
borderRadius: BorderRadius.circular(40.0),
|
||||
),
|
||||
child: TextField(
|
||||
readOnly: true,
|
||||
style: Theme.of(context).textTheme.titleMedium,
|
||||
controller: _replyContentController,
|
||||
autofocus: false,
|
||||
focusNode: replyContentFocusNode,
|
||||
decoration: const InputDecoration(
|
||||
border: InputBorder.none, // 移除默认边框
|
||||
hintText: '开发中 ...', // 提示文本
|
||||
contentPadding: EdgeInsets.symmetric(
|
||||
horizontal: 16.0, vertical: 12.0), // 内边距
|
||||
),
|
||||
),
|
||||
child: Semantics(
|
||||
label: '私信输入框(开发中)',
|
||||
child: TextField(
|
||||
readOnly: true,
|
||||
style: Theme.of(context).textTheme.titleMedium,
|
||||
controller: _replyContentController,
|
||||
autofocus: false,
|
||||
focusNode: replyContentFocusNode,
|
||||
decoration: const InputDecoration(
|
||||
border: InputBorder.none, // 移除默认边框
|
||||
hintText: '开发中 ...', // 提示文本
|
||||
contentPadding: EdgeInsets.symmetric(
|
||||
horizontal: 16.0, vertical: 12.0), // 内边距
|
||||
),
|
||||
)),
|
||||
),
|
||||
),
|
||||
IconButton(
|
||||
tooltip: '发送',
|
||||
// onPressed: _whisperDetailController.sendMsg,
|
||||
onPressed: null,
|
||||
icon: Icon(
|
||||
|
||||
Reference in New Issue
Block a user