forked from akanyan/STARTLINER
feat: display witchcraft
This commit is contained in:
@ -6,10 +6,9 @@ import TabList from 'primevue/tablist';
|
||||
import TabPanel from 'primevue/tabpanel';
|
||||
import TabPanels from 'primevue/tabpanels';
|
||||
import Tabs from 'primevue/tabs';
|
||||
import { onOpenUrl } from '@tauri-apps/plugin-deep-link';
|
||||
import ModList from './ModList.vue';
|
||||
import ModStore from './ModStore.vue';
|
||||
import Options from './Options.vue';
|
||||
import OptionList from './OptionList.vue';
|
||||
import ProfileList from './ProfileList.vue';
|
||||
import StartButton from './StartButton.vue';
|
||||
import { usePkgStore, usePrfStore } from '../stores';
|
||||
@ -64,7 +63,7 @@ onMounted(async () => {
|
||||
<ModStore />
|
||||
</TabPanel>
|
||||
<TabPanel value="2">
|
||||
<Options />
|
||||
<OptionList />
|
||||
</TabPanel>
|
||||
<TabPanel value="3">
|
||||
<strong>UNDER CONSTRUCTION</strong><br />Many features are
|
||||
|
15
src/components/OptionCategory.vue
Normal file
15
src/components/OptionCategory.vue
Normal file
@ -0,0 +1,15 @@
|
||||
<script setup lang="ts">
|
||||
import Fieldset from 'primevue/fieldset';
|
||||
|
||||
defineProps({
|
||||
title: String,
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Fieldset :legend="title" :toggleable="true">
|
||||
<div class="flex w-full flex-col gap-1">
|
||||
<slot />
|
||||
</div>
|
||||
</Fieldset>
|
||||
</template>
|
182
src/components/OptionList.vue
Normal file
182
src/components/OptionList.vue
Normal file
@ -0,0 +1,182 @@
|
||||
<script setup lang="ts">
|
||||
import { Ref, computed, ref } from 'vue';
|
||||
import InputNumber from 'primevue/inputnumber';
|
||||
import InputText from 'primevue/inputtext';
|
||||
import Select from 'primevue/select';
|
||||
import SelectButton from 'primevue/selectbutton';
|
||||
import Toggle from 'primevue/toggleswitch';
|
||||
import OptionCategory from './OptionCategory.vue';
|
||||
import OptionRow from './OptionRow.vue';
|
||||
import { invoke } from '../invoke';
|
||||
import { usePrfStore } from '../stores';
|
||||
|
||||
const prf = usePrfStore();
|
||||
|
||||
const _cfg = <T extends string | number | boolean>(key: string, dflt: T) =>
|
||||
computed({
|
||||
get() {
|
||||
return (prf.cfg(key) as T) ?? dflt;
|
||||
},
|
||||
async set(value) {
|
||||
await prf.setCfg(key, value ?? dflt);
|
||||
},
|
||||
});
|
||||
|
||||
const cfgIntel = _cfg('intel', false);
|
||||
const cfgRezW = _cfg('rez-w', 1080);
|
||||
const cfgRezH = _cfg('rez-h', 1920);
|
||||
const cfgDisplayMode = _cfg('display-mode', 'borderless');
|
||||
const displayModeList = [
|
||||
{ title: 'Window', value: 'window' },
|
||||
{ title: 'Borderless window', value: 'borderless' },
|
||||
{ title: 'Fullscreen', value: 'fullscreen' },
|
||||
];
|
||||
const cfgDisplay = _cfg('display', 'default');
|
||||
const cfgDisplayRotation = _cfg('display-rotation', 0);
|
||||
const displayRotationList = [
|
||||
{ title: 'Unchanged', value: 0 },
|
||||
{ title: 'Portrait', value: 90 },
|
||||
{ title: 'Portrait (flipped)', value: 270 },
|
||||
];
|
||||
|
||||
const cfgAime = _cfg('aime', false);
|
||||
const aimeCode = ref('');
|
||||
const capabilities: Ref<string[]> = ref([]);
|
||||
const displayList: Ref<{ title: string; value: string }[]> = ref([
|
||||
{
|
||||
title: 'Primary',
|
||||
value: 'default',
|
||||
},
|
||||
]);
|
||||
|
||||
invoke('read_profile_data', {
|
||||
path: 'aime.txt',
|
||||
})
|
||||
.then((v: unknown) => {
|
||||
if (typeof v === 'string') {
|
||||
aimeCode.value = v;
|
||||
} else {
|
||||
aimeCode.value = '';
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
aimeCode.value = '';
|
||||
});
|
||||
|
||||
invoke('list_platform_capabilities')
|
||||
.then(async (v: unknown) => {
|
||||
if (Array.isArray(v)) {
|
||||
capabilities.value.push(...v);
|
||||
}
|
||||
|
||||
if (capabilities.value.includes('display')) {
|
||||
for (const [devName, devString] of (await invoke(
|
||||
'list_displays'
|
||||
)) as Array<[string, string]>) {
|
||||
displayList.value.push({
|
||||
title: `${devName.replace('\\\\.\\', '')} (${devString})`,
|
||||
value: devName,
|
||||
});
|
||||
}
|
||||
}
|
||||
})
|
||||
.catch(() => {});
|
||||
|
||||
const aimeCodeModel = computed({
|
||||
get() {
|
||||
return aimeCode.value;
|
||||
},
|
||||
async set(value: string) {
|
||||
aimeCode.value = value;
|
||||
if (value.match(/^[0-9]{20}$/)) {
|
||||
await invoke('write_profile_data', {
|
||||
path: 'aime.txt',
|
||||
content: aimeCode.value,
|
||||
});
|
||||
}
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<OptionCategory title="Display options">
|
||||
<OptionRow
|
||||
v-if="capabilities.includes('display')"
|
||||
title="Target display"
|
||||
>
|
||||
<Select
|
||||
v-model="cfgDisplay"
|
||||
:options="displayList"
|
||||
option-label="title"
|
||||
option-value="value"
|
||||
></Select>
|
||||
</OptionRow>
|
||||
<OptionRow id="resolution" title="Resolution">
|
||||
<InputNumber
|
||||
class="shrink"
|
||||
size="small"
|
||||
:min="480"
|
||||
:max="9999"
|
||||
:use-grouping="false"
|
||||
v-model="cfgRezW"
|
||||
/>
|
||||
x
|
||||
<InputNumber
|
||||
class="shrink"
|
||||
size="small"
|
||||
:min="640"
|
||||
:max="9999"
|
||||
:use-grouping="false"
|
||||
v-model="cfgRezH"
|
||||
/>
|
||||
</OptionRow>
|
||||
<OptionRow title="Display mode">
|
||||
<SelectButton
|
||||
v-model="cfgDisplayMode"
|
||||
:options="displayModeList"
|
||||
option-label="title"
|
||||
option-value="value"
|
||||
/>
|
||||
</OptionRow>
|
||||
<OptionRow
|
||||
title="Display rotation"
|
||||
v-if="capabilities.includes('display')"
|
||||
>
|
||||
<SelectButton
|
||||
v-model="cfgDisplayRotation"
|
||||
:options="displayRotationList"
|
||||
option-label="title"
|
||||
option-value="value"
|
||||
:disabled="cfgDisplay === 'default'"
|
||||
/>
|
||||
</OptionRow>
|
||||
</OptionCategory>
|
||||
<OptionCategory title="Misc">
|
||||
<OptionRow title="OpenSSL bug workaround for Intel ≥10th gen">
|
||||
<Toggle v-model="cfgIntel" />
|
||||
</OptionRow>
|
||||
<OptionRow title="Aime emulation">
|
||||
<Toggle inputId="switch2" v-model="cfgAime" />
|
||||
</OptionRow>
|
||||
<OptionRow title="Aime code">
|
||||
<InputText
|
||||
class="shrink"
|
||||
size="small"
|
||||
:disabled="prf.cfg('aime') !== true"
|
||||
:maxlength="20"
|
||||
placeholder="00000000000000000000"
|
||||
v-model="aimeCodeModel"
|
||||
/>
|
||||
</OptionRow>
|
||||
</OptionCategory>
|
||||
</template>
|
||||
|
||||
<style>
|
||||
#resolution .p-inputnumber-input {
|
||||
width: 4rem;
|
||||
}
|
||||
|
||||
.p-inputtext {
|
||||
font-family: monospace;
|
||||
}
|
||||
</style>
|
12
src/components/OptionRow.vue
Normal file
12
src/components/OptionRow.vue
Normal file
@ -0,0 +1,12 @@
|
||||
<script setup lang="ts">
|
||||
defineProps({
|
||||
title: String,
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="flex flex-row w-full p-2 gap-2 items-center">
|
||||
<div class="grow">{{ title }}</div>
|
||||
<slot />
|
||||
</div>
|
||||
</template>
|
@ -1,146 +0,0 @@
|
||||
<script setup lang="ts">
|
||||
import { computed, ref } from 'vue';
|
||||
import Fieldset from 'primevue/fieldset';
|
||||
import InputNumber from 'primevue/inputnumber';
|
||||
import InputText from 'primevue/inputtext';
|
||||
import RadioButton from 'primevue/radiobutton';
|
||||
import Toggle from 'primevue/toggleswitch';
|
||||
import { invoke } from '../invoke';
|
||||
import { usePrfStore } from '../stores';
|
||||
|
||||
const prf = usePrfStore();
|
||||
|
||||
const _cfg = <T extends string | number | boolean>(key: string, dflt: T) =>
|
||||
computed({
|
||||
get() {
|
||||
return (prf.cfg(key) as T) ?? dflt;
|
||||
},
|
||||
async set(value) {
|
||||
await prf.setCfg(key, value ?? dflt);
|
||||
},
|
||||
});
|
||||
|
||||
const cfgIntel = _cfg('intel', false);
|
||||
const cfgRezW = _cfg('rez-w', 1080);
|
||||
const cfgRezH = _cfg('rez-h', 1920);
|
||||
const cfgDisplayMode = _cfg('display-mode', 'borderless');
|
||||
const cfgAime = _cfg('aime', false);
|
||||
|
||||
const aimeCode = ref('');
|
||||
|
||||
(async () => {
|
||||
try {
|
||||
aimeCode.value = await invoke('read_profile_data', {
|
||||
path: 'aime.txt',
|
||||
});
|
||||
} catch (e) {
|
||||
aimeCode.value = '';
|
||||
}
|
||||
})();
|
||||
|
||||
const aimeCodeModel = computed({
|
||||
get() {
|
||||
return aimeCode.value;
|
||||
},
|
||||
async set(value: string) {
|
||||
aimeCode.value = value;
|
||||
if (value.match(/^[0-9]{20}$/)) {
|
||||
await invoke('write_profile_data', {
|
||||
path: 'aime.txt',
|
||||
content: aimeCode.value,
|
||||
});
|
||||
}
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Fieldset legend="Launch options" :toggleable="true">
|
||||
<div class="flex w-full flex-col gap-1">
|
||||
<label for="switch1" class="flex flex-row w-full p-2">
|
||||
<div class="grow">
|
||||
OpenSSL bug workaround for Intel ≥10th gen
|
||||
</div>
|
||||
<Toggle inputId="switch1" v-model="cfgIntel" />
|
||||
</label>
|
||||
<label
|
||||
id="resolution"
|
||||
class="flex flex-row w-full p-2 gap-2 items-center"
|
||||
>
|
||||
<div class="grow">Resolution</div>
|
||||
<InputNumber
|
||||
class="shrink"
|
||||
size="small"
|
||||
:min="480"
|
||||
:max="9999"
|
||||
:use-grouping="false"
|
||||
v-model="cfgRezW"
|
||||
/>
|
||||
x
|
||||
<InputNumber
|
||||
class="shrink"
|
||||
size="small"
|
||||
:min="640"
|
||||
:max="9999"
|
||||
:use-grouping="false"
|
||||
v-model="cfgRezH"
|
||||
/>
|
||||
</label>
|
||||
<label class="flex flex-row w-full p-2 gap-2">
|
||||
<div class="grow">Display mode</div>
|
||||
<div class="flex items-center gap-2">
|
||||
<RadioButton
|
||||
v-model="cfgDisplayMode"
|
||||
inputId="ingredient1"
|
||||
name="window"
|
||||
value="window"
|
||||
/>
|
||||
<label for="ingredient1">window</label>
|
||||
</div>
|
||||
<div class="flex items-center gap-2">
|
||||
<RadioButton
|
||||
v-model="cfgDisplayMode"
|
||||
inputId="ingredient2"
|
||||
name="borderless"
|
||||
value="borderless"
|
||||
/>
|
||||
<label for="ingredient2">borderless window</label>
|
||||
</div>
|
||||
<div class="flex items-center gap-2">
|
||||
<RadioButton
|
||||
v-model="cfgDisplayMode"
|
||||
inputId="ingredient3"
|
||||
name="fullscreen"
|
||||
value="fullscreen"
|
||||
/>
|
||||
<label for="ingredient3">fullscreen</label>
|
||||
</div>
|
||||
</label>
|
||||
<label for="switch2" class="flex flex-row w-full p-2">
|
||||
<div class="grow">Aime emulation</div>
|
||||
<Toggle inputId="switch2" v-model="cfgAime" />
|
||||
</label>
|
||||
<label class="flex flex-row w-full p-2 items-center">
|
||||
<div class="grow">Aime code</div>
|
||||
<InputText
|
||||
class="shrink"
|
||||
size="small"
|
||||
:disabled="prf.cfg('aime') !== true"
|
||||
:maxlength="20"
|
||||
placeholder="00000000000000000000"
|
||||
v-model="aimeCodeModel"
|
||||
/>
|
||||
</label>
|
||||
</div>
|
||||
</Fieldset>
|
||||
</template>
|
||||
|
||||
<style>
|
||||
#resolution .p-inputnumber-input {
|
||||
width: 4rem;
|
||||
}
|
||||
|
||||
.p-inputtext {
|
||||
font-family: monospace;
|
||||
}
|
||||
</style>
|
Reference in New Issue
Block a user