note-improvements (#9734)

Not sure if this is the best way to jump to the post

This also lets you select text w/out clicking to the post (and clicking normally on top of the text opens the post)

Co-authored-by: Freeplay <Freeplay@duck.com>
Reviewed-on: https://codeberg.org/calckey/calckey/pulls/9734
Co-authored-by: Free <freeplay@duck.com>
Co-committed-by: Free <freeplay@duck.com>
This commit is contained in:
Free 2023-03-20 02:31:02 +00:00 committed by Kainoa Kanter
parent d75a4e56e3
commit c2df136dda
4 changed files with 48 additions and 15 deletions

View file

@ -33,7 +33,7 @@
</div>
</div>
</div>
<article class="article" @contextmenu.stop="onContextmenu" @click="router.push(notePage(appearNote))">
<article class="article" @contextmenu.stop="onContextmenu" @click="noteClick">
<div class="main">
<div class="header-container">
<MkAvatar class="avatar" :user="appearNote.user"/>
@ -41,16 +41,16 @@
</div>
<div class="body">
<p v-if="appearNote.cw != null" class="cw">
<Mfm v-if="appearNote.cw != ''" class="text" :text="appearNote.cw" :author="appearNote.user" :i="$i" :custom-emojis="appearNote.emojis" @click.stop/>
<Mfm v-if="appearNote.cw != ''" class="text" :text="appearNote.cw" :author="appearNote.user" :custom-emojis="appearNote.emojis" :i="$i"/>
<XCwButton v-model="showContent" :note="appearNote"/>
</p>
<div v-show="appearNote.cw == null || showContent" class="content" :class="{ collapsed, isLong }">
<div class="text">
<Mfm v-if="appearNote.text" :text="appearNote.text" :author="appearNote.user" :i="$i" :custom-emojis="appearNote.emojis" @click.stop/>
<Mfm v-if="appearNote.text" :text="appearNote.text" :author="appearNote.user" :i="$i" :custom-emojis="appearNote.emojis"/>
<!-- <a v-if="appearNote.renote != null" class="rp">RN:</a> -->
<div v-if="translating || translation" class="translation">
<MkLoading v-if="translating" mini/>
<div v-else class="translated" @click.stop>
<div v-else class="translated">
<b>{{ i18n.t('translatedFrom', { x: translation.sourceLang }) }}: </b>
<Mfm :text="translation.text" :author="appearNote.user" :i="$i" :custom-emojis="appearNote.emojis"/>
</div>
@ -264,6 +264,14 @@ function focusAfter() {
focusNext(el.value);
}
function noteClick(e) {
if (document.getSelection().type === 'Range') {
e.stopPropagation();
} else {
router.push(notePage(appearNote))
}
}
function readPromo() {
os.api('promo/read', {
noteId: appearNote.id,

View file

@ -9,8 +9,8 @@
:tabindex="!isDeleted ? '-1' : null"
:class="{ renote: isRenote }"
>
<MkNoteSub v-for="note in conversation" :key="note.id" class="reply-to-more" :note="note" @click.self="router.push(notePage(note))"/>
<MkNoteSub v-if="appearNote.reply" :note="appearNote.reply" class="reply-to" @click.self="router.push(notePage(appearNote))"/>
<MkNoteSub v-for="note in conversation" :key="note.id" class="reply-to-more" :note="note"/>
<MkNoteSub v-if="appearNote.reply" :note="appearNote.reply" class="reply-to"/>
<div v-if="isRenote" class="renote">
<MkAvatar class="avatar" :user="note.user"/>
<i class="ph-repeat ph-bold ph-lg"></i>
@ -29,7 +29,7 @@
<MkVisibility :note="note"/>
</div>
</div>
<article class="article" @contextmenu.stop="onContextmenu">
<article ref="noteEl" class="article" @contextmenu.stop="onContextmenu" tabindex="-1">
<header class="header">
<MkAvatar class="avatar" :user="appearNote.user" :show-indicator="true"/>
<div class="body">
@ -99,7 +99,7 @@
</footer>
</div>
</article>
<MkNoteSub v-for="note in directReplies" :key="note.id" :note="note" class="reply" :conversation="replies" @click.self="router.push(notePage(note))"/>
<MkNoteSub v-for="note in directReplies" :key="note.id" :note="note" class="reply" :conversation="replies"/>
</div>
<div v-else class="_panel muted" @click="muted = false">
<I18n :src="i18n.ts.userSaysSomething" tag="small">
@ -113,7 +113,7 @@
</template>
<script lang="ts" setup>
import { computed, inject, onMounted, onUnmounted, reactive, ref } from 'vue';
import { computed, inject, onMounted, onUnmounted, onUpdated, reactive, ref } from 'vue';
import * as mfm from 'mfm-js';
import type * as misskey from 'calckey-js';
import MkNoteSub from '@/components/MkNoteSub.vue';
@ -175,6 +175,7 @@ const isRenote = (
);
const el = ref<HTMLElement>();
const noteEl = $ref();
const menuButton = ref<HTMLElement>();
const starButton = ref<InstanceType<typeof XStarButton>>();
const renoteButton = ref<InstanceType<typeof XRenoteButton>>();
@ -192,6 +193,8 @@ const showTicker = (defaultStore.state.instanceTicker === 'always') || (defaultS
const conversation = ref<misskey.entities.Note[]>([]);
const replies = ref<misskey.entities.Note[]>([]);
const directReplies = ref<misskey.entities.Note[]>([]);
let isScrolling;
const keymap = {
'r': () => reply(true),
@ -281,11 +284,11 @@ function showRenoteMenu(viaKeyboard = false): void {
}
function focus() {
el.value.focus();
noteEl.focus();
}
function blur() {
el.value.blur();
noteEl.blur();
}
os.api('notes/children', {
@ -302,6 +305,7 @@ if (appearNote.replyId) {
noteId: appearNote.replyId,
}).then(res => {
conversation.value = res.reverse();
focus();
});
}
@ -322,13 +326,26 @@ function onNoteReplied(noteData: NoteUpdatedEvent): void {
}
document.addEventListener("wheel", () => {
isScrolling = true;
})
onMounted(() => {
stream.on("noteUpdated", onNoteReplied);
isScrolling = false;
noteEl.scrollIntoView();
});
onUpdated(() => {
if (!isScrolling) {
noteEl.scrollIntoView()
}
})
onUnmounted(() => {
stream.off("noteUpdated", onNoteReplied);
});
</script>
<style lang="scss" scoped>
@ -434,7 +451,8 @@ onUnmounted(() => {
}
font-size: 1.2em;
overflow: clip;
outline: none;
scroll-margin-top: calc(var(--stickyTop) + 20vh);
> .header {
display: flex;
position: relative;

View file

@ -1,7 +1,7 @@
<template>
<div v-size="{ max: [450, 500] }" class="wrpstxzv" :class="{ children: depth > 1, singleStart: replies.length == 1, firstColumn: depth == 1 && conversation }">
<div v-if="conversation && depth > 1" class="line"></div>
<div class="main" @click="router.push(notePage(note))">
<div class="main" @click="noteClick">
<div class="avatar-container">
<MkAvatar class="avatar" :user="note.user"/>
<div v-if="(!conversation) || replies.length > 0" class="line"></div>
@ -19,7 +19,7 @@
<Mfm v-if="note.cw != ''" class="text" :text="note.cw" :author="note.user" :i="$i" :custom-emojis="note.emojis"/>
<XCwButton v-model="showContent" :note="note"/>
</p>
<div v-show="note.cw == null || showContent" class="content" @click="router.push(notePage(note))">
<div v-show="note.cw == null || showContent" class="content">
<MkSubNoteContent class="text" :note="note" :detailed="true" :parentId="note.parentId" :conversation="conversation"/>
</div>
</div>
@ -68,6 +68,14 @@ const props = withDefaults(defineProps<{
let showContent = $ref(false);
const replies: misskey.entities.Note[] = props.conversation?.filter(item => item.replyId === props.note.id || item.renoteId === props.note.id).reverse() ?? [];
function noteClick(e) {
if (document.getSelection().type === 'Range') {
e.stopPropagation();
} else {
router.push(notePage(props.note))
}
}
</script>
<style lang="scss" scoped>

View file

@ -88,7 +88,6 @@ html._themeChanging_ {
html, body {
margin: 0;
padding: 0;
scroll-behavior: smooth;
}
a {