(files: File[])
| 125 | }; |
| 126 | |
| 127 | const addFiles = async (files: File[]) => { |
| 128 | setProjectError(undefined); |
| 129 | setProjectNotice(undefined); |
| 130 | const entries: FontSourceEntry[] = files.map((file) => ({ |
| 131 | id: nextSourceId.current++, |
| 132 | file, |
| 133 | inspection: null, |
| 134 | })); |
| 135 | if (entries.length === 0) return; |
| 136 | const totalBytes = [...sources, ...entries].reduce( |
| 137 | (total, source) => total + source.file.size, |
| 138 | 0, |
| 139 | ); |
| 140 | if (totalBytes > MAX_PROJECT_BYTES) { |
| 141 | setProjectError( |
| 142 | 'The selected files would exceed the 250 MB batch limit. Remove some font files or choose fewer files.', |
| 143 | ); |
| 144 | return; |
| 145 | } |
| 146 | |
| 147 | resetResults(); |
| 148 | setSources((current) => [...current, ...entries]); |
| 149 | const ctx = createFontContext(); |
| 150 | |
| 151 | try { |
| 152 | await processWithConcurrency( |
| 153 | entries, |
| 154 | async (entry) => { |
| 155 | try { |
| 156 | const inspection = await inspectFont( |
| 157 | ctx, |
| 158 | new Uint8Array(await entry.file.arrayBuffer()), |
| 159 | ); |
| 160 | |
| 161 | setSources((current) => |
| 162 | current.map((source) => |
| 163 | source.id === entry.id ? { ...source, inspection } : source, |
| 164 | ), |
| 165 | ); |
| 166 | } catch { |
| 167 | setSources((current) => |
| 168 | current.map((source) => |
| 169 | source.id === entry.id |
| 170 | ? { |
| 171 | ...source, |
| 172 | error: |
| 173 | 'We could not read this file as a font. Try another copy.', |
| 174 | } |
| 175 | : source, |
| 176 | ), |
| 177 | ); |
| 178 | } |
| 179 | }, |
| 180 | () => stopRequested.current, |
| 181 | ); |
| 182 | } finally { |
| 183 | ctx.destroy(); |
| 184 | } |
nothing calls this directly
no test coverage detected