mirror of
https://github.com/MrUnknownDE/VRCX.git
synced 2026-05-07 06:56:04 +02:00
fix sidebar auto scroll on list update
This commit is contained in:
@@ -150,7 +150,7 @@
|
|||||||
size="icon-lg"
|
size="icon-lg"
|
||||||
style="margin-left: 5px"
|
style="margin-left: 5px"
|
||||||
@click="clearGroupRepresentation(groupDialog.id)">
|
@click="clearGroupRepresentation(groupDialog.id)">
|
||||||
<Star />
|
<BookmarkCheck />
|
||||||
</Button>
|
</Button>
|
||||||
</TooltipWrapper>
|
</TooltipWrapper>
|
||||||
<TooltipWrapper v-else side="top" :content="t('dialog.group.actions.represent_tooltip')">
|
<TooltipWrapper v-else side="top" :content="t('dialog.group.actions.represent_tooltip')">
|
||||||
@@ -161,7 +161,7 @@
|
|||||||
size="icon-lg"
|
size="icon-lg"
|
||||||
:disabled="groupDialog.ref.privacy === 'private'"
|
:disabled="groupDialog.ref.privacy === 'private'"
|
||||||
@click="setGroupRepresentation(groupDialog.id)">
|
@click="setGroupRepresentation(groupDialog.id)">
|
||||||
<Star />
|
<Bookmark />
|
||||||
</Button>
|
</Button>
|
||||||
</span>
|
</span>
|
||||||
</TooltipWrapper>
|
</TooltipWrapper>
|
||||||
@@ -1117,6 +1117,8 @@
|
|||||||
import {
|
import {
|
||||||
Bell,
|
Bell,
|
||||||
BellOff,
|
BellOff,
|
||||||
|
Bookmark,
|
||||||
|
BookmarkCheck,
|
||||||
Check,
|
Check,
|
||||||
CheckCircle,
|
CheckCircle,
|
||||||
Copy,
|
Copy,
|
||||||
@@ -1128,7 +1130,6 @@
|
|||||||
RefreshCw,
|
RefreshCw,
|
||||||
Settings,
|
Settings,
|
||||||
Share2,
|
Share2,
|
||||||
Star,
|
|
||||||
Tag,
|
Tag,
|
||||||
Ticket,
|
Ticket,
|
||||||
Trash2,
|
Trash2,
|
||||||
|
|||||||
@@ -0,0 +1,62 @@
|
|||||||
|
import { nextTick } from 'vue';
|
||||||
|
|
||||||
|
export function useVirtualizerAnchor({
|
||||||
|
virtualizer,
|
||||||
|
virtualRows,
|
||||||
|
scrollViewportRef
|
||||||
|
}) {
|
||||||
|
const captureScrollAnchor = () => {
|
||||||
|
const viewport = scrollViewportRef.value;
|
||||||
|
const items = virtualizer.value?.getVirtualItems?.() ?? [];
|
||||||
|
if (!viewport || !items.length) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
const firstItem = items[0];
|
||||||
|
const row = virtualRows.value[firstItem.index];
|
||||||
|
const key = row?.key ?? firstItem.key;
|
||||||
|
if (typeof key === 'undefined') {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
key,
|
||||||
|
offset: viewport.scrollTop - firstItem.start
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const restoreScrollAnchor = (anchor) => {
|
||||||
|
if (!anchor) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const index = virtualRows.value.findIndex(
|
||||||
|
(row) => row?.key === anchor.key
|
||||||
|
);
|
||||||
|
if (index === -1) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const offsetInfo = virtualizer.value?.getOffsetForIndex?.(
|
||||||
|
index,
|
||||||
|
'start'
|
||||||
|
);
|
||||||
|
const targetStart = Array.isArray(offsetInfo) ? offsetInfo[0] : null;
|
||||||
|
if (typeof targetStart !== 'number') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
virtualizer.value?.scrollToOffset?.(targetStart + anchor.offset);
|
||||||
|
};
|
||||||
|
|
||||||
|
const measureWithAnchor = (measureFn) => {
|
||||||
|
const anchor = captureScrollAnchor();
|
||||||
|
nextTick(() => {
|
||||||
|
if (measureFn) {
|
||||||
|
measureFn();
|
||||||
|
}
|
||||||
|
restoreScrollAnchor(anchor);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
return {
|
||||||
|
captureScrollAnchor,
|
||||||
|
restoreScrollAnchor,
|
||||||
|
measureWithAnchor
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -99,6 +99,7 @@
|
|||||||
} from '../../../stores';
|
} from '../../../stores';
|
||||||
import { isRealInstance, userImage, userStatusClass } from '../../../shared/utils';
|
import { isRealInstance, userImage, userStatusClass } from '../../../shared/utils';
|
||||||
import { getFriendsLocations } from '../../../shared/utils/location.js';
|
import { getFriendsLocations } from '../../../shared/utils/location.js';
|
||||||
|
import { useVirtualizerAnchor } from '../../../composables/useVirtualizerAnchor';
|
||||||
|
|
||||||
import FriendItem from './FriendItem.vue';
|
import FriendItem from './FriendItem.vue';
|
||||||
import Location from '../../../components/Location.vue';
|
import Location from '../../../components/Location.vue';
|
||||||
@@ -422,6 +423,12 @@
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const { measureWithAnchor } = useVirtualizerAnchor({
|
||||||
|
virtualizer,
|
||||||
|
virtualRows,
|
||||||
|
scrollViewportRef
|
||||||
|
});
|
||||||
|
|
||||||
function saveFriendsGroupStates() {
|
function saveFriendsGroupStates() {
|
||||||
configRepository.setBool('VRCX_isFriendsGroupMe', isFriendsGroupMe.value);
|
configRepository.setBool('VRCX_isFriendsGroupMe', isFriendsGroupMe.value);
|
||||||
configRepository.setBool('VRCX_isFriendsGroupFavorites', isVIPFriends.value);
|
configRepository.setBool('VRCX_isFriendsGroupFavorites', isVIPFriends.value);
|
||||||
@@ -482,7 +489,7 @@
|
|||||||
});
|
});
|
||||||
|
|
||||||
watch(virtualRows, () => {
|
watch(virtualRows, () => {
|
||||||
nextTick(() => {
|
measureWithAnchor(() => {
|
||||||
virtualizer.value?.measure?.();
|
virtualizer.value?.measure?.();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -56,6 +56,7 @@
|
|||||||
|
|
||||||
import { useAppearanceSettingsStore, useGroupStore } from '../../../stores';
|
import { useAppearanceSettingsStore, useGroupStore } from '../../../stores';
|
||||||
import { convertFileUrlToImageUrl } from '../../../shared/utils';
|
import { convertFileUrlToImageUrl } from '../../../shared/utils';
|
||||||
|
import { useVirtualizerAnchor } from '../../../composables/useVirtualizerAnchor';
|
||||||
|
|
||||||
import Location from '../../../components/Location.vue';
|
import Location from '../../../components/Location.vue';
|
||||||
|
|
||||||
@@ -168,6 +169,12 @@
|
|||||||
transform: `translateY(${item.virtualItem.start}px)`
|
transform: `translateY(${item.virtualItem.start}px)`
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const { measureWithAnchor } = useVirtualizerAnchor({
|
||||||
|
virtualizer,
|
||||||
|
virtualRows,
|
||||||
|
scrollViewportRef
|
||||||
|
});
|
||||||
|
|
||||||
function getSmallGroupIconUrl(url) {
|
function getSmallGroupIconUrl(url) {
|
||||||
return convertFileUrlToImageUrl(url);
|
return convertFileUrlToImageUrl(url);
|
||||||
}
|
}
|
||||||
@@ -188,7 +195,7 @@
|
|||||||
});
|
});
|
||||||
|
|
||||||
watch(virtualRows, () => {
|
watch(virtualRows, () => {
|
||||||
nextTick(() => {
|
measureWithAnchor(() => {
|
||||||
virtualizer.value?.measure?.();
|
virtualizer.value?.measure?.();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user