22import type { FileDiffResponse , FileChange } from ' #shared/types'
33import { onClickOutside } from ' @vueuse/core'
44
5+ const bytesFormatter = useBytesFormatter ()
6+
57const props = defineProps <{
68 packageName: string
79 fromVersion: string
@@ -20,9 +22,21 @@ onClickOutside(optionsDropdownRef, () => {
2022 showOptions .value = false
2123})
2224
23- const apiUrl = computed (
24- () =>
25- ` /api/registry/compare-file/${props .packageName }/v/${props .fromVersion }...${props .toVersion }/${props .file .path } ` ,
25+ // Maximum file size we'll try to load (250KB) - must match server
26+ const MAX_FILE_SIZE = 250 * 1024
27+ const isFilesTooLarge = computed (() => {
28+ const newSize = props .file ?.newSize
29+ const oldSize = props .file ?.oldSize
30+ return (
31+ (newSize !== undefined && newSize > MAX_FILE_SIZE ) ||
32+ (oldSize !== undefined && oldSize > MAX_FILE_SIZE )
33+ )
34+ })
35+
36+ const apiUrl = computed (() =>
37+ isFilesTooLarge .value
38+ ? null
39+ : ` /api/registry/compare-file/${props .packageName }/v/${props .fromVersion }...${props .toVersion }/${props .file .path } ` ,
2640)
2741
2842const apiQuery = computed (() => ({
@@ -36,7 +50,7 @@ const {
3650 data : diff,
3751 status,
3852 error : loadError,
39- } = useFetch <FileDiffResponse >(apiUrl , {
53+ } = useFetch <FileDiffResponse >(() => apiUrl . value ! , {
4054 query: apiQuery ,
4155 timeout: 15000 ,
4256})
@@ -69,13 +83,6 @@ const changeRatioPercent = computed(() => calcPercent(maxChangeRatio.value, 0, 1
6983const diffDistancePercent = computed (() => calcPercent (maxDiffDistance .value , 1 , 60 ))
7084const charEditPercent = computed (() => calcPercent (inlineMaxCharEdits .value , 0 , 10 ))
7185
72- function formatBytes(bytes : number | undefined ): string {
73- if (bytes === undefined ) return ' '
74- if (bytes < 1024 ) return ` ${bytes } B `
75- if (bytes < 1024 * 1024 ) return ` ${(bytes / 1024 ).toFixed (1 )} KB `
76- return ` ${(bytes / (1024 * 1024 )).toFixed (1 )} MB `
77- }
78-
7986// Build code browser URL
8087function getCodeUrl(version : string ): string {
8188 return ` /package-code/${props .packageName }/v/${version }/${props .file .path } `
@@ -117,13 +124,14 @@ function getCodeUrl(version: string): string {
117124 <!-- File sizes -->
118125 <span v-if =" file.oldSize || file.newSize" class =" text-xs text-fg-subtle shrink-0" >
119126 <template v-if =" file .type === ' modified' " >
120- {{ formatBytes(file.oldSize) }} → {{ formatBytes(file.newSize) }}
127+ {{ bytesFormatter.format(file.oldSize ?? 0) }} →
128+ {{ bytesFormatter.format(file.newSize ?? 0) }}
121129 </template >
122130 <template v-else-if =" file .type === ' added' " >
123- {{ formatBytes (file.newSize) }}
131+ {{ bytesFormatter.format (file.newSize ?? 0 ) }}
124132 </template >
125133 <template v-else >
126- {{ formatBytes (file.oldSize) }}
134+ {{ bytesFormatter.format (file.oldSize ?? 0 ) }}
127135 </template >
128136 </span >
129137 </div >
@@ -295,8 +303,20 @@ function getCodeUrl(version: string): string {
295303
296304 <!-- Content -->
297305 <div class =" flex-1 overflow-auto relative" >
306+ <!-- File too large warning -->
307+ <div v-if =" isFilesTooLarge" class =" py-20 text-center" >
308+ <div class =" i-lucide:file-text w-12 h-12 mx-auto text-fg-subtle mb-4" />
309+ <p class =" text-fg-muted mb-2" >{{ $t('compare.file_too_large') }}</p >
310+ <p class =" text-fg-subtle text-sm mb-4" >
311+ {{
312+ $t('compare.file_size_warning', {
313+ size: bytesFormatter.format(Math.max(file.newSize ?? 0, file.oldSize ?? 0)),
314+ })
315+ }}
316+ </p >
317+ </div >
298318 <!-- Loading state -->
299- <div v-if =" status === 'pending'" class =" py-12 text-center" >
319+ <div v-else- if =" status === 'pending'" class =" py-12 text-center" >
300320 <div class =" i-svg-spinners-ring-resize w-6 h-6 mx-auto text-fg-muted" />
301321 <p class =" mt-2 text-sm text-fg-muted" >Loading diff...</p >
302322 </div >
0 commit comments