feat(server,web,mobile): Use binary prefixes for data sizes (#1009)

This commit is contained in:
Kiel Hurley 2022-11-25 06:39:27 +13:00 committed by GitHub
parent df0a059a02
commit 976d347623
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 64 additions and 101 deletions

View File

@ -6,6 +6,7 @@ import 'package:immich_mobile/shared/models/asset.dart';
import 'package:openapi/api.dart';
import 'package:path/path.dart' as p;
import 'package:latlong2/latlong.dart';
import 'package:immich_mobile/utils/bytes_units.dart';
class ExifBottomSheet extends ConsumerWidget {
final Asset assetDetail;
@ -162,7 +163,7 @@ class ExifBottomSheet extends ConsumerWidget {
),
subtitle: exifInfo.exifImageHeight != null
? Text(
"${exifInfo.exifImageHeight} x ${exifInfo.exifImageWidth} ${exifInfo.fileSizeInByte!}B ",
"${exifInfo.exifImageHeight} x ${exifInfo.exifImageWidth} ${formatBytes(exifInfo.fileSizeInByte!)} ",
)
: null,
),

View File

@ -1,15 +1,17 @@
String formatBytes(int bytes) {
if (bytes < 1000) {
return "$bytes B";
} else if (bytes < 1000000) {
final kb = (bytes / 1000).toStringAsFixed(1);
return "$kb kB";
} else if (bytes < 1000000000) {
final mb = (bytes / 1000000).toStringAsFixed(1);
return "$mb MB";
} else {
final gb = (bytes / 1000000000).toStringAsFixed(1);
return "$gb GB";
const units = ['B', 'KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB'];
int magnitude = 0;
double remainder = bytes.toDouble();
while (remainder >= 1024) {
if (magnitude + 1 < units.length) {
magnitude++;
remainder /= 1024;
}
else {
break;
}
}
return "${remainder.toStringAsFixed(magnitude == 0 ? 0 : 1)} ${units[magnitude]}";
}

View File

@ -35,7 +35,7 @@ export class DownloadService {
fileCount++;
// for easier testing, can be changed before merging.
if (totalSize > HumanReadableSize.GB * 20) {
if (totalSize > HumanReadableSize.GiB * 20) {
complete = false;
this.logger.log(
`Archive size exceeded after ${fileCount} files, capping at ${totalSize} bytes (${asHumanReadable(

View File

@ -1,31 +1,25 @@
const KB = 1000;
const MB = KB * 1000;
const GB = MB * 1000;
const TB = GB * 1000;
const PB = TB * 1000;
const KiB = Math.pow(1024, 1);
const MiB = Math.pow(1024, 2);
const GiB = Math.pow(1024, 3);
const TiB = Math.pow(1024, 4);
const PiB = Math.pow(1024, 5);
export const HumanReadableSize = { KB, MB, GB, TB, PB };
export const HumanReadableSize = { KiB, MiB, GiB, TiB, PiB };
export function asHumanReadable(bytes: number, precision = 1) {
if (bytes >= PB) {
return `${(bytes / PB).toFixed(precision)}PB`;
export function asHumanReadable(bytes: number, precision = 1): string {
const units = ['B', 'KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB'];
let magnitude = 0;
let remainder = bytes;
while (remainder >= 1024) {
if (magnitude + 1 < units.length) {
magnitude++;
remainder /= 1024;
}
else {
break;
}
}
if (bytes >= TB) {
return `${(bytes / TB).toFixed(precision)}TB`;
}
if (bytes >= GB) {
return `${(bytes / GB).toFixed(precision)}GB`;
}
if (bytes >= MB) {
return `${(bytes / MB).toFixed(precision)}MB`;
}
if (bytes >= KB) {
return `${(bytes / KB).toFixed(precision)}KB`;
}
return `${bytes}B`;
return `${remainder.toFixed( magnitude == 0 ? 0 : precision )} ${units[magnitude]}`;
}

View File

@ -15,8 +15,8 @@
return name;
};
$: spaceUnit = stats.usage.slice(stats.usage.length - 2, stats.usage.length);
$: spaceUsage = stats.usage.slice(0, stats.usage.length - 2);
$: spaceUnit = stats.usage.split(' ')[1];
$: spaceUsage = stats.usage.split(' ')[0];
</script>
<div class="flex flex-col gap-5">

View File

@ -8,6 +8,7 @@
import { createEventDispatcher, onMount } from 'svelte';
import { browser } from '$app/environment';
import { AssetResponseDto, AlbumResponseDto } from '@api';
import { getHumanReadableBytes } from '../../utils/byte-units';
type Leaflet = typeof import('leaflet');
type LeafletMap = import('leaflet').Map;
@ -59,32 +60,6 @@
}
const dispatch = createEventDispatcher();
const getHumanReadableString = (sizeInByte: number) => {
const pepibyte = 1.126 * Math.pow(10, 15);
const tebibyte = 1.1 * Math.pow(10, 12);
const gibibyte = 1.074 * Math.pow(10, 9);
const mebibyte = 1.049 * Math.pow(10, 6);
const kibibyte = 1024;
// Pebibyte
if (sizeInByte >= pepibyte) {
// Pe
return `${(sizeInByte / pepibyte).toFixed(1)}PB`;
} else if (tebibyte <= sizeInByte && sizeInByte < pepibyte) {
// Te
return `${(sizeInByte / tebibyte).toFixed(1)}TB`;
} else if (gibibyte <= sizeInByte && sizeInByte < tebibyte) {
// Gi
return `${(sizeInByte / gibibyte).toFixed(1)}GB`;
} else if (mebibyte <= sizeInByte && sizeInByte < gibibyte) {
// Mega
return `${(sizeInByte / mebibyte).toFixed(1)}MB`;
} else if (kibibyte <= sizeInByte && sizeInByte < mebibyte) {
// Kibi
return `${(sizeInByte / kibibyte).toFixed(1)}KB`;
} else {
return `${sizeInByte}B`;
}
};
const getMegapixel = (width: number, height: number): number | undefined => {
const megapixel = Math.round((height * width) / 1_000_000);
@ -149,7 +124,7 @@
<p>{asset.exifInfo.exifImageHeight} x {asset.exifInfo.exifImageWidth}</p>
{/if}
<p>{getHumanReadableString(asset.exifInfo.fileSizeInByte)}</p>
<p>{getHumanReadableBytes(asset.exifInfo.fileSizeInByte)}</p>
</div>
</div>
</div>
@ -162,7 +137,7 @@
<div>
<p>{asset.exifInfo.make || ''} {asset.exifInfo.model || ''}</p>
<div class="flex text-sm gap-2">
<p>{`f/${asset.exifInfo.fNumber}` || ''}</p>
<p>{`ƒ/${asset.exifInfo.fNumber}` || ''}</p>
{#if asset.exifInfo.exposureTime}
<p>{`1/${Math.floor(1 / asset.exifInfo.exposureTime)}`}</p>

View File

@ -6,6 +6,8 @@
import WindowMinimize from 'svelte-material-icons/WindowMinimize.svelte';
import type { UploadAsset } from '$lib/models/upload-asset';
import { notificationController, NotificationType } from './notification/notification';
import { getHumanReadableBytes } from '../../utils/byte-units';
let showDetail = true;
let uploadLength = 0;
@ -30,33 +32,6 @@
}
};
function getSizeInHumanReadableFormat(sizeInByte: number) {
const pepibyte = 1.126 * Math.pow(10, 15);
const tebibyte = 1.1 * Math.pow(10, 12);
const gibibyte = 1.074 * Math.pow(10, 9);
const mebibyte = 1.049 * Math.pow(10, 6);
const kibibyte = 1024;
// Pebibyte
if (sizeInByte >= pepibyte) {
// Pe
return `${(sizeInByte / pepibyte).toFixed(1)}PB`;
} else if (tebibyte <= sizeInByte && sizeInByte < pepibyte) {
// Te
return `${(sizeInByte / tebibyte).toFixed(1)}TB`;
} else if (gibibyte <= sizeInByte && sizeInByte < tebibyte) {
// Gi
return `${(sizeInByte / gibibyte).toFixed(1)}GB`;
} else if (mebibyte <= sizeInByte && sizeInByte < gibibyte) {
// Mega
return `${(sizeInByte / mebibyte).toFixed(1)}MB`;
} else if (kibibyte <= sizeInByte && sizeInByte < mebibyte) {
// Kibi
return `${(sizeInByte / kibibyte).toFixed(1)}KB`;
} else {
return `${sizeInByte}B`;
}
}
// Reactive action to get thumbnail image of upload asset whenever there is a new one added to the list
$: {
if ($uploadAssetsStore.length != uploadLength) {
@ -140,7 +115,7 @@
<input
disabled
class="bg-gray-100 border w-full p-1 rounded-md text-[10px] px-2"
value={`[${getSizeInHumanReadableFormat(uploadAsset.file.size)}] ${
value={`[${getHumanReadableBytes(uploadAsset.file.size)}] ${
uploadAsset.file.name
}`}
/>

View File

@ -0,0 +1,16 @@
export function getHumanReadableBytes(bytes: number): string {
const units = ['B', 'KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB'];
let magnitude = 0;
let remainder = bytes;
while (remainder >= 1024) {
if (magnitude + 1 < units.length) {
magnitude++;
remainder /= 1024;
} else {
break;
}
}
return `${remainder.toFixed(magnitude == 0 ? 0 : 1)} ${units[magnitude]}`;
}