ReviewOS

also looking at this

stacks/wildloop

feat: native trail maps and complete native mobile screens

#1017
Draft chris wants to merge codex/trail-experience into main
60 files +2505 -823

Review threads live on the whole diff, not on one commit, so none are shown here - a thread's line means something in the branch's final form, and painting it into an intermediate step would put it on code it is not about.

resources/native/Record.stxmodified+14-7
Changes to resources/native/Record.stx
@@ -109,14 +109,21 @@ async function recover() {
109109 notice.set('Your finished recording is saved on this device. Retry the upload when connected.')
110110 return
111111 }
112 if (saved?.phase==='starting') {
113 recording.set(saved);running.set(false);paused.set(false)
114 notice.set('The recording start was interrupted. Retry starting with its saved identity, or discard the intent.')
115 return
116 }
117112 if (!owner) {recording.set(null);running.set(false);paused.set(false);return}
118113 await session!.api.readToken()
119 const host=await craft.location?.getRecordingState(saved?.id ? {expectedId:saved.id} : undefined)
114 let host
115 try { host=await craft.location?.getRecordingState(saved?.id ? {expectedId:saved.id} : undefined) }
116 catch (cause) {
117 // A registered intent may not have reached the host. An explicit native
118 // ownership conflict permits retrying that same ID, never a replacement.
119 if (saved?.phase==='starting' && cause instanceof Error && 'code' in cause && cause.code==='RECORDING_CONFLICT') {
120 if (!current()) return
121 recording.set(saved);running.set(false);paused.set(false)
122 notice.set('The recording start was interrupted. Retry starting with its saved identity, or discard the intent.')
123 return
124 }
125 throw cause
126 }
120127 if (!current()) return
121128 if (host?.active && (!saved || (saved.id && saved.id !== host.id))) {
122129 error.set('A device recording is already active. Its account checkpoint could not be verified, so it has been retained without starting another recording.')
@@ -129,7 +136,7 @@ async function recover() {
129136 const fixes=await craft.location!.readRecording({expectedId:saved.id!})
130137 if (!current()) return
131138 append(fixes)
132 if (!host.active) recording.set({...recording()!,phase:'stopped',endedAt:saved.endedAt ?? Date.now()})
139 recording.set({...recording()!,phase:host.active ? 'recording' : 'stopped',startedAt:host.startedAt ?? saved.startedAt,...host.active ? {} : {endedAt:saved.endedAt ?? Date.now()}})
133140 await persist(recording()!)
134141 if (!current()) return
135142 if(host.active) attachWatch()