Fix share dialog overflow, improve shared files UX

- Share dialog max-width respects viewport (no off-screen)
- Shared files show filename + owner + permission level
- Click hint below shared list
- Empty state message when no files shared
- openSharedFile uses owner_id for cross-user read
This commit is contained in:
2026-05-27 10:28:53 +02:00
parent 764a405958
commit b2f3aa39af
+31 -2
View File
@@ -34,7 +34,9 @@
</div> </div>
<div v-if="loading" class="loading-bar"></div> <div v-if="loading" class="loading-bar"></div>
<FileTree v-if="view === 'files'" :files="filteredFiles" :selected="currentFile" @select="openFile" @delete="deleteItem" @move="moveFile" @rename="renameFile" /> <FileTree v-if="view === 'files'" :files="filteredFiles" :selected="currentFile" @select="openFile" @delete="deleteItem" @move="moveFile" @rename="renameFile" />
<FileTree v-if="view === 'shared'" :files="sharedFiles" :selected="currentFile" @select="openFile" @delete="deleteItem" @move="moveFile" /> <FileTree v-if="view === 'shared'" :files="sharedFiles" :selected="currentFile" @select="openSharedFile" @delete="deleteItem" @move="moveFile" />
<p v-if="view === 'shared' && !sharedFiles.length" style="padding:16px;color:var(--text-muted);font-size:13px;text-align:center">No files shared with you yet</p>
<p v-if="view === 'shared' && sharedFiles.length" style="padding:4px 12px;color:var(--text-muted);font-size:11px">Click a file to open it</p>
<div v-if="view === 'trash'" class="trash-view"> <div v-if="view === 'trash'" class="trash-view">
<div class="trash-header"> <div class="trash-header">
<span>{{ trashItems.length }} item(s)</span> <span>{{ trashItems.length }} item(s)</span>
@@ -656,12 +658,38 @@ async function handleImageDrop(e) {
async function loadShared() { async function loadShared() {
try { try {
sharedFiles.value = await api('/api/files/shared', {}) const data = await api('/api/files/shared', {})
// Convert to FileTree-compatible format
sharedFiles.value = (data || []).filter(f => f.type !== 'outgoing').map(f => ({
name: `${f.path} (${f.owner}, ${f.level})`,
path: f.path,
isDir: false,
owner_id: f.owner_id,
}))
} catch (e) { } catch (e) {
sharedFiles.value = [] sharedFiles.value = []
} }
} }
async function openSharedFile(path) {
// Find the shared file entry to get owner_id
const entry = sharedFiles.value.find(f => f.path === path)
if (!entry || !entry.owner_id) {
openFile(path)
return
}
try {
const res = await api('/api/files/read', { path, owner_id: entry.owner_id })
currentFile.value = path
content.value = res.content
fileMeta.value = `Shared by ${entry.name.split('(')[1]?.split(')')[0] || 'unknown'}`
isDirty.value = false
view.value = 'shared'
} catch (e) {
toast('Cannot open shared file', 'error')
}
}
async function loadTrash() { async function loadTrash() {
try { try {
trashItems.value = await api('/api/files/trash', {}) trashItems.value = await api('/api/files/trash', {})
@@ -1400,6 +1428,7 @@ body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; b
right: 0; right: 0;
top: 50px; top: 50px;
width: 360px; width: 360px;
max-width: calc(100vw - 280px);
max-height: calc(100vh - 60px); max-height: calc(100vh - 60px);
overflow-y: auto; overflow-y: auto;
background: var(--bg-primary); background: var(--bg-primary);