Compare commits

...

3 commits

Author SHA1 Message Date
cfba325ae7 Merge pull request 'frontend performance improvements' (#59) from sugar/forkey:frontend-performance-improvements into main
All checks were successful
Lint / pnpm_install (push) Successful in 34s
Test (production install and build) / production (22.x) (push) Successful in 1m4s
Lint / lint (misskey-js) (push) Successful in 36s
Lint / lint (sw) (push) Successful in 38s
Lint / lint (backend) (push) Successful in 1m4s
Lint / typecheck (misskey-js) (push) Successful in 35s
Lint / typecheck (backend) (push) Successful in 1m24s
Lint / lint (frontend) (push) Successful in 7m16s
Reviewed-on: #59
Reviewed-by: leah <leah@noreply.woem.men>
2025-02-07 18:36:39 +00:00
71606c5507 avoid computing tooltip position every frame
All checks were successful
Lint / pnpm_install (pull_request) Successful in 2m59s
Test (frontend) / vitest (22.x) (pull_request) Successful in 2m56s
Test (production install and build) / production (22.x) (pull_request) Successful in 2m16s
Lint / lint (backend) (pull_request) Successful in 2m26s
Lint / lint (frontend) (pull_request) Successful in 9m0s
Lint / lint (misskey-js) (pull_request) Successful in 1m59s
Lint / lint (sw) (pull_request) Successful in 2m13s
Lint / typecheck (backend) (pull_request) Successful in 2m41s
Lint / typecheck (misskey-js) (pull_request) Successful in 1m57s
this fixes an issue causing misskey to constantly recompute tooltip
position when any kind of chart is being displayed (such as the one
on user profile page, or any page for unauthenticated users)
2025-02-02 17:33:33 +01:00
8165088886 only run parallax effect when scrolling user profile
running animation handler every frame is slow
2025-02-02 16:58:14 +01:00
2 changed files with 45 additions and 13 deletions

View file

@ -23,7 +23,7 @@ SPDX-License-Identifier: AGPL-3.0-only
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { nextTick, onMounted, onUnmounted, shallowRef } from 'vue'; import { nextTick, onMounted, onUnmounted, shallowRef, watch } from 'vue';
import * as os from '@/os.js'; import * as os from '@/os.js';
import { calcPopupPosition } from '@/scripts/popup-position.js'; import { calcPopupPosition } from '@/scripts/popup-position.js';
import { defaultStore } from '@/store.js'; import { defaultStore } from '@/store.js';
@ -70,7 +70,7 @@ function setPosition() {
el.value.style.top = data.top + 'px'; el.value.style.top = data.top + 'px';
} }
let loopHandler; let loopHandler: number | undefined;
onMounted(() => { onMounted(() => {
nextTick(() => { nextTick(() => {
@ -81,12 +81,23 @@ onMounted(() => {
loopHandler = window.requestAnimationFrame(loop); loopHandler = window.requestAnimationFrame(loop);
}; };
watch(() => props.showing, show => {
if (show) {
if (!loopHandler) {
loop(); loop();
}
} else if (loopHandler) {
window.cancelAnimationFrame(loopHandler);
loopHandler = undefined;
}
});
}); });
}); });
onUnmounted(() => { onUnmounted(() => {
if (loopHandler) {
window.cancelAnimationFrame(loopHandler); window.cancelAnimationFrame(loopHandler);
}
}); });
</script> </script>

View file

@ -225,7 +225,7 @@ import MkTextarea from '@/components/MkTextarea.vue';
import MkOmit from '@/components/MkOmit.vue'; import MkOmit from '@/components/MkOmit.vue';
import MkInfo from '@/components/MkInfo.vue'; import MkInfo from '@/components/MkInfo.vue';
import MkButton from '@/components/MkButton.vue'; import MkButton from '@/components/MkButton.vue';
import { getScrollPosition } from '@/scripts/scroll.js'; import { getScrollContainer } from '@/scripts/scroll.js';
import { getUserMenu } from '@/scripts/get-user-menu.js'; import { getUserMenu } from '@/scripts/get-user-menu.js';
import number from '@/filters/number.js'; import number from '@/filters/number.js';
import { userPage } from '@/filters/user.js'; import { userPage } from '@/filters/user.js';
@ -282,6 +282,7 @@ const isEditingMemo = ref(false);
const moderationNote = ref(props.user.moderationNote); const moderationNote = ref(props.user.moderationNote);
const editModerationNote = ref(false); const editModerationNote = ref(false);
const movedFromLog = ref<null | {movedFromId:string;}[]>(null); const movedFromLog = ref<null | {movedFromId:string;}[]>(null);
let scrollEl: null | HTMLElement = null;
watch(moderationNote, async () => { watch(moderationNote, async () => {
await misskeyApi('admin/update-user-note', { userId: props.user.id, text: moderationNote.value }); await misskeyApi('admin/update-user-note', { userId: props.user.id, text: moderationNote.value });
@ -313,15 +314,19 @@ async function fetchMovedFromLog() {
} }
function parallaxLoop() { function parallaxLoop() {
parallaxAnimationId.value = window.requestAnimationFrame(parallaxLoop); requestNextParallaxFrame();
parallax(); parallax();
} }
function requestNextParallaxFrame() {
parallaxAnimationId.value = window.requestAnimationFrame(parallaxLoop);
}
function parallax() { function parallax() {
const banner = bannerEl.value as any; const banner = bannerEl.value as any;
if (banner == null) return; if (banner == null) return;
const top = getScrollPosition(rootEl.value); const top = scrollEl?.scrollTop ?? scrollY;
if (top < 0) return; if (top < 0) return;
@ -330,6 +335,23 @@ function parallax() {
banner.style.backgroundPosition = `center calc(50% - ${pos}px)`; banner.style.backgroundPosition = `center calc(50% - ${pos}px)`;
} }
function startParallax() {
(scrollEl ?? window).removeEventListener('scroll', startParallax);
requestNextParallaxFrame();
}
function addScrollEvent() {
(scrollEl ?? window).addEventListener('scroll', startParallax);
}
function cancelParallax() {
if (parallaxAnimationId.value) {
window.cancelAnimationFrame(parallaxAnimationId.value);
parallaxAnimationId.value = null;
addScrollEvent();
}
}
function showMemoTextarea() { function showMemoTextarea() {
isEditingMemo.value = true; isEditingMemo.value = true;
nextTick(() => { nextTick(() => {
@ -394,7 +416,10 @@ watch([props.user], () => {
}); });
onMounted(() => { onMounted(() => {
window.requestAnimationFrame(parallaxLoop); scrollEl = getScrollContainer(rootEl.value);
addScrollEvent();
(scrollEl ?? window).addEventListener('scrollend', cancelParallax);
parallax();
narrow.value = rootEl.value!.clientWidth < 1000; narrow.value = rootEl.value!.clientWidth < 1000;
if (props.user.birthday) { if (props.user.birthday) {
@ -417,11 +442,7 @@ onMounted(() => {
}); });
}); });
onUnmounted(() => { onUnmounted(cancelParallax);
if (parallaxAnimationId.value) {
window.cancelAnimationFrame(parallaxAnimationId.value);
}
});
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>