Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions app/src/main/java/dev/finalish/core/data/FrameioRepository.kt
Original file line number Diff line number Diff line change
Expand Up @@ -939,6 +939,10 @@ class FrameioRepository(
return dev.finalish.core.model.FileAccess.ofRole(role).also { accessByProject[key] = it }
}

/** The [fileAccess] already read this session, without asking Frame.io; null until then. */
fun cachedFileAccess(account: String, projectId: String): dev.finalish.core.model.FileAccess? =
accessByProject["$account:$projectId"]

private suspend fun myRole(account: String, projectId: String): String? {
val accountRoles = accounts().firstOrNull { it.id == account }?.roles.orEmpty()
if ("owner" in accountRoles || "admin" in accountRoles) return "owner"
Expand Down
18 changes: 11 additions & 7 deletions app/src/main/java/dev/finalish/core/model/Models.kt
Original file line number Diff line number Diff line change
Expand Up @@ -707,25 +707,29 @@ data class GroupRole(
/**
* What the signed-in user may do with the files of a project, from their role there (Frame.io's
* "Managing user permissions" guide): `viewer` only views, `commenter` also comments, `edit_only`
* also uploads and manages files but can't share or download, `editor` and `full_access` (and
* account owners and admins) can do everything. An unknown role keeps every action: the server
* still has the last word.
* also uploads and manages files but can't share or download, `editor` can do all that and share and
* download, and only `full_access` (and account owners and admins) also "manage settings and invite
* users", i.e. rename, restrict, archive and delete the project. An unknown role keeps every action:
* the server still has the last word.
*/
@Immutable
data class FileAccess(
val comment: Boolean = true,
/** Rename, move, copy, duplicate, delete, upload (also a new version), stack. */
/** Rename, move, copy, duplicate, delete, upload (also a new version), stack; restore deleted files. */
val manage: Boolean = true,
val share: Boolean = true,
val download: Boolean = true,
/** The project itself: rename, restrict, archive, delete. */
val projectSettings: Boolean = true,
) {
companion object {
val Full = FileAccess()

fun ofRole(role: String?): FileAccess = when (role) {
"viewer" -> FileAccess(comment = false, manage = false, share = false, download = false)
"commenter" -> FileAccess(comment = true, manage = false, share = false, download = false)
"edit_only" -> FileAccess(comment = true, manage = true, share = false, download = false)
"viewer" -> FileAccess(comment = false, manage = false, share = false, download = false, projectSettings = false)
"commenter" -> FileAccess(comment = true, manage = false, share = false, download = false, projectSettings = false)
"edit_only" -> FileAccess(comment = true, manage = true, share = false, download = false, projectSettings = false)
"editor" -> FileAccess(projectSettings = false)
else -> Full
}
}
Expand Down
15 changes: 11 additions & 4 deletions app/src/main/java/dev/finalish/ui/browser/FolderScreen.kt
Original file line number Diff line number Diff line change
Expand Up @@ -296,7 +296,9 @@ fun FolderScreen(
filterCount = fieldFilters.size,
onFilters = { filtersOpen = true },
projectActions = ProjectActions(
{ onOpenMembers(project.ifBlank { title }) }, { onOpenTrash(project.ifBlank { title }) }, { onOpenShares(project.ifBlank { title }) },
{ onOpenMembers(project.ifBlank { title }) },
trash = if (fileAccess.manage) ({ onOpenTrash(project.ifBlank { title }) }) else null,
shares = if (fileAccess.share) ({ onOpenShares(project.ifBlank { title }) }) else null,
folderMembers = if (isProjectRoot) null else ({ onOpenFolderMembers(folderId, title) }),
),
)
Expand Down Expand Up @@ -685,7 +687,8 @@ fun FolderScreen(
}
}

class ProjectActions(val members: () -> Unit, val trash: () -> Unit, val shares: () -> Unit, val folderMembers: (() -> Unit)? = null)
/** The project "⋯" in the top bar; a null action is one the user's role can't use (see [projectActionsFor][dev.finalish.ui.home.projectActionsFor]). */
class ProjectActions(val members: () -> Unit, val trash: (() -> Unit)?, val shares: (() -> Unit)?, val folderMembers: (() -> Unit)? = null)

@Composable
private fun ImportFromLinkDialog(onDismiss: () -> Unit, onImport: (url: String, name: String) -> Unit) {
Expand Down Expand Up @@ -790,8 +793,12 @@ private fun BrowserTopBar(
DropdownMenuItem(text = { Text(stringResource(R.string.browser_folder_members)) }, leadingIcon = { Icon(Icons.Rounded.FolderShared, null) }, onClick = { projectMenu = false; fm() })
}
DropdownMenuItem(text = { Text(stringResource(if (projectActions.folderMembers != null) R.string.browser_project_members else R.string.browser_action_members)) }, leadingIcon = { Icon(Icons.Rounded.Group, null) }, onClick = { projectMenu = false; projectActions.members() })
DropdownMenuItem(text = { Text(stringResource(R.string.browser_share_links)) }, leadingIcon = { Icon(Icons.Rounded.Link, null) }, onClick = { projectMenu = false; projectActions.shares() })
DropdownMenuItem(text = { Text(stringResource(R.string.browser_recently_deleted)) }, leadingIcon = { Icon(Icons.Rounded.DeleteSweep, null) }, onClick = { projectMenu = false; projectActions.trash() })
projectActions.shares?.let { shares ->
DropdownMenuItem(text = { Text(stringResource(R.string.browser_share_links)) }, leadingIcon = { Icon(Icons.Rounded.Link, null) }, onClick = { projectMenu = false; shares() })
}
projectActions.trash?.let { trash ->
DropdownMenuItem(text = { Text(stringResource(R.string.browser_recently_deleted)) }, leadingIcon = { Icon(Icons.Rounded.DeleteSweep, null) }, onClick = { projectMenu = false; trash() })
}
}
}
}
Expand Down
Loading
Loading