diff --git a/frontend/index.html b/frontend/index.html
index b1a173f..e6b7d0c 100644
--- a/frontend/index.html
+++ b/frontend/index.html
@@ -6,7 +6,27 @@
Holy Flavors
-
+
+
diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx
index 5285b06..24e1b64 100644
--- a/frontend/src/App.tsx
+++ b/frontend/src/App.tsx
@@ -249,7 +249,10 @@ const App: React.FC = () => {
if (userRes.data && userRes.data.username) {
setUser(userRes.data);
- if (userRes.data.theme) setThemeName(userRes.data.theme);
+ if (userRes.data.theme) {
+ setThemeName(userRes.data.theme);
+ localStorage.setItem('theme', userRes.data.theme);
+ }
if (userRes.data.language) i18n.changeLanguage(userRes.data.language);
try {
diff --git a/frontend/src/pages/PublicProfile.tsx b/frontend/src/pages/PublicProfile.tsx
index 542b364..4efe4c9 100644
--- a/frontend/src/pages/PublicProfile.tsx
+++ b/frontend/src/pages/PublicProfile.tsx
@@ -121,8 +121,30 @@ const PublicProfile: React.FC = ({ adminMode }) => {
img.onload = () => {
const colorThief = new ColorThief();
try {
- const colors = colorThief.getPalette(img, 3);
- setPalette(colors.map(c => `rgb(${c[0]}, ${c[1]}, ${c[2]})`));
+ const palette = colorThief.getPalette(img, 10);
+
+ // Filter for colors that are neither too dark nor too bright (washed out)
+ // and prefer higher saturation
+ const processed = palette.map(c => {
+ const r = c[0] / 255, g = c[1] / 255, b = c[2] / 255;
+ const max = Math.max(r, g, b), min = Math.min(r, g, b);
+ const l = (max + min) / 2;
+ const s = max === min ? 0 : (l > 0.5 ? (max - min) / (2 - max - min) : (max - min) / (max + min));
+ return { rgb: `rgb(${c[0]}, ${c[1]}, ${c[2]})`, l, s };
+ });
+
+ // Sort by saturation (highest first) then filter by luminance (0.3 - 0.8 range)
+ const vibrant = processed
+ .filter(c => c.l > 0.2 && c.l < 0.85) // Avoid pure black/white
+ .sort((a, b) => b.s - a.s); // Prefer colorful ones
+
+ if (vibrant.length >= 2) {
+ setPalette([vibrant[0].rgb, vibrant[1].rgb]);
+ } else if (vibrant.length === 1) {
+ setPalette([vibrant[0].rgb, vibrant[0].rgb]);
+ } else {
+ setPalette([]);
+ }
} catch (e) {
setPalette([]);
}
@@ -206,15 +228,17 @@ const PublicProfile: React.FC = ({ adminMode }) => {
const bannerColors = [
palette[0] || theme.palette.primary.main,
palette[1] || theme.palette.secondary.main,
- theme.palette.primary.main,
- theme.palette.secondary.main
+ theme.palette.secondary.main,
+ theme.palette.primary.main
];
const abstractBanner = `
- radial-gradient(at 0% 0%, ${alpha(bannerColors[0], 0.6)} 0px, transparent 50%),
- radial-gradient(at 100% 0%, ${alpha(bannerColors[1], 0.4)} 0px, transparent 50%),
- radial-gradient(at 50% 100%, ${alpha(bannerColors[2], 0.3)} 0px, transparent 50%),
- linear-gradient(135deg, ${alpha(bannerColors[0], 0.1)} 0%, ${alpha(bannerColors[3], 0.1)} 100%)
+ radial-gradient(at 0% 0%, ${alpha(bannerColors[0], 0.8)} 0px, transparent 55%),
+ radial-gradient(at 100% 0%, ${alpha(bannerColors[1], 0.7)} 0px, transparent 55%),
+ radial-gradient(at 100% 100%, ${alpha(bannerColors[2], 0.6)} 0px, transparent 55%),
+ radial-gradient(at 0% 100%, ${alpha(bannerColors[3], 0.5)} 0px, transparent 55%),
+ radial-gradient(at 50% 50%, ${alpha(bannerColors[0], 0.4)} 0px, transparent 60%),
+ linear-gradient(135deg, ${alpha(bannerColors[0], 0.2)} 0%, ${alpha(bannerColors[1], 0.2)} 100%)
`;
const handleGoBack = () => {