summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/client/components/ui/range.vue138
-rw-r--r--src/client/pages/preferences/index.vue18
2 files changed, 152 insertions, 4 deletions
diff --git a/src/client/components/ui/range.vue b/src/client/components/ui/range.vue
new file mode 100644
index 0000000000..ab59bf516c
--- /dev/null
+++ b/src/client/components/ui/range.vue
@@ -0,0 +1,138 @@
+<template>
+<div class="timctyfi" :class="{ focused, disabled }">
+ <div class="icon"><slot name="icon"></slot></div>
+ <span class="title"><slot name="title"></slot></span>
+ <input
+ type="range"
+ ref="input"
+ v-model="v"
+ :disabled="disabled"
+ :min="min"
+ :max="max"
+ :step="step"
+ :autofocus="autofocus"
+ @focus="focused = true"
+ @blur="focused = false"
+ @input="$emit('input', $event.target.value)"
+ />
+</div>
+</template>
+
+<script lang="ts">
+import Vue from "vue";
+export default Vue.extend({
+ props: {
+ value: {
+ type: Number,
+ required: false,
+ default: 0
+ },
+ disabled: {
+ type: Boolean,
+ required: false,
+ default: false
+ },
+ min: {
+ type: String,
+ required: false,
+ default: "0"
+ },
+ max: {
+ type: String,
+ required: false,
+ default: "100"
+ },
+ step: {
+ type: String,
+ required: false,
+ default: "1"
+ },
+ autofocus: {
+ type: Boolean,
+ required: false
+ }
+ },
+ data() {
+ return {
+ v: this.value,
+ focused: false
+ };
+ },
+ watch: {
+ value(v) {
+ this.v = parseFloat(v);
+ }
+ },
+ mounted() {
+ if (this.autofocus) {
+ this.$nextTick(() => {
+ this.$refs.input.focus();
+ });
+ }
+ }
+});
+</script>
+
+<style lang="scss" scoped>
+.timctyfi {
+ position: relative;
+ margin: 8px;
+
+ > .icon {
+ display: inline-block;
+ width: 24px;
+ text-align: center;
+ }
+
+ > .title {
+ pointer-events: none;
+ font-size: 16px;
+ color: var(--inputLabel);
+ overflow: hidden;
+ }
+
+ > input {
+ -webkit-appearance: none;
+ -moz-appearance: none;
+ appearance: none;
+ background: var(--xxubwiul);
+ height: 7px;
+ margin: 0 8px;
+ outline: 0;
+ border: 0;
+ border-radius: 7px;
+
+ &.disabled {
+ opacity: 0.6;
+ cursor: not-allowed;
+ }
+
+ &::-webkit-slider-thumb {
+ -webkit-appearance: none;
+ appearance: none;
+ cursor: pointer;
+ width: 20px;
+ height: 20px;
+ display: block;
+ border-radius: 50%;
+ border: none;
+ background: var(--accent);
+ box-shadow: 0 0 6px rgba(0, 0, 0, 0.3);
+ box-sizing: content-box;
+ }
+
+ &::-moz-range-thumb {
+ -moz-appearance: none;
+ appearance: none;
+ cursor: pointer;
+ width: 20px;
+ height: 20px;
+ display: block;
+ border-radius: 50%;
+ border: none;
+ background: var(--accent);
+ box-shadow: 0 0 6px rgba(0, 0, 0, 0.3);
+ }
+ }
+}
+</style>
diff --git a/src/client/pages/preferences/index.vue b/src/client/pages/preferences/index.vue
index eddf69653d..3bc305a229 100644
--- a/src/client/pages/preferences/index.vue
+++ b/src/client/pages/preferences/index.vue
@@ -8,8 +8,10 @@
<section class="_card">
<div class="_title"><fa :icon="faMusic"/> {{ $t('sounds') }}</div>
<div class="_content">
- {{ $t('volume') }}
- <input type="range" v-model="sfxVolume" min="0" max="1" step="0.1"/>
+ <mk-range v-model="sfxVolume" min="0" max="1" step="0.1">
+ <fa slot="icon" :icon="volumeIcon"/>
+ <span slot="title">{{ $t('volume') }}</span>
+ </mk-range>
</div>
<div class="_content">
<mk-select v-model="sfxNote">
@@ -85,12 +87,13 @@
<script lang="ts">
import Vue from 'vue';
-import { faImage, faCog, faMusic, faPlay } from '@fortawesome/free-solid-svg-icons';
+import { faImage, faCog, faMusic, faPlay, faVolumeUp, faVolumeMute } from '@fortawesome/free-solid-svg-icons';
import MkInput from '../../components/ui/input.vue';
import MkButton from '../../components/ui/button.vue';
import MkSwitch from '../../components/ui/switch.vue';
import MkSelect from '../../components/ui/select.vue';
import MkRadio from '../../components/ui/radio.vue';
+import MkRange from '../../components/ui/range.vue';
import XTheme from './theme.vue';
import i18n from '../../i18n';
import { langs } from '../../config';
@@ -128,6 +131,7 @@ export default Vue.extend({
MkSwitch,
MkSelect,
MkRadio,
+ MkRange
},
data() {
@@ -136,7 +140,7 @@ export default Vue.extend({
lang: localStorage.getItem('lang'),
fontSize: localStorage.getItem('fontSize'),
sounds,
- faImage, faCog, faMusic, faPlay
+ faImage, faCog, faMusic, faPlay, faVolumeUp, faVolumeMute
}
},
@@ -210,6 +214,12 @@ export default Vue.extend({
get() { return this.$store.state.device.sfxAntenna; },
set(value) { this.$store.commit('device/set', { key: 'sfxAntenna', value }); }
},
+
+ volumeIcon: {
+ get() {
+ return this.sfxVolume === 0 ? faVolumeMute : faVolumeUp;
+ }
+ }
},
watch: {