@adminide-stack/yantra-mobile 12.0.131 → 12.0.132-alpha.0

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.
Files changed (149) hide show
  1. package/lib/components/CustomDrawer.js +2 -2
  2. package/lib/components/CustomDrawer.js.map +1 -1
  3. package/lib/features/apps/AppsCatalog.js +7 -1
  4. package/lib/features/apps/AppsCatalog.js.map +1 -1
  5. package/lib/features/apps/nativeSurfaceTwin.js +35 -0
  6. package/lib/features/apps/nativeSurfaceTwin.js.map +1 -0
  7. package/lib/features/canvas/CanvasBoardsGrid.js +49 -49
  8. package/lib/features/canvas/CanvasBoardsGrid.js.map +1 -1
  9. package/lib/features/canvas/CanvasExperience.js +69 -28
  10. package/lib/features/canvas/CanvasExperience.js.map +1 -1
  11. package/lib/features/canvas/audioEditor/AudioWaveform.js +1 -1
  12. package/lib/features/canvas/designCatalog.js +63 -39
  13. package/lib/features/canvas/designCatalog.js.map +1 -1
  14. package/lib/features/canvas/designCategories.js +56 -0
  15. package/lib/features/canvas/designCategories.js.map +1 -1
  16. package/lib/features/canvas/generator/DirectorSheet.js +3 -2
  17. package/lib/features/canvas/generator/DirectorSheet.js.map +1 -1
  18. package/lib/features/canvas/home/HeroComposer.js +165 -76
  19. package/lib/features/canvas/home/HeroComposer.js.map +1 -1
  20. package/lib/features/canvas/home/HeroMonitor.js +75 -46
  21. package/lib/features/canvas/home/HeroMonitor.js.map +1 -1
  22. package/lib/features/canvas/home/TemplatesGallery.js +273 -138
  23. package/lib/features/canvas/home/TemplatesGallery.js.map +1 -1
  24. package/lib/features/canvas/home/templatesGallerySources.js +221 -0
  25. package/lib/features/canvas/home/templatesGallerySources.js.map +1 -0
  26. package/lib/features/canvas/homeWork.js +12 -11
  27. package/lib/features/canvas/homeWork.js.map +1 -1
  28. package/lib/features/canvas/lazyEditors.js +51 -0
  29. package/lib/features/canvas/lazyEditors.js.map +1 -0
  30. package/lib/features/canvas/rankedCatalogSearch.js +33 -23
  31. package/lib/features/canvas/rankedCatalogSearch.js.map +1 -1
  32. package/lib/features/canvas/set/SetViewportWebView.js +1 -1
  33. package/lib/features/canvas/set/agent/tools.js +1 -1
  34. package/lib/features/canvas/studioCatalog.js +2 -2
  35. package/lib/features/canvas/studioCatalog.js.map +1 -1
  36. package/lib/features/canvas/templateSearch.js +8 -1
  37. package/lib/features/canvas/templateSearch.js.map +1 -1
  38. package/lib/features/canvas/videoEditor/BlurBoxOverlay.js +1 -1
  39. package/lib/features/design/DesignEditorExperience.js +103 -29
  40. package/lib/features/design/DesignEditorExperience.js.map +1 -1
  41. package/lib/features/design/DesignExperience.js +4 -3
  42. package/lib/features/design/DesignExperience.js.map +1 -1
  43. package/lib/features/design/doc/aiDesign.js +1 -1
  44. package/lib/features/design/doc/aiDesign.js.map +1 -1
  45. package/lib/features/design/doc/artifacts.js +40 -13
  46. package/lib/features/design/doc/artifacts.js.map +1 -1
  47. package/lib/features/design/doc/chart.js +387 -13
  48. package/lib/features/design/doc/chart.js.map +1 -1
  49. package/lib/features/design/doc/copyStyle.js +47 -0
  50. package/lib/features/design/doc/copyStyle.js.map +1 -0
  51. package/lib/features/design/doc/docOps.js +22 -4
  52. package/lib/features/design/doc/docOps.js.map +1 -1
  53. package/lib/features/design/doc/geometry.js +32 -18
  54. package/lib/features/design/doc/geometry.js.map +1 -1
  55. package/lib/features/design/doc/newDoc.js +5 -1
  56. package/lib/features/design/doc/newDoc.js.map +1 -1
  57. package/lib/features/design/doc/resize.js +101 -0
  58. package/lib/features/design/doc/resize.js.map +1 -0
  59. package/lib/features/design/doc/sizes.js +15 -2
  60. package/lib/features/design/doc/sizes.js.map +1 -1
  61. package/lib/features/design/editor/ChartDataPanel.js +49 -9
  62. package/lib/features/design/editor/ChartDataPanel.js.map +1 -1
  63. package/lib/features/design/editor/CropOverlay.js +1 -1
  64. package/lib/features/design/editor/DesignCanvas.js +14 -13
  65. package/lib/features/design/editor/DesignCanvas.js.map +1 -1
  66. package/lib/features/design/editor/ExportSheet.js +8 -4
  67. package/lib/features/design/editor/ExportSheet.js.map +1 -1
  68. package/lib/features/design/editor/LayerTools.js +37 -5
  69. package/lib/features/design/editor/LayerTools.js.map +1 -1
  70. package/lib/features/design/editor/Slideshow.js +30 -5
  71. package/lib/features/design/editor/Slideshow.js.map +1 -1
  72. package/lib/features/design/editor/useDesignSave.js +21 -36
  73. package/lib/features/design/editor/useDesignSave.js.map +1 -1
  74. package/lib/features/design/export/exportDesign.js +3 -1
  75. package/lib/features/design/export/exportDesign.js.map +1 -1
  76. package/lib/features/design/home/DesignHome.js +7 -2
  77. package/lib/features/design/home/DesignHome.js.map +1 -1
  78. package/lib/features/design/render/DesignPageView.js +1 -1
  79. package/lib/features/design/render/DesignPageView.js.map +1 -1
  80. package/lib/features/design/render/PageCapture.js +11 -10
  81. package/lib/features/design/render/PageCapture.js.map +1 -1
  82. package/lib/features/design/render/fontRegistry.js +27 -3
  83. package/lib/features/design/render/fontRegistry.js.map +1 -1
  84. package/lib/features/design/render/svgParts.js +27 -74
  85. package/lib/features/design/render/svgParts.js.map +1 -1
  86. package/lib/features/devices/brands/qnScale.js +7 -2
  87. package/lib/features/devices/brands/qnScale.js.map +1 -1
  88. package/lib/features/devices/brands/uuids.js +2 -1
  89. package/lib/features/devices/brands/uuids.js.map +1 -1
  90. package/lib/features/devices/devices.js +2 -1
  91. package/lib/features/devices/devices.js.map +1 -1
  92. package/lib/features/docs/DocBlockRow.js +1 -1
  93. package/lib/features/docs/docArtifacts.js +2 -2
  94. package/lib/features/docs/docArtifacts.js.map +1 -1
  95. package/lib/features/health/healthSync.js +3 -1
  96. package/lib/features/health/healthSync.js.map +1 -1
  97. package/lib/features/health/nativeHealth.js +8 -0
  98. package/lib/features/health/nativeHealth.js.map +1 -0
  99. package/lib/features/links/openInApp.js +11 -1
  100. package/lib/features/links/openInApp.js.map +1 -1
  101. package/lib/features/webbuilder/WebBuilderExperience.js +135 -28
  102. package/lib/features/webbuilder/WebBuilderExperience.js.map +1 -1
  103. package/lib/features/webbuilder/buildFragments.js +14 -6
  104. package/lib/features/webbuilder/buildFragments.js.map +1 -1
  105. package/lib/features/webbuilder/components/PreviewFrame.js +28 -3
  106. package/lib/features/webbuilder/components/PreviewFrame.js.map +1 -1
  107. package/lib/features/webbuilder/components/PreviewScreen.js +1 -1
  108. package/lib/features/webbuilder/components/PreviewScreen.js.map +1 -1
  109. package/lib/features/webbuilder/components/ProjectChat.js +24 -5
  110. package/lib/features/webbuilder/components/ProjectChat.js.map +1 -1
  111. package/lib/features/webbuilder/components/ProjectsScreen.js +18 -2
  112. package/lib/features/webbuilder/components/ProjectsScreen.js.map +1 -1
  113. package/lib/features/webbuilder/components/ui.js +20 -6
  114. package/lib/features/webbuilder/components/ui.js.map +1 -1
  115. package/lib/features/webbuilder/exportCode.js +52 -0
  116. package/lib/features/webbuilder/exportCode.js.map +1 -0
  117. package/lib/features/webbuilder/siteAddress.js +71 -0
  118. package/lib/features/webbuilder/siteAddress.js.map +1 -0
  119. package/lib/features/webbuilder/widgetBlocks.js +30 -0
  120. package/lib/features/webbuilder/widgetBlocks.js.map +1 -0
  121. package/lib/screens/Chat/index.js +5 -6
  122. package/lib/screens/Chat/index.js.map +1 -1
  123. package/lib/screens/ChatHistory/index.js +3 -2
  124. package/lib/screens/ChatHistory/index.js.map +1 -1
  125. package/lib/screens/Home/HomeScreen.js +20 -4
  126. package/lib/screens/Home/HomeScreen.js.map +1 -1
  127. package/lib/screens/Home/components/WebBuilderCodePrewarm.js +18 -0
  128. package/lib/screens/Home/components/WebBuilderCodePrewarm.js.map +1 -0
  129. package/lib/screens/WebBuilderNative/index.js +1 -1
  130. package/lib/screens/WebBuilderNative/index.js.map +1 -1
  131. package/lib/screens/WebBuilderNative/keepAlive.js +112 -0
  132. package/lib/screens/WebBuilderNative/keepAlive.js.map +1 -0
  133. package/lib/screens/WebBuilderNative/runningBuilds.js +40 -0
  134. package/lib/screens/WebBuilderNative/runningBuilds.js.map +1 -0
  135. package/lib/screens/WebBuilderNative/useSandboxKeepAlive.js +57 -0
  136. package/lib/screens/WebBuilderNative/useSandboxKeepAlive.js.map +1 -0
  137. package/lib/screens/WebBuilderNative/useWebBuilderGallery.js +73 -14
  138. package/lib/screens/WebBuilderNative/useWebBuilderGallery.js.map +1 -1
  139. package/lib/screens/WebBuilderNative/useWebBuilderHost.js +143 -34
  140. package/lib/screens/WebBuilderNative/useWebBuilderHost.js.map +1 -1
  141. package/lib/screens/WebBuilderNative/useWebBuilderJobs.js +17 -5
  142. package/lib/screens/WebBuilderNative/useWebBuilderJobs.js.map +1 -1
  143. package/lib/screens/WebBuilderNative/versionUndo.js +144 -0
  144. package/lib/screens/WebBuilderNative/versionUndo.js.map +1 -0
  145. package/lib/screens/WebBuilderNative/webbuilderSnapshotKey.js +1 -0
  146. package/lib/screens/WebBuilderNative/webbuilderSnapshotKey.js.map +1 -0
  147. package/lib/screens/WebBuilderNative/webbuilderTransport.js +90 -6
  148. package/lib/screens/WebBuilderNative/webbuilderTransport.js.map +1 -1
  149. package/package.json +4 -4
@@ -1 +1 @@
1
- {"version":3,"file":"svgParts.js","sources":["../../../../src/features/design/render/svgParts.tsx"],"sourcesContent":["/**\n * Layers as react-native-svg elements, in their own box's coordinates - the\n * drawing both the live canvas (where a view alone cannot do it: true outlines,\n * curved text, filtered pictures) and the export page (render/PageSvg.tsx)\n * share, so what is exported is what was on screen.\n *\n * Every length on a layer is a fraction of the page WIDTH, so each part takes\n * `W`, the page's drawn width in the units of the svg it lands in.\n *\n * Text cannot wrap itself in svg. Its lines come measured from a hidden RN\n * Text of the same style (`MeasuredLine`, render/TextMeasure.tsx), and each\n * line is drawn as one svg text at the place RN laid it out.\n */\nimport React from 'react';\nimport { chartMax, pieSlices, readChartData, slicePath } from '../doc/chart';\nimport { curveArc } from '../doc/curve';\nimport { adjustColorMatrix } from '../doc/imageAdjust';\nimport { scalePath } from '../doc/pathScale';\nimport { gradientLine, isStrokeShape, roundRectD, shapeSpec } from '../doc/shapes';\nimport { layerSpans, type RunStyle, type TextSpan } from '../doc/textLayout';\nimport { GLITCH_COLORS, liftShadow, neonBlur, offsetAlong, rgbaOf, spliceFillOf, tintOf } from '../doc/textEffects';\nimport {\n layerFontFamily,\n type ChartLayer,\n type DesignFontPair,\n type ImageLayer,\n type ShapeLayer,\n type TextLayer,\n} from '../doc/types';\nimport { resolveTextFont } from './fontRegistry';\n\nexport type SvgModule = typeof import('react-native-svg');\n\n/** One laid-out line of a text layer, in the units it was measured at. */\nexport interface MeasuredLine {\n text: string;\n x: number;\n y: number;\n width: number;\n height: number;\n ascender: number;\n descender: number;\n}\n\n/** What a curved layer needs measured: its words on one line. */\nexport interface MeasuredCurve {\n width: number;\n ascender: number;\n descender: number;\n}\n\n/** A per-layer id prefix that survives being several times in one svg. */\nconst safeId = (id: string) => id.replace(/[^A-Za-z0-9_-]/g, '_');\n\n// ── Shapes ───────────────────────────────────────────────────────────────\n\nexport function shapeSvg(svg: SvgModule, layer: ShapeLayer, bw: number, bh: number, W: number): React.ReactElement {\n const { Path, Line, Polygon, Defs, LinearGradient, Stop, G } = svg;\n const stroke = layer.stroke && layer.stroke !== 'none' ? layer.stroke : undefined;\n const sw = Math.max(0.5, (layer.strokeWidthFrac ?? 0) * W);\n const gradient = layer.fillTo ? gradientLine(0, 0, bw, bh, layer.fillAngle ?? 180) : null;\n const gid = `sg-${safeId(layer.id)}`;\n const paint = gradient ? `url(#${gid})` : layer.fill;\n let body: React.ReactNode;\n if (isStrokeShape(layer.shape)) {\n const vertical = bh > bw;\n const thickness = Math.max(sw, 1);\n const span = vertical ? bh : bw;\n const headLen = layer.shape === 'arrow' ? Math.min(span * 0.4, thickness * 3.2) : 0;\n const c = vertical ? bw / 2 : bh / 2;\n const tip = vertical ? bh : bw;\n body = (\n <>\n {vertical ? (\n <Line\n x1={c}\n y1={0}\n x2={c}\n y2={bh - headLen}\n stroke={paint}\n strokeWidth={thickness}\n strokeLinecap=\"round\"\n />\n ) : (\n <Line\n x1={0}\n y1={c}\n x2={bw - headLen}\n y2={c}\n stroke={paint}\n strokeWidth={thickness}\n strokeLinecap=\"round\"\n />\n )}\n {headLen > 0 ? (\n <Polygon\n fill={paint}\n points={\n vertical\n ? `${c},${tip} ${c - thickness * 1.6},${tip - headLen} ${c + thickness * 1.6},${tip - headLen}`\n : `${tip},${c} ${tip - headLen},${c - thickness * 1.6} ${tip - headLen},${c + thickness * 1.6}`\n }\n />\n ) : null}\n </>\n );\n } else {\n const d =\n layer.shape === 'rect'\n ? roundRectD(bw, bh, layer.radiusFrac ?? 0)\n : scalePath(shapeSpec(layer.shape).d, bw, bh);\n body = <Path d={d} fill={paint} stroke={stroke} strokeWidth={stroke ? sw : 0} strokeLinejoin=\"round\" />;\n }\n return (\n <G>\n {gradient ? (\n <Defs>\n <LinearGradient\n id={gid}\n gradientUnits=\"userSpaceOnUse\"\n x1={gradient[0]}\n y1={gradient[1]}\n x2={gradient[2]}\n y2={gradient[3]}\n >\n <Stop offset=\"0\" stopColor={layer.fill} />\n <Stop offset=\"1\" stopColor={layer.fillTo} />\n </LinearGradient>\n </Defs>\n ) : null}\n {body}\n </G>\n );\n}\n\n// ── Charts ───────────────────────────────────────────────────────────────\n\n/** Every series: grouped or stacked bars and rows, a line or area per series, a pie of the first. */\nexport function chartSvg(svg: SvgModule, layer: ChartLayer, bw: number, bh: number): React.ReactElement | null {\n const { Rect, Path, Polyline, G, Text: SvgText, Circle } = svg;\n const data = readChartData(layer);\n const colors = layer.colors?.length ? layer.colors : ['#38bdf8'];\n if (data.categories.length === 0) return null;\n const ink = layer.ink ?? '#475569';\n const n = data.categories.length;\n const legend = Boolean(layer.legend) && data.series.length > 0;\n const legendH = legend ? Math.max(10, bh * 0.08) : 0;\n const ph = bh - legendH;\n let body: React.ReactNode;\n if (layer.chart === 'pie' || layer.chart === 'donut') {\n const r = Math.min(bw, ph) / 2;\n const inner = layer.chart === 'donut' ? r * (layer.holeFrac ?? 0.55) : 0;\n body = pieSlices(data.series[0]?.values ?? []).map((s) => (\n <Path\n key={s.index}\n d={slicePath(bw / 2, ph / 2, r, s.start, s.sweep, inner)}\n fill={colors[s.index % colors.length]}\n />\n ));\n } else if (layer.chart === 'line' || layer.chart === 'area') {\n const stacked = layer.chart === 'area' && Boolean(layer.stacked);\n const max = chartMax(data, stacked);\n const x = (i: number) => (n === 1 ? bw / 2 : (i / (n - 1)) * bw);\n const y = (v: number) => ph - (Math.max(0, v) / max) * ph;\n const base = new Array(n).fill(0);\n body = data.series.map((s, si) => {\n const color = colors[si % colors.length];\n const tops = s.values.map((v, i) => (stacked ? base[i] + Math.max(0, v) : v));\n const bottoms = stacked ? [...base] : new Array(n).fill(0);\n if (stacked) tops.forEach((t, i) => (base[i] = t));\n if (layer.chart === 'area') {\n const top = tops.map((v, i) => `${i === 0 ? 'M' : 'L'}${x(i)} ${y(v)}`).join('');\n const bottom = bottoms\n .map((v, i) => [i, v] as const)\n .reverse()\n .map(([i, v]) => `L${x(i)} ${y(v)}`)\n .join('');\n return <Path key={si} d={`${top}${bottom}Z`} fill={color} opacity={stacked ? 0.85 : 0.55} />;\n }\n const pts = tops.map((v, i) => `${x(i)},${y(v)}`).join(' ');\n const sw = Math.max(1.5, ph * 0.012);\n return (\n <G key={si}>\n <Polyline\n points={pts}\n fill=\"none\"\n stroke={color}\n strokeWidth={sw}\n strokeLinejoin=\"round\"\n strokeLinecap=\"round\"\n />\n {tops.map((v, i) => (\n <Circle key={i} cx={x(i)} cy={y(v)} r={sw * 1.3} fill={color} />\n ))}\n </G>\n );\n });\n } else {\n const horizontal = layer.chart === 'row';\n const stacked = Boolean(layer.stacked);\n const max = chartMax(data, stacked);\n const band = (horizontal ? ph : bw) / n;\n const groups = stacked ? 1 : data.series.length;\n const barW = (band * 0.7) / groups;\n const length = horizontal ? bw : ph;\n const rects: React.ReactNode[] = [];\n for (let i = 0; i < n; i += 1) {\n let offset = 0;\n data.series.forEach((s, si) => {\n const v = Math.max(0, s.values[i] ?? 0);\n const size = (v / max) * length;\n const across = i * band + band * 0.15 + (stacked ? 0 : si * barW);\n const along = stacked ? offset : 0;\n offset += size;\n const color = colors[si % colors.length];\n rects.push(\n horizontal ? (\n <Rect key={`${i}-${si}`} x={along} y={across} width={size} height={barW} fill={color} />\n ) : (\n <Rect\n key={`${i}-${si}`}\n x={across}\n y={ph - along - size}\n width={barW}\n height={size}\n fill={color}\n />\n ),\n );\n });\n }\n body = rects;\n }\n const legendFont = Math.max(6, legendH * 0.6);\n const pie = layer.chart === 'pie' || layer.chart === 'donut';\n const entries = pie ? data.categories : data.series.map((s) => s.name);\n const slot = entries.length ? bw / entries.length : bw;\n return (\n <G>\n {body}\n {legend\n ? entries.map((name, i) => (\n <G key={`lg${i}`}>\n <Rect\n x={i * slot}\n y={ph + legendH * 0.3}\n width={legendFont * 0.8}\n height={legendFont * 0.8}\n rx={legendFont * 0.2}\n fill={colors[i % colors.length]}\n />\n <SvgText\n x={i * slot + legendFont * 1.1}\n y={ph + legendH * 0.3 + legendFont * 0.75}\n fontSize={legendFont}\n fill={ink}\n >\n {name || `Series ${i + 1}`}\n </SvgText>\n </G>\n ))\n : null}\n </G>\n );\n}\n\n// ── Images ───────────────────────────────────────────────────────────────\n\n/** Where the whole source sits behind a box that shows only `crop` of it. */\nexport function croppedPlacement(bw: number, bh: number, crop?: { x: number; y: number; w: number; h: number }) {\n const c = crop && crop.w > 0 && crop.h > 0 ? crop : { x: 0, y: 0, w: 1, h: 1 };\n const iw = bw / c.w;\n const ih = bh / c.h;\n return { left: -c.x * iw, top: -c.y * ih, width: iw, height: ih };\n}\n\n/** A picture with its crop, frame, look and shadow (web drawImageLayer). */\nexport function imageSvg(\n svg: SvgModule,\n layer: ImageLayer,\n bw: number,\n bh: number,\n W: number,\n onLoad?: () => void,\n): React.ReactElement | null {\n if (!layer.src) return null;\n const { Defs, ClipPath, Path, Rect, Image: SvgImage, G, Filter, FeColorMatrix, FeGaussianBlur } = svg;\n const id = safeId(layer.id);\n const place = croppedPlacement(bw, bh, layer.crop);\n const outline = layer.clipPath ? scalePath(layer.clipPath, bw, bh) : null;\n const matrix = adjustColorMatrix(layer.adjust);\n const blur = (layer.adjust?.blurFrac ?? 0) * W;\n const look = Boolean((matrix || blur) && Filter && FeColorMatrix && FeGaussianBlur);\n const shadow = layer.shadow;\n const off = shadow ? offsetAlong(shadow.angle, shadow.distFrac * W) : null;\n const shadowBlur = shadow ? shadow.blurFrac * W : 0;\n return (\n <G>\n <Defs>\n <ClipPath id={`ic-${id}`}>\n {outline ? <Path d={outline} /> : <Rect x={0} y={0} width={bw} height={bh} />}\n </ClipPath>\n {look ? (\n <Filter id={`if-${id}`} x=\"-20%\" y=\"-20%\" width=\"140%\" height=\"140%\">\n {matrix ? <FeColorMatrix type=\"matrix\" values={matrix} /> : null}\n {blur ? <FeGaussianBlur stdDeviation={blur / 2} /> : null}\n </Filter>\n ) : null}\n {shadow && shadowBlur > 0 && Filter && FeGaussianBlur ? (\n <Filter id={`is-${id}`} x=\"-50%\" y=\"-50%\" width=\"200%\" height=\"200%\">\n <FeGaussianBlur stdDeviation={shadowBlur / 2} />\n </Filter>\n ) : null}\n </Defs>\n {shadow && off ? (\n <G\n transform={`translate(${off.dx}, ${off.dy})`}\n opacity={shadow.alpha}\n {...(shadowBlur > 0 && Filter && FeGaussianBlur ? { filter: `url(#is-${id})` } : {})}\n >\n {outline ? (\n <Path d={outline} fill={shadow.color} />\n ) : (\n <Rect x={0} y={0} width={bw} height={bh} fill={shadow.color} />\n )}\n </G>\n ) : null}\n <G clipPath={`url(#ic-${id})`}>\n <SvgImage\n href={{ uri: layer.src }}\n x={place.left}\n y={place.top}\n width={place.width}\n height={place.height}\n preserveAspectRatio=\"none\"\n onLoad={onLoad}\n {...(look ? { filter: `url(#if-${id})` } : {})}\n />\n </G>\n </G>\n );\n}\n\n// ── Text ─────────────────────────────────────────────────────────────────\n\n/** Text a view cannot draw faithfully: true outlines, a splice, a curve. */\nexport function needsSvgText(layer: TextLayer): boolean {\n return Boolean(layer.curve) || layer.effect?.kind === 'hollow' || layer.effect?.kind === 'splice';\n}\n\ninterface SvgFont {\n fontFamily?: string;\n fontWeight?: string;\n fontStyle?: 'normal' | 'italic';\n}\n\nfunction svgFont(family: string, weight: number | undefined, italic: boolean | undefined): SvgFont {\n const f = resolveTextFont(family, weight, italic);\n const out: SvgFont = {};\n if (f.fontFamily) out.fontFamily = f.fontFamily;\n if (f.fontWeight) out.fontWeight = String(f.fontWeight);\n if (f.fontStyle) out.fontStyle = f.fontStyle;\n return out;\n}\n\n/** One stretch of a line in one style. */\ninterface Piece {\n text: string;\n style: RunStyle | null;\n}\n\n/** The pieces each measured line is made of, found by walking the drawn text alongside the lines. */\nexport function linePieces(spans: TextSpan[], lines: Array<Pick<MeasuredLine, 'text'>>): Piece[][] {\n const drawn = spans.map((s) => s.text).join('');\n const styleAt: Array<RunStyle | null> = [];\n for (const s of spans) for (let i = 0; i < s.text.length; i += 1) styleAt.push(s.style);\n let cursor = 0;\n return lines.map((line) => {\n let start = cursor;\n const t = line.text;\n if (drawn.startsWith(t, cursor)) {\n cursor += t.length;\n } else {\n const at = drawn.indexOf(t.replace(/\\s+$/, ''), cursor);\n if (at < 0) return [{ text: t.replace(/\\n$/, ''), style: null }];\n start = at;\n cursor = at + t.length;\n }\n if (drawn[cursor] === '\\n' && !t.endsWith('\\n')) cursor += 1;\n const pieces: Piece[] = [];\n for (let i = start; i < Math.min(start + t.length, drawn.length); i += 1) {\n const ch = drawn[i];\n if (ch === '\\n') continue;\n const st = styleAt[i] ?? null;\n const prev = pieces[pieces.length - 1];\n if (prev && prev.style === st) prev.text += ch;\n else pieces.push({ text: ch, style: st });\n }\n return pieces;\n });\n}\n\ninterface Ink {\n fill?: string | ((piece: Piece) => string);\n stroke?: string | ((piece: Piece) => string);\n strokeWidth?: number;\n dx?: number;\n dy?: number;\n opacity?: number;\n filter?: string;\n}\n\n/**\n * A text layer as svg, from its measured lines: the effect's copies behind\n * the words, then the words (web shared/textRaster.ts paint order).\n */\nexport function textSvg(\n svg: SvgModule,\n layer: TextLayer,\n lines: MeasuredLine[],\n W: number,\n fontPair?: DesignFontPair,\n curve?: MeasuredCurve | null,\n): React.ReactElement {\n const { G, Text: SvgText, TSpan, Rect, Defs, Filter, FeGaussianBlur, Path, TextPath } = svg;\n const id = safeId(layer.id);\n const fs = Math.max(1, layer.fontSizeFrac * W);\n const family = layerFontFamily(layer, fontPair);\n const baseFont = svgFont(family, layer.fontWeight, layer.italic);\n const spans = layerSpans(layer);\n const own = (piece: Piece) => piece.style?.color ?? layer.color;\n const fx = layer.effect;\n const canBlur = Boolean(Filter && FeGaussianBlur);\n const blurs: Array<{ key: string; std: number }> = [];\n const blurId = (std: number) => {\n const key = `tb-${id}-${blurs.length}`;\n blurs.push({ key, std });\n return `url(#${key})`;\n };\n const tracking = (layer.letterSpacingFrac ?? 0) * W;\n const deco = (st: RunStyle | null) => {\n const u = st?.underline ?? layer.underline;\n const s = st?.strike ?? layer.strike;\n return u && s ? 'underline line-through' : u ? 'underline' : s ? 'line-through' : undefined;\n };\n const pieceProps = (piece: Piece) => {\n const st = piece.style;\n const props: Record<string, unknown> = {};\n if (st?.fontSizeFrac != null) props.fontSize = st.fontSizeFrac * W;\n if (st?.letterSpacingFrac != null) props.letterSpacing = st.letterSpacingFrac * W;\n if (st && (st.fontFamily != null || st.fontWeight != null || st.italic != null)) {\n Object.assign(\n props,\n svgFont(st.fontFamily ?? family, st.fontWeight ?? layer.fontWeight, st.italic ?? layer.italic),\n );\n }\n const d = deco(st);\n if (d) props.textDecoration = d;\n return props;\n };\n const paintOf = (v: Ink['fill'], piece: Piece) => (typeof v === 'function' ? v(piece) : v);\n\n let draw: (ink: Ink, key: string) => React.ReactElement;\n let highlight: React.ReactNode = null;\n if (curve) {\n const arc = curveArc(curve.width, layer.curve, curve.ascender, curve.descender);\n const flat = spans.map((s) => ({ text: s.text.replace(/\\n/g, ' '), style: s.style }));\n const pathId = `tp-${id}`;\n const shiftX = (layer.w * W) / 2;\n const shiftY = arc ? -arc.minY : curve.ascender;\n draw = (ink, key) => (\n <G\n key={key}\n transform={`translate(${shiftX + (ink.dx ?? 0)}, ${shiftY + (ink.dy ?? 0)})`}\n opacity={ink.opacity}\n {...(ink.filter ? { filter: ink.filter } : {})}\n >\n <SvgText fontSize={fs} letterSpacing={tracking} textAnchor=\"middle\" {...baseFont}>\n <TextPath href={`#${pathId}`} startOffset=\"50%\">\n {flat.map((p, i) => (\n <TSpan\n key={i}\n {...pieceProps(p)}\n fill={paintOf(ink.fill, p) ?? 'none'}\n stroke={paintOf(ink.stroke, p)}\n strokeWidth={ink.strokeWidth}\n strokeLinejoin=\"round\"\n >\n {p.text}\n </TSpan>\n ))}\n </TextPath>\n </SvgText>\n </G>\n );\n const arcDef = arc ? (\n <Path id={pathId} d={arc.d} fill=\"none\" />\n ) : (\n <Path id={pathId} d={`M${-curve.width / 2} 0H${curve.width / 2}`} fill=\"none\" />\n );\n highlight = <Defs>{arcDef}</Defs>;\n } else {\n const pieces = linePieces(spans, lines);\n draw = (ink, key) => (\n <G\n key={key}\n transform={ink.dx || ink.dy ? `translate(${ink.dx ?? 0}, ${ink.dy ?? 0})` : undefined}\n opacity={ink.opacity}\n {...(ink.filter ? { filter: ink.filter } : {})}\n >\n {lines.map((line, li) => (\n <SvgText\n key={li}\n x={line.x}\n y={line.y + line.ascender}\n fontSize={fs}\n letterSpacing={tracking}\n {...baseFont}\n >\n {(pieces[li] ?? []).map((p, pi) => (\n <TSpan\n key={pi}\n {...pieceProps(p)}\n fill={paintOf(ink.fill, p) ?? 'none'}\n stroke={paintOf(ink.stroke, p)}\n strokeWidth={ink.strokeWidth}\n strokeLinejoin=\"round\"\n >\n {p.text}\n </TSpan>\n ))}\n </SvgText>\n ))}\n </G>\n );\n if (fx?.kind === 'background') {\n const spread = fx.spreadEm * fs;\n highlight = lines\n .filter((l) => l.width > 0)\n .map((l, i) => (\n <Rect\n key={`hl${i}`}\n x={l.x - spread}\n y={l.y}\n width={l.width + spread * 2}\n height={l.height}\n rx={(fx.roundness * l.height) / 2}\n fill={rgbaOf(fx.color, fx.opacity)}\n />\n ));\n }\n }\n\n const layers: React.ReactElement[] = [];\n // Copies behind the text.\n if (fx?.kind === 'echo') {\n const o = offsetAlong(fx.angle, fx.offsetEm * fs);\n layers.push(draw({ fill: (p) => rgbaOf(fx.color ?? own(p), 0.25), dx: o.dx * 2, dy: o.dy * 2 }, 'echo2'));\n layers.push(draw({ fill: (p) => rgbaOf(fx.color ?? own(p), 0.5), dx: o.dx, dy: o.dy }, 'echo1'));\n } else if (fx?.kind === 'glitch') {\n const [a, b] = GLITCH_COLORS[fx.palette] ?? GLITCH_COLORS['cyan-magenta'];\n const o = offsetAlong(fx.angle, fx.offsetEm * fs);\n layers.push(draw({ fill: a, dx: -o.dx, dy: -o.dy }, 'gl-a'));\n layers.push(draw({ fill: b, dx: o.dx, dy: o.dy }, 'gl-b'));\n } else if (fx?.kind === 'splice') {\n const o = offsetAlong(fx.angle, fx.offsetEm * fs);\n layers.push(draw({ fill: (p) => fx.color ?? spliceFillOf(own(p)), dx: o.dx, dy: o.dy }, 'splice'));\n }\n // Shadows: a blurred copy where the platform blurs, else a soft offset copy.\n const shadowCopy = (color: string, blur: number, dx: number, dy: number, key: string, opacity?: number) =>\n layers.push(\n draw({ fill: color, dx, dy, opacity, ...(canBlur && blur > 0.5 ? { filter: blurId(blur / 2) } : {}) }, key),\n );\n if (layer.shadow) {\n const s = layer.shadow;\n const o = offsetAlong(s.angle, s.distFrac * W);\n shadowCopy(rgbaOf(s.color, s.alpha), s.blurFrac * W, o.dx, o.dy, 'drop');\n } else if (fx?.kind === 'lift') {\n const l = liftShadow(fx.intensity, fs);\n shadowCopy(l.color, l.blur, 0, l.dy, 'lift');\n } else if (fx?.kind === 'glow') {\n shadowCopy(rgbaOf(fx.color ?? layer.color, fx.opacity), fx.sizeEm * fs, 0, 0, 'glow');\n } else if (fx?.kind === 'neon') {\n shadowCopy(layer.color, neonBlur(fx.intensity, fs), 0, 0, 'neon');\n }\n // The words.\n if (fx?.kind === 'hollow' || fx?.kind === 'splice') {\n layers.push(draw({ fill: 'none', stroke: own, strokeWidth: fs * fx.thicknessEm }, 'words'));\n } else {\n if (layer.outline && layer.outline.widthEm > 0) {\n layers.push(\n draw(\n {\n fill: layer.outline.color,\n stroke: layer.outline.color,\n strokeWidth: layer.outline.widthEm * fs * 2,\n },\n 'outline',\n ),\n );\n }\n const neon = fx?.kind === 'neon' ? 0.45 + 0.35 * fx.intensity : 0;\n layers.push(draw({ fill: neon ? (p) => tintOf(own(p), neon) : own }, 'words'));\n }\n return (\n <G>\n {blurs.length ? (\n <Defs>\n {blurs.map((b) => (\n <Filter key={b.key} id={b.key} x=\"-50%\" y=\"-50%\" width=\"200%\" height=\"200%\">\n <FeGaussianBlur stdDeviation={b.std} />\n </Filter>\n ))}\n </Defs>\n ) : null}\n {highlight}\n {layers}\n </G>\n );\n}\n\n/** The height a curved layer draws at, in the units its curve was measured in. */\nexport function curvedHeight(layer: TextLayer, curve: MeasuredCurve): number {\n const arc = curveArc(curve.width, layer.curve, curve.ascender, curve.descender);\n return arc ? arc.height : curve.ascender + curve.descender;\n}\n"],"names":["_a","_b","_c"],"mappings":"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"}
1
+ {"version":3,"file":"svgParts.js","sources":["../../../../src/features/design/render/svgParts.tsx"],"sourcesContent":["/**\n * Layers as react-native-svg elements, in their own box's coordinates - the\n * drawing both the live canvas (where a view alone cannot do it: true outlines,\n * curved text, filtered pictures) and the export page (render/PageSvg.tsx)\n * share, so what is exported is what was on screen.\n *\n * Every length on a layer is a fraction of the page WIDTH, so each part takes\n * `W`, the page's drawn width in the units of the svg it lands in.\n *\n * Text cannot wrap itself in svg. Its lines come measured from a hidden RN\n * Text of the same style (`MeasuredLine`, render/TextMeasure.tsx), and each\n * line is drawn as one svg text at the place RN laid it out.\n */\nimport React from 'react';\nimport { chartMarks } from '../doc/chart';\nimport { curveArc } from '../doc/curve';\nimport { adjustColorMatrix } from '../doc/imageAdjust';\nimport { scalePath } from '../doc/pathScale';\nimport { gradientLine, isStrokeShape, roundRectD, shapeSpec } from '../doc/shapes';\nimport { layerSpans, type RunStyle, type TextSpan } from '../doc/textLayout';\nimport { GLITCH_COLORS, liftShadow, neonBlur, offsetAlong, rgbaOf, spliceFillOf, tintOf } from '../doc/textEffects';\nimport {\n layerFontFamily,\n type ChartLayer,\n type DesignFontPair,\n type ImageLayer,\n type ShapeLayer,\n type TextLayer,\n} from '../doc/types';\nimport { resolveTextFont } from './fontRegistry';\n\nexport type SvgModule = typeof import('react-native-svg');\n\n/** One laid-out line of a text layer, in the units it was measured at. */\nexport interface MeasuredLine {\n text: string;\n x: number;\n y: number;\n width: number;\n height: number;\n ascender: number;\n descender: number;\n}\n\n/** What a curved layer needs measured: its words on one line. */\nexport interface MeasuredCurve {\n width: number;\n ascender: number;\n descender: number;\n}\n\n/** A per-layer id prefix that survives being several times in one svg. */\nconst safeId = (id: string) => id.replace(/[^A-Za-z0-9_-]/g, '_');\n\n// ── Shapes ───────────────────────────────────────────────────────────────\n\nexport function shapeSvg(svg: SvgModule, layer: ShapeLayer, bw: number, bh: number, W: number): React.ReactElement {\n const { Path, Line, Polygon, Defs, LinearGradient, Stop, G } = svg;\n const stroke = layer.stroke && layer.stroke !== 'none' ? layer.stroke : undefined;\n const sw = Math.max(0.5, (layer.strokeWidthFrac ?? 0) * W);\n const gradient = layer.fillTo ? gradientLine(0, 0, bw, bh, layer.fillAngle ?? 180) : null;\n const gid = `sg-${safeId(layer.id)}`;\n const paint = gradient ? `url(#${gid})` : layer.fill;\n let body: React.ReactNode;\n if (isStrokeShape(layer.shape)) {\n const vertical = bh > bw;\n const thickness = Math.max(sw, 1);\n const span = vertical ? bh : bw;\n const headLen = layer.shape === 'arrow' ? Math.min(span * 0.4, thickness * 3.2) : 0;\n const c = vertical ? bw / 2 : bh / 2;\n const tip = vertical ? bh : bw;\n body = (\n <>\n {vertical ? (\n <Line\n x1={c}\n y1={0}\n x2={c}\n y2={bh - headLen}\n stroke={paint}\n strokeWidth={thickness}\n strokeLinecap=\"round\"\n />\n ) : (\n <Line\n x1={0}\n y1={c}\n x2={bw - headLen}\n y2={c}\n stroke={paint}\n strokeWidth={thickness}\n strokeLinecap=\"round\"\n />\n )}\n {headLen > 0 ? (\n <Polygon\n fill={paint}\n points={\n vertical\n ? `${c},${tip} ${c - thickness * 1.6},${tip - headLen} ${c + thickness * 1.6},${tip - headLen}`\n : `${tip},${c} ${tip - headLen},${c - thickness * 1.6} ${tip - headLen},${c + thickness * 1.6}`\n }\n />\n ) : null}\n </>\n );\n } else {\n const d =\n layer.shape === 'rect'\n ? roundRectD(bw, bh, layer.radiusFrac ?? 0)\n : scalePath(shapeSpec(layer.shape).d, bw, bh);\n body = <Path d={d} fill={paint} stroke={stroke} strokeWidth={stroke ? sw : 0} strokeLinejoin=\"round\" />;\n }\n return (\n <G>\n {gradient ? (\n <Defs>\n <LinearGradient\n id={gid}\n gradientUnits=\"userSpaceOnUse\"\n x1={gradient[0]}\n y1={gradient[1]}\n x2={gradient[2]}\n y2={gradient[3]}\n >\n <Stop offset=\"0\" stopColor={layer.fill} />\n <Stop offset=\"1\" stopColor={layer.fillTo} />\n </LinearGradient>\n </Defs>\n ) : null}\n {body}\n </G>\n );\n}\n\n// ── Charts ───────────────────────────────────────────────────────────────\n\n/**\n * A chart as web draws it (doc/chart.ts `chartMarks`, web drawChart): title,\n * legend, value ticks with gridlines and axis labels, bars below zero, value\n * labels - so a web-made chart looks the same here and in native exports.\n */\nexport function chartSvg(svg: SvgModule, layer: ChartLayer, bw: number, bh: number): React.ReactElement | null {\n const { Path, Line, G, Text: SvgText, Circle } = svg;\n const marks = chartMarks(layer, bw, bh);\n if (!marks.length) return null;\n return (\n <G>\n {marks.map((m, i) => {\n switch (m.t) {\n case 'path':\n return (\n <Path\n key={i}\n d={m.d}\n fill={m.fill ?? 'none'}\n {...(m.stroke\n ? {\n stroke: m.stroke,\n strokeWidth: m.sw,\n strokeLinejoin: 'round' as const,\n strokeLinecap: 'round' as const,\n }\n : {})}\n {...(m.opacity !== undefined ? { opacity: m.opacity } : {})}\n />\n );\n case 'line':\n return Line ? (\n <Line\n key={i}\n x1={m.x1}\n y1={m.y1}\n x2={m.x2}\n y2={m.y2}\n stroke={m.stroke}\n strokeWidth={m.sw}\n opacity={m.opacity}\n />\n ) : (\n <Path\n key={i}\n d={`M${m.x1} ${m.y1}L${m.x2} ${m.y2}`}\n stroke={m.stroke}\n strokeWidth={m.sw}\n opacity={m.opacity}\n />\n );\n case 'circle':\n return <Circle key={i} cx={m.cx} cy={m.cy} r={m.r} fill={m.fill} />;\n case 'text':\n return (\n <SvgText\n key={i}\n x={m.x}\n y={m.y}\n fontSize={m.size}\n {...(m.weight ? { fontWeight: m.weight } : {})}\n fill={m.fill}\n textAnchor={m.anchor}\n >\n {m.text}\n </SvgText>\n );\n default:\n return null;\n }\n })}\n </G>\n );\n}\n\n// ── Images ───────────────────────────────────────────────────────────────\n\n/** Where the whole source sits behind a box that shows only `crop` of it. */\nexport function croppedPlacement(bw: number, bh: number, crop?: { x: number; y: number; w: number; h: number }) {\n const c = crop && crop.w > 0 && crop.h > 0 ? crop : { x: 0, y: 0, w: 1, h: 1 };\n const iw = bw / c.w;\n const ih = bh / c.h;\n return { left: -c.x * iw, top: -c.y * ih, width: iw, height: ih };\n}\n\n/** A picture with its crop, frame, look and shadow (web drawImageLayer). */\nexport function imageSvg(\n svg: SvgModule,\n layer: ImageLayer,\n bw: number,\n bh: number,\n W: number,\n onLoad?: () => void,\n): React.ReactElement | null {\n if (!layer.src) return null;\n const { Defs, ClipPath, Path, Rect, Image: SvgImage, G, Filter, FeColorMatrix, FeGaussianBlur } = svg;\n const id = safeId(layer.id);\n const place = croppedPlacement(bw, bh, layer.crop);\n const outline = layer.clipPath ? scalePath(layer.clipPath, bw, bh) : null;\n const matrix = adjustColorMatrix(layer.adjust);\n const blur = (layer.adjust?.blurFrac ?? 0) * W;\n const look = Boolean((matrix || blur) && Filter && FeColorMatrix && FeGaussianBlur);\n const shadow = layer.shadow;\n const off = shadow ? offsetAlong(shadow.angle, shadow.distFrac * W) : null;\n const shadowBlur = shadow ? shadow.blurFrac * W : 0;\n return (\n <G>\n <Defs>\n <ClipPath id={`ic-${id}`}>\n {outline ? <Path d={outline} /> : <Rect x={0} y={0} width={bw} height={bh} />}\n </ClipPath>\n {look ? (\n <Filter id={`if-${id}`} x=\"-20%\" y=\"-20%\" width=\"140%\" height=\"140%\">\n {matrix ? <FeColorMatrix type=\"matrix\" values={matrix} /> : null}\n {blur ? <FeGaussianBlur stdDeviation={blur / 2} /> : null}\n </Filter>\n ) : null}\n {shadow && shadowBlur > 0 && Filter && FeGaussianBlur ? (\n <Filter id={`is-${id}`} x=\"-50%\" y=\"-50%\" width=\"200%\" height=\"200%\">\n <FeGaussianBlur stdDeviation={shadowBlur / 2} />\n </Filter>\n ) : null}\n </Defs>\n {shadow && off ? (\n <G\n transform={`translate(${off.dx}, ${off.dy})`}\n opacity={shadow.alpha}\n {...(shadowBlur > 0 && Filter && FeGaussianBlur ? { filter: `url(#is-${id})` } : {})}\n >\n {outline ? (\n <Path d={outline} fill={shadow.color} />\n ) : (\n <Rect x={0} y={0} width={bw} height={bh} fill={shadow.color} />\n )}\n </G>\n ) : null}\n <G clipPath={`url(#ic-${id})`}>\n <SvgImage\n href={{ uri: layer.src }}\n x={place.left}\n y={place.top}\n width={place.width}\n height={place.height}\n preserveAspectRatio=\"none\"\n onLoad={onLoad}\n {...(look ? { filter: `url(#if-${id})` } : {})}\n />\n </G>\n </G>\n );\n}\n\n// ── Text ─────────────────────────────────────────────────────────────────\n\n/** Text a view cannot draw faithfully: true outlines, a splice, a curve. */\nexport function needsSvgText(layer: TextLayer): boolean {\n return Boolean(layer.curve) || layer.effect?.kind === 'hollow' || layer.effect?.kind === 'splice';\n}\n\ninterface SvgFont {\n fontFamily?: string;\n fontWeight?: string;\n fontStyle?: 'normal' | 'italic';\n}\n\nfunction svgFont(family: string, weight: number | undefined, italic: boolean | undefined): SvgFont {\n const f = resolveTextFont(family, weight, italic);\n const out: SvgFont = {};\n if (f.fontFamily) out.fontFamily = f.fontFamily;\n if (f.fontWeight) out.fontWeight = String(f.fontWeight);\n if (f.fontStyle) out.fontStyle = f.fontStyle;\n return out;\n}\n\n/** One stretch of a line in one style. */\ninterface Piece {\n text: string;\n style: RunStyle | null;\n}\n\n/** The pieces each measured line is made of, found by walking the drawn text alongside the lines. */\nexport function linePieces(spans: TextSpan[], lines: Array<Pick<MeasuredLine, 'text'>>): Piece[][] {\n const drawn = spans.map((s) => s.text).join('');\n const styleAt: Array<RunStyle | null> = [];\n for (const s of spans) for (let i = 0; i < s.text.length; i += 1) styleAt.push(s.style);\n let cursor = 0;\n return lines.map((line) => {\n let start = cursor;\n const t = line.text;\n if (drawn.startsWith(t, cursor)) {\n cursor += t.length;\n } else {\n const at = drawn.indexOf(t.replace(/\\s+$/, ''), cursor);\n if (at < 0) return [{ text: t.replace(/\\n$/, ''), style: null }];\n start = at;\n cursor = at + t.length;\n }\n if (drawn[cursor] === '\\n' && !t.endsWith('\\n')) cursor += 1;\n const pieces: Piece[] = [];\n for (let i = start; i < Math.min(start + t.length, drawn.length); i += 1) {\n const ch = drawn[i];\n if (ch === '\\n') continue;\n const st = styleAt[i] ?? null;\n const prev = pieces[pieces.length - 1];\n if (prev && prev.style === st) prev.text += ch;\n else pieces.push({ text: ch, style: st });\n }\n return pieces;\n });\n}\n\ninterface Ink {\n fill?: string | ((piece: Piece) => string);\n stroke?: string | ((piece: Piece) => string);\n strokeWidth?: number;\n dx?: number;\n dy?: number;\n opacity?: number;\n filter?: string;\n}\n\n/**\n * A text layer as svg, from its measured lines: the effect's copies behind\n * the words, then the words (web shared/textRaster.ts paint order).\n */\nexport function textSvg(\n svg: SvgModule,\n layer: TextLayer,\n lines: MeasuredLine[],\n W: number,\n fontPair?: DesignFontPair,\n curve?: MeasuredCurve | null,\n): React.ReactElement {\n const { G, Text: SvgText, TSpan, Rect, Defs, Filter, FeGaussianBlur, Path, TextPath } = svg;\n const id = safeId(layer.id);\n const fs = Math.max(1, layer.fontSizeFrac * W);\n const family = layerFontFamily(layer, fontPair);\n const baseFont = svgFont(family, layer.fontWeight, layer.italic);\n const spans = layerSpans(layer);\n const own = (piece: Piece) => piece.style?.color ?? layer.color;\n const fx = layer.effect;\n const canBlur = Boolean(Filter && FeGaussianBlur);\n const blurs: Array<{ key: string; std: number }> = [];\n const blurId = (std: number) => {\n const key = `tb-${id}-${blurs.length}`;\n blurs.push({ key, std });\n return `url(#${key})`;\n };\n const tracking = (layer.letterSpacingFrac ?? 0) * W;\n const deco = (st: RunStyle | null) => {\n const u = st?.underline ?? layer.underline;\n const s = st?.strike ?? layer.strike;\n return u && s ? 'underline line-through' : u ? 'underline' : s ? 'line-through' : undefined;\n };\n const pieceProps = (piece: Piece) => {\n const st = piece.style;\n const props: Record<string, unknown> = {};\n if (st?.fontSizeFrac != null) props.fontSize = st.fontSizeFrac * W;\n if (st?.letterSpacingFrac != null) props.letterSpacing = st.letterSpacingFrac * W;\n if (st && (st.fontFamily != null || st.fontWeight != null || st.italic != null)) {\n Object.assign(\n props,\n svgFont(st.fontFamily ?? family, st.fontWeight ?? layer.fontWeight, st.italic ?? layer.italic),\n );\n }\n const d = deco(st);\n if (d) props.textDecoration = d;\n return props;\n };\n const paintOf = (v: Ink['fill'], piece: Piece) => (typeof v === 'function' ? v(piece) : v);\n\n let draw: (ink: Ink, key: string) => React.ReactElement;\n let highlight: React.ReactNode = null;\n if (curve) {\n const arc = curveArc(curve.width, layer.curve, curve.ascender, curve.descender);\n const flat = spans.map((s) => ({ text: s.text.replace(/\\n/g, ' '), style: s.style }));\n const pathId = `tp-${id}`;\n const shiftX = (layer.w * W) / 2;\n const shiftY = arc ? -arc.minY : curve.ascender;\n draw = (ink, key) => (\n <G\n key={key}\n transform={`translate(${shiftX + (ink.dx ?? 0)}, ${shiftY + (ink.dy ?? 0)})`}\n opacity={ink.opacity}\n {...(ink.filter ? { filter: ink.filter } : {})}\n >\n <SvgText fontSize={fs} letterSpacing={tracking} textAnchor=\"middle\" {...baseFont}>\n <TextPath href={`#${pathId}`} startOffset=\"50%\">\n {flat.map((p, i) => (\n <TSpan\n key={i}\n {...pieceProps(p)}\n fill={paintOf(ink.fill, p) ?? 'none'}\n stroke={paintOf(ink.stroke, p)}\n strokeWidth={ink.strokeWidth}\n strokeLinejoin=\"round\"\n >\n {p.text}\n </TSpan>\n ))}\n </TextPath>\n </SvgText>\n </G>\n );\n const arcDef = arc ? (\n <Path id={pathId} d={arc.d} fill=\"none\" />\n ) : (\n <Path id={pathId} d={`M${-curve.width / 2} 0H${curve.width / 2}`} fill=\"none\" />\n );\n highlight = <Defs>{arcDef}</Defs>;\n } else {\n const pieces = linePieces(spans, lines);\n draw = (ink, key) => (\n <G\n key={key}\n transform={ink.dx || ink.dy ? `translate(${ink.dx ?? 0}, ${ink.dy ?? 0})` : undefined}\n opacity={ink.opacity}\n {...(ink.filter ? { filter: ink.filter } : {})}\n >\n {lines.map((line, li) => (\n <SvgText\n key={li}\n x={line.x}\n y={line.y + line.ascender}\n fontSize={fs}\n letterSpacing={tracking}\n {...baseFont}\n >\n {(pieces[li] ?? []).map((p, pi) => (\n <TSpan\n key={pi}\n {...pieceProps(p)}\n fill={paintOf(ink.fill, p) ?? 'none'}\n stroke={paintOf(ink.stroke, p)}\n strokeWidth={ink.strokeWidth}\n strokeLinejoin=\"round\"\n >\n {p.text}\n </TSpan>\n ))}\n </SvgText>\n ))}\n </G>\n );\n if (fx?.kind === 'background') {\n const spread = fx.spreadEm * fs;\n highlight = lines\n .filter((l) => l.width > 0)\n .map((l, i) => (\n <Rect\n key={`hl${i}`}\n x={l.x - spread}\n y={l.y}\n width={l.width + spread * 2}\n height={l.height}\n rx={(fx.roundness * l.height) / 2}\n fill={rgbaOf(fx.color, fx.opacity)}\n />\n ));\n }\n }\n\n const layers: React.ReactElement[] = [];\n // Copies behind the text.\n if (fx?.kind === 'echo') {\n const o = offsetAlong(fx.angle, fx.offsetEm * fs);\n layers.push(draw({ fill: (p) => rgbaOf(fx.color ?? own(p), 0.25), dx: o.dx * 2, dy: o.dy * 2 }, 'echo2'));\n layers.push(draw({ fill: (p) => rgbaOf(fx.color ?? own(p), 0.5), dx: o.dx, dy: o.dy }, 'echo1'));\n } else if (fx?.kind === 'glitch') {\n const [a, b] = GLITCH_COLORS[fx.palette] ?? GLITCH_COLORS['cyan-magenta'];\n const o = offsetAlong(fx.angle, fx.offsetEm * fs);\n layers.push(draw({ fill: a, dx: -o.dx, dy: -o.dy }, 'gl-a'));\n layers.push(draw({ fill: b, dx: o.dx, dy: o.dy }, 'gl-b'));\n } else if (fx?.kind === 'splice') {\n const o = offsetAlong(fx.angle, fx.offsetEm * fs);\n layers.push(draw({ fill: (p) => fx.color ?? spliceFillOf(own(p)), dx: o.dx, dy: o.dy }, 'splice'));\n }\n // Shadows: a blurred copy where the platform blurs, else a soft offset copy.\n const shadowCopy = (color: string, blur: number, dx: number, dy: number, key: string, opacity?: number) =>\n layers.push(\n draw({ fill: color, dx, dy, opacity, ...(canBlur && blur > 0.5 ? { filter: blurId(blur / 2) } : {}) }, key),\n );\n if (layer.shadow) {\n const s = layer.shadow;\n const o = offsetAlong(s.angle, s.distFrac * W);\n shadowCopy(rgbaOf(s.color, s.alpha), s.blurFrac * W, o.dx, o.dy, 'drop');\n } else if (fx?.kind === 'lift') {\n const l = liftShadow(fx.intensity, fs);\n shadowCopy(l.color, l.blur, 0, l.dy, 'lift');\n } else if (fx?.kind === 'glow') {\n shadowCopy(rgbaOf(fx.color ?? layer.color, fx.opacity), fx.sizeEm * fs, 0, 0, 'glow');\n } else if (fx?.kind === 'neon') {\n shadowCopy(layer.color, neonBlur(fx.intensity, fs), 0, 0, 'neon');\n }\n // The words.\n if (fx?.kind === 'hollow' || fx?.kind === 'splice') {\n layers.push(draw({ fill: 'none', stroke: own, strokeWidth: fs * fx.thicknessEm }, 'words'));\n } else {\n if (layer.outline && layer.outline.widthEm > 0) {\n layers.push(\n draw(\n {\n fill: layer.outline.color,\n stroke: layer.outline.color,\n strokeWidth: layer.outline.widthEm * fs * 2,\n },\n 'outline',\n ),\n );\n }\n const neon = fx?.kind === 'neon' ? 0.45 + 0.35 * fx.intensity : 0;\n layers.push(draw({ fill: neon ? (p) => tintOf(own(p), neon) : own }, 'words'));\n }\n return (\n <G>\n {blurs.length ? (\n <Defs>\n {blurs.map((b) => (\n <Filter key={b.key} id={b.key} x=\"-50%\" y=\"-50%\" width=\"200%\" height=\"200%\">\n <FeGaussianBlur stdDeviation={b.std} />\n </Filter>\n ))}\n </Defs>\n ) : null}\n {highlight}\n {layers}\n </G>\n );\n}\n\n/** The height a curved layer draws at, in the units its curve was measured in. */\nexport function curvedHeight(layer: TextLayer, curve: MeasuredCurve): number {\n const arc = curveArc(curve.width, layer.curve, curve.ascender, curve.descender);\n return arc ? arc.height : curve.ascender + curve.descender;\n}\n"],"names":["_a","_b","_c"],"mappings":"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"}
@@ -20,6 +20,7 @@ function qnTime(now) {
20
20
  function startQnScale(link, ctx) {
21
21
  const useAlt = !link.has(QN.service) && link.has(QN.serviceAlt);
22
22
  const service = useAlt ? QN.serviceAlt : QN.service;
23
+ const notifyChar = useAlt ? QN.notifyAlt : QN.notify;
23
24
  const writeChar = (cmd) => useAlt ? QN.writeAlt : cmd === 32 || cmd === 34 ? QN.write20 : QN.write13;
24
25
  const withoutResponse = (char) => {
25
26
  var _a, _b;
@@ -34,6 +35,7 @@ function startQnScale(link, ctx) {
34
35
  let deviceByte = 0;
35
36
  let resolution = 0;
36
37
  let done = false;
38
+ let configSent = false;
37
39
  const weightKgOf = (raw) => {
38
40
  const w = raw * (resolution === 1 ? 0.1 : 0.01);
39
41
  return w > 300 ? w * 0.1 : w;
@@ -61,7 +63,7 @@ function startQnScale(link, ctx) {
61
63
  void send(qnPacket([19, 9, deviceByte, unitByte, 16, height, age, male])).catch(() => void 0);
62
64
  void send(qnPacket([32, 8, deviceByte, ...le32(qnTime(ctx.now()))])).catch(() => void 0);
63
65
  };
64
- const unsub = link.monitor(service, QN.notify, (p) => {
66
+ const unsub = link.monitor(service, notifyChar, (p) => {
65
67
  var _a, _b;
66
68
  if (p.length === 1) {
67
69
  (_a = ctx.onLive) == null ? void 0 : _a.call(ctx, {
@@ -74,7 +76,10 @@ function startQnScale(link, ctx) {
74
76
  if (cmd === 18 && p.length >= 11) {
75
77
  deviceByte = p[2];
76
78
  resolution = (p[10] & 1) === 0 ? 1 : 0;
77
- sendConfig();
79
+ if (!configSent) {
80
+ configSent = true;
81
+ sendConfig();
82
+ }
78
83
  return;
79
84
  }
80
85
  if (cmd === 16 && p.length >= 6) {
@@ -1 +1 @@
1
- {"version":3,"file":"qnScale.js","sources":["../../../../src/features/devices/brands/qnScale.ts"],"sourcesContent":["/**\n * QN / Yolanda public scales (PROTOCOLS.md section 6). Packets are\n * `cmd len deviceByte ... sum`, notified on FFE1; writes go to FFE3/FFE4 (or\n * FFF2 when the scale exposes the FFF0 service).\n *\n * Yantra reads weight (reliable on the public protocol) and, when the scale\n * does not scramble it, the impedance. Body composition is left to Yantra's own\n * estimate: the scale's own figure needs QN's proprietary algorithm.\n */\nimport type { DriverContext, DriverHandle, GattLink } from '../drivers';\nimport { readingId, type BodyReading } from '../readings';\nimport { le32, qnChecksumOk, qnPacket, u16be } from './frames';\nimport { QN } from './uuids';\n\n/** Seconds from 2000-01-01 UTC, the epoch QN scales stamp with. */\nfunction qnTime(now: number): number {\n return Math.max(0, Math.floor((now - Date.UTC(2000, 0, 1)) / 1000));\n}\n\nexport function startQnScale(link: GattLink, ctx: DriverContext): DriverHandle {\n const useAlt = !link.has(QN.service) && link.has(QN.serviceAlt);\n const service = useAlt ? QN.serviceAlt : QN.service;\n const writeChar = (cmd: number) => (useAlt ? QN.writeAlt : cmd === 0x20 || cmd === 0x22 ? QN.write20 : QN.write13);\n const withoutResponse = (char: string) => link.canWriteWithoutResponse?.(service, char) ?? false;\n\n const send = (packet: number[]) => {\n const char = writeChar(packet[0]);\n return link.write(service, char, packet, { withoutResponse: withoutResponse(char) });\n };\n\n let deviceByte = 0;\n let resolution = 0; // 0 = 0.01 kg, 1 = 0.1 kg\n let done = false;\n\n const weightKgOf = (raw: number) => {\n const w = raw * (resolution === 1 ? 0.1 : 0.01);\n // The scale's own guard: a value over 300 is still in the finer unit.\n return w > 300 ? w * 0.1 : w;\n };\n\n const emitFinal = (weightKg: number, impedance: number | undefined) => {\n const at = ctx.now();\n const reading: BodyReading = {\n kind: 'body',\n id: readingId(link.id, 'body', at),\n at,\n deviceId: link.id,\n deviceName: link.name,\n weightKg,\n ...(impedance ? { impedanceOhm: impedance } : {}),\n };\n ctx.onReading(reading);\n };\n\n const sendConfig = () => {\n const unitByte = 0x01; // kg\n const height = Math.round(ctx.person.heightCm ?? 0);\n const age = Math.round(ctx.person.age ?? 0);\n const male = ctx.person.sex === 'male' ? 1 : 0;\n void send(qnPacket([0x13, 0x09, deviceByte, unitByte, 0x10, height, age, male])).catch(() => undefined);\n void send(qnPacket([0x20, 0x08, deviceByte, ...le32(qnTime(ctx.now()))])).catch(() => undefined);\n };\n\n const unsub = link.monitor(service, QN.notify, (p) => {\n if (p.length === 1) {\n ctx.onLive?.({ battery: p[0] });\n return;\n }\n if (!qnChecksumOk(p)) return;\n const cmd = p[0];\n if (cmd === 0x12 && p.length >= 11) {\n deviceByte = p[2];\n resolution = (p[10] & 1) === 0 ? 1 : 0; // flag bit0 set => 0.01 kg\n sendConfig();\n return;\n }\n if (cmd === 0x10 && p.length >= 6) {\n const weightKg = weightKgOf(u16be(p, 3));\n const state = p[5];\n if (state === 0 || state === 0x11 || state === 0x12) {\n ctx.onLive?.({ weightKg });\n } else if ((state === 1 || state === 2) && !done) {\n done = true;\n // Impedance is reported raw only when the scale does not scramble it.\n const impedance = p.length >= 8 ? u16be(p, 6) || undefined : undefined;\n emitFinal(weightKg, impedance);\n }\n return;\n }\n });\n\n return { stop: unsub };\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"qnScale.js","sources":["../../../../src/features/devices/brands/qnScale.ts"],"sourcesContent":["/**\n * QN / Yolanda public scales (PROTOCOLS.md section 6). Packets are\n * `cmd len deviceByte ... sum`, notified on FFE1; writes go to FFE3/FFE4 (or\n * FFF2 when the scale exposes the FFF0 service).\n *\n * Yantra reads weight (reliable on the public protocol) and, when the scale\n * does not scramble it, the impedance. Body composition is left to Yantra's own\n * estimate: the scale's own figure needs QN's proprietary algorithm.\n */\nimport type { DriverContext, DriverHandle, GattLink } from '../drivers';\nimport { readingId, type BodyReading } from '../readings';\nimport { le32, qnChecksumOk, qnPacket, u16be } from './frames';\nimport { QN } from './uuids';\n\n/** Seconds from 2000-01-01 UTC, the epoch QN scales stamp with. */\nfunction qnTime(now: number): number {\n return Math.max(0, Math.floor((now - Date.UTC(2000, 0, 1)) / 1000));\n}\n\nexport function startQnScale(link: GattLink, ctx: DriverContext): DriverHandle {\n // A scale advertises FFE0 but may expose FFE0 or FFF0 in its GATT; prefer\n // whichever is actually present (confirmed: Renpho-Scale exposes FFF0/FFF1/FFF2).\n const useAlt = !link.has(QN.service) && link.has(QN.serviceAlt);\n const service = useAlt ? QN.serviceAlt : QN.service;\n const notifyChar = useAlt ? QN.notifyAlt : QN.notify;\n const writeChar = (cmd: number) => (useAlt ? QN.writeAlt : cmd === 0x20 || cmd === 0x22 ? QN.write20 : QN.write13);\n const withoutResponse = (char: string) => link.canWriteWithoutResponse?.(service, char) ?? false;\n\n const send = (packet: number[]) => {\n const char = writeChar(packet[0]);\n return link.write(service, char, packet, { withoutResponse: withoutResponse(char) });\n };\n\n let deviceByte = 0;\n let resolution = 0; // 0 = 0.01 kg, 1 = 0.1 kg\n let done = false;\n let configSent = false; // the scale repeats 0x12 until it gets the config reply\n\n const weightKgOf = (raw: number) => {\n const w = raw * (resolution === 1 ? 0.1 : 0.01);\n // The scale's own guard: a value over 300 is still in the finer unit.\n return w > 300 ? w * 0.1 : w;\n };\n\n const emitFinal = (weightKg: number, impedance: number | undefined) => {\n const at = ctx.now();\n const reading: BodyReading = {\n kind: 'body',\n id: readingId(link.id, 'body', at),\n at,\n deviceId: link.id,\n deviceName: link.name,\n weightKg,\n ...(impedance ? { impedanceOhm: impedance } : {}),\n };\n ctx.onReading(reading);\n };\n\n const sendConfig = () => {\n const unitByte = 0x01; // kg\n const height = Math.round(ctx.person.heightCm ?? 0);\n const age = Math.round(ctx.person.age ?? 0);\n const male = ctx.person.sex === 'male' ? 1 : 0;\n void send(qnPacket([0x13, 0x09, deviceByte, unitByte, 0x10, height, age, male])).catch(() => undefined);\n void send(qnPacket([0x20, 0x08, deviceByte, ...le32(qnTime(ctx.now()))])).catch(() => undefined);\n };\n\n const unsub = link.monitor(service, notifyChar, (p) => {\n if (p.length === 1) {\n ctx.onLive?.({ battery: p[0] });\n return;\n }\n if (!qnChecksumOk(p)) return;\n const cmd = p[0];\n if (cmd === 0x12 && p.length >= 11) {\n deviceByte = p[2];\n resolution = (p[10] & 1) === 0 ? 1 : 0; // flag bit0 set => 0.01 kg\n if (!configSent) {\n configSent = true;\n sendConfig();\n }\n return;\n }\n if (cmd === 0x10 && p.length >= 6) {\n const weightKg = weightKgOf(u16be(p, 3));\n const state = p[5];\n if (state === 0 || state === 0x11 || state === 0x12) {\n ctx.onLive?.({ weightKg });\n } else if ((state === 1 || state === 2) && !done) {\n done = true;\n // Impedance is reported raw only when the scale does not scramble it.\n const impedance = p.length >= 8 ? u16be(p, 6) || undefined : undefined;\n emitFinal(weightKg, impedance);\n }\n return;\n }\n });\n\n return { stop: unsub };\n}\n"],"names":[],"mappings":"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"}
@@ -30,9 +30,10 @@ const RENPHO_RING = {
30
30
  };
31
31
  const QN = {
32
32
  service: uuid16("ffe0"),
33
- serviceAlt: uuid16("fff0"),
34
33
  notify: uuid16("ffe1"),
35
34
  write13: uuid16("ffe3"),
36
35
  write20: uuid16("ffe4"),
36
+ serviceAlt: uuid16("fff0"),
37
+ notifyAlt: uuid16("fff1"),
37
38
  writeAlt: uuid16("fff2")
38
39
  };export{QN,RENPHO_BP,RENPHO_COMMON,RENPHO_OLD_TAPE,RENPHO_RING,RENPHO_ROPE,RENPHO_SCALE};//# sourceMappingURL=uuids.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"uuids.js","sources":["../../../../src/features/devices/brands/uuids.ts"],"sourcesContent":["/**\n * The service and characteristic UUIDs each RENPHO / QN protocol uses, from\n * the devices' own handlers (initWithDeviceModel, scanSubscribeCharacteristic;\n * ~/Downloads/renpho-rea/PROTOCOLS.md).\n *\n * react-native-ble-plx reports and takes full 128-bit lowercase UUIDs, so the\n * 16-bit ones are expanded; the two custom services keep their literal value.\n */\nimport { uuid16 } from '../gatt/uuids';\n\n/** RENPHO common-frame body scale (service 1A10, write 2A11 with response, notify 2A10). */\nexport const RENPHO_SCALE = {\n service: uuid16('1a10'),\n write: uuid16('2a11'),\n notify: uuid16('2a10'),\n} as const;\n\n/** RENPHO blood pressure (service 1A10, write 1A11, notify 1A12, indicate 1A13). */\nexport const RENPHO_BP = {\n service: uuid16('1a10'),\n write: uuid16('1a11'),\n notify: uuid16('1a12'),\n indicate: uuid16('1a13'),\n} as const;\n\n/** RENPHO food scale and newer tape measure (service 1A10, write 1A11, notify 1A12). */\nexport const RENPHO_COMMON = {\n service: uuid16('1a10'),\n write: uuid16('1a11'),\n notify: uuid16('1a12'),\n} as const;\n\n/** Jump rope (Alpwise service). */\nexport const RENPHO_ROPE = {\n service: '00005301-0000-0041-4c50-574953450000',\n write: '00005302-0000-0041-4c50-574953450000',\n notify: '00005303-0000-0041-4c50-574953450000',\n} as const;\n\n/** Old ES-Tape. */\nexport const RENPHO_OLD_TAPE = {\n service: '0783b03e-8535-b5a0-7140-a304d2495cb7',\n notify: '0783b03e-8535-b5a0-7140-a304d2495cb8',\n} as const;\n\n/** Smart ring (service FFF0, write FFF6, notify FFF7). */\nexport const RENPHO_RING = {\n service: uuid16('fff0'),\n write: uuid16('fff6'),\n notify: uuid16('fff7'),\n} as const;\n\n/** QN / Yolanda scale. Notify FFE1; writes go to FFE3/FFE4, or FFF2 in the FFF0 service. */\nexport const QN = {\n service: uuid16('ffe0'),\n serviceAlt: uuid16('fff0'),\n notify: uuid16('ffe1'),\n write13: uuid16('ffe3'),\n write20: uuid16('ffe4'),\n writeAlt: uuid16('fff2'),\n} as const;\n"],"names":[],"mappings":"sCAWO,MAAM,YAAe,GAAA;AAAA,EAC1B,OAAA,EAAS,OAAO,MAAM,CAAA;AAAA,EACtB,KAAA,EAAO,OAAO,MAAM,CAAA;AAAA,EACpB,MAAA,EAAQ,OAAO,MAAM;AACvB;AAGO,MAAM,SAAY,GAAA;AAAA,EACvB,OAAA,EAAS,OAAO,MAAM,CAAA;AAAA,EACtB,KAAA,EAAO,OAAO,MAAM,CAAA;AAAA,EACpB,MAAA,EAAQ,OAAO,MAAM,CAAA;AAAA,EACrB,QAAA,EAAU,OAAO,MAAM;AACzB;AAGO,MAAM,aAAgB,GAAA;AAAA,EAC3B,OAAA,EAAS,OAAO,MAAM,CAAA;AAAA,EACtB,KAAA,EAAO,OAAO,MAAM,CAAA;AAAA,EACpB,MAAA,EAAQ,OAAO,MAAM;AACvB;AAGO,MAAM,WAAc,GAAA;AAAA,EACzB,OAAS,EAAA,sCAAA;AAAA,EACT,KAAO,EAAA,sCAAA;AAAA,EACP,MAAQ,EAAA;AACV;AAGO,MAAM,eAAkB,GAAA;AAAA,EAC7B,OAAS,EAAA,sCAAA;AAAA,EACT,MAAQ,EAAA;AACV;AAGO,MAAM,WAAc,GAAA;AAAA,EACzB,OAAA,EAAS,OAAO,MAAM,CAAA;AAAA,EACtB,KAAA,EAAO,OAAO,MAAM,CAAA;AAAA,EACpB,MAAA,EAAQ,OAAO,MAAM;AACvB;AAGO,MAAM,EAAK,GAAA;AAAA,EAChB,OAAA,EAAS,OAAO,MAAM,CAAA;AAAA,EACtB,UAAA,EAAY,OAAO,MAAM,CAAA;AAAA,EACzB,MAAA,EAAQ,OAAO,MAAM,CAAA;AAAA,EACrB,OAAA,EAAS,OAAO,MAAM,CAAA;AAAA,EACtB,OAAA,EAAS,OAAO,MAAM,CAAA;AAAA,EACtB,QAAA,EAAU,OAAO,MAAM;AACzB"}
1
+ {"version":3,"file":"uuids.js","sources":["../../../../src/features/devices/brands/uuids.ts"],"sourcesContent":["/**\n * The service and characteristic UUIDs each RENPHO / QN protocol uses, from\n * the devices' own handlers (initWithDeviceModel, scanSubscribeCharacteristic;\n * ~/Downloads/renpho-rea/PROTOCOLS.md).\n *\n * react-native-ble-plx reports and takes full 128-bit lowercase UUIDs, so the\n * 16-bit ones are expanded; the two custom services keep their literal value.\n */\nimport { uuid16 } from '../gatt/uuids';\n\n/** RENPHO common-frame body scale (service 1A10, write 2A11 with response, notify 2A10). */\nexport const RENPHO_SCALE = {\n service: uuid16('1a10'),\n write: uuid16('2a11'),\n notify: uuid16('2a10'),\n} as const;\n\n/** RENPHO blood pressure (service 1A10, write 1A11, notify 1A12, indicate 1A13). */\nexport const RENPHO_BP = {\n service: uuid16('1a10'),\n write: uuid16('1a11'),\n notify: uuid16('1a12'),\n indicate: uuid16('1a13'),\n} as const;\n\n/** RENPHO food scale and newer tape measure (service 1A10, write 1A11, notify 1A12). */\nexport const RENPHO_COMMON = {\n service: uuid16('1a10'),\n write: uuid16('1a11'),\n notify: uuid16('1a12'),\n} as const;\n\n/** Jump rope (Alpwise service). */\nexport const RENPHO_ROPE = {\n service: '00005301-0000-0041-4c50-574953450000',\n write: '00005302-0000-0041-4c50-574953450000',\n notify: '00005303-0000-0041-4c50-574953450000',\n} as const;\n\n/** Old ES-Tape. */\nexport const RENPHO_OLD_TAPE = {\n service: '0783b03e-8535-b5a0-7140-a304d2495cb7',\n notify: '0783b03e-8535-b5a0-7140-a304d2495cb8',\n} as const;\n\n/** Smart ring (service FFF0, write FFF6, notify FFF7). */\nexport const RENPHO_RING = {\n service: uuid16('fff0'),\n write: uuid16('fff6'),\n notify: uuid16('fff7'),\n} as const;\n\n/**\n * QN / Yolanda scale. Two GATT variants (a scale advertises FFE0 but may expose\n * either service): FFE0 with notify FFE1 and writes FFE3/FFE4, or FFF0 with\n * notify FFF1 and write FFF2. Confirmed against a real \"Renpho-Scale\": it\n * advertises FFE0 but implements FFF0 / FFF1 (notify) / FFF2 (write).\n */\nexport const QN = {\n service: uuid16('ffe0'),\n notify: uuid16('ffe1'),\n write13: uuid16('ffe3'),\n write20: uuid16('ffe4'),\n serviceAlt: uuid16('fff0'),\n notifyAlt: uuid16('fff1'),\n writeAlt: uuid16('fff2'),\n} as const;\n"],"names":[],"mappings":"sCAWO,MAAM,YAAe,GAAA;AAAA,EAC1B,OAAA,EAAS,OAAO,MAAM,CAAA;AAAA,EACtB,KAAA,EAAO,OAAO,MAAM,CAAA;AAAA,EACpB,MAAA,EAAQ,OAAO,MAAM;AACvB;AAGO,MAAM,SAAY,GAAA;AAAA,EACvB,OAAA,EAAS,OAAO,MAAM,CAAA;AAAA,EACtB,KAAA,EAAO,OAAO,MAAM,CAAA;AAAA,EACpB,MAAA,EAAQ,OAAO,MAAM,CAAA;AAAA,EACrB,QAAA,EAAU,OAAO,MAAM;AACzB;AAGO,MAAM,aAAgB,GAAA;AAAA,EAC3B,OAAA,EAAS,OAAO,MAAM,CAAA;AAAA,EACtB,KAAA,EAAO,OAAO,MAAM,CAAA;AAAA,EACpB,MAAA,EAAQ,OAAO,MAAM;AACvB;AAGO,MAAM,WAAc,GAAA;AAAA,EACzB,OAAS,EAAA,sCAAA;AAAA,EACT,KAAO,EAAA,sCAAA;AAAA,EACP,MAAQ,EAAA;AACV;AAGO,MAAM,eAAkB,GAAA;AAAA,EAC7B,OAAS,EAAA,sCAAA;AAAA,EACT,MAAQ,EAAA;AACV;AAGO,MAAM,WAAc,GAAA;AAAA,EACzB,OAAA,EAAS,OAAO,MAAM,CAAA;AAAA,EACtB,KAAA,EAAO,OAAO,MAAM,CAAA;AAAA,EACpB,MAAA,EAAQ,OAAO,MAAM;AACvB;AAQO,MAAM,EAAK,GAAA;AAAA,EAChB,OAAA,EAAS,OAAO,MAAM,CAAA;AAAA,EACtB,MAAA,EAAQ,OAAO,MAAM,CAAA;AAAA,EACrB,OAAA,EAAS,OAAO,MAAM,CAAA;AAAA,EACtB,OAAA,EAAS,OAAO,MAAM,CAAA;AAAA,EACtB,UAAA,EAAY,OAAO,MAAM,CAAA;AAAA,EACzB,SAAA,EAAW,OAAO,MAAM,CAAA;AAAA,EACxB,QAAA,EAAU,OAAO,MAAM;AACzB"}
@@ -1,4 +1,5 @@
1
- import AsyncStorage from'@react-native-async-storage/async-storage';import {Platform}from'react-native';import {useEffect,useSyncExternalStore,useState}from'react';import {healthSyncStore}from'../health/healthSync.js';import {createBleTransport}from'./bleTransport.js';import {DeviceStore}from'./deviceStore.js';import {DeviceSession}from'./session.js';async function createPlatformWriter() {
1
+ import AsyncStorage from'@react-native-async-storage/async-storage';import {Platform}from'react-native';import {useEffect,useSyncExternalStore,useState}from'react';import {healthSyncStore}from'../health/healthSync.js';import {nativeHealthLoadable}from'../health/nativeHealth.js';import {createBleTransport}from'./bleTransport.js';import {DeviceStore}from'./deviceStore.js';import {DeviceSession}from'./session.js';async function createPlatformWriter() {
2
+ if (!nativeHealthLoadable()) return null;
2
3
  try {
3
4
  if (Platform.OS === "ios") return (await import('../health/healthkitWriter.js')).createHealthKitWriter();
4
5
  if (Platform.OS === "android") return (await import('../health/healthConnectWriter.js')).createHealthConnectWriter();
@@ -1 +1 @@
1
- {"version":3,"file":"devices.js","sources":["../../../src/features/devices/devices.ts"],"sourcesContent":["/**\n * The app's one DeviceStore, wired to AsyncStorage, the platform's health\n * writer and the Bluetooth radio, plus the hooks the screens use.\n *\n * The native modules (react-native-ble-plx, the health writers) load with a\n * dynamic import inside a try, as healthSync.ts does for the readers: a\n * JavaScript update reaching an older app binary must not crash at startup,\n * it only means \"not available in this build\".\n */\nimport AsyncStorage from '@react-native-async-storage/async-storage';\nimport { Platform } from 'react-native';\nimport { useEffect, useState, useSyncExternalStore } from 'react';\nimport { healthSyncStore } from '../health/healthSync';\nimport type { HealthWriter } from '../health/writer';\nimport { createBleTransport } from './bleTransport';\nimport type { DeviceKindId } from './catalog';\nimport { DeviceStore, type DeviceSnapshot } from './deviceStore';\nimport type { BleTransport } from './link';\nimport { DeviceSession, type SessionSnapshot } from './session';\n\nasync function createPlatformWriter(): Promise<HealthWriter | null> {\n try {\n if (Platform.OS === 'ios') return (await import('../health/healthkitWriter')).createHealthKitWriter();\n if (Platform.OS === 'android')\n return (await import('../health/healthConnectWriter')).createHealthConnectWriter();\n } catch {\n // This binary does not include the native module.\n }\n return null;\n}\n\nexport const deviceStore = new DeviceStore({\n storage: AsyncStorage,\n createWriter: createPlatformWriter,\n healthConnected: () => healthSyncStore.getSnapshot().sync.connected,\n});\n\nlet writer: Promise<HealthWriter | null> | null = null;\n/** The health store writer, for the screens that ask permission to save. */\nexport function platformWriter(): Promise<HealthWriter | null> {\n if (!writer) writer = createPlatformWriter();\n return writer;\n}\n\nlet transport: Promise<BleTransport | null> | null = null;\nfunction bluetooth(): Promise<BleTransport | null> {\n if (!transport) transport = createBleTransport().catch(() => null);\n return transport;\n}\n\nexport function useDevices(): DeviceSnapshot {\n useEffect(() => {\n void deviceStore.load();\n }, []);\n return useSyncExternalStore(deviceStore.subscribe, deviceStore.getSnapshot, deviceStore.getSnapshot);\n}\n\nconst IDLE: SessionSnapshot = { state: { step: 'starting' }, kind: 'scale', readings: [], notices: [] };\n\n/**\n * One take-a-reading session for as long as the screen shows it: started on\n * mount, closed (scan stopped, device disconnected) on unmount or when the\n * kind or device changes. Null kind = no session.\n */\nexport function useDeviceSession(\n kind: DeviceKindId | null,\n deviceId?: string,\n): { snapshot: SessionSnapshot; session: DeviceSession | null } {\n const [session, setSession] = useState<DeviceSession | null>(null);\n useEffect(() => {\n if (!kind) return undefined;\n let live = true;\n let created: DeviceSession | null = null;\n void bluetooth().then((t) => {\n if (!live) return;\n created = new DeviceSession({ transport: t, store: deviceStore, kind, deviceId });\n setSession(created);\n void created.start();\n });\n return () => {\n live = false;\n void created?.close();\n setSession(null);\n };\n }, [kind, deviceId]);\n const snapshot = useSyncExternalStore(\n session ? session.subscribe : noopSubscribe,\n session ? session.getSnapshot : idle,\n session ? session.getSnapshot : idle,\n );\n return { snapshot, session };\n}\n\nconst noopSubscribe = () => () => undefined;\nconst idle = () => IDLE;\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"devices.js","sources":["../../../src/features/devices/devices.ts"],"sourcesContent":["/**\n * The app's one DeviceStore, wired to AsyncStorage, the platform's health\n * writer and the Bluetooth radio, plus the hooks the screens use.\n *\n * The native modules (react-native-ble-plx, the health writers) load with a\n * dynamic import inside a try, as healthSync.ts does for the readers: a\n * JavaScript update reaching an older app binary must not crash at startup,\n * it only means \"not available in this build\".\n */\nimport AsyncStorage from '@react-native-async-storage/async-storage';\nimport { Platform } from 'react-native';\nimport { useEffect, useState, useSyncExternalStore } from 'react';\nimport { healthSyncStore } from '../health/healthSync';\nimport { nativeHealthLoadable } from '../health/nativeHealth';\nimport type { HealthWriter } from '../health/writer';\nimport { createBleTransport } from './bleTransport';\nimport type { DeviceKindId } from './catalog';\nimport { DeviceStore, type DeviceSnapshot } from './deviceStore';\nimport type { BleTransport } from './link';\nimport { DeviceSession, type SessionSnapshot } from './session';\n\nasync function createPlatformWriter(): Promise<HealthWriter | null> {\n if (!nativeHealthLoadable()) return null;\n try {\n if (Platform.OS === 'ios') return (await import('../health/healthkitWriter')).createHealthKitWriter();\n if (Platform.OS === 'android')\n return (await import('../health/healthConnectWriter')).createHealthConnectWriter();\n } catch {\n // This binary does not include the native module.\n }\n return null;\n}\n\nexport const deviceStore = new DeviceStore({\n storage: AsyncStorage,\n createWriter: createPlatformWriter,\n healthConnected: () => healthSyncStore.getSnapshot().sync.connected,\n});\n\nlet writer: Promise<HealthWriter | null> | null = null;\n/** The health store writer, for the screens that ask permission to save. */\nexport function platformWriter(): Promise<HealthWriter | null> {\n if (!writer) writer = createPlatformWriter();\n return writer;\n}\n\nlet transport: Promise<BleTransport | null> | null = null;\nfunction bluetooth(): Promise<BleTransport | null> {\n if (!transport) transport = createBleTransport().catch(() => null);\n return transport;\n}\n\nexport function useDevices(): DeviceSnapshot {\n useEffect(() => {\n void deviceStore.load();\n }, []);\n return useSyncExternalStore(deviceStore.subscribe, deviceStore.getSnapshot, deviceStore.getSnapshot);\n}\n\nconst IDLE: SessionSnapshot = { state: { step: 'starting' }, kind: 'scale', readings: [], notices: [] };\n\n/**\n * One take-a-reading session for as long as the screen shows it: started on\n * mount, closed (scan stopped, device disconnected) on unmount or when the\n * kind or device changes. Null kind = no session.\n */\nexport function useDeviceSession(\n kind: DeviceKindId | null,\n deviceId?: string,\n): { snapshot: SessionSnapshot; session: DeviceSession | null } {\n const [session, setSession] = useState<DeviceSession | null>(null);\n useEffect(() => {\n if (!kind) return undefined;\n let live = true;\n let created: DeviceSession | null = null;\n void bluetooth().then((t) => {\n if (!live) return;\n created = new DeviceSession({ transport: t, store: deviceStore, kind, deviceId });\n setSession(created);\n void created.start();\n });\n return () => {\n live = false;\n void created?.close();\n setSession(null);\n };\n }, [kind, deviceId]);\n const snapshot = useSyncExternalStore(\n session ? session.subscribe : noopSubscribe,\n session ? session.getSnapshot : idle,\n session ? session.getSnapshot : idle,\n );\n return { snapshot, session };\n}\n\nconst noopSubscribe = () => () => undefined;\nconst idle = () => IDLE;\n"],"names":[],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import {jsx,jsxs}from'react/jsx-runtime';import {memo,useMemo,useState}from'react';import {Platform,View,Text,TextInput,StyleSheet,ScrollView}from'react-native';import {MaterialCommunityIcons}from'@expo/vector-icons';import {Image}from'expo-image';import {themedStyles}from'../canvas/canvasTheme.js';import {SPACE,Pressable,RADIUS}from'../canvas/canvasUi.js';import {inlineToRuns,isObject,tableCellRuns}from'./blocks.js';import {BACKGROUND_COLORS,TEXT_COLORS}from'./docExport.js';var __defProp = Object.defineProperty;
1
+ import {jsx,jsxs}from'react/jsx-runtime';import {memo,useMemo,useState}from'react';import {View,Text,TextInput,StyleSheet,Platform,ScrollView}from'react-native';import {MaterialCommunityIcons}from'@expo/vector-icons';import {Image}from'expo-image';import {themedStyles}from'../canvas/canvasTheme.js';import {SPACE,Pressable,RADIUS}from'../canvas/canvasUi.js';import {inlineToRuns,isObject,tableCellRuns}from'./blocks.js';import {BACKGROUND_COLORS,TEXT_COLORS}from'./docExport.js';var __defProp = Object.defineProperty;
2
2
  var __getOwnPropSymbols = Object.getOwnPropertySymbols;
3
3
  var __hasOwnProp = Object.prototype.hasOwnProperty;
4
4
  var __propIsEnum = Object.prototype.propertyIsEnumerable;
@@ -93,7 +93,7 @@ async function saveDocArtifact(opts, artifact) {
93
93
  };
94
94
  }
95
95
  async function listDocArtifacts(opts, limit = 24) {
96
- const page = await channelsMatching(opts, "doc:", limit);
96
+ const page = await channelsMatching(opts, "doc:", limit, ["canvas"]);
97
97
  const docs = [];
98
98
  for (const row of page.rows) {
99
99
  const artifact = coerceDocArtifact(row.metadata);
@@ -115,7 +115,7 @@ async function loadOwnedDocArtifact(opts, id) {
115
115
  error: null
116
116
  };
117
117
  const key = id.trim();
118
- const page = await channelsMatching(opts, key, 5);
118
+ const page = await channelsMatching(opts, key, 5, ["canvas"]);
119
119
  const row = page.rows.find((r) => r.channelId === key);
120
120
  if (!row) return {
121
121
  artifact: null,
@@ -1 +1 @@
1
- {"version":3,"file":"docArtifacts.js","sources":["../../../src/features/docs/docArtifacts.ts"],"sourcesContent":["/**\n * Saved docs - native twin of the web docs editor's `persistence.ts` over\n * canvas-surface `state/artifacts.ts`.\n *\n * One SurfaceChannel row per document on the `canvas` surface, keyed\n * `doc:<uuid>`, `{ artifact }` in metadata where `artifact.doc` is\n * `{ version: 2, title, blocks (BlockNote JSON), updatedAt }`. That is exactly\n * what the web writes and lists, so a doc written on the phone opens in the\n * web editor and the reverse.\n *\n * The transport is the design index's (`design/doc/artifacts.ts`): a save\n * is the idempotent upsert and replaces metadata wholesale, so it always\n * sends the whole document.\n *\n * Pure apart from `fetch`: runs under jest as-is.\n */\nimport {\n channelsMatching,\n decodeMetadata,\n gql,\n isDocArtifactId,\n newArtifactId,\n type IndexOptions,\n} from '../design/doc/artifacts';\nimport { parseBlocks, type DocBlock } from './blocks';\n\nexport { isDocArtifactId };\n\n/** The editor payload (web `DocsDoc`). v1 (tiptap HTML) is gone: it fails the guard and opens blank. */\nexport interface DocsDoc {\n version: 2;\n title: string;\n /** BlockNote's block JSON (`editor.document`). */\n blocks: DocBlock[];\n updatedAt: number;\n}\n\n/** One saved doc row (web `CanvasArtifact<DocsDoc>`). */\nexport interface DocArtifact {\n /** Row id AND artifact id: `doc:<uuid>`. */\n id: string;\n kind: 'doc';\n sessionId?: string;\n title: string;\n updatedAt: number;\n doc: DocsDoc;\n /** Written by web; kept through native saves. */\n thumbUrl?: string;\n exportUrl?: string;\n}\n\nexport const UNTITLED_DOC = 'Untitled doc';\n\n/** Mint the row id a brand-new document saves under (web `newDocId`). */\nexport function newDocId(): string {\n return newArtifactId('doc');\n}\n\n/** Validate a doc payload (web `coerceDoc`); blocks are parsed, unknown block types kept. */\nexport function coerceDocsDoc(doc: unknown): DocsDoc | null {\n const d = doc as Partial<DocsDoc> | null | undefined;\n if (!d || typeof d !== 'object' || d.version !== 2 || !Array.isArray(d.blocks)) return null;\n return {\n ...(d as DocsDoc),\n version: 2,\n title: typeof d.title === 'string' ? d.title : '',\n blocks: parseBlocks(d.blocks),\n updatedAt: typeof d.updatedAt === 'number' ? d.updatedAt : 0,\n };\n}\n\n/** Validate a decoded row (untrusted JSON from the index); null for anything but a v2 doc. */\nexport function coerceDocArtifact(metadata: unknown): DocArtifact | null {\n const meta = decodeMetadata(metadata) as { artifact?: DocArtifact } | null;\n const artifact = meta?.artifact;\n if (!artifact || typeof artifact.id !== 'string' || !artifact.id || artifact.kind !== 'doc') return null;\n const doc = coerceDocsDoc(artifact.doc);\n if (!doc) return null;\n return { ...artifact, doc };\n}\n\n/** The row a save writes (web `saveDocById`). */\nexport function buildDocArtifact(\n id: string,\n doc: DocsDoc,\n keep: Pick<DocArtifact, 'sessionId' | 'thumbUrl' | 'exportUrl'> = {},\n): DocArtifact {\n return {\n id,\n kind: 'doc',\n ...(keep.sessionId ? { sessionId: keep.sessionId } : {}),\n title: doc.title?.trim() || UNTITLED_DOC,\n updatedAt: doc.updatedAt,\n doc,\n ...(keep.thumbUrl ? { thumbUrl: keep.thumbUrl } : {}),\n ...(keep.exportUrl ? { exportUrl: keep.exportUrl } : {}),\n };\n}\n\nconst ROW_FIELDS = 'channelId title metadata updatedAt';\n\n/** Write one doc. `ok: false` is lost work: say so. */\nexport async function saveDocArtifact(\n opts: IndexOptions,\n artifact: DocArtifact,\n): Promise<{ ok: boolean; error: string | null }> {\n const { data, error } = await gql<{ registerSurfaceChannel?: { channelId?: string } | null }>(\n opts,\n `mutation RegisterSurfaceChannel($input: RegisterSurfaceChannelInput!) {\n registerSurfaceChannel(input: $input) { ${ROW_FIELDS} }\n }`,\n {\n input: {\n surface: 'canvas',\n channelId: artifact.id,\n // Top-level AND inside the payload, as web: the column is what lists\n // filter on, the metadata copy is what the reader validates.\n ...(artifact.sessionId ? { sessionId: artifact.sessionId } : {}),\n ...(artifact.title ? { title: artifact.title } : {}),\n metadata: { artifact },\n },\n },\n );\n if (error) return { ok: false, error };\n return data?.registerSurfaceChannel?.channelId\n ? { ok: true, error: null }\n : { ok: false, error: 'Could not save. Recent edits are not stored yet.' };\n}\n\nexport interface DocListResult {\n docs: DocArtifact[];\n more: boolean;\n error: string | null;\n}\n\n/** The caller's docs, newest first (web `listArtifactsOfKinds(['doc'])`). */\nexport async function listDocArtifacts(opts: IndexOptions, limit = 24): Promise<DocListResult> {\n const page = await channelsMatching(opts, 'doc:', limit);\n const docs: DocArtifact[] = [];\n for (const row of page.rows) {\n const artifact = coerceDocArtifact(row.metadata);\n // The search also matches titles, so the kind and id are checked again.\n if (artifact && artifact.id === row.channelId) docs.push(artifact);\n }\n docs.sort((a, b) => (b.updatedAt ?? 0) - (a.updatedAt ?? 0));\n return {\n docs: docs.slice(0, limit),\n more: page.total > limit || docs.length > limit,\n error: docs.length === 0 ? page.error : null,\n };\n}\n\n/**\n * One of the CALLER'S OWN docs (web `loadOwnedArtifact`): only an id the\n * bearer-scoped list returns opens, so a link cannot open someone else's.\n */\nexport async function loadOwnedDocArtifact(\n opts: IndexOptions,\n id: string,\n): Promise<{ artifact: DocArtifact | null; error: string | null }> {\n if (!isDocArtifactId(id)) return { artifact: null, error: null };\n const key = id.trim();\n const page = await channelsMatching(opts, key, 5);\n const row = page.rows.find((r) => r.channelId === key);\n if (!row) return { artifact: null, error: page.error };\n const artifact = coerceDocArtifact(row.metadata);\n return { artifact: artifact && artifact.id === key ? artifact : null, error: null };\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"docArtifacts.js","sources":["../../../src/features/docs/docArtifacts.ts"],"sourcesContent":["/**\n * Saved docs - native twin of the web docs editor's `persistence.ts` over\n * canvas-surface `state/artifacts.ts`.\n *\n * One SurfaceChannel row per document on the `canvas` surface, keyed\n * `doc:<uuid>`, `{ artifact }` in metadata where `artifact.doc` is\n * `{ version: 2, title, blocks (BlockNote JSON), updatedAt }`. That is exactly\n * what the web writes and lists, so a doc written on the phone opens in the\n * web editor and the reverse.\n *\n * The transport is the design index's (`design/doc/artifacts.ts`): a save\n * is the idempotent upsert and replaces metadata wholesale, so it always\n * sends the whole document.\n *\n * Pure apart from `fetch`: runs under jest as-is.\n */\nimport {\n channelsMatching,\n decodeMetadata,\n gql,\n isDocArtifactId,\n newArtifactId,\n type IndexOptions,\n} from '../design/doc/artifacts';\nimport { parseBlocks, type DocBlock } from './blocks';\n\nexport { isDocArtifactId };\n\n/** The editor payload (web `DocsDoc`). v1 (tiptap HTML) is gone: it fails the guard and opens blank. */\nexport interface DocsDoc {\n version: 2;\n title: string;\n /** BlockNote's block JSON (`editor.document`). */\n blocks: DocBlock[];\n updatedAt: number;\n}\n\n/** One saved doc row (web `CanvasArtifact<DocsDoc>`). */\nexport interface DocArtifact {\n /** Row id AND artifact id: `doc:<uuid>`. */\n id: string;\n kind: 'doc';\n sessionId?: string;\n title: string;\n updatedAt: number;\n doc: DocsDoc;\n /** Written by web; kept through native saves. */\n thumbUrl?: string;\n exportUrl?: string;\n}\n\nexport const UNTITLED_DOC = 'Untitled doc';\n\n/** Mint the row id a brand-new document saves under (web `newDocId`). */\nexport function newDocId(): string {\n return newArtifactId('doc');\n}\n\n/** Validate a doc payload (web `coerceDoc`); blocks are parsed, unknown block types kept. */\nexport function coerceDocsDoc(doc: unknown): DocsDoc | null {\n const d = doc as Partial<DocsDoc> | null | undefined;\n if (!d || typeof d !== 'object' || d.version !== 2 || !Array.isArray(d.blocks)) return null;\n return {\n ...(d as DocsDoc),\n version: 2,\n title: typeof d.title === 'string' ? d.title : '',\n blocks: parseBlocks(d.blocks),\n updatedAt: typeof d.updatedAt === 'number' ? d.updatedAt : 0,\n };\n}\n\n/** Validate a decoded row (untrusted JSON from the index); null for anything but a v2 doc. */\nexport function coerceDocArtifact(metadata: unknown): DocArtifact | null {\n const meta = decodeMetadata(metadata) as { artifact?: DocArtifact } | null;\n const artifact = meta?.artifact;\n if (!artifact || typeof artifact.id !== 'string' || !artifact.id || artifact.kind !== 'doc') return null;\n const doc = coerceDocsDoc(artifact.doc);\n if (!doc) return null;\n return { ...artifact, doc };\n}\n\n/** The row a save writes (web `saveDocById`). */\nexport function buildDocArtifact(\n id: string,\n doc: DocsDoc,\n keep: Pick<DocArtifact, 'sessionId' | 'thumbUrl' | 'exportUrl'> = {},\n): DocArtifact {\n return {\n id,\n kind: 'doc',\n ...(keep.sessionId ? { sessionId: keep.sessionId } : {}),\n title: doc.title?.trim() || UNTITLED_DOC,\n updatedAt: doc.updatedAt,\n doc,\n ...(keep.thumbUrl ? { thumbUrl: keep.thumbUrl } : {}),\n ...(keep.exportUrl ? { exportUrl: keep.exportUrl } : {}),\n };\n}\n\nconst ROW_FIELDS = 'channelId title metadata updatedAt';\n\n/** Write one doc. `ok: false` is lost work: say so. */\nexport async function saveDocArtifact(\n opts: IndexOptions,\n artifact: DocArtifact,\n): Promise<{ ok: boolean; error: string | null }> {\n const { data, error } = await gql<{ registerSurfaceChannel?: { channelId?: string } | null }>(\n opts,\n `mutation RegisterSurfaceChannel($input: RegisterSurfaceChannelInput!) {\n registerSurfaceChannel(input: $input) { ${ROW_FIELDS} }\n }`,\n {\n input: {\n surface: 'canvas',\n channelId: artifact.id,\n // Top-level AND inside the payload, as web: the column is what lists\n // filter on, the metadata copy is what the reader validates.\n ...(artifact.sessionId ? { sessionId: artifact.sessionId } : {}),\n ...(artifact.title ? { title: artifact.title } : {}),\n metadata: { artifact },\n },\n },\n );\n if (error) return { ok: false, error };\n return data?.registerSurfaceChannel?.channelId\n ? { ok: true, error: null }\n : { ok: false, error: 'Could not save. Recent edits are not stored yet.' };\n}\n\nexport interface DocListResult {\n docs: DocArtifact[];\n more: boolean;\n error: string | null;\n}\n\n/** The caller's docs, newest first (web `listArtifactsOfKinds(['doc'])`). */\nexport async function listDocArtifacts(opts: IndexOptions, limit = 24): Promise<DocListResult> {\n const page = await channelsMatching(opts, 'doc:', limit, ['canvas']);\n const docs: DocArtifact[] = [];\n for (const row of page.rows) {\n const artifact = coerceDocArtifact(row.metadata);\n // The search also matches titles, so the kind and id are checked again.\n if (artifact && artifact.id === row.channelId) docs.push(artifact);\n }\n docs.sort((a, b) => (b.updatedAt ?? 0) - (a.updatedAt ?? 0));\n return {\n docs: docs.slice(0, limit),\n more: page.total > limit || docs.length > limit,\n error: docs.length === 0 ? page.error : null,\n };\n}\n\n/**\n * One of the CALLER'S OWN docs (web `loadOwnedArtifact`): only an id the\n * bearer-scoped list returns opens, so a link cannot open someone else's.\n */\nexport async function loadOwnedDocArtifact(\n opts: IndexOptions,\n id: string,\n): Promise<{ artifact: DocArtifact | null; error: string | null }> {\n if (!isDocArtifactId(id)) return { artifact: null, error: null };\n const key = id.trim();\n const page = await channelsMatching(opts, key, 5, ['canvas']);\n const row = page.rows.find((r) => r.channelId === key);\n if (!row) return { artifact: null, error: page.error };\n const artifact = coerceDocArtifact(row.metadata);\n return { artifact: artifact && artifact.id === key ? artifact : null, error: null };\n}\n"],"names":[],"mappings":"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"}
@@ -1,4 +1,5 @@
1
- import AsyncStorage from'@react-native-async-storage/async-storage';import {Platform}from'react-native';import {useSyncExternalStore}from'react';import {readAuth0IdToken}from'../../bridge/readAuth0Session.js';import {HealthSyncStore}from'./healthSyncStore.js';import {secureSessionVault}from'./sessionVault.js';async function createPlatformReader() {
1
+ import AsyncStorage from'@react-native-async-storage/async-storage';import {Platform}from'react-native';import {useSyncExternalStore}from'react';import {readAuth0IdToken}from'../../bridge/readAuth0Session.js';import {HealthSyncStore}from'./healthSyncStore.js';import {nativeHealthLoadable}from'./nativeHealth.js';import {secureSessionVault}from'./sessionVault.js';async function createPlatformReader() {
2
+ if (!nativeHealthLoadable()) return null;
2
3
  try {
3
4
  if (Platform.OS === "ios") return (await import('./healthkitReader.js')).createHealthKitReader();
4
5
  if (Platform.OS === "android") return (await import('./healthConnectReader.js')).createHealthConnectReader();
@@ -10,6 +11,7 @@ let background = null;
10
11
  function loadPlatformBackground() {
11
12
  if (!background) {
12
13
  background = (async () => {
14
+ if (!nativeHealthLoadable()) return null;
13
15
  try {
14
16
  if (Platform.OS === "ios") return (await import('./healthkitBackground.js')).healthkitBackground;
15
17
  if (Platform.OS === "android") {
@@ -1 +1 @@
1
- {"version":3,"file":"healthSync.js","sources":["../../../src/features/health/healthSync.ts"],"sourcesContent":["/**\n * The app's one HealthSyncStore, wired to AsyncStorage and this platform's\n * reader.\n *\n * The readers load with a dynamic import, inside a try: both native\n * libraries create their native objects when first imported, and an app\n * binary built before they were added (an over-the-air JS update reaching an\n * older build) would crash at startup on a static import. Here it only means\n * \"not available in this build\". Rollup keeps `import()` as its own module.\n */\nimport AsyncStorage from '@react-native-async-storage/async-storage';\nimport { Platform } from 'react-native';\nimport { useSyncExternalStore } from 'react';\nimport { readAuth0IdToken } from '../../bridge/readAuth0Session';\nimport type { HealthReader } from './reader';\nimport { HealthSyncStore, type BackgroundSource, type HealthSyncSnapshot } from './healthSyncStore';\nimport { secureSessionVault } from './sessionVault';\n\nasync function createPlatformReader(): Promise<HealthReader | null> {\n try {\n if (Platform.OS === 'ios') return (await import('./healthkitReader')).createHealthKitReader();\n if (Platform.OS === 'android') return (await import('./healthConnectReader')).createHealthConnectReader();\n } catch {\n // This binary does not include the native module.\n }\n return null;\n}\n\nlet background: Promise<BackgroundSource | null> | null = null;\n\n/**\n * Syncing while closed: Apple Health background delivery, or Health Connect's\n * hourly job. Null where there is neither (web, a build without the module).\n */\nexport function loadPlatformBackground(): Promise<BackgroundSource | null> {\n if (!background) {\n background = (async () => {\n try {\n if (Platform.OS === 'ios') return (await import('./healthkitBackground')).healthkitBackground;\n if (Platform.OS === 'android') {\n return (await import('./healthConnectBackground')).healthConnectBackground;\n }\n } catch {\n // This build has no such native module.\n }\n return null;\n })();\n }\n return background;\n}\n\nexport const healthSyncStore = new HealthSyncStore({\n storage: AsyncStorage,\n createReader: createPlatformReader,\n vault: secureSessionVault,\n background: {\n enable: async () => {\n await (await loadPlatformBackground())?.enable();\n },\n disable: async () => {\n await (await loadPlatformBackground())?.disable();\n },\n },\n signedIn: async () => Boolean(await readAuth0IdToken()),\n});\n\nexport function useHealthSync(): HealthSyncSnapshot {\n return useSyncExternalStore(healthSyncStore.subscribe, healthSyncStore.getSnapshot, healthSyncStore.getSnapshot);\n}\n"],"names":[],"mappings":"uTAiBA,eAAe,oBAAqD,GAAA;AAClE,EAAI,IAAA;AACF,IAAI,IAAA,QAAA,CAAS,OAAO,KAAO,EAAA,OAAA,CAAQ,MAAM,OAAO,sBAAmB,GAAG,qBAAsB,EAAA;AAC5F,IAAI,IAAA,QAAA,CAAS,OAAO,SAAW,EAAA,OAAA,CAAQ,MAAM,OAAO,0BAAuB,GAAG,yBAA0B,EAAA;AAAA,GAClG,CAAA,OAAA,CAAA,EAAA;AAAA;AAGR,EAAO,OAAA,IAAA;AACT;AACA,IAAI,UAAsD,GAAA,IAAA;AAMnD,SAAS,sBAA2D,GAAA;AACzE,EAAA,IAAI,CAAC,UAAY,EAAA;AACf,IAAA,UAAA,GAAA,CAAc,YAAY;AACxB,MAAI,IAAA;AACF,QAAA,IAAI,SAAS,EAAO,KAAA,KAAA,UAAe,MAAM,OAAO,0BAAuB,CAAG,EAAA,mBAAA;AAC1E,QAAI,IAAA,QAAA,CAAS,OAAO,SAAW,EAAA;AAC7B,UAAQ,OAAA,CAAA,MAAM,OAAO,8BAA2B,CAAG,EAAA,uBAAA;AAAA;AACrD,OACM,CAAA,OAAA,CAAA,EAAA;AAAA;AAGR,MAAO,OAAA,IAAA;AAAA,KACN,GAAA;AAAA;AAEL,EAAO,OAAA,UAAA;AACT;AACa,MAAA,eAAA,GAAkB,IAAI,eAAgB,CAAA;AAAA,EACjD,OAAS,EAAA,YAAA;AAAA,EACT,YAAc,EAAA,oBAAA;AAAA,EACd,KAAO,EAAA,kBAAA;AAAA,EACP,UAAY,EAAA;AAAA,IACV,QAAQ,YAAY;AArDxB,MAAA,IAAA,EAAA;AAsDM,MAAO,OAAA,CAAA,EAAA,GAAA,MAAM,sBAAuB,EAAA,KAA7B,IAAiC,GAAA,MAAA,GAAA,EAAA,CAAA,MAAA,EAAA,CAAA;AAAA,KAC1C;AAAA,IACA,SAAS,YAAY;AAxDzB,MAAA,IAAA,EAAA;AAyDM,MAAO,OAAA,CAAA,EAAA,GAAA,MAAM,sBAAuB,EAAA,KAA7B,IAAiC,GAAA,MAAA,GAAA,EAAA,CAAA,OAAA,EAAA,CAAA;AAAA;AAC1C,GACF;AAAA,EACA,QAAU,EAAA,YAAY,OAAQ,CAAA,MAAM,kBAAkB;AACxD,CAAC;AACM,SAAS,aAAoC,GAAA;AAClD,EAAA,OAAO,qBAAqB,eAAgB,CAAA,SAAA,EAAW,eAAgB,CAAA,WAAA,EAAa,gBAAgB,WAAW,CAAA;AACjH"}
1
+ {"version":3,"file":"healthSync.js","sources":["../../../src/features/health/healthSync.ts"],"sourcesContent":["/**\n * The app's one HealthSyncStore, wired to AsyncStorage and this platform's\n * reader.\n *\n * The readers load with a dynamic import, inside a try: both native\n * libraries create their native objects when first imported, and an app\n * binary built before they were added (an over-the-air JS update reaching an\n * older build) would crash at startup on a static import. Here it only means\n * \"not available in this build\". Rollup keeps `import()` as its own module.\n */\nimport AsyncStorage from '@react-native-async-storage/async-storage';\nimport { Platform } from 'react-native';\nimport { useSyncExternalStore } from 'react';\nimport { readAuth0IdToken } from '../../bridge/readAuth0Session';\nimport type { HealthReader } from './reader';\nimport { HealthSyncStore, type BackgroundSource, type HealthSyncSnapshot } from './healthSyncStore';\nimport { nativeHealthLoadable } from './nativeHealth';\nimport { secureSessionVault } from './sessionVault';\n\nasync function createPlatformReader(): Promise<HealthReader | null> {\n if (!nativeHealthLoadable()) return null;\n try {\n if (Platform.OS === 'ios') return (await import('./healthkitReader')).createHealthKitReader();\n if (Platform.OS === 'android') return (await import('./healthConnectReader')).createHealthConnectReader();\n } catch {\n // This binary does not include the native module.\n }\n return null;\n}\n\nlet background: Promise<BackgroundSource | null> | null = null;\n\n/**\n * Syncing while closed: Apple Health background delivery, or Health Connect's\n * hourly job. Null where there is neither (web, a build without the module).\n */\nexport function loadPlatformBackground(): Promise<BackgroundSource | null> {\n if (!background) {\n background = (async () => {\n if (!nativeHealthLoadable()) return null;\n try {\n if (Platform.OS === 'ios') return (await import('./healthkitBackground')).healthkitBackground;\n if (Platform.OS === 'android') {\n return (await import('./healthConnectBackground')).healthConnectBackground;\n }\n } catch {\n // This build has no such native module.\n }\n return null;\n })();\n }\n return background;\n}\n\nexport const healthSyncStore = new HealthSyncStore({\n storage: AsyncStorage,\n createReader: createPlatformReader,\n vault: secureSessionVault,\n background: {\n enable: async () => {\n await (await loadPlatformBackground())?.enable();\n },\n disable: async () => {\n await (await loadPlatformBackground())?.disable();\n },\n },\n signedIn: async () => Boolean(await readAuth0IdToken()),\n});\n\nexport function useHealthSync(): HealthSyncSnapshot {\n return useSyncExternalStore(healthSyncStore.subscribe, healthSyncStore.getSnapshot, healthSyncStore.getSnapshot);\n}\n"],"names":[],"mappings":"4WAkBA,eAAe,oBAAqD,GAAA;AAClE,EAAI,IAAA,CAAC,oBAAqB,EAAA,EAAU,OAAA,IAAA;AACpC,EAAI,IAAA;AACF,IAAI,IAAA,QAAA,CAAS,OAAO,KAAO,EAAA,OAAA,CAAQ,MAAM,OAAO,sBAAmB,GAAG,qBAAsB,EAAA;AAC5F,IAAI,IAAA,QAAA,CAAS,OAAO,SAAW,EAAA,OAAA,CAAQ,MAAM,OAAO,0BAAuB,GAAG,yBAA0B,EAAA;AAAA,GAClG,CAAA,OAAA,CAAA,EAAA;AAAA;AAGR,EAAO,OAAA,IAAA;AACT;AACA,IAAI,UAAsD,GAAA,IAAA;AAMnD,SAAS,sBAA2D,GAAA;AACzE,EAAA,IAAI,CAAC,UAAY,EAAA;AACf,IAAA,UAAA,GAAA,CAAc,YAAY;AACxB,MAAI,IAAA,CAAC,oBAAqB,EAAA,EAAU,OAAA,IAAA;AACpC,MAAI,IAAA;AACF,QAAA,IAAI,SAAS,EAAO,KAAA,KAAA,UAAe,MAAM,OAAO,0BAAuB,CAAG,EAAA,mBAAA;AAC1E,QAAI,IAAA,QAAA,CAAS,OAAO,SAAW,EAAA;AAC7B,UAAQ,OAAA,CAAA,MAAM,OAAO,8BAA2B,CAAG,EAAA,uBAAA;AAAA;AACrD,OACM,CAAA,OAAA,CAAA,EAAA;AAAA;AAGR,MAAO,OAAA,IAAA;AAAA,KACN,GAAA;AAAA;AAEL,EAAO,OAAA,UAAA;AACT;AACa,MAAA,eAAA,GAAkB,IAAI,eAAgB,CAAA;AAAA,EACjD,OAAS,EAAA,YAAA;AAAA,EACT,YAAc,EAAA,oBAAA;AAAA,EACd,KAAO,EAAA,kBAAA;AAAA,EACP,UAAY,EAAA;AAAA,IACV,QAAQ,YAAY;AAxDxB,MAAA,IAAA,EAAA;AAyDM,MAAO,OAAA,CAAA,EAAA,GAAA,MAAM,sBAAuB,EAAA,KAA7B,IAAiC,GAAA,MAAA,GAAA,EAAA,CAAA,MAAA,EAAA,CAAA;AAAA,KAC1C;AAAA,IACA,SAAS,YAAY;AA3DzB,MAAA,IAAA,EAAA;AA4DM,MAAO,OAAA,CAAA,EAAA,GAAA,MAAM,sBAAuB,EAAA,KAA7B,IAAiC,GAAA,MAAA,GAAA,EAAA,CAAA,OAAA,EAAA,CAAA;AAAA;AAC1C,GACF;AAAA,EACA,QAAU,EAAA,YAAY,OAAQ,CAAA,MAAM,kBAAkB;AACxD,CAAC;AACM,SAAS,aAAoC,GAAA;AAClD,EAAA,OAAO,qBAAqB,eAAgB,CAAA,SAAA,EAAW,eAAgB,CAAA,WAAA,EAAa,gBAAgB,WAAW,CAAA;AACjH"}
@@ -0,0 +1,8 @@
1
+ function nativeHealthLoadable() {
2
+ try {
3
+ const Constants = require("expo-constants").default;
4
+ if ((Constants == null ? void 0 : Constants.appOwnership) === "expo") return false;
5
+ } catch (e) {
6
+ }
7
+ return true;
8
+ }export{nativeHealthLoadable};//# sourceMappingURL=nativeHealth.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"nativeHealth.js","sources":["../../../src/features/health/nativeHealth.ts"],"sourcesContent":["/**\n * Whether the native health libraries may be loaded at all. Expo Go ships\n * neither: the HealthKit library is a Nitro module and throws \"NitroModules are\n * not supported in Expo Go\" while it loads. Metro reports an error thrown\n * during module setup as fatal even when the `import()` sits inside a try, so\n * the try around each dynamic import is not enough there - skip the import.\n */\nexport function nativeHealthLoadable(): boolean {\n try {\n const Constants = require('expo-constants').default as { appOwnership?: string | null };\n if (Constants?.appOwnership === 'expo') return false;\n } catch {\n /* not running under Expo */\n }\n return true;\n}\n"],"names":[],"mappings":"AAOO,SAAS,oBAAgC,GAAA;AAC9C,EAAI,IAAA;AACF,IAAM,MAAA,SAAA,GAAY,OAAQ,CAAA,gBAAgB,CAAE,CAAA,OAAA;AAG5C,IAAI,IAAA,CAAA,SAAA,IAAA,IAAA,GAAA,KAAA,CAAA,GAAA,SAAA,CAAW,YAAiB,MAAA,MAAA,EAAe,OAAA,KAAA;AAAA,GACzC,CAAA,OAAA,CAAA,EAAA;AAAA;AAGR,EAAO,OAAA,IAAA;AACT"}
@@ -1,4 +1,4 @@
1
- import {CommonActions}from'@react-navigation/native';import*as WebBrowser from'expo-web-browser';import {Linking}from'react-native';import {designOpeningFromUrl}from'../design/surface/designLinks.js';var __defProp = Object.defineProperty;
1
+ import {CommonActions}from'@react-navigation/native';import*as WebBrowser from'expo-web-browser';import {Linking}from'react-native';import {nativeTwinForSurface}from'../apps/nativeSurfaceTwin.js';import {designOpeningFromUrl}from'../design/surface/designLinks.js';var __defProp = Object.defineProperty;
2
2
  var __getOwnPropSymbols = Object.getOwnPropertySymbols;
3
3
  var __hasOwnProp = Object.prototype.hasOwnProperty;
4
4
  var __propIsEnum = Object.prototype.propertyIsEnumerable;
@@ -26,6 +26,16 @@ function openSurfaceInApp(navigation, target) {
26
26
  openDesignNative(navigation, design);
27
27
  return;
28
28
  }
29
+ const twin = nativeTwinForSurface(target.surface);
30
+ if (twin) {
31
+ navigation.dispatch(CommonActions.navigate({
32
+ name: twin.screen,
33
+ params: {
34
+ appTitle: twin.title
35
+ }
36
+ }));
37
+ return;
38
+ }
29
39
  navigation.dispatch(CommonActions.navigate({
30
40
  name: "MainStack.WebBuilder",
31
41
  params: {
@@ -1 +1 @@
1
- {"version":3,"file":"openInApp.js","sources":["../../../src/features/links/openInApp.ts"],"sourcesContent":["/**\n * Where a tapped link opens on the phone.\n *\n * A Yantra surface page opens in the app's own surface screen (WebBuilder),\n * which hands the page this device's sign-in - so a bounty link opens the\n * bounty in Freelance, signed in, ready to apply. Any other web page opens in\n * an in-app browser sheet, so reading a link never drops the person out of\n * Yantra. WHICH links are surface pages is the messenger gateway's call\n * (`Query.gatewayLinkPreview` -> `open`), not decided here.\n *\n * Shared by the messenger's host seam (portable-devices `useChatLinkSeam`) and\n * the assistant chat, so a link behaves the same wherever it was tapped.\n */\nimport { CommonActions, type NavigationProp, type ParamListBase } from '@react-navigation/native';\nimport * as WebBrowser from 'expo-web-browser';\nimport { Linking } from 'react-native';\nimport { designOpeningFromUrl } from '../design/surface/designLinks';\n\nexport interface InAppSurfaceTarget {\n surface: string;\n url: string;\n}\n\n/** `freelance` -> `Freelance`, `job-search` -> `Job Search`: the surface screen's header. */\nexport function surfaceTitle(slug: string): string {\n return slug\n .split(/[-_]+/)\n .filter(Boolean)\n .map((word) => word[0].toUpperCase() + word.slice(1))\n .join(' ');\n}\n\n/**\n * Open a surface page in the app's surface screen - the same navigation the\n * Apps catalog uses to open a surface tile, with the link's page as its URL.\n */\nexport function openSurfaceInApp(\n navigation: Pick<NavigationProp<ParamListBase>, 'dispatch'>,\n target: InAppSurfaceTarget,\n): void {\n // The Design surface has a native screen: its links open there (on the template\n // gallery when they ask for design templates), never the web surface in a WebView.\n const design =\n target.surface === 'design' || target.surface === 'design-native'\n ? (designOpeningFromUrl(target.url) ?? { templates: false })\n : designOpeningFromUrl(target.url);\n if (design) {\n openDesignNative(navigation, design);\n return;\n }\n navigation.dispatch(\n CommonActions.navigate({\n name: 'MainStack.WebBuilder',\n params: { url: target.url, appTitle: surfaceTitle(target.surface) },\n }),\n );\n}\n\n/** Native Design, optionally on its template gallery with a search. */\nexport function openDesignNative(\n navigation: Pick<NavigationProp<ParamListBase>, 'dispatch'>,\n opening: { templates: boolean; templatesQuery?: string },\n): void {\n navigation.dispatch(\n CommonActions.navigate({\n name: 'MainStack.DesignNative',\n params: {\n appTitle: 'Design',\n // A fresh value each time, so a second card re-opens the gallery on the reused screen.\n ...(opening.templates ? { templates: Date.now(), templatesQuery: opening.templatesQuery ?? '' } : {}),\n },\n }),\n );\n}\n\n/** Open a web page in an in-app browser sheet; anything that is not a web page goes to the OS. */\nexport async function openWebPageInApp(url: string): Promise<void> {\n try {\n if (/^https?:\\/\\//i.test(url)) {\n await WebBrowser.openBrowserAsync(url, {\n presentationStyle: WebBrowser.WebBrowserPresentationStyle.PAGE_SHEET,\n dismissButtonStyle: 'close',\n });\n return;\n }\n await Linking.openURL(url);\n } catch {\n // A link that cannot be opened must not take the screen down with it.\n }\n}\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAuBO,SAAS,aAAa,IAAsB,EAAA;AACjD,EAAO,OAAA,IAAA,CAAK,MAAM,OAAO,CAAA,CAAE,OAAO,OAAO,CAAA,CAAE,IAAI,CAAQ,IAAA,KAAA,IAAA,CAAK,CAAC,CAAE,CAAA,WAAA,KAAgB,IAAK,CAAA,KAAA,CAAM,CAAC,CAAC,CAAA,CAAE,KAAK,GAAG,CAAA;AACxG;AAMgB,SAAA,gBAAA,CAAiB,YAA6D,MAAkC,EAAA;AA/BhI,EAAA,IAAA,EAAA;AAkCE,EAAM,MAAA,MAAA,GAAS,MAAO,CAAA,OAAA,KAAY,QAAY,IAAA,MAAA,CAAO,OAAY,KAAA,eAAA,GAAA,CAAkB,EAAqB,GAAA,oBAAA,CAAA,MAAA,CAAO,GAAG,CAAA,KAA/B,IAAoC,GAAA,EAAA,GAAA;AAAA,IACrH,SAAW,EAAA;AAAA,GACb,GAAI,oBAAqB,CAAA,MAAA,CAAO,GAAG,CAAA;AACnC,EAAA,IAAI,MAAQ,EAAA;AACV,IAAA,gBAAA,CAAiB,YAAY,MAAM,CAAA;AACnC,IAAA;AAAA;AAEF,EAAW,UAAA,CAAA,QAAA,CAAS,cAAc,QAAS,CAAA;AAAA,IACzC,IAAM,EAAA,sBAAA;AAAA,IACN,MAAQ,EAAA;AAAA,MACN,KAAK,MAAO,CAAA,GAAA;AAAA,MACZ,QAAA,EAAU,YAAa,CAAA,MAAA,CAAO,OAAO;AAAA;AACvC,GACD,CAAC,CAAA;AACJ;AAGgB,SAAA,gBAAA,CAAiB,YAA6D,OAGrF,EAAA;AAtDT,EAAA,IAAA,EAAA;AAuDE,EAAW,UAAA,CAAA,QAAA,CAAS,cAAc,QAAS,CAAA;AAAA,IACzC,IAAM,EAAA,wBAAA;AAAA,IACN,MAAQ,EAAA,cAAA,CAAA;AAAA,MACN,QAAU,EAAA;AAAA,KAAA,EAEN,QAAQ,SAAY,GAAA;AAAA,MACtB,SAAA,EAAW,KAAK,GAAI,EAAA;AAAA,MACpB,cAAA,EAAA,CAAgB,EAAQ,GAAA,OAAA,CAAA,cAAA,KAAR,IAA0B,GAAA,EAAA,GAAA;AAAA,QACxC,EAAC;AAAA,GAER,CAAC,CAAA;AACJ;AAGA,eAAsB,iBAAiB,GAA4B,EAAA;AACjE,EAAI,IAAA;AACF,IAAI,IAAA,eAAA,CAAgB,IAAK,CAAA,GAAG,CAAG,EAAA;AAC7B,MAAM,MAAA,UAAA,CAAW,iBAAiB,GAAK,EAAA;AAAA,QACrC,iBAAA,EAAmB,WAAW,2BAA4B,CAAA,UAAA;AAAA,QAC1D,kBAAoB,EAAA;AAAA,OACrB,CAAA;AACD,MAAA;AAAA;AAEF,IAAM,MAAA,OAAA,CAAQ,QAAQ,GAAG,CAAA;AAAA,GACnB,CAAA,OAAA,CAAA,EAAA;AAAA;AAGV"}
1
+ {"version":3,"file":"openInApp.js","sources":["../../../src/features/links/openInApp.ts"],"sourcesContent":["/**\n * Where a tapped link opens on the phone.\n *\n * A Yantra surface page opens on the app's native screen when it has one\n * (nativeSurfaceTwin), else in the app's own surface screen (WebBuilder),\n * which hands the page this device's sign-in - so a bounty link opens the\n * bounty in Freelance, signed in, ready to apply. Any other web page opens in\n * an in-app browser sheet, so reading a link never drops the person out of\n * Yantra. WHICH links are surface pages is the messenger gateway's call\n * (`Query.gatewayLinkPreview` -> `open`), not decided here.\n *\n * Shared by the messenger's host seam (portable-devices `useChatLinkSeam`) and\n * the assistant chat, so a link behaves the same wherever it was tapped.\n */\nimport { CommonActions, type NavigationProp, type ParamListBase } from '@react-navigation/native';\nimport * as WebBrowser from 'expo-web-browser';\nimport { Linking } from 'react-native';\nimport { nativeTwinForSurface } from '../apps/nativeSurfaceTwin';\nimport { designOpeningFromUrl } from '../design/surface/designLinks';\n\nexport interface InAppSurfaceTarget {\n surface: string;\n url: string;\n}\n\n/** `freelance` -> `Freelance`, `job-search` -> `Job Search`: the surface screen's header. */\nexport function surfaceTitle(slug: string): string {\n return slug\n .split(/[-_]+/)\n .filter(Boolean)\n .map((word) => word[0].toUpperCase() + word.slice(1))\n .join(' ');\n}\n\n/**\n * Open a surface page in the app's surface screen - the same navigation the\n * Apps catalog uses to open a surface tile, with the link's page as its URL.\n */\nexport function openSurfaceInApp(\n navigation: Pick<NavigationProp<ParamListBase>, 'dispatch'>,\n target: InAppSurfaceTarget,\n): void {\n // The Design surface has a native screen: its links open there (on the template\n // gallery when they ask for design templates), never the web surface in a WebView.\n const design =\n target.surface === 'design' || target.surface === 'design-native'\n ? (designOpeningFromUrl(target.url) ?? { templates: false })\n : designOpeningFromUrl(target.url);\n if (design) {\n openDesignNative(navigation, design);\n return;\n }\n // Apps with a native screen (Shop, Travel, Job Search, ...) open it, as their Apps tile does.\n const twin = nativeTwinForSurface(target.surface);\n if (twin) {\n navigation.dispatch(CommonActions.navigate({ name: twin.screen, params: { appTitle: twin.title } }));\n return;\n }\n navigation.dispatch(\n CommonActions.navigate({\n name: 'MainStack.WebBuilder',\n params: { url: target.url, appTitle: surfaceTitle(target.surface) },\n }),\n );\n}\n\n/** Native Design, optionally on its template gallery with a search. */\nexport function openDesignNative(\n navigation: Pick<NavigationProp<ParamListBase>, 'dispatch'>,\n opening: { templates: boolean; templatesQuery?: string },\n): void {\n navigation.dispatch(\n CommonActions.navigate({\n name: 'MainStack.DesignNative',\n params: {\n appTitle: 'Design',\n // A fresh value each time, so a second card re-opens the gallery on the reused screen.\n ...(opening.templates ? { templates: Date.now(), templatesQuery: opening.templatesQuery ?? '' } : {}),\n },\n }),\n );\n}\n\n/** Open a web page in an in-app browser sheet; anything that is not a web page goes to the OS. */\nexport async function openWebPageInApp(url: string): Promise<void> {\n try {\n if (/^https?:\\/\\//i.test(url)) {\n await WebBrowser.openBrowserAsync(url, {\n presentationStyle: WebBrowser.WebBrowserPresentationStyle.PAGE_SHEET,\n dismissButtonStyle: 'close',\n });\n return;\n }\n await Linking.openURL(url);\n } catch {\n // A link that cannot be opened must not take the screen down with it.\n }\n}\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAyBO,SAAS,aAAa,IAAsB,EAAA;AACjD,EAAO,OAAA,IAAA,CAAK,MAAM,OAAO,CAAA,CAAE,OAAO,OAAO,CAAA,CAAE,IAAI,CAAQ,IAAA,KAAA,IAAA,CAAK,CAAC,CAAE,CAAA,WAAA,KAAgB,IAAK,CAAA,KAAA,CAAM,CAAC,CAAC,CAAA,CAAE,KAAK,GAAG,CAAA;AACxG;AAMgB,SAAA,gBAAA,CAAiB,YAA6D,MAAkC,EAAA;AAjChI,EAAA,IAAA,EAAA;AAoCE,EAAM,MAAA,MAAA,GAAS,MAAO,CAAA,OAAA,KAAY,QAAY,IAAA,MAAA,CAAO,OAAY,KAAA,eAAA,GAAA,CAAkB,EAAqB,GAAA,oBAAA,CAAA,MAAA,CAAO,GAAG,CAAA,KAA/B,IAAoC,GAAA,EAAA,GAAA;AAAA,IACrH,SAAW,EAAA;AAAA,GACb,GAAI,oBAAqB,CAAA,MAAA,CAAO,GAAG,CAAA;AACnC,EAAA,IAAI,MAAQ,EAAA;AACV,IAAA,gBAAA,CAAiB,YAAY,MAAM,CAAA;AACnC,IAAA;AAAA;AAGF,EAAM,MAAA,IAAA,GAAO,oBAAqB,CAAA,MAAA,CAAO,OAAO,CAAA;AAChD,EAAA,IAAI,IAAM,EAAA;AACR,IAAW,UAAA,CAAA,QAAA,CAAS,cAAc,QAAS,CAAA;AAAA,MACzC,MAAM,IAAK,CAAA,MAAA;AAAA,MACX,MAAQ,EAAA;AAAA,QACN,UAAU,IAAK,CAAA;AAAA;AACjB,KACD,CAAC,CAAA;AACF,IAAA;AAAA;AAEF,EAAW,UAAA,CAAA,QAAA,CAAS,cAAc,QAAS,CAAA;AAAA,IACzC,IAAM,EAAA,sBAAA;AAAA,IACN,MAAQ,EAAA;AAAA,MACN,KAAK,MAAO,CAAA,GAAA;AAAA,MACZ,QAAA,EAAU,YAAa,CAAA,MAAA,CAAO,OAAO;AAAA;AACvC,GACD,CAAC,CAAA;AACJ;AAGgB,SAAA,gBAAA,CAAiB,YAA6D,OAGrF,EAAA;AAnET,EAAA,IAAA,EAAA;AAoEE,EAAW,UAAA,CAAA,QAAA,CAAS,cAAc,QAAS,CAAA;AAAA,IACzC,IAAM,EAAA,wBAAA;AAAA,IACN,MAAQ,EAAA,cAAA,CAAA;AAAA,MACN,QAAU,EAAA;AAAA,KAAA,EAEN,QAAQ,SAAY,GAAA;AAAA,MACtB,SAAA,EAAW,KAAK,GAAI,EAAA;AAAA,MACpB,cAAA,EAAA,CAAgB,EAAQ,GAAA,OAAA,CAAA,cAAA,KAAR,IAA0B,GAAA,EAAA,GAAA;AAAA,QACxC,EAAC;AAAA,GAER,CAAC,CAAA;AACJ;AAGA,eAAsB,iBAAiB,GAA4B,EAAA;AACjE,EAAI,IAAA;AACF,IAAI,IAAA,eAAA,CAAgB,IAAK,CAAA,GAAG,CAAG,EAAA;AAC7B,MAAM,MAAA,UAAA,CAAW,iBAAiB,GAAK,EAAA;AAAA,QACrC,iBAAA,EAAmB,WAAW,2BAA4B,CAAA,UAAA;AAAA,QAC1D,kBAAoB,EAAA;AAAA,OACrB,CAAA;AACD,MAAA;AAAA;AAEF,IAAM,MAAA,OAAA,CAAQ,QAAQ,GAAG,CAAA;AAAA,GACnB,CAAA,OAAA,CAAA,EAAA;AAAA;AAGV"}