diff --git a/public/healthz.json b/public/healthz.json index 2f36db0..0c10620 100644 --- a/public/healthz.json +++ b/public/healthz.json @@ -2,7 +2,7 @@ "status": "ok", "service": "aitherboard", "version": "0.2.0", - "buildTime": "2026-02-06T23:46:07.275Z", + "buildTime": "2026-02-07T00:27:17.672Z", "gitCommit": "unknown", - "timestamp": 1770421567275 + "timestamp": 1770424037672 } \ No newline at end of file diff --git a/src/lib/components/EventMenu.svelte b/src/lib/components/EventMenu.svelte index ff9d63e..98254bd 100644 --- a/src/lib/components/EventMenu.svelte +++ b/src/lib/components/EventMenu.svelte @@ -97,10 +97,11 @@ const buttonRect = menuButtonElement.getBoundingClientRect(); const viewportWidth = window.innerWidth; const viewportHeight = window.innerHeight; - const padding = 8; // Padding from viewport edges + const isMobile = viewportWidth < 640; + const padding = isMobile ? 4 : 8; // Smaller padding on mobile // Get dropdown dimensions (estimate or use actual if available) - let dropdownWidth = 200; // min-width from CSS + let dropdownWidth = isMobile ? 180 : 200; // min-width from CSS let dropdownHeight = 300; // Estimate, will be updated // Position below button by default, aligned to right edge @@ -155,6 +156,11 @@ adjustedRight = padding; } + // On mobile, ensure menu doesn't go off left edge + if (isMobile && adjustedLeft < padding) { + adjustedRight = Math.max(padding, viewportWidth - dropdownWidth - padding); + } + menuPosition = { top: adjustedTop, right: adjustedRight }; }); @@ -422,7 +428,7 @@ {#if isLoggedIn && onReply} - @@ -561,6 +567,31 @@ overflow-x: hidden; } + .menu-item-reply { + display: flex !important; + visibility: visible !important; + } + + @media (max-width: 640px) { + .menu-dropdown { + min-width: 180px; + max-width: calc(100vw - 8px); + font-size: 0.875rem; + } + + .menu-item { + padding: 0.625rem 0.75rem; + font-size: 0.875rem; + min-height: 2.5rem; + } + + .menu-button { + padding: 0.375rem 0.5rem; + min-width: 2.5rem; + min-height: 2.5rem; + } + } + :global(.dark) .menu-dropdown { background: var(--fog-dark-post, #1f2937); border-color: var(--fog-dark-border, #374151); diff --git a/src/lib/components/profile/ProfileMenu.svelte b/src/lib/components/profile/ProfileMenu.svelte index 9dba6a2..57066c8 100644 --- a/src/lib/components/profile/ProfileMenu.svelte +++ b/src/lib/components/profile/ProfileMenu.svelte @@ -25,6 +25,7 @@ let profileEvent = $state(null); let muting = $state(false); let following = $state(false); + let showJsonModal = $state(false); let isLoggedIn = $derived(sessionManager.isLoggedIn()); let currentUserPubkey = $derived(sessionManager.getCurrentPubkey()); @@ -243,6 +244,18 @@ } } + async function viewJson() { + if (!profileEvent) { + await loadProfileEvent(); + } + showJsonModal = true; + closeMenu(); + } + + function closeJsonModal() { + showJsonModal = false; + } + function shareWithAitherboard() { const url = `${window.location.origin}/profile/${pubkey}`; navigator.clipboard.writeText(url).then(() => { @@ -331,6 +344,11 @@ {/if} + + +
+
+

Profile Event JSON

+ +
+
+ {#if profileEvent} +
{JSON.stringify(profileEvent, null, 2)}
+ {:else} +

Loading profile event...

+ {/if} +
+
+ + {/if} diff --git a/src/lib/components/ui/IconButton.svelte b/src/lib/components/ui/IconButton.svelte index a7b76ff..f697d3e 100644 --- a/src/lib/components/ui/IconButton.svelte +++ b/src/lib/components/ui/IconButton.svelte @@ -32,11 +32,12 @@ title={label} > + {label} diff --git a/src/lib/modules/comments/Comment.svelte b/src/lib/modules/comments/Comment.svelte index bea4eab..c311f51 100644 --- a/src/lib/modules/comments/Comment.svelte +++ b/src/lib/modules/comments/Comment.svelte @@ -122,7 +122,7 @@ {#if getClientName()} via {getClientName()} {/if} -
+
Reply @@ -232,6 +231,57 @@ border-top-color: var(--fog-dark-border, #374151); } + .reply-button { + font-size: 0.875rem; + padding: 0.25rem 0.5rem; + background: none; + border: none; + cursor: pointer; + transition: opacity 0.2s; + min-height: 2rem; + display: inline-flex; + align-items: center; + } + + .reply-button:hover { + opacity: 0.8; + } + + .comment-header-actions { + display: flex !important; + visibility: visible !important; + flex-shrink: 0; + } + + @media (max-width: 640px) { + .comment-actions { + padding-right: 4rem; + flex-wrap: wrap; + gap: 0.5rem; + } + + .reply-button { + font-size: 0.875rem; + padding: 0.375rem 0.75rem; + min-height: 2.25rem; + font-weight: 500; + } + + .comment-header { + flex-wrap: wrap; + gap: 0.5rem; + } + + .comment-header .ml-auto { + margin-left: auto; + flex-shrink: 0; + } + + .comment-header-actions { + gap: 0.375rem; + } + } + .card-content { max-height: 500px; overflow: hidden; diff --git a/src/lib/modules/feed/FeedPost.svelte b/src/lib/modules/feed/FeedPost.svelte index c153522..1a9aecd 100644 --- a/src/lib/modules/feed/FeedPost.svelte +++ b/src/lib/modules/feed/FeedPost.svelte @@ -1231,6 +1231,32 @@ .post-header-actions { flex-shrink: 0; + display: flex !important; + align-items: center; + gap: 0.5rem; + flex-wrap: wrap; + visibility: visible !important; + } + + .feed-card-actions { + display: flex !important; + visibility: visible !important; + } + + @media (max-width: 640px) { + .post-header-actions { + gap: 0.375rem; + } + + .feed-card-actions { + gap: 0.375rem; + flex-wrap: wrap; + } + + .post-header { + flex-wrap: wrap; + gap: 0.5rem; + } } diff --git a/src/lib/modules/profiles/ProfilePage.svelte b/src/lib/modules/profiles/ProfilePage.svelte index b364378..f0ff9c5 100644 --- a/src/lib/modules/profiles/ProfilePage.svelte +++ b/src/lib/modules/profiles/ProfilePage.svelte @@ -722,10 +722,10 @@ {profile.name {/if} -

{profile.name || 'Anonymous'}

+

{profile.name || 'Anonymous'}

{#if profile.about}

{profile.about}

{/if} @@ -795,10 +795,10 @@
-
+
@@ -810,28 +810,28 @@ await loadWallComments(profileEvent.id); } }} - class="px-4 py-2 font-semibold {activeTab === 'wall' ? 'border-b-2 border-fog-accent dark:border-fog-dark-accent' : ''}" + class="px-2 sm:px-4 py-2 font-semibold whitespace-nowrap flex-shrink-0 {activeTab === 'wall' ? 'border-b-2 border-fog-accent dark:border-fog-dark-accent' : ''}" > Wall ({wallComments.length}) {#if isOwnProfile} {:else if currentUserPubkey && currentUserPubkey !== profilePubkey} {/if} @@ -932,11 +932,26 @@ .profile-page { max-width: var(--content-width); margin: 0 auto; - padding: 1rem; + padding: 0.75rem; + } + + @media (min-width: 640px) { + .profile-page { + padding: 1rem; + } } .profile-picture { object-fit: cover; + width: 4rem; + height: 4rem; + } + + @media (min-width: 640px) { + .profile-picture { + width: 6rem; + height: 6rem; + } } .profile-header { @@ -948,6 +963,17 @@ overflow-wrap: break-word; word-break: break-word; } + + .profile-name { + font-size: 1.5rem; + line-height: 1.2; + } + + @media (min-width: 640px) { + .profile-name { + font-size: 2rem; + } + } .profile-header p { overflow-wrap: break-word; @@ -1092,4 +1118,60 @@ flex-direction: column; gap: 1rem; } + + /* Hide scrollbar for tabs on mobile */ + .scrollbar-hide { + -ms-overflow-style: none; + scrollbar-width: none; + } + + .scrollbar-hide::-webkit-scrollbar { + display: none; + } + + /* Responsive tabs */ + .tabs { + scrollbar-width: thin; + scrollbar-color: var(--fog-border, #e5e7eb) transparent; + } + + :global(.dark) .tabs { + scrollbar-color: var(--fog-dark-border, #374151) transparent; + } + + @media (max-width: 640px) { + .tabs { + -webkit-overflow-scrolling: touch; + } + + .tabs button { + font-size: 0.875rem; + } + } + + /* Responsive profile header */ + @media (max-width: 640px) { + .profile-header { + margin-bottom: 1rem; + } + + .profile-header p { + font-size: 0.875rem; + } + } + + /* Responsive npub display */ + @media (max-width: 640px) { + .npub-display { + flex-direction: column; + align-items: flex-start; + gap: 0.5rem; + } + + .npub-text { + font-size: 0.75rem; + word-break: break-all; + max-width: 100%; + } + } diff --git a/src/routes/profile/[pubkey]/+page.svelte b/src/routes/profile/[pubkey]/+page.svelte index 4da32bd..e8730e5 100644 --- a/src/routes/profile/[pubkey]/+page.svelte +++ b/src/routes/profile/[pubkey]/+page.svelte @@ -11,6 +11,6 @@
-
+