mirror of
https://github.com/BetterSEQTA/BetterSEQTA-Plus.git
synced 2026-08-28 17:21:05 +00:00
fix(cloud PFP): Not pulling from cloud on page load
This commit is contained in:
@@ -28,6 +28,10 @@ export function pfpUrlWithHash(url: string, hash: string | null | undefined): st
|
||||
return `${base}?v=${hash}`;
|
||||
}
|
||||
|
||||
export function defaultAccountsPfpUrl(userId: string): string {
|
||||
return `${ACCOUNTS_BASE}/api/user/pfp/${userId}`;
|
||||
}
|
||||
|
||||
async function fetchServerHash(userId: string): Promise<string | null> {
|
||||
const res = await fetch(`${ACCOUNTS_BASE}/api/user/pfp/${userId}/meta`);
|
||||
if (!res.ok) return null;
|
||||
@@ -95,6 +99,10 @@ export async function resolveCloudPfp(
|
||||
if (localHash) {
|
||||
headers["If-None-Match"] = `"${localHash}"`;
|
||||
}
|
||||
const token = await cloudAuth.getStoredToken();
|
||||
if (token && isAccountsHostedPfpUrl(pfpUrl)) {
|
||||
headers.Authorization = `Bearer ${token}`;
|
||||
}
|
||||
|
||||
const res = await fetch(imageUrl, { headers });
|
||||
if (res.status === 304 && localBlob instanceof Blob) {
|
||||
|
||||
+131
-18
@@ -1,7 +1,10 @@
|
||||
import browser from "webextension-polyfill";
|
||||
import localforage from "localforage";
|
||||
import { cloudAuth } from "@/seqta/utils/CloudAuth";
|
||||
import { clearCloudPfpCache, pfpUrlWithHash } from "@/seqta/utils/cloudPfpCache";
|
||||
import { cloudAuth, type CloudUser } from "@/seqta/utils/CloudAuth";
|
||||
import {
|
||||
clearCloudPfpCache,
|
||||
pfpUrlWithHash,
|
||||
} from "@/seqta/utils/cloudPfpCache";
|
||||
|
||||
const ACCOUNTS_BASE = "https://accounts.betterseqta.org";
|
||||
const PLUGIN_SETTINGS_KEY = "plugin.profile-picture.settings";
|
||||
@@ -54,6 +57,92 @@ async function parseJsonResponse(r: Response): Promise<Record<string, unknown>>
|
||||
}
|
||||
}
|
||||
|
||||
function mergeMeIntoUser(current: CloudUser, data: Record<string, unknown>): CloudUser {
|
||||
const raw = (data.user as Record<string, unknown> | undefined) ?? data;
|
||||
const pfpUrlRaw = raw.pfpUrl as string | null | undefined;
|
||||
const pfpHash = (raw.pfpHash as string | null | undefined) ?? null;
|
||||
const pfpUrl =
|
||||
pfpUrlRaw == null || pfpUrlRaw === ""
|
||||
? undefined
|
||||
: pfpUrlWithHash(pfpUrlRaw, pfpHash);
|
||||
|
||||
return {
|
||||
...current,
|
||||
email: (raw.email as string | undefined) ?? current.email,
|
||||
username: (raw.username as string | undefined) ?? current.username,
|
||||
displayName: (raw.displayName as string | undefined) ?? current.displayName,
|
||||
admin_level: (raw.admin_level as number | undefined) ?? current.admin_level,
|
||||
pfpUrl,
|
||||
pfpHash,
|
||||
};
|
||||
}
|
||||
|
||||
/** Fetch `/api/auth/me` and update stored user (pfpUrl / pfpHash). */
|
||||
export async function refreshCloudUserFromServer(): Promise<{
|
||||
success: boolean;
|
||||
error?: string;
|
||||
}> {
|
||||
if (!cloudAuth.state.isLoggedIn) {
|
||||
return { success: false, error: "Not signed in to BetterSEQTA Cloud" };
|
||||
}
|
||||
|
||||
const token = await cloudAuth.getStoredToken();
|
||||
if (!token) return { success: false, error: "Not signed in to BetterSEQTA Cloud" };
|
||||
|
||||
const current = cloudAuth.state.user;
|
||||
if (!current?.id) return { success: false, error: "No cloud user on this device" };
|
||||
|
||||
try {
|
||||
const res = await fetch(`${ACCOUNTS_BASE}/api/auth/me`, {
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
});
|
||||
const data = await parseJsonResponse(res);
|
||||
if (!res.ok) {
|
||||
return {
|
||||
success: false,
|
||||
error: (data.error as string) ?? `Could not refresh account (${res.status})`,
|
||||
};
|
||||
}
|
||||
|
||||
await cloudAuth.setUser(mergeMeIntoUser(current, data));
|
||||
return { success: true };
|
||||
} catch (err) {
|
||||
return {
|
||||
success: false,
|
||||
error: err instanceof Error ? err.message : "Could not refresh account",
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/** Pull cloud avatar metadata from the server and refresh the in-page profile image. */
|
||||
export async function pullCloudProfilePictureFromServer(): Promise<{
|
||||
success: boolean;
|
||||
error?: string;
|
||||
}> {
|
||||
const refreshed = await refreshCloudUserFromServer();
|
||||
if (!refreshed.success) return refreshed;
|
||||
|
||||
const userId = cloudAuth.state.user?.id;
|
||||
if (userId) await clearCloudPfpCache(userId);
|
||||
await notifyProfilePictureChanged();
|
||||
return { success: true };
|
||||
}
|
||||
|
||||
/** When cloud PFP is enabled: upload local image if present, otherwise pull from server. */
|
||||
export async function onUseCloudPfpToggled(enabled: boolean): Promise<void> {
|
||||
if (!enabled) {
|
||||
await notifyProfilePictureChanged();
|
||||
return;
|
||||
}
|
||||
|
||||
const blob = await profileStore.getItem<Blob>("profile-picture");
|
||||
if (blob instanceof Blob) {
|
||||
await syncLocalProfilePictureToCloud();
|
||||
} else {
|
||||
await pullCloudProfilePictureFromServer();
|
||||
}
|
||||
}
|
||||
|
||||
export async function syncLocalProfilePictureToCloud(): Promise<{
|
||||
success: boolean;
|
||||
error?: string;
|
||||
@@ -72,22 +161,7 @@ export async function syncLocalProfilePictureToCloud(): Promise<{
|
||||
|
||||
try {
|
||||
if (!blob || !(blob instanceof Blob)) {
|
||||
const res = await fetch(`${ACCOUNTS_BASE}/api/user/pfp/clear`, {
|
||||
method: "POST",
|
||||
headers: {
|
||||
Authorization: `Bearer ${token}`,
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify({}),
|
||||
});
|
||||
const data = await parseJsonResponse(res);
|
||||
if (!res.ok) {
|
||||
return { success: false, error: (data.error as string) ?? `Clear failed (${res.status})` };
|
||||
}
|
||||
if (user) {
|
||||
await cloudAuth.setUser({ ...user, pfpUrl: undefined, pfpHash: null });
|
||||
}
|
||||
if (userId) await clearCloudPfpCache(userId);
|
||||
// No local upload — keep the server avatar; do not clear cloud.
|
||||
return { success: true };
|
||||
}
|
||||
|
||||
@@ -131,6 +205,45 @@ export async function syncLocalProfilePictureToCloud(): Promise<{
|
||||
}
|
||||
}
|
||||
|
||||
/** Upload local image to cloud, or clear cloud only when explicitly removing local image. */
|
||||
export async function clearCloudProfilePicture(): Promise<{
|
||||
success: boolean;
|
||||
error?: string;
|
||||
}> {
|
||||
if (!cloudAuth.state.isLoggedIn) return { success: true };
|
||||
|
||||
const token = await cloudAuth.getStoredToken();
|
||||
if (!token) return { success: false, error: "Not logged in" };
|
||||
|
||||
const user = cloudAuth.state.user;
|
||||
const userId = user?.id;
|
||||
|
||||
try {
|
||||
const res = await fetch(`${ACCOUNTS_BASE}/api/user/pfp/clear`, {
|
||||
method: "POST",
|
||||
headers: {
|
||||
Authorization: `Bearer ${token}`,
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify({}),
|
||||
});
|
||||
const data = await parseJsonResponse(res);
|
||||
if (!res.ok) {
|
||||
return { success: false, error: (data.error as string) ?? `Clear failed (${res.status})` };
|
||||
}
|
||||
if (user) {
|
||||
await cloudAuth.setUser({ ...user, pfpUrl: undefined, pfpHash: null });
|
||||
}
|
||||
if (userId) await clearCloudPfpCache(userId);
|
||||
return { success: true };
|
||||
} catch (err) {
|
||||
return {
|
||||
success: false,
|
||||
error: err instanceof Error ? err.message : "Cloud profile picture clear failed",
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/** Notify SEQTA content scripts to refresh the in-page profile image. */
|
||||
export async function notifyProfilePictureChanged(): Promise<void> {
|
||||
const revision = Date.now();
|
||||
|
||||
Reference in New Issue
Block a user