Refactoring round one: HttpFontStore/HttpSoundStore/HttpTextureStore collapse into a generic HttpFileStore over a FileStore contract; fontImport/soundImport/textureImport share assetImport with an ImportKind per sort; ImagePicker/FontPicker/SoundPicker sit on FilePicker and describe only their row. The group/comment drag logic leaves GraphCanvas for annotationDrag.ts (with its own unit test), declaredRows.ts replaces the duplicated row build in particles.ts and shaders.ts, and dead code in font/sound/compile/emission/transform/actions is gone. README: asset list, check count 958, the two-job CI, the Scenes wiki page. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
48 lines
1.8 KiB
TypeScript
48 lines
1.8 KiB
TypeScript
import { CreateFontCommand } from '../core/commands/assetCommands';
|
||
import type { FontStore, UploadedFont } from '../core/store/FontStore';
|
||
import { type ImportKind, type ImportOutcome, importFiles, importStored, pickAndImport } from './assetImport';
|
||
import type { EditorState } from './state';
|
||
|
||
/** What the file dialog offers and a drop accepts; the server rejects everything else anyway. */
|
||
export const FONT_ACCEPT = '.ttf,.otf,.woff,.woff2';
|
||
|
||
const FONT_EXTENSION = /\.(ttf|otf|woff|woff2)$/i;
|
||
|
||
/**
|
||
* Fonts are told apart by their name, not their MIME type: browsers report a dropped `.ttf` as
|
||
* `font/ttf`, `application/x-font-ttf` or nothing at all, depending on the platform.
|
||
*/
|
||
export function isFontFileName(name: string): boolean {
|
||
return FONT_EXTENSION.test(name);
|
||
}
|
||
|
||
export interface FontImportDeps {
|
||
state: EditorState;
|
||
fonts: FontStore;
|
||
}
|
||
|
||
const FONT_KIND: ImportKind<UploadedFont, FontImportDeps> = {
|
||
type: 'font',
|
||
noun: 'font',
|
||
fallbackName: 'Font',
|
||
store: (deps) => deps.fonts,
|
||
// The bytes go up untouched: unlike a picture, a typeface cannot be re-encoded smaller here.
|
||
prepare: (file) =>
|
||
isFontFileName(file.name)
|
||
? Promise.resolve({ blob: file, type: file.type || 'application/octet-stream' })
|
||
: Promise.reject(new Error('Not a font file – use TTF, OTF, WOFF or WOFF2.')),
|
||
create: (name, font) => new CreateFontCommand(name, font.file),
|
||
};
|
||
|
||
export function importFonts(files: readonly File[], deps: FontImportDeps): Promise<ImportOutcome[]> {
|
||
return importFiles(FONT_KIND, files, deps);
|
||
}
|
||
|
||
export function importStoredFont(font: UploadedFont, deps: FontImportDeps): ImportOutcome {
|
||
return importStored(FONT_KIND, font, deps);
|
||
}
|
||
|
||
export function pickAndImportFonts(deps: FontImportDeps): void {
|
||
pickAndImport(FONT_KIND, FONT_ACCEPT, deps);
|
||
}
|