diff options
| author | syuilo <syuilotan@yahoo.co.jp> | 2018-09-29 00:01:11 +0900 |
|---|---|---|
| committer | syuilo <syuilotan@yahoo.co.jp> | 2018-09-29 00:01:11 +0900 |
| commit | 6a82e94c5489d4879cbbf86091cd15c7d144f284 (patch) | |
| tree | 148f1b4bba454a71075d4b7b21d983b58215e8af /src/client/app/common/views/components | |
| parent | wip (diff) | |
| download | misskey-6a82e94c5489d4879cbbf86091cd15c7d144f284.tar.gz misskey-6a82e94c5489d4879cbbf86091cd15c7d144f284.tar.bz2 misskey-6a82e94c5489d4879cbbf86091cd15c7d144f284.zip | |
wip
Diffstat (limited to 'src/client/app/common/views/components')
| -rw-r--r-- | src/client/app/common/views/components/avatar.vue | 4 | ||||
| -rw-r--r-- | src/client/app/common/views/components/index.ts | 2 | ||||
| -rw-r--r-- | src/client/app/common/views/components/theme.vue | 179 | ||||
| -rw-r--r-- | src/client/app/common/views/components/ui/button.vue | 12 |
4 files changed, 188 insertions, 9 deletions
diff --git a/src/client/app/common/views/components/avatar.vue b/src/client/app/common/views/components/avatar.vue index ca09af87de..ac018abcfc 100644 --- a/src/client/app/common/views/components/avatar.vue +++ b/src/client/app/common/views/components/avatar.vue @@ -59,7 +59,9 @@ export default Vue.extend({ } }, mounted() { - this.$el.style.color = `rgb(${this.user.avatarColor.slice(0, 3).join(',')})`; + if (this.user.avatarColor) { + this.$el.style.color = `rgb(${this.user.avatarColor.slice(0, 3).join(',')})`; + } }, methods: { onClick(e) { diff --git a/src/client/app/common/views/components/index.ts b/src/client/app/common/views/components/index.ts index 4c1c0afa80..0dea38a7a1 100644 --- a/src/client/app/common/views/components/index.ts +++ b/src/client/app/common/views/components/index.ts @@ -1,5 +1,6 @@ import Vue from 'vue'; +import theme from './theme.vue'; import instance from './instance.vue'; import cwButton from './cw-button.vue'; import tagCloud from './tag-cloud.vue'; @@ -43,6 +44,7 @@ import uiSelect from './ui/select.vue'; import formButton from './ui/form/button.vue'; import formRadio from './ui/form/radio.vue'; +Vue.component('mk-theme', theme); Vue.component('mk-instance', instance); Vue.component('mk-cw-button', cwButton); Vue.component('mk-tag-cloud', tagCloud); diff --git a/src/client/app/common/views/components/theme.vue b/src/client/app/common/views/components/theme.vue new file mode 100644 index 0000000000..27888d1e85 --- /dev/null +++ b/src/client/app/common/views/components/theme.vue @@ -0,0 +1,179 @@ +<template> +<div class="nicnklzforebnpfgasiypmpdaaglujqm"> + <label> + <span>%i18n:@light-theme%</span> + <ui-select v-model="light" placeholder="%i18n:@light-theme%"> + <option v-for="x in themes" :value="x.meta.id" :key="x.meta.id">{{ x.meta.name }}</option> + </ui-select> + </label> + + <label> + <span>%i18n:@dark-theme%</span> + <ui-select v-model="dark" placeholder="%i18n:@dark-theme%"> + <option v-for="x in themes" :value="x.meta.id" :key="x.meta.id">{{ x.meta.name }}</option> + </ui-select> + </label> + + <details class="creator"> + <summary>%i18n:@create-a-theme%</summary> + <div> + <span>%i18n:@base-theme%:</span> + <ui-radio v-model="myThemeBase" value="light">%i18n:@base-theme-light%</ui-radio> + <ui-radio v-model="myThemeBase" value="dark">%i18n:@base-theme-dark%</ui-radio> + </div> + <div> + <ui-input v-model="myThemeName"> + <span>%i18n:@theme-name%</span> + </ui-input> + </div> + <div> + <div style="padding-bottom:8px;">%i18n:@primary-color%:</div> + <color-picker v-model="myThemePrimary"/> + </div> + <div> + <div style="padding-bottom:8px;">%i18n:@secondary-color%:</div> + <color-picker v-model="myThemeSecondary"/> + </div> + <div> + <div style="padding-bottom:8px;">%i18n:@text-color%:</div> + <color-picker v-model="myThemeText"/> + </div> + <ui-button @click="preview()">%i18n:@preview-created-theme%</ui-button> + <ui-button primary @click="gen()">%i18n:@save-created-theme%</ui-button> + </details> + + <details> + <summary>%i18n:@install-a-theme%</summary> + <ui-textarea v-model="installThemeCode"> + <span>%i18n:@theme-code%</span> + </ui-textarea> + <ui-button @click="install()">%i18n:@install%</ui-button> + </details> + + <details> + <summary>%i18n:@installed-themes%</summary> + <ui-select v-model="selectedInstalledTheme" placeholder="%i18n:@select-theme%"> + <option v-for="x in installedThemes" :value="x.meta.id" :key="x.meta.id">{{ x.meta.name }}</option> + </ui-select> + <ui-textarea readonly :value="selectedInstalledThemeCode"> + <span>%i18n:@theme-code%</span> + </ui-textarea> + </details> +</div> +</template> + +<script lang="ts"> +import Vue from 'vue'; +import { apiUrl, docsUrl } from '../../../config'; +import { lightTheme, darkTheme, builtinThemes, applyTheme } from '../../../theme'; +import { Chrome } from 'vue-color'; +import * as uuid from 'uuid'; +import * as tinycolor from 'tinycolor2'; + +export default Vue.extend({ + components: { + ColorPicker: Chrome + }, + + data() { + return { + installThemeCode: null, + selectedInstalledTheme: null, + myThemeBase: 'light', + myThemeName: '', + myThemePrimary: lightTheme.meta.vars.primary, + myThemeSecondary: lightTheme.meta.vars.secondary, + myThemeText: lightTheme.meta.vars.text + }; + }, + + computed: { + themes(): any { + return this.$store.state.device.themes.concat(builtinThemes); + }, + + installedThemes(): any { + return this.$store.state.device.themes; + }, + + light: { + get() { return this.$store.state.device.lightTheme; }, + set(value) { this.$store.commit('device/set', { key: 'lightTheme', value }); } + }, + + dark: { + get() { return this.$store.state.device.darkTheme; }, + set(value) { this.$store.commit('device/set', { key: 'darkTheme', value }); } + }, + + selectedInstalledThemeCode() { + if (this.selectedInstalledTheme == null) return null; + return JSON.stringify(this.installedThemes.find(x => x.meta.id == this.selectedInstalledTheme)); + }, + + myTheme(): any { + return { + meta: { + name: this.myThemeName, + author: this.$store.state.i.name, + base: this.myThemeBase, + vars: { + primary: tinycolor(typeof this.myThemePrimary == 'string' ? this.myThemePrimary : this.myThemePrimary.rgba).toRgbString(), + secondary: tinycolor(typeof this.myThemeSecondary == 'string' ? this.myThemeSecondary : this.myThemeSecondary.rgba).toRgbString(), + text: tinycolor(typeof this.myThemeText == 'string' ? this.myThemeText : this.myThemeText.rgba).toRgbString() + } + } + }; + } + }, + + watch: { + myThemeBase(v) { + const theme = v == 'light' ? lightTheme : darkTheme; + this.myThemePrimary = theme.meta.vars.primary; + this.myThemeSecondary = theme.meta.vars.secondary; + this.myThemeText = theme.meta.vars.text; + } + }, + + methods: { + install() { + const theme = JSON.parse(this.installThemeCode); + if (theme.meta == null || theme.meta.id == null) { + alert('%i18n:@invalid-theme%'); + return; + } + if (this.$store.state.device.themes.some(t => t.meta.id == theme.meta.id)) { + alert('%i18n:@already-installed%'); + return; + } + const themes = this.$store.state.device.themes.concat(theme); + this.$store.commit('device/set', { + key: 'themes', value: themes + }); + }, + + preview() { + applyTheme(this.myTheme, false); + }, + + gen() { + const theme = this.myTheme; + theme.meta.id = uuid(); + const themes = this.$store.state.device.themes.concat(theme); + this.$store.commit('device/set', { + key: 'themes', value: themes + }); + alert('%i18n:@saved%'); + } + } +}); +</script> + +<style lang="stylus" scoped> +.nicnklzforebnpfgasiypmpdaaglujqm + > .creator + > div + padding 16px 0 + border-bottom solid 1px var(--faceDivider) +</style> diff --git a/src/client/app/common/views/components/ui/button.vue b/src/client/app/common/views/components/ui/button.vue index a165d100a4..47644b32b5 100644 --- a/src/client/app/common/views/components/ui/button.vue +++ b/src/client/app/common/views/components/ui/button.vue @@ -27,14 +27,6 @@ export default Vue.extend({ return { styl: 'fill' }; - }, - inject: { - isCardChild: { default: false } - }, - created() { - if (this.isCardChild) { - this.styl = 'line'; - } } }); </script> @@ -43,6 +35,7 @@ export default Vue.extend({ .dmtdnykelhudezerjlfpbhgovrgnqqgr display block width 100% + min-height 40px margin 0 padding 0 font-weight normal @@ -52,6 +45,9 @@ export default Vue.extend({ outline none box-shadow none + &:not(.inline) + .dmtdnykelhudezerjlfpbhgovrgnqqgr + margin-top 16px + &.inline display inline-block width auto |