diff options
| -rw-r--r-- | Digitigrade/Model/Note.php | 13 | ||||
| -rw-r--r-- | Digitigrade/Model/NoteAttachment.php | 6 | ||||
| -rw-r--r-- | locale/en_GB.json | 1 | ||||
| -rw-r--r-- | static/form.css | 14 | ||||
| -rw-r--r-- | static/icons.css | 3 | ||||
| -rw-r--r-- | static/note.css | 63 | ||||
| -rw-r--r-- | templates/note.php | 17 | ||||
| -rw-r--r-- | templates/write_note_form.php | 11 |
8 files changed, 119 insertions, 9 deletions
diff --git a/Digitigrade/Model/Note.php b/Digitigrade/Model/Note.php index 0164e7d..a4df99d 100644 --- a/Digitigrade/Model/Note.php +++ b/Digitigrade/Model/Note.php @@ -82,10 +82,14 @@ class Note extends PushableModel implements TimelineIncludeable, Notifyable { $this->mentions = $this->findMentions(); $this->attachments = NoteAttachment::findAllWhere('note_id = ?', [$this->id]); $this->extensions = $this->findExtensions(); + + // put attachments back in the right order + usort($this->attachments, fn($a, $b) => $a->index <=> $b->index); } protected function dehydrate() { $this->saveMentions(); + $this->saveAttachments(); $this->saveExtensions(); } @@ -130,6 +134,15 @@ class Note extends PushableModel implements TimelineIncludeable, Notifyable { } } + private function saveAttachments() { + $index = 0; + foreach ($this->attachments as $att) { + $att->index = $index++; + $att->setOwnerId($this->id); + $att->save(); + } + } + private function saveExtensions() { $pdo = Db::getInstance()->getPdo(); foreach ($this->extensions as $uri => $obj) { diff --git a/Digitigrade/Model/NoteAttachment.php b/Digitigrade/Model/NoteAttachment.php index c47ec64..9e6a3d3 100644 --- a/Digitigrade/Model/NoteAttachment.php +++ b/Digitigrade/Model/NoteAttachment.php @@ -10,13 +10,13 @@ class NoteAttachment extends Model { public string $href; public ?string $description; - protected function setOwnerId(int $id) { + public function setOwnerId(int $id) { $this->noteId = $id; } protected function getUpdateWhereClause($db): ?string { - if (self::findWhere('note_id = ?', [$this->noteId]) != null) { - return "note_id = $this->noteId"; + if (self::findWhere('note_id = ? AND index = ?', [$this->noteId, $this->index]) != null) { + return "note_id = $this->noteId AND index = $this->index"; } return null; } diff --git a/locale/en_GB.json b/locale/en_GB.json index e3e2a4c..9d2a2b7 100644 --- a/locale/en_GB.json +++ b/locale/en_GB.json @@ -72,6 +72,7 @@ "login.action": "Log in", "login.failed": "Invalid email address or password", "writeNote.label": "Write a note", + "writeNote.placeholder": "What's on your mind?", "writeNote.summary.label": "Content warning (optional)", "writeNote.scope.label": "Visibility", "writeNote.action": "Post", diff --git a/static/form.css b/static/form.css index c14b0b7..b309f33 100644 --- a/static/form.css +++ b/static/form.css @@ -63,6 +63,20 @@ form:not(.nopanel):not([hidden]) { &#writeNoteForm { max-width: 100%; + .summaryAndContent { + input:has(+ textarea) { + margin-bottom: 0; + border-bottom-left-radius: 0; + border-bottom-right-radius: 0; + border-bottom: none; + + textarea { + margin-top: 0; + border-top-left-radius: 0; + border-top-right-radius: 0; + } + } + } + .miniProfile { display: grid; grid-template-columns: max-content 1fr; diff --git a/static/icons.css b/static/icons.css index efbf8ca..8d6b7b5 100644 --- a/static/icons.css +++ b/static/icons.css @@ -99,4 +99,7 @@ &.delete-outline { --svg: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24'%3E%3Cpath fill='%23000' d='M7 21q-.825 0-1.412-.587T5 19V6H4V4h5V3h6v1h5v2h-1v13q0 .825-.587 1.413T17 21zM17 6H7v13h10zM9 17h2V8H9zm4 0h2V8h-2zM7 6v13z'/%3E%3C/svg%3E"); } + &.attach-file { + --svg: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24'%3E%3Cpath fill='%23000' d='M18 15.75q0 2.6-1.825 4.425T11.75 22t-4.425-1.825T5.5 15.75V6.5q0-1.875 1.313-3.187T10 2t3.188 1.313T14.5 6.5v8.75q0 1.15-.8 1.95t-1.95.8t-1.95-.8t-.8-1.95V6h2v9.25q0 .325.213.538t.537.212t.538-.213t.212-.537V6.5q-.025-1.05-.737-1.775T10 4t-1.775.725T7.5 6.5v9.25q-.025 1.775 1.225 3.013T11.75 20q1.75 0 2.975-1.237T16 15.75V6h2z'/%3E%3C/svg%3E"); + } } diff --git a/static/note.css b/static/note.css index 9b9eb65..0400b21 100644 --- a/static/note.css +++ b/static/note.css @@ -128,6 +128,69 @@ article.note { } } + .attachments { + padding: var(--spacing-single) 0; + display: grid; + grid-template-columns: auto; + grid-template-rows: auto; + grid-auto-flow: row; + width: 100%; + box-sizing: border-box; + gap: var(--spacing-single); + + &:has(:nth-child(2)) { + grid-template-columns: auto auto; + } + &:has(:nth-child(3)) { + grid-template-columns: auto auto auto; + } + &:has(:nth-child(4)) { + grid-template-columns: auto auto; + grid-template-rows: auto auto; + } + &:has(:nth-child(5)) { + grid-template-columns: unset; + grid-template-rows: auto; + grid-auto-flow: column; + } + + > * { + border-radius: var(--border-radius); + overflow: hidden; + display: flex; + &:has(img) { + background: black; + } + } + + img { + width: 100%; + max-height: 16lh; + object-fit: contain; + object-position: center; + } + + a.file { + border: var(--border); + border-radius: var(--border-radius); + background: var(--clr-panel-background); + color: var(--clr-foreground); + text-decoration: none; + padding: var(--spacing-single); + display: grid; + width: 100%; + box-sizing: border-box; + grid-auto-flow: column; + align-items: center; + justify-content: start; + gap: var(--spacing-half); + span { + text-overflow: ellipsis; + overflow: hidden; + } + } + } + .buttons { margin-top: var(--spacing-single); padding: 0; diff --git a/templates/note.php b/templates/note.php index 4d05554..c69531b 100644 --- a/templates/note.php +++ b/templates/note.php @@ -77,6 +77,23 @@ if ($user != null) { <?php endif; ?> </div> + <?php if (count($note->attachments) > 0): ?> + <div class="attachments"> + <?php foreach ($note->attachments as $attachment): ?> + <div> + <?php if (str_starts_with($attachment->type, 'image/')): ?> + <img src="<?= $attachment->href ?>"> + <?php else: ?> + <a class="file" href="<?= $attachment->href ?>" target="_blank"> + <span class="material-symbols attach-file"></span> + <span><?= $attachment->description ?? basename($attachment->href) ?></span> + </a> + <?php endif; ?> + </div> + <?php endforeach; ?> + </div> + <?php endif; ?> + <div class="buttons"> <?php foreach (['like', 'dislike', 'reshare'] as $action) { $kind = InteractionKind::from($action); diff --git a/templates/write_note_form.php b/templates/write_note_form.php index d2dae61..b86e825 100644 --- a/templates/write_note_form.php +++ b/templates/write_note_form.php @@ -9,13 +9,12 @@ <div class="handle">@<?= $actor->handle ?></div> </div> </div> - <div class="row"> + <div class="row summaryAndContent"> <label for="noteContent"><?= __('writeNote.label') ?></label> - <textarea name="content" id="noteContent" required autocomplete="off"></textarea> - </div> - <div class="row"> - <label for="noteSummary"><?= __('writeNote.summary.label') ?></label> - <input type="text" id="noteSummary" name="summary" autocomplete="off"> + <input type="text" id="noteSummary" name="summary" autocomplete="off" + placeholder="<?= __('writeNote.summary.label') ?>"> + <textarea name="content" id="noteContent" required autocomplete="off" + placeholder="<?= __('writeNote.placeholder') ?>"></textarea> </div> <div class="row"> <label class="standalone"><?= __('writeNote.mentions.label') ?></label> |
