Commit Graph

26 Commits

Author SHA1 Message Date
mroxso
014fb2a9a7 Place notification count beside bell 2026-09-06 22:26:36 +02:00
mroxso
6cd5914243 Keep notification badge within menu bar 2026-09-06 22:25:36 +02:00
mroxso
cd85dcf83c Fix notification bell triggers 2026-09-06 22:24:22 +02:00
copilot-swe-agent[bot]
547e25d7dd Fix notification event selection and account read-state sync
Co-authored-by: mroxso <24775431+mroxso@users.noreply.github.com>
2026-09-06 20:18:25 +00:00
mroxso
8824bb759f Add notifications center 2026-09-06 22:03:29 +02:00
mroxso
179d3682f8 feat: bookmarks for notes and articles (NIP-51) (#29)
* feat: bookmarks for notes and articles (NIP-51)

Adds a Bookmarks app backed by a kind 10003 NIP-51 bookmark list:
- BookmarkButton toggles a note (`e` tag) or article (`a` tag) in and
  out of the signed-in user's list, reading it back before publishing
  so an update never clobbers other entries — the same whole-list
  replacement trap follow lists have.
- Wired into NoteCard's action row and the Reader's article toolbar.
- The new Bookmarks app lists saved notes and articles, opening
  articles back in the Reader.

Closes #21

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BYiUtZMQeA5RHggQw73wto

* fix: address review feedback and add a Bookmarked tab to the Reader

Per review:
- useToggleBookmark now fetches the bookmark list fresh from relays
  right before writing instead of trusting the query cache (60s
  staleTime), which could otherwise clobber concurrent edits from
  another tab or device.
- The article BookmarkButton only renders when the article actually
  has a `d` tag, instead of falling back to an unresolvable
  "kind:pubkey:" address.
- Bookmarked note/article ids are filtered for a non-empty tag value
  before use, and article addresses are parsed properly (kind,
  author, `d`) instead of a naive split(':')[2] — the relay query is
  now also constrained by kind and author, not just `d`, and
  identifiers containing ':' round-trip correctly.
- BookmarkButton sets type="button" so it can't misbehave as a form
  submit button.

Per a reviewer comment: added a "Recent" / "Bookmarked" tab to the
Reader's sidebar (src/apps/articles/index.tsx) so bookmarked articles
are reachable without leaving the app — the dedicated Bookmarks app
stays as-is. Both now share useMyBookmarkedArticles from
src/hooks/useBookmarks.ts rather than duplicating the address-parsing
logic.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BYiUtZMQeA5RHggQw73wto

* fix: reject empty-identifier addresses and surface bookmark load errors

Per review:
- parseAddress() now rejects an empty d-identifier as malformed
  (e.g. "30023:<pubkey>:") instead of producing a "#d: ['']" relay
  query and an unopenable bookmark.
- useMyBookmarkedArticles() filters out matched events with empty
  content, the same non-renderable criteria the Reader's own list
  uses, so a broken/blank article can't land in the Bookmarked view.
- BookmarksApp now distinguishes "the query failed" from "there are
  no bookmarks" — React Query leaves data undefined in both cases, so
  a relay/network failure no longer reads as an empty list.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BYiUtZMQeA5RHggQw73wto

---------

Co-authored-by: highperfocused <highperfocused@pm.me>
Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-06 18:45:21 +02:00
mroxso
809077d054 fix: open the picked app from the mobile app switcher (#18)
The switcher only focused the window it was given. `FOCUS_WINDOW` raises
and focuses but never un-minimizes, while the mobile shell renders a
window only when it is focused *and* not minimized — so picking a
minimized app updated the URL and the document title (both follow
`focusedId`) while the home screen stayed on screen.

Restore a minimized window instead of merely focusing it, the same way the
menu bar's Window menu and the command palette already do.

Fixes #15


Claude-Session: https://claude.ai/code/session_01Trku191Ww2a2YmDWQF3fTS

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
2026-09-06 12:09:21 +02:00
mroxso
dc1701afd9 fix: stop the render loop that crashes the mobile app switcher (#17)
`mapWindow` flagged the state as changed whenever the target window id
matched, even when the updater handed the very same window object back.
`SET_TITLE` is guarded against a no-op title, but that guard was defeated:
the reducer still returned a fresh state object, so the context value
changed, every consumer re-rendered, and each app's `setTitle` effect —
keyed on a `setTitle` callback that the mobile shell re-created on every
render — dispatched `SET_TITLE` again. That loop ran continuously while an
app was open on mobile; opening the app-switcher Sheet on top of it made
Radix re-attach its composed refs on every one of those renders until
React bailed out with "Maximum update depth exceeded" and the
ErrorBoundary took over.

Only count a window as changed when the updater actually returned a
different object, and memoise the mobile shell's `setTitle`/`setParams`
per window, matching what `WindowFrame` already does.

Fixes #14


Claude-Session: https://claude.ai/code/session_01Trku191Ww2a2YmDWQF3fTS

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
2026-09-06 12:09:11 +02:00
mroxso
cde5be0874 fix: keep a window in place when focus switches (#16)
Raising a window made it visibly jump to the top-left corner and animate
back. Two things combined: the enter keyframes animated `transform`, which
overrode the inline `translate3d` a window's position is applied with, and
the window layer rendered the z-sorted list, so focusing a window moved its
DOM node and made the browser replay that animation.

Animate the standalone `scale` property instead — it composes with the
inline transform rather than replacing it — scope the animation to
`.os-window` (it was hitting every child of the layer, including the snap
preview, which is positioned the same way), and render windows in their
stable creation order, since the inline `z-index` already handles stacking.

Fixes #13


Claude-Session: https://claude.ai/code/session_01Trku191Ww2a2YmDWQF3fTS

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
2026-09-06 12:09:00 +02:00
mroxso
949a551492 feat: New Web OS design (#12)
* new web os frontend

* add docs

* Add CNAME and restore NIP-05 nostr.json for GitHub Pages

The Pages custom domain (layer.systems) is only stored in repo settings;
a CNAME file in the build output makes it survive Pages reconfiguration.
Restore public/.well-known/nostr.json, which this branch had dropped —
removing it would break the existing NIP-05 identifiers on layer.systems.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014YtQoCzkP7Bo8nruhxojPi

* Ignore eslint and tsc build caches

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014YtQoCzkP7Bo8nruhxojPi

* Rebrand page title and metadata to LAYER.systems

The site ships on layer.systems, so the document title, meta and OG
description, and the web manifest now carry that name instead of
"Nostr OS". OsShell sets the title at runtime, so it is updated too —
otherwise the tab would fall back to the old branding after hydration.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014YtQoCzkP7Bo8nruhxojPi

* Rename remaining visible "Nostr OS" strings to LAYER.systems

Covers the About window heading, the mobile shell header and the app
icon's aria-label, so the visible branding matches the page title.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014YtQoCzkP7Bo8nruhxojPi

---------

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
2026-09-06 11:37:43 +02:00
0492427582 fix: add DashboardExport page and integrate into routing and sidebar navigation 2026-01-04 20:40:46 +01:00
d464e8a44c fix: enhance layout and overflow handling in EventExplorer and DashboardEvents components 2026-01-01 21:00:37 +01:00
8f75803797 fix: add overflow handling to charts and dashboard components for better layout 2026-01-01 21:00:30 +01:00
0a0c4adb09 fix: update terminology for clarity in DashboardStats and RecentActivityChart components 2025-12-28 22:32:52 +01:00
af94fa7a3b fix: update chart color variables to use HSL format for consistency 2025-12-28 22:19:52 +01:00
7c8d2cff31 fix: update color variables for consistency in RecentActivityChart and CSS 2025-12-28 22:15:40 +01:00
91d51a35f9 feat: add RecentActivityChart component to Dashboard 2025-12-28 22:13:13 +01:00
686c31aca8 feat: add DashboardEvents page and integrate EventExplorer component 2025-12-28 21:48:13 +01:00
42e234105b fix: remove modal prop from DropdownMenu in AccountSwitcher component 2025-12-28 15:10:30 +01:00
3ca5966d03 feat: add theme selection toggle to AccountSwitcher component 2025-12-28 15:04:30 +01:00
462741c3bd feat: add dashboard navigation to AccountSwitcher component 2025-12-28 14:43:12 +01:00
1972c1e27c refactor: comment out unused imports and effect in NostrSync component 2025-12-28 14:40:15 +01:00
da73c6091b feat: add relay management drawer to AccountSwitcher component 2025-12-28 14:34:01 +01:00
ecf597d072 feat: refactor EventKindsChart to use current user context and update chart colors 2025-12-28 14:24:40 +01:00
098626fbea feat: add Dashboard page with user statistics and recent activity components 2025-12-28 13:54:11 +01:00
a833997770 initial code commit 2025-12-27 21:42:31 +01:00