44 lines
1.7 KiB
TypeScript
44 lines
1.7 KiB
TypeScript
/**
|
||
* 添付ファイル共通ヘルパー。
|
||
* - toBase64: File → base64(data: URL のヘッダを除去)
|
||
* - uniqueAttachmentName: クリップボード画像の "image.png" 問題と名前衝突を解決。
|
||
* 添付一覧は name を React key / 削除キーに使うため一意である必要がある。
|
||
*/
|
||
export async function toBase64(file: File): Promise<string> {
|
||
return new Promise((resolve, reject) => {
|
||
const reader = new FileReader();
|
||
reader.onload = () => {
|
||
const result = String(reader.result ?? '');
|
||
resolve(result.includes(',') ? result.split(',')[1]! : result);
|
||
};
|
||
reader.onerror = () => reject(reader.error ?? new Error('file read error'));
|
||
reader.readAsDataURL(file);
|
||
});
|
||
}
|
||
|
||
function splitExt(name: string): { stem: string; ext: string } {
|
||
const dot = name.lastIndexOf('.');
|
||
if (dot <= 0) return { stem: name, ext: '' };
|
||
return { stem: name.slice(0, dot), ext: name.slice(dot) };
|
||
}
|
||
|
||
export function uniqueAttachmentName(
|
||
original: string,
|
||
taken: Set<string>,
|
||
now: Date = new Date(),
|
||
): string {
|
||
let base = original;
|
||
// ブラウザのクリップボード画像は一律 "image.png" で来るため日時名に差し替える
|
||
if (original === 'image.png') {
|
||
const pad = (n: number, w = 2) => String(n).padStart(w, '0');
|
||
const stamp = `${now.getFullYear()}${pad(now.getMonth() + 1)}${pad(now.getDate())}-${pad(now.getHours())}${pad(now.getMinutes())}${pad(now.getSeconds())}`;
|
||
base = `pasted-${stamp}.png`;
|
||
}
|
||
if (!taken.has(base)) return base;
|
||
const { stem, ext } = splitExt(base);
|
||
for (let i = 2; ; i++) {
|
||
const candidate = `${stem}-${i}${ext}`;
|
||
if (!taken.has(candidate)) return candidate;
|
||
}
|
||
}
|