feat: 유저별 로고·브랜드명 커스터마이징 — .smallclaw/users/<user>/logo.png, brand_name.txt
헤더/환영화면/채팅 아바타·라벨을 로그인 유저별로 스왑. 파일 없으면 기본 HomeClaw 유지. 애플·자스민 계정에 기본 로고(이모지 아이콘) 적용. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01E5kyXurhNSboRcY3dAGceY
This commit is contained in:
@@ -2496,6 +2496,7 @@ app.get('/api/auth/status', (_req, res) => {
|
||||
authenticated: !!session,
|
||||
username: session?.username ?? null,
|
||||
role: session?.role ?? null,
|
||||
brandName: getUserBrandName(session?.username),
|
||||
});
|
||||
});
|
||||
|
||||
@@ -2836,6 +2837,34 @@ app.all('/api/localllm/:provider/{*subPath}', async (req: express.Request, res:
|
||||
}
|
||||
});
|
||||
|
||||
// Per-user brand name override, e.g. <configDir>/users/<username>/brand_name.txt
|
||||
// containing "체리클로" — falls back to "HomeClaw" when absent.
|
||||
function getUserBrandName(username: string | null | undefined): string | null {
|
||||
if (!username) return null;
|
||||
try {
|
||||
const p = path.join(getConfig().getConfigDir(), 'users', username, 'brand_name.txt');
|
||||
if (fs.existsSync(p)) {
|
||||
const name = fs.readFileSync(p, 'utf8').trim();
|
||||
if (name) return name.slice(0, 40);
|
||||
}
|
||||
} catch {}
|
||||
return null;
|
||||
}
|
||||
|
||||
// Per-user logo — falls back to the default HomeClaw logo when the user has
|
||||
// no custom logo file. Drop a PNG at <configDir>/users/<username>/logo.png
|
||||
// to override (e.g. an old family nickname logo).
|
||||
app.get('/api/branding/logo', (req, res) => {
|
||||
const username = (req as any).user?.username as string | undefined;
|
||||
const defaultLogo = path.join(webUiPath, 'homeclaw_logo.png');
|
||||
res.setHeader('Cache-Control', 'no-cache');
|
||||
if (username) {
|
||||
const custom = path.join(getConfig().getConfigDir(), 'users', username, 'logo.png');
|
||||
if (fs.existsSync(custom)) return res.sendFile(custom);
|
||||
}
|
||||
res.sendFile(defaultLogo);
|
||||
});
|
||||
|
||||
app.use(express.static(webUiPath, { setHeaders: (res) => { res.setHeader('Cache-Control', 'no-cache'); } }));
|
||||
|
||||
// Serve code directory files for HTML preview (window.open)
|
||||
|
||||
Reference in New Issue
Block a user