Surface/lib/widgets/realm/realm_item.dart
2025-02-20 23:44:28 +08:00

150 lines
4.9 KiB
Dart

import 'package:flutter/material.dart';
import 'package:gap/gap.dart';
import 'package:go_router/go_router.dart';
import 'package:material_symbols_icons/symbols.dart';
import 'package:provider/provider.dart';
import 'package:styled_widget/styled_widget.dart';
import 'package:surface/providers/sn_network.dart';
import 'package:surface/types/realm.dart';
import 'package:surface/widgets/account/account_image.dart';
import 'package:surface/widgets/universal_image.dart';
class RealmItemWidget extends StatelessWidget {
final SnRealm item;
final bool isListView;
final List<PopupMenuItem>? actionListView;
final Function? onUpdate;
final Function? onTap;
final bool showPopularity;
const RealmItemWidget({
super.key,
required this.item,
required this.isListView,
this.actionListView,
this.onUpdate,
this.onTap,
this.showPopularity = true,
});
@override
Widget build(BuildContext context) {
if (isListView) {
return ListTile(
contentPadding: const EdgeInsets.symmetric(horizontal: 16),
leading: AccountImage(
content: item.avatar,
fallbackWidget: const Icon(Symbols.group, size: 20),
),
title: Text(item.name),
subtitle: Row(
children: [
if (showPopularity) const Icon(Symbols.local_fire_department, size: 18).padding(right: 1),
if (showPopularity) Text(item.popularity.toString()),
if (showPopularity) const Gap(6),
Expanded(
child: Text(
item.description,
maxLines: 1,
overflow: TextOverflow.ellipsis,
),
),
],
),
trailing:
actionListView != null ? PopupMenuButton(itemBuilder: (BuildContext context) => actionListView!) : null,
onTap: () {
if (onTap != null) {
onTap!();
return;
}
GoRouter.of(context).pushNamed(
'realmDetail',
pathParameters: {'alias': item.alias},
).then((value) {
if (value == true) {
onUpdate?.call();
}
});
},
);
}
final sn = context.read<SnNetworkProvider>();
return Container(
constraints: BoxConstraints(maxWidth: 640),
child: Card(
margin: const EdgeInsets.all(12),
child: InkWell(
borderRadius: const BorderRadius.all(Radius.circular(8)),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
AspectRatio(
aspectRatio: 16 / 7,
child: Stack(
clipBehavior: Clip.none,
fit: StackFit.expand,
children: [
ClipRRect(
borderRadius: const BorderRadius.all(Radius.circular(8)),
child: Container(
color: Theme.of(context).colorScheme.surfaceContainer,
child: (item.banner?.isEmpty ?? true)
? const SizedBox.shrink()
: AutoResizeUniversalImage(
sn.getAttachmentUrl(item.banner!),
fit: BoxFit.cover,
),
),
),
Positioned(
bottom: -30,
left: 18,
child: AccountImage(
content: item.avatar,
radius: 24,
fallbackWidget: const Icon(Symbols.group, size: 24),
),
),
],
),
),
const Gap(20 + 12),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(item.name).textStyle(Theme.of(context).textTheme.titleMedium!),
if (showPopularity)
Row(
children: [
Text(item.popularity.toString()),
const Icon(Symbols.local_fire_department, size: 16).padding(bottom: 2),
],
).padding(top: 6),
Text(item.description).textStyle(Theme.of(context).textTheme.bodySmall!),
],
).padding(horizontal: 24, bottom: 14),
],
),
onTap: () {
if (onTap != null) {
onTap!();
return;
}
GoRouter.of(context).pushNamed(
'realmDetail',
pathParameters: {'alias': item.alias},
).then((value) {
if (value == true) {
onUpdate?.call();
}
});
},
),
),
).center();
}
}