From 0336d640ecf223e179bc18e02f66dfc7b5c9ea19 Mon Sep 17 00:00:00 2001 From: syuilo <syuilotan@yahoo.co.jp> Date: Mon, 15 Feb 2021 17:17:19 +0900 Subject: [PATCH] wip --- src/client/components/note.vue | 4 +- src/client/directives/follow-append.ts | 2 - src/client/ui/chat/date-separated-list.vue | 15 ++++ src/client/ui/chat/header-clock.vue | 44 +++++++++++ src/client/ui/chat/index.vue | 91 +++++++++++++--------- src/client/ui/chat/note.vue | 47 +++++++---- src/client/ui/chat/timeline.vue | 8 +- 7 files changed, 155 insertions(+), 56 deletions(-) create mode 100644 src/client/ui/chat/header-clock.vue diff --git a/src/client/components/note.vue b/src/client/components/note.vue index b839ab3e8f..d532289857 100644 --- a/src/client/components/note.vue +++ b/src/client/components/note.vue @@ -1,6 +1,6 @@ <template> <div - class="note _panel" + class="tkcbzcuz _panel" v-if="!muted" v-show="!isDeleted" :tabindex="!isDeleted ? '-1' : null" @@ -858,7 +858,7 @@ export default defineComponent({ </script> <style lang="scss" scoped> -.note { +.tkcbzcuz { position: relative; transition: box-shadow 0.1s ease; overflow: hidden; diff --git a/src/client/directives/follow-append.ts b/src/client/directives/follow-append.ts index 9490dcf786..b0e99628b0 100644 --- a/src/client/directives/follow-append.ts +++ b/src/client/directives/follow-append.ts @@ -13,12 +13,10 @@ export default { const viewHeight = container.clientHeight; const height = container.scrollHeight; isBottom = (pos + viewHeight > height - 32); - console.log(isBottom); }, { passive: true }); container.scrollTop = container.scrollHeight; const ro = new ResizeObserver((entries, observer) => { - console.log(isBottom); if (isBottom) { const height = container.scrollHeight; container.scrollTop = height; diff --git a/src/client/ui/chat/date-separated-list.vue b/src/client/ui/chat/date-separated-list.vue index eb671510af..0120bf33f7 100644 --- a/src/client/ui/chat/date-separated-list.vue +++ b/src/client/ui/chat/date-separated-list.vue @@ -120,6 +120,20 @@ export default defineComponent({ .hmjzthxl { > .separator { text-align: center; + position: relative; + + &:before { + content: ""; + display: block; + position: absolute; + top: 50%; + left: 0; + right: 0; + margin: auto; + width: calc(100% - 32px); + height: 1px; + background: var(--divider); + } > .date { display: inline-block; @@ -130,6 +144,7 @@ export default defineComponent({ text-align: center; font-size: 12px; color: var(--dateLabelFg); + background: var(--panel); > span { &:first-child { diff --git a/src/client/ui/chat/header-clock.vue b/src/client/ui/chat/header-clock.vue new file mode 100644 index 0000000000..65573d460b --- /dev/null +++ b/src/client/ui/chat/header-clock.vue @@ -0,0 +1,44 @@ +<template> +<div class="_monospace"> + <span> + <span v-text="hh"></span> + <span :style="{ visibility: showColon ? 'visible' : 'hidden' }">:</span> + <span v-text="mm"></span> + <span :style="{ visibility: showColon ? 'visible' : 'hidden' }">:</span> + <span v-text="ss"></span> + </span> +</div> +</template> + +<script lang="ts"> +import { defineComponent } from 'vue'; +import * as os from '@/os'; + +export default defineComponent({ + data() { + return { + clock: null, + hh: null, + mm: null, + ss: null, + showColon: true, + }; + }, + created() { + this.tick(); + this.clock = setInterval(this.tick, 1000); + }, + beforeUnmount() { + clearInterval(this.clock); + }, + methods: { + tick() { + const now = new Date(); + this.hh = now.getHours().toString().padStart(2, '0'); + this.mm = now.getMinutes().toString().padStart(2, '0'); + this.ss = now.getSeconds().toString().padStart(2, '0'); + this.showColon = now.getSeconds() % 2 === 0; + } + } +}); +</script> diff --git a/src/client/ui/chat/index.vue b/src/client/ui/chat/index.vue index 56a1364f16..678ba2c7a8 100644 --- a/src/client/ui/chat/index.vue +++ b/src/client/ui/chat/index.vue @@ -62,21 +62,27 @@ <main class="main" @contextmenu.stop="onContextmenu"> <header class="header" ref="header" @click="onHeaderClick"> - <div v-if="tl === 'home'"> - <Fa :icon="faHome" class="icon"/> - <div class="title">{{ $ts._timelines.home }}</div> + <div class="left"> + <template v-if="tl === 'home'"> + <Fa :icon="faHome" class="icon"/> + <div class="title">{{ $ts._timelines.home }}</div> + </template> + <template v-else-if="tl === 'local'"> + <Fa :icon="faShareAlt" class="icon"/> + <div class="title">{{ $ts._timelines.local }}</div> + </template> + <template v-else-if="tl === 'social'"> + <Fa :icon="faShareAlt" class="icon"/> + <div class="title">{{ $ts._timelines.social }}</div> + </template> + <template v-else-if="tl === 'global'"> + <Fa :icon="faShareAlt" class="icon"/> + <div class="title">{{ $ts._timelines.global }}</div> + </template> </div> - <div v-else-if="tl === 'local'"> - <Fa :icon="faShareAlt" class="icon"/> - <div class="title">{{ $ts._timelines.local }}</div> - </div> - <div v-else-if="tl === 'social'"> - <Fa :icon="faShareAlt" class="icon"/> - <div class="title">{{ $ts._timelines.social }}</div> - </div> - <div v-else-if="tl === 'global'"> - <Fa :icon="faShareAlt" class="icon"/> - <div class="title">{{ $ts._timelines.global }}</div> + + <div class="right"> + <XHeaderClock/> </div> </header> <div class="body"> @@ -105,6 +111,7 @@ import XCommon from '../_common_/common.vue'; import XSide from './side.vue'; import XTimeline from './timeline.vue'; import XPostForm from './post-form.vue'; +import XHeaderClock from './header-clock.vue'; import * as os from '@/os'; import { sidebarDef } from '@/sidebar'; @@ -115,6 +122,7 @@ export default defineComponent({ XSide, // NOTE: dynamic importするとAsyncComponentWrapperが間に入るせいでref取得できなくて面倒になる XTimeline, XPostForm, + XHeaderClock, }, provide() { @@ -260,6 +268,29 @@ export default defineComponent({ border-top: solid 1px var(--divider); } + > .left, > .right { + > .item, > .menu { + height: ($header-height - ($padding * 2)); + width: ($header-height - ($padding * 2)); + padding: 10px; + box-sizing: border-box; + margin-right: 4px; + //opacity: 0.6; + position: relative; + line-height: initial; + + > i { + position: absolute; + top: 8px; + right: 8px; + color: var(--indicator); + font-size: 8px; + line-height: 8px; + animation: blink 1s infinite; + } + } + } + > .left { > .account { display: flex; @@ -276,26 +307,6 @@ export default defineComponent({ > .right { margin-left: auto; - - > .item { - height: ($header-height - ($padding * 2)); - width: ($header-height - ($padding * 2)); - padding: 10px; - box-sizing: border-box; - margin-right: 4px; - //opacity: 0.6; - position: relative; - - > i { - position: absolute; - top: 8px; - right: 8px; - color: var(--indicator); - font-size: 8px; - line-height: 8px; - animation: blink 1s infinite; - } - } } } @@ -358,18 +369,19 @@ export default defineComponent({ > .header { $padding: 8px; + display: flex; z-index: 1000; height: $header-height; padding: $padding; box-sizing: border-box; line-height: ($header-height - ($padding * 2)); - font-weight: bold; background-color: var(--panel); border-bottom: solid 1px var(--divider); user-select: none; - > div { + > .left { display: flex; + font-weight: bold; > .icon { height: ($header-height - ($padding * 2)); @@ -380,10 +392,15 @@ export default defineComponent({ opacity: 0.6; } } + + > .right { + margin-left: auto; + padding: 0 8px; + } } > .footer { - padding: 16px; + padding: 0 16px 16px 16px; } > .body { diff --git a/src/client/ui/chat/note.vue b/src/client/ui/chat/note.vue index f17f459625..cfc385bdf0 100644 --- a/src/client/ui/chat/note.vue +++ b/src/client/ui/chat/note.vue @@ -1,10 +1,10 @@ <template> <div - class="note" + class="vfzoeqcg" v-if="!muted" v-show="!isDeleted" :tabindex="!isDeleted ? '-1' : null" - :class="{ renote: isRenote }" + :class="{ renote: isRenote, operating }" v-hotkey="keymap" > <XSub :note="appearNote.reply" class="reply-to" v-if="appearNote.reply"/> @@ -171,6 +171,7 @@ export default defineComponent({ collapsed: false, isDeleted: false, muted: false, + operating: false, faEdit, faBolt, faTimes, faBullhorn, faPlus, faMinus, faRetweet, faReply, faReplyAll, faEllipsisH, faHome, faUnlock, faEnvelope, faThumbtack, faBan, faBiohazard, faPlug, faSatelliteDish }; }, @@ -439,16 +440,19 @@ export default defineComponent({ reply(viaKeyboard = false) { pleaseLogin(); + this.operating = true; os.post({ reply: this.appearNote, animation: !viaKeyboard, }, () => { + this.operating = false; this.focus(); }); }, renote(viaKeyboard = false) { pleaseLogin(); + this.operating = true; this.blur(); os.modalMenu([{ text: this.$ts.renote, @@ -468,6 +472,8 @@ export default defineComponent({ } }], this.$refs.renoteButton, { viaKeyboard + }).then(() => { + this.operating = false; }); }, @@ -494,10 +500,11 @@ export default defineComponent({ }); }, - react(viaKeyboard = false) { + async react(viaKeyboard = false) { pleaseLogin(); + this.operating = true; this.blur(); - os.popup(import('@/components/emoji-picker.vue'), { + const { dispose } = await os.popup(import('@/components/emoji-picker.vue'), { src: this.$refs.reactButton, asReactionPicker: true }, { @@ -508,9 +515,13 @@ export default defineComponent({ reaction: reaction }); } - this.focus(); }, - }, 'closed'); + closed: () => { + this.operating = false; + this.focus(); + dispose(); + } + }); }, reactDirectly(reaction) { @@ -734,9 +745,13 @@ export default defineComponent({ }, menu(viaKeyboard = false) { + this.operating = true; os.modalMenu(this.getMenu(), this.$refs.menuButton, { viaKeyboard - }).then(this.focus); + }).then(() => { + this.operating = false; + this.focus(); + }); }, showRenoteMenu(viaKeyboard = false) { @@ -857,10 +872,8 @@ export default defineComponent({ </script> <style lang="scss" scoped> -.note { +.vfzoeqcg { position: relative; - transition: box-shadow 0.1s ease; - overflow: hidden; contain: content; // これらの指定はパフォーマンス向上には有効だが、ノートの高さは一定でないため、 @@ -879,8 +892,10 @@ export default defineComponent({ background: rgba(0, 0, 0, 0.05); } - &:hover > .article > .main > .footer { - display: block; + &:hover, &.operating { + > .article > .main > .footer { + display: block; + } } &.renote { @@ -983,8 +998,8 @@ export default defineComponent({ > .avatar { flex-shrink: 0; display: block; - //position: sticky; - //top: 72px; + position: sticky; + top: 12px; margin: 0 14px 0 0; width: 46px; height: 46px; @@ -1122,5 +1137,9 @@ export default defineComponent({ .muted { padding: 8px 16px; opacity: 0.7; + + &:hover { + background: rgba(0, 0, 0, 0.05); + } } </style> diff --git a/src/client/ui/chat/timeline.vue b/src/client/ui/chat/timeline.vue index 3a32b9faee..d73a40dab5 100644 --- a/src/client/ui/chat/timeline.vue +++ b/src/client/ui/chat/timeline.vue @@ -1,5 +1,5 @@ <template> -<XNotes ref="tl" :pagination="pagination" @queue="$emit('queue', $event)" v-follow="pagination.reversed"/> +<XNotes class="dbiokgaf" ref="tl" :pagination="pagination" @queue="$emit('queue', $event)" v-follow="pagination.reversed"/> </template> <script lang="ts"> @@ -188,3 +188,9 @@ export default defineComponent({ } }); </script> + +<style lang="scss" scoped> +.dbiokgaf { + padding: 16px 0; +} +</style>