summaryrefslogtreecommitdiff
path: root/src/web/app
diff options
context:
space:
mode:
authorsyuilo <syuilotan@yahoo.co.jp>2018-03-02 18:46:08 +0900
committersyuilo <syuilotan@yahoo.co.jp>2018-03-02 18:46:08 +0900
commitd10be711613a897e0c4356993ea98af81b1c0c0e (patch)
treef15fa90ac5647c7076e2b4fcc36e27cd00f424c8 /src/web/app
parentoops (diff)
downloadmisskey-d10be711613a897e0c4356993ea98af81b1c0c0e.tar.gz
misskey-d10be711613a897e0c4356993ea98af81b1c0c0e.tar.bz2
misskey-d10be711613a897e0c4356993ea98af81b1c0c0e.zip
#1161, #1163
Diffstat (limited to 'src/web/app')
-rw-r--r--src/web/app/common/mios.ts2
-rw-r--r--src/web/app/common/scripts/check-for-update.ts12
-rw-r--r--src/web/app/common/views/components/index.ts2
-rw-r--r--src/web/app/common/views/components/switch.vue170
-rw-r--r--src/web/app/desktop/views/components/dialog.vue17
-rw-r--r--src/web/app/desktop/views/components/settings.profile.vue2
-rw-r--r--src/web/app/desktop/views/components/settings.vue75
7 files changed, 265 insertions, 15 deletions
diff --git a/src/web/app/common/mios.ts b/src/web/app/common/mios.ts
index 6cc441cd1d..3701a24c30 100644
--- a/src/web/app/common/mios.ts
+++ b/src/web/app/common/mios.ts
@@ -27,7 +27,7 @@ export type API = {
dialog: (opts: {
title: string;
text: string;
- actions: Array<{
+ actions?: Array<{
text: string;
id?: string;
}>;
diff --git a/src/web/app/common/scripts/check-for-update.ts b/src/web/app/common/scripts/check-for-update.ts
index fe539407da..3e7eb79d8b 100644
--- a/src/web/app/common/scripts/check-for-update.ts
+++ b/src/web/app/common/scripts/check-for-update.ts
@@ -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);
}
- 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;
}
}
diff --git a/src/web/app/common/views/components/index.ts b/src/web/app/common/views/components/index.ts
index ab0f1767d4..5274920228 100644
--- a/src/web/app/common/views/components/index.ts
+++ b/src/web/app/common/views/components/index.ts
@@ -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);
diff --git a/src/web/app/common/views/components/switch.vue b/src/web/app/common/views/components/switch.vue
new file mode 100644
index 0000000000..fc12e00540
--- /dev/null
+++ b/src/web/app/common/views/components/switch.vue
@@ -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>
diff --git a/src/web/app/desktop/views/components/dialog.vue b/src/web/app/desktop/views/components/dialog.vue
index 28f22f7b62..e89e8654e6 100644
--- a/src/web/app/desktop/views/components/dialog.vue
+++ b/src/web/app/desktop/views/components/dialog.vue
@@ -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';
diff --git a/src/web/app/desktop/views/components/settings.profile.vue b/src/web/app/desktop/views/components/settings.profile.vue
index 218da67e81..b57ac10287 100644
--- a/src/web/app/desktop/views/components/settings.profile.vue
+++ b/src/web/app/desktop/views/components/settings.profile.vue
@@ -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>
diff --git a/src/web/app/desktop/views/components/settings.vue b/src/web/app/desktop/views/components/settings.vue
index b65623e33a..4a9db5f48b 100644
--- a/src/web/app/desktop/views/components/settings.vue
+++ b/src/web/app/desktop/views/components/settings.vue
@@ -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'">
@@ -67,6 +75,28 @@
</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>
<a :href="licenseUrl" target="_blank">サードパーティ</a>
@@ -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