@wix/himalaya-cli 0.1318.0 → 0.1320.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/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/core/sdk/sdk-types/src/capabilities.generated.d.ts +2 -1
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/core/sdk/theme/src/index.d.ts +21 -0
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/core/sdk/webview-page/src/capabilities.generated.d.ts +2 -0
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/core/ts/src/brand-color-math.d.ts +98 -0
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/core/ts/src/define-app.d.ts +1 -1
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/core/ts/src/schema.d.ts +9 -0
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/audio-record.mjs +1 -0
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/calendar.mjs +1 -0
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/calls.mjs +1 -0
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/contacts.mjs +1 -0
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/core/brand-color-math.mjs +183 -0
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/location.mjs +1 -0
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/motion.mjs +1 -0
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/photos.mjs +1 -0
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/sdk-types.mjs +1 -0
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/tasks.mjs +1 -0
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/theme.mjs +189 -0
- package/dist/authoring-runtime/node_modules/@wix/himalaya/package.json +8 -0
- package/dist/cli.mjs +574 -404
- package/dist/preview-assets.generated.bin +0 -0
- package/guides/app-config.md +1 -1
- package/guides/capabilities.md +17 -0
- package/guides/designing-himi-screens.md +2 -0
- package/guides/importable-sdks.md +1 -0
- package/guides/qa-builds.md +34 -8
- package/guides/sdk-reference.json +39 -2
- package/guides/web-page-sdk-reference.md +1 -0
- package/package.json +2 -2
- package/templates/beauty-salon-owner/config.ts +1 -1
- package/templates/beauty-salon-owner/dev/index.ts +125 -24
- package/templates/beauty-salon-owner/tier5-src/_shared/aria-attachments.ts +41 -2
- package/templates/beauty-salon-owner/tier5-src/_shared/aria-chat.ts +59 -31
- package/templates/beauty-salon-owner/tier5-src/himi-owner-lite-aria/index.ts +154 -13
- package/templates/brandy/README.md +5 -3
- package/templates/community-club-owner/config.ts +1 -1
- package/templates/community-club-owner/dev/index.ts +125 -24
- package/templates/community-club-owner/tier5-src/_shared/aria-attachments.ts +41 -2
- package/templates/community-club-owner/tier5-src/_shared/aria-chat.ts +59 -31
- package/templates/community-club-owner/tier5-src/himi-owner-lite-aria/index.ts +154 -13
- package/templates/events-meetups-owner/config.ts +1 -1
- package/templates/events-meetups-owner/dev/index.ts +125 -24
- package/templates/events-meetups-owner/tier5-src/_shared/aria-attachments.ts +41 -2
- package/templates/events-meetups-owner/tier5-src/_shared/aria-chat.ts +59 -31
- package/templates/events-meetups-owner/tier5-src/himi-owner-lite-aria/index.ts +154 -13
- package/templates/gym-fitness-owner/config.ts +1 -1
- package/templates/gym-fitness-owner/dev/index.ts +125 -24
- package/templates/gym-fitness-owner/tier5-src/_shared/aria-attachments.ts +41 -2
- package/templates/gym-fitness-owner/tier5-src/_shared/aria-chat.ts +59 -31
- package/templates/gym-fitness-owner/tier5-src/himi-owner-lite-aria/index.ts +154 -13
- package/templates/nonprofit-cause-owner/config.ts +1 -1
- package/templates/nonprofit-cause-owner/dev/index.ts +125 -24
- package/templates/nonprofit-cause-owner/tier5-src/_shared/aria-attachments.ts +41 -2
- package/templates/nonprofit-cause-owner/tier5-src/_shared/aria-chat.ts +59 -31
- package/templates/nonprofit-cause-owner/tier5-src/himi-owner-lite-aria/index.ts +154 -13
- package/templates/owner-lite/config.ts +1 -1
- package/templates/owner-lite/dev/index.ts +125 -24
- package/templates/owner-lite/tier5-src/_shared/aria-attachments.ts +41 -2
- package/templates/owner-lite/tier5-src/_shared/aria-chat.ts +59 -31
- package/templates/owner-lite/tier5-src/himi-owner-lite-aria/index.ts +154 -13
- package/templates/podcast-creator-owner/config.ts +1 -1
- package/templates/podcast-creator-owner/dev/index.ts +125 -24
- package/templates/podcast-creator-owner/tier5-src/_shared/aria-attachments.ts +41 -2
- package/templates/podcast-creator-owner/tier5-src/_shared/aria-chat.ts +59 -31
- package/templates/podcast-creator-owner/tier5-src/himi-owner-lite-aria/index.ts +154 -13
- package/templates/portfolio-creative-owner/config.ts +1 -1
- package/templates/portfolio-creative-owner/dev/index.ts +125 -24
- package/templates/portfolio-creative-owner/tier5-src/_shared/aria-attachments.ts +41 -2
- package/templates/portfolio-creative-owner/tier5-src/_shared/aria-chat.ts +59 -31
- package/templates/portfolio-creative-owner/tier5-src/himi-owner-lite-aria/index.ts +154 -13
- package/templates/restaurant-owner/config.ts +1 -1
- package/templates/restaurant-owner/dev/index.ts +125 -24
- package/templates/restaurant-owner/tier5-src/_shared/aria-attachments.ts +41 -2
- package/templates/restaurant-owner/tier5-src/_shared/aria-chat.ts +59 -31
- package/templates/restaurant-owner/tier5-src/himi-owner-lite-aria/index.ts +154 -13
- package/templates/retail-store-owner/config.ts +1 -1
- package/templates/retail-store-owner/dev/index.ts +125 -24
- package/templates/retail-store-owner/tier5-src/_shared/aria-attachments.ts +41 -2
- package/templates/retail-store-owner/tier5-src/_shared/aria-chat.ts +59 -31
- package/templates/retail-store-owner/tier5-src/himi-owner-lite-aria/index.ts +154 -13
- package/templates/yoga-studio-owner/config.ts +1 -1
- package/templates/yoga-studio-owner/dev/index.ts +125 -24
- package/templates/yoga-studio-owner/tier5-src/_shared/aria-attachments.ts +41 -2
- package/templates/yoga-studio-owner/tier5-src/_shared/aria-chat.ts +59 -31
- package/templates/yoga-studio-owner/tier5-src/himi-owner-lite-aria/index.ts +154 -13
|
@@ -28,7 +28,7 @@ import { defineService } from "@himalaya/state";
|
|
|
28
28
|
import { open } from "@himalaya/open-url";
|
|
29
29
|
import { writeText } from "@himalaya/clipboard";
|
|
30
30
|
import { availability, recognizeOnce, stop as stopSpeech } from "@himalaya/speech";
|
|
31
|
-
import { capturePhoto } from "@himalaya/camera";
|
|
31
|
+
import { capturePhoto, pickDocument } from "@himalaya/camera";
|
|
32
32
|
import { put } from "@himalaya/presigned-upload";
|
|
33
33
|
import { alert } from "@himalaya/ui";
|
|
34
34
|
import { auth } from "@himalaya/wix-platform";
|
|
@@ -250,12 +250,13 @@ const core = createAriaChat({
|
|
|
250
250
|
widgetItemsUnavailable: () => copyParam("ownerAria.widget.itemsUnavailable", "Items aren't available here."),
|
|
251
251
|
attachUploading: () => copyParam("ownerAria.attach.uploading", "Uploading…"),
|
|
252
252
|
attachFailed: () => copyParam("ownerAria.attach.failed", "Couldn't upload"),
|
|
253
|
-
attachTooMany: (max) => copyTemplate("ownerAria.attach.tooMany", "You can attach up to {max}
|
|
253
|
+
attachTooMany: (max) => copyTemplate("ownerAria.attach.tooMany", "You can attach up to {max} files.", { max }),
|
|
254
254
|
attachUnsupported: () => copyParam("ownerAria.attach.unsupported", "That file type can't be attached."),
|
|
255
|
-
attachTooLarge: (mb) => copyTemplate("ownerAria.attach.tooLarge", "That
|
|
256
|
-
attachWaitUploading: () => copyParam("ownerAria.attach.waitUploading", "Wait for your
|
|
257
|
-
attachWaitFailed: () => copyParam("ownerAria.attach.waitFailed", "Retry or remove the
|
|
258
|
-
|
|
255
|
+
attachTooLarge: (mb) => copyTemplate("ownerAria.attach.tooLarge", "That file is too large to attach (up to {mb} MB).", { mb }),
|
|
256
|
+
attachWaitUploading: () => copyParam("ownerAria.attach.waitUploading", "Wait for your file to finish uploading."),
|
|
257
|
+
attachWaitFailed: () => copyParam("ownerAria.attach.waitFailed", "Retry or remove the file that didn't upload."),
|
|
258
|
+
attachWaitRemove: () => copyParam("ownerAria.attach.waitRemove", "Remove the file that didn't upload, then add it again."),
|
|
259
|
+
attachNeedsText: () => copyParam("ownerAria.attach.needsText", "Add a message to send with your file."),
|
|
259
260
|
toolFailed: () => copyParam("ownerAria.toolFailed", "Aria couldn't finish that. Try again."),
|
|
260
261
|
},
|
|
261
262
|
clientTools: { confirm: confirmWithOwner, userAgent },
|
|
@@ -305,6 +306,10 @@ const core = createAriaChat({
|
|
|
305
306
|
// which go to a self-authorizing url with no Wix credential attached.
|
|
306
307
|
attachments: {
|
|
307
308
|
pick: async (source) => {
|
|
309
|
+
if (source === "document") {
|
|
310
|
+
const file = await pickDocument();
|
|
311
|
+
return file ? { dataUri: file.uri, name: file.name, mimeType: file.mime } : null;
|
|
312
|
+
}
|
|
308
313
|
const asset = await capturePhoto({ source, maxEdgePixels: 2048 });
|
|
309
314
|
return asset ? { dataUri: asset.uri, mimeType: asset.mime } : null;
|
|
310
315
|
},
|
|
@@ -318,6 +323,92 @@ const core = createAriaChat({
|
|
|
318
323
|
},
|
|
319
324
|
});
|
|
320
325
|
|
|
326
|
+
// Focused native TextFields keep their local non-empty edit rather than adopting
|
|
327
|
+
// worker normalization (the shared shouldAdoptWorkerValue rule). Remember only
|
|
328
|
+
// prefixes where THIS draft actually selected a reference, so later editor echoes and
|
|
329
|
+
// the Form.message submission cannot restore those triggers into the wire text.
|
|
330
|
+
// Email addresses and newly authored @ characters are never blanket-stripped.
|
|
331
|
+
let mentionTriggerPrefixes: string[] = [];
|
|
332
|
+
let pendingMentionTrigger: { rawPrefix: string; prefix: string } | null = null;
|
|
333
|
+
let mentionDraftRevision = 0;
|
|
334
|
+
let previousMentionRaw = "";
|
|
335
|
+
// Set by a selection that consumed a typed trigger: the normalized draft the
|
|
336
|
+
// worker now holds. A field that blurs adopts that value WITHOUT dispatching
|
|
337
|
+
// typing, so the next keystroke is an edit of it, not of previousMentionRaw.
|
|
338
|
+
// The first typing after a selection whose raw value is byte-identical to the
|
|
339
|
+
// pre-selection one cannot be an edit of the focused raw text (nothing changed),
|
|
340
|
+
// so it is read as an edit of the adopted draft: that field holds no consumed
|
|
341
|
+
// marker any more, and a standalone @ there is a new trigger.
|
|
342
|
+
let adoptedMentionDraft: string | null = null;
|
|
343
|
+
function reconcileMentionDraft(raw: string): string {
|
|
344
|
+
// Move consumed trigger positions with an edit anywhere in the focused field.
|
|
345
|
+
// A replaced/deleted trigger loses its marker, so newly authored @ text stays literal.
|
|
346
|
+
let start = 0;
|
|
347
|
+
while (start < previousMentionRaw.length && start < raw.length && previousMentionRaw[start] === raw[start]) start += 1;
|
|
348
|
+
let suffix = 0;
|
|
349
|
+
while (suffix < previousMentionRaw.length - start && suffix < raw.length - start
|
|
350
|
+
&& previousMentionRaw[previousMentionRaw.length - suffix - 1] === raw[raw.length - suffix - 1]) suffix += 1;
|
|
351
|
+
const end = previousMentionRaw.length - suffix;
|
|
352
|
+
const delta = raw.length - previousMentionRaw.length;
|
|
353
|
+
const move = (position: number): number | null => position < start ? position : position >= end ? position + delta : null;
|
|
354
|
+
mentionTriggerPrefixes = mentionTriggerPrefixes.flatMap(prefix => {
|
|
355
|
+
let position = move(prefix.length);
|
|
356
|
+
// A whole-draft replacement ("Ask @" → "New @") shares only whitespace and the @
|
|
357
|
+
// with the old text, so the common suffix lines the NEW @ up with the old marker.
|
|
358
|
+
// When every word before the marker was replaced, its context is gone: the @ is
|
|
359
|
+
// newly authored and must stay (and may open the picker again).
|
|
360
|
+
if (position !== null && start === 0 && prefix.length >= end && prefix.trim()
|
|
361
|
+
&& !previousMentionRaw.slice(end, prefix.length).trim()) return [];
|
|
362
|
+
// Coalesced edits may add text on both sides of the marker. Keep it when
|
|
363
|
+
// its complete previous context still occurs exactly once in the new value.
|
|
364
|
+
if (position === null && prefix) {
|
|
365
|
+
const anchor = `${prefix}@`; const found = raw.indexOf(anchor);
|
|
366
|
+
if (found >= 0 && raw.indexOf(anchor, found + 1) < 0) position = found + prefix.length;
|
|
367
|
+
}
|
|
368
|
+
// A coalesced focused-field edit can replace context on both sides of a
|
|
369
|
+
// selected marker. If this is the sole consumed marker and the new draft
|
|
370
|
+
// has one standalone @, its position is unambiguous even without the old
|
|
371
|
+
// prefix. Email addresses and authored @suffixes are never candidates.
|
|
372
|
+
if (position === null && mentionTriggerPrefixes.length === 1) {
|
|
373
|
+
const candidates = [...raw.matchAll(/(^|\s)@(?=\s|$)/g)].map(match => match.index! + match[1].length);
|
|
374
|
+
if (candidates.length === 1) position = candidates[0];
|
|
375
|
+
}
|
|
376
|
+
// Only the standalone trigger that opened the picker is consumed. Adding
|
|
377
|
+
// a literal suffix (or joining it to the preceding word) authors ordinary
|
|
378
|
+
// @ text even when the focused editor retains the selected trigger.
|
|
379
|
+
const standalone = position !== null && raw[position] === "@"
|
|
380
|
+
&& (position === 0 || /\s/.test(raw[position - 1]))
|
|
381
|
+
&& (position + 1 === raw.length || /\s/.test(raw[position + 1]));
|
|
382
|
+
return standalone ? [raw.slice(0, position!)] : [];
|
|
383
|
+
});
|
|
384
|
+
if (pendingMentionTrigger) {
|
|
385
|
+
const position = move(pendingMentionTrigger.rawPrefix.length);
|
|
386
|
+
const standalone = position !== null && raw[position] === "@"
|
|
387
|
+
&& (position === 0 || /\s/.test(raw[position - 1]))
|
|
388
|
+
&& (position + 1 === raw.length || /\s/.test(raw[position + 1]));
|
|
389
|
+
pendingMentionTrigger = standalone
|
|
390
|
+
? { rawPrefix: raw.slice(0, position!), prefix: raw.slice(0, position!) } : null;
|
|
391
|
+
if (pendingMentionTrigger) {
|
|
392
|
+
for (const prefix of [...mentionTriggerPrefixes].sort((a, b) => b.length - a.length)) {
|
|
393
|
+
if (prefix.length < pendingMentionTrigger.rawPrefix.length) pendingMentionTrigger.prefix = pendingMentionTrigger.prefix.slice(0, prefix.length) + pendingMentionTrigger.prefix.slice(prefix.length + 1);
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
previousMentionRaw = raw;
|
|
398
|
+
let text = raw;
|
|
399
|
+
for (const prefix of [...mentionTriggerPrefixes].sort((a, b) => b.length - a.length)) {
|
|
400
|
+
text = text.slice(0, prefix.length) + text.slice(prefix.length + 1);
|
|
401
|
+
}
|
|
402
|
+
return text;
|
|
403
|
+
}
|
|
404
|
+
function reconciledMentionArg(arg?: AriaActionArg): AriaActionArg | undefined {
|
|
405
|
+
if (typeof arg === "string") return reconcileMentionDraft(arg);
|
|
406
|
+
if (!arg) return arg;
|
|
407
|
+
const keys: Array<"message" | "text" | "value" | "intent" | "id"> = ["message", "text", "value", "intent", "id"];
|
|
408
|
+
const key = keys.find(k => typeof arg[k] === "string" && arg[k]);
|
|
409
|
+
return key ? { ...arg, [key]: reconcileMentionDraft(String(arg[key])) } : arg;
|
|
410
|
+
}
|
|
411
|
+
|
|
321
412
|
const svc = defineService<AriaChatState, {
|
|
322
413
|
load: (s: AriaChatState, arg?: AriaActionArg) => Promise<AriaChatState>;
|
|
323
414
|
submit: (s: AriaChatState, arg?: AriaActionArg) => Promise<AriaChatState>;
|
|
@@ -374,13 +465,51 @@ const svc = defineService<AriaChatState, {
|
|
|
374
465
|
state: core.initialState,
|
|
375
466
|
actions: {
|
|
376
467
|
// `load` is the onAppear dispatch, so it is where the copy pack arrives.
|
|
377
|
-
load: (s, arg) => { stashCopy(arg); stashTargets(arg); stashRealtimeUrl(arg); return core.load(s); },
|
|
378
|
-
submit:
|
|
379
|
-
|
|
380
|
-
|
|
468
|
+
load: (s, arg) => { mentionDraftRevision += 1; mentionTriggerPrefixes = []; pendingMentionTrigger = null; previousMentionRaw = ""; adoptedMentionDraft = null; stashCopy(arg); stashTargets(arg); stashRealtimeUrl(arg); return core.load(s); },
|
|
469
|
+
submit: async (s, arg) => {
|
|
470
|
+
const normalized = reconciledMentionArg(arg);
|
|
471
|
+
const previousPrefixes = mentionTriggerPrefixes; const previousTrigger = pendingMentionTrigger;
|
|
472
|
+
const revision = mentionDraftRevision;
|
|
473
|
+
const next = await core.submit(s, normalized);
|
|
474
|
+
// A refusal keeps this draft; a later keystroke/new-chat belongs to its own.
|
|
475
|
+
if (revision === mentionDraftRevision) {
|
|
476
|
+
if (next.input && next.input === s.input) { mentionTriggerPrefixes = previousPrefixes; pendingMentionTrigger = previousTrigger; }
|
|
477
|
+
else { mentionTriggerPrefixes = []; pendingMentionTrigger = null; previousMentionRaw = ""; adoptedMentionDraft = null; }
|
|
478
|
+
}
|
|
479
|
+
return next;
|
|
480
|
+
},
|
|
481
|
+
submitPrompt: async (s, arg) => {
|
|
482
|
+
const previousPrefixes = mentionTriggerPrefixes; const previousTrigger = pendingMentionTrigger;
|
|
483
|
+
const revision = mentionDraftRevision;
|
|
484
|
+
const next = await core.submitPrompt(s, arg);
|
|
485
|
+
if (revision === mentionDraftRevision) {
|
|
486
|
+
if (next.input && next.input === s.input) { mentionTriggerPrefixes = previousPrefixes; pendingMentionTrigger = previousTrigger; }
|
|
487
|
+
else { mentionTriggerPrefixes = []; pendingMentionTrigger = null; previousMentionRaw = ""; adoptedMentionDraft = null; }
|
|
488
|
+
}
|
|
489
|
+
return next;
|
|
490
|
+
},
|
|
491
|
+
newChat: (s) => { mentionDraftRevision += 1; mentionTriggerPrefixes = []; pendingMentionTrigger = null; previousMentionRaw = ""; adoptedMentionDraft = null; return core.newChat(s); },
|
|
381
492
|
// The composer's onChange. Mirrors the draft into state so `submit` can
|
|
382
493
|
// empty it and the field actually clears.
|
|
383
|
-
typing:
|
|
494
|
+
typing: (s, arg) => {
|
|
495
|
+
mentionDraftRevision += 1;
|
|
496
|
+
const raw = typeof arg === "string" ? arg : ([arg?.value, arg?.text, arg?.message].find((v): v is string => typeof v === "string") ?? "");
|
|
497
|
+
if (adoptedMentionDraft !== null) {
|
|
498
|
+
if (raw === previousMentionRaw) { mentionTriggerPrefixes = []; previousMentionRaw = adoptedMentionDraft; }
|
|
499
|
+
adoptedMentionDraft = null;
|
|
500
|
+
}
|
|
501
|
+
const next = core.typing(s, { value: reconcileMentionDraft(raw) });
|
|
502
|
+
// A standalone @ asks for a reference; emails and embedded @ characters
|
|
503
|
+
// remain ordinary text. A successful selection consumes its trigger.
|
|
504
|
+
if (next.input !== s.input && /(?:^|\s)@$/.test(next.input) && !next.mention.openHidden) {
|
|
505
|
+
// Keep the fragment editable until a reference is selected. Cancelling
|
|
506
|
+
// the picker must not turn a literal @example.com into example.com.
|
|
507
|
+
pendingMentionTrigger = { rawPrefix: raw.slice(0, -1), prefix: next.input.slice(0, -1) };
|
|
508
|
+
void svc.mentionOpen();
|
|
509
|
+
return next;
|
|
510
|
+
}
|
|
511
|
+
return next;
|
|
512
|
+
},
|
|
384
513
|
// Named by the `_poll` directive above. A name that does not resolve here is
|
|
385
514
|
// a `poll-action-missing` error in `himi test --content`.
|
|
386
515
|
tick: core.tick,
|
|
@@ -419,11 +548,23 @@ const svc = defineService<AriaChatState, {
|
|
|
419
548
|
// chips above the composer. Every one is named by the descriptor, so every
|
|
420
549
|
// one has to be exported here — see the note on the picker family above.
|
|
421
550
|
mentionOpen: core.mentionOpen,
|
|
422
|
-
mentionClose: core.mentionClose,
|
|
551
|
+
mentionClose: (s) => { pendingMentionTrigger = null; return core.mentionClose(s); },
|
|
423
552
|
mentionBack: core.mentionBack,
|
|
424
553
|
mentionProvider: core.mentionProvider,
|
|
425
554
|
mentionQuery: core.mentionQuery,
|
|
426
|
-
mentionPick:
|
|
555
|
+
mentionPick: (s, arg) => {
|
|
556
|
+
const next = core.mentionPick(s, arg);
|
|
557
|
+
const trigger = pendingMentionTrigger;
|
|
558
|
+
if (trigger && !s.mention.hidden && next.mention.hidden && next.input.startsWith(`${trigger.prefix}@`)) {
|
|
559
|
+
mentionDraftRevision += 1;
|
|
560
|
+
pendingMentionTrigger = null;
|
|
561
|
+
if (!mentionTriggerPrefixes.includes(trigger.rawPrefix)) mentionTriggerPrefixes.push(trigger.rawPrefix);
|
|
562
|
+
const normalized = next.input.slice(0, trigger.prefix.length) + next.input.slice(trigger.prefix.length + 1);
|
|
563
|
+
adoptedMentionDraft = normalized;
|
|
564
|
+
return core.typing(next, { value: normalized });
|
|
565
|
+
}
|
|
566
|
+
return next;
|
|
567
|
+
},
|
|
427
568
|
mentionRemove: core.mentionRemove,
|
|
428
569
|
// The composer's photos. `attachmentSettled` is dispatched by the upload
|
|
429
570
|
// itself (see `attachments.settled` above), never by the descriptor.
|
|
@@ -37,7 +37,7 @@ export default defineApp({
|
|
|
37
37
|
actions: "http://localhost:8190/v1/actions",
|
|
38
38
|
sync: "http://localhost:8190/v1/sync",
|
|
39
39
|
},
|
|
40
|
-
capabilities: ["live_activity","push","share","secure_storage","open_url","local_database","clipboard","ui","speech","camera","presigned_upload","app_info","biometrics"],
|
|
40
|
+
capabilities: ["live_activity","push","share","secure_storage","open_url","local_database","clipboard","ui","speech","camera","presigned_upload","app_info","biometrics","wix_platform"],
|
|
41
41
|
designTokensPath: "./tokens.json",
|
|
42
42
|
navigation: {
|
|
43
43
|
"navKind": "responsive",
|
|
@@ -62051,6 +62051,65 @@ const SCREENS = runtimeSetting({
|
|
|
62051
62051
|
},
|
|
62052
62052
|
{
|
|
62053
62053
|
"id": "",
|
|
62054
|
+
"body": {
|
|
62055
|
+
"package": "himalaya",
|
|
62056
|
+
"type": "VStack",
|
|
62057
|
+
"props": {
|
|
62058
|
+
"spacing": 4,
|
|
62059
|
+
"children": [
|
|
62060
|
+
{
|
|
62061
|
+
"id": "",
|
|
62062
|
+
"body": {
|
|
62063
|
+
"package": "himalaya",
|
|
62064
|
+
"type": "Icon",
|
|
62065
|
+
"props": {
|
|
62066
|
+
"name": "doc",
|
|
62067
|
+
"size": 24,
|
|
62068
|
+
"tint": "textSecondary"
|
|
62069
|
+
}
|
|
62070
|
+
},
|
|
62071
|
+
"modifiers": {
|
|
62072
|
+
"accessibilityRole": "decorative"
|
|
62073
|
+
}
|
|
62074
|
+
},
|
|
62075
|
+
{
|
|
62076
|
+
"id": "",
|
|
62077
|
+
"body": {
|
|
62078
|
+
"package": "himalaya",
|
|
62079
|
+
"type": "Text",
|
|
62080
|
+
"props": {
|
|
62081
|
+
"text": "$item.name",
|
|
62082
|
+
"style": "caption",
|
|
62083
|
+
"color": "textPrimary",
|
|
62084
|
+
"maxLines": 2
|
|
62085
|
+
}
|
|
62086
|
+
},
|
|
62087
|
+
"modifiers": {
|
|
62088
|
+
"height": 44
|
|
62089
|
+
}
|
|
62090
|
+
},
|
|
62091
|
+
{
|
|
62092
|
+
"id": "",
|
|
62093
|
+
"body": {
|
|
62094
|
+
"package": "himalaya",
|
|
62095
|
+
"type": "Text",
|
|
62096
|
+
"props": {
|
|
62097
|
+
"text": "$item.typeLabel",
|
|
62098
|
+
"style": "caption",
|
|
62099
|
+
"color": "textSecondary",
|
|
62100
|
+
"maxLines": 1
|
|
62101
|
+
}
|
|
62102
|
+
}
|
|
62103
|
+
}
|
|
62104
|
+
]
|
|
62105
|
+
}
|
|
62106
|
+
},
|
|
62107
|
+
"modifiers": {
|
|
62108
|
+
"hiddenPath": "$item.documentHidden"
|
|
62109
|
+
}
|
|
62110
|
+
},
|
|
62111
|
+
{
|
|
62112
|
+
"id": "himi_owner_lite_aria.attachment_status_$item.id",
|
|
62054
62113
|
"body": {
|
|
62055
62114
|
"package": "himalaya",
|
|
62056
62115
|
"type": "Text",
|
|
@@ -62062,6 +62121,7 @@ const SCREENS = runtimeSetting({
|
|
|
62062
62121
|
}
|
|
62063
62122
|
},
|
|
62064
62123
|
"modifiers": {
|
|
62124
|
+
"height": 44,
|
|
62065
62125
|
"hiddenPath": "$item.statusHidden"
|
|
62066
62126
|
}
|
|
62067
62127
|
},
|
|
@@ -62077,21 +62137,22 @@ const SCREENS = runtimeSetting({
|
|
|
62077
62137
|
"id": "himi_owner_lite_aria.attachment_retry_$item.id",
|
|
62078
62138
|
"body": {
|
|
62079
62139
|
"package": "himalaya",
|
|
62080
|
-
"type": "
|
|
62140
|
+
"type": "Button",
|
|
62081
62141
|
"props": {
|
|
62082
|
-
"
|
|
62083
|
-
"
|
|
62084
|
-
|
|
62085
|
-
|
|
62142
|
+
"title": "Retry",
|
|
62143
|
+
"action": {
|
|
62144
|
+
"actionId": "tier5.himiOwnerLiteAria.retryAttachment",
|
|
62145
|
+
"params": {
|
|
62146
|
+
"id": "$item.id"
|
|
62147
|
+
}
|
|
62148
|
+
},
|
|
62149
|
+
"style": "tertiary",
|
|
62150
|
+
"size": "sm"
|
|
62086
62151
|
}
|
|
62087
62152
|
},
|
|
62088
62153
|
"modifiers": {
|
|
62089
|
-
"
|
|
62090
|
-
|
|
62091
|
-
"params": {
|
|
62092
|
-
"id": "$item.id"
|
|
62093
|
-
}
|
|
62094
|
-
},
|
|
62154
|
+
"width": 92,
|
|
62155
|
+
"height": 48,
|
|
62095
62156
|
"hiddenPath": "$item.retryHidden"
|
|
62096
62157
|
}
|
|
62097
62158
|
},
|
|
@@ -62099,32 +62160,51 @@ const SCREENS = runtimeSetting({
|
|
|
62099
62160
|
"id": "himi_owner_lite_aria.attachment_remove_$item.id",
|
|
62100
62161
|
"body": {
|
|
62101
62162
|
"package": "himalaya",
|
|
62102
|
-
"type": "
|
|
62163
|
+
"type": "Button",
|
|
62103
62164
|
"props": {
|
|
62104
|
-
"
|
|
62105
|
-
"
|
|
62106
|
-
|
|
62165
|
+
"title": "Remove attachment",
|
|
62166
|
+
"action": {
|
|
62167
|
+
"actionId": "tier5.himiOwnerLiteAria.removeAttachment",
|
|
62168
|
+
"params": {
|
|
62169
|
+
"id": "$item.id"
|
|
62170
|
+
}
|
|
62171
|
+
},
|
|
62172
|
+
"style": "tertiary",
|
|
62173
|
+
"iconOnly": true,
|
|
62174
|
+
"leadingIcon": "close",
|
|
62175
|
+
"cornerRadius": 24,
|
|
62176
|
+
"minHeight": 48
|
|
62107
62177
|
}
|
|
62108
62178
|
},
|
|
62109
62179
|
"modifiers": {
|
|
62110
|
-
"
|
|
62111
|
-
|
|
62112
|
-
|
|
62113
|
-
|
|
62114
|
-
}
|
|
62115
|
-
},
|
|
62116
|
-
"accessibilityLabel": "Remove photo"
|
|
62180
|
+
"width": 48,
|
|
62181
|
+
"height": 48,
|
|
62182
|
+
"accessibilityLabel": "Remove attachment",
|
|
62183
|
+
"accessibilityRole": "button"
|
|
62117
62184
|
}
|
|
62118
62185
|
}
|
|
62119
62186
|
]
|
|
62120
62187
|
}
|
|
62188
|
+
},
|
|
62189
|
+
"modifiers": {
|
|
62190
|
+
"height": 48
|
|
62121
62191
|
}
|
|
62122
62192
|
}
|
|
62123
62193
|
]
|
|
62124
62194
|
}
|
|
62125
62195
|
},
|
|
62126
62196
|
"modifiers": {
|
|
62127
|
-
"width":
|
|
62197
|
+
"width": 160,
|
|
62198
|
+
"padding": {
|
|
62199
|
+
"top": 8,
|
|
62200
|
+
"bottom": 8,
|
|
62201
|
+
"leading": 8,
|
|
62202
|
+
"trailing": 8
|
|
62203
|
+
},
|
|
62204
|
+
"background": {
|
|
62205
|
+
"token": "surfaceSecondary"
|
|
62206
|
+
},
|
|
62207
|
+
"cornerRadius": 12
|
|
62128
62208
|
}
|
|
62129
62209
|
}
|
|
62130
62210
|
]
|
|
@@ -62136,7 +62216,7 @@ const SCREENS = runtimeSetting({
|
|
|
62136
62216
|
"leading": 0,
|
|
62137
62217
|
"trailing": 0,
|
|
62138
62218
|
"top": 8,
|
|
62139
|
-
"bottom":
|
|
62219
|
+
"bottom": 8
|
|
62140
62220
|
}
|
|
62141
62221
|
}
|
|
62142
62222
|
},
|
|
@@ -62189,6 +62269,27 @@ const SCREENS = runtimeSetting({
|
|
|
62189
62269
|
},
|
|
62190
62270
|
"accessibilityLabel": "Take a photo"
|
|
62191
62271
|
}
|
|
62272
|
+
},
|
|
62273
|
+
{
|
|
62274
|
+
"id": "himi_owner_lite_aria.attach.document",
|
|
62275
|
+
"body": {
|
|
62276
|
+
"package": "himalaya",
|
|
62277
|
+
"type": "Icon",
|
|
62278
|
+
"props": {
|
|
62279
|
+
"name": "document",
|
|
62280
|
+
"size": 22,
|
|
62281
|
+
"tint": "accentPrimary"
|
|
62282
|
+
}
|
|
62283
|
+
},
|
|
62284
|
+
"modifiers": {
|
|
62285
|
+
"onTap": {
|
|
62286
|
+
"actionId": "tier5.himiOwnerLiteAria.attach",
|
|
62287
|
+
"params": {
|
|
62288
|
+
"source": "document"
|
|
62289
|
+
}
|
|
62290
|
+
},
|
|
62291
|
+
"accessibilityLabel": "Add files"
|
|
62292
|
+
}
|
|
62192
62293
|
}
|
|
62193
62294
|
]
|
|
62194
62295
|
}
|
|
@@ -27,6 +27,14 @@ export const ARIA_IMAGE_TYPES: readonly string[] = [
|
|
|
27
27
|
"image/heic",
|
|
28
28
|
];
|
|
29
29
|
|
|
30
|
+
/** Document MIME types supported by the native Aria reference. */
|
|
31
|
+
export const ARIA_DOCUMENT_TYPES: readonly string[] = [
|
|
32
|
+
"text/csv", "text/plain", "application/pdf", "application/msword",
|
|
33
|
+
"application/vnd.ms-excel", "application/vnd.ms-powerpoint",
|
|
34
|
+
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
|
|
35
|
+
"application/vnd.openxmlformats-officedocument.wordprocessingml.document",
|
|
36
|
+
];
|
|
37
|
+
|
|
30
38
|
/** At most this many attachments ride one message. The native Aria app caps at
|
|
31
39
|
* 10; nothing on the wire says otherwise. */
|
|
32
40
|
export const ARIA_MAX_ATTACHMENTS = 10;
|
|
@@ -40,6 +48,9 @@ export const ARIA_MAX_ATTACHMENTS = 10;
|
|
|
40
48
|
* Checking it HERE is what turns that refusal into a sentence the owner can act
|
|
41
49
|
* on, instead of a chip that fails for no stated reason. */
|
|
42
50
|
export const ARIA_MAX_IMAGE_BYTES = 8 * 1024 * 1024;
|
|
51
|
+
// Inline documents include base64 and JSON overhead under the 4 MiB frame bridge.
|
|
52
|
+
// Larger documents use the file-backed attachment follow-up.
|
|
53
|
+
export const ARIA_MAX_DOCUMENT_BYTES = 2 * 1024 * 1024;
|
|
43
54
|
|
|
44
55
|
/** A chip in the composer. Every field is always present — a `$item.` path that
|
|
45
56
|
* is missing on some rows does not substitute — and each `…Hidden` flag
|
|
@@ -58,6 +69,9 @@ export interface AriaAttachmentChip {
|
|
|
58
69
|
* runtime's frame limit. */
|
|
59
70
|
thumbUrl: string;
|
|
60
71
|
thumbHidden: boolean;
|
|
72
|
+
/** Filename/type card for documents (images keep the 72pt preview). */
|
|
73
|
+
documentHidden: boolean;
|
|
74
|
+
typeLabel: string;
|
|
61
75
|
/** "Uploading…" / "Couldn't upload" / "" — collapses when empty. */
|
|
62
76
|
statusText: string;
|
|
63
77
|
statusHidden: boolean;
|
|
@@ -113,6 +127,21 @@ export function normalizeMime(mime: string): string {
|
|
|
113
127
|
}
|
|
114
128
|
}
|
|
115
129
|
|
|
130
|
+
/** Native providers sometimes report a generic MIME; match the reference's
|
|
131
|
+
* extension fallback only for those values, not a conflicting explicit type. */
|
|
132
|
+
export function attachmentMime(mime: string, name = ""): string {
|
|
133
|
+
const normalized = normalizeMime(mime);
|
|
134
|
+
if (normalized === "text/comma-separated-values") return "text/csv";
|
|
135
|
+
if (normalized && normalized !== "application/octet-stream") return normalized;
|
|
136
|
+
const extension = name.split(".").pop()?.toLowerCase() ?? "";
|
|
137
|
+
const types: Record<string, string> = {
|
|
138
|
+
png: "image/png", jpg: "image/jpeg", jpeg: "image/jpeg", webp: "image/webp", gif: "image/gif", heic: "image/heic", heif: "image/heif",
|
|
139
|
+
csv: "text/csv", txt: "text/plain", pdf: "application/pdf", doc: "application/msword", xls: "application/vnd.ms-excel", ppt: "application/vnd.ms-powerpoint",
|
|
140
|
+
xlsx: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", docx: "application/vnd.openxmlformats-officedocument.wordprocessingml.document", pptx: "application/vnd.openxmlformats-officedocument.presentationml.presentation",
|
|
141
|
+
};
|
|
142
|
+
return types[extension] ?? normalized;
|
|
143
|
+
}
|
|
144
|
+
|
|
116
145
|
/** A file name for an image the picker did not name, by type. The service
|
|
117
146
|
* requires one (1–255 characters), and it is what the transcript shows. */
|
|
118
147
|
export function imageFileName(mimeType: string, n: number, given?: string): string {
|
|
@@ -131,8 +160,8 @@ export type AttachRefusal = "" | "type" | "size" | "count";
|
|
|
131
160
|
|
|
132
161
|
export function refusalFor(parsed: ParsedDataUri | null, mimeType: string, attached: number): AttachRefusal {
|
|
133
162
|
if (attached >= ARIA_MAX_ATTACHMENTS) return "count";
|
|
134
|
-
if (!parsed || !ARIA_IMAGE_TYPES.includes(mimeType)) return "type";
|
|
135
|
-
if (parsed.bytes > ARIA_MAX_IMAGE_BYTES) return "size";
|
|
163
|
+
if (!parsed || ![...ARIA_IMAGE_TYPES, ...ARIA_DOCUMENT_TYPES].includes(mimeType)) return "type";
|
|
164
|
+
if (parsed.bytes > (mimeType.startsWith("image/") ? ARIA_MAX_IMAGE_BYTES : ARIA_MAX_DOCUMENT_BYTES)) return "size";
|
|
136
165
|
return "";
|
|
137
166
|
}
|
|
138
167
|
|
|
@@ -146,10 +175,20 @@ export function chipIn(
|
|
|
146
175
|
ref = "",
|
|
147
176
|
): AriaAttachmentChip {
|
|
148
177
|
const statusText = state === "uploading" ? labels.uploading : state === "failed" ? labels.failed : "";
|
|
178
|
+
const dot = base.name.lastIndexOf(".");
|
|
179
|
+
const extension = dot > 0 && dot < base.name.length - 1 ? base.name.slice(dot + 1).toUpperCase() : "";
|
|
180
|
+
const mimeLabels: Record<string, string> = {
|
|
181
|
+
"application/pdf": "PDF", "text/csv": "CSV", "text/plain": "TXT", "application/msword": "DOC",
|
|
182
|
+
"application/vnd.ms-excel": "XLS", "application/vnd.ms-powerpoint": "PPT",
|
|
183
|
+
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet": "XLSX",
|
|
184
|
+
"application/vnd.openxmlformats-officedocument.wordprocessingml.document": "DOCX",
|
|
185
|
+
};
|
|
149
186
|
return {
|
|
150
187
|
...base,
|
|
151
188
|
state,
|
|
152
189
|
thumbHidden: !base.thumbUrl,
|
|
190
|
+
documentHidden: base.mimeType.startsWith("image/"),
|
|
191
|
+
typeLabel: extension || mimeLabels[base.mimeType] || base.mimeType,
|
|
153
192
|
statusText,
|
|
154
193
|
statusHidden: !statusText,
|
|
155
194
|
retryHidden: state !== "failed",
|