Browse Source

Fix web UI reactivity and center login prompts

- Fix BlossomView blob list not refreshing after upload by replacing
  getDisplayBlobs() function call with reactive $: displayBlobs declaration
- Fix EventsView not reflecting login state by moving permission check
  from EventsView template to App.svelte where reactive variables live
- Await fetchUserRole() in loadRelayData() to prevent race condition
  during auto-login from localStorage
- Trigger explicit event loading after handleLogin() completes
- Center login prompts and permission messages in main content panel
  using margin:auto and align-items:center on main-content flex container
- Add warning log for blossom upload auth validation failures
- Remove temporary debug logging from blossom handlers
- Bump version to v0.58.7

Files modified:
- app/web/src/App.svelte: Permission gating, event loading, centered prompts
- app/web/src/BlossomView.svelte: Reactive displayBlobs declaration
- app/web/src/EventsView.svelte: Remove internal permission checks
- pkg/blossom/handlers.go: Clean up debug logging, add auth failure warning
- pkg/version/version: v0.58.7

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
imwald-v0.58.10
woikos 4 months ago
parent
commit
7d7f16dee7
No known key found for this signature in database
  1. 4
      app/web/dist/bundle.css
  2. 28
      app/web/dist/bundle.js
  3. 2
      app/web/dist/bundle.js.map
  4. 50
      app/web/src/App.svelte
  5. 14
      app/web/src/BlossomView.svelte
  6. 19
      app/web/src/EventsView.svelte
  7. 4
      pkg/blossom/handlers.go
  8. 2
      pkg/version/version

4
app/web/dist/bundle.css vendored

File diff suppressed because one or more lines are too long

28
app/web/dist/bundle.js vendored

File diff suppressed because one or more lines are too long

2
app/web/dist/bundle.js.map vendored

File diff suppressed because one or more lines are too long

50
app/web/src/App.svelte

@ -911,9 +911,9 @@ @@ -911,9 +911,9 @@
async function loadRelayData() {
// Fetch user role for already logged in users
if (isLoggedIn) {
fetchUserRole();
await fetchUserRole();
}
fetchACLMode();
await fetchACLMode();
// Load sprocket configuration
loadSprocketConfig();
@ -1966,6 +1966,14 @@ @@ -1966,6 +1966,14 @@
// Fetch user role/permissions
await fetchUserRole();
await fetchACLMode();
// Trigger event loading if currently on events tab
if (selectedTab === "events") {
hasAttemptedEventLoad = false;
const authors =
showOnlyMyEvents && userPubkey ? [userPubkey] : null;
loadAllEvents(true, authors);
}
}
function handleLogout() {
@ -3040,6 +3048,7 @@ @@ -3040,6 +3048,7 @@
on:openLoginModal={openLoginModal}
/>
{:else if selectedTab === "events"}
{#if isLoggedIn && (userRole === "read" || userRole === "write" || userRole === "admin" || userRole === "owner")}
<EventsView
{isLoggedIn}
{userRole}
@ -3061,6 +3070,16 @@ @@ -3061,6 +3070,16 @@
on:filterApply={handleFilterApply}
on:filterClear={handleFilterClear}
/>
{:else if isLoggedIn && !userRole}
<div class="events-loading-permissions">
<div class="spinner"></div>
<p>Checking permissions...</p>
</div>
{:else}
<div class="permission-denied">
<p>Read, write, admin, or owner permission required to view events.</p>
</div>
{/if}
{:else if selectedTab === "blossom"}
{#key $relayUrl}
<BlossomView
@ -3851,10 +3870,9 @@ @@ -3851,10 +3870,9 @@
background-color: var(--bg-color);
color: var(--text-color);
display: flex;
align-items: flex-start;
align-items: center;
justify-content: flex-start;
flex-direction: column;
display: flex;
}
.welcome-message {
@ -4797,4 +4815,28 @@ @@ -4797,4 +4815,28 @@
.change-relay-btn:hover {
background: #00acc1;
}
/* Centered permission/login prompts within main-content */
.events-loading-permissions,
.permission-denied,
.access-denied {
margin: auto;
text-align: center;
color: var(--text-color);
}
.main-content :global(.login-prompt),
.main-content :global(.permission-denied) {
margin: auto;
}
.events-loading-permissions .spinner {
width: 24px;
height: 24px;
border: 2px solid var(--border-color);
border-top-color: var(--primary);
border-radius: 50%;
animation: spin 1s linear infinite;
margin: 0 auto 1em;
}
</style>

14
app/web/src/BlossomView.svelte

@ -38,6 +38,7 @@ @@ -38,6 +38,7 @@
$: canAccess = isLoggedIn && userPubkey;
$: isAdmin = currentEffectiveRole === "admin" || currentEffectiveRole === "owner";
$: displayBlobs = selectedAdminUser ? selectedUserBlobs : blobs;
// Track if we've loaded once to prevent repeated loads
let hasLoadedOnce = false;
@ -429,12 +430,7 @@ @@ -429,12 +430,7 @@
}
}
function getDisplayBlobs() {
if (selectedAdminUser) {
return selectedUserBlobs;
}
return blobs;
}
</script>
<svelte:window on:keydown={handleKeydown} />
@ -549,15 +545,15 @@ @@ -549,15 +545,15 @@
{/if}
{:else}
<!-- Normal blob list view (own files or selected user's files) -->
{#if isLoading && getDisplayBlobs().length === 0}
{#if isLoading && displayBlobs.length === 0}
<div class="loading">Loading blobs...</div>
{:else if getDisplayBlobs().length === 0}
{:else if displayBlobs.length === 0}
<div class="empty-state">
<p>{selectedAdminUser ? "No files found for this user." : "No files found in your Blossom storage."}</p>
</div>
{:else}
<div class="blob-list">
{#each getDisplayBlobs() as blob}
{#each displayBlobs as blob}
<div
class="blob-item"
on:click={() => openModal(blob)}

19
app/web/src/EventsView.svelte

@ -121,7 +121,6 @@ @@ -121,7 +121,6 @@
</script>
<div class="events-view-container">
{#if isLoggedIn && (userRole === "read" || userRole === "write" || userRole === "admin" || userRole === "owner")}
<div class="events-view-content" on:scroll={handleScroll}>
{#if filteredEvents.length > 0}
{#each filteredEvents as event}
@ -230,15 +229,6 @@ @@ -230,15 +229,6 @@
</div>
{/if}
</div>
{:else}
<div class="permission-denied">
<p>
❌ Read, write, admin, or owner permission required to view all
events.
</p>
</div>
{/if}
{#if isLoggedIn && (userRole === "read" || userRole === "write" || userRole === "admin" || userRole === "owner")}
<div class="events-view-footer">
<!-- Filter Builder Slide-up Panel -->
<div class="filter-panel" class:open={showFilterBuilder}>
@ -307,7 +297,6 @@ @@ -307,7 +297,6 @@
</div>
</div>
</div>
{/if}
</div>
<style>
@ -554,14 +543,6 @@ @@ -554,14 +543,6 @@
}
}
.permission-denied {
text-align: center;
padding: 2em;
background-color: var(--card-bg);
border-radius: 8px;
border: 1px solid var(--border-color);
color: var(--text-color);
}
.events-view-footer {
position: relative;

4
pkg/blossom/handlers.go

@ -183,9 +183,11 @@ func (s *Server) handleUpload(w http.ResponseWriter, r *http.Request) { @@ -183,9 +183,11 @@ func (s *Server) handleUpload(w http.ResponseWriter, r *http.Request) {
// Optional authorization validation (do this BEFORE ACL check)
// For upload, we don't pass sha256Hash because upload auth events don't have 'x' tags
// (the hash isn't known at auth event creation time)
if r.Header.Get(AuthorizationHeader) != "" {
authHeader := r.Header.Get(AuthorizationHeader)
if authHeader != "" {
authEv, err := ValidateAuthEvent(r, "upload", nil)
if err != nil {
log.W.F("blossom upload: auth validation failed: %v", err)
s.setErrorResponse(w, http.StatusUnauthorized, err.Error())
return
}

2
pkg/version/version

@ -1 +1 @@ @@ -1 +1 @@
v0.58.6
v0.58.7

Loading…
Cancel
Save