🐛 Fix bugs

This commit is contained in:
2025-09-24 22:34:05 +08:00
parent 67eac5dcf5
commit 1de7ef8c96
5 changed files with 180 additions and 126 deletions

View File

@@ -3,6 +3,7 @@ import 'package:flutter/material.dart';
import 'package:gap/gap.dart';
import 'package:island/models/activity.dart';
import 'package:island/services/time.dart';
import 'package:island/utils/activity_utils.dart';
import 'package:material_symbols_icons/symbols.dart';
import 'package:styled_widget/styled_widget.dart';
@@ -75,7 +76,10 @@ class EventDetailsWidget extends StatelessWidget {
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(status.label),
if ((getActivityTitle(status.label, status.meta) ?? status.label).isNotEmpty)
Text(getActivityTitle(status.label, status.meta) ?? status.label),
if (getActivitySubtitle(status.meta) != null)
Text(getActivitySubtitle(status.meta)!).fontSize(11).opacity(0.8),
Text(
'${status.createdAt.formatSystem()} - ${status.clearedAt?.formatSystem() ?? 'present'.tr()}',
).fontSize(11).opacity(0.8),

View File

@@ -4,8 +4,10 @@ import 'package:flutter/material.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:island/models/account.dart';
import 'package:island/pods/network.dart';
import 'package:island/pods/userinfo.dart';
import 'package:island/screens/account/profile.dart';
import 'package:island/services/time.dart';
import 'package:island/utils/activity_utils.dart';
import 'package:island/widgets/account/status_creation.dart';
import 'package:material_symbols_icons/symbols.dart';
import 'package:riverpod_annotation/riverpod_annotation.dart';
@@ -13,8 +15,31 @@ import 'package:styled_widget/styled_widget.dart';
part 'status.g.dart';
class CurrentAccountStatusNotifier extends StateNotifier<SnAccountStatus?> {
CurrentAccountStatusNotifier() : super(null);
void setStatus(SnAccountStatus status) {
state = status;
}
void clearStatus() {
state = null;
}
}
final currentAccountStatusProvider = StateNotifierProvider<CurrentAccountStatusNotifier, SnAccountStatus?>((ref) {
return CurrentAccountStatusNotifier();
});
@riverpod
Future<SnAccountStatus?> accountStatus(Ref ref, String uname) async {
final userInfo = ref.watch(userInfoProvider);
if (uname == 'me' || (userInfo.value != null && uname == userInfo.value!.name)) {
final local = ref.watch(currentAccountStatusProvider);
if (local != null) {
return local;
}
}
final apiClient = ref.watch(apiClientProvider);
try {
final resp = await apiClient.get('/id/accounts/$uname/statuses');
@@ -110,129 +135,13 @@ class AccountStatusWidget extends HookConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
final status = ref.watch(accountStatusProvider(uname));
final userInfo = ref.watch(userInfoProvider);
final localStatus = ref.watch(currentAccountStatusProvider);
final status = (uname == 'me' || (userInfo.value != null && uname == userInfo.value!.name && localStatus != null))
? AsyncValue.data(localStatus)
: ref.watch(accountStatusProvider(uname));
final account = ref.watch(accountProvider(uname));
String? getActivityTitle(String? label, Map<String, dynamic>? meta) {
if (meta == null) return label;
if (meta['assets']?['large_text'] is String) {
return meta['assets']?['large_text'];
}
return label;
}
String? getActivitySubtitle(Map<String, dynamic>? meta) {
if (meta == null) return null;
if (meta['assets']?['small_text'] is String) {
return meta['assets']?['small_text'];
}
return null;
}
InlineSpan getActivityFullMessage(SnAccountStatus? status) {
if (status?.meta == null) return TextSpan(text: 'No activity details available');
final meta = status!.meta!;
final List<InlineSpan> spans = [];
if (meta.containsKey('assets') && meta['assets'] is Map) {
final assets = meta['assets'] as Map<String, dynamic>;
if (assets.containsKey('large_text')) {
spans.add(TextSpan(text: assets['large_text'], style: TextStyle(fontWeight: FontWeight.bold)));
}
if (assets.containsKey('small_text')) {
if (spans.isNotEmpty) spans.add(TextSpan(text: '\n'));
spans.add(TextSpan(text: assets['small_text']));
}
}
String normalText = '';
if (meta.containsKey('details')) {
normalText += 'Details: ${meta['details']}\n';
}
if (meta.containsKey('state')) {
normalText += 'State: ${meta['state']}\n';
}
if (meta.containsKey('timestamps') && meta['timestamps'] is Map) {
final ts = meta['timestamps'] as Map<String, dynamic>;
if (ts.containsKey('start') && ts['start'] is int) {
final start = DateTime.fromMillisecondsSinceEpoch(ts['start'] * 1000);
normalText += 'Started: ${start.toLocal()}\n';
}
if (ts.containsKey('end') && ts['end'] is int) {
final end = DateTime.fromMillisecondsSinceEpoch(ts['end'] * 1000);
normalText += 'Ends: ${end.toLocal()}\n';
}
}
if (meta.containsKey('party') && meta['party'] is Map) {
final party = meta['party'] as Map<String, dynamic>;
if (party.containsKey('size') && party['size'] is List && party['size'].length >= 2) {
final size = party['size'] as List;
normalText += 'Party: ${size[0]}/${size[1]}\n';
}
}
if (meta.containsKey('instance')) {
normalText += 'Instance: ${meta['instance']}\n';
}
// Add other keys if present
meta.forEach((key, value) {
if (!['details', 'state', 'timestamps', 'assets', 'party', 'secrets', 'instance'].contains(key)) {
normalText += '$key: $value\n';
}
});
if (normalText.isNotEmpty) {
if (spans.isNotEmpty) spans.add(TextSpan(text: '\n'));
spans.add(TextSpan(text: normalText.trimRight()));
}
return TextSpan(children: spans);
}
Widget _buildActivityDetails(SnAccountStatus? status) {
if (status?.meta == null) return Text('No activity details available');
final meta = status!.meta!;
final List<Widget> children = [];
if (meta.containsKey('assets') && meta['assets'] is Map) {
final assets = meta['assets'] as Map<String, dynamic>;
if (assets.containsKey('large_text')) {
children.add(Text(assets['large_text']));
}
if (assets.containsKey('small_text')) {
children.add(Text(assets['small_text']));
}
}
if (meta.containsKey('details')) {
children.add(Text('Details: ${meta['details']}'));
}
if (meta.containsKey('state')) {
children.add(Text('State: ${meta['state']}'));
}
if (meta.containsKey('timestamps') && meta['timestamps'] is Map) {
final ts = meta['timestamps'] as Map<String, dynamic>;
if (ts.containsKey('start') && ts['start'] is int) {
final start = DateTime.fromMillisecondsSinceEpoch(ts['start'] * 1000);
children.add(Text('Started: ${start.toLocal()}'));
}
if (ts.containsKey('end') && ts['end'] is int) {
final end = DateTime.fromMillisecondsSinceEpoch(ts['end'] * 1000);
children.add(Text('Ends: ${end.toLocal()}'));
}
}
if (meta.containsKey('party') && meta['party'] is Map) {
final party = meta['party'] as Map<String, dynamic>;
if (party.containsKey('size') && party['size'] is List && party['size'].length >= 2) {
final size = party['size'] as List;
children.add(Text('Party: ${size[0]}/${size[1]}'));
}
}
if (meta.containsKey('instance')) {
children.add(Text('Instance: ${meta['instance']}'));
}
// Add other keys if present
children.addAll(meta.entries.where((e) => !['details', 'state', 'timestamps', 'assets', 'party', 'secrets', 'instance'].contains(e.key)).map((e) => Text('${e.key}: ${e.value}')));
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: children,
);
}
return Padding(
padding: padding ?? EdgeInsets.symmetric(horizontal: 27, vertical: 4),
child: Row(
@@ -259,7 +168,7 @@ class AccountStatusWidget extends HookConsumerWidget {
context: context,
builder: (context) => AlertDialog(
title: Text('Activity Details'),
content: _buildActivityDetails(status.value),
content: buildActivityDetails(status.value),
actions: [
TextButton(
onPressed: () => Navigator.of(context).pop(),