diff --git a/src/client/components/modal-page-window.vue b/src/client/components/modal-page-window.vue index e7d96f7a6f..f57516360d 100644 --- a/src/client/components/modal-page-window.vue +++ b/src/client/components/modal-page-window.vue @@ -3,10 +3,11 @@ <div class="hrmcaedk _window _narrow_" :style="{ width: `${width}px`, height: (height ? `min(${height}px, 100%)` : '100%') }"> <div class="header" @contextmenu="onContextmenu"> <span class="title"> - <XHeader :info="pageInfo" :back-button="history.length > 0" @back="back()" :close-button="true" @close="$refs.modal.close()"/> + </span> </div> <div class="body _flat_"> + <XHeader :info="pageInfo"/> <keep-alive> <component :is="component" v-bind="props" :ref="changePage"/> </keep-alive> diff --git a/src/client/components/page-window.vue b/src/client/components/page-window.vue index fbc9f0b7fd..a8a8b76100 100644 --- a/src/client/components/page-window.vue +++ b/src/client/components/page-window.vue @@ -3,14 +3,20 @@ :initial-width="500" :initial-height="500" :can-resize="true" - :close-button="false" + :close-button="true" :contextmenu="contextmenu" @closed="$emit('closed')" > <template #header> - <XHeader :info="pageInfo" :back-button="history.length > 0" @back="back()" :close-button="true" @close="close()" :title-only="true"/> + <template v-if="pageInfo"> + {{ pageInfo.title }} + </template> + </template> + <template #headerLeft> + <button v-if="history.length > 0" class="_button" @click="back()"><i class="fas fa-arrow-left"></i></button> </template> <div class="yrolvcoq _flat_"> + <XHeader :info="pageInfo"/> <component :is="component" v-bind="props" :ref="changePage"/> </div> </XWindow> diff --git a/src/client/components/ui/window.vue b/src/client/components/ui/window.vue index 773c3b9b13..6a7c61a7d5 100644 --- a/src/client/components/ui/window.vue +++ b/src/client/components/ui/window.vue @@ -3,11 +3,16 @@ <div class="ebkgocck" :class="{ front }" v-if="showing"> <div class="body _window _shadow _narrow_" @mousedown="onBodyMousedown" @keydown="onKeydown"> <div class="header" :class="{ mini }" @contextmenu.prevent.stop="onContextmenu"> - <button v-if="closeButton" class="_button" @click="close()"><i class="fas fa-times"></i></button> - + <span class="left"> + <slot name="headerLeft"></slot> + </span> <span class="title" @mousedown.prevent="onHeaderMousedown" @touchstart.prevent="onHeaderMousedown"> <slot name="header"></slot> </span> + <span class="right"> + <slot name="headerRight"></slot> + <button v-if="closeButton" class="_button" @click="close()"><i class="fas fa-times"></i></button> + </span> </div> <div class="body" v-if="padding"> <div class="_section"> @@ -418,12 +423,14 @@ export default defineComponent({ height: var(--height); border-bottom: solid 1px var(--divider); - > ::v-deep(button) { - height: var(--height); - width: var(--height); + > .left, > .right { + > ::v-deep(button) { + height: var(--height); + width: var(--height); - &:hover { - color: var(--fgHighlighted); + &:hover { + color: var(--fgHighlighted); + } } } diff --git a/src/client/directives/get-size.ts b/src/client/directives/get-size.ts new file mode 100644 index 0000000000..e3b5dea0f3 --- /dev/null +++ b/src/client/directives/get-size.ts @@ -0,0 +1,34 @@ +import { Directive } from 'vue'; + +export default { + mounted(src, binding, vn) { + const calc = () => { + const height = src.clientHeight; + const width = src.clientWidth; + + // 要素が(一時的に)DOMに存在しないときは計算スキップ + if (height === 0) return; + + binding.value(width, height); + }; + + calc(); + + // Vue3では使えなくなった + // 無くても大丈夫か...? + // TODO: ↑大丈夫じゃなかったので解決策を探す + //vn.context.$on('hook:activated', calc); + + const ro = new ResizeObserver((entries, observer) => { + calc(); + }); + ro.observe(src); + + src._get_size_ro_ = ro; + }, + + unmounted(src, binding, vn) { + binding.value(0, 0); + src._get_size_ro_.unobserve(src); + } +} as Directive; diff --git a/src/client/directives/index.ts b/src/client/directives/index.ts index f0a0123771..cd71bc26d3 100644 --- a/src/client/directives/index.ts +++ b/src/client/directives/index.ts @@ -2,6 +2,7 @@ import { App } from 'vue'; import userPreview from './user-preview'; import size from './size'; +import getSize from './get-size'; import particle from './particle'; import tooltip from './tooltip'; import hotkey from './hotkey'; @@ -14,6 +15,7 @@ export default function(app: App) { app.directive('userPreview', userPreview); app.directive('user-preview', userPreview); app.directive('size', size); + app.directive('get-size', getSize); app.directive('particle', particle); app.directive('tooltip', tooltip); app.directive('hotkey', hotkey); diff --git a/src/client/pages/settings/index.vue b/src/client/pages/settings/index.vue index cb86fdca71..3a8503ac55 100644 --- a/src/client/pages/settings/index.vue +++ b/src/client/pages/settings/index.vue @@ -74,6 +74,7 @@ export default defineComponent({ title: i18n.locale.settings, icon: 'fas fa-cog', bg: 'var(--bg)', + hide: true, }; const INFO = ref(indexInfo); const page = ref(props.initialPage); diff --git a/src/client/pages/settings/profile.vue b/src/client/pages/settings/profile.vue index 3c93e93480..eb9bc6565f 100644 --- a/src/client/pages/settings/profile.vue +++ b/src/client/pages/settings/profile.vue @@ -77,7 +77,8 @@ export default defineComponent({ [symbols.PAGE_INFO]: { title: this.$ts.profile, icon: 'fas fa-user', - bg: 'var(--bg)' + bg: 'var(--bg)', + hide: true, }, host, langs, diff --git a/src/client/ui/_common_/header.vue b/src/client/ui/_common_/header.vue index f21be2f9cd..5405c43f8c 100644 --- a/src/client/ui/_common_/header.vue +++ b/src/client/ui/_common_/header.vue @@ -1,10 +1,5 @@ <template> -<div class="fdidabkb" :class="{ slim: titleOnly || narrow }" :style="`--height:${height};`" :key="key"> - <transition :name="$store.state.animation ? 'header' : ''" mode="out-in" appear> - <div class="buttons left" v-if="backButton"> - <button class="_button button back" @click.stop="$emit('back')" @touchstart="preventDrag" v-tooltip="$ts.goBack"><i class="fas fa-chevron-left"></i></button> - </div> - </transition> +<div class="fdidabkb" :class="{ slim: narrow, thin }" :key="key"> <template v-if="info"> <div class="titleContainer" @click="showTabsPopup"> <i v-if="info.icon" class="icon" :class="info.icon"></i> @@ -34,7 +29,6 @@ <button v-for="action in info.actions" class="_button button" :class="{ highlighted: action.highlighted }" @click.stop="action.handler" @touchstart="preventDrag" v-tooltip="action.text"><i :class="action.icon"></i></button> </template> <button v-if="shouldShowMenu" class="_button button" @click.stop="showMenu" @touchstart="preventDrag" v-tooltip="$ts.menu"><i class="fas fa-ellipsis-h"></i></button> - <button v-if="closeButton" class="_button button" @click.stop="$emit('close')" @touchstart="preventDrag" v-tooltip="$ts.close"><i class="fas fa-times"></i></button> </div> </div> </template> @@ -52,20 +46,9 @@ export default defineComponent({ menu: { required: false }, - backButton: { - type: Boolean, + thin: { required: false, - default: false, - }, - closeButton: { - type: Boolean, - required: false, - default: false, - }, - titleOnly: { - type: Boolean, - required: false, - default: false, + default: false }, }, @@ -99,11 +82,9 @@ export default defineComponent({ }, mounted() { - this.height = this.$el.parentElement.offsetHeight + 'px'; - this.narrow = this.titleOnly || this.$el.parentElement.offsetWidth < 500; + this.narrow = this.$el.offsetWidth < 500; new ResizeObserver((entries, observer) => { - this.height = this.$el.parentElement.offsetHeight + 'px'; - this.narrow = this.titleOnly || this.$el.parentElement.offsetWidth < 500; + this.narrow = this.$el.offsetWidth < 500; }).observe(this.$el); }, @@ -161,8 +142,13 @@ export default defineComponent({ <style lang="scss" scoped> .fdidabkb { + --height: 60px; display: flex; + &.thin { + --height: 50px; + } + &.slim { text-align: center; @@ -220,6 +206,7 @@ export default defineComponent({ text-align: left; font-weight: bold; flex-shrink: 0; + margin-left: 24px; > .avatar { $size: 32px; diff --git a/src/client/ui/chat/index.vue b/src/client/ui/chat/index.vue index e8275def81..7090c9486a 100644 --- a/src/client/ui/chat/index.vue +++ b/src/client/ui/chat/index.vue @@ -74,7 +74,7 @@ <main class="main" @contextmenu.stop="onContextmenu"> <header class="header"> - <XHeader class="header" :info="pageInfo" :menu="menu" :center="false" :back-button="true" @back="back()" @click="onHeaderClick"/> + <XHeader class="header" :info="pageInfo" :menu="menu" :center="false" @click="onHeaderClick"/> </header> <router-view v-slot="{ Component }"> <transition :name="$store.state.animation ? 'page' : ''" mode="out-in" @enter="onTransition"> diff --git a/src/client/ui/chat/side.vue b/src/client/ui/chat/side.vue index ebf1cf9979..3e8904596d 100644 --- a/src/client/ui/chat/side.vue +++ b/src/client/ui/chat/side.vue @@ -1,7 +1,7 @@ <template> <div class="mrajymqm _narrow_" v-if="component"> <header class="header" @contextmenu.prevent.stop="onContextmenu"> - <XHeader class="title" :info="pageInfo" :center="false" :back-button="history.length > 0" @back="back()" :close-button="true" @close="close()"/> + <XHeader class="title" :info="pageInfo" :center="false"/> </header> <component :is="component" v-bind="props" :ref="changePage" class="body _flat_"/> </div> diff --git a/src/client/ui/deck/main-column.vue b/src/client/ui/deck/main-column.vue index 4c591022a5..42d963cda6 100644 --- a/src/client/ui/deck/main-column.vue +++ b/src/client/ui/deck/main-column.vue @@ -1,9 +1,12 @@ <template> <XColumn v-if="deckStore.state.alwaysShowMainColumn || $route.name !== 'index'" :column="column" :is-stacked="isStacked"> <template #header> - <XHeader :info="pageInfo" :back-button="true" @back="back()"/> + <template v-if="pageInfo"> + {{ pageInfo.title }} + </template> </template> + <XHeader :info="pageInfo"/> <router-view v-slot="{ Component }" class="_flat_"> <transition> <keep-alive :include="['timeline']"> diff --git a/src/client/ui/default.header.vue b/src/client/ui/default.header.vue index 6fbdd625c7..75c5c0c051 100644 --- a/src/client/ui/default.header.vue +++ b/src/client/ui/default.header.vue @@ -29,7 +29,7 @@ <MkAvatar :user="$i" class="avatar"/><MkAcct class="acct" :user="$i"/> </button> <div class="post" @click="post"> - <MkButton class="button" primary full> + <MkButton class="button" primary full rounded> <i class="fas fa-pencil-alt fa-fw"></i> </MkButton> </div> diff --git a/src/client/ui/default.side.vue b/src/client/ui/default.side.vue index 4d65779612..c453781e80 100644 --- a/src/client/ui/default.side.vue +++ b/src/client/ui/default.side.vue @@ -4,9 +4,10 @@ <header class="header" @contextmenu.prevent.stop="onContextmenu"> <button class="_button" @click="back()" v-if="history.length > 0"><i class="fas fa-chevron-left"></i></button> <button class="_button" style="pointer-events: none;" v-else><!-- マージンのバランスを取るためのダミー --></button> - <XHeader class="title" :info="pageInfo" :back-button="false"/> + <span class="title">{{ pageInfo.title }}</span> <button class="_button" @click="close()"><i class="fas fa-times"></i></button> </header> + <XHeader class="pageHeader" :info="pageInfo"/> <component :is="component" v-bind="props" :ref="changePage"/> </div> </div> diff --git a/src/client/ui/default.vue b/src/client/ui/default.vue index a5ec243e9e..4ceb3e1650 100644 --- a/src/client/ui/default.vue +++ b/src/client/ui/default.vue @@ -1,5 +1,5 @@ <template> -<div class="mk-app" :class="{ wallpaper, isMobile }"> +<div class="mk-app" :class="{ wallpaper, isMobile }" :style="`--headerHeight:` + headerHeight + 'px'"> <XHeaderMenu v-if="showMenuOnTop"/> <div class="columns" :class="{ fullView, withGlobalHeader: showMenuOnTop }"> @@ -14,7 +14,7 @@ <main class="main" @contextmenu.stop="onContextmenu" :style="{ background: pageInfo?.bg }"> <header class="header" @click="onHeaderClick"> - <XHeader :info="pageInfo" :back-button="true" @back="back()"/> + <XHeader :info="pageInfo" v-get-size="(w, h) => headerHeight = h" :thin="true"/> </header> <div class="content" :class="{ _flat_: !fullView }"> <router-view v-slot="{ Component }"> @@ -88,6 +88,7 @@ export default defineComponent({ data() { return { pageInfo: null, + headerHeight: 0, menuDef: menuDef, isMobile: window.innerWidth <= MOBILE_THRESHOLD, isDesktop: window.innerWidth >= DESKTOP_THRESHOLD, @@ -257,7 +258,6 @@ export default defineComponent({ } .mk-app { - $header-height: 50px; $ui-font-size: 1em; $widgets-hide-threshold: 1200px; $nav-icon-only-width: 78px; // TODO: どこかに集約したい @@ -330,7 +330,6 @@ export default defineComponent({ position: sticky; z-index: 1000; top: var(--globalHeaderHeight, 0px); - height: $header-height; -webkit-backdrop-filter: var(--blur, blur(32px)); backdrop-filter: var(--blur, blur(32px)); background-color: var(--header); @@ -338,11 +337,11 @@ export default defineComponent({ } > .content { - --stickyTop: calc(var(--globalHeaderHeight, 0px) + #{$header-height}); + --stickyTop: calc(var(--globalHeaderHeight, 0px) + var(--headerHeight)); } @media (max-width: 850px) { - padding-top: $header-height; + padding-top: var(--headerHeight); > .header { position: fixed; diff --git a/src/client/ui/universal.vue b/src/client/ui/universal.vue index ec9254b697..5b51752dda 100644 --- a/src/client/ui/universal.vue +++ b/src/client/ui/universal.vue @@ -1,10 +1,10 @@ <template> -<div class="mk-app" :class="{ wallpaper }"> +<div class="mk-app" :class="{ wallpaper }" :style="`--headerHeight:` + headerHeight + 'px'"> <XSidebar ref="nav" class="sidebar"/> <div class="contents" ref="contents" @contextmenu.stop="onContextmenu" :style="{ background: pageInfo?.bg }"> <header class="header" ref="header" @click="onHeaderClick" :style="{ background: pageInfo?.bg }"> - <XHeader :info="pageInfo" :back-button="true" @back="back()"/> + <XHeader v-if="!pageInfo?.hide" :info="pageInfo" v-get-size="(w, h) => headerHeight = h"/> </header> <main ref="main"> <div class="content"> @@ -86,6 +86,7 @@ export default defineComponent({ data() { return { pageInfo: null, + headerHeight: 0, isDesktop: window.innerWidth >= DESKTOP_THRESHOLD, menuDef: menuDef, navHidden: false, @@ -243,7 +244,6 @@ export default defineComponent({ } .mk-app { - $header-height: 58px; // TODO: どこかに集約したい $ui-font-size: 1em; // TODO: どこかに集約したい $widgets-hide-threshold: 1090px; @@ -263,19 +263,14 @@ export default defineComponent({ > .contents { width: 100%; min-width: 0; - --stickyTop: #{$header-height}; - padding-top: $header-height; + --stickyTop: var(--headerHeight); + padding-top: var(--headerHeight); background: var(--panel); > .header { position: fixed; z-index: 1000; top: 0; - height: $header-height; - width: 100%; - line-height: $header-height; - text-align: center; - font-weight: bold; //background-color: var(--panel); -webkit-backdrop-filter: var(--blur, blur(32px)); backdrop-filter: var(--blur, blur(32px)); @@ -287,13 +282,6 @@ export default defineComponent({ > main { min-width: 0; - > .content { - > * { - // ほんとは単に calc(100vh - #{$header-height}) と書きたいところだが... https://css-tricks.com/the-trick-to-viewport-units-on-mobile/ - min-height: calc((var(--vh, 1vh) * 100) - #{$header-height}); - } - } - > .spacer { height: 82px;