@olares/lares-mobile 0.15.24 → 0.15.26
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 +18 -4
- package/src/chat/ChatBar.vue +4 -0
- package/src/chat/Transcript.vue +11 -12
- package/src/chat/VoiceInput.vue +0 -5
- package/src/desktop/DesktopQueue.vue +1 -3
- package/src/desktop/DesktopShell.vue +1 -0
- package/src/host.js +2 -0
- package/src/mobile/MobileShell.vue +27 -1
- package/src/motion.css +16 -0
- package/src/settings/AgentSettings.vue +206 -36
- package/src/settings/Select.vue +7 -1
- package/src/settings/Sheet.vue +19 -0
- package/src/settings/TtsSettings.vue +260 -39
- package/src/settings/VoiceKeys.vue +267 -0
- package/src/settings/VoicePreferences.vue +80 -32
|
@@ -44,36 +44,107 @@
|
|
|
44
44
|
<section class="lares-agent__group">
|
|
45
45
|
<h2>{{ tVoice("settings.title") }}</h2>
|
|
46
46
|
<div class="lares-agent__list">
|
|
47
|
-
<
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
47
|
+
<template v-if="isDesktop">
|
|
48
|
+
<label class="lares-agent__field">
|
|
49
|
+
<span>{{ tVoice('settings.stt.model') }}</span>
|
|
50
|
+
<LaresSelect
|
|
51
|
+
:value="voiceModelId"
|
|
52
|
+
:sections="voiceModelSections"
|
|
53
|
+
:disabled="busy || !voice"
|
|
54
|
+
@select="chooseVoiceModel"
|
|
55
|
+
/>
|
|
56
|
+
</label>
|
|
57
|
+
<label class="lares-agent__field">
|
|
58
|
+
<span>{{ tVoice('settings.language.title') }}</span>
|
|
59
|
+
<LaresSelect
|
|
60
|
+
:value="voiceLangId"
|
|
61
|
+
:sections="voiceLanguageSections"
|
|
62
|
+
:disabled="busy || !voice"
|
|
63
|
+
@select="chooseVoiceLanguage"
|
|
64
|
+
/>
|
|
65
|
+
</label>
|
|
66
|
+
</template>
|
|
67
|
+
<template v-else>
|
|
68
|
+
<LaresSettingRow
|
|
69
|
+
:label="tVoice('settings.stt.model')"
|
|
70
|
+
:value="voiceModelLabel"
|
|
71
|
+
chevron
|
|
72
|
+
boxed
|
|
73
|
+
:disabled="Boolean(pending)"
|
|
74
|
+
@click="openSheet('voiceModel')"
|
|
75
|
+
/>
|
|
76
|
+
<LaresSettingRow
|
|
77
|
+
:label="tVoice('settings.language.title')"
|
|
78
|
+
:value="voiceLangLabel"
|
|
79
|
+
chevron
|
|
80
|
+
boxed
|
|
81
|
+
:disabled="Boolean(pending)"
|
|
82
|
+
@click="openSheet('voiceLang')"
|
|
83
|
+
/>
|
|
84
|
+
</template>
|
|
63
85
|
</div>
|
|
64
86
|
<VoicePreferences :key="hostKey" ref="voicePreferences" :settings="settings" :tts-fetch="ttsFetch" :snapshot="voice" :device="device" :t="tVoice" :bind-before-leave="bindBeforeLeave" @change="voice = $event" />
|
|
65
|
-
<
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
<
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
87
|
+
<h3>{{ tVoice("settings.conversation") }}</h3>
|
|
88
|
+
<div class="lares-agent__list">
|
|
89
|
+
<template v-if="isDesktop">
|
|
90
|
+
<label class="lares-agent__field">
|
|
91
|
+
<span>{{ tVoice('settings.mobileMode') }}</span>
|
|
92
|
+
<LaresSelect
|
|
93
|
+
:value="voice?.config?.mobileMode || 'continuous'"
|
|
94
|
+
:sections="mobileModeSections"
|
|
95
|
+
:disabled="busy || !voice"
|
|
96
|
+
@select="(item) => patchVoice('mobileMode', item.id)"
|
|
97
|
+
/>
|
|
98
|
+
</label>
|
|
99
|
+
<label class="lares-agent__field">
|
|
100
|
+
<span>{{ tVoice('settings.device') }}</span>
|
|
101
|
+
<LaresSelect
|
|
102
|
+
:value="voice?.config?.device || 'auto'"
|
|
103
|
+
:sections="deviceSections"
|
|
104
|
+
:disabled="busy || !voice"
|
|
105
|
+
@select="(item) => patchVoice('device', item.id)"
|
|
106
|
+
/>
|
|
107
|
+
</label>
|
|
108
|
+
<label class="lares-agent__field">
|
|
109
|
+
<span>{{ tVoice('settings.mode.title') }}</span>
|
|
110
|
+
<LaresSelect
|
|
111
|
+
:value="voice?.config?.streaming ? 'streaming' : 'turns'"
|
|
112
|
+
:sections="readingSections"
|
|
113
|
+
:disabled="busy || !voice || !reading"
|
|
114
|
+
@select="(item) => chooseReading(item.id)"
|
|
115
|
+
/>
|
|
116
|
+
</label>
|
|
117
|
+
</template>
|
|
118
|
+
<template v-else>
|
|
119
|
+
<LaresSettingRow
|
|
120
|
+
:label="tVoice('settings.mobileMode')"
|
|
121
|
+
:value="voiceChoiceLabel('mobileMode')"
|
|
122
|
+
chevron
|
|
123
|
+
boxed
|
|
124
|
+
:disabled="Boolean(pending) || !voice"
|
|
125
|
+
@click="openSheet('voiceMobileMode')"
|
|
126
|
+
/>
|
|
127
|
+
<LaresSettingRow
|
|
128
|
+
:label="tVoice('settings.device')"
|
|
129
|
+
:value="voiceChoiceLabel('device')"
|
|
130
|
+
chevron
|
|
131
|
+
boxed
|
|
132
|
+
:disabled="Boolean(pending) || !voice"
|
|
133
|
+
@click="openSheet('voiceDevice')"
|
|
134
|
+
/>
|
|
135
|
+
<LaresSettingRow
|
|
136
|
+
:label="tVoice('settings.mode.title')"
|
|
137
|
+
:value="voiceChoiceLabel('reading')"
|
|
138
|
+
chevron
|
|
139
|
+
boxed
|
|
140
|
+
:disabled="Boolean(pending) || !voice || !reading"
|
|
141
|
+
@click="openSheet('voiceReading')"
|
|
142
|
+
/>
|
|
143
|
+
</template>
|
|
144
|
+
</div>
|
|
145
|
+
<p class="lares-agent__hint">{{ readingHint }}</p>
|
|
76
146
|
<p v-if="voiceError" class="lares-agent__hint" data-status="error">{{ voiceError }}</p>
|
|
147
|
+
<VoiceKeys :key="`keys-${hostKey}`" :client="voiceKeys" :t="tVoice" />
|
|
77
148
|
</section>
|
|
78
149
|
<section class="lares-agent__group">
|
|
79
150
|
<h2>{{ tSearch("settings.title") }}</h2>
|
|
@@ -105,7 +176,7 @@
|
|
|
105
176
|
:key="item.id"
|
|
106
177
|
:label="item.label"
|
|
107
178
|
:checked="item.id === sheetCurrent"
|
|
108
|
-
:disabled="busy"
|
|
179
|
+
:disabled="busy || item.disabled"
|
|
109
180
|
@click="pick(item)"
|
|
110
181
|
/>
|
|
111
182
|
</template>
|
|
@@ -138,6 +209,7 @@ import { adoptHost } from "../runtime.js";
|
|
|
138
209
|
import { createT } from "../i18n.js";
|
|
139
210
|
import { chatDevice, DEVICE_DESKTOP } from "../layout.js";
|
|
140
211
|
import VoicePreferences from "./VoicePreferences.vue";
|
|
212
|
+
import VoiceKeys from "./VoiceKeys.vue";
|
|
141
213
|
import LaresSettingRow from "./SettingRow.vue";
|
|
142
214
|
import LaresSheet from "./Sheet.vue";
|
|
143
215
|
import LaresSelect from "./Select.vue";
|
|
@@ -154,7 +226,7 @@ function itemLabel(items, id) {
|
|
|
154
226
|
|
|
155
227
|
export default {
|
|
156
228
|
name: "LaresAgentSettings",
|
|
157
|
-
components: { VoicePreferences, LaresSettingRow, LaresSheet, LaresSelect },
|
|
229
|
+
components: { VoicePreferences, VoiceKeys, LaresSettingRow, LaresSheet, LaresSelect },
|
|
158
230
|
expose: ["reload", "beforeLeave"],
|
|
159
231
|
props: {
|
|
160
232
|
locale: { type: String, default: "en" },
|
|
@@ -180,6 +252,7 @@ export default {
|
|
|
180
252
|
voiceError: "",
|
|
181
253
|
searchError: "",
|
|
182
254
|
conversationError: "",
|
|
255
|
+
reading: null,
|
|
183
256
|
};
|
|
184
257
|
},
|
|
185
258
|
computed: {
|
|
@@ -205,6 +278,7 @@ export default {
|
|
|
205
278
|
return hostSessionKey(this.ports);
|
|
206
279
|
},
|
|
207
280
|
ttsFetch() { return createHostClient(this.ports).ttsFetch; },
|
|
281
|
+
voiceKeys() { return createHostClient(this.ports).voiceKeys; },
|
|
208
282
|
settings() {
|
|
209
283
|
return createHostClient(this.ports).settings;
|
|
210
284
|
},
|
|
@@ -244,13 +318,31 @@ export default {
|
|
|
244
318
|
}
|
|
245
319
|
return this.models.default?.model || "—";
|
|
246
320
|
},
|
|
321
|
+
voiceModelId() {
|
|
322
|
+
return voiceMenuValue(this.voice?.config?.model);
|
|
323
|
+
},
|
|
324
|
+
voiceLangId() {
|
|
325
|
+
return voiceMenuValue(this.voice?.config?.language);
|
|
326
|
+
},
|
|
327
|
+
voiceModelSections() {
|
|
328
|
+
return [{ items: this.voiceModels }];
|
|
329
|
+
},
|
|
330
|
+
voiceLanguageSections() {
|
|
331
|
+
return [{ items: this.voiceLanguages }];
|
|
332
|
+
},
|
|
247
333
|
voiceModelLabel() {
|
|
248
334
|
if (!this.voice) return "—";
|
|
249
|
-
return itemLabel(this.voiceModels,
|
|
335
|
+
return itemLabel(this.voiceModels, this.voiceModelId);
|
|
250
336
|
},
|
|
251
337
|
voiceLangLabel() {
|
|
252
338
|
if (!this.voice) return "—";
|
|
253
|
-
return itemLabel(this.voiceLanguages,
|
|
339
|
+
return itemLabel(this.voiceLanguages, this.voiceLangId);
|
|
340
|
+
},
|
|
341
|
+
readingHint() {
|
|
342
|
+
if (this.reading && !this.reading.allowed) return this.tVoice("settings.mode.hint");
|
|
343
|
+
const type = this.reading?.gpu?.type;
|
|
344
|
+
if (type) return this.tVoice("settings.mode.gpu", { type: this.tVoice(`settings.gpu.${type}`) });
|
|
345
|
+
return this.tVoice("settings.mode.hint");
|
|
254
346
|
},
|
|
255
347
|
searchMenuId() {
|
|
256
348
|
return searchMenuValue(this.search);
|
|
@@ -280,10 +372,27 @@ export default {
|
|
|
280
372
|
],
|
|
281
373
|
}];
|
|
282
374
|
},
|
|
375
|
+
mobileModeSections() {
|
|
376
|
+
return [{ items: ["single", "continuous"].map((id) => ({ id, label: this.tVoice(`settings.mode.${id}`) })) }];
|
|
377
|
+
},
|
|
378
|
+
deviceSections() {
|
|
379
|
+
return [{ items: ["auto", "device", "headset"].map((id) => ({ id, label: this.tVoice(`settings.device.${id}`) })) }];
|
|
380
|
+
},
|
|
381
|
+
readingSections() {
|
|
382
|
+
return [{
|
|
383
|
+
items: [
|
|
384
|
+
{ id: "turns", label: this.tVoice("settings.mode.turns") },
|
|
385
|
+
{ id: "streaming", label: this.tVoice("settings.mode.streaming"), disabled: !this.reading?.allowed },
|
|
386
|
+
],
|
|
387
|
+
}];
|
|
388
|
+
},
|
|
283
389
|
sheetTitle() {
|
|
284
390
|
if (this.panel === "model") return this.tModel("settings.title");
|
|
285
391
|
if (this.panel === "voiceModel") return this.tVoice("settings.stt.model");
|
|
286
392
|
if (this.panel === "voiceLang") return this.tVoice("settings.language.title");
|
|
393
|
+
if (this.panel === "voiceMobileMode") return this.tVoice("settings.mobileMode");
|
|
394
|
+
if (this.panel === "voiceDevice") return this.tVoice("settings.device");
|
|
395
|
+
if (this.panel === "voiceReading") return this.tVoice("settings.mode.title");
|
|
287
396
|
if (this.panel === "search") return this.tSearch("settings.default");
|
|
288
397
|
return "";
|
|
289
398
|
},
|
|
@@ -298,6 +407,9 @@ export default {
|
|
|
298
407
|
if (this.panel === "voiceLang") {
|
|
299
408
|
return [{ items: this.voiceLanguages.map((item) => ({ id: item.id, label: item.label })) }];
|
|
300
409
|
}
|
|
410
|
+
if (this.panel === "voiceMobileMode") return this.mobileModeSections;
|
|
411
|
+
if (this.panel === "voiceDevice") return this.deviceSections;
|
|
412
|
+
if (this.panel === "voiceReading") return this.readingSections;
|
|
301
413
|
if (this.panel === "search") return this.searchSelectSections;
|
|
302
414
|
return [];
|
|
303
415
|
},
|
|
@@ -357,7 +469,16 @@ export default {
|
|
|
357
469
|
if (!ready) return;
|
|
358
470
|
this.panel = panel;
|
|
359
471
|
},
|
|
472
|
+
chooseVoiceModel(item) { return this.patchVoice("model", voiceValueFromMenu(item.id)); },
|
|
473
|
+
chooseVoiceLanguage(item) { return this.patchVoice("language", voiceValueFromMenu(item.id)); },
|
|
474
|
+
voiceChoiceLabel(kind) {
|
|
475
|
+
if (!this.voice) return "—";
|
|
476
|
+
if (kind === "mobileMode") return this.tVoice(`settings.mode.${this.voice.config?.mobileMode || "continuous"}`);
|
|
477
|
+
if (kind === "device") return this.tVoice(`settings.device.${this.voice.config?.device || "auto"}`);
|
|
478
|
+
return this.tVoice(`settings.mode.${this.voice.config?.streaming ? "streaming" : "turns"}`);
|
|
479
|
+
},
|
|
360
480
|
async pick(item, panel = this.panel) {
|
|
481
|
+
if (item.disabled) return;
|
|
361
482
|
if (item.id === this.sheetCurrentFor(panel)) {
|
|
362
483
|
this.panel = "";
|
|
363
484
|
return;
|
|
@@ -366,12 +487,18 @@ export default {
|
|
|
366
487
|
if (panel === "model") await this.chooseModel(item.model);
|
|
367
488
|
if (panel === "voiceModel") await this.patchVoice("model", voiceValueFromMenu(item.id));
|
|
368
489
|
if (panel === "voiceLang") await this.patchVoice("language", voiceValueFromMenu(item.id));
|
|
490
|
+
if (panel === "voiceMobileMode") await this.patchVoice("mobileMode", item.id);
|
|
491
|
+
if (panel === "voiceDevice") await this.patchVoice("device", item.id);
|
|
492
|
+
if (panel === "voiceReading") this.chooseReading(item.id);
|
|
369
493
|
if (panel === "search") await this.chooseSearch(item.id);
|
|
370
494
|
},
|
|
371
495
|
sheetCurrentFor(panel) {
|
|
372
496
|
if (panel === "model") return this.modelCurrent;
|
|
373
497
|
if (panel === "voiceModel") return voiceMenuValue(this.voice?.config?.model);
|
|
374
498
|
if (panel === "voiceLang") return voiceMenuValue(this.voice?.config?.language);
|
|
499
|
+
if (panel === "voiceMobileMode") return this.voice?.config?.mobileMode || "continuous";
|
|
500
|
+
if (panel === "voiceDevice") return this.voice?.config?.device || "auto";
|
|
501
|
+
if (panel === "voiceReading") return this.voice?.config?.streaming ? "streaming" : "turns";
|
|
375
502
|
if (panel === "search") return searchMenuValue(this.search);
|
|
376
503
|
return "";
|
|
377
504
|
},
|
|
@@ -387,7 +514,10 @@ export default {
|
|
|
387
514
|
this.voice = remembered.voice ?? this.voice;
|
|
388
515
|
this.search = remembered.search ?? this.search;
|
|
389
516
|
this.conversation = remembered.conversation ?? this.conversation;
|
|
390
|
-
if (this.models && this.voice && this.search && this.conversation)
|
|
517
|
+
if (this.models && this.voice && this.search && this.conversation) {
|
|
518
|
+
void this.loadReading();
|
|
519
|
+
return;
|
|
520
|
+
}
|
|
391
521
|
}
|
|
392
522
|
this.panel = "";
|
|
393
523
|
this.loading = true;
|
|
@@ -410,6 +540,21 @@ export default {
|
|
|
410
540
|
if (conversation.status === "fulfilled") this.conversation = conversation.value;
|
|
411
541
|
else this.conversationError = conversation.reason instanceof Error ? conversation.reason.message : String(conversation.reason);
|
|
412
542
|
this.loading = false;
|
|
543
|
+
void this.loadReading();
|
|
544
|
+
},
|
|
545
|
+
async loadReading() {
|
|
546
|
+
try {
|
|
547
|
+
this.reading = await this.settings.readingMode();
|
|
548
|
+
} catch {
|
|
549
|
+
this.reading = { streaming: false, allowed: false, gpu: null };
|
|
550
|
+
}
|
|
551
|
+
},
|
|
552
|
+
chooseReading(value) {
|
|
553
|
+
if (value === "streaming" && !this.reading?.allowed) {
|
|
554
|
+
this.voiceError = this.tVoice("error.voice_streaming_time_slice");
|
|
555
|
+
return;
|
|
556
|
+
}
|
|
557
|
+
void this.patchVoice("streaming", value === "streaming");
|
|
413
558
|
},
|
|
414
559
|
async chooseModel(model) {
|
|
415
560
|
const selection = { provider: model.provider, model: model.id };
|
|
@@ -431,8 +576,10 @@ export default {
|
|
|
431
576
|
this.voiceError = "";
|
|
432
577
|
try {
|
|
433
578
|
this.voice = await this.$refs.voicePreferences.patch({ [key]: value });
|
|
434
|
-
} catch {
|
|
435
|
-
|
|
579
|
+
} catch (err) {
|
|
580
|
+
const code = err?.code;
|
|
581
|
+
const text = code ? this.tVoice(`error.${code}`) : "";
|
|
582
|
+
this.voiceError = text && text !== `error.${code}` ? text : this.tVoice("settings.saveFailed");
|
|
436
583
|
} finally {
|
|
437
584
|
this.pending = "";
|
|
438
585
|
}
|
|
@@ -544,22 +691,45 @@ export default {
|
|
|
544
691
|
gap: 8px;
|
|
545
692
|
}
|
|
546
693
|
|
|
547
|
-
.lares-agent__group h2
|
|
694
|
+
.lares-agent__group h2,
|
|
695
|
+
.lares-agent__group h3 {
|
|
548
696
|
margin: 0;
|
|
549
|
-
font-size: 18px;
|
|
550
697
|
font-weight: 500;
|
|
698
|
+
color: var(--q-ink-1);
|
|
699
|
+
}
|
|
700
|
+
|
|
701
|
+
.lares-agent__group h2 {
|
|
702
|
+
font-size: 18px;
|
|
551
703
|
line-height: 24px;
|
|
552
704
|
}
|
|
553
705
|
|
|
706
|
+
.lares-agent__group h3 {
|
|
707
|
+
margin-top: 8px;
|
|
708
|
+
color: var(--q-ink-3);
|
|
709
|
+
font-size: 14px;
|
|
710
|
+
line-height: 18px;
|
|
711
|
+
}
|
|
712
|
+
|
|
554
713
|
.lares-agent__list {
|
|
555
714
|
display: flex;
|
|
556
715
|
flex-direction: column;
|
|
557
716
|
gap: 12px;
|
|
558
717
|
}
|
|
559
718
|
|
|
719
|
+
.lares-agent__field {
|
|
720
|
+
display: flex;
|
|
721
|
+
flex-direction: column;
|
|
722
|
+
gap: 8px;
|
|
723
|
+
min-width: 0;
|
|
724
|
+
color: var(--q-ink-1);
|
|
725
|
+
font-size: 15px;
|
|
726
|
+
line-height: 22px;
|
|
727
|
+
}
|
|
728
|
+
|
|
560
729
|
.lares-agent__hint {
|
|
561
730
|
margin: 0;
|
|
562
731
|
font-size: 15px;
|
|
732
|
+
line-height: 22px;
|
|
563
733
|
color: var(--q-ink-3);
|
|
564
734
|
}
|
|
565
735
|
|
package/src/settings/Select.vue
CHANGED
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
class="lares-select__option"
|
|
28
28
|
role="option"
|
|
29
29
|
:aria-selected="item.id === value"
|
|
30
|
-
:disabled="disabled"
|
|
30
|
+
:disabled="disabled || item.disabled"
|
|
31
31
|
@click="choose(item)"
|
|
32
32
|
>
|
|
33
33
|
<span>{{ item.label }}</span>
|
|
@@ -75,6 +75,7 @@ export default {
|
|
|
75
75
|
},
|
|
76
76
|
methods: {
|
|
77
77
|
choose(item) {
|
|
78
|
+
if (this.disabled || item.disabled) return;
|
|
78
79
|
this.open = false;
|
|
79
80
|
this.$emit("select", item);
|
|
80
81
|
},
|
|
@@ -177,6 +178,11 @@ export default {
|
|
|
177
178
|
background: var(--q-background-hover);
|
|
178
179
|
}
|
|
179
180
|
|
|
181
|
+
.lares-select__option:disabled {
|
|
182
|
+
cursor: default;
|
|
183
|
+
opacity: 0.45;
|
|
184
|
+
}
|
|
185
|
+
|
|
180
186
|
.lares-select__option[aria-selected="true"] span {
|
|
181
187
|
color: var(--q-blue-default);
|
|
182
188
|
}
|
package/src/settings/Sheet.vue
CHANGED
|
@@ -19,6 +19,9 @@
|
|
|
19
19
|
<div class="lares-sheet__body">
|
|
20
20
|
<slot />
|
|
21
21
|
</div>
|
|
22
|
+
<footer v-if="$slots.footer" class="lares-sheet__foot">
|
|
23
|
+
<slot name="footer" />
|
|
24
|
+
</footer>
|
|
22
25
|
</div>
|
|
23
26
|
</div>
|
|
24
27
|
</Teleport>
|
|
@@ -84,6 +87,11 @@ export default {
|
|
|
84
87
|
transform: translateY(0);
|
|
85
88
|
}
|
|
86
89
|
|
|
90
|
+
.lares-sheet:has(.lares-sheet__foot) .lares-sheet__panel {
|
|
91
|
+
height: 45%;
|
|
92
|
+
overflow: hidden;
|
|
93
|
+
}
|
|
94
|
+
|
|
87
95
|
.lares-sheet__head {
|
|
88
96
|
display: flex;
|
|
89
97
|
align-items: center;
|
|
@@ -129,6 +137,17 @@ export default {
|
|
|
129
137
|
-webkit-overflow-scrolling: touch;
|
|
130
138
|
}
|
|
131
139
|
|
|
140
|
+
.lares-sheet:has(.lares-sheet__foot) .lares-sheet__body {
|
|
141
|
+
flex: 1 1 auto;
|
|
142
|
+
padding-bottom: 8px;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
.lares-sheet__foot {
|
|
146
|
+
flex-shrink: 0;
|
|
147
|
+
padding: 0 0 env(safe-area-inset-bottom, 0px);
|
|
148
|
+
background: var(--q-background-1);
|
|
149
|
+
}
|
|
150
|
+
|
|
132
151
|
@media (prefers-reduced-motion: reduce) {
|
|
133
152
|
.lares-sheet__backdrop,
|
|
134
153
|
.lares-sheet__panel {
|