Resolve #2900
This commit is contained in:
parent
5dce81c0db
commit
99073b56df
|
@ -883,6 +883,11 @@ desktop/views/components/settings.vue:
|
||||||
task-manager: "タスクマネージャ"
|
task-manager: "タスクマネージャ"
|
||||||
third-parties: "サードパーティ"
|
third-parties: "サードパーティ"
|
||||||
|
|
||||||
|
navbar-position: "ナビゲーションバーの位置"
|
||||||
|
navbar-position-top: "上"
|
||||||
|
navbar-position-left: "左"
|
||||||
|
navbar-position-right: "右"
|
||||||
|
|
||||||
desktop/views/components/settings.2fa.vue:
|
desktop/views/components/settings.2fa.vue:
|
||||||
intro: "二段階認証を設定すると、サインイン時にパスワードだけでなく、予め登録しておいた物理的なデバイス(例えばあなたのスマートフォンなど)も必要になり、よりセキュリティが向上します。"
|
intro: "二段階認証を設定すると、サインイン時にパスワードだけでなく、予め登録しておいた物理的なデバイス(例えばあなたのスマートフォンなど)も必要になり、よりセキュリティが向上します。"
|
||||||
detail: "詳細..."
|
detail: "詳細..."
|
||||||
|
|
|
@ -88,6 +88,13 @@
|
||||||
<ui-switch v-model="disableAnimatedMfm">%i18n:common.disable-animated-mfm%</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_showBoardLabels">%i18n:common.show-reversi-board-labels%</ui-switch>
|
||||||
<ui-switch v-model="games_reversi_useContrastStones">%i18n:common.use-contrast-reversi-stones%</ui-switch>
|
<ui-switch v-model="games_reversi_useContrastStones">%i18n:common.use-contrast-reversi-stones%</ui-switch>
|
||||||
|
|
||||||
|
<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>
|
</section>
|
||||||
|
|
||||||
<section class="web" v-show="page == 'web'">
|
<section class="web" v-show="page == 'web'">
|
||||||
|
@ -293,6 +300,11 @@ export default Vue.extend({
|
||||||
set(value) { this.$store.commit('device/set', { key: 'darkmode', value }); }
|
set(value) { this.$store.commit('device/set', { key: 'darkmode', value }); }
|
||||||
},
|
},
|
||||||
|
|
||||||
|
navbar: {
|
||||||
|
get() { return this.$store.state.device.navbar; },
|
||||||
|
set(value) { this.$store.commit('device/set', { key: 'navbar', value }); }
|
||||||
|
},
|
||||||
|
|
||||||
enableSounds: {
|
enableSounds: {
|
||||||
get() { return this.$store.state.device.enableSounds; },
|
get() { return this.$store.state.device.enableSounds; },
|
||||||
set(value) { this.$store.commit('device/set', { key: 'enableSounds', value }); }
|
set(value) { this.$store.commit('device/set', { key: 'enableSounds', value }); }
|
||||||
|
|
237
src/client/app/desktop/views/components/ui.sidebar.vue
Normal file
237
src/client/app/desktop/views/components/ui.sidebar.vue
Normal file
|
@ -0,0 +1,237 @@
|
||||||
|
<template>
|
||||||
|
<div class="header" :class="$store.state.device.navbar">
|
||||||
|
<div class="post">
|
||||||
|
<button @click="post" title="%i18n:@post%">%fa:pencil-alt%</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="nav" v-if="$store.getters.isSignedIn">
|
||||||
|
<div class="home" :class="{ active: $route.name == 'index' }" @click="goToTop">
|
||||||
|
<router-link to="/">%fa:home%</router-link>
|
||||||
|
</div>
|
||||||
|
<div class="deck" :class="{ active: $route.name == 'deck' }" @click="goToTop">
|
||||||
|
<router-link to="/deck">%fa:columns%</router-link>
|
||||||
|
</div>
|
||||||
|
<div class="messaging">
|
||||||
|
<a @click="messaging">%fa:comments%<template v-if="hasUnreadMessagingMessage">%fa:circle%</template></a>
|
||||||
|
</div>
|
||||||
|
<div class="game">
|
||||||
|
<a @click="game">%fa:gamepad%<template v-if="hasGameInvitations">%fa:circle%</template></a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="nav bottom" v-if="$store.getters.isSignedIn">
|
||||||
|
<div>
|
||||||
|
<a @click="drive">%fa:cloud%</a>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<router-link to="/i/favorites">%fa:star%</router-link>
|
||||||
|
</div>
|
||||||
|
<div v-if="($store.state.i.isLocked || $store.state.i.carefulBot)">
|
||||||
|
<a @click="followRequests">%fa:envelope R%<i v-if="$store.state.i.pendingReceivedFollowRequestsCount">{{ $store.state.i.pendingReceivedFollowRequestsCount }}</i></a>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<a @click="settings">%fa:cog%</a>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<a @click="dark"><template v-if="$store.state.device.darkmode">%fa:moon%</template><template v-else>%fa:R moon%</template></a>
|
||||||
|
</div>
|
||||||
|
<div class="signout">
|
||||||
|
<a @click="signout">%fa:power-off%</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="account">
|
||||||
|
<router-link :to="`/@${ $store.state.i.username }`">
|
||||||
|
<mk-avatar class="avatar" :user="$store.state.i"/>
|
||||||
|
</router-link>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import Vue from 'vue';
|
||||||
|
import MkUserListsWindow from './user-lists-window.vue';
|
||||||
|
import MkFollowRequestsWindow from './received-follow-requests-window.vue';
|
||||||
|
import MkSettingsWindow from './settings-window.vue';
|
||||||
|
import MkDriveWindow from './drive-window.vue';
|
||||||
|
import MkMessagingWindow from './messaging-window.vue';
|
||||||
|
import MkGameWindow from './game-window.vue';
|
||||||
|
|
||||||
|
export default Vue.extend({
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
hasGameInvitations: false,
|
||||||
|
connection: null
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
computed: {
|
||||||
|
hasUnreadMessagingMessage(): boolean {
|
||||||
|
return this.$store.getters.isSignedIn && this.$store.state.i.hasUnreadMessagingMessage;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
mounted() {
|
||||||
|
if (this.$store.getters.isSignedIn) {
|
||||||
|
this.connection = (this as any).os.stream.useSharedConnection('main');
|
||||||
|
|
||||||
|
this.connection.on('reversiInvited', this.onReversiInvited);
|
||||||
|
this.connection.on('reversi_no_invites', this.onReversiNoInvites);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
beforeDestroy() {
|
||||||
|
if (this.$store.getters.isSignedIn) {
|
||||||
|
this.connection.dispose();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
methods: {
|
||||||
|
onReversiInvited() {
|
||||||
|
this.hasGameInvitations = true;
|
||||||
|
},
|
||||||
|
|
||||||
|
onReversiNoInvites() {
|
||||||
|
this.hasGameInvitations = false;
|
||||||
|
},
|
||||||
|
|
||||||
|
messaging() {
|
||||||
|
(this as any).os.new(MkMessagingWindow);
|
||||||
|
},
|
||||||
|
|
||||||
|
game() {
|
||||||
|
(this as any).os.new(MkGameWindow);
|
||||||
|
},
|
||||||
|
|
||||||
|
post() {
|
||||||
|
(this as any).apis.post();
|
||||||
|
},
|
||||||
|
|
||||||
|
drive() {
|
||||||
|
(this as any).os.new(MkDriveWindow);
|
||||||
|
},
|
||||||
|
|
||||||
|
list() {
|
||||||
|
const w = (this as any).os.new(MkUserListsWindow);
|
||||||
|
w.$once('choosen', list => {
|
||||||
|
this.$router.push(`i/lists/${ list.id }`);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
followRequests() {
|
||||||
|
(this as any).os.new(MkFollowRequestsWindow);
|
||||||
|
},
|
||||||
|
|
||||||
|
settings() {
|
||||||
|
(this as any).os.new(MkSettingsWindow);
|
||||||
|
},
|
||||||
|
|
||||||
|
signout() {
|
||||||
|
(this as any).os.signout();
|
||||||
|
},
|
||||||
|
|
||||||
|
dark() {
|
||||||
|
this.$store.commit('device/set', {
|
||||||
|
key: 'darkmode',
|
||||||
|
value: !this.$store.state.device.darkmode
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
goToTop() {
|
||||||
|
window.scrollTo({
|
||||||
|
top: 0,
|
||||||
|
behavior: 'smooth'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="stylus" scoped>
|
||||||
|
.header
|
||||||
|
$width = 68px
|
||||||
|
|
||||||
|
position fixed
|
||||||
|
top 0
|
||||||
|
z-index 1000
|
||||||
|
width $width
|
||||||
|
height 100%
|
||||||
|
background var(--desktopHeaderBg)
|
||||||
|
box-shadow var(--shadow)
|
||||||
|
|
||||||
|
&.left
|
||||||
|
left 0
|
||||||
|
|
||||||
|
&.right
|
||||||
|
right 0
|
||||||
|
|
||||||
|
> .nav
|
||||||
|
> *
|
||||||
|
> *
|
||||||
|
display block
|
||||||
|
width $width
|
||||||
|
line-height 56px
|
||||||
|
text-align center
|
||||||
|
font-size 18px
|
||||||
|
color var(--desktopHeaderFg)
|
||||||
|
|
||||||
|
&:hover
|
||||||
|
color var(--desktopHeaderHoverFg)
|
||||||
|
text-decoration none
|
||||||
|
|
||||||
|
> .nav.bottom
|
||||||
|
position absolute
|
||||||
|
bottom 64px
|
||||||
|
left 0
|
||||||
|
|
||||||
|
> .post
|
||||||
|
width $width
|
||||||
|
height $width
|
||||||
|
padding 10px
|
||||||
|
|
||||||
|
> button
|
||||||
|
display inline-block
|
||||||
|
margin 0
|
||||||
|
padding 0 10px
|
||||||
|
height 100%
|
||||||
|
width 100%
|
||||||
|
font-size 1.2em
|
||||||
|
font-weight normal
|
||||||
|
text-decoration none
|
||||||
|
color var(--primaryForeground)
|
||||||
|
background var(--primary) !important
|
||||||
|
outline none
|
||||||
|
border none
|
||||||
|
border-radius 4px
|
||||||
|
transition background 0.1s ease
|
||||||
|
cursor pointer
|
||||||
|
|
||||||
|
*
|
||||||
|
pointer-events none
|
||||||
|
|
||||||
|
&:hover
|
||||||
|
background var(--primaryLighten10) !important
|
||||||
|
|
||||||
|
&:active
|
||||||
|
background var(--primaryDarken10) !important
|
||||||
|
transition background 0s ease
|
||||||
|
|
||||||
|
> .account
|
||||||
|
position absolute
|
||||||
|
bottom 0
|
||||||
|
left 0
|
||||||
|
width $width
|
||||||
|
height $width
|
||||||
|
padding 12px
|
||||||
|
|
||||||
|
> *
|
||||||
|
display block
|
||||||
|
width 100%
|
||||||
|
height 100%
|
||||||
|
|
||||||
|
> .avatar
|
||||||
|
pointer-events none
|
||||||
|
width 100%
|
||||||
|
height 100%
|
||||||
|
|
||||||
|
</style>
|
|
@ -1,8 +1,9 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="mk-ui" v-hotkey.global="keymap">
|
<div class="mk-ui" v-hotkey.global="keymap">
|
||||||
<div class="bg" v-if="$store.getters.isSignedIn && $store.state.i.wallpaperUrl" :style="style"></div>
|
<div class="bg" v-if="$store.getters.isSignedIn && $store.state.i.wallpaperUrl" :style="style"></div>
|
||||||
<x-header class="header" v-show="!zenMode" ref="header"/>
|
<x-header class="header" v-if="navbar == 'top'" v-show="!zenMode" ref="header"/>
|
||||||
<div class="content">
|
<x-sidebar class="sidebar" v-if="navbar != 'top'" ref="sidebar"/>
|
||||||
|
<div class="content" :class="[{ sidebar: navbar != 'top' }, navbar]">
|
||||||
<slot></slot>
|
<slot></slot>
|
||||||
</div>
|
</div>
|
||||||
<mk-stream-indicator v-if="$store.getters.isSignedIn"/>
|
<mk-stream-indicator v-if="$store.getters.isSignedIn"/>
|
||||||
|
@ -12,10 +13,12 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import Vue from 'vue';
|
import Vue from 'vue';
|
||||||
import XHeader from './ui.header.vue';
|
import XHeader from './ui.header.vue';
|
||||||
|
import XSidebar from './ui.sidebar.vue';
|
||||||
|
|
||||||
export default Vue.extend({
|
export default Vue.extend({
|
||||||
components: {
|
components: {
|
||||||
XHeader
|
XHeader,
|
||||||
|
XSidebar
|
||||||
},
|
},
|
||||||
|
|
||||||
data() {
|
data() {
|
||||||
|
@ -25,6 +28,10 @@ export default Vue.extend({
|
||||||
},
|
},
|
||||||
|
|
||||||
computed: {
|
computed: {
|
||||||
|
navbar(): string {
|
||||||
|
return this.$store.state.device.navbar;
|
||||||
|
},
|
||||||
|
|
||||||
style(): any {
|
style(): any {
|
||||||
if (!this.$store.getters.isSignedIn || this.$store.state.i.wallpaperUrl == null) return {};
|
if (!this.$store.getters.isSignedIn || this.$store.state.i.wallpaperUrl == null) return {};
|
||||||
return {
|
return {
|
||||||
|
@ -45,6 +52,12 @@ export default Vue.extend({
|
||||||
watch: {
|
watch: {
|
||||||
'$store.state.uiHeaderHeight'() {
|
'$store.state.uiHeaderHeight'() {
|
||||||
this.$el.style.paddingTop = this.$store.state.uiHeaderHeight + 'px';
|
this.$el.style.paddingTop = this.$store.state.uiHeaderHeight + 'px';
|
||||||
|
},
|
||||||
|
|
||||||
|
navbar() {
|
||||||
|
if (this.navbar != 'top') {
|
||||||
|
this.$store.commit('setUiHeaderHeight', 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -87,4 +100,10 @@ export default Vue.extend({
|
||||||
@media (max-width 1000px)
|
@media (max-width 1000px)
|
||||||
display none
|
display none
|
||||||
|
|
||||||
|
> .content.sidebar.left
|
||||||
|
padding-left 64px
|
||||||
|
|
||||||
|
> .content.sidebar.right
|
||||||
|
padding-right 64px
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -56,6 +56,7 @@ const defaultDeviceSettings = {
|
||||||
loadRawImages: false,
|
loadRawImages: false,
|
||||||
alwaysShowNsfw: false,
|
alwaysShowNsfw: false,
|
||||||
postStyle: 'standard',
|
postStyle: 'standard',
|
||||||
|
navbar: 'top',
|
||||||
mobileNotificationPosition: 'bottom'
|
mobileNotificationPosition: 'bottom'
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue