update onboarding, perimissions, layout

This commit is contained in:
Fabian Freund
2025-06-26 00:13:58 +02:00
parent 5889c1272a
commit 4f2b76c09d
5 changed files with 137 additions and 58 deletions
@@ -7,6 +7,7 @@ import 'package:weblibre/core/providers/router.dart';
import 'package:weblibre/features/geckoview/domain/repositories/tab.dart';
import 'package:weblibre/features/onboarding/presentation/pages/abstract/i_form_page.dart';
import 'package:weblibre/features/onboarding/presentation/pages/default_search.dart';
import 'package:weblibre/features/onboarding/presentation/pages/permissions.dart';
import 'package:weblibre/features/onboarding/presentation/pages/ublock_opt_in.dart';
import 'package:weblibre/features/onboarding/presentation/pages/welcome.dart';
import 'package:weblibre/features/user/domain/repositories/onboarding.dart';
@@ -32,6 +33,7 @@ class OnboardingScreen extends HookConsumerWidget {
const WelcomePage(),
const DefaultSearchPage(),
UBlockOptInPage(formKey: GlobalKey<FormState>()),
PermissionsPage(formKey: GlobalKey<FormState>()),
];
}, [currentRevision, targetRevision]);
@@ -13,6 +13,8 @@ class DefaultSearchPage extends HookConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
final theme = Theme.of(context);
final bangs = ref.watch(bangListProvider(triggers: defaultBangs));
final activeBang = ref.watch(defaultSearchBangDataProvider).valueOrNull;
@@ -26,67 +28,77 @@ class DefaultSearchPage extends HookConsumerWidget {
);
}
return bangs.when(
skipLoadingOnReload: true,
data: (availableBangs) {
return ListView(
children: [
SizedBox(
height: 48,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
const Text('Default Search:'),
if (activeBang != null)
FilterChip(
showCheckmark: false,
label: Text(activeBang.websiteName),
avatar: UrlIcon([
activeBang.getTemplateUrl(''),
], iconSize: 20),
selected: true,
onSelected: (value) {},
),
],
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 16.0),
child: bangs.when(
skipLoadingOnReload: true,
data: (availableBangs) {
return ListView(
children: [
const SizedBox(height: 24),
Center(
child: Text(
'Default Search Provider',
style: theme.textTheme.headlineMedium,
),
),
),
const Divider(),
Wrap(
spacing: 8.0,
children: [
...availableBangs.map(
(bang) => FilterChip(
showCheckmark: false,
label: Text(bang.websiteName),
avatar: UrlIcon([bang.getTemplateUrl('')], iconSize: 20),
selected: activeBang?.trigger == bang.trigger,
onSelected: (selected) async {
if (selected) {
await updateSearchProvider(bang.trigger);
const SizedBox(height: 24),
SizedBox(
height: 48,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
const Text('Selected Provider'),
if (activeBang != null)
FilterChip(
showCheckmark: false,
label: Text(activeBang.websiteName),
avatar: UrlIcon([
activeBang.getTemplateUrl(''),
], iconSize: 20),
selected: true,
onSelected: (value) {},
),
],
),
),
const Divider(),
Wrap(
spacing: 8.0,
children: [
...availableBangs.map(
(bang) => FilterChip(
showCheckmark: false,
label: Text(bang.websiteName),
avatar: UrlIcon([bang.getTemplateUrl('')], iconSize: 20),
selected: activeBang?.trigger == bang.trigger,
onSelected: (selected) async {
if (selected) {
await updateSearchProvider(bang.trigger);
}
},
),
),
ActionChip(
label: const Text('Search more'),
avatar: const Icon(Icons.search),
onPressed: () async {
final trigger = await const BangSearchRoute()
.push<String?>(context);
if (trigger != null) {
await updateSearchProvider(trigger);
}
},
),
),
ActionChip(
label: const Text('Search more'),
avatar: const Icon(Icons.search),
onPressed: () async {
final trigger = await const BangSearchRoute().push<String?>(
context,
);
if (trigger != null) {
await updateSearchProvider(trigger);
}
},
),
],
),
],
);
},
error: (error, stackTrace) => const SizedBox.shrink(),
loading: () => const SizedBox(height: 48, width: double.infinity),
],
),
],
);
},
error: (error, stackTrace) => const SizedBox.shrink(),
loading: () => const SizedBox(height: 48, width: double.infinity),
),
);
}
}
@@ -0,0 +1,63 @@
import 'package:flutter/material.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:skeletonizer/skeletonizer.dart';
import 'package:weblibre/features/onboarding/presentation/pages/abstract/i_form_page.dart';
import 'package:weblibre/presentation/hooks/cached_future.dart';
class PermissionsPage extends HookConsumerWidget implements IFormPage {
@override
final GlobalKey<FormState> formKey;
const PermissionsPage({super.key, required this.formKey});
@override
Widget build(BuildContext context, WidgetRef ref) {
final theme = Theme.of(context);
final notificationPermissionEnabled = useCachedFuture(
() => Permission.notification.isGranted,
);
return Form(
key: formKey,
child: ListView(
children: [
const SizedBox(height: 24),
Center(
child: Text('Permissions', style: theme.textTheme.headlineMedium),
),
const SizedBox(height: 24),
// Padding(
// padding: const EdgeInsets.symmetric(horizontal: 16.0),
// child: const Text('WebLibre requires following permissions'),
// ),
// const SizedBox(height: 24),
Skeletonizer(
enabled: !notificationPermissionEnabled.hasData,
child: FormField(
initialValue: true,
onSaved: (newValue) async {
if (newValue == true) {
await Permission.notification.request();
}
},
builder: (field) => SwitchListTile(
value: field.value ?? true,
title: const Text('Notifications'),
subtitle: const Text(
'Required to inform about download status',
),
onChanged: (notificationPermissionEnabled.data == true)
? null
: (value) {
field.didChange(value);
},
),
),
),
],
),
);
}
}
@@ -21,10 +21,11 @@ class UBlockOptInPage extends HookConsumerWidget implements IFormPage {
key: formKey,
child: ListView(
children: [
const SizedBox(height: 24),
SvgPicture.asset('assets/images/ublock.svg'),
const SizedBox(height: 8),
Center(
child: Text('uBlock Origin', style: theme.textTheme.headlineLarge),
child: Text('uBlock Origin', style: theme.textTheme.headlineMedium),
),
const SizedBox(height: 24),
const Padding(
+1
View File
@@ -48,6 +48,7 @@ dependencies:
package_info_plus: ^8.3.0
path: ^1.9.1
path_provider: ^2.1.5
permission_handler: ^12.0.0+1
pretty_qr_code: ^3.4.0
riverpod: ^2.6.1
riverpod_annotation: ^2.6.1