Commit Graph

210 Commits

Author SHA1 Message Date
Julien Calixte
3e9418285f refactor(notes): let mobile notes size to content 2026-04-29 11:09:31 +02:00
Julien Calixte
17f015b686 fix(notes): wait for stacked note element before scrolling on mobile
A single nextTick is not enough for a freshly added stacked note to be
in the DOM, so the mobile scroll target was computed against a null
element. Poll with requestAnimationFrame (mirroring scrollToHashInNote)
and use offsetTop, with an (index + 1) * height fallback.
2026-04-29 10:52:07 +02:00
Julien Calixte
adb1bd5945 fix: fix height on mobile 2026-04-29 10:34:46 +02:00
Julien Calixte
cf5567de7c refactor(notes): use options object for renderCodeFile params 2026-04-27 20:36:46 +02:00
Julien Calixte
9d6f70546e feat(notes): render code files with Shikiji syntax highlighting
Non-markdown files opened as stacked notes are now highlighted using
the existing markdown-it-shikiji pipeline (4-backtick fence wrapping)
with a h1 filename heading. Edit controls are hidden for code files.
Adds alloy language grammar and a fileLanguage utility mapping
extensions to Shikiji language IDs.
2026-04-27 19:57:15 +02:00
Julien Calixte
812f393283 design: reduce padding for pre in tabs 2026-04-27 18:22:48 +02:00
Julien Calixte
37b39a6d96 design: box for tabs instead 2026-04-27 15:34:12 +02:00
Julien Calixte
df8bda0130 feat(markdown): render tabs as DaisyUI radio input pattern
Use @mdit/plugin-tab custom renderers to emit DaisyUI tabs-lift
structure (radio inputs + tab-content divs) instead of unstyled
default output. CSS-driven, no JS required.
2026-04-27 15:28:10 +02:00
Julien Calixte
74491a45a9 fix(repoList): prevent duplicate entries from concurrent loadMore calls
Add isLoading guard so concurrent fetches are rejected, and include
isLoading in canLoadMore so vInfiniteScroll waits before firing again.
2026-04-27 10:33:31 +02:00
Julien Calixte
da4fada8a1 fix(repoList): handle Bad credentials error from GitHub API
Catch 401 responses in useRepos loadMore and expose hasCredentialError,
then show a sign-in prompt in RepoList instead of an unhandled rejection.
2026-04-27 10:32:37 +02:00
Julien Calixte
836b480ea6 fix(navigation): resolve clicked anchor when target is a nested element
A click on a child of an <a> (e.g. nested <strong>, <em>, <code>, icon)
made event.target a non-anchor, so getAttribute('href') returned null
and the handler bailed without preventDefault. The browser then
performed the native navigation, which for relative links like
'../note.md' resolved against the current /:user/:repo URL and the SPA
re-routed treating the destination as a new repo.
2026-04-26 13:58:48 +02:00
Julien Calixte
181ffd1e5c feat(navigation): smooth scroll for in-note anchor links
Pure-fragment links (#heading) used to fall through to the browser's
default jump. Handle them in the click listener and scope the lookup
to the same stacked note so identical heading ids in other notes
don't win, with smooth scroll behavior to match cross-note anchors
into already-stacked notes.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-26 09:59:12 +02:00
Julien Calixte
c00065ce4a refactor(navigation): scrollToFocusedNote takes an options object
Smooth-scroll for the anchor jump when the target note is already
stacked, instant otherwise. While threading the new flag, the four
positional params got hard to read, so collapse them into
{ noteId, notes, hash, smoothHash } and update all call sites.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-26 09:56:32 +02:00
Julien Calixte
4ce8c30649 fix(navigation): support anchor fragments in note links
Links like `path/to/note.md#heading` previously errored with "Note not
found" because the full href (including `#hash`) was matched against
file paths. Split the fragment off in the link handler, plumb it through
the event bus, and scroll the matching heading into view once the
target note is in place. Headings now get GitHub-style ids via
markdown-it-anchor + github-slugger so the anchors actually exist.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-26 09:40:30 +02:00
Julien Calixte
e03ff49764 fix(mobile): restore overflow-y and unstick readme on vertical scroll
- Restore explicit overflow-y:auto on #main-app for mobile (removed in
  63f5d64) — implicit coercion from overflow-x:auto is not reliable in
  all Safari/WebKit versions.
- Override position:sticky on .readme to position:relative on mobile.
  The desktop sticky (left:0) is correct for horizontal scroll, but on
  mobile vertical scroll it pinned the 100dvh-tall readme across the
  entire viewport, hiding all stacked notes behind it.
2026-04-24 23:42:22 +02:00
Julien Calixte
19495ddf0c feat(scroll): use smooth scrollTo instead of direct property assignment 2026-04-23 18:07:44 +02:00
Julien Calixte
63bc3f4d5d fix(mobile): scroll #main-app instead of body on mobile
body/html have overflow:hidden so scrollTop is a no-op on them.
#main-app is the actual scroll container; use overflow-y:auto on
mobile and target it directly in scrollToNote and the scroll listener.
2026-04-23 18:01:30 +02:00
Julien Calixte
449a16f791 fix(layout): prevent document-level scroll-y when stacked notes overflow
Contain horizontal overflow within #main-app instead of leaking to the
document, which caused a horizontal scrollbar to consume viewport height
and trigger an unwanted vertical scrollbar. Also fix note pane height
to use 100% instead of 100vh, and switch useResizeContainer to minWidth
so the flex container can grow when the window is wider than the notes.
Add a window resize listener to keep the value accurate on resize.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-22 23:52:03 +02:00
Julien Calixte
8d9134a062 perf: cache repo list with 20-minute stale time
Hoist useRepos state to module scope so all callers share one instance, and skip re-fetching until data is older than 20 minutes.
2026-04-06 14:59:12 +02:00
Julien Calixte
006cd63388 feat: paginate repo list with infinite scroll
Load 30 repos at a time instead of 100 at once, showing data sooner.
Adds v-infinite-scroll to RepoList.vue to fetch subsequent pages on scroll.
2026-04-05 11:56:36 +02:00
Julien Calixte
b003a3e008 perf: move PouchDB/IndexedDB operations to a Web Worker
All database reads and writes now run off the main thread via a
dedicated worker, eliminating IndexedDB overhead from the frame budget.

- Create data.worker.ts exposing the Data class via Comlink
- Refactor data.ts to export a Comlink-wrapped proxy and a standalone
  generateId() pure function (workers can't expose sync methods cleanly)
- Update all 10 call sites to import generateId directly instead of
  calling data.generateId()

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-04 11:27:45 +02:00
Julien Calixte
52d7c84bd0 perf: prevent FPS drops during navigation in FluxNoteView
- Narrow backlinks watcher from entire store to store.files only,
  reducing trigger count from ~8 to 2 per navigation
- Defer computation start by 300ms so it runs after the 250ms view
  transition animation completes
- Yield to the browser between each file iteration using
  scheduler.yield() (with setTimeout fallback) to avoid blocking frames

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-04 11:14:02 +02:00
Julien Calixte
20e9538983 feat: mv profile to footer 2026-03-28 20:24:08 +01:00
Julien Calixte
5f48aa5690 chore: lint and fmt 2026-03-28 09:38:55 +01:00
Julien Calixte
32f79785a8 fix: prevent stacking a duplicate of the main note when clicking a self-link 2026-03-21 22:59:10 +01:00
Julien Calixte
ddabe5082d feat: show skeleton loaders while ATProto identity resolves
- Show skeleton in PublicNoteView and StackedPublicNote while note
  content is pending author resolution
- Show skeleton h1 in PublicNoteListByDidView while author loads
- Show skeleton in SignInAtproto until auth state is known
- Load cached session from IndexedDB before OAuth restore so the
  homepage resolves immediately without waiting for network
2026-03-19 18:12:52 +01:00
Julien Calixte
944b128894 feat: add icons, better suited than emojis 2026-03-17 23:43:29 +01:00
Julien Calixte
163e3ee756 feat: shorten DID in public note URLs by stripping did:plc: prefix
URLs are now /pub/<base32id>/rkey instead of /pub/did:plc:<base32id>/rkey.
Non-plc DIDs keep their method prefix (e.g. web:example.com).
2026-03-17 01:33:51 +01:00
Julien Calixte
40c461e150 chore: move api to remanso.space 2026-03-17 00:53:58 +01:00
Julien Calixte
330bc5b41d fix: scroll to stacked note on title click
- Pass didrkey (with colons) instead of classNameId to scrollToFocusedNote in StackedPublicNote, so findIndex matches the URL-stored ID
- Revert includes() to strict === in findIndex for semantic correctness
2026-03-16 18:49:21 +01:00
Julien Calixte
e9f37a9b8e fix: preserve search params when clearing OAuth callback hash 2026-03-10 16:10:08 +01:00
Julien Calixte
97c6f01e1c fix: skip following feed fetch when all tab is active 2026-03-10 16:06:35 +01:00
Julien Calixte
cb15eac854 feat: use POST /notes/feed for following tab with server-side DID filtering 2026-03-10 15:53:25 +01:00
Julien Calixte
9b6bc62044 feat: add following tabs 2026-03-10 15:44:35 +01:00
Julien Calixte
c721338dc0 fix: atproto oauth dev redirect, tab isolation, and concurrent load guard
- Use buildLoopbackClientId(window.location) for dev to include port in redirect URI
- Bind Vite dev server to 127.0.0.1 explicitly
- Remove scope override in signInRedirect (use metadata default)
- Clear OAuth callback params from URL after session restore
- Replace follows badge with DaisyUI tabs (All / Following)
- Use separate PublicNoteList instances per tab to isolate v-infinite-scroll state
- Add isLoading guard in onLoadMore to prevent concurrent fetches
2026-03-10 14:18:41 +01:00
Julien Calixte
8843d67a80 feat: create atproto oauth login 2026-03-10 12:27:35 +01:00
Julien Calixte
1dffab12df fix: no : in class names 2026-02-21 19:37:36 +01:00
Julien Calixte
1ad59addf0 fix: note class name 2026-02-19 23:07:45 +01:00
Julien Calixte
801832c6e5 feat: handle absolute internal links for stacked notes 2026-02-19 21:32:37 +01:00
Julien Calixte
8da5dcc50f fix: scroll both body and documentElement for cross-browser compatibility 2026-02-19 19:19:49 +01:00
Julien Calixte
4a06c11b0a fix: use window scroll API for cross-browser compatibility (Safari) 2026-02-19 19:03:06 +01:00
Julien Calixte
5bad66884f fix: scroll to note 2026-02-19 17:36:44 +01:00
Julien Calixte
103b23884f refacto: use microcosm endpoint and change types 2026-02-17 09:30:27 +01:00
Julien Calixte
f017b4f0ff fix: remove frontmatter content before rendering 2026-02-17 01:12:47 +01:00
Julien Calixte
1644f241d4 chore: fix ts warning 2026-02-15 21:21:56 +01:00
Julien Calixte
8e754021bd fix: better mobile usage 2026-02-15 19:43:22 +01:00
Julien Calixte
ff8795581e feat: add public notes by author page
Extract note-list fetching into usePublicNoteList composable, add
/pub/:did route to view notes from a single author, and make author
aliases clickable links in both the note list and note view.
2026-02-15 13:18:59 +01:00
Julien Calixte
bf73f08cb2 refactor: unify NOTE_WIDTH constant with --note-width CSS variable
Read note width from the CSS custom property at runtime (cached on first
call) instead of duplicating the value in a JS constant.
2026-02-15 09:09:20 +01:00
Julien Calixte
b03626bb1a fix: note width. TODO: sync NOTE_WIDTH js constant to css variable --note-width 2026-02-15 08:40:58 +01:00
Julien Calixte
5c70232fba deps: upgrade 2026-02-15 08:00:11 +01:00