Fetch friend requests for the add friend window

This commit is contained in:
Samuel Elliott 2025-07-25 19:27:49 +01:00
parent 0f0f666ea6
commit cd96ed7960
No known key found for this signature in database
GPG Key ID: 8420C7CDE43DC4D6
6 changed files with 48 additions and 9 deletions

View File

@ -61,6 +61,8 @@ export interface CoralApiInterface {
getUser(id: number): Promise<Result<User>>;
getUserByFriendCode(friend_code: string, hash?: string): Promise<Result<FriendCodeUser>>;
getCurrentUser(): Promise<Result<CurrentUser>>;
getReceivedFriendRequests(): Promise<Result<ReceivedFriendRequests>>;
getSentFriendRequests(): Promise<Result<SentFriendRequests>>;
getFriendCodeUrl(): Promise<Result<FriendCodeUrl>>;
getCurrentUserPermissions(): Promise<Result<CurrentUserPermissions>>;
getWebServiceToken(id: number): Promise<Result<WebServiceToken>>;

View File

@ -36,6 +36,11 @@ export default function AddFriendWindow(props: AddFriendProps) {
const [user] = useAsync(useCallback(() => token ?
ipc.getSavedCoralToken(token) : Promise.resolve(null), [ipc, token]));
const [fr_received, fr_received_error, fr_received_state] = useAsync(useCallback(() => token ?
ipc.getNsoReceivedFriendRequests(token) : Promise.resolve(null), [ipc, token]));
const [fr_sent, fr_sent_error, fr_sent_state] = useAsync(useCallback(() => token ?
ipc.getNsoSentFriendRequests(token) : Promise.resolve(null), [ipc, token]));
const [friendcode, setFriendCode] = useState(props.friendcode ?? '');
const is_valid_friendcode = FRIEND_CODE.test(friendcode);
const show_friendcode_field = !props.friendcode || !FRIEND_CODE.test(props.friendcode);

View File

@ -3,7 +3,7 @@ import { Image, ImageStyle, Platform, ScrollView, StyleSheet, Text, TouchableOpa
import { Trans, useTranslation } from 'react-i18next';
import ipc from '../ipc.js';
import { useAccentColour, useColourScheme, User, useTimeSince } from '../util.js';
import { Friend, Presence, PresenceState } from '../../../api/coral-types.js';
import { Friend_4, Presence, PresenceState } from '../../../api/coral-types.js';
import { TEXT_COLOUR_ACTIVE, TEXT_COLOUR_DARK, TEXT_COLOUR_LIGHT } from '../constants.js';
import Section, { HEADER_SIZE } from './section.js';
import AddOutline from '../components/icons/add-outline.js';
@ -11,7 +11,7 @@ import { FriendCode } from '../components/index.js';
export default function Friends(props: {
user: User;
friends: Friend[];
friends: Friend_4[];
loading?: boolean;
error?: Error;
}) {
@ -52,7 +52,7 @@ export default function Friends(props: {
}
function Friend(props: {
friend: Friend;
friend: Friend_4;
user?: User<true>;
}) {
const theme = useColourScheme() === 'light' ? light : dark;

View File

@ -90,6 +90,8 @@ export function setupIpc(appinstance: App, ipcMain: IpcMain) {
null)));
handle('coral:activeevent', (e, token: string) => store.users.get(token).then(u => u.getActiveEvent()));
handle('coral:friendcodeurl', (e, token: string) => store.users.get(token).then(u => u.nso.getFriendCodeUrl()));
handle('coral:friendrequests:received', (e, token: string) => store.users.get(token).then(u => u.nso.getReceivedFriendRequests()));
handle('coral:friendrequests:sent', (e, token: string) => store.users.get(token).then(u => u.nso.getSentFriendRequests()));
handle('coral:friendcode', (e, token: string, friendcode: string, hash?: string) => store.users.get(token).then(u => u.nso.getUserByFriendCode(friendcode, hash)));
handle('coral:addfriend', (e, token: string, nsaid: string) => store.users.get(token).then(u => u.addFriend(nsaid)));

View File

@ -7,7 +7,7 @@ import type { SavedToken } from '../../common/auth/coral.js';
import type { SavedMoonToken } from '../../common/auth/moon.js';
import type { UpdateCacheData } from '../../common/update.js';
import type { StatusUpdate } from '../../common/status.js';
import type { Announcements, CoralSuccessResponse, CurrentUser, Friend, FriendCodeUrl, FriendCodeUser, GetActiveEventResult, WebService, WebServices } from '../../api/coral-types.js';
import type { Announcements, Announcements_4, CoralSuccessResponse, CurrentUser, Friend, Friend_4, FriendCodeUrl, FriendCodeUser, GetActiveEventResult, ReceivedFriendRequests, SentFriendRequests, WebService, WebServices, WebServices_4 } from '../../api/coral-types.js';
import type { DiscordPresence } from '../../discord/types.js';
import type { NintendoAccountUser } from '../../api/na.js';
import type { DiscordSetupProps } from '../browser/discord/index.js';
@ -61,12 +61,14 @@ const ipc = {
getNintendoAccountCoralToken: (id: string) => inv<string | undefined>('coral:gettoken', id),
getSavedCoralToken: (token: string) => inv<SavedToken | undefined>('coral:getcachedtoken', token),
getCoralAnnouncements: (token: string) => inv<Announcements>('coral:announcements', token),
getNsoFriends: (token: string) => inv<Friend[]>('coral:friends', token),
getWebServices: (token: string) => inv<WebServices | undefined>('coral:webservices', token),
getCoralAnnouncements: (token: string) => inv<Announcements_4>('coral:announcements', token),
getNsoFriends: (token: string) => inv<Friend_4[]>('coral:friends', token),
getWebServices: (token: string) => inv<WebServices_4 | undefined>('coral:webservices', token),
openWebService: (webservice: WebService, token: string, qs?: string) => inv<number>('coral:openwebservice', webservice, token, qs),
getCoralActiveEvent: (token: string) => inv<GetActiveEventResult>('coral:activeevent', token),
getNsoFriendCodeUrl: (token: string) => inv<FriendCodeUrl>('coral:friendcodeurl', token),
getNsoReceivedFriendRequests: (token: string) => inv<ReceivedFriendRequests>('coral:friendrequests:received', token),
getNsoSentFriendRequests: (token: string) => inv<SentFriendRequests>('coral:friendrequests:sent', token),
getNsoUserByFriendCode: (token: string, friendcode: string, hash?: string) => inv<FriendCodeUser>('coral:friendcode', token, friendcode, hash),
addNsoFriend: (token: string, nsa_id: string) => inv<{result: CoralSuccessResponse<{}>; friend: Friend | null}>('coral:addfriend', token, nsa_id),

View File

@ -4,7 +4,7 @@ import { Response } from 'undici';
import createDebug from '../util/debug.js';
import CoralApi, { CoralApiInterface, NintendoAccountUserCoral, Result } from '../api/coral.js';
import ZncProxyApi from '../api/znc-proxy.js';
import { Friend, GetActiveEventResult, CoralSuccessResponse, WebService, CoralError, Announcements_4, Friends_4, WebServices_4, ListMedia, ListChat, WebService_4, CurrentUser } from '../api/coral-types.js';
import { Friend, GetActiveEventResult, CoralSuccessResponse, WebService, CoralError, Announcements_4, Friends_4, WebServices_4, ListMedia, ListChat, WebService_4, CurrentUser, ReceivedFriendRequests, SentFriendRequests } from '../api/coral-types.js';
import { getToken, SavedToken } from './auth/coral.js';
import type { Store } from '../app/main/index.js';
@ -119,6 +119,9 @@ export class CoralUser<T extends CoralApiInterface = CoralApi> implements CoralU
promise = new Map<string, Promise<void>>();
delay_retry_after_error_until: number | null = null;
fr_received: CoralSuccessResponse<ReceivedFriendRequests> | null = null;
fr_sent: CoralSuccessResponse<SentFriendRequests> | null = null;
updated = {
announcements: Date.now(),
friends: Date.now(),
@ -127,6 +130,9 @@ export class CoralUser<T extends CoralApiInterface = CoralApi> implements CoralU
media: Date.now(),
active_event: Date.now(),
user: Date.now(),
fr_received: null as number | null,
fr_sent: null as number | null,
};
delay_retry_after_error = 5 * 1000; // 5 seconds
@ -147,7 +153,7 @@ export class CoralUser<T extends CoralApiInterface = CoralApi> implements CoralU
) {}
private async update(key: keyof CoralUser['updated'], callback: () => Promise<void>, ttl: number) {
if ((this.updated[key] + ttl) < Date.now()) {
if (!this.updated[key] || (this.updated[key] + ttl) < Date.now()) {
const promise = this.promise.get(key) ?? Promise.resolve().then(() => {
const delay_retry = (this.delay_retry_after_error_until ?? 0) - Date.now();
@ -264,6 +270,28 @@ export class CoralUser<T extends CoralApiInterface = CoralApi> implements CoralU
return this.user.result;
}
async getReceivedFriendRequests() {
await this.update('fr_received', async () => {
// Always requested together when refreshing add friend page
this.getSentFriendRequests();
this.fr_received = await this.nso.getReceivedFriendRequests();
}, this.update_interval);
return this.fr_received!.result.friendRequests;
}
async getSentFriendRequests() {
await this.update('fr_sent', async () => {
// Always requested together when refreshing add friend page
this.getReceivedFriendRequests();
this.fr_sent = await this.nso.getSentFriendRequests();
}, this.update_interval);
return this.fr_sent!.result.friendRequests;
}
async addFriend(nsa_id: string) {
if (!(this.nso instanceof CoralApi)) {
throw new Error('Cannot send friend requests using Coral API proxy');