summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorsyuilo <Syuilotan@yahoo.co.jp>2018-10-19 06:18:33 +0900
committerGitHub <noreply@github.com>2018-10-19 06:18:33 +0900
commitfef4f7fce81d5aca76a8c45713c76c0c482884e7 (patch)
tree87f460732361921860ac40b2130430014fce6e58 /src
parentMerge pull request #2929 from syuilo/l10n_develop (diff)
downloadsharkey-fef4f7fce81d5aca76a8c45713c76c0c482884e7.tar.gz
sharkey-fef4f7fce81d5aca76a8c45713c76c0c482884e7.tar.bz2
sharkey-fef4f7fce81d5aca76a8c45713c76c0c482884e7.zip
#2930 (#2933)
* wip * wip * Clean up * wip * wip * wip * wip * wip * wip * wip * wip * :art: * wip * wip
Diffstat (limited to 'src')
-rw-r--r--src/client/app/common/views/components/index.ts2
-rw-r--r--src/client/app/common/views/components/profile-editor.vue (renamed from src/client/app/mobile/views/pages/settings/settings.profile.vue)6
-rw-r--r--src/client/app/common/views/components/ui/input.vue20
-rw-r--r--src/client/app/common/views/widgets/photo-stream.vue3
-rw-r--r--src/client/app/desktop/script.ts4
-rw-r--r--src/client/app/desktop/views/components/note-detail.vue2
-rw-r--r--src/client/app/desktop/views/components/note.sub.vue (renamed from src/client/app/desktop/views/components/notes.note.sub.vue)17
-rw-r--r--src/client/app/desktop/views/components/note.vue (renamed from src/client/app/desktop/views/components/notes.note.vue)86
-rw-r--r--src/client/app/desktop/views/components/notes.vue2
-rw-r--r--src/client/app/desktop/views/components/settings.2fa.vue6
-rw-r--r--src/client/app/desktop/views/components/settings.api.vue6
-rw-r--r--src/client/app/desktop/views/components/settings.password.vue2
-rw-r--r--src/client/app/desktop/views/components/settings.profile.vue106
-rw-r--r--src/client/app/desktop/views/components/settings.vue423
-rw-r--r--src/client/app/desktop/views/pages/deck/deck.column.vue54
-rw-r--r--src/client/app/desktop/views/pages/deck/deck.note-column.vue69
-rw-r--r--src/client/app/desktop/views/pages/deck/deck.note.sub.vue71
-rw-r--r--src/client/app/desktop/views/pages/deck/deck.note.vue323
-rw-r--r--src/client/app/desktop/views/pages/deck/deck.notes.vue6
-rw-r--r--src/client/app/desktop/views/pages/deck/deck.notification.vue8
-rw-r--r--src/client/app/desktop/views/pages/deck/deck.user-column.vue261
-rw-r--r--src/client/app/desktop/views/pages/deck/deck.vue45
-rw-r--r--src/client/app/desktop/views/pages/user/user.photos.vue3
-rw-r--r--src/client/app/init.ts13
-rw-r--r--src/client/app/mobile/views/pages/settings.vue8
-rw-r--r--src/client/app/store.ts11
-rw-r--r--src/client/theme/dark.json51
-rw-r--r--src/client/theme/light.json51
28 files changed, 785 insertions, 774 deletions
diff --git a/src/client/app/common/views/components/index.ts b/src/client/app/common/views/components/index.ts
index e2b9089d35..0dd013807c 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 profileEditor from './profile-editor.vue';
import noteSkeleton from './note-skeleton.vue';
import theme from './theme.vue';
import instance from './instance.vue';
@@ -45,6 +46,7 @@ import uiSelect from './ui/select.vue';
import formButton from './ui/form/button.vue';
import formRadio from './ui/form/radio.vue';
+Vue.component('mk-profile-editor', profileEditor);
Vue.component('mk-note-skeleton', noteSkeleton);
Vue.component('mk-theme', theme);
Vue.component('mk-instance', instance);
diff --git a/src/client/app/mobile/views/pages/settings/settings.profile.vue b/src/client/app/common/views/components/profile-editor.vue
index 160a05a3e0..10bdc0b579 100644
--- a/src/client/app/mobile/views/pages/settings/settings.profile.vue
+++ b/src/client/app/common/views/components/profile-editor.vue
@@ -49,6 +49,7 @@
<div>
<ui-switch v-model="isCat" @change="save(false)">%i18n:@is-cat%</ui-switch>
+ <ui-switch v-model="isBot" @change="save(false)">%i18n:@is-bot%</ui-switch>
<ui-switch v-model="alwaysMarkNsfw">%i18n:common.always-mark-nsfw%</ui-switch>
</div>
</section>
@@ -66,7 +67,7 @@
<script lang="ts">
import Vue from 'vue';
-import { apiUrl, host } from '../../../../config';
+import { apiUrl, host } from '../../../config';
export default Vue.extend({
data() {
@@ -80,6 +81,7 @@ export default Vue.extend({
avatarId: null,
bannerId: null,
isCat: false,
+ isBot: false,
isLocked: false,
carefulBot: false,
saving: false,
@@ -104,6 +106,7 @@ export default Vue.extend({
this.avatarId = this.$store.state.i.avatarId;
this.bannerId = this.$store.state.i.bannerId;
this.isCat = this.$store.state.i.isCat;
+ this.isBot = this.$store.state.i.isBot;
this.isLocked = this.$store.state.i.isLocked;
this.carefulBot = this.$store.state.i.carefulBot;
},
@@ -164,6 +167,7 @@ export default Vue.extend({
avatarId: this.avatarId,
bannerId: this.bannerId,
isCat: this.isCat,
+ isBot: this.isBot,
isLocked: this.isLocked,
carefulBot: this.carefulBot
}).then(i => {
diff --git a/src/client/app/common/views/components/ui/input.vue b/src/client/app/common/views/components/ui/input.vue
index abbd5a2feb..7e1a16bb3f 100644
--- a/src/client/app/common/views/components/ui/input.vue
+++ b/src/client/app/common/views/components/ui/input.vue
@@ -122,17 +122,19 @@ export default Vue.extend({
}
},
mounted() {
- if (this.$refs.prefix) {
- this.$refs.label.style.left = (this.$refs.prefix.offsetLeft + this.$refs.prefix.offsetWidth) + 'px';
- if (this.$refs.prefix.offsetWidth) {
- this.$refs.input.style.paddingLeft = this.$refs.prefix.offsetWidth + 'px';
+ this.$nextTick(() => {
+ if (this.$refs.prefix) {
+ this.$refs.label.style.left = (this.$refs.prefix.offsetLeft + this.$refs.prefix.offsetWidth) + 'px';
+ if (this.$refs.prefix.offsetWidth) {
+ this.$refs.input.style.paddingLeft = this.$refs.prefix.offsetWidth + 'px';
+ }
}
- }
- if (this.$refs.suffix) {
- if (this.$refs.suffix.offsetWidth) {
- this.$refs.input.style.paddingRight = this.$refs.suffix.offsetWidth + 'px';
+ if (this.$refs.suffix) {
+ if (this.$refs.suffix.offsetWidth) {
+ this.$refs.input.style.paddingRight = this.$refs.suffix.offsetWidth + 'px';
+ }
}
- }
+ });
},
methods: {
focus() {
diff --git a/src/client/app/common/views/widgets/photo-stream.vue b/src/client/app/common/views/widgets/photo-stream.vue
index 047b01df4f..02cb9204b5 100644
--- a/src/client/app/common/views/widgets/photo-stream.vue
+++ b/src/client/app/common/views/widgets/photo-stream.vue
@@ -73,9 +73,6 @@ export default define({
border-radius 8px
.stream
- display -webkit-flex
- display -moz-flex
- display -ms-flex
display flex
justify-content center
flex-wrap wrap
diff --git a/src/client/app/desktop/script.ts b/src/client/app/desktop/script.ts
index 85c81d73a2..3c9003cbe7 100644
--- a/src/client/app/desktop/script.ts
+++ b/src/client/app/desktop/script.ts
@@ -67,8 +67,8 @@ init(async (launch) => {
{ path: '/tags/:tag', component: MkTag },
{ path: '/share', component: MkShare },
{ path: '/reversi/:game?', component: MkReversi },
- { path: '/@:user', component: MkUser },
- { path: '/notes/:note', component: MkNote },
+ { path: '/@:user', name: 'user', component: MkUser },
+ { path: '/notes/:note', name: 'note', component: MkNote },
{ path: '/authorize-follow', component: MkFollow }
]
});
diff --git a/src/client/app/desktop/views/components/note-detail.vue b/src/client/app/desktop/views/components/note-detail.vue
index b119f23d7a..dce5b12615 100644
--- a/src/client/app/desktop/views/components/note-detail.vue
+++ b/src/client/app/desktop/views/components/note-detail.vue
@@ -91,7 +91,7 @@ import MkPostFormWindow from './post-form-window.vue';
import MkRenoteFormWindow from './renote-form-window.vue';
import MkNoteMenu from '../../../common/views/components/note-menu.vue';
import MkReactionPicker from '../../../common/views/components/reaction-picker.vue';
-import XSub from './notes.note.sub.vue';
+import XSub from './note.sub.vue';
import { sum } from '../../../../../prelude/array';
import noteSubscriber from '../../../common/scripts/note-subscriber';
diff --git a/src/client/app/desktop/views/components/notes.note.sub.vue b/src/client/app/desktop/views/components/note.sub.vue
index ee52670f8f..5ba22fc76f 100644
--- a/src/client/app/desktop/views/components/notes.note.sub.vue
+++ b/src/client/app/desktop/views/components/note.sub.vue
@@ -1,5 +1,5 @@
<template>
-<div class="tkfdzaxtkdeianobciwadajxzbddorql" :title="title">
+<div class="tkfdzaxtkdeianobciwadajxzbddorql" :class="{ mini }" :title="title">
<mk-avatar class="avatar" :user="note.user"/>
<div class="main">
<mk-note-header class="header" :note="note"/>
@@ -24,6 +24,11 @@ export default Vue.extend({
note: {
type: Object,
required: true
+ },
+ mini: {
+ type: Boolean,
+ required: false,
+ default: false
}
},
@@ -44,11 +49,19 @@ export default Vue.extend({
<style lang="stylus" scoped>
.tkfdzaxtkdeianobciwadajxzbddorql
display flex
- margin 0
padding 16px 32px
font-size 0.9em
background var(--subNoteBg)
+ &.mini
+ padding 16px
+ font-size 10px
+
+ > .avatar
+ margin 0 8px 0 0
+ width 38px
+ height 38px
+
> .avatar
flex-shrink 0
display block
diff --git a/src/client/app/desktop/views/components/notes.note.vue b/src/client/app/desktop/views/components/note.vue
index 7714557ae7..7fa423b19b 100644
--- a/src/client/app/desktop/views/components/notes.note.vue
+++ b/src/client/app/desktop/views/components/note.vue
@@ -1,7 +1,17 @@
<template>
-<div class="note" v-show="appearNote.deletedAt == null" :tabindex="appearNote.deletedAt == null ? '-1' : null" v-hotkey="keymap" :title="title">
+<div
+ class="note"
+ :class="{ mini }"
+ v-show="appearNote.deletedAt == null"
+ :tabindex="appearNote.deletedAt == null ? '-1' : null"
+ v-hotkey="keymap"
+ :title="title"
+>
+ <div class="conversation" v-if="detail && conversation.length > 0">
+ <x-sub v-for="note in conversation" :key="note.id" :note="note" :mini="mini"/>
+ </div>
<div class="reply-to" v-if="appearNote.reply && (!$store.getters.isSignedIn || $store.state.settings.showReplyTarget)">
- <x-sub :note="appearNote.reply"/>
+ <x-sub :note="appearNote.reply" :mini="mini"/>
</div>
<div class="renote" v-if="isRenote">
<mk-avatar class="avatar" :user="note.user"/>
@@ -32,8 +42,8 @@
</div>
<mk-poll v-if="appearNote.poll" :note="appearNote" ref="pollViewer"/>
<a class="location" v-if="appearNote.geo" :href="`https://maps.google.com/maps?q=${appearNote.geo.coordinates[1]},${appearNote.geo.coordinates[0]}`" target="_blank">%fa:map-marker-alt% 位置情報</a>
- <div class="renote" v-if="appearNote.renote"><mk-note-preview :note="appearNote.renote"/></div>
- <mk-url-preview v-for="url in urls" :url="url" :key="url"/>
+ <div class="renote" v-if="appearNote.renote"><mk-note-preview :note="appearNote.renote" :mini="mini"/></div>
+ <mk-url-preview v-for="url in urls" :url="url" :key="url" :mini="mini"/>
</div>
</div>
<footer>
@@ -55,15 +65,16 @@
</footer>
</div>
</article>
+ <div class="replies" v-if="detail && replies.length > 0">
+ <x-sub v-for="note in replies" :key="note.id" :note="note" :mini="mini"/>
+ </div>
</div>
</template>
<script lang="ts">
import Vue from 'vue';
-import MkPostFormWindow from './post-form-window.vue';
-import MkRenoteFormWindow from './renote-form-window.vue';
-import XSub from './notes.note.sub.vue';
+import XSub from './note.sub.vue';
import noteMixin from '../../../common/scripts/note-mixin';
import noteSubscriber from '../../../common/scripts/note-subscriber';
@@ -81,6 +92,40 @@ export default Vue.extend({
note: {
type: Object,
required: true
+ },
+ detail: {
+ type: Boolean,
+ required: false,
+ default: false
+ },
+ mini: {
+ type: Boolean,
+ required: false,
+ default: false
+ }
+ },
+
+ data() {
+ return {
+ conversation: [],
+ replies: []
+ };
+ },
+
+ created() {
+ if (this.detail) {
+ (this as any).api('notes/replies', {
+ noteId: this.appearNote.id,
+ limit: 8
+ }).then(replies => {
+ this.replies = replies;
+ });
+
+ (this as any).api('notes/conversation', {
+ noteId: this.appearNote.replyId
+ }).then(conversation => {
+ this.conversation = conversation.reverse();
+ });
}
}
});
@@ -93,14 +138,23 @@ export default Vue.extend({
background var(--face)
border-bottom solid 1px var(--faceDivider)
- &[data-round]
- &:first-child
- border-top-left-radius 6px
- border-top-right-radius 6px
+ &.mini
+ font-size 13px
+
+ > .renote
+ padding 8px 16px 0 16px
+
+ .avatar
+ width 20px
+ height 20px
- > .renote
- border-top-left-radius 6px
- border-top-right-radius 6px
+ > article
+ padding 16px 16px 4px
+
+ > .avatar
+ margin 0 10px 8px 0
+ width 42px
+ height 42px
&:last-of-type
border-bottom none
@@ -129,6 +183,7 @@ export default Vue.extend({
background linear-gradient(to bottom, var(--renoteGradient) 0%, var(--face) 100%)
.avatar
+ flex-shrink 0
display inline-block
width 28px
height 28px
@@ -273,6 +328,9 @@ export default Vue.extend({
border none
cursor pointer
+ &:last-child
+ margin-right 0
+
&:hover
color var(--noteActionsHover)
diff --git a/src/client/app/desktop/views/components/notes.vue b/src/client/app/desktop/views/components/notes.vue
index 219fd5db60..768dd4f9d1 100644
--- a/src/client/app/desktop/views/components/notes.vue
+++ b/src/client/app/desktop/views/components/notes.vue
@@ -40,7 +40,7 @@ import Vue from 'vue';
import * as config from '../../../config';
import getNoteSummary from '../../../../../misc/get-note-summary';
-import XNote from './notes.note.vue';
+import XNote from './note.vue';
const displayLimit = 30;
diff --git a/src/client/app/desktop/views/components/settings.2fa.vue b/src/client/app/desktop/views/components/settings.2fa.vue
index 3e8c860eba..98e73a95b3 100644
--- a/src/client/app/desktop/views/components/settings.2fa.vue
+++ b/src/client/app/desktop/views/components/settings.2fa.vue
@@ -2,10 +2,10 @@
<div class="2fa">
<p>%i18n:@intro%<a href="%i18n:@url%" target="_blank">%i18n:@detail%</a></p>
<div class="ui info warn"><p>%fa:exclamation-triangle%%i18n:@caution%</p></div>
- <p v-if="!data && !$store.state.i.twoFactorEnabled"><button @click="register" class="ui primary">%i18n:@register%</button></p>
+ <p v-if="!data && !$store.state.i.twoFactorEnabled"><ui-button @click="register">%i18n:@register%</ui-button></p>
<template v-if="$store.state.i.twoFactorEnabled">
<p>%i18n:@already-registered%</p>
- <button @click="unregister" class="ui">%i18n:@unregister%</button>
+ <ui-button @click="unregister">%i18n:@unregister%</ui-button>
</template>
<div v-if="data">
<ol>
@@ -13,7 +13,7 @@
<li>%i18n:@scan%<br><img :src="data.qr"></li>
<li>%i18n:@done%<br>
<input type="number" v-model="token" class="ui">
- <button @click="submit" class="ui primary">%i18n:@submit%</button>
+ <ui-button primary @click="submit">%i18n:@submit%</ui-button>
</li>
</ol>
<div class="ui info"><p>%fa:info-circle%%i18n:@info%</p></div>
diff --git a/src/client/app/desktop/views/components/settings.api.vue b/src/client/app/desktop/views/components/settings.api.vue
index 113764c3e1..f0103b5d43 100644
--- a/src/client/app/desktop/views/components/settings.api.vue
+++ b/src/client/app/desktop/views/components/settings.api.vue
@@ -1,10 +1,12 @@
<template>
<div class="root api">
- <p>%i18n:@token% <code>{{ $store.state.i.token }}</code></p>
+ <ui-input :value="$store.state.i.token" readonly>
+ <span>%i18n:@token%</span>
+ </ui-input>
<p>%i18n:@intro%</p>
<div class="ui info warn"><p>%fa:exclamation-triangle%%i18n:@caution%</p></div>
<p>%i18n:@regeneration-of-token%</p>
- <button class="ui" @click="regenerateToken">%i18n:@regenerate-token%</button>
+ <ui-button @click="regenerateToken">%i18n:@regenerate-token%</ui-button>
</div>
</template>
diff --git a/src/client/app/desktop/views/components/settings.password.vue b/src/client/app/desktop/views/components/settings.password.vue
index 39896daf67..82b163f1fa 100644
--- a/src/client/app/desktop/views/components/settings.password.vue
+++ b/src/client/app/desktop/views/components/settings.password.vue
@@ -1,6 +1,6 @@
<template>
<div>
- <button @click="reset" class="ui primary">%i18n:@reset%</button>
+ <ui-button @click="reset">%i18n:@reset%</ui-button>
</div>
</template>
diff --git a/src/client/app/desktop/views/components/settings.profile.vue b/src/client/app/desktop/views/components/settings.profile.vue
deleted file mode 100644
index 15569d3694..0000000000
--- a/src/client/app/desktop/views/components/settings.profile.vue
+++ /dev/null
@@ -1,106 +0,0 @@
-<template>
-<div class="profile">
- <label class="avatar ui from group">
- <p>%i18n:@avatar%</p>
- <img class="avatar" :src="$store.state.i.avatarUrl" alt="avatar"/>
- <button class="ui" @click="updateAvatar">%i18n:@choice-avatar%</button>
- </label>
- <label class="ui from group">
- <ui-input v-model="name" type="text">%i18n:@name%</ui-input>
- </label>
- <label class="ui from group">
- <ui-input v-model="location" type="text">%i18n:@location%</ui-input>
- </label>
- <label class="ui from group">
- <ui-textarea v-model="description">%i18n:@description%</ui-textarea>
- </label>
- <label class="ui from group">
- <p>%i18n:@birthday%</p>
- <input type="date" v-model="birthday"/>
- </label>
- <ui-button primary @click="save">%i18n:@save%</ui-button>
- <section>
- <h2>%i18n:@locked-account%</h2>
- <ui-switch v-model="isLocked" @change="save(false)">%i18n:@is-locked%</ui-switch>
- <ui-switch v-model="carefulBot" @change="save(false)">%i18n:@careful-bot%</ui-switch>
- </section>
- <section>
- <h2>%i18n:@other%</h2>
- <ui-switch v-model="isBot" @change="save(false)">%i18n:@is-bot%</ui-switch>
- <ui-switch v-model="isCat" @change="save(false)">%i18n:@is-cat%</ui-switch>
- <ui-switch v-model="alwaysMarkNsfw">%i18n:common.always-mark-nsfw%</ui-switch>
- </section>
-</div>
-</template>
-
-<script lang="ts">
-import Vue from 'vue';
-
-export default Vue.extend({
- data() {
- return {
- name: null,
- location: null,
- description: null,
- birthday: null,
- isBot: false,
- isCat: false,
- isLocked: false,
- carefulBot: false,
- };
- },
- computed: {
- alwaysMarkNsfw: {
- get() { return this.$store.state.i.settings.alwaysMarkNsfw; },
- set(value) { (this as any).api('i/update', { alwaysMarkNsfw: value }); }
- },
- },
- created() {
- this.name = this.$store.state.i.name || '';
- this.location = this.$store.state.i.profile.location;
- this.description = this.$store.state.i.description;
- this.birthday = this.$store.state.i.profile.birthday;
- this.isCat = this.$store.state.i.isCat;
- this.isBot = this.$store.state.i.isBot;
- this.isLocked = this.$store.state.i.isLocked;
- this.carefulBot = this.$store.state.i.carefulBot;
- },
- methods: {
- updateAvatar() {
- (this as any).apis.updateAvatar();
- },
- save(notify) {
- (this as any).api('i/update', {
- name: this.name || null,
- location: this.location || null,
- description: this.description || null,
- birthday: this.birthday || null,
- isCat: this.isCat,
- isBot: this.isBot,
- isLocked: this.isLocked,
- carefulBot: this.carefulBot
- }).then(() => {
- if (notify) {
- (this as any).apis.notify('%i18n:@profile-updated%');
- }
- });
- }
- }
-});
-</script>
-
-<style lang="stylus" scoped>
-.profile
- > .avatar
- > img
- display inline-block
- vertical-align top
- width 64px
- height 64px
- border-radius 4px
-
- > button
- margin-left 8px
-
-</style>
-
diff --git a/src/client/app/desktop/views/components/settings.vue b/src/client/app/desktop/views/components/settings.vue
index 778302a7a5..1a8cb6b0b9 100644
--- a/src/client/app/desktop/views/components/settings.vue
+++ b/src/client/app/desktop/views/components/settings.vue
@@ -2,38 +2,59 @@
<div class="mk-settings">
<div class="nav">
<p :class="{ active: page == 'profile' }" @mousedown="page = 'profile'">%fa:user .fw%%i18n:@profile%</p>
+ <p :class="{ active: page == 'theme' }" @mousedown="page = 'theme'">%fa:palette .fw%%i18n:@theme%</p>
<p :class="{ active: page == 'web' }" @mousedown="page = 'web'">%fa:desktop .fw%Web</p>
<p :class="{ active: page == 'notification' }" @mousedown="page = 'notification'">%fa:R bell .fw%%i18n:@notification%</p>
<p :class="{ active: page == 'drive' }" @mousedown="page = 'drive'">%fa:cloud .fw%%i18n:@drive%</p>
<p :class="{ active: page == 'hashtags' }" @mousedown="page = 'hashtags'">%fa:hashtag .fw%%i18n:@tags%</p>
<p :class="{ active: page == 'mute' }" @mousedown="page = 'mute'">%fa:ban .fw%%i18n:@mute%</p>
<p :class="{ active: page == 'apps' }" @mousedown="page = 'apps'">%fa:puzzle-piece .fw%%i18n:@apps%</p>
- <p :class="{ active: page == 'twitter' }" @mousedown="page = 'twitter'">%fa:B twitter .fw%Twitter</p>
<p :class="{ active: page == 'security' }" @mousedown="page = 'security'">%fa:unlock-alt .fw%%i18n:@security%</p>
<p :class="{ active: page == 'api' }" @mousedown="page = 'api'">%fa:key .fw%API</p>
<p :class="{ active: page == 'other' }" @mousedown="page = 'other'">%fa:cogs .fw%%i18n:@other%</p>
</div>
<div class="pages">
- <section class="profile" v-show="page == 'profile'">
- <h1>%i18n:@profile%</h1>
- <x-profile/>
- </section>
+ <div class="profile" v-show="page == 'profile'">
+ <mk-profile-editor/>
- <section class="web" v-show="page == 'web'">
- <h1>%i18n:@theme%</h1>
- <mk-theme/>
- </section>
+ <ui-card>
+ <div slot="title">%fa:B twitter% %i18n:@twitter%</div>
+ <section>
+ <mk-twitter-setting/>
+ </section>
+ </ui-card>
+ </div>
+
+ <ui-card class="theme" v-show="page == 'theme'">
+ <div slot="title">%fa:palette% %i18n:@theme%</div>
+
+ <section>
+ <mk-theme/>
+ </section>
+ </ui-card>
+
+ <ui-card class="web" v-show="page == 'web'">
+ <div slot="title">%fa:sliders-h% %i18n:@behaviour%</div>
+
+ <section>
+ <ui-switch v-model="fetchOnScroll">
+ %i18n:@fetch-on-scroll%
+ <span slot="desc">%i18n:@fetch-on-scroll-desc%</span>
+ </ui-switch>
+ <ui-switch v-model="autoPopout">
+ %i18n:@auto-popout%
+ <span slot="desc">%i18n:@auto-popout-desc%</span>
+ </ui-switch>
+ <ui-switch v-model="deckNav">%i18n:@deck-nav%<span slot="desc">%i18n:@deck-nav-desc%</span></ui-switch>
- <section class="web" v-show="page == 'web'">
- <h1>%i18n:@behaviour%</h1>
- <ui-switch v-model="fetchOnScroll">
- %i18n:@fetch-on-scroll%
- <span slot="desc">%i18n:@fetch-on-scroll-desc%</span>
- </ui-switch>
- <ui-switch v-model="autoPopout">
- %i18n:@auto-popout%
- <span slot="desc">%i18n:@auto-popout-desc%</span>
- </ui-switch>
+ <details>
+ <summary>%i18n:@advanced%</summary>
+ <ui-switch v-model="apiViaStream">
+ %i18n:@api-via-stream%
+ <span slot="desc">%i18n:@api-via-stream-desc%</span>
+ </ui-switch>
+ </details>
+ </section>
<section>
<header>%i18n:@note-visibility%</header>
@@ -49,24 +70,26 @@
</ui-select>
</section>
</section>
+ </ui-card>
- <details>
- <summary>%i18n:@advanced%</summary>
- <ui-switch v-model="apiViaStream">
- %i18n:@api-via-stream%
- <span slot="desc">%i18n:@api-via-stream-desc%</span>
- </ui-switch>
- </details>
- </section>
+ <ui-card class="web" v-show="page == 'web'">
+ <div slot="title">%fa:desktop% %i18n:@display%</div>
- <section class="web" v-show="page == 'web'">
- <h1>%i18n:@display%</h1>
- <div class="div">
- <button class="ui button" @click="customizeHome" style="margin-bottom: 16px">%i18n:@customize%</button>
- </div>
- <div class="div">
- <button class="ui" @click="updateWallpaper">%i18n:@choose-wallpaper%</button>
- <button class="ui" @click="deleteWallpaper">%i18n:@delete-wallpaper%</button>
+ <section>
+ <ui-button @click="customizeHome">%i18n:@customize%</ui-button>
+ </section>
+ <section>
+ <header>%i18n:@wallpaper%</header>
+ <ui-button @click="updateWallpaper">%i18n:@choose-wallpaper%</ui-button>
+ <ui-button @click="deleteWallpaper">%i18n:@delete-wallpaper%</ui-button>
+ </section>
+ <section>
+ <header>%i18n:@navbar-position%</header>
+ <ui-radio v-model="navbar" value="top">%i18n:@navbar-position-top%</ui-radio>
+ <ui-radio v-model="navbar" value="left">%i18n:@navbar-position-left%</ui-radio>
+ <ui-radio v-model="navbar" value="right">%i18n:@navbar-position-right%</ui-radio>
+ </section>
+ <section>
<ui-switch v-model="darkmode">%i18n:@dark-mode%</ui-switch>
<ui-switch v-model="useShadow">%i18n:@use-shadow%</ui-switch>
<ui-switch v-model="roundedCorners">%i18n:@rounded-corners%</ui-switch>
@@ -75,171 +98,186 @@
<ui-switch v-model="contrastedAcct">%i18n:@contrasted-acct%</ui-switch>
<ui-switch v-model="showFullAcct">%i18n:common.show-full-acct%</ui-switch>
<ui-switch v-model="iLikeSushi">%i18n:common.i-like-sushi%</ui-switch>
- </div>
- <ui-switch v-model="showPostFormOnTopOfTl">%i18n:@post-form-on-timeline%</ui-switch>
- <ui-switch v-model="suggestRecentHashtags">%i18n:@suggest-recent-hashtags%</ui-switch>
- <ui-switch v-model="showClockOnHeader">%i18n:@show-clock-on-header%</ui-switch>
- <ui-switch v-model="alwaysShowNsfw">%i18n:common.always-show-nsfw%</ui-switch>
- <ui-switch v-model="showReplyTarget">%i18n:@show-reply-target%</ui-switch>
- <ui-switch v-model="showMyRenotes">%i18n:@show-my-renotes%</ui-switch>
- <ui-switch v-model="showRenotedMyNotes">%i18n:@show-renoted-my-notes%</ui-switch>
- <ui-switch v-model="showLocalRenotes">%i18n:@show-local-renotes%</ui-switch>
- <ui-switch v-model="showMaps">%i18n:@show-maps%</ui-switch>
- <ui-switch v-model="disableAnimatedMfm">%i18n:common.disable-animated-mfm%</ui-switch>
- <ui-switch v-model="games_reversi_showBoardLabels">%i18n:common.show-reversi-board-labels%</ui-switch>
- <ui-switch v-model="games_reversi_useContrastStones">%i18n:common.use-contrast-reversi-stones%</ui-switch>
-
+ </section>
<section>
- <header>%i18n:@navbar-position%</header>
- <ui-radio v-model="navbar" value="top">%i18n:@navbar-position-top%</ui-radio>
- <ui-radio v-model="navbar" value="left">%i18n:@navbar-position-left%</ui-radio>
- <ui-radio v-model="navbar" value="right">%i18n:@navbar-position-right%</ui-radio>
+ <ui-switch v-model="showPostFormOnTopOfTl">%i18n:@post-form-on-timeline%</ui-switch>
+ <ui-switch v-model="suggestRecentHashtags">%i18n:@suggest-recent-hashtags%</ui-switch>
+ <ui-switch v-model="showClockOnHeader">%i18n:@show-clock-on-header%</ui-switch>
+ <ui-switch v-model="alwaysShowNsfw">%i18n:common.always-show-nsfw%</ui-switch>
+ <ui-switch v-model="showReplyTarget">%i18n:@show-reply-target%</ui-switch>
+ <ui-switch v-model="showMyRenotes">%i18n:@show-my-renotes%</ui-switch>
+ <ui-switch v-model="showRenotedMyNotes">%i18n:@show-renoted-my-notes%</ui-switch>
+ <ui-switch v-model="showLocalRenotes">%i18n:@show-local-renotes%</ui-switch>
+ <ui-switch v-model="showMaps">%i18n:@show-maps%</ui-switch>
+ <ui-switch v-model="disableAnimatedMfm">%i18n:common.disable-animated-mfm%</ui-switch>
+ <ui-switch v-model="games_reversi_showBoardLabels">%i18n:common.show-reversi-board-labels%</ui-switch>
+ <ui-switch v-model="games_reversi_useContrastStones">%i18n:common.use-contrast-reversi-stones%</ui-switch>
</section>
- </section>
+ </ui-card>
- <section class="web" v-show="page == 'web'">
- <h1>%i18n:@sound%</h1>
- <ui-switch v-model="enableSounds">
- %i18n:@enable-sounds%
- <span slot="desc">%i18n:@enable-sounds-desc%</span>
- </ui-switch>
- <label>%i18n:@volume%</label>
- <input type="range"
- v-model="soundVolume"
- :disabled="!enableSounds"
- max="1"
- step="0.1"
- />
- <button class="ui button" @click="soundTest">%fa:volume-up% %i18n:@test%</button>
- </section>
+ <ui-card class="web" v-show="page == 'web'">
+ <div slot="title">%fa:volume-up% %i18n:@sound%</div>
- <section class="web" v-show="page == 'web'">
- <h1>%i18n:@mobile%</h1>
- <ui-switch v-model="disableViaMobile">%i18n:@disable-via-mobile%</ui-switch>
- </section>
+ <section>
+ <ui-switch v-model="enableSounds">
+ %i18n:@enable-sounds%
+ <span slot="desc">%i18n:@enable-sounds-desc%</span>
+ </ui-switch>
+ <label>%i18n:@volume%</label>
+ <input type="range"
+ v-model="soundVolume"
+ :disabled="!enableSounds"
+ max="1"
+ step="0.1"
+ />
+ <ui-button @click="soundTest">%fa:volume-up% %i18n:@test%</ui-button>
+ </section>
+ </ui-card>
- <section class="web" v-show="page == 'web'">
- <h1>%i18n:@language%</h1>
- <select v-model="lang" placeholder="%i18n:@pick-language%">
- <optgroup label="%i18n:@recommended%">
- <option value="">%i18n:@auto%</option>
- </optgroup>
+ <ui-card class="web" v-show="page == 'web'">
+ <div slot="title">%fa:language% %i18n:@language%</div>
+ <section class="fit-top">
+ <ui-select v-model="lang" placeholder="%i18n:@pick-language%">
+ <optgroup label="%i18n:@recommended%">
+ <option value="">%i18n:@auto%</option>
+ </optgroup>
- <optgroup label="%i18n:@specify-language%">
- <option v-for="x in langs" :value="x[0]" :key="x[0]">{{ x[1] }}</option>
- </optgroup>
- </select>
- <div class="none ui info">
- <p>%fa:info-circle%%i18n:@language-desc%</p>
- </div>
- </section>
+ <optgroup label="%i18n:@specify-language%">
+ <option v-for="x in langs" :value="x[0]" :key="x[0]">{{ x[1] }}</option>
+ </optgroup>
+ </ui-select>
+ <div class="none ui info">
+ <p>%fa:info-circle%%i18n:@language-desc%</p>
+ </div>
+ </section>
+ </ui-card>
- <section class="web" v-show="page == 'web'">
- <h1>%i18n:@cache%</h1>
- <button class="ui button" @click="clean">%i18n:@clean-cache%</button>
- <div class="none ui info warn">
- <p>%fa:exclamation-triangle%%i18n:@cache-warn%</p>
- </div>
- </section>
+ <ui-card class="web" v-show="page == 'web'">
+ <div slot="title">%fa:trash-alt R% %i18n:@cache%</div>
+ <section>
+ <ui-button @click="clean">%i18n:@clean-cache%</ui-button>
+ <div class="none ui info warn">
+ <p>%fa:exclamation-triangle%%i18n:@cache-warn%</p>
+ </div>
+ </section>
+ </ui-card>
- <section class="notification" v-show="page == 'notification'">
- <h1>%i18n:@notification%</h1>
- <ui-switch v-model="$store.state.i.settings.autoWatch" @change="onChangeAutoWatch">
- %i18n:@auto-watch%
- <span slot="desc">%i18n:@auto-watch-desc%</span>
- </ui-switch>
- </section>
+ <ui-card class="notification" v-show="page == 'notification'">
+ <div slot="title">%fa:bell R% %i18n:@notification%</div>
+ <section>
+ <ui-switch v-model="$store.state.i.settings.autoWatch" @change="onChangeAutoWatch">
+ %i18n:@auto-watch%
+ <span slot="desc">%i18n:@auto-watch-desc%</span>
+ </ui-switch>
+ </section>
+ </ui-card>
- <section class="drive" v-show="page == 'drive'">
- <h1>%i18n:@drive%</h1>
- <x-drive/>
- </section>
+ <ui-card class="drive" v-show="page == 'drive'">
+ <div slot="title">%fa:cloud% %i18n:@drive%</div>
+ <section>
+ <x-drive/>
+ </section>
+ </ui-card>
- <section class="hashtags" v-show="page == 'hashtags'">
- <h1>%i18n:@tags%</h1>
- <x-tags/>
- </section>
+ <ui-card class="hashtags" v-show="page == 'hashtags'">
+ <div slot="title">%fa:hashtag% %i18n:@tags%</div>
+ <section>
+ <x-tags/>
+ </section>
+ </ui-card>
- <section class="mute" v-show="page == 'mute'">
- <h1>%i18n:@mute%</h1>
- <x-mute/>
- </section>
+ <ui-card class="mute" v-show="page == 'mute'">
+ <div slot="title">%fa:ban% %i18n:@mute%</div>
+ <section>
+ <x-mute/>
+ </section>
+ </ui-card>
- <section class="apps" v-show="page == 'apps'">
- <h1>%i18n:@apps%</h1>
- <x-apps/>
- </section>
+ <ui-card class="apps" v-show="page == 'apps'">
+ <div slot="title">%fa:puzzle-piece% %i18n:@apps%</div>
+ <section>
+ <x-apps/>
+ </section>
+ </ui-card>
- <section class="twitter" v-show="page == 'twitter'">
- <h1>Twitter</h1>
- <mk-twitter-setting/>
- </section>
+ <ui-card class="password" v-show="page == 'security'">
+ <div slot="title">%fa:unlock-alt% %i18n:@password%</div>
+ <section>
+ <x-password/>
+ </section>
+ </ui-card>
- <section class="password" v-show="page == 'security'">
- <h1>%i18n:@password%</h1>
- <x-password/>
- </section>
+ <ui-card class="2fa" v-show="page == 'security'">
+ <div slot="title">%fa:mobile-alt% %i18n:@2fa%</div>
+ <section>
+ <x-2fa/>
+ </section>
+ </ui-card>
- <section class="2fa" v-show="page == 'security'">
- <h1>%i18n:@2fa%</h1>
- <x-2fa/>
- </section>
+ <ui-card class="signin" v-show="page == 'security'">
+ <div slot="title">%fa:sign-in-alt% %i18n:@signin%</div>
+ <section>
+ <x-signins/>
+ </section>
+ </ui-card>
- <section class="signin" v-show="page == 'security'">
- <h1>%i18n:@signin%</h1>
- <x-signins/>
- </section>
+ <ui-card class="api" v-show="page == 'api'">
+ <div slot="title">%fa:key% API</div>
+ <section class="fit-top">
+ <x-api/>
+ </section>
+ </ui-card>
- <section class="api" v-show="page == 'api'">
- <h1>API</h1>
- <x-api/>
- </section>
+ <ui-card class="other" v-show="page == 'other'">
+ <div slot="title">%fa:info-circle% %i18n:@about%</div>
+ <section>
+ <p v-if="meta">%i18n:@operator%: <i><a :href="meta.maintainer.url" target="_blank">{{ meta.maintainer.name }}</a></i></p>
+ </section>
+ </ui-card>
- <section class="other" v-show="page == 'other'">
- <h1>%i18n:@about%</h1>
- <p v-if="meta">%i18n:@operator%: <i><a :href="meta.maintainer.url" target="_blank">{{ meta.maintainer.name }}</a></i></p>
- </section>
+ <ui-card class="other" v-show="page == 'other'">
+ <div slot="title">%fa:sync-alt% %i18n:@update%</div>
+ <section>
+ <p>
+ <span>%i18n:@version% <i>{{ version }}</i></span>
+ <template v-if="latestVersion !== undefined">
+ <br>
+ <span>%i18n:@latest-version% <i>{{ latestVersion ? latestVersion : version }}</i></span>
+ </template>
+ </p>
+ <button class="ui button block" @click="checkForUpdate" :disabled="checkingForUpdate">
+ <template v-if="checkingForUpdate">%i18n:@update-checking%<mk-ellipsis/></template>
+ <template v-else>%i18n:@do-update%</template>
+ </button>
+ <details>
+ <summary>%i18n:@update-settings%</summary>
+ <ui-switch v-model="preventUpdate">
+ %i18n:@prevent-update%
+ <span slot="desc">%i18n:@prevent-update-desc%</span>
+ </ui-switch>
+ </details>
+ </section>
+ </ui-card>
- <section class="other" v-show="page == 'other'">
- <h1>%i18n:@update%</h1>
- <p>
- <span>%i18n:@version% <i>{{ version }}</i></span>
- <template v-if="latestVersion !== undefined">
- <br>
- <span>%i18n:@latest-version% <i>{{ latestVersion ? latestVersion : version }}</i></span>
- </template>
- </p>
- <button class="ui button block" @click="checkForUpdate" :disabled="checkingForUpdate">
- <template v-if="checkingForUpdate">%i18n:@update-checking%<mk-ellipsis/></template>
- <template v-else>%i18n:@do-update%</template>
- </button>
- <details>
- <summary>%i18n:@update-settings%</summary>
- <ui-switch v-model="preventUpdate">
- %i18n:@prevent-update%
- <span slot="desc">%i18n:@prevent-update-desc%</span>
+ <ui-card class="other" v-show="page == 'other'">
+ <div slot="title">%fa:cogs% %i18n:@advanced-settings%</div>
+ <section>
+ <ui-switch v-model="debug">
+ %i18n:@debug-mode%
+ <span slot="desc">%i18n:@debug-mode-desc%</span>
</ui-switch>
- </details>
- </section>
-
- <section class="other" v-show="page == 'other'">
- <h1>%i18n:@advanced-settings%</h1>
- <ui-switch v-model="debug">
- %i18n:@debug-mode%
- <span slot="desc">%i18n:@debug-mode-desc%</span>
- </ui-switch>
- <ui-switch v-model="enableExperimentalFeatures">
- %i18n:@experimental%
- <span slot="desc">%i18n:@experimental-desc%</span>
- </ui-switch>
- </section>
+ <ui-switch v-model="enableExperimentalFeatures">
+ %i18n:@experimental%
+ <span slot="desc">%i18n:@experimental-desc%</span>
+ </ui-switch>
+ </section>
+ </ui-card>
</div>
</div>
</template>
<script lang="ts">
import Vue from 'vue';
-import XProfile from './settings.profile.vue';
import XMute from './settings.mute.vue';
import XPassword from './settings.password.vue';
import X2fa from './settings.2fa.vue';
@@ -253,7 +291,6 @@ import checkForUpdate from '../../../common/scripts/check-for-update';
export default Vue.extend({
components: {
- XProfile,
XMute,
XPassword,
X2fa,
@@ -295,6 +332,11 @@ export default Vue.extend({
set(value) { this.$store.commit('device/set', { key: 'autoPopout', value }); }
},
+ deckNav: {
+ get() { return this.$store.state.settings.deckNav; },
+ set(value) { this.$store.commit('settings/set', { key: 'deckNav', value }); }
+ },
+
darkmode: {
get() { return this.$store.state.device.darkmode; },
set(value) { this.$store.commit('device/set', { key: 'darkmode', value }); }
@@ -438,11 +480,6 @@ export default Vue.extend({
disableAnimatedMfm: {
get() { return this.$store.state.settings.disableAnimatedMfm; },
set(value) { this.$store.dispatch('settings/set', { key: 'disableAnimatedMfm', value }); }
- },
-
- disableViaMobile: {
- get() { return this.$store.state.settings.disableViaMobile; },
- set(value) { this.$store.dispatch('settings/set', { key: 'disableViaMobile', value }); }
}
},
created() {
@@ -546,34 +583,10 @@ export default Vue.extend({
height 100%
flex auto
overflow auto
+ background var(--bg)
> section
margin 32px
color var(--text)
- > h1
- margin 0 0 1em 0
- padding 0 0 8px 0
- font-size 1em
- border-bottom solid 1px var(--faceDivider)
-
- &, >>> *
- .ui.button.block
- margin 16px 0
-
- > section
- margin 32px 0
-
- > h2
- margin 0 0 1em 0
- padding 0 0 8px 0
- font-size 1em
- color var(--text)
- border-bottom solid 1px var(--faceDivider)
-
- > .web
- > .div
- border-bottom solid 1px var(--faceDivider)
- margin 16px 0
-
</style>
diff --git a/src/client/app/desktop/views/pages/deck/deck.column.vue b/src/client/app/desktop/views/pages/deck/deck.column.vue
index e2c7e83199..aced5848e4 100644
--- a/src/client/app/desktop/views/pages/deck/deck.column.vue
+++ b/src/client/app/desktop/views/pages/deck/deck.column.vue
@@ -1,7 +1,6 @@
<template>
<div class="dnpfarvgbnfmyzbdquhhzyxcmstpdqzs" :class="{ naked, narrow, active, isStacked, draghover, dragging, dropready }"
@dragover.prevent.stop="onDragover"
- @dragenter.prevent="onDragenter"
@dragleave="onDragleave"
@drop.prevent.stop="onDrop">
<header :class="{ indicate: count > 0 }"
@@ -16,7 +15,8 @@
</button>
<slot name="header"></slot>
<span class="count" v-if="count > 0">({{ count }})</span>
- <button class="menu" ref="menu" @click.stop="showMenu">%fa:caret-down%</button>
+ <button v-if="!isTemporaryColumn" class="menu" ref="menu" @click.stop="showMenu">%fa:caret-down%</button>
+ <button v-else class="close" @click.stop="close">%fa:times%</button>
</header>
<div ref="body" v-show="active">
<slot></slot>
@@ -34,11 +34,13 @@ export default Vue.extend({
props: {
column: {
type: Object,
- required: true
+ required: false,
+ default: null
},
isStacked: {
type: Boolean,
- required: true
+ required: false,
+ default: false
},
name: {
type: String,
@@ -61,6 +63,12 @@ export default Vue.extend({
}
},
+ computed: {
+ isTemporaryColumn(): boolean {
+ return this.column == null;
+ }
+ },
+
inject: {
getColumnVm: { from: 'getColumnVm' }
},
@@ -96,14 +104,20 @@ export default Vue.extend({
mounted() {
this.$refs.body.addEventListener('scroll', this.onScroll, { passive: true });
- this.$root.$on('deck.column.dragStart', this.onOtherDragStart);
- this.$root.$on('deck.column.dragEnd', this.onOtherDragEnd);
+
+ if (!this.isTemporaryColumn) {
+ this.$root.$on('deck.column.dragStart', this.onOtherDragStart);
+ this.$root.$on('deck.column.dragEnd', this.onOtherDragEnd);
+ }
},
beforeDestroy() {
this.$refs.body.removeEventListener('scroll', this.onScroll);
- this.$root.$off('deck.column.dragStart', this.onOtherDragStart);
- this.$root.$off('deck.column.dragEnd', this.onOtherDragEnd);
+
+ if (!this.isTemporaryColumn) {
+ this.$root.$off('deck.column.dragStart', this.onOtherDragStart);
+ this.$root.$off('deck.column.dragEnd', this.onOtherDragEnd);
+ }
},
methods: {
@@ -203,6 +217,7 @@ export default Vue.extend({
},
onContextmenu(e) {
+ if (this.isTemporaryColumn) return;
contextmenu((this as any).os)(e, this.getMenu());
},
@@ -214,6 +229,13 @@ export default Vue.extend({
});
},
+ close() {
+ this.$store.commit('device/set', {
+ key: 'deckTemporaryColumn',
+ value: null
+ });
+ },
+
goTop() {
this.$refs.body.scrollTo({
top: 0,
@@ -222,6 +244,12 @@ export default Vue.extend({
},
onDragstart(e) {
+ // テンポラリカラムはドラッグさせない
+ if (this.isTemporaryColumn) {
+ e.preventDefault();
+ return;
+ }
+
e.dataTransfer.effectAllowed = 'move';
e.dataTransfer.setData('mk-deck-column', this.column.id);
this.dragging = true;
@@ -232,6 +260,12 @@ export default Vue.extend({
},
onDragover(e) {
+ // テンポラリカラムにはドロップさせない
+ if (this.isTemporaryColumn) {
+ e.dataTransfer.dropEffect = 'none';
+ return;
+ }
+
// 自分自身がドラッグされている場合
if (this.dragging) {
// 自分自身にはドロップさせない
@@ -242,9 +276,7 @@ export default Vue.extend({
const isDeckColumn = e.dataTransfer.types[0] == 'mk-deck-column';
e.dataTransfer.dropEffect = isDeckColumn ? 'move' : 'none';
- },
- onDragenter() {
if (!this.dragging) this.draghover = true;
},
@@ -349,6 +381,7 @@ export default Vue.extend({
> .toggleActive
> .menu
+ > .close
padding 0
width $header-height
line-height $header-height
@@ -365,6 +398,7 @@ export default Vue.extend({
margin-left -16px
> .menu
+ > .close
margin-left auto
margin-right -16px
diff --git a/src/client/app/desktop/views/pages/deck/deck.note-column.vue b/src/client/app/desktop/views/pages/deck/deck.note-column.vue
new file mode 100644
index 0000000000..b8386e5b3d
--- /dev/null
+++ b/src/client/app/desktop/views/pages/deck/deck.note-column.vue
@@ -0,0 +1,69 @@
+<template>
+<x-column>
+ <span slot="header">
+ %fa:comment-alt R%<span>{{ title }}</span>
+ </span>
+
+ <div class="rvtscbadixhhbsczoorqoaygovdeecsx" v-if="note">
+ <div class="is-remote" v-if="note.user.host != null">%fa:exclamation-triangle% %i18n:@is-remote%<a :href="note.url || note.uri" target="_blank">%i18n:@view-remote%</a></div>
+ <x-note :note="note" :detail="true" :mini="true"/>
+ </div>
+</x-column>
+</template>
+
+<script lang="ts">
+import Vue from 'vue';
+import XColumn from './deck.column.vue';
+import XNotes from './deck.notes.vue';
+import XNote from '../../components/note.vue';
+
+export default Vue.extend({
+ components: {
+ XColumn,
+ XNotes,
+ XNote
+ },
+
+ props: {
+ noteId: {
+ type: String,
+ required: true
+ }
+ },
+
+ data() {
+ return {
+ note: null,
+ fetching: true
+ };
+ },
+
+ computed: {
+ title(): string {
+ return this.note ? Vue.filter('userName')(this.note.user) : '';
+ }
+ },
+
+ created() {
+ (this as any).api('notes/show', { noteId: this.noteId }).then(note => {
+ this.note = note;
+ this.fetching = false;
+ });
+ }
+});
+</script>
+
+<style lang="stylus" scoped>
+.rvtscbadixhhbsczoorqoaygovdeecsx
+ > .is-remote
+ padding 8px 16px
+ font-size 12px
+
+ &.is-remote
+ color var(--remoteInfoFg)
+ background var(--remoteInfoBg)
+
+ > a
+ font-weight bold
+
+</style>
diff --git a/src/client/app/desktop/views/pages/deck/deck.note.sub.vue b/src/client/app/desktop/views/pages/deck/deck.note.sub.vue
deleted file mode 100644
index 445bf7e365..0000000000
--- a/src/client/app/desktop/views/pages/deck/deck.note.sub.vue
+++ /dev/null
@@ -1,71 +0,0 @@
-<template>
-<div class="fnlfosztlhtptnongximhlbykxblytcq">
- <mk-avatar class="avatar" :user="note.user"/>
- <div class="main">
- <mk-note-header class="header" :note="note" :mini="true"/>
- <div class="body">
- <mk-sub-note-content class="text" :note="note"/>
- </div>
- </div>
-</div>
-</template>
-
-<script lang="ts">
-import Vue from 'vue';
-
-export default Vue.extend({
- props: {
- note: {
- type: Object,
- required: true
- },
- // TODO
- truncate: {
- type: Boolean,
- default: true
- }
- }
-});
-</script>
-
-<style lang="stylus" scoped>
-.fnlfosztlhtptnongximhlbykxblytcq
- display flex
- padding 16px
- font-size 10px
- background var(--subNoteBg)
-
- &.smart
- > .main
- width 100%
-
- > header
- align-items center
-
- > .avatar
- flex-shrink 0
- display block
- margin 0 8px 0 0
- width 38px
- height 38px
- border-radius 8px
-
- > .main
- flex 1
- min-width 0
-
- > .header
- margin-bottom 2px
-
- > .body
-
- > .text
- margin 0
- padding 0
- color var(--subNoteText)
-
- pre
- max-height 120px
- font-size 80%
-
-</style>
diff --git a/src/client/app/desktop/views/pages/deck/deck.note.vue b/src/client/app/desktop/views/pages/deck/deck.note.vue
deleted file mode 100644
index 03cf3e2911..0000000000
--- a/src/client/app/desktop/views/pages/deck/deck.note.vue
+++ /dev/null
@@ -1,323 +0,0 @@
-<template>
-<div
- v-if="!mediaView"
- v-show="appearNote.deletedAt == null"
- :tabindex="appearNote.deletedAt == null ? '-1' : null"
- class="zyjjkidcqjnlegkqebitfviomuqmseqk"
- :class="{ renote: isRenote }"
- v-hotkey="keymap"
- :title="title"
->
- <div class="reply-to" v-if="appearNote.reply && (!$store.getters.isSignedIn || $store.state.settings.showReplyTarget)">
- <x-sub :note="appearNote.reply"/>
- </div>
- <div class="renote" v-if="isRenote">
- <mk-avatar class="avatar" :user="note.user"/>
- %fa:retweet%
- <span>{{ '%i18n:@reposted-by%'.substr(0, '%i18n:@reposted-by%'.indexOf('{')) }}</span>
- <router-link class="name" :to="note.user | userPage">{{ note.user | userName }}</router-link>
- <span>{{ '%i18n:@reposted-by%'.substr('%i18n:@reposted-by%'.indexOf('}') + 1) }}</span>
- <mk-time :time="note.createdAt"/>
- </div>
- <article>
- <mk-avatar class="avatar" :user="appearNote.user"/>
- <div class="main">
- <mk-note-header class="header" :note="appearNote" :mini="true"/>
- <div class="body">
- <p v-if="appearNote.cw != null" class="cw">
- <span class="text" v-if="appearNote.cw != ''">{{ appearNote.cw }}</span>
- <mk-cw-button v-model="showContent"/>
- </p>
- <div class="content" v-show="appearNote.cw == null || showContent">
- <div class="text">
- <span v-if="appearNote.isHidden" style="opacity: 0.5">(%i18n:@private%)</span>
- <a class="reply" v-if="appearNote.reply">%fa:reply%</a>
- <misskey-flavored-markdown v-if="appearNote.text" :text="appearNote.text" :i="$store.state.i"/>
- <a class="rp" v-if="appearNote.renote != null">RP:</a>
- </div>
- <div class="files" v-if="appearNote.files.length > 0">
- <mk-media-list :media-list="appearNote.files"/>
- </div>
- <mk-poll v-if="appearNote.poll" :note="appearNote" ref="pollViewer"/>
- <a class="location" v-if="appearNote.geo" :href="`https://maps.google.com/maps?q=${appearNote.geo.coordinates[1]},${appearNote.geo.coordinates[0]}`" target="_blank">%fa:map-marker-alt% %i18n:@location%</a>
- <div class="renote" v-if="appearNote.renote">
- <mk-note-preview :note="appearNote.renote" :mini="true"/>
- </div>
- <mk-url-preview v-for="url in urls" :url="url" :key="url" :detail="false" :mini="true"/>
- </div>
- <span class="app" v-if="appearNote.app">via <b>{{ appearNote.app.name }}</b></span>
- </div>
- <footer>
- <mk-reactions-viewer :note="appearNote" ref="reactionsViewer"/>
- <button @click="reply()">
- <template v-if="appearNote.reply">%fa:reply-all%</template>
- <template v-else>%fa:reply%</template>
- </button>
- <button @click="renote()" title="Renote">%fa:retweet%</button>
- <button :class="{ reacted: appearNote.myReaction != null }" @click="react()" ref="reactButton">%fa:plus%</button>
- <button class="menu" @click="menu()" ref="menuButton">%fa:ellipsis-h%</button>
- </footer>
- </div>
- </article>
-</div>
-<div v-else class="srwrkujossgfuhrbnvqkybtzxpblgchi">
- <div v-if="note.files.length > 0">
- <mk-media-list :media-list="note.files"/>
- </div>
- <div v-if="note.renote && note.renote.files.length > 0">
- <mk-media-list :media-list="note.renote.files"/>
- </div>
-</div>
-</template>
-
-<script lang="ts">
-import Vue from 'vue';
-import MkPostFormWindow from '../../components/post-form-window.vue';
-import MkRenoteFormWindow from '../../components/renote-form-window.vue';
-import XSub from './deck.note.sub.vue';
-import noteMixin from '../../../../common/scripts/note-mixin';
-import noteSubscriber from '../../../../common/scripts/note-subscriber';
-
-export default Vue.extend({
- components: {
- XSub
- },
-
- mixins: [
- noteMixin(),
- noteSubscriber('note')
- ],
-
- props: {
- note: {
- type: Object,
- required: true
- },
- mediaView: {
- type: Boolean,
- required: false,
- default: false
- }
- }
-});
-</script>
-
-<style lang="stylus" scoped>
-.srwrkujossgfuhrbnvqkybtzxpblgchi
- font-size 13px
- margin 4px 12px
-
- &:first-child
- margin-top 12px
-
- &:last-child
- margin-bottom 12px
-
-.zyjjkidcqjnlegkqebitfviomuqmseqk
- font-size 13px
- border-bottom solid 1px var(--faceDivider)
-
- &:focus
- z-index 1
-
- &:after
- content ""
- pointer-events none
- position absolute
- top 2px
- right 2px
- bottom 2px
- left 2px
- border 2px solid var(--primaryAlpha03)
- border-radius 4px
-
- &:last-of-type
- border-bottom none
-
- &.smart
- > article
- > .main
- > header
- align-items center
- margin-bottom 4px
-
- > .renote
- display flex
- align-items center
- padding 8px 16px 0 16px
- line-height 28px
- white-space pre
- color var(--renoteText)
- background linear-gradient(to bottom, var(--renoteGradient) 0%, var(--face) 100%)
-
- .avatar
- flex-shrink 0
- display inline-block
- width 20px
- height 20px
- margin 0 8px 0 0
- border-radius 6px
-
- [data-fa]
- margin-right 4px
-
- > span
- flex-shrink 0
-
- &:last-of-type
- margin-right 8px
-
- .name
- overflow hidden
- flex-shrink 1
- text-overflow ellipsis
- white-space nowrap
- font-weight bold
-
- > .mk-time
- display block
- margin-left auto
- flex-shrink 0
- font-size 0.9em
-
- & + article
- padding-top 8px
-
- > article
- display flex
- padding 16px 16px 4px
-
- > .avatar
- flex-shrink 0
- display block
- margin 0 10px 8px 0
- width 42px
- height 42px
- border-radius 6px
- //position -webkit-sticky
- //position sticky
- //top 62px
-
- > .main
- flex 1
- min-width 0
-
- > .body
-
- > .cw
- cursor default
- display block
- margin 0
- padding 0
- overflow-wrap break-word
- color var(--noteText)
-
- > .text
- margin-right 8px
-
- > .content
-
- > .text
- display block
- margin 0
- padding 0
- overflow-wrap break-word
- color var(--noteText)
-
- >>> .title
- display block
- margin-bottom 4px
- padding 4px
- font-size 90%
- text-align center
- background var(--mfmTitleBg)
- border-radius 4px
-
- >>> .code
- margin 8px 0
-
- >>> .quote
- margin 8px
- padding 6px 12px
- color var(--mfmQuote)
- border-left solid 3px var(--mfmQuoteLine)
-
- > .reply
- margin-right 8px
- color var(--noteText)
-
- > .rp
- margin-left 4px
- font-style oblique
- color var(--renoteText)
-
- [data-is-me]:after
- content "you"
- padding 0 4px
- margin-left 4px
- font-size 80%
- color var(--primaryForeground)
- background var(--primary)
- border-radius 4px
-
- .mk-url-preview
- margin-top 8px
-
- > .files
- > img
- display block
- max-width 100%
-
- > .location
- margin 4px 0
- font-size 12px
- color #ccc
-
- > .map
- width 100%
- height 200px
-
- &:empty
- display none
-
- > .mk-poll
- font-size 80%
-
- > .renote
- margin 8px 0
-
- > *
- padding 16px
- border dashed 1px var(--quoteBorder)
- border-radius 8px
-
- > .app
- font-size 12px
- color #ccc
-
- > footer
- > button
- margin 0
- padding 4px 8px 8px 8px
- background transparent
- border none
- box-shadow none
- font-size 1em
- color var(--noteActions)
- cursor pointer
-
- &:not(:last-child)
- margin-right 28px
-
- &:hover
- color var(--noteActionsHover)
-
- > .count
- display inline
- margin 0 0 0 8px
- color #999
-
- &.reacted
- color var(--primary)
-
-</style>
diff --git a/src/client/app/desktop/views/pages/deck/deck.notes.vue b/src/client/app/desktop/views/pages/deck/deck.notes.vue
index 5898f5b05e..c656fe9179 100644
--- a/src/client/app/desktop/views/pages/deck/deck.notes.vue
+++ b/src/client/app/desktop/views/pages/deck/deck.notes.vue
@@ -17,7 +17,7 @@
<!--<transition-group name="mk-notes" class="transition">-->
<div class="notes">
<template v-for="(note, i) in _notes">
- <x-note :note="note" :key="note.id" @update:note="onNoteUpdated(i, $event)" :media-view="mediaView"/>
+ <x-note :note="note" :key="note.id" @update:note="onNoteUpdated(i, $event)" :media-view="mediaView" :mini="true"/>
<p class="date" :key="note.id + '_date'" v-if="i != notes.length - 1 && note._date != _notes[i + 1]._date">
<span>%fa:angle-up%{{ note._datetext }}</span>
<span>%fa:angle-down%{{ _notes[i + 1]._datetext }}</span>
@@ -38,7 +38,7 @@
<script lang="ts">
import Vue from 'vue';
-import XNote from './deck.note.vue';
+import XNote from '../../components/note.vue';
const displayLimit = 20;
@@ -220,7 +220,7 @@ export default Vue.extend({
display block
margin 0
line-height 32px
- font-size 14px
+ font-size 12px
text-align center
color var(--dateDividerFg)
background var(--dateDividerBg)
diff --git a/src/client/app/desktop/views/pages/deck/deck.notification.vue b/src/client/app/desktop/views/pages/deck/deck.notification.vue
index 149bd10293..fa8f99a2ba 100644
--- a/src/client/app/desktop/views/pages/deck/deck.notification.vue
+++ b/src/client/app/desktop/views/pages/deck/deck.notification.vue
@@ -66,15 +66,15 @@
</div>
<template v-if="notification.type == 'quote'">
- <x-note :note="notification.note" @update:note="onNoteUpdated"/>
+ <x-note :note="notification.note" @update:note="onNoteUpdated" :mini="true"/>
</template>
<template v-if="notification.type == 'reply'">
- <x-note :note="notification.note" @update:note="onNoteUpdated"/>
+ <x-note :note="notification.note" @update:note="onNoteUpdated" :mini="true"/>
</template>
<template v-if="notification.type == 'mention'">
- <x-note :note="notification.note" @update:note="onNoteUpdated"/>
+ <x-note :note="notification.note" @update:note="onNoteUpdated" :mini="true"/>
</template>
</div>
</template>
@@ -82,7 +82,7 @@
<script lang="ts">
import Vue from 'vue';
import getNoteSummary from '../../../../../../misc/get-note-summary';
-import XNote from './deck.note.vue';
+import XNote from '../../components/note.vue';
export default Vue.extend({
components: {
diff --git a/src/client/app/desktop/views/pages/deck/deck.user-column.vue b/src/client/app/desktop/views/pages/deck/deck.user-column.vue
new file mode 100644
index 0000000000..217008e0ec
--- /dev/null
+++ b/src/client/app/desktop/views/pages/deck/deck.user-column.vue
@@ -0,0 +1,261 @@
+<template>
+<x-column>
+ <span slot="header">
+ %fa:user%<span>{{ title }}</span>
+ </span>
+
+ <div class="zubukjlciycdsyynicqrnlsmdwmymzqu" v-if="user">
+ <div class="is-remote" v-if="user.host != null">%fa:exclamation-triangle% %i18n:@is-remote%<a :href="user.url || user.uri" target="_blank">%i18n:@view-remote%</a></div>
+ <header :style="bannerStyle">
+ <div>
+ <mk-follow-button v-if="$store.getters.isSignedIn && user.id != $store.state.i.id" :user="user" class="follow"/>
+ <mk-avatar class="avatar" :user="user" :disable-preview="true"/>
+ <span class="name">{{ user | userName }}</span>
+ <span class="acct">@{{ user | acct }}</span>
+ </div>
+ </header>
+ <div class="info">
+ <div class="description">
+ <misskey-flavored-markdown v-if="user.description" :text="user.description" :i="$store.state.i"/>
+ </div>
+ </div>
+ <div class="pinned" v-if="user.pinnedNotes && user.pinnedNotes.length > 0">
+ <p>%fa:thumbtack% %i18n:@pinned-notes%</p>
+ <div class="notes">
+ <x-note v-for="n in user.pinnedNotes" :key="n.id" :note="n" :mini="true"/>
+ </div>
+ </div>
+ <div class="images" v-if="images.length > 0">
+ <router-link v-for="image in images" :style="`background-image: url(${image.thumbnailUrl})`" :key="`${image.id}:${image._note.id}`" :to="image._note | notePage"></router-link>
+ </div>
+ <div class="tl">
+ <x-notes ref="timeline" :more="existMore ? fetchMoreNotes : null"/>
+ </div>
+ </div>
+</x-column>
+</template>
+
+<script lang="ts">
+import Vue from 'vue';
+import parseAcct from '../../../../../../misc/acct/parse';
+import XColumn from './deck.column.vue';
+import XNotes from './deck.notes.vue';
+import XNote from '../../components/note.vue';
+
+const fetchLimit = 10;
+
+export default Vue.extend({
+ components: {
+ XColumn,
+ XNotes,
+ XNote
+ },
+
+ props: {
+ acct: {
+ type: String,
+ required: true
+ }
+ },
+
+ data() {
+ return {
+ user: null,
+ fetching: true,
+ existMore: false,
+ moreFetching: false,
+ withFiles: false,
+ images: []
+ };
+ },
+
+ computed: {
+ title(): string {
+ return this.user ? Vue.filter('userName')(this.user) : '';
+ },
+
+ bannerStyle(): any {
+ if (this.user == null) return {};
+ if (this.user.bannerUrl == null) return {};
+ return {
+ backgroundColor: this.user.bannerColor && this.user.bannerColor.length == 3 ? `rgb(${ this.user.bannerColor.join(',') })` : null,
+ backgroundImage: `url(${ this.user.bannerUrl })`
+ };
+ },
+ },
+
+ created() {
+ (this as any).api('users/show', parseAcct(this.acct)).then(user => {
+ this.user = user;
+ this.fetching = false;
+
+ this.$nextTick(() => {
+ (this.$refs.timeline as any).init(() => this.initTl());
+ });
+
+ (this as any).api('users/notes', {
+ userId: this.user.id,
+ withFiles: true,
+ limit: 9
+ }).then(notes => {
+ notes.forEach(note => {
+ note.files.forEach(file => {
+ file._note = note;
+ if (this.images.length < 9) this.images.push(file);
+ });
+ });
+ });
+ });
+ },
+
+ methods: {
+ initTl() {
+ return new Promise((res, rej) => {
+ (this as any).api('users/notes', {
+ userId: this.user.id,
+ limit: fetchLimit + 1,
+ withFiles: this.withFiles,
+ includeMyRenotes: this.$store.state.settings.showMyRenotes,
+ includeRenotedMyNotes: this.$store.state.settings.showRenotedMyNotes,
+ includeLocalRenotes: this.$store.state.settings.showLocalRenotes
+ }).then(notes => {
+ if (notes.length == fetchLimit + 1) {
+ notes.pop();
+ this.existMore = true;
+ }
+ res(notes);
+ }, rej);
+ });
+ },
+
+ fetchMoreNotes() {
+ this.moreFetching = true;
+
+ const promise = (this as any).api('users/notes', {
+ userId: this.user.id,
+ limit: fetchLimit + 1,
+ untilId: (this.$refs.timeline as any).tail().id,
+ withFiles: this.withFiles,
+ includeMyRenotes: this.$store.state.settings.showMyRenotes,
+ includeRenotedMyNotes: this.$store.state.settings.showRenotedMyNotes,
+ includeLocalRenotes: this.$store.state.settings.showLocalRenotes
+ });
+
+ promise.then(notes => {
+ if (notes.length == fetchLimit + 1) {
+ notes.pop();
+ } else {
+ this.existMore = false;
+ }
+ notes.forEach(n => (this.$refs.timeline as any).append(n));
+ this.moreFetching = false;
+ });
+
+ return promise;
+ },
+ }
+});
+</script>
+
+<style lang="stylus" scoped>
+.zubukjlciycdsyynicqrnlsmdwmymzqu
+ background var(--deckUserColumnBg)
+
+ > .is-remote
+ padding 8px 16px
+ font-size 12px
+
+ &.is-remote
+ color var(--remoteInfoFg)
+ background var(--remoteInfoBg)
+
+ > a
+ font-weight bold
+
+ > header
+ overflow hidden
+ background-size cover
+ background-position center
+
+ > div
+ padding 32px
+ background rgba(#000, 0.5)
+ color #fff
+ text-align center
+
+ > .follow
+ position absolute
+ top 16px
+ right 16px
+
+ > .avatar
+ display block
+ width 64px
+ height 64px
+ margin 0 auto
+
+ > .name
+ display block
+ margin-top 8px
+ font-weight bold
+ text-shadow 0 0 8px #000
+
+ > .acct
+ font-size 14px
+ opacity 0.7
+ text-shadow 0 0 8px #000
+
+ > .info
+ padding 16px
+ font-size 14px
+ color var(--text)
+ text-align center
+ background var(--face)
+ border-bottom solid 1px var(--faceDivider)
+
+ &:before
+ content ""
+ display blcok
+ position absolute
+ top -32px
+ left 0
+ right 0
+ width 0px
+ margin 0 auto
+ border-top solid 16px transparent
+ border-left solid 16px transparent
+ border-right solid 16px transparent
+ border-bottom solid 16px var(--face)
+
+ > .pinned
+ padding-bottom 16px
+ background var(--deckUserColumnBg)
+
+ > p
+ margin 0
+ padding 8px 16px
+ font-size 14px
+ color var(--text)
+
+ > .notes
+ background var(--face)
+
+ > .images
+ display grid
+ grid-template-rows 1fr 1fr 1fr
+ grid-template-columns 1fr 1fr 1fr
+ gap 4px
+ height 250px
+ padding 16px
+ margin-bottom 16px
+ background var(--face)
+
+ > *
+ background-position center center
+ background-size cover
+ background-clip content-box
+
+ > .tl
+ background var(--face)
+
+</style>
diff --git a/src/client/app/desktop/views/pages/deck/deck.vue b/src/client/app/desktop/views/pages/deck/deck.vue
index 22b4c50bb4..2ff3d68a91 100644
--- a/src/client/app/desktop/views/pages/deck/deck.vue
+++ b/src/client/app/desktop/views/pages/deck/deck.vue
@@ -9,6 +9,10 @@
</div>
<x-column-core v-else :ref="ids[0]" :key="ids[0]" :column="columns.find(c => c.id == ids[0])"/>
</template>
+ <template v-if="temporaryColumn">
+ <x-user-column v-if="temporaryColumn.type == 'user'" :acct="temporaryColumn.acct" :key="temporaryColumn.acct"/>
+ <x-note-column v-else-if="temporaryColumn.type == 'note'" :note-id="temporaryColumn.noteId" :key="temporaryColumn.noteId"/>
+ </template>
<button ref="add" @click="add" title="%i18n:common.deck.add-column%">%fa:plus%</button>
</div>
</mk-ui>
@@ -19,11 +23,16 @@ import Vue from 'vue';
import XColumnCore from './deck.column-core.vue';
import Menu from '../../../../common/views/components/menu.vue';
import MkUserListsWindow from '../../components/user-lists-window.vue';
+import XUserColumn from './deck.user-column.vue';
+import XNoteColumn from './deck.note-column.vue';
+
import * as uuid from 'uuid';
export default Vue.extend({
components: {
- XColumnCore
+ XColumnCore,
+ XUserColumn,
+ XNoteColumn
},
computed: {
@@ -31,15 +40,21 @@ export default Vue.extend({
if (this.$store.state.settings.deck == null) return [];
return this.$store.state.settings.deck.columns;
},
+
layout(): any[] {
if (this.$store.state.settings.deck == null) return [];
if (this.$store.state.settings.deck.layout == null) return this.$store.state.settings.deck.columns.map(c => [c.id]);
return this.$store.state.settings.deck.layout;
},
+
style(): any {
return {
height: `calc(100vh - ${this.$store.state.uiHeaderHeight}px)`
};
+ },
+
+ temporaryColumn(): any {
+ return this.$store.state.device.deckTemporaryColumn;
}
},
@@ -50,6 +65,8 @@ export default Vue.extend({
},
created() {
+ this.$store.commit('navHook', this.onNav);
+
if (this.$store.state.settings.deck == null) {
const deck = {
columns: [/*{
@@ -95,6 +112,8 @@ export default Vue.extend({
},
beforeDestroy() {
+ this.$store.commit('navHook', null);
+
document.documentElement.style.overflow = 'auto';
},
@@ -103,6 +122,30 @@ export default Vue.extend({
return this.$refs[id][0];
},
+ onNav(to) {
+ if (!this.$store.state.settings.deckNav) return false;
+
+ if (to.name == 'user') {
+ this.$store.commit('device/set', {
+ key: 'deckTemporaryColumn',
+ value: {
+ type: 'user',
+ acct: to.params.user
+ }
+ });
+ return true;
+ } else if (to.name == 'note') {
+ this.$store.commit('device/set', {
+ key: 'deckTemporaryColumn',
+ value: {
+ type: 'note',
+ noteId: to.params.note
+ }
+ });
+ return true;
+ }
+ },
+
add() {
this.os.new(Menu, {
source: this.$refs.add,
diff --git a/src/client/app/desktop/views/pages/user/user.photos.vue b/src/client/app/desktop/views/pages/user/user.photos.vue
index 628d5b6d95..2f525b003d 100644
--- a/src/client/app/desktop/views/pages/user/user.photos.vue
+++ b/src/client/app/desktop/views/pages/user/user.photos.vue
@@ -60,9 +60,6 @@ export default Vue.extend({
margin-right 4px
> .stream
- display -webkit-flex
- display -moz-flex
- display -ms-flex
display flex
justify-content center
flex-wrap wrap
diff --git a/src/client/app/init.ts b/src/client/app/init.ts
index 2cbceb8e78..7277e70d83 100644
--- a/src/client/app/init.ts
+++ b/src/client/app/init.ts
@@ -148,6 +148,19 @@ export default (callback: (launch: (router: VueRouter, api?: (os: MiOS) => API)
});
//#endregion
+ // Navigation hook
+ router.beforeEach((to, from, next) => {
+ if (os.store.state.navHook) {
+ if (os.store.state.navHook(to)) {
+ next(false);
+ } else {
+ next();
+ }
+ } else {
+ next();
+ }
+ });
+
Vue.mixin({
data() {
return {
diff --git a/src/client/app/mobile/views/pages/settings.vue b/src/client/app/mobile/views/pages/settings.vue
index c0159a0484..6ac8c8bd08 100644
--- a/src/client/app/mobile/views/pages/settings.vue
+++ b/src/client/app/mobile/views/pages/settings.vue
@@ -5,7 +5,7 @@
<div class="signin-as" v-html="'%i18n:@signed-in-as%'.replace('{}', `<b>${name}</b>`)"></div>
<div>
- <x-profile/>
+ <mk-profile-editor/>
<ui-card>
<div slot="title">%fa:palette% %i18n:@theme%</div>
@@ -148,13 +148,7 @@ import Vue from 'vue';
import { apiUrl, version, codename, langs } from '../../../config';
import checkForUpdate from '../../../common/scripts/check-for-update';
-import XProfile from './settings/settings.profile.vue';
-
export default Vue.extend({
- components: {
- XProfile
- },
-
data() {
return {
apiUrl,
diff --git a/src/client/app/store.ts b/src/client/app/store.ts
index 63365f7fba..0a38decfa4 100644
--- a/src/client/app/store.ts
+++ b/src/client/app/store.ts
@@ -10,6 +10,7 @@ const defaultSettings = {
home: null,
mobileHome: [],
deck: null,
+ deckNav: true,
tagTimelines: [],
fetchOnScroll: true,
showMaps: true,
@@ -57,7 +58,8 @@ const defaultDeviceSettings = {
alwaysShowNsfw: false,
postStyle: 'standard',
navbar: 'top',
- mobileNotificationPosition: 'bottom'
+ mobileNotificationPosition: 'bottom',
+ deckTemporaryColumn: null
};
export default (os: MiOS) => new Vuex.Store({
@@ -68,7 +70,8 @@ export default (os: MiOS) => new Vuex.Store({
state: {
i: null,
indicate: false,
- uiHeaderHeight: 0
+ uiHeaderHeight: 0,
+ navHook: null
},
getters: {
@@ -90,6 +93,10 @@ export default (os: MiOS) => new Vuex.Store({
setUiHeaderHeight(state, height) {
state.uiHeaderHeight = height;
+ },
+
+ navHook(state, callback) {
+ state.navHook = callback;
}
},
diff --git a/src/client/theme/dark.json5 b/src/client/theme/dark.json5
index 59cff0ae44..deb4c4ceee 100644
--- a/src/client/theme/dark.json5
+++ b/src/client/theme/dark.json5
@@ -174,6 +174,7 @@
desktopSettingsNavItemHover: ':lighten<10<$text',
deckAcrylicColumnBg: 'rgba(0, 0, 0, 0.25)',
+ deckUserColumnBg: ':darken<3<@face',
mobileHeaderBg: ':lighten<5<$secondary',
mobileHeaderFg: '$text',
diff --git a/src/client/theme/light.json5 b/src/client/theme/light.json5
index a1b000530a..c5b3148834 100644
--- a/src/client/theme/light.json5
+++ b/src/client/theme/light.json5
@@ -174,6 +174,7 @@
desktopSettingsNavItemHover: ':darken<10<$text',
deckAcrylicColumnBg: 'rgba(0, 0, 0, 0.1)',
+ deckUserColumnBg: ':darken<4<@face',
mobileHeaderBg: ':lighten<5<$secondary',
mobileHeaderFg: '$text',