feat: add QR share button to profile and fix mobile header layout

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
SITO 2026-05-01 01:48:13 +02:00
parent 9ee8fd60cd
commit dad3871c65
4 changed files with 117 additions and 46 deletions

View file

@ -60,63 +60,68 @@ pre, code {
display: flex !important;
flex-direction: row !important;
flex-wrap: wrap !important;
width: 100% !important;
max-width: 100% !important;
padding: 4px 2px !important;
gap: 2px !important;
align-items: center !important;
}
.header-content {
display: flex !important;
flex-wrap: wrap !important;
width: 100% !important;
max-width: 100% !important;
padding: 2px !important;
gap: 4px !important;
padding: 2px 4px !important;
gap: 0 !important;
}
body div.top-bar-left {
display: contents !important;
}
body div.top-bar-left > a.logo-icon {
flex: 0 0 100% !important;
}
body div.top-bar-left > nav,
body div.top-bar-left > nav > ul,
body div.top-bar-right,
body div.top-bar-right nav,
body div.top-bar-right nav ul {
display: contents !important;
}
body div.top-bar-left nav ul li a,
body div.top-bar-right nav ul li a {
padding: 5px 5px !important;
font-size: 0.82rem !important;
min-height: auto !important;
border: none !important;
}
.top-bar-left, .top-bar-mid, .top-bar-right {
.top-bar-left {
display: flex !important;
flex-direction: row !important;
align-items: center !important;
flex: 1 !important;
flex-wrap: nowrap !important;
gap: 2px !important;
width: auto !important;
max-width: none !important;
padding: 0 !important;
}
.top-bar-right {
display: flex !important;
flex-direction: row !important;
align-items: center !important;
flex-shrink: 0 !important;
flex-wrap: nowrap !important;
gap: 2px !important;
width: auto !important;
max-width: none !important;
padding: 0 !important;
}
.top-bar-left nav,
.top-bar-right nav {
display: flex !important;
flex-direction: column !important;
width: 100% !important;
max-width: 100% !important;
align-items: stretch !important;
gap: 4px !important;
}
.top-bar-left nav ul,
.top-bar-mid nav ul,
.top-bar-right nav ul {
display: flex !important;
flex-wrap: wrap !important;
gap: 4px !important;
flex-direction: row !important;
flex-wrap: nowrap !important;
gap: 2px !important;
padding: 0 !important;
margin: 0 !important;
list-style: none !important;
}
a.logo-icon img.logo-icon {
width: 28px !important;
height: 28px !important;
display: block !important;
}
.header nav ul li a,
.top-bar-left nav ul li a,
.top-bar-right nav ul li a {
padding: 4px 6px !important;
font-size: 0.75rem !important;
min-height: auto !important;
border: none !important;
white-space: nowrap !important;
display: inline-block !important;
line-height: 1.2 !important;
}
.oasis-nav-header { font-size: 0.85rem !important; }

View file

@ -4315,3 +4315,43 @@ button, input[type="submit"], input[type="button"], .filter-btn {
grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
gap: 20px;
}
/* ---- QR Compartir ID (details/summary en perfil) ---- */
.qr-share-details {
margin: 8px 0;
width: 100%;
}
.qr-share-btn {
display: inline-flex;
align-items: center;
gap: 6px;
cursor: pointer;
padding: 8px 16px;
border-radius: 8px;
font-size: 0.9rem;
font-weight: bold;
list-style: none;
user-select: none;
}
.qr-share-btn::-webkit-details-marker { display: none; }
.qr-share-panel {
display: flex;
flex-direction: column;
align-items: center;
gap: 8px;
padding: 16px 8px;
margin-top: 8px;
border-radius: 12px;
}
.qr-share-id {
font-family: monospace;
font-size: 0.7rem;
word-break: break-all;
text-align: center;
max-width: 280px;
opacity: 0.7;
}

View file

@ -329,3 +329,19 @@ a.user-link:focus {
.qr-code svg path {
fill: #FFD700;
}
.qr-share-btn {
background-color: #2a2a00;
color: #FFD700;
border: 1px solid #555;
}
.qr-share-btn:hover {
background-color: #3a3a00;
border-color: #FFD700;
}
.qr-share-panel {
background-color: #1A1A1A;
border: 1px solid #333;
}

View file

@ -2,6 +2,7 @@
const path = require("path");
const fs = require("fs");
const QRCode = require('../server/node_modules/qrcode');
const envPaths = require("../server/node_modules/env-paths");
const debug = require("../server/node_modules/debug")("oasis");
@ -1514,7 +1515,7 @@ exports.editProfileView = ({ name, description }) =>
)
);
exports.authorView = ({
exports.authorView = async ({
avatarUrl,
description,
feedId,
@ -1562,6 +1563,8 @@ exports.authorView = ({
const { lastActivityBadge } = require('./inhabitants_view');
const qrSvg = feedId ? await QRCode.toString(feedId, { type: 'svg' }) : '';
const prefix = section(
{ class: "message" },
div(
@ -1572,6 +1575,13 @@ exports.authorView = ({
),
pre({ class: "md-mention", innerHTML: sanitizeHtml(markdownMention) }),
p(a({ class: "user-link", href: `/author/${encodeURIComponent(feedId)}` }, feedId)),
qrSvg ? details({ class: 'qr-share-details' },
summary({ class: 'qr-share-btn' }, '⬡ Compartir ID'),
div({ class: 'qr-share-panel' },
div({ class: 'qr-code qr-code-profile', innerHTML: qrSvg }),
p({ class: 'qr-share-id' }, feedId)
)
) : null,
div({ class: "profile-metrics" },
p(`${i18n.bankingUserEngagementScore}: `, strong(karmaScore !== undefined ? karmaScore : 0)),
...lastActivityBadge({ lastActivityBucket: bucket }, true),