forked from FoundKeyGang/FoundKey
parent
21ebc5e84e
commit
d10be71161
7 changed files with 265 additions and 15 deletions
|
@ -27,7 +27,7 @@ export type API = {
|
||||||
dialog: (opts: {
|
dialog: (opts: {
|
||||||
title: string;
|
title: string;
|
||||||
text: string;
|
text: string;
|
||||||
actions: Array<{
|
actions?: Array<{
|
||||||
text: string;
|
text: string;
|
||||||
id?: string;
|
id?: string;
|
||||||
}>;
|
}>;
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
import MiOS from '../mios';
|
import MiOS from '../mios';
|
||||||
import { version } from '../../config';
|
import { version } from '../../config';
|
||||||
|
|
||||||
export default async function(mios: MiOS) {
|
export default async function(mios: MiOS, force = false, silent = false) {
|
||||||
const meta = await mios.getMeta();
|
const meta = await mios.getMeta(force);
|
||||||
|
|
||||||
if (meta.version != version) {
|
if (meta.version != version) {
|
||||||
localStorage.setItem('should-refresh', 'true');
|
localStorage.setItem('should-refresh', 'true');
|
||||||
|
@ -20,6 +20,12 @@ export default async function(mios: MiOS) {
|
||||||
console.error(e);
|
console.error(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
alert('%i18n:common.update-available%'.replace('{newer}', meta.version).replace('{current}', version));
|
if (!silent) {
|
||||||
|
alert('%i18n:common.update-available%'.replace('{newer}', meta.version).replace('{current}', version));
|
||||||
|
}
|
||||||
|
|
||||||
|
return meta.version;
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,7 @@ import messagingRoom from './messaging-room.vue';
|
||||||
import urlPreview from './url-preview.vue';
|
import urlPreview from './url-preview.vue';
|
||||||
import twitterSetting from './twitter-setting.vue';
|
import twitterSetting from './twitter-setting.vue';
|
||||||
import fileTypeIcon from './file-type-icon.vue';
|
import fileTypeIcon from './file-type-icon.vue';
|
||||||
|
import Switch from './switch.vue';
|
||||||
|
|
||||||
Vue.component('mk-signin', signin);
|
Vue.component('mk-signin', signin);
|
||||||
Vue.component('mk-signup', signup);
|
Vue.component('mk-signup', signup);
|
||||||
|
@ -41,3 +42,4 @@ Vue.component('mk-messaging-room', messagingRoom);
|
||||||
Vue.component('mk-url-preview', urlPreview);
|
Vue.component('mk-url-preview', urlPreview);
|
||||||
Vue.component('mk-twitter-setting', twitterSetting);
|
Vue.component('mk-twitter-setting', twitterSetting);
|
||||||
Vue.component('mk-file-type-icon', fileTypeIcon);
|
Vue.component('mk-file-type-icon', fileTypeIcon);
|
||||||
|
Vue.component('mk-switch', Switch);
|
||||||
|
|
170
src/web/app/common/views/components/switch.vue
Normal file
170
src/web/app/common/views/components/switch.vue
Normal file
|
@ -0,0 +1,170 @@
|
||||||
|
<template>
|
||||||
|
<div
|
||||||
|
class="mk-switch"
|
||||||
|
:class="{ disabled, checked }"
|
||||||
|
role="switch"
|
||||||
|
:aria-checked="checked"
|
||||||
|
:aria-disabled="disabled"
|
||||||
|
@click="switchValue"
|
||||||
|
@mouseover="mouseenter"
|
||||||
|
>
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
@change="handleChange"
|
||||||
|
ref="input"
|
||||||
|
:disabled="disabled"
|
||||||
|
@keydown.enter="switchValue"
|
||||||
|
>
|
||||||
|
<span class="button">
|
||||||
|
<span :style="{ transform }"></span>
|
||||||
|
</span>
|
||||||
|
<span class="label">
|
||||||
|
<span :aria-hidden="!checked">{{ text }}</span>
|
||||||
|
<p :aria-hidden="!checked">
|
||||||
|
<slot></slot>
|
||||||
|
</p>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import Vue from 'vue';
|
||||||
|
export default Vue.extend({
|
||||||
|
props: {
|
||||||
|
value: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
disabled: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
text: String
|
||||||
|
},/*
|
||||||
|
created() {
|
||||||
|
if (!~[true, false].indexOf(this.value)) {
|
||||||
|
this.$emit('input', false);
|
||||||
|
}
|
||||||
|
},*/
|
||||||
|
computed: {
|
||||||
|
checked(): boolean {
|
||||||
|
return this.value;
|
||||||
|
},
|
||||||
|
transform(): string {
|
||||||
|
return this.checked ? 'translate3d(20px, 0, 0)' : '';
|
||||||
|
}
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
value() {
|
||||||
|
(this.$refs.input as any).checked = this.checked;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
(this.$refs.input as any).checked = this.checked;
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
mouseenter() {
|
||||||
|
(this.$el).style.transition = 'all 0s';
|
||||||
|
},
|
||||||
|
handleChange() {
|
||||||
|
(this.$el).style.transition = 'all 0.3s';
|
||||||
|
this.$emit('input', !this.checked);
|
||||||
|
this.$emit('change', !this.checked);
|
||||||
|
this.$nextTick(() => {
|
||||||
|
// set input's checked property
|
||||||
|
// in case parent refuses to change component's value
|
||||||
|
(this.$refs.input as any).checked = this.checked;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
switchValue() {
|
||||||
|
!this.disabled && this.handleChange();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="stylus" scoped>
|
||||||
|
.mk-switch
|
||||||
|
display flex
|
||||||
|
cursor pointer
|
||||||
|
transition all 0.3s
|
||||||
|
|
||||||
|
> *
|
||||||
|
user-select none
|
||||||
|
|
||||||
|
&.disabled
|
||||||
|
opacity 0.6
|
||||||
|
cursor not-allowed
|
||||||
|
|
||||||
|
&.checked
|
||||||
|
> .button
|
||||||
|
background-color $theme-color
|
||||||
|
border-color $theme-color
|
||||||
|
|
||||||
|
> .label
|
||||||
|
> span
|
||||||
|
color $theme-color
|
||||||
|
|
||||||
|
&:hover
|
||||||
|
> .label
|
||||||
|
> span
|
||||||
|
color darken($theme-color, 10%)
|
||||||
|
|
||||||
|
> .button
|
||||||
|
background darken($theme-color, 10%)
|
||||||
|
border-color darken($theme-color, 10%)
|
||||||
|
|
||||||
|
&:hover
|
||||||
|
> .label
|
||||||
|
> span
|
||||||
|
color #2e3338
|
||||||
|
|
||||||
|
> .button
|
||||||
|
background #ced2da
|
||||||
|
border-color #ced2da
|
||||||
|
|
||||||
|
> input
|
||||||
|
position absolute
|
||||||
|
width 0
|
||||||
|
height 0
|
||||||
|
opacity 0
|
||||||
|
margin 0
|
||||||
|
|
||||||
|
> .button
|
||||||
|
display inline-block
|
||||||
|
margin 0
|
||||||
|
width 40px
|
||||||
|
height 20px
|
||||||
|
background #dcdfe6
|
||||||
|
border 1px solid #dcdfe6
|
||||||
|
outline none
|
||||||
|
border-radius 10px
|
||||||
|
transition inherit
|
||||||
|
|
||||||
|
> *
|
||||||
|
position absolute
|
||||||
|
top 1px
|
||||||
|
left 1px
|
||||||
|
border-radius 100%
|
||||||
|
transition transform 0.3s
|
||||||
|
width 16px
|
||||||
|
height 16px
|
||||||
|
background-color #fff
|
||||||
|
|
||||||
|
> .label
|
||||||
|
margin-left 8px
|
||||||
|
display block
|
||||||
|
font-size 14px
|
||||||
|
cursor pointer
|
||||||
|
transition inherit
|
||||||
|
|
||||||
|
> span
|
||||||
|
line-height 20px
|
||||||
|
color #4a535a
|
||||||
|
transition inherit
|
||||||
|
|
||||||
|
> p
|
||||||
|
margin 0
|
||||||
|
color #9daab3
|
||||||
|
|
||||||
|
</style>
|
|
@ -16,21 +16,28 @@ import Vue from 'vue';
|
||||||
import * as anime from 'animejs';
|
import * as anime from 'animejs';
|
||||||
|
|
||||||
export default Vue.extend({
|
export default Vue.extend({
|
||||||
props: ['title', 'text', 'buttons', 'modal']/*{
|
props: {
|
||||||
title: {
|
title: {
|
||||||
type: String
|
type: String,
|
||||||
|
required: false
|
||||||
},
|
},
|
||||||
text: {
|
text: {
|
||||||
type: String
|
type: String,
|
||||||
|
required: true
|
||||||
},
|
},
|
||||||
buttons: {
|
buttons: {
|
||||||
type: Array
|
type: Array,
|
||||||
|
default: () => {
|
||||||
|
return [{
|
||||||
|
text: 'OK'
|
||||||
|
}];
|
||||||
|
}
|
||||||
},
|
},
|
||||||
modal: {
|
modal: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: false
|
default: false
|
||||||
}
|
}
|
||||||
}*/,
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
this.$nextTick(() => {
|
this.$nextTick(() => {
|
||||||
(this.$refs.bg as any).style.pointerEvents = 'auto';
|
(this.$refs.bg as any).style.pointerEvents = 'auto';
|
||||||
|
|
|
@ -24,7 +24,7 @@
|
||||||
<button class="ui primary" @click="save">%i18n:desktop.tags.mk-profile-setting.save%</button>
|
<button class="ui primary" @click="save">%i18n:desktop.tags.mk-profile-setting.save%</button>
|
||||||
<section>
|
<section>
|
||||||
<h2>その他</h2>
|
<h2>その他</h2>
|
||||||
<el-switch v-model="os.i.is_bot" @change="onChangeIsBot" active-text="このアカウントはbotです"/>
|
<mk-switch v-model="os.i.is_bot" @change="onChangeIsBot" text="このアカウントはbotです"/>
|
||||||
</section>
|
</section>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -20,10 +20,18 @@
|
||||||
|
|
||||||
<section class="web" v-show="page == 'web'">
|
<section class="web" v-show="page == 'web'">
|
||||||
<h1>デザイン</h1>
|
<h1>デザイン</h1>
|
||||||
<div>
|
<div class="div">
|
||||||
<button class="ui button" @click="customizeHome">ホームをカスタマイズ</button>
|
<button class="ui button" @click="customizeHome">ホームをカスタマイズ</button>
|
||||||
</div>
|
</div>
|
||||||
<el-switch v-model="showPostFormOnTopOfTl" @change="onChangeShowPostFormOnTopOfTl" active-text="タイムライン上部に投稿フォームを表示する"/>
|
<mk-switch v-model="showPostFormOnTopOfTl" @change="onChangeShowPostFormOnTopOfTl" text="タイムライン上部に投稿フォームを表示する"/>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section class="web" v-show="page == 'web'">
|
||||||
|
<h1>キャッシュ</h1>
|
||||||
|
<button class="ui button" @click="clean">クリーンアップ</button>
|
||||||
|
<div class="none ui info">
|
||||||
|
<p>%fa:info-circle%クリーンアップを行うと、ブラウザに記憶されたアカウント情報のキャッシュ、書きかけの投稿・返信・メッセージ、およびその他のデータ(設定情報含む)が削除されます。クリーンアップを行った後はページを再度読み込みする必要があります。</p>
|
||||||
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section class="drive" v-show="page == 'drive'">
|
<section class="drive" v-show="page == 'drive'">
|
||||||
|
@ -66,6 +74,28 @@
|
||||||
<x-api/>
|
<x-api/>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
|
<section class="other" v-show="page == 'other'">
|
||||||
|
<h1>Misskey Update</h1>
|
||||||
|
<p>
|
||||||
|
<span>バージョン: <i>{{ version }}</i></span>
|
||||||
|
<template v-if="latestVersion !== undefined">
|
||||||
|
<br>
|
||||||
|
<span>最新のバージョン: <i>{{ latestVersion ? latestVersion : version }}</i></span>
|
||||||
|
</template>
|
||||||
|
</p>
|
||||||
|
<button class="ui button" @click="checkForUpdate" :disabled="checkingForUpdate">
|
||||||
|
<template v-if="checkingForUpdate">アップデートを確認中<mk-ellipsis/></template>
|
||||||
|
<template v-else>アップデートを確認</template>
|
||||||
|
</button>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section class="other" v-show="page == 'other'">
|
||||||
|
<h1>高度な設定</h1>
|
||||||
|
<mk-switch v-model="debug" text="デバッグモードを有効にする">
|
||||||
|
<span>この設定はアカウントに保存されません。</span>
|
||||||
|
</mk-switch>
|
||||||
|
</section>
|
||||||
|
|
||||||
<section class="other" v-show="page == 'other'">
|
<section class="other" v-show="page == 'other'">
|
||||||
<h1>%i18n:desktop.tags.mk-settings.license%</h1>
|
<h1>%i18n:desktop.tags.mk-settings.license%</h1>
|
||||||
<div v-html="license"></div>
|
<div v-html="license"></div>
|
||||||
|
@ -82,7 +112,8 @@ import XMute from './settings.mute.vue';
|
||||||
import XPassword from './settings.password.vue';
|
import XPassword from './settings.password.vue';
|
||||||
import X2fa from './settings.2fa.vue';
|
import X2fa from './settings.2fa.vue';
|
||||||
import XApi from './settings.api.vue';
|
import XApi from './settings.api.vue';
|
||||||
import { docsUrl, license, lang } from '../../../config';
|
import { docsUrl, license, lang, version } from '../../../config';
|
||||||
|
import checkForUpdate from '../../../common/scripts/check-for-update';
|
||||||
|
|
||||||
export default Vue.extend({
|
export default Vue.extend({
|
||||||
components: {
|
components: {
|
||||||
|
@ -96,9 +127,18 @@ export default Vue.extend({
|
||||||
return {
|
return {
|
||||||
page: 'profile',
|
page: 'profile',
|
||||||
license,
|
license,
|
||||||
showPostFormOnTopOfTl: false
|
version,
|
||||||
|
latestVersion: undefined,
|
||||||
|
checkingForUpdate: false,
|
||||||
|
showPostFormOnTopOfTl: false,
|
||||||
|
debug: localStorage.getItem('debug') == 'true'
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
watch: {
|
||||||
|
debug() {
|
||||||
|
localStorage.setItem('debug', this.debug ? 'true' : 'false');
|
||||||
|
}
|
||||||
|
},
|
||||||
computed: {
|
computed: {
|
||||||
licenseUrl(): string {
|
licenseUrl(): string {
|
||||||
return `${docsUrl}/${lang}/license`;
|
return `${docsUrl}/${lang}/license`;
|
||||||
|
@ -117,6 +157,31 @@ export default Vue.extend({
|
||||||
name: 'showPostFormOnTopOfTl',
|
name: 'showPostFormOnTopOfTl',
|
||||||
value: this.showPostFormOnTopOfTl
|
value: this.showPostFormOnTopOfTl
|
||||||
});
|
});
|
||||||
|
},
|
||||||
|
checkForUpdate() {
|
||||||
|
this.checkingForUpdate = true;
|
||||||
|
checkForUpdate((this as any).os, true, true).then(newer => {
|
||||||
|
this.checkingForUpdate = false;
|
||||||
|
this.latestVersion = newer;
|
||||||
|
if (newer == null) {
|
||||||
|
(this as any).apis.dialog({
|
||||||
|
title: '利用可能な更新はありません',
|
||||||
|
text: 'お使いのMisskeyは最新です。'
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
(this as any).apis.dialog({
|
||||||
|
title: '新しいバージョンが利用可能です',
|
||||||
|
text: 'ページを再度読み込みすると更新が適用されます。'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
clean() {
|
||||||
|
localStorage.clear();
|
||||||
|
(this as any).apis.dialog({
|
||||||
|
title: 'キャッシュを削除しました',
|
||||||
|
text: 'ページを再度読み込みしてください。'
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -184,7 +249,7 @@ export default Vue.extend({
|
||||||
border-bottom solid 1px #eee
|
border-bottom solid 1px #eee
|
||||||
|
|
||||||
> .web
|
> .web
|
||||||
> div
|
> .div
|
||||||
border-bottom solid 1px #eee
|
border-bottom solid 1px #eee
|
||||||
padding 0 0 16px 0
|
padding 0 0 16px 0
|
||||||
margin 0 0 16px 0
|
margin 0 0 16px 0
|
||||||
|
|
Loading…
Reference in a new issue