diff --git a/components/hub/ChatPanel.vue b/components/hub/ChatPanel.vue index 42904ebaa..df334b42e 100644 --- a/components/hub/ChatPanel.vue +++ b/components/hub/ChatPanel.vue @@ -1,5 +1,5 @@ + + + + + + + {{ $t("layouts.chat_panel.requests.title") }} + + + {{ $t("layouts.chat_panel.requests.hint") }} + + + + + + + + + + + + + + {{ (nameOf(request) || "?").slice(0, 2).toUpperCase() }} + + + + + {{ nameOf(request) }} + + + {{ $t("layouts.chat_panel.requests.wants_to_message") }} + + + + + + {{ $t("layouts.chat_panel.requests.deny") }} + + + + + + + diff --git a/components/hub/MessageRequestsRailButton.vue b/components/hub/MessageRequestsRailButton.vue new file mode 100644 index 000000000..f2e872a70 --- /dev/null +++ b/components/hub/MessageRequestsRailButton.vue @@ -0,0 +1,40 @@ + + + + + + + + + {{ count > 99 ? "99+" : count }} + + + diff --git a/components/hub/NewConversation.vue b/components/hub/NewConversation.vue index ec9affd78..888baa4bb 100644 --- a/components/hub/NewConversation.vue +++ b/components/hub/NewConversation.vue @@ -9,9 +9,8 @@ import { setActiveHub } from "~/composables/useHubState"; import { resolveAvatarUrl } from "~/utilities/avatarUrl"; // Starting a conversation, inside Chat itself: the thread area becomes a -// "To:" field over your friends, online first. Direct messages are between -// accepted friends only (the server enforces the same), so this lists friends -// rather than searching every player and refusing most of them. +// "To:" field over your friends, online first. Anyone else is messaged from +// their profile or name, where a first message goes out as a request. const emit = defineEmits<{ (e: "close"): void }>(); const matchmakingStore = useMatchmakingStore(); diff --git a/components/matchmaking-lobby/FriendListItem.vue b/components/matchmaking-lobby/FriendListItem.vue index f046e2638..291b1fd94 100644 --- a/components/matchmaking-lobby/FriendListItem.vue +++ b/components/matchmaking-lobby/FriendListItem.vue @@ -20,10 +20,13 @@ import { Swords, LogIn, MessageSquare, + MessageSquareOff, Ban, } from "lucide-vue-next"; import BlockPlayerDialog from "~/components/player/BlockPlayerDialog.vue"; import { useFriendActions } from "~/composables/useFriendActions"; +import { directRoomId } from "~/composables/useDirectMessages"; +import { useMessageRequests } from "~/composables/useMessageRequests"; import { usePlayerBlocks } from "~/composables/usePlayerBlocks"; import { useFriendStatus } from "~/composables/useFriendStatus"; import { useDraftGamesStore } from "~/stores/DraftGamesStore"; @@ -55,9 +58,8 @@ const { inviteToDraft: sendDraftInvite, } = useFriendActions(); -// Rendered inside the accepted-friend branch, so the friend-only rule the -// server enforces is already satisfied by where the button lives. const { openConversation } = useDirectMessages(); +const { isAwaitingReply } = useMessageRequests(); const { available: blocksAvailable } = usePlayerBlocks(); @@ -77,6 +79,35 @@ const currentLobby = computed(() => const isFriend = computed(() => rel.value === "friend"); +function message() { + openConversation({ + steam_id: String(props.player.steam_id), + name: props.player.name, + avatar_url: props.player.avatar_url, + }); +} + +// Anyone who is not a friend can still be written to: the first message goes +// as a request they reply to accept. Friends keep their own button below. +const canRequest = computed( + () => rel.value === "none" || rel.value === "outgoing", +); +const requestsOff = computed( + () => props.player?.allow_message_requests === false, +); +const awaitingReply = computed(() => { + const me = useAuthStore().me?.steam_id; + + return ( + !!me && + canRequest.value && + isAwaitingReply( + directRoomId(me, props.player.steam_id), + String(props.player.steam_id), + ) + ); +}); + const isOnline = computed(() => useMatchmakingStore().onlinePlayerSteamIds.includes( String(props.player.steam_id), @@ -238,8 +269,17 @@ const amberHover = :truncate-name="true" :context-menu="false" > - - + + + {{ $t("chat.direct.request.waiting") }} + + {{ $t("matchmaking.friends.just_online") }} @@ -283,6 +323,58 @@ const amberHover = + + + + + + + + + + + + + {{ + $t("chat.direct.request.friends_only", { + name: player.name, + }) + }} + + + {{ + $t("layouts.chat_panel.requests.awaiting_reply", { + name: player.name, + }) + }} + + + + {{ $t("chat.direct.request.title") }} + + + {{ + $t("chat.direct.request.description", { + name: player.name, + }) + }} + + + + +