mirror of
https://github.com/MrUnknownDE/VRCX.git
synced 2026-05-07 06:56:04 +02:00
feat: Add context menu to mutual friends graph nodes
This commit is contained in:
@@ -565,6 +565,10 @@
|
|||||||
"exclude_friends": "Exclude friends",
|
"exclude_friends": "Exclude friends",
|
||||||
"exclude_friends_placeholder": "Select friends to exclude",
|
"exclude_friends_placeholder": "Select friends to exclude",
|
||||||
"exclude_friends_help": "Selected friends will be hidden from the graph."
|
"exclude_friends_help": "Selected friends will be hidden from the graph."
|
||||||
|
},
|
||||||
|
"context_menu": {
|
||||||
|
"view_details": "View Details",
|
||||||
|
"hide_friend": "Hide from Graph"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"hot_worlds": {
|
"hot_worlds": {
|
||||||
|
|||||||
@@ -46,9 +46,9 @@
|
|||||||
<div class="flex-1 overflow-hidden">
|
<div class="flex-1 overflow-hidden">
|
||||||
<span
|
<span
|
||||||
class="block truncate font-medium leading-[18px]"
|
class="block truncate font-medium leading-[18px]"
|
||||||
:style="{ color: item.user.$userColour }">{{
|
:style="{ color: item.user.$userColour }"
|
||||||
item.user.displayName
|
>{{ item.user.displayName }}</span
|
||||||
}}</span>
|
>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<template v-else>
|
<template v-else>
|
||||||
@@ -236,11 +236,26 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div
|
<ContextMenu @update:open="onNodeMenuOpenChange">
|
||||||
v-show="!(hasFetched && !isFetching && !graphReady)"
|
<ContextMenuTrigger as-child>
|
||||||
ref="graphContainerRef"
|
<div
|
||||||
class="mt-3 h-[calc(100vh-260px)] min-h-[520px] w-full flex-1 rounded-lg bg-transparent"
|
v-show="!(hasFetched && !isFetching && !graphReady)"
|
||||||
:style="{ backgroundColor: canvasBackground }"></div>
|
ref="graphContainerRef"
|
||||||
|
class="mt-3 h-[calc(100vh-260px)] min-h-[520px] w-full flex-1 rounded-lg bg-transparent"
|
||||||
|
:style="{ backgroundColor: canvasBackground }"></div>
|
||||||
|
</ContextMenuTrigger>
|
||||||
|
<ContextMenuContent v-if="contextMenuNodeId" class="min-w-40">
|
||||||
|
<ContextMenuItem @click="handleNodeMenuViewDetails">
|
||||||
|
<UserIcon class="mr-2 size-4" />
|
||||||
|
{{ t('view.charts.mutual_friend.context_menu.view_details') }}
|
||||||
|
</ContextMenuItem>
|
||||||
|
<ContextMenuSeparator />
|
||||||
|
<ContextMenuItem @click="handleNodeMenuHide">
|
||||||
|
<EyeOffIcon class="mr-2 size-4" />
|
||||||
|
{{ t('view.charts.mutual_friend.context_menu.hide_friend') }}
|
||||||
|
</ContextMenuItem>
|
||||||
|
</ContextMenuContent>
|
||||||
|
</ContextMenu>
|
||||||
|
|
||||||
<Empty v-if="hasFetched && !isFetching && !graphReady" class="mt-3 w-full flex-1">
|
<Empty v-if="hasFetched && !isFetching && !graphReady" class="mt-3 w-full flex-1">
|
||||||
<EmptyHeader>
|
<EmptyHeader>
|
||||||
@@ -262,7 +277,14 @@
|
|||||||
import { Sheet, SheetContent, SheetHeader, SheetTitle, SheetTrigger } from '@/components/ui/sheet';
|
import { Sheet, SheetContent, SheetHeader, SheetTitle, SheetTrigger } from '@/components/ui/sheet';
|
||||||
import { Field, FieldContent, FieldGroup, FieldLabel } from '@/components/ui/field';
|
import { Field, FieldContent, FieldGroup, FieldLabel } from '@/components/ui/field';
|
||||||
import { Empty, EmptyDescription, EmptyHeader } from '@/components/ui/empty';
|
import { Empty, EmptyDescription, EmptyHeader } from '@/components/ui/empty';
|
||||||
import { Check as CheckIcon, Settings } from 'lucide-vue-next';
|
import {
|
||||||
|
ContextMenu,
|
||||||
|
ContextMenuContent,
|
||||||
|
ContextMenuItem,
|
||||||
|
ContextMenuSeparator,
|
||||||
|
ContextMenuTrigger
|
||||||
|
} from '@/components/ui/context-menu';
|
||||||
|
import { Check as CheckIcon, EyeOff as EyeOffIcon, Settings, User as UserIcon } from 'lucide-vue-next';
|
||||||
import { Button } from '@/components/ui/button';
|
import { Button } from '@/components/ui/button';
|
||||||
import { Progress } from '@/components/ui/progress';
|
import { Progress } from '@/components/ui/progress';
|
||||||
import { Slider } from '@/components/ui/slider';
|
import { Slider } from '@/components/ui/slider';
|
||||||
@@ -529,6 +551,8 @@
|
|||||||
|
|
||||||
const selectedFriendId = ref(null);
|
const selectedFriendId = ref(null);
|
||||||
|
|
||||||
|
const contextMenuNodeId = ref(null);
|
||||||
|
|
||||||
const EXCLUDED_FRIENDS_KEY = 'VRCX_MutualGraphExcludedFriends';
|
const EXCLUDED_FRIENDS_KEY = 'VRCX_MutualGraphExcludedFriends';
|
||||||
const excludedFriendIds = useLocalStorage(EXCLUDED_FRIENDS_KEY, []);
|
const excludedFriendIds = useLocalStorage(EXCLUDED_FRIENDS_KEY, []);
|
||||||
|
|
||||||
@@ -565,7 +589,6 @@
|
|||||||
return [{ key: 'friends', label: t('side_panel.friends'), items }];
|
return [{ key: 'friends', label: t('side_panel.friends'), items }];
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
function navigateToFriend(friendId) {
|
function navigateToFriend(friendId) {
|
||||||
selectedFriendId.value = friendId;
|
selectedFriendId.value = friendId;
|
||||||
if (!friendId || !currentGraph || !sigmaInstance) return;
|
if (!friendId || !currentGraph || !sigmaInstance) return;
|
||||||
@@ -1045,6 +1068,14 @@
|
|||||||
if (node) showUserDialog(node);
|
if (node) showUserDialog(node);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
sigmaInstance.on('rightClickNode', ({ node }) => {
|
||||||
|
contextMenuNodeId.value = node || null;
|
||||||
|
});
|
||||||
|
|
||||||
|
sigmaInstance.on('rightClickStage', () => {
|
||||||
|
contextMenuNodeId.value = null;
|
||||||
|
});
|
||||||
|
|
||||||
sigmaInstance.refresh();
|
sigmaInstance.refresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1157,4 +1188,26 @@
|
|||||||
function cancelFetch() {
|
function cancelFetch() {
|
||||||
chartsStore.requestMutualGraphCancel();
|
chartsStore.requestMutualGraphCancel();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function onNodeMenuOpenChange(open) {
|
||||||
|
if (!open) {
|
||||||
|
contextMenuNodeId.value = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleNodeMenuViewDetails() {
|
||||||
|
if (contextMenuNodeId.value) {
|
||||||
|
showUserDialog(contextMenuNodeId.value);
|
||||||
|
}
|
||||||
|
contextMenuNodeId.value = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleNodeMenuHide() {
|
||||||
|
if (contextMenuNodeId.value) {
|
||||||
|
if (!excludedFriendIds.value.includes(contextMenuNodeId.value)) {
|
||||||
|
excludedFriendIds.value = [...excludedFriendIds.value, contextMenuNodeId.value];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
contextMenuNodeId.value = null;
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
Reference in New Issue
Block a user