forked from FoundKeyGang/FoundKey
wip
This commit is contained in:
parent
80eefa92ce
commit
0336d640ec
7 changed files with 155 additions and 56 deletions
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 {
|
||||
|
|
44
src/client/ui/chat/header-clock.vue
Normal file
44
src/client/ui/chat/header-clock.vue
Normal file
|
@ -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>
|
|
@ -62,21 +62,27 @@
|
|||
|
||||
<main class="main" @contextmenu.stop="onContextmenu">
|
||||
<header class="header" ref="header" @click="onHeaderClick">
|
||||
<div v-if="tl === 'home'">
|
||||
<div class="left">
|
||||
<template v-if="tl === 'home'">
|
||||
<Fa :icon="faHome" class="icon"/>
|
||||
<div class="title">{{ $ts._timelines.home }}</div>
|
||||
</div>
|
||||
<div v-else-if="tl === 'local'">
|
||||
</template>
|
||||
<template v-else-if="tl === 'local'">
|
||||
<Fa :icon="faShareAlt" class="icon"/>
|
||||
<div class="title">{{ $ts._timelines.local }}</div>
|
||||
</div>
|
||||
<div v-else-if="tl === 'social'">
|
||||
</template>
|
||||
<template v-else-if="tl === 'social'">
|
||||
<Fa :icon="faShareAlt" class="icon"/>
|
||||
<div class="title">{{ $ts._timelines.social }}</div>
|
||||
</div>
|
||||
<div v-else-if="tl === 'global'">
|
||||
</template>
|
||||
<template v-else-if="tl === 'global'">
|
||||
<Fa :icon="faShareAlt" class="icon"/>
|
||||
<div class="title">{{ $ts._timelines.global }}</div>
|
||||
</template>
|
||||
</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 {
|
||||
|
|
|
@ -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,9 +892,11 @@ export default defineComponent({
|
|||
background: rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
|
||||
&:hover > .article > .main > .footer {
|
||||
&:hover, &.operating {
|
||||
> .article > .main > .footer {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
&.renote {
|
||||
background: rgba(128, 255, 0, 0.05);
|
||||
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
Loading…
Reference in a new issue