[client] Misc fixes

This commit is contained in:
Abhishek Shroff
2025-04-05 21:41:30 +05:30
parent f28115edc1
commit b1f2d1a4df
7 changed files with 33 additions and 81 deletions
@@ -25,12 +25,15 @@ class UpdatePermissionsChange extends LocalChange<Resource> {
@override
Resource? apply(Resource? data) {
if (data == null) return null;
final p = mergePermissions({}, data.permissions);
var p = data.grants.parsePermissionMap();
if ((p[username] ?? 0) == permission) {
return data;
}
if (permission == 0) {
p.remove(username);
} else if (p.isEmpty) {
// Empty means const map, so we can't add to it
p = {username: permission};
} else {
p[username] = permission;
}
+1 -1
View File
@@ -6,6 +6,6 @@ Bookmark parseBookmark(Map<String, dynamic> data) {
name: data['name'],
dir: data['dir'],
created: data['created'],
deleted: data['deleted'],
deleted: data.containsKey('deleted') ? data['deleted'] : false,
);
}
+2 -2
View File
@@ -14,7 +14,7 @@ Resource parseFullResource(Map<String, dynamic> data) {
contentType: data['c_type'],
permissions: data['permissions'].isEmpty ? null : data['permissions'],
publinks: data['publinks'].isEmpty ? null : data['publinks'],
grants: data['grants'].isEmpty ? null : data['grants'],
grants: data['grants'].isEmpty || data['grants'] == '{}' ? null : data['grants'],
);
}
@@ -45,7 +45,7 @@ ResourcesCompanion parsePartialResource(Map<String, dynamic> data, [String? id])
: Value(data['permissions'])
: Value.absent(),
grants: data.containsKey('grants')
? data['grants'].isEmpty
? data['grants'].isEmpty || data['grants'] == '{}'
? Value(null)
: Value(data['grants'])
: Value.absent(),
@@ -24,7 +24,7 @@ class BookmarkRepository extends Repository<PhylumAccount, Bookmark> {
if (!Hive.isAdapterRegistered(const BookmarkAdapter().typeId)) {
Hive.registerAdapter(const BookmarkAdapter());
}
final box = await _account.openBox<Bookmark>(_remoteBookmarksBoxName);
final box = await account.openBox<Bookmark>(_remoteBookmarksBoxName);
final remoteData = Map<String, Bookmark?>.fromIterable(box.keys, value: (key) => box.get(key));
await box.close();
_account = account;
+15 -55
View File
@@ -4,7 +4,6 @@ import 'package:flutter/material.dart';
import 'package:offtheline/offtheline.dart';
import 'package:phylum/libphylum/actions/action_resource.dart';
import 'package:phylum/libphylum/db/db.dart';
import 'package:phylum/libphylum/db/resource_helpers.dart';
import 'package:phylum/libphylum/phylum_account.dart';
import 'package:phylum/libphylum/explorer/explorer_controller.dart';
import 'package:phylum/libphylum/phylum_api_types.dart';
@@ -56,6 +55,13 @@ class ResourceInfoView extends StatelessWidget {
@override
Widget build(BuildContext context) {
final account = context.read<PhylumAccount>();
final p = resource.permissions.parsePermissionMap();
final myPermission = p.remove(account.userEmail) ?? 0;
final repository = context.read<PhylumAccount>().userRepository;
final entries = p.entries.toList(growable: false)..sort(((a, b) => a.key.compareTo(b.key)));
final other = entries.map((e) => repository.getUserDisplayName(e.key)).join(', ');
return ListTileTheme(
data: ListTileThemeData(
visualDensity: VisualDensity.adaptivePlatformDensity,
@@ -92,7 +98,14 @@ class ResourceInfoView extends StatelessWidget {
overflow: TextOverflow.fade,
),
),
PermissionsTile(resourceId: resource.id),
ListTile(
title: const Text('My Permissions'),
subtitle: Text(myPermission.toStringFull()),
),
ListTile(
title: const Text('Others with Access'),
subtitle: other.isEmpty ? const Text('--') : Text(other),
),
],
),
);
@@ -163,56 +176,3 @@ class _PendingActionsTileState extends State<PendingActionsTile> {
);
}
}
class PermissionsTile extends StatefulWidget {
final String resourceId;
const PermissionsTile({super.key, required this.resourceId});
@override
State<PermissionsTile> createState() => _PermissionsTileState();
}
class _PermissionsTileState extends State<PermissionsTile> {
Permission? myPermission;
Map<String, Permission>? otherPermissions;
StreamSubscription<List<ParentsResult>>? sub;
@override
void initState() {
super.initState();
final account = context.read<PhylumAccount>();
sub = account.db.watchParents(widget.resourceId).listen((data) {
final p = calculatePermissionSet(data.map((e) => e.permissions));
setState(() {
myPermission = p.remove(account.userEmail) ?? 0;
otherPermissions = p;
});
});
}
@override
void dispose() {
sub?.cancel();
super.dispose();
}
@override
Widget build(BuildContext context) {
final repository = context.read<PhylumAccount>().userRepository;
final entries = otherPermissions?.entries.toList(growable: false)?..sort(((a, b) => a.key.compareTo(b.key)));
final other = entries?.map((e) => repository.getUserDisplayName(e.key)).join(', ');
return Column(
children: [
ListTile(
title: const Text('My Permissions'),
subtitle: myPermission == null ? const Text('') : Text(myPermission!.toStringFull()),
),
ListTile(
title: const Text('Others with Access'),
subtitle: (other?.isEmpty ?? true) ? const Text('--') : Text(other!),
),
],
);
}
}
@@ -29,12 +29,10 @@ class _ResourcePermissionsViewState extends State<ResourcePermissionsView> {
super.initState();
final account = context.read<PhylumAccount>();
sub = account.db.watchParents(widget.resourceId).listen((data) {
final inheritedPermissions = calculatePermissionSet(data.sublist(1).map((e) => e.permissions));
final permissions = mergePermissions(Map.of(inheritedPermissions), data.first.permissions);
setState(() {
resourceName = data.first.name;
this.inheritedPermissions = inheritedPermissions;
this.permissions = permissions;
inheritedPermissions = data.length > 1 ? data[1].permissions.parsePermissionMap() : const {};
permissions = data.first.permissions.parsePermissionMap();
});
});
}
@@ -72,10 +70,13 @@ class _ResourcePermissionsViewState extends State<ResourcePermissionsView> {
final users = account.userRepository.users.entries
.where((e) => !inheritedPermissions.containsKey(e.key) && !permissions.containsKey(e.key))
.map((e) => e.value);
final user = await showOptionsDialogBuilder(context, users.toList(growable: false), (user) => ListTile(title: Text(user.display)),
final user = await showOptionsDialogBuilder(
context, users.toList(growable: false), (user) => ListTile(title: Text(user.display)),
filterList: (u, q) {
final query = q.toLowerCase();
return u.where((u) => u.username.contains(query) || u.display.contains(query)).toList(growable: false);
return u
.where((u) => u.username.contains(query) || u.display.contains(query))
.toList(growable: false);
});
if (user == null || !context.mounted) return;
final permission = await showOptionsDialogBuilder(
+3 -15
View File
@@ -12,21 +12,9 @@ const Permission permissionSetReadOnly = permissionRead;
const Permission permissionSetReadWrite = permissionRead | permissionWrite;
const Permission permissionSetReadWriteShare = permissionRead | permissionWrite | permissionShare;
Map<String, Permission> calculatePermissionSet(Iterable<String?> permissionJsons) {
final permissions = <String, Permission>{};
for (final p in permissionJsons) {
mergePermissions(permissions, p);
}
return permissions;
}
Map<String, Permission> mergePermissions(Map<String, Permission> permissions, String? permissionsJson) {
if (permissionsJson != null) {
for (final e in (jsonDecode(permissionsJson) as Map).cast<String, Permission>().entries) {
permissions[e.key] = (permissions[e.key] ?? 0) | e.value;
}
}
return permissions;
extension PermissionMapper on String? {
Map<String, Permission> parsePermissionMap() =>
this == null ? const {} : (jsonDecode(this!) as Map).cast<String, Permission>();
}
extension PermissionStringer on Permission {