Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 42 additions & 0 deletions src/app/features/settings/account/ExternalConnections.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { SequenceCard } from '$components/sequence-card';
import { useMatrixClient } from '$hooks/useMatrixClient';
import { UserProfile } from '$hooks/useUserProfile';
import { profilesCacheAtom } from '$state/userRoomProfile';
import { Box, Text } from 'folds';
import { useSetAtom } from 'jotai';
import { useCallback } from 'react';
import { SequenceCardStyle } from '../styles.css';
import { ExternalListenbrainzConnectionEditor } from './ExternalListenbrainzConnection';

type ExternalConnectionsProps = {
profile: UserProfile;
userId: string;
};
export function ExternalConnectionsEditor({ profile, userId }: ExternalConnectionsProps) {
const mx = useMatrixClient();
const setGlobalProfiles = useSetAtom(profilesCacheAtom);

const handleSaveField = useCallback(
async (key: string, value: any) => {
await mx.setExtendedProfileProperty?.(key, value);
setGlobalProfiles((prev) => {
const newCache = { ...prev };
delete newCache[userId];
return newCache;
});
},
[mx, userId, setGlobalProfiles]
);

return (
<Box direction="Column" gap="100">
<Text size="L400">External Connections</Text>
<SequenceCard className={SequenceCardStyle} variant="SurfaceVariant" direction="Column">
<ExternalListenbrainzConnectionEditor
current={profile.listenBrainzAccount}
onSave={(con) => handleSaveField('fyi.cisnt.external.listenbrainz', con)}
/>
</SequenceCard>
</Box>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import { SettingTile } from '$components/setting-tile';
import { ExternalListenbrainzConnection } from '$hooks/useUserProfile';
import { Input } from 'folds';
import { useState, useEffect, ChangeEvent } from 'react';

export type ExternalListenbrainzConnectionProps = {
current?: ExternalListenbrainzConnection;
onSave: (p: ExternalListenbrainzConnection) => void;
};

export function ExternalListenbrainzConnectionEditor({
current,
onSave,
}: ExternalListenbrainzConnectionProps) {
const initialString = current?.username ? `@${current.username}` : '';
const [val, setVal] = useState(initialString);

useEffect(() => setVal(initialString), [initialString]);

const handleSave = () => {
if (val === initialString) return;
onSave({ username: val.replace('@', ''), v: 1 });
};

const handleChange = (e: ChangeEvent<HTMLInputElement>) => {
setVal(e.currentTarget.value);
};

return (
<SettingTile
title="Listenbrainz Account"
// let people link their Listenbrainz account by entering their Listenbrainz username (e.g. "@myusername")
description="Enter your Listenbrainz username (e.g. '@myusername') to link your account."
after={
<Input
value={val}
size="300"
radii="300"
variant="Secondary"
placeholder="Listenbrainz username..."
onChange={handleChange}
onBlur={handleSave}
onKeyDown={(e) => e.key === 'Enter' && handleSave()}
style={{ width: '232px' }}
/>
}
/>
);
}
2 changes: 2 additions & 0 deletions src/app/features/settings/account/Profile.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ import { PronounEditor } from './PronounEditor';
import { BioEditor } from './BioEditor';
import { NameColorEditor } from './NameColorEditor';
import { StatusEditor } from './StatusEditor';
import { ExternalConnectionsEditor } from './ExternalConnections';

type PronounSet = {
summary: string;
Expand Down Expand Up @@ -735,6 +736,7 @@ export function Profile() {
</Box>
<ProfileExtended userId={userId} profile={profile} />
<AnimalCosmetics userId={userId} profile={profile} />
<ExternalConnectionsEditor userId={userId} profile={profile} />
</Box>
);
}
9 changes: 9 additions & 0 deletions src/app/hooks/useUserProfile.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,11 @@ import { useMatrixClient } from './useMatrixClient';

const inFlightProfiles = new Map<string, Promise<any>>();

export type ExternalListenbrainzConnection = {
username?: string;
v?: number;
};

export type UserProfile = {
avatarUrl?: string;
displayName?: string;
Expand All @@ -22,6 +27,7 @@ export type UserProfile = {
nameColor?: string;
isCat?: boolean;
hasCats?: boolean;
listenBrainzAccount?: ExternalListenbrainzConnection;
extended?: Record<string, any>;
_fetched?: boolean;
};
Expand All @@ -40,6 +46,8 @@ const normalizeInfo = (info: any): UserProfile => {
'moe.sable.app.name_color',
'kitty.meow.has_cats',
'kitty.meow.is_cat',
// listenbrainz linking
'fyi.cisnt.external.listenbrainz',
];

const extended: Record<string, any> = {};
Expand All @@ -60,6 +68,7 @@ const normalizeInfo = (info: any): UserProfile => {
nameColor: info['moe.sable.app.name_color'],
isCat: info['kitty.meow.is_cat'] === true,
hasCats: info['kitty.meow.has_cats'] === true,
listenBrainzAccount: info['fyi.cisnt.external.listenbrainz'],
extended,
_fetched: true,
};
Expand Down