opt: msg item

Signed-off-by: bggRGjQaUbCoE <githubaccount56556@proton.me>
This commit is contained in:
bggRGjQaUbCoE
2025-05-10 17:40:02 +08:00
parent 68fe3bbd4b
commit 3f3a1a6d7f
2 changed files with 119 additions and 57 deletions

View File

@@ -114,7 +114,8 @@ class _WhisperDetailPageState
if (_whisperDetailController.mid != null) ...[ if (_whisperDetailController.mid != null) ...[
_buildInputView(theme), _buildInputView(theme),
buildPanelContainer(theme.colorScheme.onInverseSurface), buildPanelContainer(theme.colorScheme.onInverseSurface),
], ] else
SizedBox(height: MediaQuery.paddingOf(context).bottom),
], ],
), ),
), ),
@@ -127,11 +128,11 @@ class _WhisperDetailPageState
Success() => loadingState.response?.isNotEmpty == true Success() => loadingState.response?.isNotEmpty == true
? refreshIndicator( ? refreshIndicator(
onRefresh: _whisperDetailController.onRefresh, onRefresh: _whisperDetailController.onRefresh,
child: ListView.builder( child: ListView.separated(
shrinkWrap: true, shrinkWrap: true,
reverse: true, reverse: true,
itemCount: loadingState.response!.length, itemCount: loadingState.response!.length,
padding: const EdgeInsets.only(bottom: 12), padding: const EdgeInsets.all(12),
physics: const AlwaysScrollableScrollPhysics( physics: const AlwaysScrollableScrollPhysics(
parent: ClampingScrollPhysics(), parent: ClampingScrollPhysics(),
), ),
@@ -182,6 +183,8 @@ class _WhisperDetailPageState
: null, : null,
); );
}, },
separatorBuilder: (BuildContext context, int index) =>
const SizedBox(height: 12),
), ),
) )
: scrollErrorWidget( : scrollErrorWidget(

View File

@@ -1,5 +1,6 @@
import 'dart:convert'; import 'dart:convert';
import 'package:PiliPlus/common/constants.dart';
import 'package:PiliPlus/common/widgets/image/network_img_layer.dart'; import 'package:PiliPlus/common/widgets/image/network_img_layer.dart';
import 'package:PiliPlus/grpc/bilibili/im/interfaces/v1.pb.dart' import 'package:PiliPlus/grpc/bilibili/im/interfaces/v1.pb.dart'
show EmotionInfo; show EmotionInfo;
@@ -7,10 +8,12 @@ import 'package:PiliPlus/grpc/bilibili/im/type.pb.dart' show Msg, MsgType;
import 'package:PiliPlus/http/search.dart'; import 'package:PiliPlus/http/search.dart';
import 'package:PiliPlus/models/common/image_preview_type.dart'; import 'package:PiliPlus/models/common/image_preview_type.dart';
import 'package:PiliPlus/models/common/image_type.dart'; import 'package:PiliPlus/models/common/image_type.dart';
import 'package:PiliPlus/utils/app_scheme.dart';
import 'package:PiliPlus/utils/extension.dart'; import 'package:PiliPlus/utils/extension.dart';
import 'package:PiliPlus/utils/id_utils.dart'; import 'package:PiliPlus/utils/id_utils.dart';
import 'package:PiliPlus/utils/page_utils.dart'; import 'package:PiliPlus/utils/page_utils.dart';
import 'package:PiliPlus/utils/utils.dart'; import 'package:PiliPlus/utils/utils.dart';
import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
@@ -63,8 +66,9 @@ class ChatItem extends StatelessWidget {
onLongPress?.call(); onLongPress?.call();
}, },
child: Row( child: Row(
mainAxisAlignment:
isOwner ? MainAxisAlignment.end : MainAxisAlignment.start,
children: [ children: [
if (!isOwner) const SizedBox(width: 12) else const Spacer(),
Container( Container(
constraints: const BoxConstraints(maxWidth: 300.0), constraints: const BoxConstraints(maxWidth: 300.0),
decoration: BoxDecoration( decoration: BoxDecoration(
@@ -78,7 +82,6 @@ class ChatItem extends StatelessWidget {
bottomRight: Radius.circular(isOwner ? 6 : 16), bottomRight: Radius.circular(isOwner ? 6 : 16),
), ),
), ),
margin: const EdgeInsets.only(top: 12),
padding: EdgeInsets.only( padding: EdgeInsets.only(
top: 8, top: 8,
bottom: 6, bottom: 6,
@@ -121,7 +124,6 @@ class ChatItem extends StatelessWidget {
], ],
), ),
), ),
if (!isOwner) const Spacer() else const SizedBox(width: 12),
], ],
), ),
); );
@@ -269,7 +271,6 @@ class ChatItem extends StatelessWidget {
bottomRight: Radius.circular(16), bottomRight: Radius.circular(16),
), ),
), ),
margin: const EdgeInsets.all(12),
padding: const EdgeInsets.all(12), padding: const EdgeInsets.all(12),
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
@@ -559,14 +560,17 @@ class ChatItem extends StatelessWidget {
} }
Widget msgTypeTipMessage_18(ThemeData theme, content) { Widget msgTypeTipMessage_18(ThemeData theme, content) {
return Text( return Padding(
padding: const EdgeInsets.symmetric(vertical: 10),
child: Text(
jsonDecode(content['content']).map((e) => e['text']).join("\n"), jsonDecode(content['content']).map((e) => e['text']).join("\n"),
textAlign: TextAlign.center, textAlign: TextAlign.center,
style: TextStyle( style: TextStyle(
height: 1.5,
letterSpacing: 0.6, letterSpacing: 0.6,
height: 5,
color: theme.colorScheme.outline.withOpacity(0.8), color: theme.colorScheme.outline.withOpacity(0.8),
), ),
),
); );
} }
@@ -619,21 +623,14 @@ class ChatItem extends StatelessWidget {
} }
Widget msgTypeNotifyMsg_10(ThemeData theme, content) { Widget msgTypeNotifyMsg_10(ThemeData theme, content) {
return Row( List? modules = content['modules'] as List?;
children: [ return Center(
const SizedBox(width: 12), child: Container(
Container( constraints: const BoxConstraints(maxWidth: 400),
constraints: const BoxConstraints(maxWidth: 300.0),
decoration: BoxDecoration( decoration: BoxDecoration(
color: theme.colorScheme.secondaryContainer.withOpacity(0.4), color: theme.colorScheme.onInverseSurface,
borderRadius: const BorderRadius.only( borderRadius: const BorderRadius.all(Radius.circular(16)),
topLeft: Radius.circular(16),
topRight: Radius.circular(16),
bottomLeft: Radius.circular(6),
bottomRight: Radius.circular(16),
), ),
),
margin: const EdgeInsets.only(top: 12),
padding: const EdgeInsets.all(12), padding: const EdgeInsets.all(12),
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
@@ -650,29 +647,91 @@ class ChatItem extends StatelessWidget {
.copyWith(color: theme.colorScheme.outline), .copyWith(color: theme.colorScheme.outline),
), ),
Divider(color: theme.colorScheme.primary.withOpacity(0.05)), Divider(color: theme.colorScheme.primary.withOpacity(0.05)),
SelectableText(content['text']) SelectableText(content['text']),
], if (modules?.isNotEmpty == true) ...[
const SizedBox(height: 4),
Text.rich(
TextSpan(
children: modules!.indexed
.map((e) => TextSpan(children: [
TextSpan(
text: e.$2['title'],
style: TextStyle(
color: theme.colorScheme.outline)),
TextSpan(text: ' ${e.$2['detail']}'),
if (e.$1 != modules.length - 1)
const TextSpan(text: '\n'),
]))
.toList(),
), ),
), ),
], ],
if ((content['jump_text'] as String?)?.isNotEmpty == true &&
(content['jump_uri'] as String?)?.isNotEmpty == true) ...[
Divider(color: theme.colorScheme.primary.withOpacity(0.05)),
GestureDetector(
behavior: HitTestBehavior.opaque,
onTap: () {
PiliScheme.routePushFromUrl(content['jump_uri']);
},
child: SizedBox(
width: double.infinity,
child: Text(content['jump_text']),
),
),
],
if ((content['jump_text_2'] as String?)?.isNotEmpty == true &&
(content['jump_uri_2'] as String?)?.isNotEmpty == true) ...[
Divider(color: theme.colorScheme.primary.withOpacity(0.05)),
GestureDetector(
behavior: HitTestBehavior.opaque,
onTap: () {
PiliScheme.routePushFromUrl(content['jump_uri_2']);
},
child: SizedBox(
width: double.infinity,
child: Text(content['jump_text_2']),
),
),
],
if ((content['jump_text_3'] as String?)?.isNotEmpty == true &&
(content['jump_uri_3'] as String?)?.isNotEmpty == true) ...[
Divider(color: theme.colorScheme.primary.withOpacity(0.05)),
GestureDetector(
behavior: HitTestBehavior.opaque,
onTap: () {
PiliScheme.routePushFromUrl(content['jump_uri_3']);
},
child: SizedBox(
width: double.infinity,
child: Text(content['jump_text_3']),
),
),
],
],
),
),
); );
} }
Widget msgTypePictureCard_13(content) { Widget msgTypePictureCard_13(content) {
return Row( return Center(
children: [ child: ConstrainedBox(
const SizedBox(width: 12), constraints: const BoxConstraints(maxWidth: 400.0),
Container( child: ClipRRect(
constraints: const BoxConstraints(maxWidth: 300.0), borderRadius: StyleString.mdRadius,
margin: const EdgeInsets.only(top: 12), child: GestureDetector(
padding: const EdgeInsets.only(bottom: 6), onTap: content['jump_url'] == null
child: NetworkImgLayer( ? null
width: 320, : () {
height: 150, PiliScheme.routePushFromUrl(content['jump_url']);
src: content['pic_url'], },
child: CachedNetworkImage(
imageUrl: Utils.thumbnailImgUrl(content['pic_url']),
),
),
), ),
), ),
],
); );
} }