Skip to content

Commit 5a3814f

Browse files
committed
feat(web-ui): replace dropdown menus with checkboxes
1 parent d50611c commit 5a3814f

14 files changed

Lines changed: 351 additions & 273 deletions

File tree

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
<script setup>
2+
const model = defineModel({ required: true });
3+
const slots = defineSlots();
4+
const props = defineProps({
5+
class: {
6+
type: String,
7+
default: ""
8+
},
9+
desc: {
10+
type: String,
11+
default: null
12+
},
13+
id: {
14+
type: String,
15+
required: true
16+
},
17+
label: {
18+
type: String,
19+
default: null
20+
},
21+
localePrefix: {
22+
type: String,
23+
default: "missing-prefix"
24+
},
25+
checkedByDef: {
26+
type: Boolean,
27+
default: false
28+
},
29+
uncheckedByDef: {
30+
type: Boolean,
31+
default: false
32+
}
33+
});
34+
35+
// Add the mandatory class values
36+
const extendedClassStr = (() => {
37+
let values = props.class.split(" ");
38+
if (!values.includes("form-check")) {
39+
values.push("form-check");
40+
}
41+
return values.join(" ");
42+
})();
43+
44+
// Determine the true/false values for the checkbox
45+
const checkboxValues = (() => {
46+
const mappedValues = (() => {
47+
// Try literal values first
48+
let value = model.value;
49+
if (value === true || value === false) {
50+
return [true, false];
51+
}
52+
if (value === 1 || value === 0) {
53+
return [1, 0];
54+
}
55+
56+
// Try mapping strings next (first in the list will be used as fallback)
57+
const stringPairs = [
58+
["true", "false"],
59+
["1", "0"],
60+
["enabled", "disabled"],
61+
["enable", "disable"],
62+
["yes", "no"],
63+
["on", "off"]
64+
];
65+
66+
value = `${value}`.toLowerCase().trim();
67+
for (const pair of stringPairs) {
68+
if (value === pair[0] || value === pair[1]) {
69+
return pair;
70+
}
71+
}
72+
73+
// Return default if nothing matches
74+
console.error(`Checkbox value ${model.value} (${value}) did not match any acceptable pattern!`);
75+
return stringPairs[0];
76+
})();
77+
78+
return { truthy: mappedValues[0], falsy: mappedValues[1] };
79+
})();
80+
81+
const labelField = props.label ?? `${props.localePrefix}.${props.id}`;
82+
const descField = props.desc ?? `${props.localePrefix}.${props.id}_desc`;
83+
const showDesc = props.desc !== "" || Object.entries(slots).length > 0;
84+
const showDefValue = props.checkedByDef || props.uncheckedByDef;
85+
const defValue = props.checkedByDef === props.uncheckedByDef ? "INVALID" :
86+
props.checkedByDef ? "_common.enabled_def_cbox" : "_common.disabled_def_cbox";
87+
</script>
88+
89+
<template>
90+
<div :class="extendedClassStr">
91+
<label :for="props.id" :class="`form-check-label${showDesc ? ' mb-2' : ''}`">
92+
{{ $t(labelField) }}
93+
<div class="mt-0 form-text" v-if="showDefValue">
94+
{{ $t(defValue) }}
95+
</div>
96+
</label>
97+
<input type="checkbox"
98+
class="form-check-input"
99+
:id="props.id"
100+
v-model="model"
101+
:true-value="checkboxValues.truthy"
102+
:false-value="checkboxValues.falsy" />
103+
<div class="form-text" v-if="showDesc">
104+
{{ $t(descField) }}
105+
<slot></slot>
106+
</div>
107+
</div>
108+
</template>

src_assets/common/assets/web/apps.html

Lines changed: 40 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -116,15 +116,13 @@ <h1>{{ $t('apps.applications_title') }}</h1>
116116
<div id="appOutputHelp" class="form-text">{{ $t('apps.output_desc') }}</div>
117117
</div>
118118
<!-- prep-cmd -->
119-
<div class="mb-3">
120-
<label for="excludeGlobalPrep" class="form-label">{{ $t('apps.global_prep_name') }}</label>
121-
<select id="excludeGlobalPrep" class="form-select" v-model="editForm['exclude-global-prep-cmd']">
122-
<option v-for="val in [false, true]" :value="val">
123-
{{ !val ? $t('_common.enabled') : $t('_common.disabled') }}
124-
</option>
125-
</select>
126-
<div class="form-text">{{ $t('apps.global_prep_desc') }}</div>
127-
</div>
119+
<Checkbox class="mb-3"
120+
id="excludeGlobalPrep"
121+
label="apps.global_prep_name"
122+
desc="apps.global_prep_desc"
123+
v-model="editForm['exclude-global-prep-cmd']"
124+
checked-by-def
125+
></Checkbox>
128126
<div class="mb-3">
129127
<label for="appName" class="form-label">{{ $t('apps.cmd_prep_name') }}</label>
130128
<div class="form-text">{{ $t('apps.cmd_prep_desc') }}</div>
@@ -152,12 +150,12 @@ <h1>{{ $t('apps.applications_title') }}</h1>
152150
<td>
153151
<input type="text" class="form-control monospace" v-model="c.undo" />
154152
</td>
155-
<td v-if="platform === 'windows'">
156-
<div class="form-check">
157-
<input type="checkbox" class="form-check-input" :id="'prep-cmd-admin-' + i" v-model="c.elevated"
158-
true-value="true" false-value="false" />
159-
<label :for="'prep-cmd-admin-' + i" class="form-check-label">{{ $t('_common.elevated') }}</label>
160-
</div>
153+
<td v-if="platform === 'windows'" class="align-middle">
154+
<Checkbox :id="'prep-cmd-admin-' + i"
155+
label="_common.elevated"
156+
desc=""
157+
v-model="c.elevated"
158+
></Checkbox>
161159
</td>
162160
<td>
163161
<button class="btn btn-danger" @click="editForm['prep-cmd'].splice(i,1)">
@@ -208,26 +206,30 @@ <h1>{{ $t('apps.applications_title') }}</h1>
208206
<div id="appWorkingDirHelp" class="form-text">{{ $t('apps.working_dir_desc') }}</div>
209207
</div>
210208
<!-- elevation -->
211-
<div class="mb-3 form-check" v-if="platform === 'windows'">
212-
<label for="appElevation" class="form-check-label">{{ $t('_common.run_as') }}</label>
213-
<input type="checkbox" class="form-check-input" id="appElevation" v-model="editForm.elevated"
214-
true-value="true" false-value="false" />
215-
<div class="form-text">{{ $t('apps.run_as_desc') }}</div>
216-
</div>
209+
<Checkbox v-if="platform === 'windows'"
210+
class="mb-3"
211+
id="appElevation"
212+
label="_common.run_as"
213+
desc="apps.run_as_desc"
214+
v-model="editForm.elevated"
215+
unchecked-by-def
216+
></Checkbox>
217217
<!-- auto-detach -->
218-
<div class="mb-3 form-check">
219-
<label for="autoDetach" class="form-check-label">{{ $t('apps.auto_detach') }}</label>
220-
<input type="checkbox" class="form-check-input" id="autoDetach" v-model="editForm['auto-detach']"
221-
true-value="true" false-value="false" />
222-
<div class="form-text">{{ $t('apps.auto_detach_desc') }}</div>
223-
</div>
218+
<Checkbox class="mb-3"
219+
id="autoDetach"
220+
label="apps.auto_detach"
221+
desc="apps.auto_detach_desc"
222+
v-model="editForm['auto-detach']"
223+
checked-by-def
224+
></Checkbox>
224225
<!-- wait for all processes -->
225-
<div class="mb-3 form-check">
226-
<label for="waitAll" class="form-check-label">{{ $t('apps.wait_all') }}</label>
227-
<input type="checkbox" class="form-check-input" id="waitAll" v-model="editForm['wait-all']"
228-
true-value="true" false-value="false" />
229-
<div class="form-text">{{ $t('apps.wait_all_desc') }}</div>
230-
</div>
226+
<Checkbox class="mb-3"
227+
id="waitAll"
228+
label="apps.wait_all"
229+
desc="apps.wait_all_desc"
230+
v-model="editForm['wait-all']"
231+
checked-by-def
232+
></Checkbox>
231233
<!-- exit timeout -->
232234
<div class="mb-3">
233235
<label for="exitTimeout" class="form-label">{{ $t('apps.exit_timeout') }}</label>
@@ -358,11 +360,13 @@ <h4>{{ $t('apps.env_vars_about') }}</h4>
358360
import { createApp } from 'vue'
359361
import { initApp } from './init'
360362
import Navbar from './Navbar.vue'
363+
import Checkbox from './Checkbox.vue'
361364
import { Dropdown } from 'bootstrap/dist/js/bootstrap'
362365

363366
const app = createApp({
364367
components: {
365-
Navbar
368+
Navbar,
369+
Checkbox
366370
},
367371
data() {
368372
return {
@@ -415,9 +419,9 @@ <h4>{{ $t('apps.env_vars_about') }}</h4>
415419
if (this.editForm["detached"] === undefined)
416420
this.editForm["detached"] = [];
417421
if (this.editForm["exclude-global-prep-cmd"] === undefined)
418-
this.editForm["exclude-global-prep-cmd"] = [];
422+
this.editForm["exclude-global-prep-cmd"] = false;
419423
if (this.editForm["elevated"] === undefined && this.platform === 'windows') {
420-
this.editForm["elevated"] = [];
424+
this.editForm["elevated"] = false;
421425
}
422426
if (this.editForm["auto-detach"] === undefined) {
423427
this.editForm["auto-detach"] = true;

src_assets/common/assets/web/configs/tabs/AudioVideo.vue

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import AdapterNameSelector from './audiovideo/AdapterNameSelector.vue'
66
import DisplayOutputSelector from './audiovideo/DisplayOutputSelector.vue'
77
import DisplayDeviceOptions from "./audiovideo/DisplayDeviceOptions.vue";
88
import DisplayModesSettings from "./audiovideo/DisplayModesSettings.vue";
9+
import Checkbox from "../../Checkbox.vue";
910
1011
const props = defineProps([
1112
'platform',
@@ -54,14 +55,12 @@ const config = ref(props.config)
5455
</div>
5556

5657
<!-- Install Steam Audio Drivers -->
57-
<div class="mb-3">
58-
<label for="install_steam_audio_drivers" class="form-label">{{ $t('config.install_steam_audio_drivers') }}</label>
59-
<select id="install_steam_audio_drivers" class="form-select" v-model="config.install_steam_audio_drivers">
60-
<option value="disabled">{{ $t('_common.disabled') }}</option>
61-
<option value="enabled">{{ $t('_common.enabled_def') }}</option>
62-
</select>
63-
<div class="form-text">{{ $t('config.install_steam_audio_drivers_desc') }}</div>
64-
</div>
58+
<Checkbox class="mb-3"
59+
id="install_steam_audio_drivers"
60+
locale-prefix="config"
61+
v-model="config.install_steam_audio_drivers"
62+
checked-by-def
63+
></Checkbox>
6564
</template>
6665
</PlatformLayout>
6766

src_assets/common/assets/web/configs/tabs/General.vue

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
<script setup>
2+
import Checkbox from '../../Checkbox.vue'
23
import { ref } from 'vue'
34
45
const props = defineProps({
@@ -100,12 +101,12 @@ function removeCmd(index) {
100101
<td>
101102
<input type="text" class="form-control monospace" v-model="c.undo" />
102103
</td>
103-
<td v-if="platform === 'windows'">
104-
<div class="form-check">
105-
<input type="checkbox" class="form-check-input" :id="'prep-cmd-admin-' + i" v-model="c.elevated"
106-
true-value="true" false-value="false" />
107-
<label :for="'prep-cmd-admin-' + i" class="form-check-label">{{ $t('config.elevated') }}</label>
108-
</div>
104+
<td v-if="platform === 'windows'" class="align-middle">
105+
<Checkbox :id="'prep-cmd-admin-' + i"
106+
label="_common.elevated"
107+
desc=""
108+
v-model="c.elevated"
109+
></Checkbox>
109110
</td>
110111
<td>
111112
<button class="btn btn-danger" @click="removeCmd(i)">
@@ -124,14 +125,12 @@ function removeCmd(index) {
124125
</div>
125126

126127
<!-- Notify Pre-Releases -->
127-
<div class="mb-3">
128-
<label for="notify_pre_releases" class="form-label">{{ $t('config.notify_pre_releases') }}</label>
129-
<select id="notify_pre_releases" class="form-select" v-model="config.notify_pre_releases">
130-
<option value="disabled">{{ $t('_common.disabled') }}</option>
131-
<option value="enabled">{{ $t('_common.enabled') }}</option>
132-
</select>
133-
<div class="form-text">{{ $t('config.notify_pre_releases_desc') }}</div>
134-
</div>
128+
<Checkbox class="mb-3"
129+
id="notify_pre_releases"
130+
locale-prefix="config"
131+
v-model="config.notify_pre_releases"
132+
unchecked-by-def
133+
></Checkbox>
135134
</div>
136135
</template>
137136

0 commit comments

Comments
 (0)