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/TrailDetail.stxmodified+19-7
Changes to resources/native/TrailDetail.stx
@@ -69,9 +69,6 @@ function textOf(event: any): string { return String(event?.text ?? '') }
6969function profilePath(): string { return trailProfilePath(profile()) }
7070function photoUrls(row: any): string[] { return parsePhotoList(row.photos).map(url=>url.startsWith('/') ? nativeApiOrigin(craft)+url : url) }
7171function photoUrl(url:string):string {return url.startsWith('/') ? nativeApiOrigin(craft)+url : url}
72function weatherLine(day: any, index: number): string {
73 return `${forecastDayLabel(day.date, index)}: ${day.label}, ${Math.round(day.low)} to ${Math.round(day.high)}°F`
74}
7572function fitRoute() {
7673 region.set(null)
7774 inspected.set(null)
@@ -333,12 +330,27 @@ onMount(() => onNativeAccountChange(craft, () => { viewer.set(0); saved.set(fals
333330 <Text :class="ui.title">Weather</Text>
334331 <Text :show="!forecast()" :class="ui.caption">No forecast is available right now. Pull down to retry.</Text>
335332 <View :show="forecast()" class="gap-3 mt-2">
336 <Text :show="forecast()?.current" :text="Math.round(forecast()?.current.temperature) + '°F, ' + forecast()?.current.label" :class="ui.body" />
337 <Text :for="(day, index) in forecast()?.days ?? []" :key="day.date" :text="weatherLine(day, index)" :class="ui.body" />
333 <View :show="forecast()?.current" class="gap-1 py-2">
334 <Text :text="Math.round(forecast()?.current.temperature) + '°F'" class="text-[42px] font-semibold text-[#192414] dark:text-[#f0f5ec]" />
335 <Text :text="forecast()?.current.label" :class="ui.body" />
336 </View>
337 <View :for="(day, index) in forecast()?.days ?? []" :key="day.date" class="gap-1 py-3 border-t border-[#e7edde] dark:border-[#314536]">
338 <View class="flex-row items-center justify-between gap-3">
339 <Text :text="forecastDayLabel(day.date, index)" :class="ui.title" />
340 <Text :text="Math.round(day.low) + '°–' + Math.round(day.high) + '°F'" :class="ui.body" />
341 </View>
342 <Text :text="day.label" :class="ui.caption" />
343 <Text :show="Number.isFinite(day.windMph) && Number.isFinite(day.precipitationMm)" :text="Math.round(day.windMph) + ' mph wind · ' + (day.precipitationMm / 25.4).toFixed(2) + ' in precipitation'" :class="ui.caption" />
344 </View>
338345 <Button @click="craft.linking.openURL(forecast()?.attribution.url)" :class="ui.caption" :text="forecast()?.attribution.label" />
339346 </View>
340 <Text class="mt-5" :class="ui.title">Surface types</Text>
341 <Text :for="surface in surfaces()" :key="surface.label" :text="surface.label" :class="ui.body" />
347 </View>
348 <View :class="ui.card" class="mt-3 gap-2">
349 <Text :class="ui.title">Surface types</Text>
350 <View :for="surface in surfaces()" :key="surface.label" :class="ui.row">
351 <View class="h-5 w-5 rounded-[4px]" :style="{backgroundColor:surface.color}" />
352 <Text :text="surface.label" :class="ui.body" />
353 </View>
342354 <Text :show="!surfaces().length" :class="ui.caption">Surface information has not been recorded for this trail.</Text>
343355 </View>
344356 <Text :class="ui.header">Reviews</Text>