Files
App/lib/screens/developers/bot_detail.dart
2025-08-26 01:18:54 +08:00

162 lines
5.0 KiB
Dart

import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:island/models/bot.dart';
import 'package:island/screens/developers/bot_keys.dart';
import 'package:island/screens/developers/edit_bot.dart';
import 'package:island/widgets/app_scaffold.dart';
import 'package:island/widgets/content/cloud_files.dart';
import 'package:island/widgets/response.dart';
import 'package:material_symbols_icons/symbols.dart';
import 'package:go_router/go_router.dart';
import 'package:styled_widget/styled_widget.dart';
class BotDetailScreen extends HookConsumerWidget {
final String publisherName;
final String projectId;
final String botId;
const BotDetailScreen({
super.key,
required this.publisherName,
required this.projectId,
required this.botId,
});
@override
Widget build(BuildContext context, WidgetRef ref) {
final tabController = useTabController(initialLength: 2);
final botData = ref.watch(botProvider(publisherName, projectId, botId));
return AppScaffold(
appBar: AppBar(
title: Text(botData.value?.account.nick ?? 'botDetails'.tr()),
actions: [
IconButton(
icon: const Icon(Symbols.edit),
onPressed:
botData.value == null
? null
: () {
context.pushNamed(
'developerBotEdit',
pathParameters: {
'name': publisherName,
'projectId': projectId,
'id': botId,
},
);
},
),
],
bottom: TabBar(
controller: tabController,
tabs: [
Tab(
child: Text(
'overview'.tr(),
textAlign: TextAlign.center,
style: TextStyle(
color: Theme.of(context).appBarTheme.foregroundColor!,
),
),
),
Tab(
child: Text(
'keys'.tr(),
textAlign: TextAlign.center,
style: TextStyle(
color: Theme.of(context).appBarTheme.foregroundColor!,
),
),
),
],
),
),
body: botData.when(
data: (bot) {
if (bot == null) {
return Center(child: Text('botNotFound'.tr()));
}
return TabBarView(
controller: tabController,
physics: const NeverScrollableScrollPhysics(),
children: [
_BotOverview(bot: bot),
BotKeysScreen(
publisherName: publisherName,
projectId: projectId,
botId: botId,
),
],
);
},
loading: () => const Center(child: CircularProgressIndicator()),
error:
(err, stack) => ResponseErrorWidget(
error: err,
onRetry:
() => ref.invalidate(
botProvider(publisherName, projectId, botId),
),
),
),
);
}
}
class _BotOverview extends StatelessWidget {
final Bot bot;
const _BotOverview({required this.bot});
@override
Widget build(BuildContext context) {
return SingleChildScrollView(
child: Column(
children: [
AspectRatio(
aspectRatio: 16 / 7,
child: Stack(
clipBehavior: Clip.none,
fit: StackFit.expand,
children: [
Container(
color: Theme.of(context).colorScheme.surfaceContainer,
child:
bot.account.profile.background != null
? CloudFileWidget(
item: bot.account.profile.background!,
fit: BoxFit.cover,
)
: const SizedBox.shrink(),
),
Positioned(
left: 20,
bottom: -32,
child: ProfilePictureWidget(
fileId: bot.account.profile.picture?.id,
radius: 40,
fallbackIcon: Symbols.smart_toy,
),
),
],
),
).padding(bottom: 32),
ListTile(title: Text('name'.tr()), subtitle: Text(bot.account.name)),
ListTile(
title: Text('nickname'.tr()),
subtitle: Text(bot.account.nick),
),
ListTile(title: Text('slug'.tr()), subtitle: Text(bot.slug)),
if (bot.account.profile.bio.isNotEmpty)
ListTile(
title: Text('bio'.tr()),
subtitle: Text(bot.account.profile.bio),
),
],
).padding(bottom: 24),
);
}
}