optimize permission section
This commit is contained in:
@@ -0,0 +1,47 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_mozilla_components/flutter_mozilla_components.dart';
|
||||||
|
import 'package:weblibre/features/geckoview/features/browser/domain/entities/site_permissions.dart';
|
||||||
|
|
||||||
|
/// Permission types with their display configuration
|
||||||
|
enum PermissionType {
|
||||||
|
camera(Icons.videocam, 'Camera'),
|
||||||
|
microphone(Icons.mic, 'Microphone'),
|
||||||
|
location(Icons.location_on, 'Location'),
|
||||||
|
notification(Icons.notifications, 'Notifications'),
|
||||||
|
persistentStorage(Icons.storage, 'Persistent Storage'),
|
||||||
|
crossOriginStorage(Icons.cookie, 'Cross-Origin Storage'),
|
||||||
|
mediaKeySystem(Icons.key, 'Media Key System (DRM)');
|
||||||
|
|
||||||
|
const PermissionType(this.icon, this.label);
|
||||||
|
final IconData icon;
|
||||||
|
final String label;
|
||||||
|
}
|
||||||
|
|
||||||
|
extension SitePermissionsGetter on SitePermissions? {
|
||||||
|
SitePermissionStatus? getStatus(PermissionType type) => switch (type) {
|
||||||
|
PermissionType.camera => this?.camera,
|
||||||
|
PermissionType.microphone => this?.microphone,
|
||||||
|
PermissionType.location => this?.location,
|
||||||
|
PermissionType.notification => this?.notification,
|
||||||
|
PermissionType.persistentStorage => this?.persistentStorage,
|
||||||
|
PermissionType.crossOriginStorage => this?.crossOriginStorageAccess,
|
||||||
|
PermissionType.mediaKeySystem => this?.mediaKeySystemAccess,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
extension SitePermissionsUpdater on SitePermissionsWrapper {
|
||||||
|
SitePermissions withStatus(
|
||||||
|
PermissionType type,
|
||||||
|
SitePermissionStatus status,
|
||||||
|
) => switch (type) {
|
||||||
|
PermissionType.camera => copyWith.camera(status),
|
||||||
|
PermissionType.microphone => copyWith.microphone(status),
|
||||||
|
PermissionType.location => copyWith.location(status),
|
||||||
|
PermissionType.notification => copyWith.notification(status),
|
||||||
|
PermissionType.persistentStorage => copyWith.persistentStorage(status),
|
||||||
|
PermissionType.crossOriginStorage => copyWith.crossOriginStorageAccess(
|
||||||
|
status,
|
||||||
|
),
|
||||||
|
PermissionType.mediaKeySystem => copyWith.mediaKeySystemAccess(status),
|
||||||
|
};
|
||||||
|
}
|
||||||
+43
-93
@@ -22,6 +22,7 @@ import 'package:flutter_hooks/flutter_hooks.dart';
|
|||||||
import 'package:flutter_mozilla_components/flutter_mozilla_components.dart';
|
import 'package:flutter_mozilla_components/flutter_mozilla_components.dart';
|
||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
import 'package:weblibre/features/geckoview/domain/providers/tab_session.dart';
|
import 'package:weblibre/features/geckoview/domain/providers/tab_session.dart';
|
||||||
|
import 'package:weblibre/features/geckoview/features/browser/domain/entities/permission_type.dart';
|
||||||
import 'package:weblibre/features/geckoview/features/browser/domain/entities/site_permissions.dart';
|
import 'package:weblibre/features/geckoview/features/browser/domain/entities/site_permissions.dart';
|
||||||
import 'package:weblibre/features/geckoview/features/browser/domain/repositories/site_permissions.dart';
|
import 'package:weblibre/features/geckoview/features/browser/domain/repositories/site_permissions.dart';
|
||||||
|
|
||||||
@@ -75,81 +76,48 @@ class _PermissionsList extends HookConsumerWidget {
|
|||||||
Widget build(BuildContext context, WidgetRef ref) {
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
final showAll = useState(false);
|
final showAll = useState(false);
|
||||||
|
|
||||||
// Build list of permission entries with their current status
|
// Memoize the update callback to avoid recreating closures
|
||||||
final allPermissions = [
|
final updatePermission = useCallback((
|
||||||
_PermissionEntry(
|
SitePermissions Function(SitePermissionsWrapper) updater,
|
||||||
icon: Icons.videocam,
|
) async {
|
||||||
label: 'Camera',
|
await ref
|
||||||
status: permissions?.camera,
|
.read(
|
||||||
onChanged: (status) => _updatePermission(
|
sitePermissionsRepositoryProvider(
|
||||||
ref,
|
origin: origin,
|
||||||
(permissions) => permissions.copyWith.camera(status),
|
isPrivate: isPrivate,
|
||||||
),
|
).notifier,
|
||||||
),
|
)
|
||||||
_PermissionEntry(
|
.updatePermission(updater);
|
||||||
icon: Icons.mic,
|
await ref.read(selectedTabSessionProvider).reload();
|
||||||
label: 'Microphone',
|
}, [origin, isPrivate]);
|
||||||
status: permissions?.microphone,
|
|
||||||
onChanged: (status) => _updatePermission(
|
// Build permission entries - only recalculates when permissions change
|
||||||
ref,
|
final allPermissions = useMemoized(
|
||||||
(permissions) => permissions.copyWith.microphone(status),
|
() => PermissionType.values
|
||||||
),
|
.map(
|
||||||
),
|
(type) => _PermissionEntry(
|
||||||
_PermissionEntry(
|
icon: type.icon,
|
||||||
icon: Icons.location_on,
|
label: type.label,
|
||||||
label: 'Location',
|
status: permissions.getStatus(type),
|
||||||
status: permissions?.location,
|
onChanged: (status) =>
|
||||||
onChanged: (status) => _updatePermission(
|
updatePermission((w) => w.withStatus(type, status)),
|
||||||
ref,
|
),
|
||||||
(permissions) => permissions.copyWith.location(status),
|
)
|
||||||
),
|
.toList(),
|
||||||
),
|
[permissions, updatePermission],
|
||||||
_PermissionEntry(
|
);
|
||||||
icon: Icons.notifications,
|
|
||||||
label: 'Notifications',
|
|
||||||
status: permissions?.notification,
|
|
||||||
onChanged: (status) => _updatePermission(
|
|
||||||
ref,
|
|
||||||
(permissions) => permissions.copyWith.notification(status),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
_PermissionEntry(
|
|
||||||
icon: Icons.storage,
|
|
||||||
label: 'Persistent Storage',
|
|
||||||
status: permissions?.persistentStorage,
|
|
||||||
onChanged: (status) => _updatePermission(
|
|
||||||
ref,
|
|
||||||
(permissions) => permissions.copyWith.persistentStorage(status),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
_PermissionEntry(
|
|
||||||
icon: Icons.cookie,
|
|
||||||
label: 'Cross-Origin Storage',
|
|
||||||
status: permissions?.crossOriginStorageAccess,
|
|
||||||
onChanged: (status) => _updatePermission(
|
|
||||||
ref,
|
|
||||||
(permissions) =>
|
|
||||||
permissions.copyWith.crossOriginStorageAccess(status),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
_PermissionEntry(
|
|
||||||
icon: Icons.key,
|
|
||||||
label: 'Media Key System (DRM)',
|
|
||||||
status: permissions?.mediaKeySystemAccess,
|
|
||||||
onChanged: (status) => _updatePermission(
|
|
||||||
ref,
|
|
||||||
(permissions) => permissions.copyWith.mediaKeySystemAccess(status),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
];
|
|
||||||
|
|
||||||
// Filter to only show permissions that have been explicitly set (not noDecision)
|
// Filter to only show permissions that have been explicitly set (not noDecision)
|
||||||
final setPermissions = allPermissions
|
// Only recalculates when allPermissions changes
|
||||||
.where(
|
final setPermissions = useMemoized(
|
||||||
(p) =>
|
() => allPermissions
|
||||||
p.status != null && p.status != SitePermissionStatus.noDecision,
|
.where(
|
||||||
)
|
(p) =>
|
||||||
.toList();
|
p.status != null && p.status != SitePermissionStatus.noDecision,
|
||||||
|
)
|
||||||
|
.toList(),
|
||||||
|
[allPermissions],
|
||||||
|
);
|
||||||
|
|
||||||
final permissionsToShow = showAll.value ? allPermissions : setPermissions;
|
final permissionsToShow = showAll.value ? allPermissions : setPermissions;
|
||||||
final hiddenCount = allPermissions.length - setPermissions.length;
|
final hiddenCount = allPermissions.length - setPermissions.length;
|
||||||
@@ -202,9 +170,8 @@ class _PermissionsList extends HookConsumerWidget {
|
|||||||
_AutoplayTile(
|
_AutoplayTile(
|
||||||
audibleStatus: permissions?.autoplayAudible,
|
audibleStatus: permissions?.autoplayAudible,
|
||||||
inaudibleStatus: permissions?.autoplayInaudible,
|
inaudibleStatus: permissions?.autoplayInaudible,
|
||||||
onChanged: (audible, inaudible) => _updatePermission(
|
onChanged: (audible, inaudible) => updatePermission(
|
||||||
ref,
|
(p) => p.copyWith(
|
||||||
(permissions) => permissions.copyWith(
|
|
||||||
autoplayAudible: audible,
|
autoplayAudible: audible,
|
||||||
autoplayInaudible: inaudible,
|
autoplayInaudible: inaudible,
|
||||||
),
|
),
|
||||||
@@ -213,23 +180,6 @@ class _PermissionsList extends HookConsumerWidget {
|
|||||||
],
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _updatePermission(
|
|
||||||
WidgetRef ref,
|
|
||||||
SitePermissions Function(SitePermissionsWrapper) updater,
|
|
||||||
) async {
|
|
||||||
await ref
|
|
||||||
.read(
|
|
||||||
sitePermissionsRepositoryProvider(
|
|
||||||
origin: origin,
|
|
||||||
isPrivate: isPrivate,
|
|
||||||
).notifier,
|
|
||||||
)
|
|
||||||
.updatePermission(updater);
|
|
||||||
|
|
||||||
// Reload the tab to apply changes
|
|
||||||
await ref.read(selectedTabSessionProvider).reload();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class _PermissionEntry {
|
class _PermissionEntry {
|
||||||
|
|||||||
Reference in New Issue
Block a user