Ported Firefish's note focus behavior
This commit is contained in:
parent
32f60f9969
commit
43b3b5a34b
2 changed files with 65 additions and 5 deletions
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
Loading…
Reference in a new issue