Skip to content

Commit 1bff261

Browse files
committed
fix
1 parent 7791650 commit 1bff261

4 files changed

Lines changed: 191 additions & 49 deletions

File tree

src/components/ColorPicker.tsx

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -56,14 +56,17 @@ export function ColorPicker({ username, onColorChange }: ColorPickerProps) {
5656
try {
5757
await updateUserAccentColor(username, color);
5858
console.log(`Successfully saved accent color: ${color}`);
59-
} catch (error) {
59+
} catch (error: any) {
6060
safeLogError('Error saving accent color:', error);
61-
// Revert color back to previous if save failed
62-
const previousColor = await getUserAccentColor(username);
63-
setAccentColor(previousColor);
64-
setCustomColor(previousColor);
65-
onColorChange?.(previousColor);
66-
alert(t('colorSaveError'));
61+
// Revert color back to previous if save failed (but not for 401)
62+
if (error.status !== 401) {
63+
const previousColor = await getUserAccentColor(username);
64+
setAccentColor(previousColor);
65+
setCustomColor(previousColor);
66+
onColorChange?.(previousColor);
67+
alert(t('colorSaveError'));
68+
}
69+
// For 401, keep the color but silently warn (handled in userSettings)
6770
} finally {
6871
setIsSaving(false);
6972
}

src/lib/auth.ts

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,22 @@ export function AuthProvider({ children }: {children: React.ReactNode;}) {
4545
setIsLoading(true);
4646
try {
4747
const path = `users/${username}.md`;
48-
const file = await getFile(path);
48+
let file = null;
49+
50+
// Try to fetch user file if token is available
51+
try {
52+
if (config.github.token) {
53+
file = await getFile(path);
54+
}
55+
} catch (error: any) {
56+
// Treat 401/404 as user not found - this is OK
57+
if (error.status === 401 || error.status === 404) {
58+
file = null;
59+
} else {
60+
// Only throw other errors
61+
throw error;
62+
}
63+
}
4964

5065
let userData: User;
5166
let isNewUser = false;
@@ -73,7 +88,19 @@ export function AuthProvider({ children }: {children: React.ReactNode;}) {
7388

7489
// Create default settings file if it doesn't exist
7590
const settingsPath = `users/${username}-settings.md`;
76-
const settingsFile = await getFile(settingsPath);
91+
let settingsFile = null;
92+
93+
// Try to fetch settings file if token is available
94+
try {
95+
if (config.github.token) {
96+
settingsFile = await getFile(settingsPath);
97+
}
98+
} catch (error: any) {
99+
// Treat 401/404 as settings not found - this is OK
100+
if (error.status === 401 || error.status === 404) {
101+
settingsFile = null;
102+
}
103+
}
77104

78105
if (!settingsFile) {
79106
const defaultSettings = {

src/lib/userSettings.ts

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -50,14 +50,34 @@ export async function saveUserSettings(username: string, settings: UserSettings)
5050
const path = `users/${username}-settings.md`;
5151
const content = stringifyFrontmatter(settings, '');
5252

53-
// Get the current file with SHA to avoid 422 error
54-
const existingFile = await getFile(path);
53+
// Try to get the current file with SHA to avoid 422 error
54+
let existingFile = null;
55+
try {
56+
existingFile = await getFile(path);
57+
} catch (error: any) {
58+
if (error.status !== 401 && error.status !== 404) {
59+
throw error;
60+
}
61+
}
5562

56-
await putFile(path, content, `Update settings for ${username}`, false, existingFile?.sha);
63+
// Try to save, but don't fail if token is missing
64+
try {
65+
await putFile(path, content, `Update settings for ${username}`, false, existingFile?.sha);
66+
} catch (error: any) {
67+
if (error.status === 401) {
68+
console.warn('GitHub token not configured. Settings saved locally only.');
69+
} else {
70+
throw error;
71+
}
72+
}
5773

5874
// Clear cache to ensure fresh data on next load
5975
if (typeof clearGitHubApiCache === 'function') {
60-
await clearGitHubApiCache();
76+
try {
77+
await clearGitHubApiCache();
78+
} catch (e) {
79+
// Ignore cache clear errors
80+
}
6181
}
6282
} catch (error) {
6383
safeLogError('Error saving user settings:', error);

src/pages/ProfilePage.tsx

Lines changed: 128 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -47,34 +47,55 @@ export function ProfilePage() {
4747
// Convert file to base64
4848
const reader = new FileReader();
4949
reader.onload = async (e) => {
50-
const base64 = e.target?.result as string;
51-
52-
// Generate unique filename
53-
const fileName = `avatar-${user.username}-${Date.now()}.${file.type.split('/')[1]}`;
54-
const path = `avatars/${fileName}`;
55-
56-
// Upload to GitHub
57-
await putFile(path, base64.split(',')[1], `Upload avatar for ${user.username}`, true);
58-
59-
// Update user profile
60-
const updatedUser = {
61-
...user,
62-
avatar: `https://raw.githubusercontent.com/feekool/feekool.github.io/master/avatars/${fileName}`
63-
};
64-
65-
const content = stringifyFrontmatter(updatedUser, '');
66-
67-
// Get the current file with SHA to avoid 422 error
68-
const userPath = `users/${user.username}.md`;
69-
const existingFile = await getFile(userPath);
70-
71-
await putFile(userPath, content, `Update profile for ${user.username}`, false, existingFile?.sha);
72-
73-
// Update local storage
74-
localStorage.setItem('user', JSON.stringify(updatedUser));
75-
76-
// Reload page to update avatar in UI
77-
window.location.reload();
50+
try {
51+
const base64 = e.target?.result as string;
52+
53+
// Generate unique filename
54+
const fileName = `avatar-${user.username}-${Date.now()}.${file.type.split('/')[1]}`;
55+
const path = `avatars/${fileName}`;
56+
57+
// Upload to GitHub
58+
await putFile(path, base64.split(',')[1], `Upload avatar for ${user.username}`, true);
59+
60+
// Update user profile
61+
const updatedUser = {
62+
...user,
63+
avatar: `https://raw.githubusercontent.com/feekool/feekool.github.io/master/avatars/${fileName}`
64+
};
65+
66+
const content = stringifyFrontmatter(updatedUser, '');
67+
68+
// Get the current file with SHA to avoid 422 error
69+
const userPath = `users/${user.username}.md`;
70+
let existingFile = null;
71+
try {
72+
existingFile = await getFile(userPath);
73+
} catch (error: any) {
74+
if (error.status !== 401 && error.status !== 404) {
75+
throw error;
76+
}
77+
}
78+
79+
try {
80+
await putFile(userPath, content, `Update profile for ${user.username}`, false, existingFile?.sha);
81+
} catch (error: any) {
82+
if (error.status === 401) {
83+
alert('GitHub token not configured. Avatar saved locally only. Set VITE_API_KEY to sync to GitHub.');
84+
} else {
85+
throw error;
86+
}
87+
}
88+
89+
// Update local storage
90+
localStorage.setItem('user', JSON.stringify(updatedUser));
91+
92+
// Reload page to update avatar in UI
93+
window.location.reload();
94+
} catch (error) {
95+
safeLogError('Error uploading avatar:', error);
96+
alert('Failed to upload avatar. Make sure VITE_API_KEY is set.');
97+
setIsUploading(false);
98+
}
7899
};
79100

80101
reader.readAsDataURL(file);
@@ -100,9 +121,24 @@ export function ProfilePage() {
100121

101122
// Get the current file with SHA to avoid 422 error
102123
const userPath = `users/${user.username}.md`;
103-
const existingFile = await getFile(userPath);
124+
let existingFile = null;
125+
try {
126+
existingFile = await getFile(userPath);
127+
} catch (error: any) {
128+
if (error.status !== 401 && error.status !== 404) {
129+
throw error;
130+
}
131+
}
104132

105-
await putFile(userPath, content, `Update profile for ${user.username}`, false, existingFile?.sha);
133+
try {
134+
await putFile(userPath, content, `Update profile for ${user.username}`, false, existingFile?.sha);
135+
} catch (error: any) {
136+
if (error.status === 401) {
137+
alert('GitHub token not configured. Profile saved locally only. Set VITE_API_KEY to sync to GitHub.');
138+
} else {
139+
throw error;
140+
}
141+
}
106142

107143
// Update local storage
108144
localStorage.setItem('user', JSON.stringify(updatedUser));
@@ -131,9 +167,24 @@ export function ProfilePage() {
131167

132168
// Get the current file with SHA to avoid 422 error
133169
const userPath = `users/${user.username}.md`;
134-
const existingFile = await getFile(userPath);
170+
let existingFile = null;
171+
try {
172+
existingFile = await getFile(userPath);
173+
} catch (error: any) {
174+
if (error.status !== 401 && error.status !== 404) {
175+
throw error;
176+
}
177+
}
135178

136-
await putFile(userPath, content, `Reset avatar to Gravatar for ${user.username}`, false, existingFile?.sha);
179+
try {
180+
await putFile(userPath, content, `Reset avatar to Gravatar for ${user.username}`, false, existingFile?.sha);
181+
} catch (error: any) {
182+
if (error.status === 401) {
183+
alert('GitHub token not configured. Avatar reset locally only. Set VITE_API_KEY to sync to GitHub.');
184+
} else {
185+
throw error;
186+
}
187+
}
137188
localStorage.setItem('user', JSON.stringify(updatedUser));
138189
window.location.reload();
139190
} catch (error) {
@@ -291,8 +342,24 @@ export function ProfilePage() {
291342
try {
292343
const updatedUser = { ...user!, lang: newLang };
293344
const content = stringifyFrontmatter(updatedUser, '');
294-
const existingFile = await getFile(`users/${user!.username}.md`);
295-
await putFile(`users/${user!.username}.md`, content, `Update language for ${user!.username}`, false, existingFile?.sha);
345+
let existingFile = null;
346+
try {
347+
existingFile = await getFile(`users/${user!.username}.md`);
348+
} catch (error: any) {
349+
if (error.status !== 401 && error.status !== 404) {
350+
throw error;
351+
}
352+
}
353+
354+
try {
355+
await putFile(`users/${user!.username}.md`, content, `Update language for ${user!.username}`, false, existingFile?.sha);
356+
} catch (error: any) {
357+
if (error.status === 401) {
358+
console.warn('Language saved locally only - GitHub token not configured.');
359+
} else {
360+
throw error;
361+
}
362+
}
296363
localStorage.setItem('user', JSON.stringify(updatedUser));
297364
localStorage.setItem('lang', newLang);
298365
window.location.reload(); // Reload to apply language
@@ -324,8 +391,24 @@ export function ProfilePage() {
324391
try {
325392
const updatedUser = { ...user!, theme: newTheme };
326393
const content = stringifyFrontmatter(updatedUser, '');
327-
const existingFile = await getFile(`users/${user!.username}.md`);
328-
await putFile(`users/${user!.username}.md`, content, `Update theme for ${user!.username}`, false, existingFile?.sha);
394+
let existingFile = null;
395+
try {
396+
existingFile = await getFile(`users/${user!.username}.md`);
397+
} catch (error: any) {
398+
if (error.status !== 401 && error.status !== 404) {
399+
throw error;
400+
}
401+
}
402+
403+
try {
404+
await putFile(`users/${user!.username}.md`, content, `Update theme for ${user!.username}`, false, existingFile?.sha);
405+
} catch (error: any) {
406+
if (error.status === 401) {
407+
console.warn('Theme saved locally only - GitHub token not configured.');
408+
} else {
409+
throw error;
410+
}
411+
}
329412
localStorage.setItem('user', JSON.stringify(updatedUser));
330413
} catch (error) {
331414
safeLogError('Error saving theme:', error);
@@ -335,6 +418,15 @@ export function ProfilePage() {
335418
updateUserTheme();
336419
}}
337420
className="px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md bg-white dark:bg-gray-700"
421+
>
422+
} catch (error) {
423+
safeLogError('Error saving theme:', error);
424+
alert('Failed to save theme. Please try again.');
425+
}
426+
};
427+
updateUserTheme();
428+
}}
429+
className="px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md bg-white dark:bg-gray-700"
338430
>
339431
<option value="light">Light</option>
340432
<option value="dark">Dark</option>

0 commit comments

Comments
 (0)