import 'package:flutter/material.dart'; import 'package:gap/gap.dart'; import 'package:hiddify/core/core_providers.dart'; import 'package:hiddify/domain/constants.dart'; import 'package:hiddify/domain/failures.dart'; import 'package:hiddify/features/common/common.dart'; import 'package:hiddify/features/common/new_version_dialog.dart'; import 'package:hiddify/gen/assets.gen.dart'; import 'package:hiddify/services/service_providers.dart'; import 'package:hiddify/utils/utils.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; class AboutPage extends HookConsumerWidget { const AboutPage({super.key}); @override Widget build(BuildContext context, WidgetRef ref) { final t = ref.watch(translationsProvider); final appInfo = ref.watch(appInfoProvider); final appUpdate = ref.watch(appUpdateNotifierProvider); ref.listen( appUpdateNotifierProvider, (_, next) async { if (!context.mounted) return; switch (next) { case AppUpdateStateAvailable(:final versionInfo) || AppUpdateStateIgnored(:final versionInfo): return NewVersionDialog( appInfo.presentVersion, versionInfo, canIgnore: false, ).show(context); case AppUpdateStateError(:final error): return CustomToast.error(t.presentShortError(error)).show(context); case AppUpdateStateNotAvailable(): return CustomToast.success(t.appUpdate.notAvailableMsg) .show(context); } }, ); return Scaffold( body: CustomScrollView( slivers: [ SliverAppBar( title: Text(t.about.pageTitle), ), SliverToBoxAdapter( child: Padding( padding: const EdgeInsets.all(16), child: Row( mainAxisAlignment: MainAxisAlignment.center, children: [ Assets.images.logo.svg(width: 64, height: 64), const Gap(16), Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( t.general.appTitle, style: Theme.of(context).textTheme.titleLarge, ), const Gap(4), Text( "${t.about.version} ${appInfo.presentVersion}", ), ], ), ], ), ), ), SliverList( delegate: SliverChildListDelegate( [ ListTile( title: Text(t.about.sourceCode), trailing: const Icon(Icons.open_in_new), onTap: () async { await UriUtils.tryLaunch( Uri.parse(Constants.githubUrl), ); }, ), ListTile( title: Text(t.about.telegramChannel), trailing: const Icon(Icons.open_in_new), onTap: () async { await UriUtils.tryLaunch( Uri.parse(Constants.telegramChannelUrl), ); }, ), if (appInfo.release.allowCustomUpdateChecker) ListTile( title: Text(t.about.checkForUpdate), trailing: switch (appUpdate) { AppUpdateStateChecking() => const SizedBox( width: 24, height: 24, child: CircularProgressIndicator(), ), _ => const Icon(Icons.update), }, onTap: () async { await ref .read(appUpdateNotifierProvider.notifier) .check(); }, ), if (PlatformUtils.isDesktop) ListTile( title: Text(t.settings.general.openWorkingDir), trailing: const Icon(Icons.arrow_outward_outlined), onTap: () async { final path = ref.read(filesEditorServiceProvider).workingDir.uri; await UriUtils.tryLaunch(path); }, ), ], ), ), ], ), ); } }