@openparachute/app 0.22.5 → 0.22.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +148 -0
- package/dist/.parachute/info +1 -1
- package/dist/assets/{Account-BhmA30V5.js → Account-DYfzZj5S.js} +1 -1
- package/dist/assets/{Activity-BgJa7Woi.js → Activity-CKF0o1vW.js} +1 -1
- package/dist/assets/{AddVault-BWa_-QjM.js → AddVault-DKBqKeyq.js} +1 -1
- package/dist/assets/{AddVaultChooser-B3ElIlza.js → AddVaultChooser-BW2Q-Yue.js} +1 -1
- package/dist/assets/{AddVaultCreate-DKJfYFJ1.js → AddVaultCreate-CtO9yrS5.js} +1 -1
- package/dist/assets/{Calendar-DUwSvnCY.js → Calendar-DFuh1M3x.js} +1 -1
- package/dist/assets/{CheckEmail-BQYQLTLL.js → CheckEmail-CIv1Gt1o.js} +1 -1
- package/dist/assets/{ConnectAI-DCtARp-w.js → ConnectAI-BL20KQ5Y.js} +1 -1
- package/dist/assets/{DayView-nficJMEc.js → DayView-Dr2pAVmN.js} +1 -1
- package/dist/assets/{Export-DNAoKjAn.js → Export-BynzqvGJ.js} +1 -1
- package/dist/assets/{Import-CoFeXNMx.js → Import-6SmwJlgO.js} +1 -1
- package/dist/assets/{NoteEditor-DtrdRbqx.js → NoteEditor-OPipzN_Z.js} +1 -1
- package/dist/assets/NoteNew-Dy1AbHxm.js +8 -0
- package/dist/assets/{NoteRenderer-Dl9X9uRt.js → NoteRenderer-BXeTxHnB.js} +1 -1
- package/dist/assets/NoteView-B0eNsUUX.js +3 -0
- package/dist/assets/{OAuthCallback-Dj26N8oJ.js → OAuthCallback-D35vvyoO.js} +1 -1
- package/dist/assets/{PinArchiveButtons-BXZFiW-i.js → PinArchiveButtons-DyFdYBrq.js} +1 -1
- package/dist/assets/Settings-UmrOUQH_.js +1 -0
- package/dist/assets/{TagPage-q7PgbEHn.js → TagPage-B7bGWyY4.js} +1 -1
- package/dist/assets/{TagSchemaEditor-DIHppYmj.js → TagSchemaEditor-Bas3UMIJ.js} +1 -1
- package/dist/assets/{Tags-BqJ9vWM5.js → Tags-CTF2n8-H.js} +1 -1
- package/dist/assets/{VaultGraph-CaiNmEtX.js → VaultGraph-BLefh0Zh.js} +2 -2
- package/dist/assets/{Vaults-CTsUsDH8.js → Vaults-tXitT9QI.js} +1 -1
- package/dist/assets/{ViewNew-BegTqdOq.js → ViewNew-DRZyYhEC.js} +1 -1
- package/dist/assets/ViewSurface-DzU1BogH.js +1 -0
- package/dist/assets/{Welcome-CN4Zh9jP.js → Welcome-yAs98HfO.js} +1 -1
- package/dist/assets/{WizardShell-ZqrzQKxp.js → WizardShell-B0Fjh0Vt.js} +1 -1
- package/dist/assets/{attachment-upload-l7qA8_xw.js → attachment-upload-B8YiOVGU.js} +1 -1
- package/dist/assets/{history-ByMClxJV.js → history-Ce29a331.js} +1 -1
- package/dist/assets/index-H6VNro-x.js +66 -0
- package/dist/assets/index-rEtUY3V3.css +1 -0
- package/dist/assets/{provenance-B6WFYTWW.js → provenance-DDSHYRnT.js} +1 -1
- package/dist/assets/{react-force-graph-2d-BMU3lxLC.js → react-force-graph-2d-G4yaBBi0.js} +1 -1
- package/dist/assets/{transcribe-default-LVAxyzpn.js → transcribe-default-B7i-j3pr.js} +1 -1
- package/dist/assets/{useAttachmentUploader-C3UnTg01.js → useAttachmentUploader-C78HTrMx.js} +1 -1
- package/dist/index.html +2 -2
- package/dist/sw.js +1 -1
- package/package.json +1 -1
- package/dist/assets/NoteNew-C0DMe5Q8.js +0 -8
- package/dist/assets/NoteView-B2QH25fP.js +0 -3
- package/dist/assets/Settings-BuXl91ig.js +0 -1
- package/dist/assets/ViewSurface-ClCtZW0N.js +0 -1
- package/dist/assets/index-CaleIHD8.css +0 -1
- package/dist/assets/index-Dwo2xe8_.js +0 -66
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,151 @@
|
|
|
1
|
+
## [0.22.9] - 2026-07-27
|
|
2
|
+
|
|
3
|
+
**A 26-minute voice memo used to render as three "Transcript pending" placeholders with only one transcript actually written back, out of order — while all three sat complete in attachment metadata. Nothing was lost; the write-back was broken.**
|
|
4
|
+
|
|
5
|
+
Root cause: the app sent `segment_index` nested under a `metadata` object; both doors read it top-level. Silently dropped, on Cloud and self-host alike. With `segment_index` absent, the vault worker treated three segments as three independent memos racing to write one note behind one shared completion flag — first to commit appends and clears the flag, the other two see "done" and no-op. **On self-host, the fix here is the app-side half only** — the vault worker's own handling of `segment_index` needs its own fix (`parachute-vault` #630, in review) before a self-host operator's own long memos actually land correctly; Cloud gets the full fix in this release.
|
|
6
|
+
|
|
7
|
+
- **`segment_index` now rides at the TOP level of the attach body**, all the way from `buildVoiceCapturePlan` through `PendingLinkAttachment` through `linkAttachment`'s wire body — nowhere nested under `metadata`. Fixes the Cloud door outright (it already read `body.segment_index`); self-host gets the same wire-shape fix, pending the vault-side companion above. A new test asserts the actual JSON body sent over the wire, not just the in-memory plan object — that's exactly the layer where the bug lived and no existing test looked.
|
|
8
|
+
- **Recorder now requests 32 kbps** (`audioBitsPerSecond`, a browser hint — some ignore it). Measured from Aaron's actual files with ffprobe: the previous browser default was **128.8 kbps** (≈0.92 MiB/min) — four times what the pipeline was sized for. That made Cloud's 25 MB per-attachment ceiling bite at **~27 minutes** instead of the ~109 the docs assumed a capture could reach. 32 kbps is excellent for speech and pushes that ceiling back out to **~109 minutes**.
|
|
9
|
+
- **Segment rollover moved from 10 to 30 minutes, with a 20 MB size cap that preempts it.** Aaron's walks run 20–30 minutes, so he hit the old boundary every time. At the intended 32 kbps a 30-minute segment is ~6.9 MB — 3.6x under the Cloud ceiling and 2x under the ~60-minute Whisper inference wall (a duration limit no bitrate change moves — the reason not to push this past 45). But `audioBitsPerSecond` is only a hint: if a browser ignores it, a full 30 minutes at the un-honored ~128.8 kbps default is ~27.6 MB — **over** the Cloud ceiling, reproducing this same PR's bug from a new cause. Rolling early at 20 MB (whichever ceiling — time or size — hits first) keeps every segment safe unconditionally, regardless of whether the hint took effect.
|
|
10
|
+
|
|
11
|
+
Every new/changed assertion was watched failing first, including a scratch reproduction of the real bug against pre-fix `queue.ts` (confirmed it actually sent `{ metadata: { segment_index: 0 } }`, not `{ segment_index: 0 }`, before any production code changed), and the size-cap test against pre-fix `segmented-recorder.ts` (confirmed it could not roll early at all).
|
|
12
|
+
|
|
13
|
+
## [0.22.7] - 2026-07-27
|
|
14
|
+
|
|
15
|
+
**GROUP BY and FIELDS now explain what a field's TYPE means for the menu, instead of offering 9 bare names and letting you find out the hard way.**
|
|
16
|
+
|
|
17
|
+
The other half of Aaron's complaint from his own vault — "how we're doing the
|
|
18
|
+
filtering, how we're selecting the schemas, um, both in the filter and in the
|
|
19
|
+
tag page." Judged against `bigvault`'s richest-schema tag, `#project` (9
|
|
20
|
+
declared fields: 3 enum, 1 string, 1 number, 1 boolean, 3 date):
|
|
21
|
+
|
|
22
|
+
| | before | after |
|
|
23
|
+
| --- | --- | --- |
|
|
24
|
+
| GROUP BY menu on `#project` | 9 bare names, undifferentiated — date fields included, each grouping into one column per distinct date | 3 value-bearing fields (a values preview: `seed · active · paused…`), 3 free-text/number fields under an honest "one column per value" heading, **3 date fields excluded outright** with a note pointing at the Calendar lens |
|
|
25
|
+
| FIELDS menu row | plain checkbox, no type cue | a type glyph per row — `●` values, `📅` date, `Aa` text, `#` number |
|
|
26
|
+
|
|
27
|
+
- **No hardcoded field vocabulary — selection is by TYPE, never by name.**
|
|
28
|
+
A `field-presets.ts` naming `status`/`priority`/`due` was deleted from this
|
|
29
|
+
repo for exactly this reason (Aaron, 2026-07-25: "I don't think any of these
|
|
30
|
+
should be hard coded... we don't really need to be opinionated on this").
|
|
31
|
+
The sectioning and glyphs both key off `resolveControlKind` — the same
|
|
32
|
+
type→kind dispatch `FieldValueControl` already uses to pick an editor —
|
|
33
|
+
never a name.
|
|
34
|
+
- **`ControlPill`** gained two small generic capabilities (not a GROUP-BY-only
|
|
35
|
+
hack): headed **sections** of option rows, and a per-option dim **hint**
|
|
36
|
+
line. Both are opt-in; every existing flat-options caller (the lens
|
|
37
|
+
switcher, By-date) renders exactly as before.
|
|
38
|
+
- **A long hint no longer crushes the field's own name.** Label and hint
|
|
39
|
+
shared `flex-shrink` on the same row, so proportional flex math let a long
|
|
40
|
+
enum preview (`home · craft · community · money`) claim the bigger
|
|
41
|
+
absolute cut, squeezing a short field name toward nothing — `status` and
|
|
42
|
+
`area` rendered as `st…`/`ar…` on `bigvault`'s `#project`. The label now
|
|
43
|
+
holds its width; only the hint shrinks and truncates — but ONLY on hinted
|
|
44
|
+
rows. A flat, no-hint row (the By-date pill's user-defined field names)
|
|
45
|
+
keeps its original `truncate`, since there it's the only thing in the row
|
|
46
|
+
competing for space — holding it unconditionally would let a long name
|
|
47
|
+
(`estimated_completion_date`) overflow the menu's fixed width into
|
|
48
|
+
horizontal scroll instead of a clean ellipsis.
|
|
49
|
+
- **The legacy-value unshift still holds**, generalized: a `group_by` naming
|
|
50
|
+
a field this menu doesn't offer — undeclared, or (since this PR) date-typed
|
|
51
|
+
— still renders as selected via an unheaded lead row, never silently
|
|
52
|
+
dropped.
|
|
53
|
+
- **A tag whose only fields are date-typed** gets the honest "date fields
|
|
54
|
+
plot on the Calendar lens" note rather than a false "no fields yet" invite
|
|
55
|
+
— the invite is reserved for a tag with genuinely zero declared fields.
|
|
56
|
+
|
|
57
|
+
Filter state, URL params, and the save format are untouched — presentation
|
|
58
|
+
only. Every new test was watched failing before the fix (stub the type
|
|
59
|
+
dispatch, the exclusion, the preview, or the section/hint rendering out;
|
|
60
|
+
confirm each goes red for the stated reason; restore).
|
|
61
|
+
|
|
62
|
+
## [0.22.8] - 2026-07-27
|
|
63
|
+
|
|
64
|
+
**The Filters panel no longer pushes the results list off the bottom of the
|
|
65
|
+
screen — it's an overlay now, and the active filters stay visible when it's
|
|
66
|
+
closed.**
|
|
67
|
+
|
|
68
|
+
Aaron's complaint, second half: "how we're doing the filtering, how we're
|
|
69
|
+
selecting the schemas... both in the filter and in the tag page." #119 fixed
|
|
70
|
+
the tag picker; a schema-menus PR fixed GROUP BY/FIELDS. This is the part that
|
|
71
|
+
actually explains why filtering "felt bad": the panel rendered in flow, so
|
|
72
|
+
opening it pushed the whole list down by its own height.
|
|
73
|
+
|
|
74
|
+
| | before | after |
|
|
75
|
+
| --- | --- | --- |
|
|
76
|
+
| Result rows visible, filter open, 1440×900 | **0** — first row landed at y=1174 | 5+ rows read clearly; the popover is a compact 26rem dropdown anchored under the trigger, list position on-screen is byte-for-byte unchanged (same DOM node, same coordinates) whether the panel is open or closed |
|
|
77
|
+
| Phone filter UI height | 945px, in flow, on an 844px screen | a bottom sheet capped at 70dvh (591px) over a scrim; the list is still live directly behind it |
|
|
78
|
+
| Active filters when the panel is closed | invisible (a bare "2" badge on the Filters button, no detail) | a chips row: `#tag ×`, `match any/all ▾` (2+ tags), `title: prefix ×`, `archived shown ×`, `oldest first ×`, trailing `Save as view…` |
|
|
79
|
+
|
|
80
|
+
- **Overlay, not inline flow.** Lifted `FieldsControl`'s own scrim + `fixed`
|
|
81
|
+
bottom-sheet / `sm:absolute` popover dual verbatim — the same pattern
|
|
82
|
+
already shipping elsewhere in this app, not a second overlay idiom. Escape
|
|
83
|
+
and outside-tap close it, same as `FieldsControl`.
|
|
84
|
+
- **Chips row replaces the badge.** Presence depends only on filter state,
|
|
85
|
+
never on whether the panel is open, so it can't itself cause the list to
|
|
86
|
+
shift. Reuses `RefinementChip` (now shared between this surface and
|
|
87
|
+
`ViewSurface`'s own refinement bar) rather than inventing a second
|
|
88
|
+
dismissable-filter affordance.
|
|
89
|
+
- **Saved views, retired as a manager on this surface.** The per-row
|
|
90
|
+
rename/update/delete menu is gone from the Filters panel — "a Filters panel
|
|
91
|
+
shouldn't also be a view manager." What's left is a quiet, closed-by-default
|
|
92
|
+
"Saved filters ▸" disclosure: click a name to load it, same links as today.
|
|
93
|
+
Nothing about the vault notes themselves changed; managing them is a
|
|
94
|
+
different surface's job.
|
|
95
|
+
- **Panel contents are otherwise the same** — Refine (sort, archived, title
|
|
96
|
+
prefix, Untagged/Orphaned), the tag browser + match mode, the lazy Folders
|
|
97
|
+
accordion (fetch-on-open unchanged) — just stacked in a single column now
|
|
98
|
+
that the popover is 26rem instead of the old 52rem-wide inline section.
|
|
99
|
+
|
|
100
|
+
State model and URL params are untouched — `searchParamsToFilters` round-trips
|
|
101
|
+
exactly as before, so old links and legacy saved views keep working.
|
|
102
|
+
Presentation only, same discipline as #119. No live result count anywhere
|
|
103
|
+
(vault#626 still tracks the real one) — the pager's "Showing 1–50 of 50+"
|
|
104
|
+
stays the only number.
|
|
105
|
+
|
|
106
|
+
## [0.22.6] - 2026-07-27
|
|
107
|
+
|
|
108
|
+
**A typeahead for the tag picker, a shortlist instead of the whole list, and
|
|
109
|
+
`#capture` finally admits it has 951 notes, not 0.**
|
|
110
|
+
|
|
111
|
+
Aaron's complaint from his own vault: "a bunch of tags for something like my
|
|
112
|
+
vault where there's a lot." Measured against `bigvault` (50 tags / 2,600
|
|
113
|
+
notes, power-law distributed) rather than the ~15-tag fixture every test
|
|
114
|
+
vault had been using — the scale that let three earlier bugs ship in one
|
|
115
|
+
night ships this one too:
|
|
116
|
+
|
|
117
|
+
| | before | after |
|
|
118
|
+
| --- | --- | --- |
|
|
119
|
+
| Tag rows rendered on opening Filters | 39 (every collapsed-group row, uncapped) | **10** (shortlist), rest behind "All 50 tags ▸" |
|
|
120
|
+
| Finding `#plant` (5 notes, rank 35 of 39) | no way to type a tag name at all — a ~34-row visual scan | type `plan` (4 keystrokes) + Enter — no scrolling |
|
|
121
|
+
| `#capture` (622 + 304 + 25 + 0 = 951 notes across the family) | **`#capture 0`** | `#capture 951` |
|
|
122
|
+
|
|
123
|
+
- **Typeahead.** The picker gets the same "Filter tags…" box the `/tags`
|
|
124
|
+
directory page already had — name-contains match, count-ranked, Enter
|
|
125
|
+
toggles the top match. Autofocuses on desktop; deliberately not on phone,
|
|
126
|
+
where it would throw up the keyboard and cover the list.
|
|
127
|
+
- **Shortlist, not the whole list.** Selected tags first, then pinned, then
|
|
128
|
+
top-by-count, capped at 10 rows. Nothing is deleted — an "All N tags ▸"
|
|
129
|
+
disclosure underneath reveals today's grouped tree exactly as it rendered
|
|
130
|
+
before.
|
|
131
|
+
- **The family-count bug.** A collapsed family whose parent tag exists (e.g.
|
|
132
|
+
`#capture`, which tags zero notes directly but is the heaviest family in a
|
|
133
|
+
real vault once `capture/voice`, `capture/text`, and `capture/photo` count)
|
|
134
|
+
showed the *parent's own* count instead of the family total. It now shows
|
|
135
|
+
the total.
|
|
136
|
+
- **Typed tags get a `⊞ N` marker** (field count), sourced from
|
|
137
|
+
`useTagsWithSchema` — the same schema-bearing query the `/tags` page
|
|
138
|
+
already pays for, so this isn't a new round trip.
|
|
139
|
+
- **`PinnedTagsStrip` is gone.** Its pinned tags dissolve into the picker's
|
|
140
|
+
shortlist. The strip was also a latent trap: single-select-*replace* (and
|
|
141
|
+
it silently cleared the path-prefix filter) sitting directly above a
|
|
142
|
+
multi-select-*toggle* control that looked just like it.
|
|
143
|
+
|
|
144
|
+
Filter state and URL params are untouched — presentation only. Every new
|
|
145
|
+
test was watched failing before the fix (stub the change out, confirm red
|
|
146
|
+
for the stated reason, restore); the family-count regression test uses the
|
|
147
|
+
bigvault fixture's real numbers so it can't pass by accident.
|
|
148
|
+
|
|
1
149
|
## [0.22.5] - 2026-07-26
|
|
2
150
|
|
|
3
151
|
**A `%` in a name no longer breaks the page — and a subtler bug that nobody
|
package/dist/.parachute/info
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{r as m,u as N,g as M,j as e,a as A,L as j,b as $,c as T,s as O,l as k,m as q,d as Y,I as _,e as D,f as F,h as U,i as G,o as H,k as Q,n as X,p as z,S as I,q as C,B as J}from"./index-Dwo2xe8_.js";import{f as K,a as S}from"./provenance-B6WFYTWW.js";function fe(){const[t,s]=m.useState({kind:"loading"}),n=N(a=>a.identityEpoch);return m.useEffect(()=>{let a=!0;return(async()=>{let l;try{l=await M()}catch{a&&s({kind:"device"});return}a&&s(l.signed_in?{kind:"manager",email:l.email,username:l.username,csrf:l.csrf}:{kind:"device"})})(),()=>{a=!1}},[n]),e.jsxs("div",{className:"page-prose",children:[e.jsxs("header",{className:"mb-8",children:[e.jsx("h1",{className:"page-title",children:"Your parachute"}),e.jsx("p",{className:"mt-2 max-w-prose text-fg-muted",children:"Your account, plan, vaults, and connections — managed here."})]}),t.kind==="loading"?e.jsx("output",{"aria-live":"polite",className:"block py-10 text-center text-sm text-fg-dim",children:e.jsx("span",{className:"animate-pulse",children:"Loading your account…"})}):t.kind==="device"?e.jsx(me,{}):e.jsx(W,{email:t.email,username:t.username,csrf:t.csrf})]})}function W({email:t,username:s,csrf:n}){const a=$(),l=A(d=>d.getActiveVault()),c=N(d=>d.identityEpoch),i=T(),x=i.isPending?"loading":i.data??null,h=O(i.data),f=m.useCallback(()=>i.refetch(),[i.refetch]),[b,r]=m.useState("loading"),[o,g]=m.useState(null);m.useEffect(()=>{let d=!0;return k().then(y=>{d&&r(y.vaults)}).catch(y=>{q(y),d&&r("error")}),Y().then(y=>{d&&g(y)}),()=>{d=!1}},[c]);const u=m.useCallback(async()=>{try{const{vaults:d}=await k();r(d)}catch{r("error")}},[]);async function p(){try{await U(n)}finally{G(),a("/",{replace:!0})}}return e.jsxs("div",{className:"space-y-6",children:[e.jsx(Z,{email:t,username:s,summary:h,onSignOut:p}),e.jsx(te,{state:x,descriptor:o,onRetry:f,retrying:i.isFetching}),e.jsx(ue,{vaults:b,summary:h,onReload:u}),e.jsx(L,{hasActiveVault:!!l})]})}function Z({email:t,username:s,summary:n,onSignOut:a}){return e.jsx("section",{"aria-label":"Account",className:"card p-6 shadow-soft",children:e.jsxs("div",{className:"flex flex-wrap items-start justify-between gap-4",children:[e.jsxs("div",{className:"min-w-0",children:[e.jsx("p",{className:"eyebrow mb-1",children:"Signed in as"}),e.jsxs("div",{className:"flex flex-wrap items-center gap-x-3 gap-y-1",children:[e.jsx("p",{className:"break-words font-serif text-xl text-fg",children:t??s??"your account"}),e.jsx(ee,{summary:n})]})]}),e.jsx("button",{type:"button",onClick:a,className:"focus-ring shrink-0 text-sm text-fg-dim hover:text-accent",children:"Sign out"})]})})}function ee({summary:t}){if(!t)return null;const s=t.plan.trial_days_left;return typeof s=="number"?e.jsxs("span",{className:"chip border-transparent bg-sun-soft font-medium text-sun-ink",children:["Free trial · ",s===0?"ends today":`${s} day${s===1?"":"s"} left`]}):e.jsx("span",{className:"chip",children:t.plan.label})}function te({state:t,descriptor:s,onRetry:n,retrying:a}){return t===null||t!=="loading"&&t!=="error"&&!t.billing_enabled?null:e.jsxs("section",{"aria-label":"Plan & billing",className:"card p-6 shadow-soft",children:[e.jsx("h2",{className:"font-serif text-xl text-fg",children:"Plan & billing"}),t==="loading"?e.jsxs("div",{"aria-busy":"true",className:"mt-4 space-y-2.5",children:[e.jsx("div",{className:"skeleton h-4 w-3/5 rounded-md"}),e.jsx("div",{className:"skeleton h-4 w-2/5 rounded-md"})]}):t==="error"?e.jsxs("div",{className:"mt-4 text-center",children:[e.jsx("p",{className:"mb-1 font-serif text-lg text-fg",children:"Couldn't load your plan."}),e.jsx("p",{className:"mb-5 text-sm text-fg-muted",children:"A hiccup reaching your account — your plan hasn't changed."}),e.jsx("button",{type:"button",onClick:n,disabled:a,className:"btn btn-primary btn-touch",children:a?"Retrying…":"Retry"})]}):t.has_billing_customer?e.jsx(se,{summary:t}):e.jsx(oe,{summary:t,plans:(s==null?void 0:s.plans)??[]})]})}function se({summary:t}){const[s,n]=m.useState(!1),[a,l]=m.useState(null);async function c(){n(!0),l(null);try{const{url:i}=await z();window.location.assign(i)}catch(i){if(n(!1),i instanceof I){N.getState().markExpired();return}l("Billing isn't available right now.")}}return e.jsxs("div",{className:"mt-4",children:[e.jsx("p",{className:"text-sm text-fg-muted",children:R(t)}),e.jsx("button",{type:"button",onClick:c,disabled:s,className:"btn btn-primary btn-touch mt-4",children:s?"Opening…":"Manage plan & billing ↗"}),a?e.jsx(B,{text:a}):null]})}const v=["monthly","quarterly","yearly"],E={monthly:"Monthly",quarterly:"Quarterly",yearly:"Yearly"},ne={monthly:"/mo",quarterly:"/quarter",yearly:"/yr"},ae={monthly:1,quarterly:3,yearly:12};function le(t){var n,a;const s=new Set;for(const l of t)for(const c of v)(a=(n=l.intervals)==null?void 0:n[c])!=null&&a.available&&s.add(c);return v.filter(l=>s.has(l))}function V(t,s){return t.label?t.label:typeof t.price=="number"?`$${t.price}${ne[s]}`:null}function re(t){var s;for(const n of v){const a=(s=t.intervals)==null?void 0:s[n];if(a!=null&&a.available)return{interval:n,entry:a}}return null}function ie(t,s){if(!s||!t.intervals)return typeof t.price_month=="number"?`$${t.price_month}/mo`:null;const n=[];let a=!1,l=null;for(const i of v){const x=t.intervals[i];if(!(x!=null&&x.available))continue;i==="monthly"&&(a=!0);const h=V(x,i);if(h&&n.push(h),typeof x.price=="number"){const f=x.price/ae[i];l=l===null?f:Math.min(l,f)}}if(n.length===0)return null;const c=n.join(" · ");return a||l===null?c:`${c} — about $${Math.max(1,Math.round(l))}/mo`}function ce(t){if(t instanceof J)switch(t.code){case"already_subscribed":return"You're already subscribed — refresh to see your plan.";case"invalid_plan":case"invalid_interval":case"invalid_tier":return"That plan isn't offered on this cycle — pick another."}return"Billing isn't available right now."}function B({text:t}){return e.jsx("p",{className:"mt-3 rounded-lg border border-danger-border bg-danger-soft px-3 py-2 text-sm text-danger",children:t})}function oe({summary:t,plans:s}){const n=le(s),[a,l]=m.useState(null),c=a!==null&&n.includes(a)?a:n[0]??null,[i,x]=m.useState(null),[h,f]=m.useState(null);async function b(r){if(!i){x(r),f(null);try{const{url:o}=c?await C(r,c):await C(r);window.location.assign(o)}catch(o){if(x(null),o instanceof I){N.getState().markExpired();return}f(ce(o))}}}return e.jsxs("div",{className:"mt-4",children:[e.jsx("p",{className:"text-sm text-fg-muted",children:R(t)}),c&&n.length>1?e.jsxs("fieldset",{className:"mt-4 flex flex-wrap items-center gap-1.5",children:[e.jsx("legend",{className:"sr-only",children:"Billing interval"}),n.map(r=>{const o=r===c;return e.jsx("button",{type:"button",onClick:()=>l(r),"aria-pressed":o,className:`chip focus-ring ${o?"chip-tag-active font-medium":"chip-tag"}`,children:E[r]},r)})]}):null,s.length>0?e.jsx("ul",{className:"mt-4 grid gap-3 sm:grid-cols-2",children:s.map(r=>{var y;const o=r.id===t.plan.tier,g=c?(y=r.intervals)==null?void 0:y[c]:void 0,u=n.length===0||(g==null?void 0:g.available)===!0,p=ie(r,n.length>0),d=u?null:re(r);return e.jsxs("li",{className:"rounded-xl border border-border bg-bg p-4",children:[e.jsxs("div",{className:"flex items-center justify-between gap-2",children:[e.jsx("span",{className:"font-serif text-lg text-fg",children:r.name}),o?e.jsx("span",{className:"chip",children:"Current"}):null]}),p?e.jsx("p",{className:"mt-1 text-sm text-fg-muted",children:p}):null,typeof r.vaults=="number"?e.jsxs("p",{className:"mt-0.5 text-xs text-fg-dim",children:[r.vaults," vault",r.vaults===1?"":"s"]}):null,o?null:u?e.jsx("button",{type:"button",onClick:()=>b(r.id),disabled:i!==null,className:"btn btn-primary btn-sm btn-touch mt-3 w-full",children:i===r.id?"Starting…":`Upgrade to ${r.name}`}):e.jsxs("div",{className:"mt-3",children:[e.jsxs("button",{type:"button",disabled:!0,className:"btn btn-secondary btn-sm btn-touch w-full",children:["Not available"," ",E[c].toLowerCase()]}),d?e.jsxs("p",{className:"mt-1 text-xs text-fg-dim",children:["Available from ",V(d.entry,d.interval)]}):null]})]},r.id)})}):null,h?e.jsx(B,{text:h}):null]})}function R(t){const{plan:s}=t,n=[s.label];typeof s.trial_days_left=="number"?n.push(`${s.trial_days_left} day${s.trial_days_left===1?"":"s"} left`):typeof s.price_monthly_usd=="number"&&s.price_monthly_usd>0&&n.push(`$${s.price_monthly_usd}/mo`),typeof s.vault_limit=="number"&&typeof s.vaults_used=="number"&&n.push(`${s.vaults_used} of ${s.vault_limit} vaults`);const a=S(s.storage_used_bytes??0);if(a){const l=s.storage_limit_bytes?S(s.storage_limit_bytes):null;n.push(l?`${a} of ${l}`:a)}return n.join(" · ")}function ue({vaults:t,summary:s,onReload:n}){const a=$(),[l,c]=m.useState(null),[i,x]=m.useState(null),[h,f]=m.useState(!1);async function b(u){if(!l){c(u.name),x(null);try{await H(u.name),Q(u.name),a("/")}catch(p){c(null),x(X(p,"Couldn't open that vault."))}}}async function r(){f(!0);try{await n()}finally{f(!1)}}const o=s==null?void 0:s.plan,g=o&&typeof o.vault_limit=="number"&&typeof o.vaults_used=="number"?`${o.vaults_used} of ${o.vault_limit} on your plan`:null;return e.jsxs("section",{"aria-label":"Your vaults",className:"card p-6 shadow-soft",children:[e.jsxs("div",{className:"flex flex-wrap items-baseline justify-between gap-x-4 gap-y-1",children:[e.jsx("h2",{className:"font-serif text-xl text-fg",children:"Your vaults"}),g?e.jsx("span",{className:"text-xs text-fg-muted",children:g}):null]}),t==="loading"?e.jsxs("div",{"aria-busy":"true",className:"mt-4 space-y-2.5",children:[e.jsx("div",{className:"skeleton h-9 rounded-lg"}),e.jsx("div",{className:"skeleton h-9 w-4/5 rounded-lg"})]}):t==="error"?e.jsxs("div",{className:"mt-4 text-center",children:[e.jsx("p",{className:"mb-1 font-serif text-lg text-fg",children:"Couldn't load your vaults."}),e.jsx("p",{className:"mb-5 text-sm text-fg-muted",children:"A hiccup reaching your account — nothing's lost, your vaults are safe."}),e.jsx("button",{type:"button",onClick:r,disabled:h,className:"btn btn-primary btn-touch",children:h?"Retrying…":"Retry"})]}):t.length===0?e.jsxs("div",{className:"mt-4 text-center",children:[e.jsx("p",{className:"mb-1 font-serif text-lg text-fg",children:"No vaults yet."}),e.jsx("p",{className:"mb-5 text-sm text-fg-muted",children:"Create your first — a private home for your notes, always yours to export."}),e.jsx(j,{to:"/add-vault/create",className:"btn btn-primary btn-touch",children:"Create a vault"})]}):e.jsxs(e.Fragment,{children:[e.jsx("ul",{className:"mt-3 divide-y divide-border-light",children:t.map(u=>{const p=K(u.usage),d=u.url?u.url.replace(/^https?:\/\//,""):null;return e.jsxs("li",{className:"flex items-center gap-3 py-3",children:[e.jsx(de,{name:u.name}),e.jsxs("div",{className:"min-w-0 flex-1",children:[e.jsx("p",{className:"truncate font-serif text-lg leading-snug text-fg",children:u.name}),d?e.jsx("p",{className:"mt-0.5 truncate note-id",children:d}):null,p?e.jsx("p",{className:"mt-0.5 text-xs text-fg-muted",children:p}):null]}),e.jsx("button",{type:"button",onClick:()=>b(u),disabled:l===u.name,className:"btn btn-primary btn-sm btn-touch shrink-0",children:l===u.name?"Opening…":"Open →"})]},u.name)})}),e.jsx("p",{className:"mt-3 border-t border-border-light pt-3 text-sm",children:e.jsx(j,{to:"/add-vault",className:"focus-ring font-semibold text-accent hover:underline",children:"+ Add a vault"})})]}),i?e.jsx("p",{className:"mt-4 rounded-lg border border-danger-border bg-danger-soft px-3 py-2 text-sm text-danger",children:i}):null]})}function de({name:t}){const s=(t.trim()[0]??"?").toUpperCase();return e.jsx("span",{"aria-hidden":!0,className:"grid h-9 w-9 shrink-0 place-items-center rounded-full bg-grass-soft text-sm font-semibold text-grass-ink",children:s})}function L({hasActiveVault:t}){return e.jsxs("section",{"aria-label":"Connections",className:"card p-6 shadow-soft",children:[e.jsx("h2",{className:"font-serif text-xl text-fg",children:"Connections"}),e.jsxs("div",{className:"mt-2 divide-y divide-border-light",children:[t?e.jsx(w,{to:"/connect",tone:"sky",icon:e.jsx(_,{width:18,height:18}),title:"Connect your AI",description:"Claude, ChatGPT, or any MCP client — one memory, shared."}):e.jsxs("div",{className:"-mx-2 flex items-center gap-3 px-2 py-3 opacity-60",children:[e.jsx(P,{tone:"sky",children:e.jsx(_,{width:18,height:18})}),e.jsxs("div",{className:"min-w-0 flex-1",children:[e.jsx("p",{className:"font-medium text-fg",children:"Connect your AI"}),e.jsx("p",{className:"mt-0.5 text-sm text-fg-muted",children:"Open a vault above to connect an AI to it."})]})]}),e.jsx(w,{to:"/import",tone:"grass",icon:e.jsx(D,{width:18,height:18}),title:"Import notes",description:"Bring your notes over from anywhere markdown lives."}),e.jsx(w,{to:"/export",tone:"sun",icon:e.jsx(F,{width:18,height:18}),title:"Export notes",description:"Download your vault as open Markdown — yours to keep."})]})]})}function w({to:t,tone:s,icon:n,title:a,description:l}){return e.jsxs(j,{to:t,className:"focus-ring -mx-2 flex items-center gap-3 rounded-lg px-2 py-3 hover:bg-bg-soft",children:[e.jsx(P,{tone:s,children:n}),e.jsxs("span",{className:"min-w-0 flex-1",children:[e.jsx("span",{className:"block font-medium text-fg",children:a}),e.jsx("span",{className:"mt-0.5 block text-sm text-fg-muted",children:l})]}),e.jsx("span",{"aria-hidden":!0,className:"shrink-0 text-lg text-fg-dim",children:"›"})]})}function P({tone:t,children:s}){const n=t==="grass"?"bg-grass-soft text-grass-ink":t==="sun"?"bg-sun-soft text-sun-ink":"bg-bg-soft";return e.jsx("span",{"aria-hidden":!0,className:`grid h-10 w-10 shrink-0 place-items-center rounded-full ${n}`,style:t==="sky"?{color:"var(--color-sky)"}:void 0,children:s})}function me(){const t=A(n=>n.vaults),s=Object.values(t);return e.jsxs("div",{className:"space-y-6",children:[e.jsxs("section",{className:"card p-6 shadow-soft",children:[e.jsx("h2",{className:"font-serif text-xl text-fg",children:"This device"}),e.jsx("p",{className:"mt-1 text-sm text-fg-muted",children:"You're managing the vaults connected on this device. Sign in to your account to manage your plan and hosted vaults from anywhere."}),e.jsxs("div",{className:"mt-4 flex flex-wrap gap-3",children:[e.jsx(j,{to:"/",className:"btn btn-primary btn-touch",children:"Sign in"}),e.jsx(j,{to:"/vaults",className:"btn btn-ghost btn-touch",children:s.length>0?`${s.length} connected`:"Connect a vault"})]})]}),e.jsx(L,{hasActiveVault:s.length>0})]})}export{fe as Account};
|
|
1
|
+
import{r as m,u as N,g as M,j as e,a as A,L as j,b as $,c as T,s as O,l as k,m as q,d as Y,I as _,e as D,f as F,h as U,i as G,o as H,k as Q,n as X,p as z,S as I,q as C,B as J}from"./index-H6VNro-x.js";import{f as K,a as S}from"./provenance-DDSHYRnT.js";function fe(){const[t,s]=m.useState({kind:"loading"}),n=N(a=>a.identityEpoch);return m.useEffect(()=>{let a=!0;return(async()=>{let l;try{l=await M()}catch{a&&s({kind:"device"});return}a&&s(l.signed_in?{kind:"manager",email:l.email,username:l.username,csrf:l.csrf}:{kind:"device"})})(),()=>{a=!1}},[n]),e.jsxs("div",{className:"page-prose",children:[e.jsxs("header",{className:"mb-8",children:[e.jsx("h1",{className:"page-title",children:"Your parachute"}),e.jsx("p",{className:"mt-2 max-w-prose text-fg-muted",children:"Your account, plan, vaults, and connections — managed here."})]}),t.kind==="loading"?e.jsx("output",{"aria-live":"polite",className:"block py-10 text-center text-sm text-fg-dim",children:e.jsx("span",{className:"animate-pulse",children:"Loading your account…"})}):t.kind==="device"?e.jsx(me,{}):e.jsx(W,{email:t.email,username:t.username,csrf:t.csrf})]})}function W({email:t,username:s,csrf:n}){const a=$(),l=A(d=>d.getActiveVault()),c=N(d=>d.identityEpoch),i=T(),x=i.isPending?"loading":i.data??null,h=O(i.data),f=m.useCallback(()=>i.refetch(),[i.refetch]),[b,r]=m.useState("loading"),[o,g]=m.useState(null);m.useEffect(()=>{let d=!0;return k().then(y=>{d&&r(y.vaults)}).catch(y=>{q(y),d&&r("error")}),Y().then(y=>{d&&g(y)}),()=>{d=!1}},[c]);const u=m.useCallback(async()=>{try{const{vaults:d}=await k();r(d)}catch{r("error")}},[]);async function p(){try{await U(n)}finally{G(),a("/",{replace:!0})}}return e.jsxs("div",{className:"space-y-6",children:[e.jsx(Z,{email:t,username:s,summary:h,onSignOut:p}),e.jsx(te,{state:x,descriptor:o,onRetry:f,retrying:i.isFetching}),e.jsx(ue,{vaults:b,summary:h,onReload:u}),e.jsx(L,{hasActiveVault:!!l})]})}function Z({email:t,username:s,summary:n,onSignOut:a}){return e.jsx("section",{"aria-label":"Account",className:"card p-6 shadow-soft",children:e.jsxs("div",{className:"flex flex-wrap items-start justify-between gap-4",children:[e.jsxs("div",{className:"min-w-0",children:[e.jsx("p",{className:"eyebrow mb-1",children:"Signed in as"}),e.jsxs("div",{className:"flex flex-wrap items-center gap-x-3 gap-y-1",children:[e.jsx("p",{className:"break-words font-serif text-xl text-fg",children:t??s??"your account"}),e.jsx(ee,{summary:n})]})]}),e.jsx("button",{type:"button",onClick:a,className:"focus-ring shrink-0 text-sm text-fg-dim hover:text-accent",children:"Sign out"})]})})}function ee({summary:t}){if(!t)return null;const s=t.plan.trial_days_left;return typeof s=="number"?e.jsxs("span",{className:"chip border-transparent bg-sun-soft font-medium text-sun-ink",children:["Free trial · ",s===0?"ends today":`${s} day${s===1?"":"s"} left`]}):e.jsx("span",{className:"chip",children:t.plan.label})}function te({state:t,descriptor:s,onRetry:n,retrying:a}){return t===null||t!=="loading"&&t!=="error"&&!t.billing_enabled?null:e.jsxs("section",{"aria-label":"Plan & billing",className:"card p-6 shadow-soft",children:[e.jsx("h2",{className:"font-serif text-xl text-fg",children:"Plan & billing"}),t==="loading"?e.jsxs("div",{"aria-busy":"true",className:"mt-4 space-y-2.5",children:[e.jsx("div",{className:"skeleton h-4 w-3/5 rounded-md"}),e.jsx("div",{className:"skeleton h-4 w-2/5 rounded-md"})]}):t==="error"?e.jsxs("div",{className:"mt-4 text-center",children:[e.jsx("p",{className:"mb-1 font-serif text-lg text-fg",children:"Couldn't load your plan."}),e.jsx("p",{className:"mb-5 text-sm text-fg-muted",children:"A hiccup reaching your account — your plan hasn't changed."}),e.jsx("button",{type:"button",onClick:n,disabled:a,className:"btn btn-primary btn-touch",children:a?"Retrying…":"Retry"})]}):t.has_billing_customer?e.jsx(se,{summary:t}):e.jsx(oe,{summary:t,plans:(s==null?void 0:s.plans)??[]})]})}function se({summary:t}){const[s,n]=m.useState(!1),[a,l]=m.useState(null);async function c(){n(!0),l(null);try{const{url:i}=await z();window.location.assign(i)}catch(i){if(n(!1),i instanceof I){N.getState().markExpired();return}l("Billing isn't available right now.")}}return e.jsxs("div",{className:"mt-4",children:[e.jsx("p",{className:"text-sm text-fg-muted",children:R(t)}),e.jsx("button",{type:"button",onClick:c,disabled:s,className:"btn btn-primary btn-touch mt-4",children:s?"Opening…":"Manage plan & billing ↗"}),a?e.jsx(B,{text:a}):null]})}const v=["monthly","quarterly","yearly"],E={monthly:"Monthly",quarterly:"Quarterly",yearly:"Yearly"},ne={monthly:"/mo",quarterly:"/quarter",yearly:"/yr"},ae={monthly:1,quarterly:3,yearly:12};function le(t){var n,a;const s=new Set;for(const l of t)for(const c of v)(a=(n=l.intervals)==null?void 0:n[c])!=null&&a.available&&s.add(c);return v.filter(l=>s.has(l))}function V(t,s){return t.label?t.label:typeof t.price=="number"?`$${t.price}${ne[s]}`:null}function re(t){var s;for(const n of v){const a=(s=t.intervals)==null?void 0:s[n];if(a!=null&&a.available)return{interval:n,entry:a}}return null}function ie(t,s){if(!s||!t.intervals)return typeof t.price_month=="number"?`$${t.price_month}/mo`:null;const n=[];let a=!1,l=null;for(const i of v){const x=t.intervals[i];if(!(x!=null&&x.available))continue;i==="monthly"&&(a=!0);const h=V(x,i);if(h&&n.push(h),typeof x.price=="number"){const f=x.price/ae[i];l=l===null?f:Math.min(l,f)}}if(n.length===0)return null;const c=n.join(" · ");return a||l===null?c:`${c} — about $${Math.max(1,Math.round(l))}/mo`}function ce(t){if(t instanceof J)switch(t.code){case"already_subscribed":return"You're already subscribed — refresh to see your plan.";case"invalid_plan":case"invalid_interval":case"invalid_tier":return"That plan isn't offered on this cycle — pick another."}return"Billing isn't available right now."}function B({text:t}){return e.jsx("p",{className:"mt-3 rounded-lg border border-danger-border bg-danger-soft px-3 py-2 text-sm text-danger",children:t})}function oe({summary:t,plans:s}){const n=le(s),[a,l]=m.useState(null),c=a!==null&&n.includes(a)?a:n[0]??null,[i,x]=m.useState(null),[h,f]=m.useState(null);async function b(r){if(!i){x(r),f(null);try{const{url:o}=c?await C(r,c):await C(r);window.location.assign(o)}catch(o){if(x(null),o instanceof I){N.getState().markExpired();return}f(ce(o))}}}return e.jsxs("div",{className:"mt-4",children:[e.jsx("p",{className:"text-sm text-fg-muted",children:R(t)}),c&&n.length>1?e.jsxs("fieldset",{className:"mt-4 flex flex-wrap items-center gap-1.5",children:[e.jsx("legend",{className:"sr-only",children:"Billing interval"}),n.map(r=>{const o=r===c;return e.jsx("button",{type:"button",onClick:()=>l(r),"aria-pressed":o,className:`chip focus-ring ${o?"chip-tag-active font-medium":"chip-tag"}`,children:E[r]},r)})]}):null,s.length>0?e.jsx("ul",{className:"mt-4 grid gap-3 sm:grid-cols-2",children:s.map(r=>{var y;const o=r.id===t.plan.tier,g=c?(y=r.intervals)==null?void 0:y[c]:void 0,u=n.length===0||(g==null?void 0:g.available)===!0,p=ie(r,n.length>0),d=u?null:re(r);return e.jsxs("li",{className:"rounded-xl border border-border bg-bg p-4",children:[e.jsxs("div",{className:"flex items-center justify-between gap-2",children:[e.jsx("span",{className:"font-serif text-lg text-fg",children:r.name}),o?e.jsx("span",{className:"chip",children:"Current"}):null]}),p?e.jsx("p",{className:"mt-1 text-sm text-fg-muted",children:p}):null,typeof r.vaults=="number"?e.jsxs("p",{className:"mt-0.5 text-xs text-fg-dim",children:[r.vaults," vault",r.vaults===1?"":"s"]}):null,o?null:u?e.jsx("button",{type:"button",onClick:()=>b(r.id),disabled:i!==null,className:"btn btn-primary btn-sm btn-touch mt-3 w-full",children:i===r.id?"Starting…":`Upgrade to ${r.name}`}):e.jsxs("div",{className:"mt-3",children:[e.jsxs("button",{type:"button",disabled:!0,className:"btn btn-secondary btn-sm btn-touch w-full",children:["Not available"," ",E[c].toLowerCase()]}),d?e.jsxs("p",{className:"mt-1 text-xs text-fg-dim",children:["Available from ",V(d.entry,d.interval)]}):null]})]},r.id)})}):null,h?e.jsx(B,{text:h}):null]})}function R(t){const{plan:s}=t,n=[s.label];typeof s.trial_days_left=="number"?n.push(`${s.trial_days_left} day${s.trial_days_left===1?"":"s"} left`):typeof s.price_monthly_usd=="number"&&s.price_monthly_usd>0&&n.push(`$${s.price_monthly_usd}/mo`),typeof s.vault_limit=="number"&&typeof s.vaults_used=="number"&&n.push(`${s.vaults_used} of ${s.vault_limit} vaults`);const a=S(s.storage_used_bytes??0);if(a){const l=s.storage_limit_bytes?S(s.storage_limit_bytes):null;n.push(l?`${a} of ${l}`:a)}return n.join(" · ")}function ue({vaults:t,summary:s,onReload:n}){const a=$(),[l,c]=m.useState(null),[i,x]=m.useState(null),[h,f]=m.useState(!1);async function b(u){if(!l){c(u.name),x(null);try{await H(u.name),Q(u.name),a("/")}catch(p){c(null),x(X(p,"Couldn't open that vault."))}}}async function r(){f(!0);try{await n()}finally{f(!1)}}const o=s==null?void 0:s.plan,g=o&&typeof o.vault_limit=="number"&&typeof o.vaults_used=="number"?`${o.vaults_used} of ${o.vault_limit} on your plan`:null;return e.jsxs("section",{"aria-label":"Your vaults",className:"card p-6 shadow-soft",children:[e.jsxs("div",{className:"flex flex-wrap items-baseline justify-between gap-x-4 gap-y-1",children:[e.jsx("h2",{className:"font-serif text-xl text-fg",children:"Your vaults"}),g?e.jsx("span",{className:"text-xs text-fg-muted",children:g}):null]}),t==="loading"?e.jsxs("div",{"aria-busy":"true",className:"mt-4 space-y-2.5",children:[e.jsx("div",{className:"skeleton h-9 rounded-lg"}),e.jsx("div",{className:"skeleton h-9 w-4/5 rounded-lg"})]}):t==="error"?e.jsxs("div",{className:"mt-4 text-center",children:[e.jsx("p",{className:"mb-1 font-serif text-lg text-fg",children:"Couldn't load your vaults."}),e.jsx("p",{className:"mb-5 text-sm text-fg-muted",children:"A hiccup reaching your account — nothing's lost, your vaults are safe."}),e.jsx("button",{type:"button",onClick:r,disabled:h,className:"btn btn-primary btn-touch",children:h?"Retrying…":"Retry"})]}):t.length===0?e.jsxs("div",{className:"mt-4 text-center",children:[e.jsx("p",{className:"mb-1 font-serif text-lg text-fg",children:"No vaults yet."}),e.jsx("p",{className:"mb-5 text-sm text-fg-muted",children:"Create your first — a private home for your notes, always yours to export."}),e.jsx(j,{to:"/add-vault/create",className:"btn btn-primary btn-touch",children:"Create a vault"})]}):e.jsxs(e.Fragment,{children:[e.jsx("ul",{className:"mt-3 divide-y divide-border-light",children:t.map(u=>{const p=K(u.usage),d=u.url?u.url.replace(/^https?:\/\//,""):null;return e.jsxs("li",{className:"flex items-center gap-3 py-3",children:[e.jsx(de,{name:u.name}),e.jsxs("div",{className:"min-w-0 flex-1",children:[e.jsx("p",{className:"truncate font-serif text-lg leading-snug text-fg",children:u.name}),d?e.jsx("p",{className:"mt-0.5 truncate note-id",children:d}):null,p?e.jsx("p",{className:"mt-0.5 text-xs text-fg-muted",children:p}):null]}),e.jsx("button",{type:"button",onClick:()=>b(u),disabled:l===u.name,className:"btn btn-primary btn-sm btn-touch shrink-0",children:l===u.name?"Opening…":"Open →"})]},u.name)})}),e.jsx("p",{className:"mt-3 border-t border-border-light pt-3 text-sm",children:e.jsx(j,{to:"/add-vault",className:"focus-ring font-semibold text-accent hover:underline",children:"+ Add a vault"})})]}),i?e.jsx("p",{className:"mt-4 rounded-lg border border-danger-border bg-danger-soft px-3 py-2 text-sm text-danger",children:i}):null]})}function de({name:t}){const s=(t.trim()[0]??"?").toUpperCase();return e.jsx("span",{"aria-hidden":!0,className:"grid h-9 w-9 shrink-0 place-items-center rounded-full bg-grass-soft text-sm font-semibold text-grass-ink",children:s})}function L({hasActiveVault:t}){return e.jsxs("section",{"aria-label":"Connections",className:"card p-6 shadow-soft",children:[e.jsx("h2",{className:"font-serif text-xl text-fg",children:"Connections"}),e.jsxs("div",{className:"mt-2 divide-y divide-border-light",children:[t?e.jsx(w,{to:"/connect",tone:"sky",icon:e.jsx(_,{width:18,height:18}),title:"Connect your AI",description:"Claude, ChatGPT, or any MCP client — one memory, shared."}):e.jsxs("div",{className:"-mx-2 flex items-center gap-3 px-2 py-3 opacity-60",children:[e.jsx(P,{tone:"sky",children:e.jsx(_,{width:18,height:18})}),e.jsxs("div",{className:"min-w-0 flex-1",children:[e.jsx("p",{className:"font-medium text-fg",children:"Connect your AI"}),e.jsx("p",{className:"mt-0.5 text-sm text-fg-muted",children:"Open a vault above to connect an AI to it."})]})]}),e.jsx(w,{to:"/import",tone:"grass",icon:e.jsx(D,{width:18,height:18}),title:"Import notes",description:"Bring your notes over from anywhere markdown lives."}),e.jsx(w,{to:"/export",tone:"sun",icon:e.jsx(F,{width:18,height:18}),title:"Export notes",description:"Download your vault as open Markdown — yours to keep."})]})]})}function w({to:t,tone:s,icon:n,title:a,description:l}){return e.jsxs(j,{to:t,className:"focus-ring -mx-2 flex items-center gap-3 rounded-lg px-2 py-3 hover:bg-bg-soft",children:[e.jsx(P,{tone:s,children:n}),e.jsxs("span",{className:"min-w-0 flex-1",children:[e.jsx("span",{className:"block font-medium text-fg",children:a}),e.jsx("span",{className:"mt-0.5 block text-sm text-fg-muted",children:l})]}),e.jsx("span",{"aria-hidden":!0,className:"shrink-0 text-lg text-fg-dim",children:"›"})]})}function P({tone:t,children:s}){const n=t==="grass"?"bg-grass-soft text-grass-ink":t==="sun"?"bg-sun-soft text-sun-ink":"bg-bg-soft";return e.jsx("span",{"aria-hidden":!0,className:`grid h-10 w-10 shrink-0 place-items-center rounded-full ${n}`,style:t==="sky"?{color:"var(--color-sky)"}:void 0,children:s})}function me(){const t=A(n=>n.vaults),s=Object.values(t);return e.jsxs("div",{className:"space-y-6",children:[e.jsxs("section",{className:"card p-6 shadow-soft",children:[e.jsx("h2",{className:"font-serif text-xl text-fg",children:"This device"}),e.jsx("p",{className:"mt-1 text-sm text-fg-muted",children:"You're managing the vaults connected on this device. Sign in to your account to manage your plan and hosted vaults from anywhere."}),e.jsxs("div",{className:"mt-4 flex flex-wrap gap-3",children:[e.jsx(j,{to:"/",className:"btn btn-primary btn-touch",children:"Sign in"}),e.jsx(j,{to:"/vaults",className:"btn btn-ghost btn-touch",children:s.length>0?`${s.length} connected`:"Connect a vault"})]})]}),e.jsx(L,{hasActiveVault:s.length>0})]})}export{fe as Account};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{a as x,t as f,r as l,j as e,N as g,v as y,E as j,L as u,w as N,x as b,V as v}from"./index-
|
|
1
|
+
import{a as x,t as f,r as l,j as e,N as g,v as y,E as j,L as u,w as N,x as b,V as v}from"./index-H6VNro-x.js";const h=1440*60*1e3,w=5e3;function E(a,n=30,s=new Date){const r=s.getTime()-n*h,i=[];for(const t of a){const c=t.path??t.id,d=Date.parse(t.createdAt);if(Number.isFinite(d)&&d>=r&&i.push({id:`${t.id}:created`,noteId:t.id,noteName:c,kind:"created",at:t.createdAt,preview:t.preview,tags:t.tags}),t.updatedAt){const o=Date.parse(t.updatedAt);Number.isFinite(o)&&o>=r&&Number.isFinite(d)&&o-d>w&&i.push({id:`${t.id}:updated`,noteId:t.id,noteName:c,kind:"updated",at:t.updatedAt,preview:t.preview,tags:t.tags})}}return i.sort((t,c)=>Date.parse(c.at)-Date.parse(t.at)),i}const k=["today","yesterday","thisWeek","older"],D={today:"Today",yesterday:"Yesterday",thisWeek:"This week",older:"Older"};function A(a,n=new Date){const s=Date.parse(a);if(!Number.isFinite(s))return null;const r=m(n),i=m(new Date(s)),t=Math.round((r.getTime()-i.getTime())/h);return t<0||t===0?"today":t===1?"yesterday":t<7?"thisWeek":"older"}function m(a){return new Date(a.getFullYear(),a.getMonth(),a.getDate())}function S(a,n=new Date){const s={today:[],yesterday:[],thisWeek:[],older:[]};for(const r of a){const i=A(r.at,n);i&&s[i].push(r)}return s}const p=50;function R(){const a=x(o=>o.getActiveVault()),n=f(),[s,r]=l.useState(p),i=l.useMemo(()=>n.data?E(n.data):[],[n.data]),t=l.useMemo(()=>i.slice(0,s),[i,s]),c=l.useMemo(()=>S(t),[t]),d=i.length-t.length;return a?e.jsxs("div",{className:"page-prose",children:[e.jsxs("header",{className:"mb-8",children:[e.jsx("p",{className:"eyebrow mb-1",children:"Activity"}),e.jsx("h1",{className:"page-title",children:"Recent changes"}),e.jsx("p",{className:"mt-2 text-fg-muted",children:"Last 30 days, newest first. Deletions aren't tracked yet."})]}),n.isPending?e.jsx(F,{}):n.isError?e.jsx(L,{error:n.error}):i.length===0?e.jsx(C,{}):e.jsxs(e.Fragment,{children:[e.jsx("div",{className:"space-y-8",children:k.map(o=>c[o].length>0?e.jsx(T,{title:D[o],events:c[o]},o):null)}),d>0?e.jsx("div",{className:"mt-8 flex justify-center",children:e.jsxs("button",{type:"button",onClick:()=>r(o=>o+p),className:"btn btn-secondary btn-touch",children:["Load more (",d," remaining)"]})}):null]})]}):e.jsx(g,{to:"/",replace:!0})}function T({title:a,events:n}){return e.jsxs("section",{children:[e.jsxs("h2",{className:"eyebrow mb-3",children:[a," (",n.length,")"]}),e.jsx("ol",{className:"card shadow-soft divide-y divide-border rounded-xl",children:n.map(s=>e.jsx("li",{children:e.jsxs(u,{to:`/n/${encodeURIComponent(s.noteId)}`,className:"focus-ring block px-5 py-4 transition-colors hover:bg-bg-soft",children:[e.jsxs("div",{className:"flex items-baseline justify-between gap-4",children:[e.jsxs("div",{className:"flex min-w-0 items-baseline gap-2",children:[e.jsx(B,{kind:s.kind}),e.jsx("span",{className:"truncate font-mono text-sm text-fg",children:s.noteName})]}),e.jsx("span",{className:"shrink-0 text-xs text-fg-dim",children:b(s.at)})]}),s.preview?e.jsx("p",{className:"mt-1 truncate text-sm text-fg-muted",children:s.preview}):null,s.tags&&s.tags.length>0?e.jsx("div",{className:"mt-2 flex flex-wrap gap-1.5",children:s.tags.map(r=>e.jsxs("span",{className:"chip chip-tag max-w-full break-all",children:["#",r]},r))}):null]})},s.id))})]})}function B({kind:a}){return a==="created"?e.jsx("span",{className:"chip chip-tag shrink-0",children:"Created"}):e.jsx("span",{className:"chip shrink-0",children:"Edited"})}function C(){return e.jsx(N,{title:"No activity in the last 30 days.",action:e.jsx(u,{to:"/new",className:"btn btn-primary",children:"New note"})})}function F(){return e.jsx("div",{className:"space-y-3","aria-busy":"true",children:[0,1,2,3,4].map(a=>e.jsx(y,{className:"h-16 rounded-xl"},a))})}function L({error:a}){const n=a instanceof v;return e.jsx(j,{title:n?"Session expired":"Could not load activity",message:a.message,action:n?e.jsx(u,{to:"/add",className:"btn btn-primary",children:"Reconnect vault"}):void 0})}export{R as Activity};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{y as z,b as E,r,z as I,A as g,C as V,D as A,a as F,F as H,G as q,j as e,P as B,H as D}from"./index-
|
|
1
|
+
import{y as z,b as E,r,z as I,A as g,C as V,D as A,a as F,F as H,G as q,j as e,P as B,H as D}from"./index-H6VNro-x.js";import{W as L}from"./WizardShell-B0Fjh0Vt.js";import{s as O}from"./url-QSQwrjSV.js";import"./history-Ce29a331.js";function W(s){const o=s.trim();if(!o)return null;try{return new URL(g(o)).host}catch{return null}}function J(){const[s,o]=z(),b=E(),m=s.get("url")??"",u=s.get("add")??"",f=/^https?:\/\//i.test(u),v=m||(f?u:""),i=O(s.get("redirect")),[a,y]=r.useState(v),[j,x]=r.useState(null),[R,w]=r.useState(!1),[h,N]=r.useState(!1),S=r.useRef(null),C=r.useRef(v.length>0),U=r.useRef(!1),c=I();r.useEffect(()=>{var t;(t=S.current)==null||t.focus()},[]),r.useEffect(()=>{C.current||c.status==="found"&&c.origin&&a===""&&(y(c.origin),C.current=!0)},[c.status,c.origin,a]);const p=r.useCallback(async t=>{x(null),w(!1);let l;try{l=g(t)}catch(n){x(n.message);return}N(!0);try{const{authorizeUrl:n}=await V(l,void 0,void 0,{...i?{redirect:i}:{}});window.location.assign(n)}catch(n){n instanceof A?w(!0):x(n.message),N(!1)}},[i]);r.useEffect(()=>{if(U.current||!u)return;U.current=!0;const t=new URLSearchParams(s);if(t.delete("add"),o(t,{replace:!0}),m||!f)return;let l;try{l=g(u)}catch{return}const P=F.getState().vaults[H(l)];if(P){q(P.id,{toast:!0}),b(i??"/",{replace:!0});return}p(l)},[u,f,m,i,s,o,b,p]);function k(t){t.preventDefault(),p(a)}const d=W(a);return e.jsxs(L,{escape:{kind:"back",to:"/"},children:[e.jsx(B,{size:60,className:"mx-auto mb-6 drop-in"}),e.jsx("p",{className:"eyebrow mb-3",children:"Self-hosted"}),e.jsxs("h1",{className:"hero-title mb-4",children:["Connect your ",e.jsx("span",{className:"accent-word",children:"own"})," vault."]}),e.jsx("p",{className:"mx-auto mb-8 max-w-sm text-lg leading-relaxed text-fg-muted",children:"Point Parachute at a vault running on your own server."}),e.jsxs("form",{onSubmit:k,className:"mx-auto w-full max-w-sm text-left",children:[e.jsx("label",{htmlFor:"vault-url",className:"eyebrow mb-2 block",children:"Vault address"}),e.jsx("input",{id:"vault-url",ref:S,type:"url",required:!0,placeholder:"hub.your-domain.com",value:a,onChange:t=>y(t.target.value),disabled:h,className:"input input-on-bg font-mono"}),e.jsxs("p",{className:"mt-1.5 text-xs text-fg-dim",children:["A local install lives at ",e.jsx("code",{className:"note-id",children:"http://localhost:1939"}),"."]}),R?e.jsx("div",{className:"mt-3",children:e.jsx(D,{})}):null,j?e.jsx("p",{className:"mt-3 rounded-xl border border-danger-border bg-danger-soft px-3 py-2 text-sm text-danger",children:j}):null,d?e.jsxs("div",{className:"mt-5 rounded-2xl border border-sun bg-sun-soft px-4 py-3 text-left font-round text-sm leading-relaxed text-sun-ink",children:["Next, ",e.jsx("b",{className:"font-semibold text-fg",children:d})," — your server, not ours — will ask you to sign in and approve this app. Then you land right back here."]}):null,e.jsx("button",{type:"submit",disabled:h||!a,className:"btn btn-primary btn-lg mt-5 w-full justify-center rounded-full shadow-soft",children:h?"Continuing…":d?`Continue to ${d} →`:"Continue"})]})]})}export{J as AddVault};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{b as o,J as c,a as d,j as e,P as m}from"./index-
|
|
1
|
+
import{b as o,J as c,a as d,j as e,P as m}from"./index-H6VNro-x.js";import{W as x}from"./WizardShell-B0Fjh0Vt.js";import"./history-Ce29a331.js";function f(){const s=o(),a=c(),t=d(l=>l.getActiveVault()),n=null,r=t?"/vaults":"/";return e.jsxs(x,{wide:!0,escape:{kind:"back",to:r},children:[e.jsx(m,{size:56,className:"mx-auto mb-6"}),a?e.jsxs("p",{className:"chip mb-4 inline-flex border-grass/40 bg-grass-soft text-grass-ink",children:[e.jsx("span",{"aria-hidden":"true",children:"✓"})," Signed in as ",a]}):null,e.jsx("p",{className:"eyebrow mb-3",children:"Add a vault"}),e.jsxs("h1",{className:"hero-title mb-8",style:{fontSize:"clamp(1.8rem, 4vw, 2.4rem)"},children:["Bring another ",e.jsx("span",{className:"accent-word",children:"vault"})," in."]}),e.jsxs("div",{className:"grid gap-4 sm:grid-cols-3",children:[e.jsx(i,{icon:"📂",verb:"Open",description:"One of your account's vaults not on this device.",onClick:()=>s("/welcome?pick=1")}),e.jsx(i,{icon:"✦",verb:"Create",description:t?e.jsxs(e.Fragment,{children:["Brand-new and empty — separate from"," ",e.jsx("b",{className:"font-semibold text-fg",children:t.name}),"."]}):"Brand-new and empty — its own private space, nothing shared.",foot:n,onClick:()=>s("/add-vault/create")}),e.jsx(i,{icon:"⌂",verb:"Connect",description:"A self-hosted vault on your own server.",onClick:()=>s("/add")})]})]})}function i({icon:s,verb:a,description:t,foot:n,onClick:r}){return e.jsxs("button",{type:"button",onClick:r,"aria-label":a,className:"tile flex flex-col items-center gap-2 p-6 text-center",children:[e.jsx("span",{"aria-hidden":"true",className:"text-xl",children:s}),e.jsx("span",{"aria-hidden":"true",className:"font-round text-base font-bold text-fg",children:a}),e.jsx("span",{className:"font-round text-xs leading-relaxed text-fg-muted",children:t}),n?e.jsx("span",{className:"mt-1 font-round text-xs text-fg-dim",children:n}):null]})}export{f as AddVaultChooser};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{b as j,y as N,r as n,K as k,n as v,j as e,N as S,P as b,J as C,a as E,d as T,o as A,k as V}from"./index-
|
|
1
|
+
import{b as j,y as N,r as n,K as k,n as v,j as e,N as S,P as b,J as C,a as E,d as T,o as A,k as V}from"./index-H6VNro-x.js";import{W as g}from"./WizardShell-B0Fjh0Vt.js";import"./history-Ce29a331.js";const h=["Name","Making it","Ready"];function y(t){return t.toLowerCase().replace(/[^a-z0-9-]/g,"")}function M(){const t=j(),[o]=N(),a=o.get("first")==="1",[s,l]=n.useState({kind:"naming"}),i=n.useRef(null);return n.useEffect(()=>{if(s.kind!=="creating"||i.current===s.name)return;i.current=s.name;const{name:r}=s;(async()=>{try{const c=await k(r),d=new URLSearchParams({vault:c});a&&d.set("first","1"),t(`/add-vault/ready?${d.toString()}`,{replace:!0})}catch(c){i.current=null,l({kind:"naming",attemptedName:r,error:v(c,"Couldn't create your vault. Try a different name.")})}})()},[s,t,a]),s.kind==="creating"?e.jsx(g,{escape:{kind:"none"},progress:{labels:h,current:1},children:e.jsx(P,{name:s.name})}):e.jsx(g,{escape:{kind:"back",to:a?"/":"/add-vault"},progress:{labels:h,current:0},children:e.jsx(L,{first:a,initialName:s.attemptedName,error:s.error,onCreate:r=>l({kind:"creating",name:r})})})}function R({email:t}){return t?e.jsxs("p",{className:"chip mb-4 inline-flex border-grass/40 bg-grass-soft text-grass-ink",children:[e.jsx("span",{"aria-hidden":"true",children:"✓"})," Signed in as ",t]}):null}function L({first:t,initialName:o,error:a,onCreate:s}){const[l,i]=n.useState(()=>y(o??"")),[r,c]=n.useState(null),d=C(),p=E(m=>{var x;return((x=m.getActiveVault())==null?void 0:x.name)??null}),u=l.trim();n.useEffect(()=>{let m=!0;return T().then(x=>{m&&c((x==null?void 0:x.vault_url_template)??null)}),()=>{m=!1}},[]);function w(m){m.preventDefault(),u&&s(u)}return e.jsxs(e.Fragment,{children:[e.jsx(b,{size:60,className:"mx-auto mb-6 drop-in"}),e.jsx(R,{email:d}),e.jsx("p",{className:"eyebrow mb-3",children:t?"Account created ✓":"Adding a vault"}),e.jsxs("h1",{className:"hero-title mb-4",children:[t?"Let's make your first":"Let's make your new"," ",e.jsx("span",{className:"accent-word",children:"vault."})]}),e.jsx("p",{className:"mx-auto mb-8 max-w-md text-lg leading-relaxed text-fg-muted",children:t?e.jsxs(e.Fragment,{children:["A vault is the private home for your notes — any AI you invite can read it, always yours to export. ",e.jsx("b",{className:"font-semibold text-fg",children:"This creates a brand-new, empty one."})]}):e.jsxs(e.Fragment,{children:["This one's separate from"," ",e.jsx("b",{className:"font-semibold text-fg",children:p??"your other vault"})," — its own private space, nothing shared."]})}),e.jsxs("form",{onSubmit:w,children:[e.jsx("input",{autoFocus:!0,value:l,onChange:m=>i(y(m.target.value)),placeholder:"moss",autoComplete:"off",spellCheck:!1,"aria-label":"Vault name",className:"mx-auto mb-2 block w-full max-w-sm border-0 border-b-2 border-border bg-transparent pb-2 text-center font-serif text-3xl text-fg outline-none transition-colors focus:border-accent-light"}),e.jsx("p",{className:"mb-6 min-h-6 font-round text-sm text-fg-muted",children:u?e.jsxs("span",{children:["Your vault:"," ",e.jsx("b",{className:"rounded-md bg-grass-soft px-2 py-0.5 text-grass-ink",children:u}),r?e.jsxs(e.Fragment,{children:[" — it will live at ",e.jsx("span",{className:"font-mono text-xs",children:r.replace("{name}",u)})]}):null]}):"Letters, numbers, hyphens — pick a word you like."}),e.jsxs("p",{className:"mx-auto mb-8 max-w-sm font-round text-xs text-fg-dim",children:[e.jsx("span",{className:"font-semibold text-fg-muted",children:"The address is permanent"}),", so pick a word you like. Letters, numbers, hyphens."]}),a?e.jsx("p",{className:"mx-auto mb-6 max-w-sm rounded-lg border border-danger-border bg-danger-soft px-3 py-2 text-sm text-danger",children:a}):null,e.jsx("button",{type:"submit",disabled:!u,className:"btn btn-primary btn-lg justify-center rounded-full px-6 shadow-soft",children:u?`Create ${u} →`:"Create →"})]})]})}const f=["Setting up your vault…","Preparing your keys…","Almost there…"];function z(){const[t,o]=n.useState(0);return n.useEffect(()=>{if(t>=f.length-1)return;const a=setTimeout(()=>o(s=>Math.min(s+1,f.length-1)),650);return()=>clearTimeout(a)},[t]),e.jsx("output",{"aria-live":"polite",className:"font-round text-sm text-fg-muted",children:f[t]})}function P({name:t}){return e.jsxs(e.Fragment,{children:[e.jsx(b,{size:96,className:"mx-auto mb-6 animate-pulse"}),e.jsxs("h1",{className:"hero-title mb-3",style:{fontSize:"clamp(1.6rem, 3.5vw, 1.9rem)"},children:["Making a place for ",e.jsxs("span",{className:"accent-word",children:[t,"…"]})]}),e.jsx(z,{})]})}function _(){const t=j(),[o]=N(),a=o.get("vault")??"",s=o.get("first")==="1",[l,i]=n.useState(!1),[r,c]=n.useState(null);if(!a)return e.jsx(S,{to:"/add-vault",replace:!0});async function d(){if(!l){i(!0),c(null);try{await A(a),V(a),t("/")}catch(p){i(!1),c(v(p,"Couldn't open your vault. Try again."))}}}return e.jsxs(g,{escape:s?{kind:"none"}:{kind:"maybe-later",to:"/"},progress:{labels:h,current:2},children:[e.jsx(b,{size:90,className:"mx-auto mb-6 fade-up"}),e.jsx("p",{className:"eyebrow mb-3",children:"Ready"}),e.jsxs("h1",{className:"hero-title mb-3",style:{fontSize:"clamp(1.8rem, 4vw, 2.3rem)"},children:[a," is ",e.jsx("span",{className:"accent-word",children:"ready."})]}),e.jsx("p",{className:"mx-auto mb-8 max-w-sm text-fg-muted",children:"Everything inside is yours. Open format. Export anytime."}),r?e.jsx("p",{className:"mx-auto mb-6 max-w-sm rounded-lg border border-danger-border bg-danger-soft px-3 py-2 text-sm text-danger",children:r}):null,e.jsx("button",{type:"button",onClick:d,disabled:l,className:"btn btn-primary btn-lg justify-center rounded-full px-6 shadow-soft",children:l?"Opening…":`Open ${a} →`})]})}export{M as AddVaultCreate,_ as AddVaultReady};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{a as k,y as E,M as y,O as f,t as A,Q as K,r as j,R as S,T,j as e,N as P,U as N,W as l,X as V,L as c,V as C}from"./index-
|
|
1
|
+
import{a as k,y as E,M as y,O as f,t as A,Q as K,r as j,R as S,T,j as e,N as P,U as N,W as l,X as V,L as c,V as C}from"./index-H6VNro-x.js";const R=["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],x=5;function W(){const a=k(t=>t.getActiveVault()),[o]=E(),i=o.get("month"),r=y(i)??y(f()),s=A(),h=K(),v=j.useMemo(()=>S(r.year,r.month),[r.year,r.month]),$=j.useMemo(()=>{const t=new Map;if(!s.data)return t;for(const n of s.data){const d=T(n.createdAt);d&&t.set(d,(t.get(d)??0)+1)}return t},[s.data]);if(!a)return e.jsx(P,{to:"/",replace:!0});const u=N(r.year,r.month,-1),p=N(r.year,r.month,1),g=`${u.year}-${l(u.month)}`,b=`${p.year}-${l(p.month)}`,M=f(),w=`${r.year}-${l(r.month)}`===M;return e.jsxs("div",{className:"mx-auto max-w-4xl px-4 py-6 md:px-6 md:py-10",children:[e.jsxs("header",{className:"mb-6 flex flex-wrap items-baseline justify-between gap-3",children:[e.jsxs("div",{children:[e.jsx("p",{className:"text-xs uppercase tracking-wider text-fg-dim",children:"Calendar"}),e.jsx("h1",{className:"font-serif text-3xl tracking-tight",children:V(r.year,r.month)})]}),e.jsxs("div",{className:"flex flex-wrap items-center gap-2 text-sm",children:[e.jsxs(c,{to:`/calendar?month=${g}`,className:"rounded-lg border border-border bg-card px-3 py-1.5 text-fg-muted hover:text-accent","aria-label":"Previous month",children:["← ",g]}),w?null:e.jsx(c,{to:"/calendar",className:"rounded-lg border border-border bg-card px-3 py-1.5 text-fg-muted hover:text-accent",children:"This month"}),e.jsxs(c,{to:`/calendar?month=${b}`,className:"rounded-lg border border-border bg-card px-3 py-1.5 text-fg-muted hover:text-accent","aria-label":"Next month",children:[b," →"]}),e.jsx(c,{to:`/today?date=${h}`,className:"rounded-lg border border-border bg-card px-3 py-1.5 text-fg-muted hover:text-accent",children:"Today"})]})]}),s.isError?e.jsx(F,{error:s.error}):e.jsxs("div",{className:"rounded-md border border-border bg-card","aria-busy":s.isPending,children:[e.jsx("div",{className:"grid grid-cols-7 border-b border-border text-xs uppercase tracking-wider text-fg-dim",children:R.map(t=>e.jsx("div",{className:"px-2 py-2 text-center",children:t},t))}),e.jsx("div",{className:"grid grid-cols-7",children:v.map(t=>{const n=`${t.getFullYear()}-${l(t.getMonth()+1)}-${l(t.getDate())}`,d=t.getMonth()+1===r.month,m=$.get(n)??0,D=n===h;return e.jsxs(c,{to:`/today?date=${n}`,className:`flex min-h-20 flex-col border-b border-r border-border p-1.5 text-xs hover:bg-bg/60 focus:bg-bg/60 focus:outline-none ${d?"":"opacity-40"}`,"aria-label":`${n} — ${m} notes`,children:[e.jsx("span",{className:`mb-1 inline-flex h-6 w-6 items-center justify-center rounded-full tabular-nums ${D?"bg-accent text-(--color-on-accent)":"text-fg"}`,children:t.getDate()}),m>0?e.jsx(_,{count:m}):e.jsx("span",{className:"sr-only",children:"no notes"})]},n)})})]}),e.jsx("p",{className:"mt-3 text-xs text-fg-dim",children:"Each dot is a note created on that day. Click any day to open /today."})]})}function _({count:a}){const o=Math.min(a,x),i=a>x?a-x:0;return e.jsxs("span",{className:"flex flex-wrap items-center gap-0.5",children:[Array.from({length:o}).map((r,s)=>e.jsx("span",{className:"h-1.5 w-1.5 rounded-full bg-accent","aria-hidden":"true"},s)),i>0?e.jsxs("span",{className:"ml-0.5 text-[10px] text-fg-dim",children:["+",i]}):null]})}function F({error:a}){const o=a instanceof C;return e.jsxs("div",{className:"rounded-md border border-red-500/30 bg-red-500/5 p-6",children:[e.jsx("p",{className:"mb-2 font-medium text-red-400",children:o?"Session expired":"Could not load notes"}),e.jsx("p",{className:"mb-4 text-sm text-fg-muted",children:a.message}),o?e.jsx(c,{to:"/add",className:"inline-block rounded-lg bg-accent px-4 py-2 text-sm font-medium text-(--color-on-accent) hover:bg-accent-hover",children:"Reconnect vault"}):null]})}export{W as Calendar};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{b as S,r as s,J as E,j as e,N as R,P as I,g as f,bB as L,bC as M,bD as O}from"./index-
|
|
1
|
+
import{b as S,r as s,J as E,j as e,N as R,P as I,g as f,bB as L,bC as M,bD as O}from"./index-H6VNro-x.js";import{W}from"./WizardShell-B0Fjh0Vt.js";import"./history-Ce29a331.js";const h="/welcome",_=3e3,N="That code didn't work — check it and try again.";function T(){const c=S(),[a,v]=s.useState(()=>E()??""),[r,i]=s.useState("idle"),[g,j]=s.useState(""),[w,o]=s.useState(""),[l,d]=s.useState(null),[b,p]=s.useState(!1),u=s.useRef(!1),m=s.useRef(!1);if(s.useEffect(()=>{let t=!1;const x=setInterval(async()=>{try{const k=await f();!t&&k.signed_in&&c(h,{replace:!0})}catch{}},_);return()=>{t=!0,clearInterval(x)}},[c]),!a)return e.jsx(R,{to:"/",replace:!0});async function y(t=a){if(!u.current){u.current=!0;try{const n=await f();await L(t,n.csrf,h),t!==a&&(M(t),v(t)),i("resent")}catch{i("idle")}finally{u.current=!1}}}async function C(t){const n=t.replace(/\D/g,"").slice(0,6);if(o(n),d(null),!(n.length<6||m.current)){m.current=!0,p(!0);try{const x=await f();if(await O(a,n,x.csrf)){c(h,{replace:!0});return}d(N),o("")}catch{d(N),o("")}finally{m.current=!1,p(!1)}}}return e.jsxs(W,{escape:{kind:"back",to:"/",label:"← Back to sign in"},children:[e.jsx(I,{size:56,className:"mx-auto mb-6"}),e.jsx("p",{className:"eyebrow mb-3",children:"Check your email"}),e.jsxs("h1",{className:"hero-title mb-3",style:{fontSize:"clamp(1.6rem, 3.5vw, 2.1rem)"},children:["We sent a sign-in link to ",e.jsx("span",{className:"accent-word",children:a})]}),e.jsx("p",{className:"text-fg-muted",children:"Works once, expires in 10 min."}),e.jsx("p",{className:"mx-auto mt-3 mb-6 max-w-sm font-round text-sm text-fg-muted",children:"New here? That same link creates your account — the email says which."}),e.jsxs("div",{className:"flex flex-wrap items-center justify-center gap-4",children:[e.jsx("button",{type:"button",onClick:()=>y(),className:"btn btn-secondary btn-touch rounded-full",children:"Resend the link"}),e.jsx("button",{type:"button",onClick:()=>i(r==="code"?"idle":"code"),className:"font-round text-sm font-semibold text-link hover:underline",style:{color:"var(--color-sky)"},children:r==="code"?"Hide the code field":"Or type the code from the email"}),e.jsx("button",{type:"button",onClick:()=>i("changeemail"),className:"font-round text-sm font-semibold text-link hover:underline",style:{color:"var(--color-sky)"},children:"Use a different email"})]}),r==="resent"?e.jsx("p",{className:"mx-auto mt-4 max-w-sm rounded-xl border border-grass bg-grass-soft px-4 py-3 text-sm text-grass-ink",children:"✓ Sent again — check your inbox."}):null,r==="code"?e.jsxs("div",{className:"mx-auto mt-4 max-w-xs",children:[e.jsx("label",{htmlFor:"signin-code",className:"mb-2 block font-round text-sm text-fg-muted",children:"6-digit code"}),e.jsx("input",{id:"signin-code",value:w,onChange:t=>{C(t.target.value)},inputMode:"numeric",autoComplete:"one-time-code",pattern:"[0-9]*",placeholder:"123456",disabled:b,"aria-invalid":l?!0:void 0,"aria-describedby":l?"signin-code-error":void 0,autoFocus:!0,className:"input w-full text-center text-2xl tracking-[0.4em]"}),e.jsx("output",{"aria-live":"polite",className:"mt-2 block text-center text-xs text-fg-dim",children:b?"Checking…":" "}),l?e.jsx("p",{id:"signin-code-error",role:"alert",className:"rounded-lg border border-danger-border bg-danger-soft px-3 py-2 text-center text-sm text-danger",children:l}):null]}):null,r==="changeemail"?e.jsxs("div",{className:"mx-auto mt-4 max-w-sm",children:[e.jsxs("div",{className:"flex gap-2",children:[e.jsx("input",{value:g,onChange:t=>j(t.target.value),placeholder:"you@example.com","aria-label":"Email address",type:"email",className:"input"}),e.jsx("button",{type:"button",onClick:()=>{const t=g.trim();/.+@.+\..+/.test(t)&&y(t)},className:"btn btn-primary btn-touch shrink-0 rounded-full",children:"Send link"})]}),e.jsx("button",{type:"button",onClick:()=>i("idle"),className:"mt-2 font-round text-sm text-fg-dim hover:text-accent",children:"Cancel"})]}):null]})}export{T as CheckEmail};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{a as m,j as e,N as h,L as l,Y as o}from"./index-
|
|
1
|
+
import{a as m,j as e,N as h,L as l,Y as o}from"./index-H6VNro-x.js";function u(s){return`${s.replace(/\/+$/,"")}/mcp`}function x(s){return`parachute-${s.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"")||"vault"}`}function p(s,t){return`claude mcp add --transport http ${x(s)} ${t}`}function y(){const s=m(n=>n.getActiveVault());if(!s)return e.jsx(h,{to:"/",replace:!0});const t=u(s.url),a=p(s.name,t);return e.jsxs("div",{className:"page-prose",children:[e.jsx("nav",{className:"mb-4 text-sm text-fg-dim",children:e.jsx(l,{to:"/",className:"focus-ring hover:text-accent",children:"← Home"})}),e.jsxs("header",{className:"mb-8",children:[e.jsx("p",{className:"eyebrow mb-1",children:s.name}),e.jsx("h1",{className:"page-title",children:"Connect your AI"}),e.jsx("p",{className:"mt-3 text-fg-muted",children:"Your vault speaks MCP — an open standard — so any AI can read and write it: Claude, ChatGPT, Claude Code, Cursor, or an agent you build. One memory, shared with every assistant you choose to connect."})]}),e.jsxs("section",{"aria-labelledby":"mcp-url-heading",className:"mb-8",children:[e.jsx("h2",{id:"mcp-url-heading",className:"eyebrow mb-2",children:"Your vault address"}),e.jsxs("p",{className:"mb-3 text-sm text-fg-muted",children:["Paste this wherever an AI asks for an MCP server. The"," ",e.jsx("code",{className:"rounded bg-bg-soft px-1 font-mono text-fg",children:"/mcp"})," suffix matters — it's the connection endpoint, not a page to open."]}),e.jsx(o,{value:t,label:"vault MCP URL"}),e.jsxs("p",{className:"mt-3 text-sm text-fg-muted",children:["It reads and writes only inside"," ",e.jsx("b",{className:"rounded-md bg-grass-soft px-2 py-0.5 font-medium text-grass-ink",children:s.name})," ","— never anywhere else. Disconnect anytime from your vault's settings."]})]}),e.jsx("h2",{className:"eyebrow mb-3",children:"Bring your AI in"}),e.jsxs("div",{className:"grid gap-4 sm:grid-cols-2",children:[e.jsx(d,{title:"Claude",initial:"C",tone:"coral",steps:g}),e.jsx(d,{title:"ChatGPT",initial:"G",tone:"grass",steps:b,note:"Exact menu names vary by ChatGPT version; the shape is the same — add an MCP server, paste the URL."})]}),e.jsxs("section",{"aria-labelledby":"other-clients-heading",className:"mt-8",children:[e.jsx("h2",{id:"other-clients-heading",className:"eyebrow mb-2",children:"Other AIs & the command line"}),e.jsx("p",{className:"mb-3 text-sm text-fg-muted",children:"That same URL works in any MCP-compatible client — Cursor, an agent you build, anywhere an AI asks for an MCP server. For Claude Code:"}),e.jsx(o,{value:a,label:"Claude Code command"})]}),e.jsx("div",{className:"mt-10 flex flex-wrap items-center gap-3 border-t border-border pt-6",children:e.jsx(l,{to:"/",className:"btn btn-primary btn-touch",children:"Done — back to your vault"})})]})}const g=[{key:"settings",body:e.jsxs(e.Fragment,{children:["Open"," ",e.jsx("a",{href:"https://claude.ai",target:"_blank",rel:"noopener noreferrer",className:"text-accent hover:underline",children:"claude.ai"})," ","and go to ",e.jsx("strong",{className:"text-fg",children:"Settings → Connectors"}),"."]})},{key:"add",body:e.jsxs(e.Fragment,{children:["Choose ",e.jsx("strong",{className:"text-fg",children:"Add custom connector"}),"."]})},{key:"paste",body:"Paste your vault address above and connect."}],b=[{key:"settings",body:e.jsxs(e.Fragment,{children:["Open ChatGPT's ",e.jsx("strong",{className:"text-fg",children:"Settings"})," and find its connectors (custom connectors need a paid ChatGPT plan)."]})},{key:"add",body:"Add a custom connector / MCP server."},{key:"paste",body:"Paste the same vault address and connect."}];function d({title:s,initial:t,tone:a,steps:n,note:r}){const i=a==="coral"?"bg-coral-soft text-coral-ink":"bg-grass-soft text-grass-ink";return e.jsxs("section",{className:"tile p-5","aria-label":`Connect ${s}`,children:[e.jsxs("div",{className:"mb-3 flex items-center gap-3",children:[e.jsx("span",{"aria-hidden":"true",className:`grid h-9 w-9 shrink-0 place-items-center rounded-full font-round text-sm font-semibold ${i}`,children:t}),e.jsx("h2",{className:"font-serif text-xl text-fg",children:s})]}),e.jsx("ol",{className:"list-decimal space-y-2 pl-5 text-sm text-fg-muted",children:n.map(c=>e.jsx("li",{children:c.body},c.key))}),r?e.jsx("p",{className:"mt-3 text-xs text-fg-dim",children:r}):null]})}export{y as ConnectAI};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{a as g,y as w,j as e,N as p,Q as k,Z as E,t as S,r as A,T as y,L as c,_ as b,$ as D,a0 as R,v as T,E as V,w as $,a1 as L,a2 as B,a3 as C,a4 as K,V as P}from"./index-
|
|
1
|
+
import{a as g,y as w,j as e,N as p,Q as k,Z as E,t as S,r as A,T as y,L as c,_ as b,$ as D,a0 as R,v as T,E as V,w as $,a1 as L,a2 as B,a3 as C,a4 as K,V as P}from"./index-H6VNro-x.js";import{u as O}from"./history-Ce29a331.js";function Z(){const s=g(t=>t.getActiveVault()),[a]=w(),n=a.get("date");return s?n===null?e.jsx(p,{to:"/",replace:!0}):e.jsx(F,{dateParam:n}):e.jsx(p,{to:"/",replace:!0})}function F({dateParam:s}){const a=O("/"),n=k(),t=s||n,r=E(t),o=S(),i=A.useMemo(()=>{const m=[],x=[];if(!o.data||!r)return{created:m,edited:x};for(const l of o.data){const j=y(l.createdAt),v=y(l.updatedAt??l.createdAt);j===t&&m.push(l),v===t&&j!==t&&x.push(l)}return{created:m,edited:x}},[o.data,r,t]);if(!r)return e.jsxs("div",{className:"page-prose",children:[e.jsxs("p",{className:"text-sm text-danger",children:["Invalid date in URL: ",t]}),e.jsx(c,{to:"/",className:"text-sm text-accent hover:underline",children:"Back to today"})]});const d=t===n,u=b(t,-1),h=b(t,1),f=t.slice(0,7);return e.jsxs("div",{className:"page-prose",children:[e.jsx("nav",{className:"mb-6 text-sm text-fg-dim",children:e.jsx("button",{type:"button",onClick:a,className:"hover:text-accent",children:"← Back"})}),e.jsxs("header",{className:"mb-6 flex flex-wrap items-baseline justify-between gap-3",children:[e.jsxs("div",{children:[e.jsx("p",{className:"eyebrow",children:d?"Today":"On"}),e.jsx("h1",{className:"page-title",children:D(t)})]}),e.jsxs("div",{className:"flex flex-wrap items-center gap-2 text-sm",children:[e.jsxs(c,{to:`/today?date=${u}`,className:"btn btn-secondary btn-sm","aria-label":"Previous day",children:["← ",u]}),d?null:e.jsx(c,{to:"/",className:"btn btn-secondary btn-sm",children:"Today"}),e.jsxs(c,{to:`/today?date=${h}`,className:"btn btn-secondary btn-sm","aria-label":"Next day",children:[h," →"]}),e.jsx(c,{to:`/calendar?month=${f}`,className:"btn btn-secondary btn-sm",children:"Calendar"}),e.jsx(c,{to:"/new",className:"btn btn-primary btn-sm",children:"+ New note"})]})]}),o.isPending?e.jsx(I,{}):o.isError&&!o.data?e.jsx(M,{error:o.error}):i.created.length===0&&i.edited.length===0?e.jsx(H,{isToday:d,targetKey:t}):e.jsxs("div",{className:"space-y-8",children:[o.isError?e.jsx(R,{}):null,i.created.length>0?e.jsx(N,{title:d?"Created today":`Created on ${t}`,notes:i.created}):null,i.edited.length>0?e.jsx(N,{title:d?"Edited today":`Edited on ${t}`,notes:i.edited}):null]})]})}function N({title:s,notes:a}){const n=g(r=>r.getActiveVault()),{roles:t}=L((n==null?void 0:n.id)??null);return e.jsxs("section",{children:[e.jsxs(B,{children:[s," (",a.length,")"]}),e.jsx(C,{children:a.map(r=>e.jsx(K,{note:r,pinnedTag:t.pinned,archivedTag:t.archived},r.id))})]})}function H({isToday:s,targetKey:a}){return e.jsx($,{title:s?"Nothing yet today — start capturing.":`Nothing on ${a}.`,action:s?e.jsx(c,{to:"/new",className:"btn btn-primary",children:"New note"}):void 0})}function I(){return e.jsx("div",{className:"space-y-3","aria-busy":"true",children:[0,1,2,3].map(s=>e.jsx(T,{className:"h-14 rounded-xl"},s))})}function M({error:s}){const a=s instanceof P;return e.jsx(V,{title:a?"Session expired":"Could not load notes",message:s.message,action:a?e.jsx(c,{to:"/add",className:"btn btn-primary",children:"Reconnect vault"}):void 0})}export{Z as DayView};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{a as u,a5 as m,a6 as p,r as d,j as e,N as x,a7 as h,L as g}from"./index-
|
|
1
|
+
import{a as u,a5 as m,a6 as p,r as d,j as e,N as x,a7 as h,L as g}from"./index-H6VNro-x.js";function j(){const a=u(s=>s.getActiveVault()),n=m(),r=p(s=>s.push),[t,o]=d.useState({kind:"idle"});if(!a)return e.jsx(x,{to:"/",replace:!0});const i=d.useCallback(async()=>{if(!n){r("Vault session unavailable — reconnect first","error");return}o({kind:"preparing"});try{const s=await n.exportVault(),c=new Date().toISOString().slice(0,10);f(s,`${a.name}-export-${c}.tar`),o({kind:"idle"}),r("Export downloaded.","success")}catch(s){if(s instanceof h){o({kind:"unsupported"});return}o({kind:"error",message:"Couldn't reach your vault — try again."})}},[n,a.name,r]),l=t.kind==="preparing";return e.jsxs("div",{className:"page-prose",children:[e.jsx("nav",{className:"mb-4 text-sm text-fg-dim",children:e.jsx(g,{to:"/notes",className:"focus-ring hover:text-accent",children:"← All notes"})}),e.jsxs("header",{className:"mb-8",children:[e.jsxs("h1",{className:"page-title",children:["Export notes from ",e.jsx("span",{className:"text-accent",children:a.name})]}),e.jsx("p",{className:"mt-3 text-fg-muted",children:"A portable folder of your notes — plain Markdown, with your tags, links, and attachments included. Yours to keep, no matter what happens to Parachute."})]}),e.jsxs("section",{className:"card space-y-5 rounded-xl p-6 shadow-soft",children:[e.jsxs("div",{children:[e.jsx("h2",{className:"font-serif text-lg text-fg",children:"What's in the download"}),e.jsxs("ul",{className:"mt-2 list-disc space-y-1 pl-5 text-sm text-fg-muted",children:[e.jsx("li",{children:"One markdown file per note, with tags, metadata, and links as frontmatter."}),e.jsx("li",{children:"Your tag definitions, so an import elsewhere keeps their structure."}),e.jsx("li",{children:"Attachment files — images, audio, PDF, video — alongside the notes that use them."})]})]}),e.jsxs("div",{className:"flex flex-wrap items-center gap-3",children:[e.jsx("button",{type:"button",onClick:i,disabled:l,className:"btn btn-primary btn-touch",children:l?"Preparing your export…":"Export my vault"}),l?e.jsx("span",{className:"text-sm text-fg-dim",children:"This can take a moment."}):null]}),t.kind==="error"?e.jsx("p",{className:"rounded-lg border border-danger-border bg-danger-soft px-3 py-2 text-sm text-danger",children:t.message}):null,t.kind==="unsupported"?e.jsxs("div",{className:"rounded-lg border border-border bg-bg-soft px-3 py-2 text-sm text-fg-muted",children:[e.jsx("p",{children:"Export over the web isn't available on this vault yet — self-hosted vaults don't carry this door today."}),e.jsxs("p",{className:"mt-1",children:["From the vault's command line, run"," ",e.jsx("code",{className:"rounded bg-card px-1 font-mono text-fg",children:"parachute-vault export <dir>"})," ","to get the same portable folder."]})]}):null]})]})}function f(a,n){const r=URL.createObjectURL(a),t=document.createElement("a");t.href=r,t.download=n,document.body.appendChild(t),t.click(),t.remove(),URL.revokeObjectURL(r)}export{j as Export};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{a8 as te,a9 as ee,V as re,aa as Mt,ab as kt,ac as ne,a as se,a5 as ie,b as ae,y as oe,a6 as le,r as gt,j as D,N as Tt,L as ce}from"./index-
|
|
1
|
+
import{a8 as te,a9 as ee,V as re,aa as Mt,ab as kt,ac as ne,a as se,a5 as ie,b as ae,y as oe,a6 as le,r as gt,j as D,N as Tt,L as ce}from"./index-H6VNro-x.js";import{f as ue,A as he}from"./attachment-upload-B8YiOVGU.js";const de=new Set(["png","jpg","jpeg","gif","webp"]),fe=new Set(["wav","mp3","m4a","ogg","webm"]),pe=new Set(["mp4"]),me=new Set(["txt","json","csv","yaml","yml","svg","tsv","log"]);function ge(y){const S=y.toLowerCase();return de.has(S)?"image":S==="pdf"?"pdf":fe.has(S)?"audio":pe.has(S)?"video":me.has(S)?"text":"unsupported"}function _e(y){return ge(ue(y))}function be(y){return y==="image"||y==="pdf"||y==="audio"||y==="video"}function $t(y){return typeof y.text=="function"?y.text():new Promise((S,o)=>{const b=new FileReader;b.onload=()=>S(b.result),b.onerror=()=>o(b.error??new Error("FileReader failed")),b.readAsText(y)})}function ye(y){const S=new Map,o=new Map;for(const b of y){const h=b.filename.toLowerCase();S.has(h)||S.set(h,b),o.set(Nt(b.sourcePath),b)}return{byBasename:S,byPath:o}}function Nt(y){let S=y.trim();try{S=decodeURIComponent(S)}catch{}return S=S.replace(/\\/g,"/").replace(/^\.\//,"").replace(/^\/+/,""),S.toLowerCase()}function Ct(y){const S=Nt(y),o=S.lastIndexOf("/");return o>=0?S.slice(o+1):S}function Bt(y){return/\.[a-z0-9]+$/i.test(Ct(y))}function Dt(y,S){const o=Nt(S),b=y.byPath.get(o);if(b)return b;for(const[h,i]of y.byPath)if(h===o||h.endsWith(`/${o}`))return i;return y.byBasename.get(Ct(S))??null}function Ft(y,S){const o=`/api/storage/${y.storagePath}`,b=S||y.filename;return y.isImage?``:`[${b}](${o})`}function ve(y,S){let o=0;const b=new Set,h=/(!?)\[\[([^\]|#]+)(?:[#|][^\]]*)?\]\]/g,i=y.replace(h,(c,m,v)=>{if(!Bt(v))return c;const _=Dt(S,v);return _?(o++,b.add(_.sourcePath),Ft(_,Ct(v))):c}),n=/(!?)\[([^\]]*)\]\(\s*(<[^>]+>|[^)\s]+)(\s+[^)]*)?\)/g;return{content:i.replace(n,(c,m,v,_,w)=>{const s=_.startsWith("<")&&_.endsWith(">")?_.slice(1,-1):_;if(/^(https?:|mailto:|tel:|#|\/api\/storage\/)/i.test(s.trim())||!Bt(s))return c;const d=Dt(S,s);if(!d)return c;o++,b.add(d.sourcePath);const a=v.trim()||Ct(s);return Ft(d,a)}),rewritten:o,referenced:b}}const we=5,ke=500;async function It(y){const{client:S,notes:o,onProgress:b,signal:h}=y,i=Math.max(1,y.concurrency??we),n=[];let r=0,c=0,m=!1;const v=o.map(ze);async function _(){for(;;){if(h!=null&&h.aborted||m)return;const l=r++;if(l>=o.length)return;const u=o[l],p=v[l],x=await xe(S,u,p,h);n[l]=x,c++,x.status==="errored"&&x.reason.startsWith("auth:")&&(m=!0),b==null||b({done:c,total:o.length})}}const w=Array.from({length:Math.min(i,o.length)},()=>_());await Promise.all(w);for(let l=0;l<o.length;l++)n[l]||(n[l]={status:"errored",sourcePath:o[l].sourcePath,reason:m?"Skipped — vault session ended before this note was reached.":"Skipped — import was cancelled."});let s=0,d=0,a=0;for(const l of n)l.status==="created"?s++:l.status==="skipped"?d++:a++;return{created:s,skipped:d,errored:a,outcomes:n}}async function xe(y,S,o,b){try{const h=await Se(y,o,b);return{status:"created",sourcePath:S.sourcePath,noteId:h.id}}catch(h){return h instanceof te||h instanceof ee?{status:"skipped",sourcePath:S.sourcePath,reason:h.message||"Already exists in vault"}:h instanceof re?{status:"errored",sourcePath:S.sourcePath,reason:`auth: ${h.message}`}:h instanceof Mt?{status:"errored",sourcePath:S.sourcePath,reason:`vault unreachable (${h.status}): ${h.message}`}:{status:"errored",sourcePath:S.sourcePath,reason:h instanceof Error?h.message:String(h)}}}async function Se(y,S,o){const b={};o&&(b.signal=o);try{return await y.createNote(S,b)}catch(h){if(!Ce(h)||o!=null&&o.aborted)throw h;return await Ee(ke,o),await y.createNote(S,b)}}function Ce(y){return y instanceof Mt}function Ee(y,S){return new Promise(o=>{const b=setTimeout(()=>{S==null||S.removeEventListener("abort",h),o()},y),h=()=>{clearTimeout(b),o()};S&&S.addEventListener("abort",h,{once:!0})})}function ze(y){const S={content:y.content};y.path&&(S.path=y.path),y.tags.length>0&&(S.tags=y.tags),Object.keys(y.metadata).length>0&&(S.metadata=y.metadata);const o=S;return y.id&&(o.id=y.id),y.createdAt&&(o.created_at=y.createdAt),S}const Lt="Imported files",Ae=20;async function Ie(y){const{client:S,parsed:o,signal:b}=y,h=[],i=[],n=[],r=[];for(const l of o.attachments)be(l.kind)?i.push(l):l.kind==="text"?n.push(l):r.push(l);const c=new Map;for(const l of i){if(b!=null&&b.aborted){h.push({status:"skipped",sourcePath:l.sourcePath,reason:"Skipped — import was cancelled."});continue}try{const u=new File([l.blob],l.filename,{type:l.blob.type||void 0}),p=await S.uploadStorageFile(u,{signal:b});c.set(l.sourcePath,{attachment:l,storagePath:p.path,mimeType:p.mimeType,isImage:p.mimeType.startsWith("image/")})}catch(u){h.push({status:"errored",sourcePath:l.sourcePath,reason:`Upload failed: ${u instanceof Error?u.message:String(u)}`})}}const m=Ne(c),v=new Map,_=o.notes.map(l=>{const{content:u,referenced:p}=ve(l.content,m);return v.set(l.sourcePath,p),{...l,content:u}}),w=await It({client:S,notes:_,...y.concurrency!==void 0?{concurrency:y.concurrency}:{},...y.onProgress?{onProgress:y.onProgress}:{},...b?{signal:b}:{}}),s=new Map;for(const l of w.outcomes)l.status==="created"&&s.set(l.sourcePath,l.noteId);const d=new Map;for(const[l,u]of v){const p=s.get(l);if(p)for(const x of u){let E=d.get(x);E||(E=new Set,d.set(x,E)),E.add(p)}}for(const[l,u]of c){const p=d.get(l);if(!p||p.size===0)continue;let x=0;for(const E of p){if(b!=null&&b.aborted)break;try{await S.linkAttachment(E,{path:u.storagePath,mimeType:u.mimeType}),x++}catch{}}h.push({status:"uploaded",sourcePath:l,storagePath:u.storagePath,references:x})}if(n.length>0&&!(b!=null&&b.aborted)){const l=[];for(const p of n)l.push(await je(p));const u=await It({client:S,notes:l,...y.concurrency!==void 0?{concurrency:y.concurrency}:{},...b?{signal:b}:{}});for(let p=0;p<n.length;p++){const x=n[p],E=u.outcomes[p];(E==null?void 0:E.status)==="created"?h.push({status:"uploaded",sourcePath:x.sourcePath,storagePath:`note:${E.noteId}`,references:1,asNote:!0}):h.push({status:"skipped",sourcePath:x.sourcePath,reason:(E==null?void 0:E.status)==="skipped"?`Imported as note, but ${E.reason}`:`Could not import as note: ${(E==null?void 0:E.status)==="errored"?E.reason:"unknown"}`})}}else if(n.length>0)for(const l of n)h.push({status:"skipped",sourcePath:l.sourcePath,reason:"Skipped — import was cancelled."});const a=[...c.entries()].filter(([l])=>{var u;return!(((u=d.get(l))==null?void 0:u.size)??0)}).map(([,l])=>l);if(a.length>0)if(b!=null&&b.aborted)for(const l of a)h.push({status:"uploaded",sourcePath:l.attachment.sourcePath,storagePath:l.storagePath,references:0});else await Re(S,a,h,y.concurrency,b);for(const l of r)h.push({status:"skipped",sourcePath:l.sourcePath,reason:`.${l.ext||"?"} is not a vault storage type — not imported. (Re-save it in a supported format to bring it across.)`});return Te(w,h)}function Ne(y){return ye([...y.values()].map(S=>({sourcePath:S.attachment.sourcePath,storagePath:S.storagePath,isImage:S.isImage,filename:S.attachment.filename})))}async function je(y){let S="";try{S=await $t(y.blob)}catch{S=""}const o=Pe(y.ext)?`\`\`\`${Oe(y.ext)}
|
|
2
2
|
${S}
|
|
3
3
|
\`\`\`
|
|
4
4
|
`:`${S}
|