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: {
|
||||
title: string;
|
||||
text: string;
|
||||
actions: Array<{
|
||||
actions?: Array<{
|
||||
text: string;
|
||||
id?: string;
|
||||
}>;
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
import MiOS from '../mios';
|
||||
import { version } from '../../config';
|
||||
|
||||
export default async function(mios: MiOS) {
|
||||
const meta = await mios.getMeta();
|
||||
export default async function(mios: MiOS, force = false, silent = false) {
|
||||
const meta = await mios.getMeta(force);
|
||||
|
||||
if (meta.version != version) {
|
||||
localStorage.setItem('should-refresh', 'true');
|
||||
|
@ -20,6 +20,12 @@ export default async function(mios: MiOS) {
|
|||
console.error(e);
|
||||
}
|
||||
|
||||
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 twitterSetting from './twitter-setting.vue';
|
||||
import fileTypeIcon from './file-type-icon.vue';
|
||||
import Switch from './switch.vue';
|
||||
|
||||
Vue.component('mk-signin', signin);
|
||||
Vue.component('mk-signup', signup);
|
||||
|
@ -41,3 +42,4 @@ Vue.component('mk-messaging-room', messagingRoom);
|
|||
Vue.component('mk-url-preview', urlPreview);
|
||||
Vue.component('mk-twitter-setting', twitterSetting);
|
||||
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';
|
||||
|
||||
export default Vue.extend({
|
||||
props: ['title', 'text', 'buttons', 'modal']/*{
|
||||
props: {
|
||||
title: {
|
||||
type: String
|
||||
type: String,
|
||||
required: false
|
||||
},
|
||||
text: {
|
||||
type: String
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
buttons: {
|
||||
type: Array
|
||||
type: Array,
|
||||
default: () => {
|
||||
return [{
|
||||
text: 'OK'
|
||||
}];
|
||||
}
|
||||
},
|
||||
modal: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
}*/,
|
||||
},
|
||||
mounted() {
|
||||
this.$nextTick(() => {
|
||||
(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>
|
||||
<section>
|
||||
<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>
|
||||
</div>
|
||||
</template>
|
||||
|
|
|
@ -20,10 +20,18 @@
|
|||
|
||||
<section class="web" v-show="page == 'web'">
|
||||
<h1>デザイン</h1>
|
||||
<div>
|
||||
<div class="div">
|
||||
<button class="ui button" @click="customizeHome">ホームをカスタマイズ</button>
|
||||
</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 class="drive" v-show="page == 'drive'">
|
||||
|
@ -66,6 +74,28 @@
|
|||
<x-api/>
|
||||
</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'">
|
||||
<h1>%i18n:desktop.tags.mk-settings.license%</h1>
|
||||
<div v-html="license"></div>
|
||||
|
@ -82,7 +112,8 @@ import XMute from './settings.mute.vue';
|
|||
import XPassword from './settings.password.vue';
|
||||
import X2fa from './settings.2fa.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({
|
||||
components: {
|
||||
|
@ -96,9 +127,18 @@ export default Vue.extend({
|
|||
return {
|
||||
page: 'profile',
|
||||
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: {
|
||||
licenseUrl(): string {
|
||||
return `${docsUrl}/${lang}/license`;
|
||||
|
@ -117,6 +157,31 @@ export default Vue.extend({
|
|||
name: '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
|
||||
|
||||
> .web
|
||||
> div
|
||||
> .div
|
||||
border-bottom solid 1px #eee
|
||||
padding 0 0 16px 0
|
||||
margin 0 0 16px 0
|
||||
|
|
Loading…
Reference in a new issue