Add identity.ts with isSelf() and resolveDisplayIdentity() — pure stateless functions that detect replicated-self using the immutable (username, homeInstance) composite key. No store lookups, no data mutation. Fixes wrong avatar gradient and missing edit/delete on own messages in remote channels. Also includes: optimistic message dedup fix for cross-instance messages (content-only matching), federation toast notifications, Username component with @domain display, invite parser, and deploy script simplification.
65 lines
1.8 KiB
TypeScript
65 lines
1.8 KiB
TypeScript
/**
|
|
* Parse invite input into a code and optional remote origin.
|
|
*
|
|
* Supported formats:
|
|
* - Bare code: "a3f1b2c4"
|
|
* - Full URL: "https://remote.com/join/a3f1b2c4"
|
|
* - Qualified code: "a3f1b2c4@remote.com"
|
|
*/
|
|
export function parseInviteInput(input: string): { code: string; origin?: string } {
|
|
const trimmed = input.trim();
|
|
if (!trimmed) throw new Error('Invite code is required');
|
|
|
|
// Full URL: starts with http:// or https://
|
|
if (/^https?:\/\//i.test(trimmed)) {
|
|
let parsed: URL;
|
|
try {
|
|
parsed = new URL(trimmed);
|
|
} catch {
|
|
throw new Error('Invalid invite link');
|
|
}
|
|
|
|
// Extract code from /join/{code} path
|
|
const match = parsed.pathname.match(/^\/join\/([^/]+)$/);
|
|
if (!match) {
|
|
throw new Error('Invalid invite link — expected format: https://instance/join/CODE');
|
|
}
|
|
|
|
const code = match[1]!;
|
|
|
|
// If the URL points at our own instance, treat as a bare code
|
|
if (parsed.origin === window.location.origin) {
|
|
return { code };
|
|
}
|
|
|
|
return { code, origin: parsed.origin };
|
|
}
|
|
|
|
// Qualified code: CODE@domain (contains @ but no spaces, no protocol)
|
|
if (trimmed.includes('@') && !trimmed.includes(' ')) {
|
|
const atIndex = trimmed.indexOf('@');
|
|
const code = trimmed.slice(0, atIndex);
|
|
const domain = trimmed.slice(atIndex + 1);
|
|
|
|
if (!code || !domain) {
|
|
throw new Error('Invalid invite format — expected: CODE@domain');
|
|
}
|
|
|
|
const origin = `https://${domain}`;
|
|
|
|
// If it resolves to our own instance, treat as bare code
|
|
try {
|
|
if (new URL(origin).origin === window.location.origin) {
|
|
return { code };
|
|
}
|
|
} catch {
|
|
throw new Error('Invalid domain in invite');
|
|
}
|
|
|
|
return { code, origin };
|
|
}
|
|
|
|
// Bare code
|
|
return { code: trimmed };
|
|
}
|