Add TypeScript migration, image resizing, media upload UX, and multimedia support
All checks were successful
Deploy to NAS / deploy (push) Successful in 2m20s
All checks were successful
Deploy to NAS / deploy (push) Successful in 2m20s
- Migrate static JS to TypeScript (static-ts/ → compiled to internal/api/static/) - Add image resizing on upload: JPEG/PNG/WebP scaled to max 1920px at quality 80 - Extract shared upload logic into upload.go (saveUpload, saveResizedImage, saveResizedWebP) - Add POST /media endpoint for drag-drop/paste media uploads with markdown ref return - Add background music player with video/audio coordination (autoplay.ts) - Add global nav, public feed, hashtags, visibility, Markdown rendering for entries - Add Dockerfile stage for TypeScript compilation (static-ts-builder) - Add goldmark, disintegration/imaging, golang.org/x/image dependencies Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -27,9 +27,6 @@ h2 { font-size: 1rem; font-weight: normal; letter-spacing: .05em; }
|
||||
.source-gps { color: #060; }
|
||||
.source-manual { color: #888; }
|
||||
|
||||
/* Top bar */
|
||||
.page-header { display: flex; justify-content: space-between; align-items: baseline; margin-bottom: 1.5rem; }
|
||||
|
||||
/* GPS row */
|
||||
.gps-row { display: flex; gap: .4rem; align-items: center; }
|
||||
.gps-row input { flex: 1; margin-bottom: 0; }
|
||||
@@ -38,10 +35,7 @@ h2 { font-size: 1rem; font-weight: normal; letter-spacing: .05em; }
|
||||
/* Narrow pages (login, register) */
|
||||
.narrow { max-width: 400px; margin-top: 4rem; }
|
||||
|
||||
/* Image preview */
|
||||
.image-preview { display: flex; flex-wrap: wrap; gap: .5rem; margin-bottom: .8rem; }
|
||||
.image-preview img, .thumb { width: 80px; height: 80px; object-fit: cover; border: 1px solid var(--pico-muted-border-color); }
|
||||
.thumb { width: 100px; height: 100px; display: block; }
|
||||
.thumb { width: 80px; height: 80px; object-fit: cover; border: 1px solid var(--pico-muted-border-color); display: block; }
|
||||
|
||||
/* Journal entry cards */
|
||||
.entry-card {
|
||||
@@ -54,8 +48,16 @@ h2 { font-size: 1rem; font-weight: normal; letter-spacing: .05em; }
|
||||
.entry-meta { font-size: .8rem; margin-bottom: .3rem; display: flex; gap: .6rem; align-items: baseline; flex-wrap: wrap; }
|
||||
.entry-edit { margin-left: auto; font-size: .75rem; }
|
||||
.entry-title { font-size: 1rem; margin-bottom: .3rem; }
|
||||
.entry-desc { white-space: pre-wrap; font-size: .9rem; }
|
||||
.entry-desc { font-size: .9rem; }
|
||||
.entry-desc p { margin-bottom: .5rem; }
|
||||
.entry-desc img { max-width: 100%; height: auto; display: block; margin: .5rem 0; }
|
||||
.entry-desc video { max-width: 100%; display: block; margin: .5rem 0; }
|
||||
.entry-desc ul,
|
||||
.entry-desc ol { padding-left: 1.2rem; margin-bottom: .5rem; }
|
||||
.entry-desc h1, .entry-desc h2, .entry-desc h3 { font-weight: normal; margin: .8rem 0 .3rem; }
|
||||
.entry-images { display: flex; flex-wrap: wrap; gap: .5rem; margin-top: .5rem; }
|
||||
.media-embed { width: 100%; max-height: 360px; display: block; margin-top: .5rem; }
|
||||
.media-audio { width: 100%; display: block; margin-top: .5rem; }
|
||||
|
||||
/* Public feed */
|
||||
.pub-card { margin-bottom: 2rem; padding-bottom: 1.5rem; border-bottom: 1px solid var(--pico-muted-border-color); }
|
||||
@@ -63,7 +65,10 @@ h2 { font-size: 1rem; font-weight: normal; letter-spacing: .05em; }
|
||||
.pub-cover { width: 100%; max-height: 320px; object-fit: cover; display: block; margin-bottom: .7rem; }
|
||||
.pub-meta { display: block; color: var(--pico-muted-color); margin-bottom: .3rem; }
|
||||
.pub-title { display: block; font-size: 1rem; margin-bottom: .4rem; }
|
||||
.pub-desc { margin: 0 0 .4rem; display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden; white-space: pre-wrap; }
|
||||
.pub-desc { margin: 0 0 .4rem; font-size: .9rem; }
|
||||
.pub-desc p { margin-bottom: .5rem; }
|
||||
.pub-desc img { max-width: 100%; height: auto; display: block; margin: .5rem 0; }
|
||||
.pub-desc video { max-width: 100%; display: block; margin: .5rem 0; }
|
||||
.pub-tags { margin-top: .3rem; }
|
||||
|
||||
/* Login */
|
||||
@@ -76,6 +81,25 @@ h2 { font-size: 1rem; font-weight: normal; letter-spacing: .05em; }
|
||||
/* Visibility badge */
|
||||
.badge-public { font-size: .7rem; background: #264; color: #8f8; padding: .1rem .4rem; border-radius: 4px; vertical-align: middle; }
|
||||
|
||||
/* Background music player */
|
||||
#bg-bar { display: none; position: fixed; bottom: 0; left: 0; right: 0; background: var(--pico-background-color); border-top: 1px solid var(--pico-muted-border-color); padding: .4rem 1rem; gap: .8rem; align-items: center; z-index: 100; font-size: .8rem; }
|
||||
#bg-title { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--pico-muted-color); }
|
||||
#bg-play, #bg-close { background: none; border: none; cursor: pointer; padding: 0 .3rem; font-size: .9rem; margin: 0; }
|
||||
.btn-bg-music { font-size: .75rem; padding: .15rem .5rem; background: none; border: 1px solid var(--pico-muted-border-color); cursor: pointer; margin-top: .3rem; display: block; }
|
||||
|
||||
/* Editor */
|
||||
.editor-wrap textarea { margin-bottom: 0; border-bottom: none; border-radius: var(--pico-border-radius) var(--pico-border-radius) 0 0; }
|
||||
.editor-wrap textarea.drag-over { outline: 2px dashed var(--pico-primary); }
|
||||
.editor-bar { display: flex; align-items: center; gap: .6rem; padding: .3rem .5rem; border: 1px solid var(--pico-form-element-border-color); border-top: none; border-radius: 0 0 var(--pico-border-radius) var(--pico-border-radius); margin-bottom: 1rem; background: var(--pico-form-element-background-color); }
|
||||
.editor-bar button { font-size: .78rem; padding: .15rem .5rem; background: none; border: 1px solid var(--pico-muted-border-color); cursor: pointer; margin: 0; }
|
||||
.upload-status { font-size: .78rem; color: var(--pico-muted-color); }
|
||||
|
||||
/* Media reference rows (edit form) */
|
||||
.media-refs { margin-bottom: 1rem; display: flex; flex-direction: column; gap: .5rem; }
|
||||
.media-ref-row { display: flex; align-items: center; gap: .6rem; flex-wrap: wrap; }
|
||||
.media-ref-code { font-size: .75rem; background: var(--pico-muted-background-color); padding: .2rem .4rem; flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
||||
.btn-insert { font-size: .75rem; padding: .2rem .5rem; background: none; border: 1px solid var(--pico-muted-border-color); cursor: pointer; white-space: nowrap; }
|
||||
|
||||
/* Delete button */
|
||||
.btn-delete { background: none; border: 1px solid #c44; color: #c44; padding: .2rem .6rem; cursor: pointer; font-size: .8rem; border-radius: 4px; }
|
||||
.btn-delete:hover { background: #c44; color: #fff; }
|
||||
|
||||
Reference in New Issue
Block a user