update onboarding, perimissions, layout
This commit is contained in:
@@ -7,6 +7,7 @@ import 'package:weblibre/core/providers/router.dart';
|
|||||||
import 'package:weblibre/features/geckoview/domain/repositories/tab.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/abstract/i_form_page.dart';
|
||||||
import 'package:weblibre/features/onboarding/presentation/pages/default_search.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/ublock_opt_in.dart';
|
||||||
import 'package:weblibre/features/onboarding/presentation/pages/welcome.dart';
|
import 'package:weblibre/features/onboarding/presentation/pages/welcome.dart';
|
||||||
import 'package:weblibre/features/user/domain/repositories/onboarding.dart';
|
import 'package:weblibre/features/user/domain/repositories/onboarding.dart';
|
||||||
@@ -32,6 +33,7 @@ class OnboardingScreen extends HookConsumerWidget {
|
|||||||
const WelcomePage(),
|
const WelcomePage(),
|
||||||
const DefaultSearchPage(),
|
const DefaultSearchPage(),
|
||||||
UBlockOptInPage(formKey: GlobalKey<FormState>()),
|
UBlockOptInPage(formKey: GlobalKey<FormState>()),
|
||||||
|
PermissionsPage(formKey: GlobalKey<FormState>()),
|
||||||
];
|
];
|
||||||
}, [currentRevision, targetRevision]);
|
}, [currentRevision, targetRevision]);
|
||||||
|
|
||||||
|
|||||||
@@ -13,6 +13,8 @@ class DefaultSearchPage extends HookConsumerWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context, WidgetRef ref) {
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
|
final theme = Theme.of(context);
|
||||||
|
|
||||||
final bangs = ref.watch(bangListProvider(triggers: defaultBangs));
|
final bangs = ref.watch(bangListProvider(triggers: defaultBangs));
|
||||||
|
|
||||||
final activeBang = ref.watch(defaultSearchBangDataProvider).valueOrNull;
|
final activeBang = ref.watch(defaultSearchBangDataProvider).valueOrNull;
|
||||||
@@ -26,67 +28,77 @@ class DefaultSearchPage extends HookConsumerWidget {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return bangs.when(
|
return Padding(
|
||||||
skipLoadingOnReload: true,
|
padding: const EdgeInsets.symmetric(horizontal: 16.0),
|
||||||
data: (availableBangs) {
|
child: bangs.when(
|
||||||
return ListView(
|
skipLoadingOnReload: true,
|
||||||
children: [
|
data: (availableBangs) {
|
||||||
SizedBox(
|
return ListView(
|
||||||
height: 48,
|
children: [
|
||||||
child: Row(
|
const SizedBox(height: 24),
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
Center(
|
||||||
children: [
|
child: Text(
|
||||||
const Text('Default Search:'),
|
'Default Search Provider',
|
||||||
if (activeBang != null)
|
style: theme.textTheme.headlineMedium,
|
||||||
FilterChip(
|
),
|
||||||
showCheckmark: false,
|
|
||||||
label: Text(activeBang.websiteName),
|
|
||||||
avatar: UrlIcon([
|
|
||||||
activeBang.getTemplateUrl(''),
|
|
||||||
], iconSize: 20),
|
|
||||||
selected: true,
|
|
||||||
onSelected: (value) {},
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
),
|
const SizedBox(height: 24),
|
||||||
const Divider(),
|
SizedBox(
|
||||||
Wrap(
|
height: 48,
|
||||||
spacing: 8.0,
|
child: Row(
|
||||||
children: [
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
...availableBangs.map(
|
children: [
|
||||||
(bang) => FilterChip(
|
const Text('Selected Provider'),
|
||||||
showCheckmark: false,
|
if (activeBang != null)
|
||||||
label: Text(bang.websiteName),
|
FilterChip(
|
||||||
avatar: UrlIcon([bang.getTemplateUrl('')], iconSize: 20),
|
showCheckmark: false,
|
||||||
selected: activeBang?.trigger == bang.trigger,
|
label: Text(activeBang.websiteName),
|
||||||
onSelected: (selected) async {
|
avatar: UrlIcon([
|
||||||
if (selected) {
|
activeBang.getTemplateUrl(''),
|
||||||
await updateSearchProvider(bang.trigger);
|
], 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?>(
|
error: (error, stackTrace) => const SizedBox.shrink(),
|
||||||
context,
|
loading: () => const SizedBox(height: 48, width: double.infinity),
|
||||||
);
|
),
|
||||||
|
|
||||||
if (trigger != null) {
|
|
||||||
await updateSearchProvider(trigger);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
},
|
|
||||||
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,
|
key: formKey,
|
||||||
child: ListView(
|
child: ListView(
|
||||||
children: [
|
children: [
|
||||||
|
const SizedBox(height: 24),
|
||||||
SvgPicture.asset('assets/images/ublock.svg'),
|
SvgPicture.asset('assets/images/ublock.svg'),
|
||||||
const SizedBox(height: 8),
|
const SizedBox(height: 8),
|
||||||
Center(
|
Center(
|
||||||
child: Text('uBlock Origin', style: theme.textTheme.headlineLarge),
|
child: Text('uBlock Origin', style: theme.textTheme.headlineMedium),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 24),
|
const SizedBox(height: 24),
|
||||||
const Padding(
|
const Padding(
|
||||||
|
|||||||
@@ -48,6 +48,7 @@ dependencies:
|
|||||||
package_info_plus: ^8.3.0
|
package_info_plus: ^8.3.0
|
||||||
path: ^1.9.1
|
path: ^1.9.1
|
||||||
path_provider: ^2.1.5
|
path_provider: ^2.1.5
|
||||||
|
permission_handler: ^12.0.0+1
|
||||||
pretty_qr_code: ^3.4.0
|
pretty_qr_code: ^3.4.0
|
||||||
riverpod: ^2.6.1
|
riverpod: ^2.6.1
|
||||||
riverpod_annotation: ^2.6.1
|
riverpod_annotation: ^2.6.1
|
||||||
|
|||||||
Reference in New Issue
Block a user