Improve Blossom UI with thumbnails and full-width layout (v0.37.0)
Some checks failed
Go / build-and-release (push) Has been cancelled

- Make Blossom view use full available width
- Add "Upload new files" label with Select Files button on right
- Show image/video thumbnails in file list (48x48px)
- Add emoji icons for audio (🎵) and documents (📄)
- Show full hash on screens > 720px, truncated on smaller

Files modified:
- app/web/src/BlossomView.svelte: UI layout and thumbnail changes
- app/web/dist/*: Rebuilt bundle

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
2025-12-25 13:07:25 +01:00
parent 0de4137a10
commit aea8fd31e7
5 changed files with 79 additions and 30 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -159,10 +159,10 @@
function getMimeIcon(mimeType) { function getMimeIcon(mimeType) {
const category = getMimeCategory(mimeType); const category = getMimeCategory(mimeType);
switch (category) { switch (category) {
case "image": return ""; case "image": return "🖼️";
case "video": return ""; case "video": return "🎬";
case "audio": return ""; case "audio": return "🎵";
default: return ""; default: return "📄";
} }
} }
@@ -464,6 +464,7 @@
{#if !isAdminView && !selectedAdminUser} {#if !isAdminView && !selectedAdminUser}
<div class="upload-section"> <div class="upload-section">
<span class="upload-label">Upload new files</span>
<input <input
type="file" type="file"
multiple multiple
@@ -471,9 +472,6 @@
on:change={handleFileSelect} on:change={handleFileSelect}
class="file-input-hidden" class="file-input-hidden"
/> />
<button class="select-btn" on:click={triggerFileInput} disabled={isUploading}>
Select Files
</button>
{#if selectedFiles.length > 0} {#if selectedFiles.length > 0}
<span class="selected-count">{selectedFiles.length} file(s) selected</span> <span class="selected-count">{selectedFiles.length} file(s) selected</span>
<button <button
@@ -484,6 +482,9 @@
{isUploading ? uploadProgress : "Upload"} {isUploading ? uploadProgress : "Upload"}
</button> </button>
{/if} {/if}
<button class="select-btn" on:click={triggerFileInput} disabled={isUploading}>
Select Files
</button>
</div> </div>
{/if} {/if}
@@ -552,12 +553,19 @@
role="button" role="button"
tabindex="0" tabindex="0"
> >
<div class="blob-icon"> <div class="blob-thumbnail">
{getMimeIcon(blob.type)} {#if getMimeCategory(blob.type) === "image"}
<img src={getBlobUrl(blob)} alt="" class="thumbnail-img" />
{:else if getMimeCategory(blob.type) === "video"}
<video src={getBlobUrl(blob)} class="thumbnail-video" muted preload="metadata"></video>
{:else}
<span class="thumbnail-icon">{getMimeIcon(blob.type)}</span>
{/if}
</div> </div>
<div class="blob-info"> <div class="blob-info">
<div class="blob-hash" title={blob.sha256}> <div class="blob-hash" title={blob.sha256}>
{truncateHash(blob.sha256)} <span class="hash-full">{blob.sha256}</span>
<span class="hash-truncated">{truncateHash(blob.sha256)}</span>
</div> </div>
<div class="blob-meta"> <div class="blob-meta">
<span class="blob-size">{formatSize(blob.size)}</span> <span class="blob-size">{formatSize(blob.size)}</span>
@@ -678,7 +686,7 @@
<style> <style>
.blossom-view { .blossom-view {
padding: 1em; padding: 1em;
max-width: 900px; width: 100%;
} }
.header-section { .header-section {
@@ -777,6 +785,12 @@
flex-wrap: wrap; flex-wrap: wrap;
} }
.upload-label {
color: var(--text-color);
font-size: 0.95em;
flex: 1;
}
.file-input-hidden { .file-input-hidden {
display: none; display: none;
} }
@@ -861,10 +875,27 @@
background-color: var(--sidebar-bg); background-color: var(--sidebar-bg);
} }
.blob-icon { .blob-thumbnail {
width: 48px;
height: 48px;
flex-shrink: 0;
display: flex;
align-items: center;
justify-content: center;
background-color: var(--bg-color);
border-radius: 4px;
overflow: hidden;
}
.thumbnail-img,
.thumbnail-video {
width: 100%;
height: 100%;
object-fit: cover;
}
.thumbnail-icon {
font-size: 1.5em; font-size: 1.5em;
width: 2em;
text-align: center;
} }
.blob-info { .blob-info {
@@ -878,6 +909,14 @@
color: var(--text-color); color: var(--text-color);
} }
.hash-full {
display: inline;
}
.hash-truncated {
display: none;
}
.blob-meta { .blob-meta {
display: flex; display: flex;
gap: 1em; gap: 1em;
@@ -1263,6 +1302,16 @@
color: var(--text-color); color: var(--text-color);
} }
@media (max-width: 720px) {
.hash-full {
display: none;
}
.hash-truncated {
display: inline;
}
}
@media (max-width: 600px) { @media (max-width: 600px) {
.blob-item { .blob-item {
flex-wrap: wrap; flex-wrap: wrap;
@@ -1271,7 +1320,7 @@
.blob-date { .blob-date {
width: 100%; width: 100%;
margin-top: 0.5em; margin-top: 0.5em;
padding-left: 3em; padding-left: 3.5em;
} }
.modal-footer { .modal-footer {

View File

@@ -1 +1 @@
v0.36.23 v0.37.0