173 lines
4.5 KiB
Vue
173 lines
4.5 KiB
Vue
<template>
|
|
<div class="container mx-0 px-0">
|
|
<FormRow id="settingsDesign" :label="$t('settings.theme.label')">
|
|
<SelectGroup
|
|
id="settingsDesign"
|
|
v-model="theme"
|
|
class="w-100"
|
|
transparent
|
|
:options="
|
|
THEMES.map((value) => ({
|
|
value,
|
|
name: $t(`settings.theme.${value}`),
|
|
}))
|
|
"
|
|
equal-width
|
|
/>
|
|
</FormRow>
|
|
<FormRow id="settingsLanguage" :label="$t('settings.language.label')">
|
|
<select
|
|
id="settingsLanguage"
|
|
v-model="language"
|
|
class="form-select form-select-sm w-75"
|
|
>
|
|
<option value="">{{ $t("settings.language.auto") }}</option>
|
|
<option v-for="option in languageOptions" :key="option.value" :value="option.value">
|
|
{{ option.name }}
|
|
</option>
|
|
</select>
|
|
</FormRow>
|
|
<FormRow id="settingsUnit" :label="$t('settings.unit.label')">
|
|
<SelectGroup
|
|
id="settingsUnit"
|
|
v-model="unit"
|
|
class="w-75"
|
|
transparent
|
|
:options="
|
|
UNITS.map((value) => ({
|
|
value,
|
|
name: $t(`settings.unit.${value}`),
|
|
}))
|
|
"
|
|
:aria-label="$t('settings.unit.label')"
|
|
equal-width
|
|
/>
|
|
</FormRow>
|
|
<FormRow id="settingsTimeFormat" :label="$t('settings.time.label')">
|
|
<SelectGroup
|
|
id="settingsTimeFormat"
|
|
v-model="timeFormat"
|
|
class="w-75"
|
|
transparent
|
|
:options="
|
|
TIME_FORMATS.map((value) => ({
|
|
value,
|
|
name: $t(`settings.time.${value}h`),
|
|
}))
|
|
"
|
|
:aria-label="$t('settings.time.label')"
|
|
equal-width
|
|
/>
|
|
</FormRow>
|
|
<FormRow v-if="loadpoints.length" :label="$t('settings.loadpoints.label')">
|
|
<LoadpointOrderSettings :loadpoints="loadpoints" />
|
|
</FormRow>
|
|
<FormRow v-if="fullscreenAvailable" :label="$t('settings.fullscreen.label')">
|
|
<button
|
|
v-if="fullscreenActive"
|
|
class="btn btn-sm btn-outline-secondary"
|
|
@click="exitFullscreen"
|
|
>
|
|
{{ $t("settings.fullscreen.exit") }}
|
|
</button>
|
|
<button v-else class="btn btn-sm btn-outline-secondary" @click="enterFullscreen">
|
|
{{ $t("settings.fullscreen.enter") }}
|
|
</button>
|
|
</FormRow>
|
|
<div class="small text-muted mb-3">
|
|
{{ $t("settings.deviceInfo") }}
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<script lang="ts">
|
|
import FormRow from "../Helper/FormRow.vue";
|
|
import SelectGroup from "../Helper/SelectGroup.vue";
|
|
import LoadpointOrderSettings from "./LoadpointOrderSettings.vue";
|
|
import {
|
|
getLocalePreference,
|
|
setLocalePreference,
|
|
LOCALES,
|
|
removeLocalePreference,
|
|
} from "@/i18n.ts";
|
|
import { getThemePreference, setThemePreference } from "@/theme.ts";
|
|
import { getUnits, setUnits, is12hFormat, set12hFormat } from "@/units";
|
|
import { isApp } from "@/utils/native";
|
|
import { defineComponent, type PropType } from "vue";
|
|
import { LENGTH_UNIT, THEME, TIME_FORMAT, type UiLoadpoint } from "@/types/evcc";
|
|
|
|
export default defineComponent({
|
|
name: "UserInterfaceSettings",
|
|
components: { FormRow, SelectGroup, LoadpointOrderSettings },
|
|
props: {
|
|
loadpoints: { type: Array as PropType<UiLoadpoint[]>, default: () => [] },
|
|
},
|
|
data() {
|
|
return {
|
|
theme: getThemePreference(),
|
|
language: getLocalePreference() || "",
|
|
unit: getUnits(),
|
|
timeFormat: is12hFormat() ? TIME_FORMAT.H12 : TIME_FORMAT.H24,
|
|
fullscreenActive: false,
|
|
THEMES: Object.values(THEME),
|
|
UNITS: Object.values(LENGTH_UNIT),
|
|
TIME_FORMATS: [TIME_FORMAT.H24, TIME_FORMAT.H12],
|
|
};
|
|
},
|
|
computed: {
|
|
languageOptions: () => {
|
|
const locales = Object.entries(LOCALES).map(([key, value]) => {
|
|
return { value: key, name: value[1] };
|
|
});
|
|
// sort by name
|
|
locales.sort((a, b) => ((a.name || "") < (b.name || "") ? -1 : 1));
|
|
return locales;
|
|
},
|
|
fullscreenAvailable: () => {
|
|
const isSupported = document.fullscreenEnabled;
|
|
const isPwa =
|
|
(navigator as any).standalone ||
|
|
window.matchMedia("(display-mode: standalone)").matches;
|
|
return isSupported && !isPwa && !isApp();
|
|
},
|
|
},
|
|
watch: {
|
|
unit(value) {
|
|
setUnits(value);
|
|
},
|
|
timeFormat(value) {
|
|
set12hFormat(value === TIME_FORMAT.H12);
|
|
},
|
|
theme(value) {
|
|
setThemePreference(value);
|
|
},
|
|
language(value) {
|
|
const i18n = this.$root?.$i18n;
|
|
if (!i18n) return;
|
|
else if (value) {
|
|
setLocalePreference(i18n, value);
|
|
} else {
|
|
removeLocalePreference(i18n);
|
|
}
|
|
},
|
|
},
|
|
mounted() {
|
|
document.addEventListener("fullscreenchange", this.fullscreenChange);
|
|
},
|
|
unmounted() {
|
|
document.removeEventListener("fullscreenchange", this.fullscreenChange);
|
|
},
|
|
methods: {
|
|
isApp,
|
|
enterFullscreen() {
|
|
document.documentElement.requestFullscreen();
|
|
},
|
|
exitFullscreen() {
|
|
document.exitFullscreen();
|
|
},
|
|
fullscreenChange() {
|
|
this.fullscreenActive = !!document.fullscreenElement;
|
|
},
|
|
},
|
|
});
|
|
</script>
|