android: pin and archive a note someone shared with you
CI & Build / Python lint (push) Successful in 2s
CI & Build / Build now, or wait for Android? (push) Successful in 2s
Android / Build, or is the channel already serving this? (push) Successful in 2s
Desktop (Tauri) / Build, or is the channel already serving this? (push) Successful in 2s
CI & Build / Web typecheck and unit tests (push) Successful in 9s
CI & Build / Python tests (push) Successful in 11s
CI & Build / integration (push) Successful in 1m24s
CI & Build / Build & push image (push) Skipped
Desktop (Tauri) / Web tests, clippy, Rust tests and rustfmt (push) Failing after 1m30s
Desktop (Tauri) / Tauri desktop (Linux) (push) Skipped
Desktop (Tauri) / Windows installer (cross-compiled) (push) Skipped
Desktop (Tauri) / Update manifest (push) Skipped
Android / Kotlin + Rust (APK) (push) Successful in 7m17s
CI & Build / Python lint (push) Successful in 2s
CI & Build / Build now, or wait for Android? (push) Successful in 2s
Android / Build, or is the channel already serving this? (push) Successful in 2s
Desktop (Tauri) / Build, or is the channel already serving this? (push) Successful in 2s
CI & Build / Web typecheck and unit tests (push) Successful in 9s
CI & Build / Python tests (push) Successful in 11s
CI & Build / integration (push) Successful in 1m24s
CI & Build / Build & push image (push) Skipped
Desktop (Tauri) / Web tests, clippy, Rust tests and rustfmt (push) Failing after 1m30s
Desktop (Tauri) / Tauri desktop (Linux) (push) Skipped
Desktop (Tauri) / Windows installer (cross-compiled) (push) Skipped
Desktop (Tauri) / Update manifest (push) Skipped
Android / Kotlin + Rust (APK) (push) Successful in 7m17s
The card's long-press menu and the editor's overflow now open on shared notes with Pin and Archive; Labels, Share and Move to trash stay the owner's. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -85,8 +85,9 @@ fun EditorTopBar(
|
||||
onConfirmDelete: () -> Unit,
|
||||
onAction: (EditorAction) -> Unit,
|
||||
) {
|
||||
// Someone else's note (#5175): its text is all that may change here, so the bar
|
||||
// keeps the checklist button and nothing that is the owner's to do.
|
||||
// Someone else's note (#5175): its text, at `edit`, and this account's own pin
|
||||
// and archive (#5176) are all that may change here, so the bar keeps the
|
||||
// checklist button and an overflow of those two, and nothing that is the owner's.
|
||||
val owner = access == NoteAccess.OWNER
|
||||
val dark = isSystemInDarkTheme()
|
||||
TopAppBar(
|
||||
@@ -133,10 +134,10 @@ fun EditorTopBar(
|
||||
)
|
||||
}
|
||||
}
|
||||
if (owner) {
|
||||
if (owner || !note.trashed) {
|
||||
OverflowMenu(
|
||||
note = note,
|
||||
readOnly = readOnly,
|
||||
owner = owner,
|
||||
onPicker = onPicker,
|
||||
onShare = onShare,
|
||||
onConfirmDelete = onConfirmDelete,
|
||||
@@ -278,7 +279,7 @@ private fun savedLabel(
|
||||
@Composable
|
||||
private fun OverflowMenu(
|
||||
note: Note,
|
||||
readOnly: Boolean,
|
||||
owner: Boolean,
|
||||
onPicker: (Picker) -> Unit,
|
||||
onShare: () -> Unit,
|
||||
onConfirmDelete: () -> Unit,
|
||||
@@ -291,7 +292,7 @@ private fun OverflowMenu(
|
||||
Icon(Icons.Filled.MoreVert, contentDescription = stringResource(R.string.editor_more))
|
||||
}
|
||||
DropdownMenu(expanded = open, onDismissRequest = close) {
|
||||
if (readOnly) {
|
||||
if (note.trashed) {
|
||||
MenuItem(R.string.editor_restore, close) { onAction(EditorAction.Restore) }
|
||||
MenuItem(R.string.editor_delete_forever, close, onConfirmDelete)
|
||||
} else {
|
||||
@@ -299,19 +300,23 @@ private fun OverflowMenu(
|
||||
if (note.pinned) R.string.editor_unpin else R.string.editor_pin,
|
||||
close,
|
||||
) { onAction(EditorAction.SetPinned(!note.pinned)) }
|
||||
if (owner) {
|
||||
MenuItem(R.string.editor_labels, close) { onPicker(Picker.LABELS) }
|
||||
}
|
||||
// Not on a draft: the server has nothing to share until it is saved.
|
||||
if (note.id != DRAFT_ID) {
|
||||
if (owner && note.id != DRAFT_ID) {
|
||||
MenuItem(R.string.editor_share, close, onShare)
|
||||
}
|
||||
MenuItem(
|
||||
if (note.archived) R.string.editor_unarchive else R.string.editor_archive,
|
||||
close,
|
||||
) { onAction(EditorAction.SetArchived(!note.archived)) }
|
||||
if (owner) {
|
||||
MenuItem(R.string.editor_trash, close) { onAction(EditorAction.Trash) }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -5,9 +5,10 @@ import com.fabledsword.inkwell.core.Note
|
||||
/**
|
||||
* How this account holds a note (#5175), read from the core's `permission`.
|
||||
*
|
||||
* Someone else's note at [EDIT] is theirs to have its TEXT changed here and nothing
|
||||
* else; at [VIEW] nothing changes here at all. The core refuses the rest anyway —
|
||||
* this only keeps the editor from offering what would be refused.
|
||||
* Someone else's note at [EDIT] may have its TEXT changed here; at [VIEW] it may
|
||||
* not. Either way its pin and archive are this account's own (#5176). The core
|
||||
* refuses the rest anyway — this only keeps the editor from offering what would be
|
||||
* refused.
|
||||
*/
|
||||
enum class NoteAccess { OWNER, EDIT, VIEW }
|
||||
|
||||
@@ -19,10 +20,10 @@ val Note.access: NoteAccess
|
||||
else -> NoteAccess.OWNER
|
||||
}
|
||||
|
||||
/** Nothing changes here: the note is in the trash, or shared with us to view. */
|
||||
/** Its content can't change here: it is in the trash, or shared with us to view. */
|
||||
val Note.readOnlyHere: Boolean
|
||||
get() = trashed || access == NoteAccess.VIEW
|
||||
|
||||
/** The owner's own controls apply: tags, reminder, files, previews, the menu. */
|
||||
/** The owner's own controls apply: tags, reminder, files, previews, share, trash. */
|
||||
val Note.ownerControlsHere: Boolean
|
||||
get() = !readOnlyHere && access == NoteAccess.OWNER
|
||||
|
||||
@@ -229,9 +229,11 @@ private fun NoteMenu(
|
||||
onAction: (EditorAction) -> Unit,
|
||||
onConfirmDelete: () -> Unit,
|
||||
) {
|
||||
// Every item here is the owner's to do, so someone else's note has no menu at all
|
||||
// rather than an empty one (#5175).
|
||||
DropdownMenu(expanded = expanded && note.access == NoteAccess.OWNER, onDismissRequest = onDismiss) {
|
||||
// Pin and archive are this account's own on someone else's note too (#5176);
|
||||
// trash is the owner's. A note shared with us never reaches our Trash, so the
|
||||
// trashed set is only ever the owner's.
|
||||
val owner = note.access == NoteAccess.OWNER
|
||||
DropdownMenu(expanded = expanded && (owner || !note.trashed), onDismissRequest = onDismiss) {
|
||||
if (note.trashed) {
|
||||
MenuItem(R.string.editor_restore, onDismiss) { onAction(EditorAction.Restore) }
|
||||
MenuItem(R.string.editor_delete_forever, onDismiss, onConfirmDelete)
|
||||
@@ -244,9 +246,11 @@ private fun NoteMenu(
|
||||
if (note.archived) R.string.editor_unarchive else R.string.editor_archive,
|
||||
onDismiss,
|
||||
) { onAction(EditorAction.SetArchived(!note.archived)) }
|
||||
if (owner) {
|
||||
MenuItem(R.string.editor_trash, onDismiss) { onAction(EditorAction.Trash) }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user