Add recent action indicators to friend context menu

This commit is contained in:
pa
2026-03-16 20:34:01 +09:00
parent 1b3e292883
commit 54572f9480
3 changed files with 25 additions and 12 deletions
@@ -147,12 +147,18 @@
v-if="item.row.friend.state === 'online'" v-if="item.row.friend.state === 'online'"
@click="friendRequestInvite(item.row.friend)"> @click="friendRequestInvite(item.row.friend)">
{{ t('dialog.user.actions.request_invite') }} {{ t('dialog.user.actions.request_invite') }}
<ContextMenuShortcut v-if="isActionRecent(item.row.friend.id, 'Request Invite')">
<Clock class="size-3.5 text-muted-foreground" />
</ContextMenuShortcut>
</ContextMenuItem> </ContextMenuItem>
<ContextMenuItem <ContextMenuItem
v-if="isGameRunning" v-if="isGameRunning"
:disabled="!canInviteToMyLocation" :disabled="!canInviteToMyLocation"
@click="friendInvite(item.row.friend)"> @click="friendInvite(item.row.friend)">
{{ t('dialog.user.actions.invite') }} {{ t('dialog.user.actions.invite') }}
<ContextMenuShortcut v-if="isActionRecent(item.row.friend.id, 'Invite')">
<Clock class="size-3.5 text-muted-foreground" />
</ContextMenuShortcut>
</ContextMenuItem> </ContextMenuItem>
<ContextMenuItem <ContextMenuItem
:disabled="!currentUser.isBoopingEnabled" :disabled="!currentUser.isBoopingEnabled"
@@ -193,7 +199,7 @@
<script setup> <script setup>
import { computed, nextTick, onMounted, reactive, ref, watch } from 'vue'; import { computed, nextTick, onMounted, reactive, ref, watch } from 'vue';
import { ChevronDown, User } from 'lucide-vue-next'; import { ChevronDown, Clock, User } from 'lucide-vue-next';
import { storeToRefs } from 'pinia'; import { storeToRefs } from 'pinia';
import { toast } from 'vue-sonner'; import { toast } from 'vue-sonner';
import { useI18n } from 'vue-i18n'; import { useI18n } from 'vue-i18n';
@@ -205,6 +211,7 @@
ContextMenuContent, ContextMenuContent,
ContextMenuItem, ContextMenuItem,
ContextMenuSeparator, ContextMenuSeparator,
ContextMenuShortcut,
ContextMenuSub, ContextMenuSub,
ContextMenuSubContent, ContextMenuSubContent,
ContextMenuSubTrigger, ContextMenuSubTrigger,
@@ -225,6 +232,7 @@
import { getFriendsSortFunction, isRealInstance } from '../../../shared/utils'; import { getFriendsSortFunction, isRealInstance } from '../../../shared/utils';
import { instanceRequest, notificationRequest, queryRequest, userRequest } from '../../../api'; import { instanceRequest, notificationRequest, queryRequest, userRequest } from '../../../api';
import { useInviteChecks } from '../../../composables/useInviteChecks'; import { useInviteChecks } from '../../../composables/useInviteChecks';
import { isActionRecent, recordRecentAction } from '../../../composables/useRecentActions';
import { useUserDisplay } from '../../../composables/useUserDisplay'; import { useUserDisplay } from '../../../composables/useUserDisplay';
import { getFriendsLocations } from '../../../shared/utils/location.js'; import { getFriendsLocations } from '../../../shared/utils/location.js';
import { parseLocation } from '../../../shared/utils'; import { parseLocation } from '../../../shared/utils';
@@ -793,6 +801,7 @@
*/ */
function friendRequestInvite(friend) { function friendRequestInvite(friend) {
notificationRequest.sendRequestInvite({ platform: 'standalonewindows' }, friend.id).then(() => { notificationRequest.sendRequestInvite({ platform: 'standalonewindows' }, friend.id).then(() => {
recordRecentAction(friend.id, 'Request Invite');
toast.success('Request invite sent'); toast.success('Request invite sent');
}); });
} }
@@ -817,6 +826,7 @@
friend.id friend.id
) )
.then(() => { .then(() => {
recordRecentAction(friend.id, 'Invite');
toast.success(t('message.invite.sent')); toast.success(t('message.invite.sent'));
}); });
}); });
@@ -180,6 +180,7 @@ vi.mock('../../../../components/ui/context-menu', () => ({
'<button :disabled="disabled" @click="$emit(\'click\')"><slot /></button>' '<button :disabled="disabled" @click="$emit(\'click\')"><slot /></button>'
}, },
ContextMenuSeparator: { template: '<hr />' }, ContextMenuSeparator: { template: '<hr />' },
ContextMenuShortcut: { template: '<span><slot /></span>' },
ContextMenuSub: { template: '<div><slot /></div>' }, ContextMenuSub: { template: '<div><slot /></div>' },
ContextMenuSubContent: { template: '<div><slot /></div>' }, ContextMenuSubContent: { template: '<div><slot /></div>' },
ContextMenuSubTrigger: { template: '<div><slot /></div>' }, ContextMenuSubTrigger: { template: '<div><slot /></div>' },
@@ -210,9 +211,15 @@ vi.mock('../FriendItem.vue', () => ({
vi.mock('lucide-vue-next', () => ({ vi.mock('lucide-vue-next', () => ({
ChevronDown: { template: '<span data-testid="chevron" />' }, ChevronDown: { template: '<span data-testid="chevron" />' },
Clock: { template: '<span data-testid="clock" />' },
User: { template: '<i />' } User: { template: '<i />' }
})); }));
vi.mock('../../../../composables/useRecentActions', () => ({
isActionRecent: vi.fn(() => false),
recordRecentAction: vi.fn()
}));
import FriendsSidebar from '../FriendsSidebar.vue'; import FriendsSidebar from '../FriendsSidebar.vue';
function flushPromises() { function flushPromises() {
+7 -11
View File
@@ -182,18 +182,14 @@
{{ t('dialog.screenshot_metadata.section_players') }} ({{ screenshotMetadataDialog.metadata.players.length }}) {{ t('dialog.screenshot_metadata.section_players') }} ({{ screenshotMetadataDialog.metadata.players.length }})
</h4> </h4>
<div class="flex flex-wrap gap-1 max-h-[180px] overflow-y-auto"> <div class="flex flex-wrap gap-1 max-h-[180px] overflow-y-auto">
<TooltipWrapper <Badge
v-for="user in screenshotMetadataDialog.metadata.players" v-for="user in screenshotMetadataDialog.metadata.players"
:key="user.id" :key="user.id"
side="top" variant="secondary"
:content="user.pos ? '(' + user.pos.x + ', ' + user.pos.y + ', ' + user.pos.z + ')' : ''"> class="cursor-pointer hover:bg-accent transition-colors"
<Badge @click="lookupUser(user)">
variant="secondary" {{ user.displayName }}
class="cursor-pointer hover:bg-accent transition-colors" </Badge>
@click="lookupUser(user)">
{{ user.displayName }}
</Badge>
</TooltipWrapper>
</div> </div>
</div> </div>
@@ -267,7 +263,7 @@
import { ButtonGroup } from '@/components/ui/button-group'; import { ButtonGroup } from '@/components/ui/button-group';
import { InputGroupSearch } from '@/components/ui/input-group'; import { InputGroupSearch } from '@/components/ui/input-group';
import { Kbd } from '@/components/ui/kbd'; import { Kbd } from '@/components/ui/kbd';
import { TooltipWrapper } from '@/components/ui/tooltip';
import { formatDateFilter } from '@/shared/utils'; import { formatDateFilter } from '@/shared/utils';
import { storeToRefs } from 'pinia'; import { storeToRefs } from 'pinia';
import { toast } from 'vue-sonner'; import { toast } from 'vue-sonner';