feat: Einzelne Nachrichten als Link teilen
Backend:
- SharedMessageRecord Model + shared_messages DB-Tabelle
- SharedEndpoint: POST /api/messages/{id}/share, GET /api/shared/{token},
GET /api/shared (Liste), DELETE /api/shared/{token}
- Auth-Ausnahme für GET /api/shared/{token} (öffentlich ohne Login)
- DB-Methoden: CreateSharedMessage, GetSharedMessage, GetChainMessagesUpTo
Frontend:
- Share-Button (fa-share-alt) an jeder Nachricht
- Kontextmenü: Einzelnachricht oder mit Thread-Kontext teilen
- Link wird automatisch in Zwischenablage kopiert
- Öffentliche Shared-Page (#shared/{token}) ohne Login
- Markdown-Rendering in der geteilten Ansicht
- CSS für Share-Button, Share-Menü und Shared-Page
This commit is contained in:
1 parent
4e915f76af
commit
be29984b25
12 files changed
+591
-8
No files matched your search
+119
-4
@@ -414,7 +414,8 @@
|
||||
|
||||
.msg-reply-btn,
|
||||
.msg-delete-btn,
|
||||
.msg-mark-btn {
|
||||
.msg-mark-btn,
|
||||
.msg-share-btn {
|
||||
position: absolute;
|
||||
top: var(--badge-spacing);
|
||||
opacity: 0;
|
||||
@@ -428,20 +429,25 @@
|
||||
}
|
||||
|
||||
.msg-reply-btn {
|
||||
right: calc(var(--badge-spacing) + 4em + var(--badge-spacing));
|
||||
right: calc(var(--badge-spacing) + 6em + var(--badge-spacing) * 1.5);
|
||||
}
|
||||
|
||||
.msg-delete-btn {
|
||||
right: calc(var(--badge-spacing) + 2em + var(--badge-spacing) / 2);
|
||||
right: calc(var(--badge-spacing) + 4em + var(--badge-spacing));
|
||||
}
|
||||
|
||||
.msg-mark-btn {
|
||||
right: calc(var(--badge-spacing) + 2em + var(--badge-spacing) / 2);
|
||||
}
|
||||
|
||||
.msg-share-btn {
|
||||
right: var(--badge-spacing);
|
||||
}
|
||||
|
||||
.msg:hover .msg-reply-btn,
|
||||
.msg:hover .msg-delete-btn,
|
||||
.msg:hover .msg-mark-btn {
|
||||
.msg:hover .msg-mark-btn,
|
||||
.msg:hover .msg-share-btn {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
@@ -858,3 +864,112 @@
|
||||
object-fit: contain;
|
||||
border-radius: var(--border-radius);
|
||||
}
|
||||
|
||||
/* Share Menu */
|
||||
|
||||
.share-menu {
|
||||
background: var(--f2-bg);
|
||||
border: var(--border-width) solid var(--f2-border);
|
||||
border-radius: var(--border-radius);
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
box-shadow: 0 4px 16px rgb(0 0 0 / 0.25);
|
||||
min-width: 12em;
|
||||
}
|
||||
|
||||
.share-menu-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: var(--badge-spacing);
|
||||
padding: var(--menu-item-padding);
|
||||
background: none;
|
||||
border: none;
|
||||
text-align: left;
|
||||
white-space: nowrap;
|
||||
cursor: pointer;
|
||||
color: var(--text);
|
||||
font-size: var(--font-size);
|
||||
}
|
||||
|
||||
.share-menu-item:hover {
|
||||
background: var(--f3-bg);
|
||||
border: none;
|
||||
}
|
||||
|
||||
/* Shared Page (öffentliche Ansicht) */
|
||||
|
||||
.shared-page {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
min-height: 100dvh;
|
||||
max-width: var(--page-width);
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.shared-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: var(--box-spacing);
|
||||
padding: var(--page-padding);
|
||||
border-bottom: var(--border-width) solid var(--f2-border);
|
||||
}
|
||||
|
||||
.shared-logo {
|
||||
font-weight: bold;
|
||||
font-size: 1.2em;
|
||||
letter-spacing: .05em;
|
||||
}
|
||||
|
||||
.shared-label {
|
||||
opacity: var(--semi-transparent);
|
||||
font-size: var(--font-size);
|
||||
}
|
||||
|
||||
.shared-content {
|
||||
flex: 1;
|
||||
padding: var(--page-padding);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: var(--badge-spacing);
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.shared-content .msg {
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
.shared-loading,
|
||||
.shared-error {
|
||||
text-align: center;
|
||||
padding: 3em 1em;
|
||||
opacity: var(--semi-transparent);
|
||||
}
|
||||
|
||||
.shared-error {
|
||||
color: var(--dangerous);
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.shared-meta {
|
||||
text-align: center;
|
||||
padding: var(--box-padding);
|
||||
opacity: var(--semi-transparent);
|
||||
font-size: var(--font-size);
|
||||
}
|
||||
|
||||
.shared-footer {
|
||||
padding: var(--page-padding);
|
||||
text-align: center;
|
||||
border-top: var(--border-width) solid var(--f2-border);
|
||||
}
|
||||
|
||||
.shared-cta {
|
||||
color: var(--primary);
|
||||
text-decoration: none;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.shared-cta:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
Reference in new issue
Block a user