⏪ Use old discovery card for the realm explore
This commit is contained in:
@@ -628,15 +628,15 @@ class _DiscoveryActivityItem extends StatelessWidget {
|
|||||||
children: [
|
children: [
|
||||||
for (final item in items)
|
for (final item in items)
|
||||||
switch (type) {
|
switch (type) {
|
||||||
'realm' => RealmCard(
|
'realm' => RealmDiscoveryCard(
|
||||||
realm: SnRealm.fromJson(item['data']),
|
realm: SnRealm.fromJson(item['data']),
|
||||||
maxWidth: 280,
|
maxWidth: 280,
|
||||||
),
|
),
|
||||||
'publisher' => PublisherCard(
|
'publisher' => PublisherDiscoveryCard(
|
||||||
publisher: SnPublisher.fromJson(item['data']),
|
publisher: SnPublisher.fromJson(item['data']),
|
||||||
maxWidth: 280,
|
maxWidth: 280,
|
||||||
),
|
),
|
||||||
'article' => WebArticleCard(
|
'article' => WebArticleDiscoveryCard(
|
||||||
article: SnWebArticle.fromJson(item['data']),
|
article: SnWebArticle.fromJson(item['data']),
|
||||||
maxWidth: 280,
|
maxWidth: 280,
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -5,11 +5,15 @@ import 'package:hooks_riverpod/hooks_riverpod.dart';
|
|||||||
import 'package:island/models/publisher.dart';
|
import 'package:island/models/publisher.dart';
|
||||||
import 'package:island/widgets/content/cloud_files.dart';
|
import 'package:island/widgets/content/cloud_files.dart';
|
||||||
|
|
||||||
class PublisherCard extends ConsumerWidget {
|
class PublisherDiscoveryCard extends ConsumerWidget {
|
||||||
final SnPublisher publisher;
|
final SnPublisher publisher;
|
||||||
final double? maxWidth;
|
final double? maxWidth;
|
||||||
|
|
||||||
const PublisherCard({super.key, required this.publisher, this.maxWidth});
|
const PublisherDiscoveryCard({
|
||||||
|
super.key,
|
||||||
|
required this.publisher,
|
||||||
|
this.maxWidth,
|
||||||
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context, WidgetRef ref) {
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
|
|||||||
@@ -6,21 +6,20 @@ import 'package:island/models/realm.dart';
|
|||||||
import 'package:island/widgets/content/cloud_files.dart';
|
import 'package:island/widgets/content/cloud_files.dart';
|
||||||
import 'package:material_symbols_icons/symbols.dart';
|
import 'package:material_symbols_icons/symbols.dart';
|
||||||
|
|
||||||
class RealmCard extends ConsumerWidget {
|
class RealmDiscoveryCard extends ConsumerWidget {
|
||||||
final SnRealm realm;
|
final SnRealm realm;
|
||||||
final double? maxWidth;
|
final double? maxWidth;
|
||||||
|
|
||||||
const RealmCard({super.key, required this.realm, this.maxWidth});
|
const RealmDiscoveryCard({super.key, required this.realm, this.maxWidth});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context, WidgetRef ref) {
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
Widget imageWidget;
|
Widget imageWidget;
|
||||||
if (realm.picture != null) {
|
if (realm.picture != null) {
|
||||||
imageWidget =
|
imageWidget = imageWidget = CloudImageWidget(
|
||||||
imageWidget = CloudImageWidget(
|
file: realm.background,
|
||||||
file: realm.background,
|
fit: BoxFit.cover,
|
||||||
fit: BoxFit.cover,
|
);
|
||||||
);
|
|
||||||
} else {
|
} else {
|
||||||
imageWidget = ColoredBox(
|
imageWidget = ColoredBox(
|
||||||
color: Theme.of(context).colorScheme.secondaryContainer,
|
color: Theme.of(context).colorScheme.secondaryContainer,
|
||||||
|
|||||||
@@ -71,3 +71,140 @@ class WebArticleCard extends StatelessWidget {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class WebArticleDiscoveryCard extends StatelessWidget {
|
||||||
|
final SnWebArticle article;
|
||||||
|
final double? maxWidth;
|
||||||
|
final bool showDetails;
|
||||||
|
|
||||||
|
const WebArticleDiscoveryCard({
|
||||||
|
super.key,
|
||||||
|
required this.article,
|
||||||
|
this.maxWidth,
|
||||||
|
this.showDetails = false,
|
||||||
|
});
|
||||||
|
|
||||||
|
void _onTap(BuildContext context) {
|
||||||
|
context.pushNamed('articleDetail', pathParameters: {'id': article.id});
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final theme = Theme.of(context);
|
||||||
|
final colorScheme = theme.colorScheme;
|
||||||
|
|
||||||
|
return ConstrainedBox(
|
||||||
|
constraints: BoxConstraints(maxWidth: maxWidth ?? double.infinity),
|
||||||
|
child: Card(
|
||||||
|
margin: EdgeInsets.zero,
|
||||||
|
clipBehavior: Clip.antiAlias,
|
||||||
|
child: InkWell(
|
||||||
|
onTap: () => _onTap(context),
|
||||||
|
child: AspectRatio(
|
||||||
|
aspectRatio: 16 / 9,
|
||||||
|
child: Stack(
|
||||||
|
fit: StackFit.expand,
|
||||||
|
children: [
|
||||||
|
// Image or fallback
|
||||||
|
article.preview?.imageUrl != null
|
||||||
|
? CachedNetworkImage(
|
||||||
|
imageUrl: article.preview!.imageUrl!,
|
||||||
|
fit: BoxFit.cover,
|
||||||
|
width: double.infinity,
|
||||||
|
height: double.infinity,
|
||||||
|
)
|
||||||
|
: ColoredBox(
|
||||||
|
color: colorScheme.secondaryContainer,
|
||||||
|
child: const Center(
|
||||||
|
child: Icon(
|
||||||
|
Icons.article_outlined,
|
||||||
|
size: 48,
|
||||||
|
color: Colors.white,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
// Gradient overlay
|
||||||
|
Container(
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
gradient: LinearGradient(
|
||||||
|
begin: Alignment.topCenter,
|
||||||
|
end: Alignment.bottomCenter,
|
||||||
|
colors: [
|
||||||
|
Colors.transparent,
|
||||||
|
Colors.black.withOpacity(0.7),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
// Title
|
||||||
|
Align(
|
||||||
|
alignment: Alignment.bottomLeft,
|
||||||
|
child: Container(
|
||||||
|
padding: const EdgeInsets.only(
|
||||||
|
left: 12,
|
||||||
|
right: 12,
|
||||||
|
bottom: 8,
|
||||||
|
),
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
mainAxisAlignment: MainAxisAlignment.end,
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
if (showDetails)
|
||||||
|
const SizedBox(height: 8)
|
||||||
|
else
|
||||||
|
Spacer(),
|
||||||
|
Text(
|
||||||
|
article.title,
|
||||||
|
style: theme.textTheme.titleSmall?.copyWith(
|
||||||
|
color: Colors.white,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
height: 1.3,
|
||||||
|
),
|
||||||
|
maxLines: showDetails ? 3 : 1,
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
),
|
||||||
|
if (showDetails &&
|
||||||
|
article.author?.isNotEmpty == true) ...[
|
||||||
|
const SizedBox(height: 4),
|
||||||
|
Text(
|
||||||
|
article.author!,
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 10,
|
||||||
|
color: Colors.white.withOpacity(0.9),
|
||||||
|
fontWeight: FontWeight.w500,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
if (showDetails) const Spacer(),
|
||||||
|
if (showDetails && article.publishedAt != null) ...[
|
||||||
|
Text(
|
||||||
|
'${article.publishedAt!.formatSystem()} · ${article.publishedAt!.formatRelative(context)}',
|
||||||
|
style: const TextStyle(
|
||||||
|
fontSize: 9,
|
||||||
|
color: Colors.white70,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 2),
|
||||||
|
],
|
||||||
|
Text(
|
||||||
|
article.feed?.title ?? 'Unknown Source',
|
||||||
|
style: const TextStyle(
|
||||||
|
fontSize: 9,
|
||||||
|
color: Colors.white70,
|
||||||
|
),
|
||||||
|
maxLines: 1,
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user