205 lines
5.7 KiB
TypeScript
205 lines
5.7 KiB
TypeScript
import type { Cluster, ImportType, License, Loader, ManagedPackage, PackageType, Providers, VersionType } from '@onelauncher/client/bindings';
|
|
import { DurationFormat } from '@formatjs/intl-durationformat';
|
|
import { open } from '@tauri-apps/plugin-shell';
|
|
|
|
export function setAsyncTimeout(ms: number): Promise<void>;
|
|
export function setAsyncTimeout(callback: () => void, ms: number): Promise<void>;
|
|
|
|
export function setAsyncTimeout(
|
|
callback: (() => void) | number,
|
|
ms?: number,
|
|
): Promise<void> {
|
|
const _ms = typeof callback === 'number' ? callback : ms;
|
|
|
|
return new Promise<void>((resolve) => {
|
|
setTimeout(() => {
|
|
if (typeof callback === 'function')
|
|
callback();
|
|
resolve();
|
|
}, _ms);
|
|
});
|
|
}
|
|
|
|
export function supportsMods(loader?: Cluster | Loader): boolean {
|
|
if (loader === undefined)
|
|
return false;
|
|
|
|
if (typeof loader !== 'string')
|
|
loader = loader.meta.loader;
|
|
|
|
return loader !== 'vanilla';
|
|
}
|
|
|
|
export function formatVersionRelease(release: VersionType): string {
|
|
const mapping: { [key in VersionType]: string } = {
|
|
old_alpha: 'Alpha',
|
|
old_beta: 'Beta',
|
|
release: 'Release',
|
|
snapshot: 'Snapshot',
|
|
};
|
|
|
|
return mapping[release];
|
|
}
|
|
|
|
export function upperFirst<T extends string>(object: T): Capitalize<T> {
|
|
const string = object.toString();
|
|
return (string.charAt(0).toUpperCase() + string.slice(1)) as Capitalize<T>;
|
|
}
|
|
|
|
export function uint32ToBigInt([high, low]: [number, number]): bigint {
|
|
return (BigInt(high >>> 0) << 32n) | BigInt(low >>> 0);
|
|
}
|
|
|
|
export function int32ToBigInt([high, low]: [number, number]): bigint {
|
|
return (BigInt(high | 0) << 32n) | BigInt(low >>> 0);
|
|
}
|
|
|
|
export function randomString(len: number = 6, charSet: string = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789') {
|
|
let randomString = '';
|
|
for (let i = 0; i < len; i++) {
|
|
const randomPos = Math.floor(Math.random() * charSet.length);
|
|
randomString += charSet.substring(randomPos, randomPos + 1);
|
|
}
|
|
return randomString;
|
|
}
|
|
|
|
export function abbreviateNumber(n: number | bigint, locale: string = 'en-US'): string {
|
|
return new Intl.NumberFormat(locale, {
|
|
notation: 'compact',
|
|
compactDisplay: 'short',
|
|
maximumFractionDigits: 1,
|
|
}).format(n);
|
|
};
|
|
|
|
export function pluralize(n: number, word: string, locale: string = 'en'): string {
|
|
const pluralRules = new Intl.PluralRules(locale);
|
|
const pluralForm = pluralRules.select(n);
|
|
return pluralForm === 'one' ? word : `${word}s`;
|
|
}
|
|
|
|
export function formatAsDuration(
|
|
seconds: number | bigint | Date,
|
|
locale: string = 'en',
|
|
style: 'long' | 'short' | 'narrow' | 'digital' = 'long',
|
|
): string {
|
|
let n: number | undefined;
|
|
|
|
if (seconds instanceof Date)
|
|
n = seconds.getTime();
|
|
else
|
|
n = Number(seconds);
|
|
|
|
const formatter = new DurationFormat(locale, { style });
|
|
const duration = formatter.format({
|
|
seconds: Math.floor(n % 60),
|
|
minutes: Math.floor(n / 60) % 60,
|
|
hours: Math.floor(n / (60 * 60)) % 24,
|
|
days: Math.floor(n / (60 * 60 * 24)) % 7,
|
|
weeks: Math.floor(n / (60 * 60 * 24 * 7)) % 4,
|
|
months: Math.floor(n / (60 * 60 * 24 * 30)) % 12,
|
|
years: Math.floor(n / (60 * 60 * 24 * 365)),
|
|
});
|
|
|
|
if (duration.length === 0)
|
|
return 'never';
|
|
|
|
return duration;
|
|
}
|
|
|
|
export function formatAsRelative(
|
|
seconds: number | bigint | Date,
|
|
locale: string = 'en',
|
|
style: 'long' | 'short' | 'narrow' | 'digital' = 'long',
|
|
): string {
|
|
let elapsed: number | undefined;
|
|
|
|
if (seconds instanceof Date)
|
|
elapsed = seconds.getTime();
|
|
else
|
|
elapsed = Number(seconds);
|
|
|
|
elapsed -= Date.now();
|
|
|
|
const units = {
|
|
year: 31536000000,
|
|
month: 2592000000,
|
|
week: 604800000,
|
|
day: 86400000,
|
|
hour: 3600000,
|
|
minute: 60000,
|
|
second: 1000,
|
|
};
|
|
|
|
const formatter = new Intl.RelativeTimeFormat(locale, { style: style as Intl.RelativeTimeFormatStyle });
|
|
for (const [unit, ms] of Object.entries(units))
|
|
if (Math.abs(elapsed) > ms || unit === 'second')
|
|
return formatter.format(Math.round(elapsed / ms), unit as Intl.RelativeTimeFormatUnit);
|
|
|
|
return 'now';
|
|
}
|
|
|
|
export function asEnvVariables(str: string): [string, string][] {
|
|
return str
|
|
.split(' ')
|
|
.map((pair) => {
|
|
const [key, value = ''] = pair.split('=', 1);
|
|
return key ? [key, value] as [string, string] : null;
|
|
})
|
|
.filter(pair => pair !== null);
|
|
}
|
|
|
|
export function getLicenseUrl(licenseId: string | License | null | undefined): string | undefined {
|
|
if (licenseId === null || licenseId === undefined)
|
|
return;
|
|
|
|
let id: string | undefined;
|
|
|
|
if (typeof licenseId !== 'string') {
|
|
if (licenseId.url !== null && licenseId.url !== undefined) {
|
|
open(licenseId.url);
|
|
return;
|
|
}
|
|
|
|
id = licenseId.id || licenseId.name;
|
|
}
|
|
else {
|
|
id = licenseId;
|
|
}
|
|
|
|
return `https://spdx.org/licenses/${id}.html`;
|
|
}
|
|
|
|
export function getPackageUrl(pkg: ManagedPackage): string {
|
|
const mapping: Record<Providers, () => string> = {
|
|
Modrinth: () => `https://modrinth.com/${pkg.package_type}/${pkg.id}`,
|
|
CurseForge: () => {
|
|
const packageTypeMapping: Record<PackageType, string> = {
|
|
mod: 'mc-mods',
|
|
shaderpack: 'shaders',
|
|
resourcepack: 'texture-packs',
|
|
datapack: 'data-packs',
|
|
modpack: 'modpacks',
|
|
};
|
|
|
|
return `https://www.curseforge.com/minecraft/${packageTypeMapping[pkg.package_type]}/${pkg.main}`;
|
|
},
|
|
SkyClient: () => 'https://skyclient.co/', // TODO: Use pkg links once added
|
|
};
|
|
|
|
return mapping[pkg.provider]();
|
|
}
|
|
|
|
export const LOADERS: Loader[] = ['vanilla', 'fabric', 'forge', 'neoforge', 'quilt'] as const;
|
|
export const PROVIDERS: Providers[] = ['Modrinth', 'CurseForge', 'SkyClient'] as const;
|
|
export const PACKAGE_TYPES: PackageType[] = ['mod', 'resourcepack', 'datapack', 'shaderpack'] as const;
|
|
export const LAUNCHER_IMPORT_TYPES: ImportType[] = [
|
|
'PrismLauncher',
|
|
'CurseForge',
|
|
// 'Modrinth',
|
|
'ATLauncher',
|
|
'GDLauncher',
|
|
// 'FTBLauncher',
|
|
'MultiMC',
|
|
// 'TLauncher',
|
|
// 'Technic'
|
|
] as const;
|