diff --git a/lib/models/dynamics/result.dart b/lib/models/dynamics/result.dart index 15aeefa4b..e4d4ab2bc 100644 --- a/lib/models/dynamics/result.dart +++ b/lib/models/dynamics/result.dart @@ -167,6 +167,7 @@ class ItemModulesModel { List? moduleContent; ModuleBlocked? moduleBlocked; ModuleFold? moduleFold; + ModuleInteraction? moduleInteraction; ItemModulesModel.fromJson(Map json) { moduleAuthor = json['module_author'] != null @@ -184,6 +185,9 @@ class ItemModulesModel { moduleFold = json['module_fold'] != null ? ModuleFold.fromJson(json['module_fold']) : null; + moduleInteraction = json['module_interaction'] != null + ? ModuleInteraction.fromJson(json['module_interaction']) + : null; } ItemModulesModel.fromOpusJson(List json) { @@ -234,6 +238,28 @@ class ItemModulesModel { } } +class ModuleInteraction { + List? items; + + ModuleInteraction.fromJson(Map json) { + items = (json['items'] as List?) + ?.map((e) => ModuleInteractionItem.fromJson(e)) + .toList(); + } +} + +class ModuleInteractionItem { + int? type; + DynamicDescModel? desc; + + ModuleInteractionItem.fromJson(Map json) { + type = json['type']; + desc = json["desc"] == null + ? null + : DynamicDescModel.fromJson(json["desc"]); + } +} + class ModuleFold { List? ids; String? statement; diff --git a/lib/pages/dynamics/widgets/dynamic_panel.dart b/lib/pages/dynamics/widgets/dynamic_panel.dart index b92d627d3..e0ac6e774 100644 --- a/lib/pages/dynamics/widgets/dynamic_panel.dart +++ b/lib/pages/dynamics/widgets/dynamic_panel.dart @@ -5,6 +5,7 @@ import 'package:PiliPlus/models/dynamics/result.dart'; import 'package:PiliPlus/pages/dynamics/widgets/action_panel.dart'; import 'package:PiliPlus/pages/dynamics/widgets/author_panel.dart'; import 'package:PiliPlus/pages/dynamics/widgets/dyn_content.dart'; +import 'package:PiliPlus/pages/dynamics/widgets/interaction.dart'; import 'package:PiliPlus/utils/page_utils.dart'; import 'package:PiliPlus/utils/platform_utils.dart'; import 'package:flutter/material.dart' hide InkWell; @@ -88,6 +89,12 @@ class DynamicPanel extends StatelessWidget { ), const SizedBox(height: 2), if (!isDetail) ...[ + if (item.modules.moduleInteraction case final moduleInteraction?) + if (moduleInteraction.items?.isNotEmpty == true) + dynInteraction( + theme: theme, + items: moduleInteraction.items!, + ), ActionPanel(item: item), if (item.modules.moduleFold case final moduleFold?) ...[ Divider( diff --git a/lib/pages/dynamics/widgets/interaction.dart b/lib/pages/dynamics/widgets/interaction.dart new file mode 100644 index 000000000..26c5f2af1 --- /dev/null +++ b/lib/pages/dynamics/widgets/interaction.dart @@ -0,0 +1,90 @@ +import 'package:PiliPlus/models/dynamics/result.dart'; +import 'package:flutter/foundation.dart' show kDebugMode; +import 'package:flutter/gestures.dart'; +import 'package:flutter/material.dart'; +import 'package:font_awesome_flutter/font_awesome_flutter.dart'; +import 'package:get/get_core/src/get_main.dart'; +import 'package:get/get_navigation/src/extension_navigation.dart'; + +Widget dynInteraction({ + required ThemeData theme, + required List items, +}) { + try { + Widget child; + if (items.length > 1) { + child = Column( + spacing: 3, + mainAxisSize: .min, + crossAxisAlignment: .start, + children: items.map((e) => _item(theme, e)).toList(), + ); + } else { + child = _item(theme, items.single); + } + return Container( + padding: const .only(left: 8), + margin: const .only(left: 12, right: 12, top: 6), + decoration: BoxDecoration( + border: Border( + left: BorderSide( + width: 1.5, + color: theme.colorScheme.outline.withValues(alpha: 0.3), + ), + ), + ), + child: child, + ); + } catch (e) { + if (kDebugMode) { + return Text( + 'interaction error: $e', + style: TextStyle(color: theme.colorScheme.error), + ); + } + return const SizedBox.shrink(); + } +} + +Widget _item( + ThemeData theme, + ModuleInteractionItem item, +) { + return Text.rich( + style: const TextStyle(fontSize: 13, height: 1.3), + strutStyle: const StrutStyle(fontSize: 13, height: 1.3, leading: 0), + TextSpan( + children: [ + WidgetSpan( + alignment: .middle, + child: Padding( + padding: const .only(right: 6), + child: Icon( + size: 13, + color: theme.colorScheme.outline, + switch (item.type) { + 1 => FontAwesomeIcons.comment, + _ => FontAwesomeIcons.thumbsUp, + }, + ), + ), + ), + ...item.desc!.richTextNodes!.map( + (e) { + final isAt = e.type == 'RICH_TEXT_NODE_TYPE_AT'; + return TextSpan( + text: e.origText, + style: isAt + ? null + : TextStyle(color: theme.colorScheme.onSurfaceVariant), + recognizer: isAt + ? (TapGestureRecognizer() + ..onTap = () => Get.toNamed('/member?mid=${e.rid}')) + : null, + ); + }, + ), + ], + ), + ); +}