forked from Cutlery/immich
		
	* add shared links page * feat(mobile): shared link items * feat(mobile): create / edit shared links page * server: add changeExpiryTime to SharedLinkEditDto * fix(mobile): edit expiry to never * mobile: add icon when shares list is empty * mobile: create new share from album / timeline * mobile: add translation texts * mobile: minor ui fixes * fix: handle serverURL with /api path * mobile: show share link on successful creation * mobile: shared links list - 2 column layout * mobile: use sharedlink pod class instead of dto * mobile: show error on link creation * mobile: show share icon only when remote assets are in selection * mobile: use server endpoint instead of server url * styling * styling --------- Co-authored-by: shalong-tanwen <139912620+shalong-tanwen@users.noreply.github.com> Co-authored-by: Alex Tran <alex.tran1502@gmail.com>
		
			
				
	
	
		
			127 lines
		
	
	
		
			4.0 KiB
		
	
	
	
		
			Dart
		
	
	
	
	
	
			
		
		
	
	
			127 lines
		
	
	
		
			4.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:immich_mobile/modules/shared_link/models/shared_link.dart';
 | 
						|
import 'package:immich_mobile/modules/shared_link/providers/shared_link.provider.dart';
 | 
						|
import 'package:immich_mobile/modules/shared_link/ui/shared_link_item.dart';
 | 
						|
import 'package:immich_mobile/shared/ui/immich_loading_indicator.dart';
 | 
						|
 | 
						|
class SharedLinkPage extends HookConsumerWidget {
 | 
						|
  const SharedLinkPage({Key? key}) : super(key: key);
 | 
						|
 | 
						|
  @override
 | 
						|
  Widget build(BuildContext context, WidgetRef ref) {
 | 
						|
    final sharedLinks = ref.watch(sharedLinksStateProvider);
 | 
						|
 | 
						|
    useEffect(
 | 
						|
      () {
 | 
						|
        ref.read(sharedLinksStateProvider.notifier).fetchLinks();
 | 
						|
        return () => ref.invalidate(sharedLinksStateProvider);
 | 
						|
      },
 | 
						|
      [],
 | 
						|
    );
 | 
						|
 | 
						|
    Widget buildNoShares() {
 | 
						|
      return Column(
 | 
						|
        crossAxisAlignment: CrossAxisAlignment.start,
 | 
						|
        children: [
 | 
						|
          Padding(
 | 
						|
            padding: const EdgeInsets.only(left: 16.0, top: 16.0),
 | 
						|
            child: const Text(
 | 
						|
              "shared_link_manage_links",
 | 
						|
              style: TextStyle(
 | 
						|
                fontSize: 14,
 | 
						|
                color: Colors.grey,
 | 
						|
                fontWeight: FontWeight.bold,
 | 
						|
              ),
 | 
						|
            ).tr(),
 | 
						|
          ),
 | 
						|
          Padding(
 | 
						|
            padding: const EdgeInsets.symmetric(horizontal: 16.0),
 | 
						|
            child: Padding(
 | 
						|
              padding: const EdgeInsets.symmetric(vertical: 10),
 | 
						|
              child: const Text(
 | 
						|
                "shared_link_empty",
 | 
						|
                style: TextStyle(fontSize: 14),
 | 
						|
              ).tr(),
 | 
						|
            ),
 | 
						|
          ),
 | 
						|
          Expanded(
 | 
						|
            child: Center(
 | 
						|
              child: Icon(
 | 
						|
                Icons.link_off,
 | 
						|
                size: 100,
 | 
						|
                color: Theme.of(context).iconTheme.color?.withOpacity(0.5),
 | 
						|
              ),
 | 
						|
            ),
 | 
						|
          ),
 | 
						|
        ],
 | 
						|
      );
 | 
						|
    }
 | 
						|
 | 
						|
    Widget buildSharesList(List<SharedLink> links) {
 | 
						|
      return Column(
 | 
						|
        crossAxisAlignment: CrossAxisAlignment.start,
 | 
						|
        children: [
 | 
						|
          Padding(
 | 
						|
            padding: const EdgeInsets.only(left: 16.0, top: 16.0, bottom: 30.0),
 | 
						|
            child: const Text(
 | 
						|
              "shared_link_manage_links",
 | 
						|
              style: TextStyle(
 | 
						|
                fontSize: 14,
 | 
						|
                color: Colors.grey,
 | 
						|
                fontWeight: FontWeight.bold,
 | 
						|
              ),
 | 
						|
            ).tr(),
 | 
						|
          ),
 | 
						|
          Expanded(
 | 
						|
            child: LayoutBuilder(
 | 
						|
              builder: (context, constraints) {
 | 
						|
                if (constraints.maxWidth > 600) {
 | 
						|
                  // Two column
 | 
						|
                  return GridView.builder(
 | 
						|
                    gridDelegate:
 | 
						|
                        const SliverGridDelegateWithFixedCrossAxisCount(
 | 
						|
                      crossAxisCount: 2,
 | 
						|
                      mainAxisExtent: 180,
 | 
						|
                    ),
 | 
						|
                    itemCount: links.length,
 | 
						|
                    itemBuilder: (context, index) {
 | 
						|
                      return SharedLinkItem(links.elementAt(index));
 | 
						|
                    },
 | 
						|
                  );
 | 
						|
                }
 | 
						|
 | 
						|
                // Single column
 | 
						|
                return ListView.builder(
 | 
						|
                  itemCount: links.length,
 | 
						|
                  itemBuilder: (context, index) {
 | 
						|
                    return SharedLinkItem(links.elementAt(index));
 | 
						|
                  },
 | 
						|
                );
 | 
						|
              },
 | 
						|
            ),
 | 
						|
          ),
 | 
						|
        ],
 | 
						|
      );
 | 
						|
    }
 | 
						|
 | 
						|
    return Scaffold(
 | 
						|
      appBar: AppBar(
 | 
						|
        title: const Text("shared_link_app_bar_title").tr(),
 | 
						|
        elevation: 0,
 | 
						|
        centerTitle: false,
 | 
						|
      ),
 | 
						|
      body: SafeArea(
 | 
						|
        child: sharedLinks.when(
 | 
						|
          data: (links) =>
 | 
						|
              links.isNotEmpty ? buildSharesList(links) : buildNoShares(),
 | 
						|
          error: (error, stackTrace) => buildNoShares(),
 | 
						|
          loading: () => const Center(child: ImmichLoadingIndicator()),
 | 
						|
        ),
 | 
						|
      ),
 | 
						|
    );
 | 
						|
  }
 | 
						|
}
 |