Ported Firefish's note focus behavior

This commit is contained in:
Volpeon 2024-01-03 13:52:46 +01:00
parent 32f60f9969
commit 43b3b5a34b
No known key found for this signature in database
2 changed files with 65 additions and 5 deletions

View file

@ -776,6 +776,10 @@ function focusAfter() {
focusNext(el.value); focusNext(el.value);
} }
function scrollIntoView() {
el.value.scrollIntoView();
}
function readPromo() { function readPromo() {
os.api('promo/read', { os.api('promo/read', {
noteId: appearNote.value.id, noteId: appearNote.value.id,
@ -790,6 +794,12 @@ function emitUpdReaction(emoji: string, delta: number) {
emit('reaction', emoji); emit('reaction', emoji);
} }
} }
defineExpose({
focus,
blur,
scrollIntoView,
});
</script> </script>
<style lang="scss" module> <style lang="scss" module>
@ -824,7 +834,7 @@ function emitUpdReaction(emoji: string, delta: number) {
margin: auto; margin: auto;
width: calc(100% - 8px); width: calc(100% - 8px);
height: calc(100% - 8px); height: calc(100% - 8px);
border: dashed 1px var(--focus); border: solid 1px var(--focus);
border-radius: var(--radius); border-radius: var(--radius);
box-sizing: border-box; box-sizing: border-box;
} }

View file

@ -43,7 +43,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<SkNoteSub v-for="note in conversation" :key="note.id" :class="$style.replyToMore" :note="note" :expandAllCws="props.expandAllCws"/> <SkNoteSub v-for="note in conversation" :key="note.id" :class="$style.replyToMore" :note="note" :expandAllCws="props.expandAllCws"/>
</template> </template>
<SkNoteSub v-if="appearNote.reply" :note="appearNote.reply" :class="$style.replyTo" :expandAllCws="props.expandAllCws"/> <SkNoteSub v-if="appearNote.reply" :note="appearNote.reply" :class="$style.replyTo" :expandAllCws="props.expandAllCws"/>
<article :class="$style.note" @contextmenu.stop="onContextmenu"> <article ref="noteEl" :class="$style.note" tabindex="-1" @contextmenu.stop="onContextmenu">
<header :class="$style.noteHeader"> <header :class="$style.noteHeader">
<MkAvatar :class="$style.noteHeaderAvatar" :user="appearNote.user" indicator link preview/> <MkAvatar :class="$style.noteHeaderAvatar" :user="appearNote.user" indicator link preview/>
<div style="display: flex; align-items: center; white-space: nowrap; overflow: hidden;"> <div style="display: flex; align-items: center; white-space: nowrap; overflow: hidden;">
@ -228,7 +228,7 @@ SPDX-License-Identifier: AGPL-3.0-only
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { computed, inject, onMounted, provide, ref, shallowRef, watch } from 'vue'; import { computed, inject, onMounted, onUnmounted, onUpdated, provide, ref, shallowRef, watch } from 'vue';
import * as mfm from '@sharkey/sfm-js'; import * as mfm from '@sharkey/sfm-js';
import * as Misskey from 'misskey-js'; import * as Misskey from 'misskey-js';
import SkNoteSub from '@/components/SkNoteSub.vue'; import SkNoteSub from '@/components/SkNoteSub.vue';
@ -301,6 +301,7 @@ const isRenote = (
); );
const el = shallowRef<HTMLElement>(); const el = shallowRef<HTMLElement>();
const noteEl = shallowRef<HTMLElement>();
const menuButton = shallowRef<HTMLElement>(); const menuButton = shallowRef<HTMLElement>();
const menuVersionsButton = shallowRef<HTMLElement>(); const menuVersionsButton = shallowRef<HTMLElement>();
const renoteButton = shallowRef<HTMLElement>(); const renoteButton = shallowRef<HTMLElement>();
@ -731,11 +732,11 @@ function showRenoteMenu(viaKeyboard = false): void {
} }
function focus() { function focus() {
el.value.focus(); noteEl.value?.focus();
} }
function blur() { function blur() {
el.value.blur(); noteEl.value?.blur();
} }
const repliesLoaded = ref(false); const repliesLoaded = ref(false);
@ -776,6 +777,7 @@ function loadConversation() {
noteId: appearNote.value.replyId, noteId: appearNote.value.replyId,
}).then(res => { }).then(res => {
conversation.value = res.reverse(); conversation.value = res.reverse();
focus();
}); });
} }
@ -792,6 +794,31 @@ function animatedMFM() {
}).then((res) => { if (!res.canceled) allowAnim.value = true; }); }).then((res) => { if (!res.canceled) allowAnim.value = true; });
} }
} }
let isScrolling = false;
function setScrolling() {
isScrolling = true;
}
onMounted(() => {
document.addEventListener('wheel', setScrolling);
isScrolling = false;
noteEl.value?.scrollIntoView({ block: 'center' });
});
onUpdated(() => {
if (!isScrolling) {
noteEl.value?.scrollIntoView({ block: 'center' });
if (location.hash) {
location.replace(location.hash); // Jump to highlighted reply
}
}
});
onUnmounted(() => {
document.removeEventListener('wheel', setScrolling);
});
</script> </script>
<style lang="scss" module> <style lang="scss" module>
@ -863,6 +890,7 @@ function animatedMFM() {
} }
.note { .note {
position: relative;
padding: 32px; padding: 32px;
font-size: 1.2em; font-size: 1.2em;
overflow: hidden; overflow: hidden;
@ -870,6 +898,28 @@ function animatedMFM() {
&:hover > .main > .footer > .button { &:hover > .main > .footer > .button {
opacity: 1; opacity: 1;
} }
&:focus-visible {
outline: none;
&:after {
content: "";
pointer-events: none;
display: block;
position: absolute;
z-index: 10;
top: 0;
left: 0;
right: 0;
bottom: 0;
margin: auto;
width: calc(100% - 8px);
height: calc(100% - 8px);
border: solid 1px var(--focus);
border-radius: var(--radius);
box-sizing: border-box;
}
}
} }
.noteHeader { .noteHeader {