59 lines
1.8 KiB
TypeScript
59 lines
1.8 KiB
TypeScript
import { Injectable, inject } from '@angular/core';
|
|
import { ElectronBridgeService } from '../../../../core/platform/electron/electron-bridge.service';
|
|
import { User } from '../../../../shared-kernel';
|
|
import {
|
|
ProcessedProfileAvatar,
|
|
resolveProfileAvatarStorageFileName
|
|
} from '../../domain/profile-avatar.models';
|
|
|
|
const LEGACY_PROFILE_FILE_NAMES = [
|
|
'profile.webp',
|
|
'profile.gif',
|
|
'profile.jpg',
|
|
'profile.jpeg',
|
|
'profile.png'
|
|
];
|
|
|
|
@Injectable({ providedIn: 'root' })
|
|
export class ProfileAvatarStorageService {
|
|
private readonly electronBridge = inject(ElectronBridgeService);
|
|
|
|
async persistProcessedAvatar(
|
|
user: Pick<User, 'id' | 'username' | 'displayName'>,
|
|
avatar: Pick<ProcessedProfileAvatar, 'base64' | 'avatarMime'>
|
|
): Promise<void> {
|
|
const electronApi = this.electronBridge.getApi();
|
|
|
|
if (!electronApi) {
|
|
return;
|
|
}
|
|
|
|
const appDataPath = await electronApi.getAppDataPath();
|
|
const usernameSegment = this.sanitizePathSegment(user.username || user.displayName || user.id || 'user');
|
|
const directoryPath = `${appDataPath}/user/${usernameSegment}/profile`;
|
|
const targetFileName = resolveProfileAvatarStorageFileName(avatar.avatarMime);
|
|
|
|
await electronApi.ensureDir(directoryPath);
|
|
|
|
for (const fileName of LEGACY_PROFILE_FILE_NAMES) {
|
|
const filePath = `${directoryPath}/${fileName}`;
|
|
|
|
if (fileName !== targetFileName && await electronApi.fileExists(filePath)) {
|
|
await electronApi.deleteFile(filePath);
|
|
}
|
|
}
|
|
|
|
await electronApi.writeFile(`${directoryPath}/${targetFileName}`, avatar.base64);
|
|
}
|
|
|
|
private sanitizePathSegment(value: string): string {
|
|
const normalized = value
|
|
.trim()
|
|
.replace(/[^a-zA-Z0-9._-]+/g, '-')
|
|
.replace(/^-+|-+$/g, '')
|
|
.slice(0, 80);
|
|
|
|
return normalized || 'user';
|
|
}
|
|
}
|