mirror of
https://github.com/MrUnknownDE/VRCX.git
synced 2026-05-06 22:46:06 +02:00
feat: add friend sidebar context menu
This commit is contained in:
@@ -111,10 +111,52 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<template v-else-if="item.row.type === 'friend-item'">
|
<template v-else-if="item.row.type === 'friend-item'">
|
||||||
<FriendItem
|
<ContextMenu>
|
||||||
:friend="item.row.friend"
|
<ContextMenuTrigger as-child>
|
||||||
:style="item.row.itemStyle"
|
<FriendItem
|
||||||
:is-group-by-instance="item.row.isGroupByInstance" />
|
:friend="item.row.friend"
|
||||||
|
:style="item.row.itemStyle"
|
||||||
|
:is-group-by-instance="item.row.isGroupByInstance" />
|
||||||
|
</ContextMenuTrigger>
|
||||||
|
<ContextMenuContent>
|
||||||
|
<ContextMenuItem
|
||||||
|
v-if="item.row.friend.state === 'online'"
|
||||||
|
@click="friendRequestInvite(item.row.friend)">
|
||||||
|
{{ t('dialog.user.actions.request_invite') }}
|
||||||
|
</ContextMenuItem>
|
||||||
|
<ContextMenuItem
|
||||||
|
v-if="isGameRunning"
|
||||||
|
:disabled="!canInviteToMyLocation"
|
||||||
|
@click="friendInvite(item.row.friend)">
|
||||||
|
{{ t('dialog.user.actions.invite') }}
|
||||||
|
</ContextMenuItem>
|
||||||
|
<ContextMenuItem
|
||||||
|
:disabled="!currentUser.isBoopingEnabled"
|
||||||
|
@click="friendSendBoop(item.row.friend)">
|
||||||
|
{{ t('dialog.user.actions.send_boop') }}
|
||||||
|
</ContextMenuItem>
|
||||||
|
<ContextMenuSeparator
|
||||||
|
v-if="
|
||||||
|
item.row.friend.state === 'online' && hasFriendLocation(item.row.friend)
|
||||||
|
" />
|
||||||
|
<ContextMenuItem
|
||||||
|
v-if="
|
||||||
|
item.row.friend.state === 'online' && hasFriendLocation(item.row.friend)
|
||||||
|
"
|
||||||
|
:disabled="!canJoinFriend(item.row.friend)"
|
||||||
|
@click="friendJoin(item.row.friend)">
|
||||||
|
{{ t('dialog.user.info.launch_invite_tooltip') }}
|
||||||
|
</ContextMenuItem>
|
||||||
|
<ContextMenuItem
|
||||||
|
v-if="
|
||||||
|
item.row.friend.state === 'online' && hasFriendLocation(item.row.friend)
|
||||||
|
"
|
||||||
|
:disabled="!canJoinFriend(item.row.friend)"
|
||||||
|
@click="friendInviteSelf(item.row.friend)">
|
||||||
|
{{ t('dialog.user.info.self_invite_tooltip') }}
|
||||||
|
</ContextMenuItem>
|
||||||
|
</ContextMenuContent>
|
||||||
|
</ContextMenu>
|
||||||
</template>
|
</template>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@@ -137,6 +179,7 @@
|
|||||||
ContextMenu,
|
ContextMenu,
|
||||||
ContextMenuCheckboxItem,
|
ContextMenuCheckboxItem,
|
||||||
ContextMenuContent,
|
ContextMenuContent,
|
||||||
|
ContextMenuItem,
|
||||||
ContextMenuSeparator,
|
ContextMenuSeparator,
|
||||||
ContextMenuSub,
|
ContextMenuSub,
|
||||||
ContextMenuSubContent,
|
ContextMenuSubContent,
|
||||||
@@ -149,13 +192,16 @@
|
|||||||
useFavoriteStore,
|
useFavoriteStore,
|
||||||
useFriendStore,
|
useFriendStore,
|
||||||
useGameStore,
|
useGameStore,
|
||||||
|
useLaunchStore,
|
||||||
useLocationStore,
|
useLocationStore,
|
||||||
useUserStore
|
useUserStore
|
||||||
} from '../../../stores';
|
} from '../../../stores';
|
||||||
import { buildFriendRow, buildInstanceHeaderRow, buildToggleRow, estimateRowSize } from '../friendsSidebarUtils';
|
import { buildFriendRow, buildInstanceHeaderRow, buildToggleRow, estimateRowSize } from '../friendsSidebarUtils';
|
||||||
import { getFriendsSortFunction, isRealInstance, userImage, userStatusClass } from '../../../shared/utils';
|
import { getFriendsSortFunction, isRealInstance, userImage, userStatusClass } from '../../../shared/utils';
|
||||||
|
import { instanceRequest, notificationRequest, userRequest, worldRequest } from '../../../api';
|
||||||
|
import { checkCanInvite, checkCanInviteSelf } from '../../../shared/utils/invite.js';
|
||||||
import { getFriendsLocations } from '../../../shared/utils/location.js';
|
import { getFriendsLocations } from '../../../shared/utils/location.js';
|
||||||
import { userRequest } from '../../../api';
|
import { parseLocation } from '../../../shared/utils';
|
||||||
|
|
||||||
import BackToTop from '../../../components/BackToTop.vue';
|
import BackToTop from '../../../components/BackToTop.vue';
|
||||||
import FriendItem from './FriendItem.vue';
|
import FriendItem from './FriendItem.vue';
|
||||||
@@ -183,7 +229,8 @@
|
|||||||
sidebarSortMethods
|
sidebarSortMethods
|
||||||
} = storeToRefs(appearanceSettingsStore);
|
} = storeToRefs(appearanceSettingsStore);
|
||||||
const { gameLogDisabled } = storeToRefs(useAdvancedSettingsStore());
|
const { gameLogDisabled } = storeToRefs(useAdvancedSettingsStore());
|
||||||
const { showUserDialog } = useUserStore();
|
const { showUserDialog, showSendBoopDialog } = useUserStore();
|
||||||
|
const launchStore = useLaunchStore();
|
||||||
const { favoriteFriendGroups, groupedByGroupKeyFavoriteFriends, localFriendFavorites } =
|
const { favoriteFriendGroups, groupedByGroupKeyFavoriteFriends, localFriendFavorites } =
|
||||||
storeToRefs(useFavoriteStore());
|
storeToRefs(useFavoriteStore());
|
||||||
const { lastLocation, lastLocationDestination } = storeToRefs(useLocationStore());
|
const { lastLocation, lastLocationDestination } = storeToRefs(useLocationStore());
|
||||||
@@ -657,4 +704,93 @@
|
|||||||
toast.success('Status updated');
|
toast.success('Status updated');
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const canInviteToMyLocation = computed(() => checkCanInvite(lastLocation.value.location));
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {object} friend - friend item from friend list
|
||||||
|
* @returns {boolean} whether the friend has a valid joinable location
|
||||||
|
*/
|
||||||
|
function hasFriendLocation(friend) {
|
||||||
|
const loc = friend.ref?.location;
|
||||||
|
return !!loc && isRealInstance(loc);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {object} friend - friend item from friend list
|
||||||
|
* @returns {boolean} whether the current user can join friend's instance
|
||||||
|
*/
|
||||||
|
function canJoinFriend(friend) {
|
||||||
|
const loc = friend.ref?.location;
|
||||||
|
if (!loc || !isRealInstance(loc)) return false;
|
||||||
|
return checkCanInviteSelf(loc);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {object} friend - friend item from friend list
|
||||||
|
*/
|
||||||
|
function friendRequestInvite(friend) {
|
||||||
|
notificationRequest.sendRequestInvite({ platform: 'standalonewindows' }, friend.id).then(() => {
|
||||||
|
toast.success('Request invite sent');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {object} friend - friend item from friend list
|
||||||
|
*/
|
||||||
|
function friendInvite(friend) {
|
||||||
|
let currentLocation = lastLocation.value.location;
|
||||||
|
if (currentLocation === 'traveling') {
|
||||||
|
currentLocation = lastLocationDestination.value;
|
||||||
|
}
|
||||||
|
const L = parseLocation(currentLocation);
|
||||||
|
worldRequest.getCachedWorld({ worldId: L.worldId }).then((args) => {
|
||||||
|
notificationRequest
|
||||||
|
.sendInvite(
|
||||||
|
{
|
||||||
|
instanceId: L.tag,
|
||||||
|
worldId: L.tag,
|
||||||
|
worldName: args.ref.name
|
||||||
|
},
|
||||||
|
friend.id
|
||||||
|
)
|
||||||
|
.then(() => {
|
||||||
|
toast.success(t('message.invite.sent'));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {object} friend - friend item from friend list
|
||||||
|
*/
|
||||||
|
function friendSendBoop(friend) {
|
||||||
|
showSendBoopDialog(friend.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Join friend's instance (launch dialog)
|
||||||
|
* @param {object} friend - friend item from friend list
|
||||||
|
*/
|
||||||
|
function friendJoin(friend) {
|
||||||
|
const loc = friend.ref?.location;
|
||||||
|
if (!loc) return;
|
||||||
|
launchStore.showLaunchDialog(loc);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {object} friend - friend item from friend list
|
||||||
|
*/
|
||||||
|
function friendInviteSelf(friend) {
|
||||||
|
const loc = friend.ref?.location;
|
||||||
|
if (!loc) return;
|
||||||
|
const L = parseLocation(loc);
|
||||||
|
instanceRequest
|
||||||
|
.selfInvite({
|
||||||
|
instanceId: L.instanceId,
|
||||||
|
worldId: L.worldId
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
toast.success(t('message.invite.self_sent'));
|
||||||
|
});
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
Reference in New Issue
Block a user