@guidelytech/react-native 0.13.0 → 0.14.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.
- package/README.md +15 -7
- package/dist/index.cjs +108 -47
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +41 -5
- package/dist/index.d.ts +41 -5
- package/dist/index.js +106 -47
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
package/README.md
CHANGED
|
@@ -88,7 +88,7 @@ tasks).
|
|
|
88
88
|
| `<GuidelyMask>` | Keeps its children out of tap-analytics text and session recordings (it sets its own `nativeID`) |
|
|
89
89
|
|
|
90
90
|
Provider props: `projectId`, `apiUrl`, `environment`, `storage`, `user`, `debug`, `analytics`,
|
|
91
|
-
`consent` (`granted` / `pending` / `denied`), `appVersion` (
|
|
91
|
+
`consent` (`granted` / `pending` / `denied`), `appVersion` (overrides the detected version, see below), `theme`,
|
|
92
92
|
`configRefreshMs`, `onNavigate`, `onError`, `showChecklistLauncher` (default `true`),
|
|
93
93
|
`showResourceCenterLauncher` (default `false`), `showMessengerLauncher` (default `true`), `insets`,
|
|
94
94
|
`launcherOffset` (default 72), `autocapture`, `appBuild`, `sessionReplay`.
|
|
@@ -111,7 +111,7 @@ runs when the project turns it on (Settings → Product analytics) and analytics
|
|
|
111
111
|
| `rage_click` | 3+ taps within 1 s and 30 pt | the `click` properties of the tapped (or hit) view + `count` |
|
|
112
112
|
| `heatmap` | Every 40 taps, on screen change and when the app goes to the background | `path?`, `viewportWidth`, `viewportHeight`, `pageHeight`, `platform`, `points` |
|
|
113
113
|
| `page_leave` | The screen changes or the app goes to the background | `path?`, `screen`, `durationMs`, `scrollDepth: 100`, `platform` |
|
|
114
|
-
| `page_view` | `screen()` with a new name; after returning to the foreground with `resumed: true` | `path`, `screen`, `platform` |
|
|
114
|
+
| `page_view` | `screen()` with a new name; after returning to the foreground with `resumed: true` | `path`, `screen`, `platform`, `deviceType`, `os`, `osVersion` |
|
|
115
115
|
| `app_install` / `app_update` | First launch / a launch with a new `appVersion` or `appBuild` | `appVersion`, `build`, `previousVersion`, `previousBuild` |
|
|
116
116
|
| `app_open` / `app_background` | Cold start and return to the foreground / background | `coldStart` / `foregroundMs` |
|
|
117
117
|
|
|
@@ -141,10 +141,18 @@ import { GuidelyMask } from "@guidelytech/react-native";
|
|
|
141
141
|
<GuidelyMask><Pressable onPress={showCard}><Text>{cardNumber}</Text></Pressable></GuidelyMask>
|
|
142
142
|
```
|
|
143
143
|
|
|
144
|
-
**App
|
|
145
|
-
`
|
|
146
|
-
|
|
147
|
-
|
|
144
|
+
**App and OS versions.** The SDK detects them on iOS and Android. The OS version (`18.1`, or `14` on
|
|
145
|
+
Android) comes from React Native and is sent as `osVersion` on `page_view` and as the `osVersion`
|
|
146
|
+
flag attribute. React Native has no API for the app's own version and build, so they are read from
|
|
147
|
+
the first linked native module that knows them: `@guidelytech/react-native-replay`
|
|
148
|
+
(`CFBundleShortVersionString` / `versionName`, `CFBundleVersion` / `versionCode`), then
|
|
149
|
+
`expo-application` (not in Expo Go, which reports its own version), then `react-native-device-info`.
|
|
150
|
+
If none of these is installed, pass `appVersion` / `appBuild`. Passing them also overrides the
|
|
151
|
+
detected values.
|
|
152
|
+
|
|
153
|
+
**App lifecycle.** `app_install` / `app_update` need a known app version (detected or the
|
|
154
|
+
`appVersion` prop) and `storage`. The last version is stored per public key. An app that already had
|
|
155
|
+
Guidely installed stores its version silently on the first launch with this release.
|
|
148
156
|
|
|
149
157
|
**Limitations.** React Native has no public API for "which component is under this point", so
|
|
150
158
|
element resolution (steps 2 and 3, `tag`, `text`) reads React's internal component tree of the touch
|
|
@@ -217,7 +225,7 @@ useGuidely().isFeatureEnabled("new-checkout"); // or getFeatureValue / getFeatur
|
|
|
217
225
|
|
|
218
226
|
Flags evaluate on the device with `id` (user id, else the anonymous id), `anonymousId`, identify
|
|
219
227
|
traits, `account`, `$audiences`, `screen`, `path`, `platform` (`ios` / `android`), `deviceType`,
|
|
220
|
-
`appVersion`, `locale` and `environment`, plus `flagAttributes` from the provider. The last payload
|
|
228
|
+
`appVersion`, `osVersion`, `locale` and `environment`, plus `flagAttributes` from the provider. The last payload
|
|
221
229
|
is kept in `storage`, so flags work offline from a cold start; they refresh when the app returns to
|
|
222
230
|
the foreground. Experiment exposures are tracked as `experiment_viewed` events.
|
|
223
231
|
|
package/dist/index.cjs
CHANGED
|
@@ -46,6 +46,8 @@ __export(index_exports, {
|
|
|
46
46
|
TargetRegistry: () => TargetRegistry,
|
|
47
47
|
createFlagsClient: () => import_flags6.createFlagsClient,
|
|
48
48
|
createSseParser: () => createSseParser,
|
|
49
|
+
detectAppVersion: () => detectAppVersion,
|
|
50
|
+
detectOsVersion: () => detectOsVersion,
|
|
49
51
|
guidelyScreenLayout: () => guidelyScreenLayout,
|
|
50
52
|
htmlToText: () => htmlToText,
|
|
51
53
|
noopClient: () => noopClient,
|
|
@@ -1445,14 +1447,14 @@ function quoteValue(value) {
|
|
|
1445
1447
|
function attrSelector(name, value) {
|
|
1446
1448
|
return `[${name}=${quoteValue(value)}]`.slice(0, 300);
|
|
1447
1449
|
}
|
|
1448
|
-
function cleanText(
|
|
1449
|
-
const t = (
|
|
1450
|
+
function cleanText(text2) {
|
|
1451
|
+
const t = (text2 ?? "").replace(/\s+/g, " ").trim();
|
|
1450
1452
|
return t ? t.slice(0, 100) : void 0;
|
|
1451
1453
|
}
|
|
1452
1454
|
function tapProperties(el, x, y, platform, maskAll) {
|
|
1453
1455
|
const props = { selector: el.selector.slice(0, 300), tag: el.tag || "View", x: Math.round(x) || 0, y: Math.round(y) || 0, platform };
|
|
1454
|
-
const
|
|
1455
|
-
if (
|
|
1456
|
+
const text2 = maskAll ? void 0 : cleanText(el.text);
|
|
1457
|
+
if (text2) props.text = text2;
|
|
1456
1458
|
return props;
|
|
1457
1459
|
}
|
|
1458
1460
|
var r2 = (n) => Math.round(Math.min(1, Math.max(0, n)) * 100) / 100;
|
|
@@ -2073,10 +2075,10 @@ function xhrStreamPost() {
|
|
|
2073
2075
|
const type = xhr.getResponseHeader("content-type") || "";
|
|
2074
2076
|
if (!type.includes("text/event-stream")) return;
|
|
2075
2077
|
streamed = true;
|
|
2076
|
-
const
|
|
2077
|
-
if (
|
|
2078
|
-
onChunk(
|
|
2079
|
-
seen =
|
|
2078
|
+
const text2 = xhr.responseText || "";
|
|
2079
|
+
if (text2.length > seen) {
|
|
2080
|
+
onChunk(text2.slice(seen));
|
|
2081
|
+
seen = text2.length;
|
|
2080
2082
|
}
|
|
2081
2083
|
};
|
|
2082
2084
|
xhr.open("POST", url);
|
|
@@ -2151,14 +2153,14 @@ function fetchStreamPost(fetchImpl) {
|
|
|
2151
2153
|
if (rest) onChunk(rest);
|
|
2152
2154
|
return { status: res.status, json: null, streamed: true };
|
|
2153
2155
|
}
|
|
2154
|
-
const
|
|
2156
|
+
const text2 = await race(res.text());
|
|
2155
2157
|
if (sse) {
|
|
2156
|
-
onChunk(
|
|
2158
|
+
onChunk(text2);
|
|
2157
2159
|
return { status: res.status, json: null, streamed: true };
|
|
2158
2160
|
}
|
|
2159
2161
|
let json = null;
|
|
2160
2162
|
try {
|
|
2161
|
-
json = JSON.parse(
|
|
2163
|
+
json = JSON.parse(text2 || "null");
|
|
2162
2164
|
} catch {
|
|
2163
2165
|
json = null;
|
|
2164
2166
|
}
|
|
@@ -2271,10 +2273,10 @@ var Messenger = class {
|
|
|
2271
2273
|
if (v.kind === "tab" && v.tab === "messages") void this.refreshConversations();
|
|
2272
2274
|
}
|
|
2273
2275
|
/** Opens a new thread (optionally pre-filling the composer). */
|
|
2274
|
-
showNewMessage(
|
|
2276
|
+
showNewMessage(text2 = "") {
|
|
2275
2277
|
this.stopThreadPolling();
|
|
2276
2278
|
if (!this.snapshot.open) this.deps.onOpen();
|
|
2277
|
-
this.set({ open: true, view: { kind: "thread", conversationId: null }, thread: { conversation: null, messages: [], streaming: {}, sending: false, error: null, draft:
|
|
2279
|
+
this.set({ open: true, view: { kind: "thread", conversationId: null }, thread: { conversation: null, messages: [], streaming: {}, sending: false, error: null, draft: text2 } });
|
|
2278
2280
|
}
|
|
2279
2281
|
async openConversation(id) {
|
|
2280
2282
|
const known = this.snapshot.conversations.find((c) => c.id === id) ?? null;
|
|
@@ -2318,8 +2320,8 @@ var Messenger = class {
|
|
|
2318
2320
|
}
|
|
2319
2321
|
}
|
|
2320
2322
|
/** Sends the composer text: starts a conversation or posts to the open one. Streams Scout's reply. */
|
|
2321
|
-
async send(
|
|
2322
|
-
const body =
|
|
2323
|
+
async send(text2) {
|
|
2324
|
+
const body = text2.trim().slice(0, 4e3);
|
|
2323
2325
|
const thread = this.snapshot.thread;
|
|
2324
2326
|
if (!body || !thread || thread.sending) return;
|
|
2325
2327
|
this.setThread({ sending: true, error: null, draft: "" });
|
|
@@ -2967,7 +2969,7 @@ var PersistentStore = class {
|
|
|
2967
2969
|
|
|
2968
2970
|
// src/core/client.ts
|
|
2969
2971
|
var SDK_NAME = "@guidelytech/react-native";
|
|
2970
|
-
var SDK_VERSION = "0.
|
|
2972
|
+
var SDK_VERSION = "0.14.0";
|
|
2971
2973
|
var DEFAULT_API_URL = "https://guidelytech.com";
|
|
2972
2974
|
var PAGE_SCOPED = /* @__PURE__ */ new Set(["page_load", "url_match", "element_click", "element_visible", "delay"]);
|
|
2973
2975
|
var CACHED_START_MS = 1500;
|
|
@@ -3739,12 +3741,12 @@ var GuidelyClient = class {
|
|
|
3739
3741
|
/** `{ appVersion, build }` of this launch, without unknown keys. */
|
|
3740
3742
|
appInfo() {
|
|
3741
3743
|
const appVersion = this.options.appVersion ?? this.bridge.device.appVersion;
|
|
3742
|
-
const build = this.options.appBuild;
|
|
3744
|
+
const build = this.options.appBuild ?? (this.options.appVersion ? void 0 : this.bridge.device.appBuild);
|
|
3743
3745
|
return { ...appVersion ? { appVersion: String(appVersion) } : {}, ...build ? { build: String(build) } : {} };
|
|
3744
3746
|
}
|
|
3745
3747
|
/**
|
|
3746
3748
|
* Once per launch, as soon as a config is known: `app_install` / `app_update` from the stored
|
|
3747
|
-
* version (when the app
|
|
3749
|
+
* version (when the app version is known and the app passes `storage`), then `app_open` with `coldStart: true`.
|
|
3748
3750
|
*/
|
|
3749
3751
|
checkLaunch() {
|
|
3750
3752
|
if (this.launchChecked || !this.config || this.destroyed || !this.hydrated) return;
|
|
@@ -4561,8 +4563,8 @@ var GuidelyClient = class {
|
|
|
4561
4563
|
this.messenger?.close();
|
|
4562
4564
|
}
|
|
4563
4565
|
/** Opens a new messenger conversation, optionally pre-filling the message. */
|
|
4564
|
-
showNewMessage(
|
|
4565
|
-
this.whenHydrated(() => this.messenger?.showNewMessage(
|
|
4566
|
+
showNewMessage(text2) {
|
|
4567
|
+
this.whenHydrated(() => this.messenger?.showNewMessage(text2));
|
|
4566
4568
|
}
|
|
4567
4569
|
// ---------------------------------------------------------------------------
|
|
4568
4570
|
// Feature flags
|
|
@@ -4586,7 +4588,7 @@ var GuidelyClient = class {
|
|
|
4586
4588
|
/** Device facts on every screen view, read by the Pages devices / browsers breakdowns. */
|
|
4587
4589
|
deviceProperties() {
|
|
4588
4590
|
const d = this.bridge.device;
|
|
4589
|
-
return { platform: d.platform, deviceType: d.deviceType, os: d.platform };
|
|
4591
|
+
return { platform: d.platform, deviceType: d.deviceType, os: d.platform, ...d.osVersion ? { osVersion: d.osVersion } : {} };
|
|
4590
4592
|
}
|
|
4591
4593
|
/** Attributes flags are evaluated with: identity, traits, account, audiences, screen and device. */
|
|
4592
4594
|
flagContext() {
|
|
@@ -4597,6 +4599,7 @@ var GuidelyClient = class {
|
|
|
4597
4599
|
deviceType: d.deviceType,
|
|
4598
4600
|
locale: d.locale,
|
|
4599
4601
|
appVersion: this.options.appVersion ?? d.appVersion,
|
|
4602
|
+
osVersion: d.osVersion,
|
|
4600
4603
|
environment: this.options.environment,
|
|
4601
4604
|
...this.screenName ? { screen: this.screenName, path: this.currentUrl() } : {},
|
|
4602
4605
|
...this.user?.traits ?? {},
|
|
@@ -4687,6 +4690,51 @@ function withoutCode(guide) {
|
|
|
4687
4690
|
return { ...guide, config: { ...guide.config, steps: guide.config.steps.map(({ code: _code, ...step }) => step) } };
|
|
4688
4691
|
}
|
|
4689
4692
|
|
|
4693
|
+
// src/core/device.ts
|
|
4694
|
+
function text(value) {
|
|
4695
|
+
if (typeof value === "number" && Number.isFinite(value)) return String(value);
|
|
4696
|
+
if (typeof value !== "string") return void 0;
|
|
4697
|
+
const v = value.trim();
|
|
4698
|
+
return v ? v.slice(0, 64) : void 0;
|
|
4699
|
+
}
|
|
4700
|
+
function constant(mod, key) {
|
|
4701
|
+
if (!mod || typeof mod !== "object" && typeof mod !== "function") return void 0;
|
|
4702
|
+
const m = mod;
|
|
4703
|
+
try {
|
|
4704
|
+
const fromGetter = typeof m.getConstants === "function" ? m.getConstants()?.[key] : void 0;
|
|
4705
|
+
return fromGetter ?? m[key];
|
|
4706
|
+
} catch {
|
|
4707
|
+
return void 0;
|
|
4708
|
+
}
|
|
4709
|
+
}
|
|
4710
|
+
function read(mod, versionKey, buildKey) {
|
|
4711
|
+
const appVersion = text(constant(mod, versionKey));
|
|
4712
|
+
if (!appVersion) return null;
|
|
4713
|
+
const appBuild = text(constant(mod, buildKey));
|
|
4714
|
+
return { appVersion, ...appBuild ? { appBuild } : {} };
|
|
4715
|
+
}
|
|
4716
|
+
function inExpoGo(src) {
|
|
4717
|
+
const c = src.expoModules?.ExponentConstants ?? src.nativeModules.ExponentConstants;
|
|
4718
|
+
return constant(c, "executionEnvironment") === "storeClient" || constant(c, "appOwnership") === "expo";
|
|
4719
|
+
}
|
|
4720
|
+
function detectAppVersion(src) {
|
|
4721
|
+
try {
|
|
4722
|
+
const expo = inExpoGo(src) ? null : src.expoModules?.ExpoApplication ?? src.nativeModules.ExpoApplication;
|
|
4723
|
+
return read(src.nativeModules.GuidelyReplay, "appVersion", "appBuild") ?? read(expo, "nativeApplicationVersion", "nativeBuildVersion") ?? read(src.nativeModules.RNDeviceInfo, "appVersion", "buildNumber") ?? {};
|
|
4724
|
+
} catch {
|
|
4725
|
+
return {};
|
|
4726
|
+
}
|
|
4727
|
+
}
|
|
4728
|
+
function detectOsVersion(src) {
|
|
4729
|
+
try {
|
|
4730
|
+
const c = src.platform.constants ?? {};
|
|
4731
|
+
if (src.platform.OS === "android") return text(c.Release) ?? text(src.platform.Version);
|
|
4732
|
+
return text(c.osVersion) ?? text(src.platform.Version);
|
|
4733
|
+
} catch {
|
|
4734
|
+
return void 0;
|
|
4735
|
+
}
|
|
4736
|
+
}
|
|
4737
|
+
|
|
4690
4738
|
// src/ui/Autocapture.tsx
|
|
4691
4739
|
var import_react8 = require("react");
|
|
4692
4740
|
var import_react_native11 = require("react-native");
|
|
@@ -4818,8 +4866,8 @@ function describe(f, masked, opts, withText) {
|
|
|
4818
4866
|
if (!sub.masked) {
|
|
4819
4867
|
const hostProps = host?.memoizedProps && typeof host.memoizedProps === "object" ? host.memoizedProps : {};
|
|
4820
4868
|
const label = props.accessibilityLabel ?? props["aria-label"] ?? hostProps.accessibilityLabel ?? hostProps["aria-label"];
|
|
4821
|
-
const
|
|
4822
|
-
if (
|
|
4869
|
+
const text2 = cleanText(sub.text) ?? (typeof label === "string" ? cleanText(label) : void 0);
|
|
4870
|
+
if (text2) el.text = text2;
|
|
4823
4871
|
}
|
|
4824
4872
|
}
|
|
4825
4873
|
if (host) el.measure = () => measureHost(host);
|
|
@@ -4975,17 +5023,17 @@ function parseHtml(html) {
|
|
|
4975
5023
|
flush();
|
|
4976
5024
|
current = { kind, level, marker, runs: [] };
|
|
4977
5025
|
};
|
|
4978
|
-
const push = (
|
|
4979
|
-
if (!
|
|
5026
|
+
const push = (text2) => {
|
|
5027
|
+
if (!text2) return;
|
|
4980
5028
|
if (!current) current = { kind: "paragraph", level: 1, runs: [] };
|
|
4981
|
-
const run = { text };
|
|
5029
|
+
const run = { text: text2 };
|
|
4982
5030
|
if (style.bold) run.bold = true;
|
|
4983
5031
|
if (style.italic) run.italic = true;
|
|
4984
5032
|
if (style.underline) run.underline = true;
|
|
4985
5033
|
if (style.code) run.code = true;
|
|
4986
5034
|
if (hrefs.length) run.href = hrefs[hrefs.length - 1];
|
|
4987
5035
|
const last = current.runs[current.runs.length - 1];
|
|
4988
|
-
if (last && last.bold === run.bold && last.italic === run.italic && last.underline === run.underline && last.code === run.code && last.href === run.href) last.text +=
|
|
5036
|
+
if (last && last.bold === run.bold && last.italic === run.italic && last.underline === run.underline && last.code === run.code && last.href === run.href) last.text += text2;
|
|
4989
5037
|
else current.runs.push(run);
|
|
4990
5038
|
};
|
|
4991
5039
|
const size = (attrs, name) => {
|
|
@@ -5001,18 +5049,18 @@ function parseHtml(html) {
|
|
|
5001
5049
|
const re = /<!--[\s\S]*?-->|<\/?([a-zA-Z][a-zA-Z0-9]*)\b([^>]*)>|([^<]+|<)/g;
|
|
5002
5050
|
let m;
|
|
5003
5051
|
while (m = re.exec(html || "")) {
|
|
5004
|
-
const [token, rawTag, attrs = "",
|
|
5005
|
-
if (
|
|
5052
|
+
const [token, rawTag, attrs = "", text2] = m;
|
|
5053
|
+
if (text2 !== void 0) {
|
|
5006
5054
|
if (skipping) continue;
|
|
5007
5055
|
if (pdf) {
|
|
5008
|
-
if (pdf.inLink) pdf.name += decodeEntities(
|
|
5056
|
+
if (pdf.inLink) pdf.name += decodeEntities(text2);
|
|
5009
5057
|
continue;
|
|
5010
5058
|
}
|
|
5011
5059
|
if (fileLink) {
|
|
5012
|
-
fileLink.name += decodeEntities(
|
|
5060
|
+
fileLink.name += decodeEntities(text2);
|
|
5013
5061
|
continue;
|
|
5014
5062
|
}
|
|
5015
|
-
push(decodeEntities(
|
|
5063
|
+
push(decodeEntities(text2.replace(/\s+/g, " ")));
|
|
5016
5064
|
continue;
|
|
5017
5065
|
}
|
|
5018
5066
|
if (!rawTag) continue;
|
|
@@ -5586,13 +5634,13 @@ function Conversations({ store, palette: p }) {
|
|
|
5586
5634
|
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(GButton, { label: "New conversation", palette: p, onPress: () => store.showNewMessage(), style: styles4.fullWidth })
|
|
5587
5635
|
] });
|
|
5588
5636
|
}
|
|
5589
|
-
function Bubble({ m, text, name, palette: p, onArticle, onGuide }) {
|
|
5637
|
+
function Bubble({ m, text: text2, name, palette: p, onArticle, onGuide }) {
|
|
5590
5638
|
if (m.author === "system")
|
|
5591
|
-
return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_react_native5.Text, { accessibilityRole: "text", style: [styles4.system, { color: p.muted }], children:
|
|
5639
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_react_native5.Text, { accessibilityRole: "text", style: [styles4.system, { color: p.muted }], children: text2 });
|
|
5592
5640
|
const mine = m.author === "user";
|
|
5593
5641
|
return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_react_native5.View, { style: [styles4.bubbleWrap, mine ? styles4.mine : styles4.theirs], children: [
|
|
5594
5642
|
!mine ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_react_native5.Text, { style: [styles4.author, { color: p.muted }], children: m.author === "agent" ? m.authorName || "Team" : name }) : null,
|
|
5595
|
-
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_react_native5.View, { style: [styles4.bubble, { borderRadius: Math.max(12, p.radius) }, mine ? { backgroundColor: p.primary } : { backgroundColor: p.surface }], children: m.status === "pending" && !
|
|
5643
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_react_native5.View, { style: [styles4.bubble, { borderRadius: Math.max(12, p.radius) }, mine ? { backgroundColor: p.primary } : { backgroundColor: p.surface }], children: m.status === "pending" && !text2 ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(TypingDots, { color: p.muted }) : /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_react_native5.Text, { style: [styles4.bubbleText, { color: mine ? p.onPrimary : p.text }], children: text2 }) }),
|
|
5596
5644
|
m.citations.length || m.suggestedGuides.length ? /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_react_native5.View, { style: styles4.chips, children: [
|
|
5597
5645
|
m.citations.map((c) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_react_native5.Pressable, { accessibilityRole: "link", accessibilityLabel: `Article: ${c.title}`, onPress: () => onArticle(c.articleId), style: [styles4.chip, { borderColor: p.border }], children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_react_native5.Text, { style: [styles4.chipText, { color: p.text }], children: [
|
|
5598
5646
|
"\u{1F4C4} ",
|
|
@@ -5611,7 +5659,7 @@ function TypingDots({ color }) {
|
|
|
5611
5659
|
function Thread({ store, palette: p, bottomInset }) {
|
|
5612
5660
|
const snap = useMessenger(store);
|
|
5613
5661
|
const t = snap.thread;
|
|
5614
|
-
const [
|
|
5662
|
+
const [text2, setText] = (0, import_react3.useState)(t?.draft ?? "");
|
|
5615
5663
|
const scroll = (0, import_react3.useRef)(null);
|
|
5616
5664
|
const convo = t?.conversation ?? null;
|
|
5617
5665
|
(0, import_react3.useEffect)(() => {
|
|
@@ -5620,7 +5668,7 @@ function Thread({ store, palette: p, bottomInset }) {
|
|
|
5620
5668
|
const streamingIds = (0, import_react3.useMemo)(() => Object.keys(t?.streaming ?? {}).filter((id) => !t?.messages.some((m) => m.id === id)), [t]);
|
|
5621
5669
|
if (!t) return null;
|
|
5622
5670
|
const send = () => {
|
|
5623
|
-
const value =
|
|
5671
|
+
const value = text2;
|
|
5624
5672
|
setText("");
|
|
5625
5673
|
void store.send(value);
|
|
5626
5674
|
};
|
|
@@ -5642,7 +5690,7 @@ function Thread({ store, palette: p, bottomInset }) {
|
|
|
5642
5690
|
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
5643
5691
|
import_react_native5.TextInput,
|
|
5644
5692
|
{
|
|
5645
|
-
value:
|
|
5693
|
+
value: text2,
|
|
5646
5694
|
onChangeText: (v) => setText(v.slice(0, 4e3)),
|
|
5647
5695
|
placeholder: convo ? "Reply\u2026" : "Write a message\u2026",
|
|
5648
5696
|
placeholderTextColor: p.muted,
|
|
@@ -5651,7 +5699,7 @@ function Thread({ store, palette: p, bottomInset }) {
|
|
|
5651
5699
|
style: [styles4.input, { color: p.text, backgroundColor: p.surface, borderRadius: Math.min(18, p.radius + 6) }]
|
|
5652
5700
|
}
|
|
5653
5701
|
),
|
|
5654
|
-
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(GButton, { label: "Send", palette: p, onPress: send, disabled: !
|
|
5702
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(GButton, { label: "Send", palette: p, onPress: send, disabled: !text2.trim() || t.sending })
|
|
5655
5703
|
] })
|
|
5656
5704
|
] });
|
|
5657
5705
|
}
|
|
@@ -6555,15 +6603,15 @@ function palette(theme, systemScheme, explicit) {
|
|
|
6555
6603
|
const wantsDark = theme.dark === "dark" || theme.dark === "auto" && systemScheme === "dark";
|
|
6556
6604
|
const dark = wantsDark && !explicit?.backgroundColor;
|
|
6557
6605
|
const background = dark ? DARK.background : theme.backgroundColor ?? "#ffffff";
|
|
6558
|
-
const
|
|
6606
|
+
const text2 = dark ? DARK.text : theme.textColor ?? "#111827";
|
|
6559
6607
|
return {
|
|
6560
6608
|
primary,
|
|
6561
6609
|
onPrimary: luminance(primary) > 0.45 ? "#111827" : "#ffffff",
|
|
6562
6610
|
background,
|
|
6563
|
-
text,
|
|
6564
|
-
muted: dark ? DARK.muted : mix(
|
|
6565
|
-
border: dark ? DARK.border : mix(
|
|
6566
|
-
surface: dark ? DARK.surface : mix(
|
|
6611
|
+
text: text2,
|
|
6612
|
+
muted: dark ? DARK.muted : mix(text2, 0.65),
|
|
6613
|
+
border: dark ? DARK.border : mix(text2, 0.12),
|
|
6614
|
+
surface: dark ? DARK.surface : mix(text2, 0.05),
|
|
6567
6615
|
radius: theme.borderRadius ?? 12,
|
|
6568
6616
|
overlay: `rgba(15, 23, 42, ${theme.overlayOpacity ?? 0.55})`,
|
|
6569
6617
|
fontFamily: nativeFont(theme.fontFamily)
|
|
@@ -6790,14 +6838,25 @@ function deviceLocale() {
|
|
|
6790
6838
|
return void 0;
|
|
6791
6839
|
}
|
|
6792
6840
|
}
|
|
6793
|
-
function
|
|
6841
|
+
function nativeSources() {
|
|
6842
|
+
return {
|
|
6843
|
+
platform: import_react_native13.Platform,
|
|
6844
|
+
nativeModules: import_react_native13.NativeModules,
|
|
6845
|
+
expoModules: globalThis.expo?.modules
|
|
6846
|
+
};
|
|
6847
|
+
}
|
|
6848
|
+
function defaultBridge(appVersion, appBuild) {
|
|
6794
6849
|
const { width, height } = import_react_native13.Dimensions.get("window");
|
|
6850
|
+
const sources = nativeSources();
|
|
6851
|
+
const detected = appVersion ? {} : detectAppVersion(sources);
|
|
6795
6852
|
return {
|
|
6796
6853
|
device: {
|
|
6797
6854
|
platform: import_react_native13.Platform.OS === "android" ? "android" : "ios",
|
|
6798
6855
|
deviceType: import_react_native13.Platform.OS === "ios" && import_react_native13.Platform.isPad || Math.min(width, height) >= 600 ? "tablet" : "mobile",
|
|
6799
6856
|
locale: deviceLocale(),
|
|
6800
|
-
appVersion
|
|
6857
|
+
appVersion: appVersion ?? detected.appVersion,
|
|
6858
|
+
appBuild: appBuild ?? detected.appBuild,
|
|
6859
|
+
osVersion: detectOsVersion(sources)
|
|
6801
6860
|
},
|
|
6802
6861
|
openExternal: (url) => void import_react_native13.Linking.openURL(url).catch(() => {
|
|
6803
6862
|
}),
|
|
@@ -6842,7 +6901,7 @@ function GuidelyProvider({ children, user, insets, launcherOffset = 72, flagsPay
|
|
|
6842
6901
|
onNavigate: (url) => optionsRef.current.onNavigate?.(url),
|
|
6843
6902
|
onError: (err) => optionsRef.current.onError?.(err)
|
|
6844
6903
|
},
|
|
6845
|
-
defaultBridge(latest.appVersion)
|
|
6904
|
+
defaultBridge(latest.appVersion, latest.appBuild)
|
|
6846
6905
|
);
|
|
6847
6906
|
} catch (err) {
|
|
6848
6907
|
optionsRef.current.onError?.(err instanceof Error ? err : new Error(String(err)));
|
|
@@ -7045,6 +7104,8 @@ function useActiveGuide() {
|
|
|
7045
7104
|
TargetRegistry,
|
|
7046
7105
|
createFlagsClient,
|
|
7047
7106
|
createSseParser,
|
|
7107
|
+
detectAppVersion,
|
|
7108
|
+
detectOsVersion,
|
|
7048
7109
|
guidelyScreenLayout,
|
|
7049
7110
|
htmlToText,
|
|
7050
7111
|
noopClient,
|