2026-07-30 12:39:24 -07:00
|
|
|
import 'dart:async';
|
|
|
|
|
|
2024-01-15 16:50:33 +00:00
|
|
|
import 'package:auto_route/auto_route.dart';
|
2023-10-22 15:05:10 +00:00
|
|
|
import 'package:flutter/material.dart';
|
|
|
|
|
import 'package:flutter_hooks/flutter_hooks.dart';
|
|
|
|
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
2023-11-29 04:17:29 +00:00
|
|
|
import 'package:immich_mobile/extensions/asyncvalue_extensions.dart';
|
2026-08-11 14:41:13 +05:30
|
|
|
import 'package:immich_mobile/generated/translations.g.dart';
|
2024-04-30 21:36:40 -05:00
|
|
|
import 'package:immich_mobile/models/shared_link/shared_link.model.dart';
|
2024-05-02 15:59:14 -05:00
|
|
|
import 'package:immich_mobile/providers/shared_link.provider.dart';
|
2024-05-06 23:04:21 -05:00
|
|
|
import 'package:immich_mobile/widgets/shared_link/shared_link_item.dart';
|
2023-10-22 15:05:10 +00:00
|
|
|
|
2024-01-15 16:50:33 +00:00
|
|
|
@RoutePage()
|
2023-10-22 15:05:10 +00:00
|
|
|
class SharedLinkPage extends HookConsumerWidget {
|
2024-01-27 16:14:32 +00:00
|
|
|
const SharedLinkPage({super.key});
|
2023-10-22 15:05:10 +00:00
|
|
|
|
|
|
|
|
@override
|
|
|
|
|
Widget build(BuildContext context, WidgetRef ref) {
|
|
|
|
|
final sharedLinks = ref.watch(sharedLinksStateProvider);
|
|
|
|
|
|
2025-07-29 00:34:03 +05:30
|
|
|
useEffect(() {
|
2026-07-30 12:39:24 -07:00
|
|
|
unawaited(ref.read(sharedLinksStateProvider.notifier).fetchLinks());
|
2025-07-29 00:34:03 +05:30
|
|
|
return () {
|
2026-05-12 00:47:24 +07:00
|
|
|
if (!context.mounted) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
2025-07-29 00:34:03 +05:30
|
|
|
ref.invalidate(sharedLinksStateProvider);
|
|
|
|
|
};
|
|
|
|
|
}, []);
|
2023-10-22 15:05:10 +00:00
|
|
|
|
|
|
|
|
Widget buildNoShares() {
|
2026-05-18 16:59:56 +02:00
|
|
|
return Center(
|
|
|
|
|
child: Column(
|
|
|
|
|
crossAxisAlignment: CrossAxisAlignment.center,
|
|
|
|
|
mainAxisAlignment: MainAxisAlignment.center,
|
|
|
|
|
children: [
|
|
|
|
|
Icon(Icons.link_off, size: 100, color: Theme.of(context).colorScheme.onSurface.withAlpha(128)),
|
|
|
|
|
const SizedBox(height: 20),
|
2026-08-11 14:41:13 +05:30
|
|
|
Text(context.t.you_dont_have_any_shared_links, style: const TextStyle(fontSize: 14)),
|
2026-05-18 16:59:56 +02:00
|
|
|
],
|
|
|
|
|
),
|
2023-10-22 15:05:10 +00:00
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Widget buildSharesList(List<SharedLink> links) {
|
2026-05-18 16:59:56 +02:00
|
|
|
return LayoutBuilder(
|
|
|
|
|
builder: (context, constraints) => constraints.maxWidth > 600
|
|
|
|
|
? GridView.builder(
|
|
|
|
|
key: const PageStorageKey('shared-links-grid'),
|
|
|
|
|
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
|
|
|
|
|
crossAxisCount: 2,
|
|
|
|
|
mainAxisExtent: 180,
|
|
|
|
|
crossAxisSpacing: 12,
|
|
|
|
|
mainAxisSpacing: 12,
|
|
|
|
|
),
|
|
|
|
|
padding: const EdgeInsets.all(12),
|
|
|
|
|
itemCount: links.length,
|
|
|
|
|
itemBuilder: (context, index) => SharedLinkItem(links[index]),
|
|
|
|
|
)
|
|
|
|
|
: ListView.separated(
|
|
|
|
|
key: const PageStorageKey('shared-links-list'),
|
|
|
|
|
padding: const EdgeInsets.symmetric(vertical: 8),
|
|
|
|
|
itemCount: links.length,
|
|
|
|
|
itemBuilder: (context, index) => SharedLinkItem(links[index]),
|
|
|
|
|
separatorBuilder: (context, index) => const Divider(height: 1),
|
|
|
|
|
),
|
2023-10-22 15:05:10 +00:00
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return Scaffold(
|
2026-08-11 14:41:13 +05:30
|
|
|
appBar: AppBar(title: Text(context.t.shared_link_app_bar_title), elevation: 0, centerTitle: false),
|
2023-10-22 15:05:10 +00:00
|
|
|
body: SafeArea(
|
2023-11-29 04:17:29 +00:00
|
|
|
child: sharedLinks.widgetWhen(
|
|
|
|
|
onError: (error, stackTrace) => buildNoShares(),
|
2025-07-25 08:07:22 +05:30
|
|
|
onData: (links) => links.isNotEmpty ? buildSharesList(links) : buildNoShares(),
|
2023-10-22 15:05:10 +00:00
|
|
|
),
|
|
|
|
|
),
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
}
|