Files
Client/lib/api/marianumcloud/files_sharing/queries/share/share.dart
T

109 lines
3.4 KiB
Dart

/// Nextcloud share types (subset the app uses).
const int kShareTypeUser = 0;
const int kShareTypeGroup = 1;
const int kShareTypePublicLink = 3;
const int kShareTypeEmail = 4;
/// A Talk conversation ("room") the file is linked into.
const int kShareTypeRoom = 10;
/// A single share as returned by the OCS `files_sharing` API.
///
/// Parsed by hand rather than via code generation: OCS is inconsistent about
/// types across versions (e.g. `id`/`share_type` may arrive as either strings
/// or numbers) and omits optional fields entirely, so defensive parsing is
/// safer than generated `as int` casts.
class Share {
final int id;
final int shareType;
final int permissions;
/// Server path of the shared item (e.g. `/Documents/x.pdf`).
final String? path;
/// `'file'` or `'folder'`.
final String? itemType;
/// Recipient id (user/group id); empty for public links.
final String? shareWith;
final String? shareWithDisplayname;
/// Public link URL (only set for [kShareTypePublicLink]).
final String? url;
/// Raw expiration as `"YYYY-MM-DD HH:MM:SS"` (or null when none).
final String? expiration;
final String? label;
/// Redacted password marker: the server returns `null` when no password is
/// set and a placeholder (`"redacted"`) when one is — never the real value.
final String? password;
const Share({
required this.id,
required this.shareType,
required this.permissions,
this.path,
this.itemType,
this.shareWith,
this.shareWithDisplayname,
this.url,
this.expiration,
this.label,
this.password,
});
bool get isPublicLink => shareType == kShareTypePublicLink;
bool get isGroup => shareType == kShareTypeGroup;
bool get isEmail => shareType == kShareTypeEmail;
bool get isRoom => shareType == kShareTypeRoom;
bool get isFolder => itemType == 'folder';
/// Whether a (link) password is currently set. See [password].
bool get hasPassword => password != null && password!.isNotEmpty;
/// Best display title for the share row.
String get displayTitle {
if (isPublicLink) return label?.isNotEmpty == true ? label! : 'Link';
final name = shareWithDisplayname;
if (name != null && name.isNotEmpty) return name;
return shareWith ?? 'Unbekannt';
}
/// Human label for the kind of share (for subtitles/headers).
String get kindLabel {
if (isPublicLink) return 'Öffentlicher Link';
if (isGroup) return 'Gruppe';
if (isRoom) return 'Talk-Chat';
if (isEmail) return 'E-Mail';
if (shareType == kShareTypeUser) return 'Person';
return 'Freigabe';
}
static int _asInt(Object? value, {int fallback = 0}) {
if (value is int) return value;
if (value is String) return int.tryParse(value) ?? fallback;
return fallback;
}
static String? _asString(Object? value) {
if (value == null) return null;
final s = value.toString();
return s.isEmpty ? null : s;
}
factory Share.fromJson(Map<String, dynamic> json) => Share(
id: _asInt(json['id']),
shareType: _asInt(json['share_type']),
permissions: _asInt(json['permissions']),
path: _asString(json['path']),
itemType: _asString(json['item_type']),
shareWith: _asString(json['share_with']),
shareWithDisplayname: _asString(json['share_with_displayname']),
url: _asString(json['url']),
expiration: _asString(json['expiration']),
label: _asString(json['label']),
password: _asString(json['password']),
);
}