@olares/lares-mobile 0.15.7 → 0.15.9
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/package.json +2 -2
- package/src/App.vue +254 -144
- package/src/chat/ChatBar.vue +134 -33
- package/src/chat/Composer.vue +245 -213
- package/src/chat/Deliverables.vue +83 -11
- package/src/chat/HistoryPanel.vue +40 -1
- package/src/chat/QuestionCard.vue +3 -3
- package/src/chat/Transcript.vue +162 -4
- package/src/chat/format.js +11 -0
- package/src/chat/playback.js +41 -0
- package/src/chat/voice.js +169 -39
- package/src/desktop/DesktopPreview.vue +10 -2
- package/src/desktop/DesktopShell.vue +2 -0
- package/src/host.js +131 -21
- package/src/index.d.ts +5 -0
- package/src/mobile/MobileNewSession.vue +6 -117
- package/src/mobile/MobileShell.vue +57 -69
- package/src/preview/Preview.vue +30 -16
- package/src/preview/PreviewBody.vue +4 -1
- package/src/settings/AgentSettings.vue +16 -8
- package/src/settings/Sheet.vue +4 -0
package/src/chat/Composer.vue
CHANGED
|
@@ -4,6 +4,8 @@
|
|
|
4
4
|
class="lares-composer__card"
|
|
5
5
|
data-composer-card
|
|
6
6
|
:data-hero="hero ? 'true' : 'false'"
|
|
7
|
+
:data-mode="inputMode"
|
|
8
|
+
:data-expanded="expanded ? 'true' : 'false'"
|
|
7
9
|
:data-holding="holding ? 'true' : 'false'"
|
|
8
10
|
>
|
|
9
11
|
<div v-if="referenceOpen" ref="referenceMenu" class="lares-composer__menu" role="listbox">
|
|
@@ -80,56 +82,53 @@
|
|
|
80
82
|
</button>
|
|
81
83
|
</figure>
|
|
82
84
|
</div>
|
|
83
|
-
<
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
<circle class="lares-composer__nucleus" cx="12" cy="12" r="2.5" />
|
|
126
|
-
<ellipse cx="12" cy="12" rx="9.2" ry="3.8" />
|
|
127
|
-
<ellipse cx="12" cy="12" rx="9.2" ry="3.8" transform="rotate(60 12 12)" />
|
|
128
|
-
<ellipse cx="12" cy="12" rx="9.2" ry="3.8" transform="rotate(-60 12 12)" />
|
|
85
|
+
<div class="lares-composer__line" :data-expanded="expanded ? 'true' : 'false'">
|
|
86
|
+
<button
|
|
87
|
+
type="button"
|
|
88
|
+
class="lares-composer__icon"
|
|
89
|
+
data-kind="attach"
|
|
90
|
+
:disabled="attachDisabled"
|
|
91
|
+
:aria-label="attachLabel"
|
|
92
|
+
@click="pickFiles"
|
|
93
|
+
>
|
|
94
|
+
<svg viewBox="0 0 24 24" aria-hidden="true">
|
|
95
|
+
<path d="M12 5v14M5 12h14" />
|
|
96
|
+
</svg>
|
|
97
|
+
</button>
|
|
98
|
+
<textarea
|
|
99
|
+
v-show="inputMode === 'text'"
|
|
100
|
+
ref="input"
|
|
101
|
+
:value="draft"
|
|
102
|
+
class="lares-composer__input"
|
|
103
|
+
rows="1"
|
|
104
|
+
:placeholder="placeholder"
|
|
105
|
+
:disabled="sending"
|
|
106
|
+
@input="onInput"
|
|
107
|
+
@keydown="onKeydown"
|
|
108
|
+
@click="onCaretMove"
|
|
109
|
+
@keyup="onCaretMove"
|
|
110
|
+
@select="onCaretMove"
|
|
111
|
+
@contextmenu="onContextMenu"
|
|
112
|
+
/>
|
|
113
|
+
<button
|
|
114
|
+
v-show="inputMode === 'voice'"
|
|
115
|
+
type="button"
|
|
116
|
+
class="lares-composer__talk"
|
|
117
|
+
:data-phase="voicePhase"
|
|
118
|
+
:disabled="voiceBlocked"
|
|
119
|
+
:aria-label="voiceLabel"
|
|
120
|
+
@pointerdown="onVoiceDown"
|
|
121
|
+
@touchstart.prevent="onVoiceTouchStart"
|
|
122
|
+
@contextmenu.prevent
|
|
123
|
+
>
|
|
124
|
+
<span v-if="voicePhase === 'preparing' || voicePhase === 'transcribing'" class="lares-composer__talk-status">
|
|
125
|
+
<svg class="lares-composer__spin" viewBox="0 0 16 16" aria-hidden="true">
|
|
126
|
+
<circle cx="8" cy="8" r="6" />
|
|
129
127
|
</svg>
|
|
130
|
-
<span>{{
|
|
131
|
-
</
|
|
132
|
-
|
|
128
|
+
<span>{{ talkLabel }}</span>
|
|
129
|
+
</span>
|
|
130
|
+
<span v-else>{{ talkLabel }}</span>
|
|
131
|
+
</button>
|
|
133
132
|
<div class="lares-composer__tools">
|
|
134
133
|
<input
|
|
135
134
|
ref="picker"
|
|
@@ -139,17 +138,22 @@
|
|
|
139
138
|
@change="onFiles"
|
|
140
139
|
/>
|
|
141
140
|
<button
|
|
141
|
+
v-if="inputMode === 'text'"
|
|
142
142
|
type="button"
|
|
143
143
|
class="lares-composer__icon"
|
|
144
|
-
|
|
145
|
-
:
|
|
146
|
-
|
|
144
|
+
data-kind="voice"
|
|
145
|
+
:disabled="sending"
|
|
146
|
+
:aria-label="t('composer.voice')"
|
|
147
|
+
@click="setMode('voice')"
|
|
147
148
|
>
|
|
148
|
-
<svg viewBox="0 0 24 24" aria-hidden="true">
|
|
149
|
-
<path d="
|
|
149
|
+
<svg class="lares-composer__wave" viewBox="0 0 24 24" aria-hidden="true">
|
|
150
|
+
<path d="M5 8v8" />
|
|
151
|
+
<path d="M12 5v14" />
|
|
152
|
+
<path d="M19 8v8" />
|
|
150
153
|
</svg>
|
|
151
154
|
</button>
|
|
152
155
|
<button
|
|
156
|
+
v-if="expanded"
|
|
153
157
|
type="submit"
|
|
154
158
|
class="lares-composer__icon"
|
|
155
159
|
data-kind="send"
|
|
@@ -157,35 +161,27 @@
|
|
|
157
161
|
:aria-label="t('chat.send')"
|
|
158
162
|
>
|
|
159
163
|
<svg viewBox="0 0 24 24" aria-hidden="true">
|
|
160
|
-
<path d="M12
|
|
164
|
+
<path d="M12 19V5M5 12.5 12 5l7 7.5" />
|
|
161
165
|
</svg>
|
|
162
166
|
</button>
|
|
163
|
-
<!-- Voice input parked.
|
|
164
167
|
<button
|
|
165
|
-
v-if="
|
|
168
|
+
v-if="inputMode === 'voice'"
|
|
166
169
|
type="button"
|
|
167
170
|
class="lares-composer__icon"
|
|
168
|
-
data-kind="
|
|
169
|
-
:
|
|
170
|
-
:
|
|
171
|
-
|
|
172
|
-
@click="$emit('voice')"
|
|
171
|
+
data-kind="keyboard"
|
|
172
|
+
:disabled="voiceBusy"
|
|
173
|
+
:aria-label="t('composer.keyboard')"
|
|
174
|
+
@click="setMode('text')"
|
|
173
175
|
>
|
|
174
|
-
<
|
|
175
|
-
|
|
176
|
-
<
|
|
177
|
-
</svg>
|
|
178
|
-
<svg v-else class="lares-composer__wave" viewBox="0 0 24 24" aria-hidden="true">
|
|
179
|
-
<path d="M6.5 9v6" />
|
|
180
|
-
<path d="M12 4.5v15" />
|
|
181
|
-
<path d="M17.5 9v6" />
|
|
176
|
+
<svg viewBox="0 0 24 24" aria-hidden="true">
|
|
177
|
+
<rect x="3.5" y="6" width="17" height="12" rx="2" />
|
|
178
|
+
<path d="M7 10h2M11 10h2M15 10h2M8 14h8" />
|
|
182
179
|
</svg>
|
|
183
180
|
</button>
|
|
184
|
-
-->
|
|
185
181
|
</div>
|
|
186
182
|
</div>
|
|
187
183
|
</div>
|
|
188
|
-
|
|
184
|
+
<p v-if="voiceError && voicePhase === 'error'" class="lares-composer__hint" data-status="error">{{ voiceError }}</p>
|
|
189
185
|
<p v-for="item in failures" :key="item.id" class="lares-composer__hint" data-status="error">
|
|
190
186
|
{{ t("upload.failed", { name: item.name, reason: t(`error.${item.code}`) }) }}
|
|
191
187
|
</p>
|
|
@@ -204,18 +200,12 @@ import {
|
|
|
204
200
|
} from "./composer-tokens.js";
|
|
205
201
|
import { draftImageStatus } from "@olares/lares-core/files/draft-images";
|
|
206
202
|
|
|
207
|
-
const HOLD_MS = 240;
|
|
208
|
-
|
|
209
203
|
export default {
|
|
210
204
|
name: "LaresComposer",
|
|
211
205
|
props: {
|
|
212
206
|
draft: { type: String, default: "" },
|
|
213
207
|
sending: { type: Boolean, default: false },
|
|
214
208
|
canSend: { type: Boolean, default: false },
|
|
215
|
-
modelLabel: { type: String, default: "" },
|
|
216
|
-
modelBusy: { type: Boolean, default: false },
|
|
217
|
-
effortLabel: { type: String, default: "" },
|
|
218
|
-
effortDisabled: { type: Boolean, default: false },
|
|
219
209
|
attachPending: { type: Boolean, default: false },
|
|
220
210
|
attachDisabled: { type: Boolean, default: false },
|
|
221
211
|
voicePhase: { type: String, default: "idle" },
|
|
@@ -229,16 +219,16 @@ export default {
|
|
|
229
219
|
commands: { type: Array, default: null },
|
|
230
220
|
commandsError: { type: String, default: "" },
|
|
231
221
|
hero: { type: Boolean, default: false },
|
|
222
|
+
inputMode: { type: String, default: "text" },
|
|
232
223
|
t: { type: Function, required: true },
|
|
233
224
|
},
|
|
234
225
|
emits: [
|
|
235
|
-
"update:draft", "
|
|
226
|
+
"update:draft", "update:inputMode", "send", "files", "voice", "hold-start", "hold-end",
|
|
236
227
|
"open-commands", "open-references", "pick-command", "remove-image",
|
|
237
228
|
],
|
|
238
229
|
data() {
|
|
239
230
|
return {
|
|
240
231
|
holding: false,
|
|
241
|
-
holdTimer: 0,
|
|
242
232
|
commandsOpen: false,
|
|
243
233
|
commandTyped: false,
|
|
244
234
|
commandIndex: 0,
|
|
@@ -249,17 +239,20 @@ export default {
|
|
|
249
239
|
};
|
|
250
240
|
},
|
|
251
241
|
computed: {
|
|
252
|
-
showSend() {
|
|
253
|
-
return Boolean(this.draft.trim()) && this.voicePhase !== "recording" && !this.holding;
|
|
254
|
-
},
|
|
255
242
|
elapsed() {
|
|
256
243
|
return formatElapsed(this.voiceElapsed);
|
|
257
244
|
},
|
|
258
|
-
|
|
259
|
-
|
|
245
|
+
talkLabel() {
|
|
246
|
+
if (this.voicePhase === "preparing") return this.t("composer.opening");
|
|
247
|
+
if (this.voicePhase === "recording") return `${this.t("composer.hold")} · ${this.elapsed}`;
|
|
248
|
+
if (this.voicePhase === "transcribing") return this.t("mic.transcribing");
|
|
249
|
+
if (this.holding) return this.t("composer.hold");
|
|
250
|
+
return this.t("composer.holdToTalk");
|
|
260
251
|
},
|
|
261
|
-
|
|
262
|
-
return this.
|
|
252
|
+
voiceBusy() {
|
|
253
|
+
return this.voicePhase === "preparing"
|
|
254
|
+
|| this.voicePhase === "recording"
|
|
255
|
+
|| this.voicePhase === "transcribing";
|
|
263
256
|
},
|
|
264
257
|
attachLabel() {
|
|
265
258
|
return this.attachPending ? this.t("button.uploading", { count: 1 }) : this.t("composer.attach");
|
|
@@ -269,14 +262,18 @@ export default {
|
|
|
269
262
|
return this.t("chat.placeholder");
|
|
270
263
|
},
|
|
271
264
|
voiceLabel() {
|
|
272
|
-
if (this.voiceError) return this.voiceError;
|
|
273
|
-
if (this.voicePhase === "
|
|
265
|
+
if (this.voicePhase === "error" && this.voiceError) return this.voiceError;
|
|
266
|
+
if (this.voicePhase === "preparing") return this.t("composer.opening");
|
|
267
|
+
if (this.voicePhase === "recording") return this.t("composer.hold");
|
|
274
268
|
if (this.voicePhase === "transcribing") return this.t("mic.transcribing");
|
|
275
269
|
return this.t("composer.voice");
|
|
276
270
|
},
|
|
277
271
|
voiceBlocked() {
|
|
278
272
|
return this.voicePhase === "transcribing" || this.sending;
|
|
279
273
|
},
|
|
274
|
+
expanded() {
|
|
275
|
+
return this.inputMode === "text" && (this.draft.trim().length > 0 || this.draftImages.length > 0);
|
|
276
|
+
},
|
|
280
277
|
referenceMenuRows() {
|
|
281
278
|
return referenceRows(this.references, this.t);
|
|
282
279
|
},
|
|
@@ -288,8 +285,9 @@ export default {
|
|
|
288
285
|
},
|
|
289
286
|
},
|
|
290
287
|
watch: {
|
|
291
|
-
draft() {
|
|
288
|
+
draft(value) {
|
|
292
289
|
this.autosize();
|
|
290
|
+
if (value && this.inputMode === "voice" && !this.voiceBusy) this.setMode("text");
|
|
293
291
|
},
|
|
294
292
|
overlayPointerActive(active) {
|
|
295
293
|
if (active) window.addEventListener("pointerdown", this.onTokenPointer, true);
|
|
@@ -385,6 +383,18 @@ export default {
|
|
|
385
383
|
imageStatus(image) {
|
|
386
384
|
return draftImageStatus(image);
|
|
387
385
|
},
|
|
386
|
+
setMode(mode) {
|
|
387
|
+
if (mode === this.inputMode) return;
|
|
388
|
+
if (mode === "text" && this.voiceBusy) return;
|
|
389
|
+
if (mode === "voice") {
|
|
390
|
+
this.closeReferences();
|
|
391
|
+
this.commandsOpen = false;
|
|
392
|
+
this.commandTyped = false;
|
|
393
|
+
this.$refs.input?.blur();
|
|
394
|
+
}
|
|
395
|
+
this.$emit("update:inputMode", mode);
|
|
396
|
+
if (mode === "text") this.$nextTick(() => this.focus());
|
|
397
|
+
},
|
|
388
398
|
onSend() {
|
|
389
399
|
if (this.referenceOpen || this.commandsOpen) return;
|
|
390
400
|
if (this.canSend) this.$emit("send");
|
|
@@ -432,40 +442,59 @@ export default {
|
|
|
432
442
|
event.preventDefault();
|
|
433
443
|
this.onSend();
|
|
434
444
|
},
|
|
435
|
-
canHold(event) {
|
|
436
|
-
// Voice input parked (hold-to-record).
|
|
437
|
-
return false;
|
|
438
|
-
if (this.draft.trim() || this.sending || this.voiceBlocked) return false;
|
|
439
|
-
if (event.pointerType === "mouse") return false;
|
|
440
|
-
return true;
|
|
441
|
-
},
|
|
442
445
|
onContextMenu(event) {
|
|
443
446
|
if (typeof window !== "undefined" && window.matchMedia?.("(pointer: coarse)").matches) {
|
|
444
447
|
event.preventDefault();
|
|
445
448
|
}
|
|
446
449
|
},
|
|
447
|
-
|
|
448
|
-
if (
|
|
450
|
+
onVoiceDown(event) {
|
|
451
|
+
if (event.pointerType === "touch") return;
|
|
452
|
+
if (event.button > 0 || this.voiceBlocked || this.holding) return;
|
|
453
|
+
event.preventDefault();
|
|
449
454
|
event.currentTarget.setPointerCapture?.(event.pointerId);
|
|
450
|
-
this.
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
},
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
this.
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
if (this.
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
455
|
+
this.beginHold("mouse");
|
|
456
|
+
},
|
|
457
|
+
onVoiceTouchStart() {
|
|
458
|
+
if (this.voiceBlocked || this.holdKind === "touch") return;
|
|
459
|
+
this.beginHold("touch");
|
|
460
|
+
},
|
|
461
|
+
beginHold(kind) {
|
|
462
|
+
const starting = !this.holding;
|
|
463
|
+
this.detachHold();
|
|
464
|
+
this.holding = true;
|
|
465
|
+
this.holdKind = kind;
|
|
466
|
+
if (starting) this.$refs.input?.blur();
|
|
467
|
+
const end = (event) => {
|
|
468
|
+
if (kind === "touch" && event.type.startsWith("pointer")) return;
|
|
469
|
+
if (kind === "mouse" && event.type.startsWith("touch")) return;
|
|
470
|
+
this.detachHold();
|
|
471
|
+
if (!this.holding) return;
|
|
466
472
|
this.holding = false;
|
|
467
|
-
|
|
473
|
+
this.holdKind = "";
|
|
474
|
+
this.$emit("hold-end", { via: event.type });
|
|
475
|
+
};
|
|
476
|
+
this.holdEnd = end;
|
|
477
|
+
if (kind === "touch") {
|
|
478
|
+
window.addEventListener("touchend", end);
|
|
479
|
+
window.addEventListener("touchcancel", end);
|
|
480
|
+
} else {
|
|
481
|
+
window.addEventListener("pointerup", end, true);
|
|
482
|
+
window.addEventListener("pointercancel", end, true);
|
|
468
483
|
}
|
|
484
|
+
if (starting) this.$emit("hold-start", { via: kind });
|
|
485
|
+
},
|
|
486
|
+
detachHold() {
|
|
487
|
+
if (!this.holdEnd) return;
|
|
488
|
+
window.removeEventListener("touchend", this.holdEnd);
|
|
489
|
+
window.removeEventListener("touchcancel", this.holdEnd);
|
|
490
|
+
window.removeEventListener("pointerup", this.holdEnd, true);
|
|
491
|
+
window.removeEventListener("pointercancel", this.holdEnd, true);
|
|
492
|
+
this.holdEnd = null;
|
|
493
|
+
},
|
|
494
|
+
clearHold() {
|
|
495
|
+
this.detachHold();
|
|
496
|
+
this.holding = false;
|
|
497
|
+
this.holdKind = "";
|
|
469
498
|
},
|
|
470
499
|
pickFiles() {
|
|
471
500
|
this.$refs.picker?.click();
|
|
@@ -507,11 +536,12 @@ export default {
|
|
|
507
536
|
position: relative;
|
|
508
537
|
display: flex;
|
|
509
538
|
flex-direction: column;
|
|
510
|
-
gap:
|
|
511
|
-
border: 1px solid var(--q-
|
|
512
|
-
border-radius:
|
|
513
|
-
padding:
|
|
539
|
+
gap: 8px;
|
|
540
|
+
border: 1px solid var(--q-separator);
|
|
541
|
+
border-radius: 999px;
|
|
542
|
+
padding: 10px 14px;
|
|
514
543
|
background: var(--q-background-1);
|
|
544
|
+
box-shadow: 0 1px 3px rgb(0 0 0 / 6%);
|
|
515
545
|
}
|
|
516
546
|
|
|
517
547
|
.lares-composer__menu {
|
|
@@ -620,22 +650,14 @@ export default {
|
|
|
620
650
|
white-space: nowrap;
|
|
621
651
|
}
|
|
622
652
|
|
|
623
|
-
.lares-composer__card[data-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
padding: 10px 14px 8px;
|
|
627
|
-
background: var(--q-background-2);
|
|
628
|
-
}
|
|
629
|
-
|
|
630
|
-
.lares-composer__card[data-hero="true"] .lares-composer__input {
|
|
631
|
-
min-height: 44px;
|
|
632
|
-
padding: 0;
|
|
633
|
-
font-size: 16px;
|
|
634
|
-
line-height: 1.45;
|
|
653
|
+
.lares-composer__card[data-expanded="true"] {
|
|
654
|
+
border-radius: 24px;
|
|
655
|
+
padding: 16px 14px 12px;
|
|
635
656
|
}
|
|
636
657
|
|
|
637
|
-
.lares-composer__card[data-
|
|
638
|
-
|
|
658
|
+
.lares-composer__card[data-holding="true"] {
|
|
659
|
+
border-color: var(--q-blue-default);
|
|
660
|
+
background: var(--q-blue-alpha);
|
|
639
661
|
}
|
|
640
662
|
|
|
641
663
|
.lares-composer__attachments {
|
|
@@ -712,90 +734,99 @@ export default {
|
|
|
712
734
|
stroke-linecap: round;
|
|
713
735
|
}
|
|
714
736
|
|
|
715
|
-
.lares-
|
|
737
|
+
.lares-composer__line {
|
|
738
|
+
display: flex;
|
|
716
739
|
width: 100%;
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
740
|
+
align-items: center;
|
|
741
|
+
gap: 12px;
|
|
742
|
+
}
|
|
743
|
+
|
|
744
|
+
.lares-composer__line[data-expanded="true"] {
|
|
745
|
+
flex-wrap: wrap;
|
|
746
|
+
row-gap: 14px;
|
|
747
|
+
}
|
|
748
|
+
|
|
749
|
+
.lares-composer__line[data-expanded="true"] .lares-composer__input {
|
|
750
|
+
order: -1;
|
|
751
|
+
flex: 1 0 100%;
|
|
752
|
+
min-height: 26px;
|
|
753
|
+
padding: 0;
|
|
754
|
+
}
|
|
755
|
+
|
|
756
|
+
.lares-composer__input,
|
|
757
|
+
.lares-composer__talk {
|
|
758
|
+
min-width: 0;
|
|
759
|
+
min-height: 36px;
|
|
760
|
+
flex: 1;
|
|
721
761
|
border: 0;
|
|
722
|
-
padding: 2px 2px 4px;
|
|
723
762
|
background: transparent;
|
|
724
|
-
|
|
763
|
+
font-size: 16px;
|
|
764
|
+
line-height: 22px;
|
|
725
765
|
}
|
|
726
766
|
|
|
727
|
-
.lares-composer__input
|
|
728
|
-
|
|
767
|
+
.lares-composer__input {
|
|
768
|
+
max-height: 176px;
|
|
769
|
+
resize: none;
|
|
770
|
+
overflow-y: auto;
|
|
771
|
+
padding: 7px 0;
|
|
772
|
+
color: var(--q-ink-1);
|
|
729
773
|
}
|
|
730
774
|
|
|
731
|
-
.lares-
|
|
732
|
-
|
|
733
|
-
color: var(--q-blue-default);
|
|
734
|
-
font-size: 15px;
|
|
735
|
-
line-height: 20px;
|
|
775
|
+
.lares-composer__input::placeholder {
|
|
776
|
+
color: var(--q-ink-3);
|
|
736
777
|
}
|
|
737
778
|
|
|
738
|
-
.lares-
|
|
739
|
-
|
|
740
|
-
align-items: center;
|
|
741
|
-
gap: 8px;
|
|
742
|
-
min-height: 32px;
|
|
779
|
+
.lares-composer__input:focus {
|
|
780
|
+
outline: none;
|
|
743
781
|
}
|
|
744
782
|
|
|
745
|
-
.lares-
|
|
783
|
+
.lares-composer__talk {
|
|
746
784
|
display: flex;
|
|
747
785
|
align-items: center;
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
786
|
+
justify-content: center;
|
|
787
|
+
padding: 9px 4px;
|
|
788
|
+
color: var(--q-ink-1);
|
|
789
|
+
font: inherit;
|
|
790
|
+
font-size: 16px;
|
|
791
|
+
font-weight: 600;
|
|
792
|
+
line-height: 22px;
|
|
793
|
+
touch-action: none;
|
|
794
|
+
user-select: none;
|
|
795
|
+
-webkit-user-select: none;
|
|
796
|
+
-webkit-touch-callout: none;
|
|
751
797
|
}
|
|
752
798
|
|
|
753
|
-
.lares-
|
|
754
|
-
|
|
755
|
-
align-items: center;
|
|
756
|
-
gap: 6px;
|
|
757
|
-
box-sizing: border-box;
|
|
758
|
-
width: 98px;
|
|
759
|
-
flex: 0 0 98px;
|
|
760
|
-
height: 32px;
|
|
761
|
-
border: 0;
|
|
762
|
-
border-radius: 999px;
|
|
763
|
-
padding: 0 10px 0 8px;
|
|
764
|
-
background: var(--q-background-3);
|
|
765
|
-
color: var(--q-ink-2);
|
|
766
|
-
font-size: 15px;
|
|
767
|
-
font-weight: 500;
|
|
768
|
-
line-height: 18px;
|
|
769
|
-
white-space: nowrap;
|
|
799
|
+
.lares-composer__talk > * {
|
|
800
|
+
pointer-events: none;
|
|
770
801
|
}
|
|
771
802
|
|
|
772
|
-
.lares-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
text-overflow: ellipsis;
|
|
803
|
+
.lares-composer__talk[data-phase="recording"],
|
|
804
|
+
.lares-composer__card[data-holding="true"] .lares-composer__talk {
|
|
805
|
+
color: var(--q-blue-default);
|
|
776
806
|
}
|
|
777
807
|
|
|
778
|
-
.lares-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
stroke: currentColor;
|
|
784
|
-
stroke-width: 1.8;
|
|
785
|
-
stroke-linecap: round;
|
|
786
|
-
stroke-linejoin: round;
|
|
808
|
+
.lares-composer__talk-status {
|
|
809
|
+
display: inline-flex;
|
|
810
|
+
align-items: center;
|
|
811
|
+
justify-content: center;
|
|
812
|
+
gap: 6px;
|
|
787
813
|
}
|
|
788
814
|
|
|
789
|
-
.lares-
|
|
790
|
-
|
|
815
|
+
.lares-composer__talk .lares-composer__spin {
|
|
816
|
+
width: 16px;
|
|
817
|
+
height: 16px;
|
|
818
|
+
flex: none;
|
|
791
819
|
}
|
|
792
820
|
|
|
793
821
|
.lares-composer__tools {
|
|
794
822
|
display: flex;
|
|
795
823
|
align-items: center;
|
|
796
|
-
gap: 16px;
|
|
797
|
-
margin-left: auto;
|
|
798
824
|
flex-shrink: 0;
|
|
825
|
+
gap: 12px;
|
|
826
|
+
}
|
|
827
|
+
|
|
828
|
+
.lares-composer__line[data-expanded="true"] .lares-composer__tools {
|
|
829
|
+
margin-left: auto;
|
|
799
830
|
}
|
|
800
831
|
|
|
801
832
|
.lares-composer__picker {
|
|
@@ -806,9 +837,10 @@ export default {
|
|
|
806
837
|
display: inline-flex;
|
|
807
838
|
align-items: center;
|
|
808
839
|
justify-content: center;
|
|
809
|
-
width:
|
|
810
|
-
height:
|
|
811
|
-
|
|
840
|
+
width: 36px;
|
|
841
|
+
height: 36px;
|
|
842
|
+
flex: 0 0 36px;
|
|
843
|
+
border: 1px solid var(--q-ink-3);
|
|
812
844
|
border-radius: 999px;
|
|
813
845
|
padding: 0;
|
|
814
846
|
background: transparent;
|
|
@@ -819,23 +851,34 @@ export default {
|
|
|
819
851
|
background: var(--q-btn-bg-pressed);
|
|
820
852
|
}
|
|
821
853
|
|
|
822
|
-
.lares-composer__icon[data-kind="
|
|
823
|
-
.lares-composer__icon[data-kind="voice"]
|
|
854
|
+
.lares-composer__icon[data-kind="attach"],
|
|
855
|
+
.lares-composer__icon[data-kind="voice"],
|
|
856
|
+
.lares-composer__icon[data-kind="keyboard"] {
|
|
824
857
|
border-color: transparent;
|
|
825
|
-
|
|
858
|
+
background: var(--q-background-3);
|
|
859
|
+
color: var(--q-ink-1);
|
|
826
860
|
}
|
|
827
861
|
|
|
828
|
-
.lares-composer__icon[data-kind="
|
|
829
|
-
|
|
862
|
+
.lares-composer__icon[data-kind="attach"]:active,
|
|
863
|
+
.lares-composer__icon[data-kind="voice"]:active,
|
|
864
|
+
.lares-composer__icon[data-kind="keyboard"]:active {
|
|
865
|
+
background: var(--q-background-selected);
|
|
830
866
|
}
|
|
831
867
|
|
|
832
|
-
.lares-composer__icon[data-kind="
|
|
868
|
+
.lares-composer__icon[data-kind="send"] {
|
|
869
|
+
border-color: transparent;
|
|
833
870
|
background: var(--q-ink-1);
|
|
871
|
+
color: var(--q-background-1);
|
|
872
|
+
}
|
|
873
|
+
|
|
874
|
+
.lares-composer__icon[data-kind="send"]:disabled {
|
|
875
|
+
opacity: 0.4;
|
|
834
876
|
}
|
|
835
877
|
|
|
836
878
|
.lares-composer__icon svg {
|
|
837
|
-
width:
|
|
838
|
-
height:
|
|
879
|
+
width: 22px;
|
|
880
|
+
height: 22px;
|
|
881
|
+
flex: none;
|
|
839
882
|
fill: none;
|
|
840
883
|
stroke: currentColor;
|
|
841
884
|
stroke-width: 2;
|
|
@@ -843,17 +886,6 @@ export default {
|
|
|
843
886
|
stroke-linejoin: round;
|
|
844
887
|
}
|
|
845
888
|
|
|
846
|
-
.lares-composer__icon svg.lares-composer__wave {
|
|
847
|
-
width: 18px;
|
|
848
|
-
height: 18px;
|
|
849
|
-
stroke-width: 2.75;
|
|
850
|
-
}
|
|
851
|
-
|
|
852
|
-
.lares-composer__live {
|
|
853
|
-
font-size: 12px;
|
|
854
|
-
font-variant-numeric: tabular-nums;
|
|
855
|
-
}
|
|
856
|
-
|
|
857
889
|
.lares-composer__spin {
|
|
858
890
|
animation: lares-composer-spin 0.8s linear infinite;
|
|
859
891
|
}
|