519c411db0
* feat: sync and update with all changes from fork * refactor: extract clipboard copy logic into custom hook * fix: correct spelling of DEFAULT_REFRESH_FREQUENCY_MS in Stamps and WalletBalance providers * refactor(ui-tests): replace fixed sleeps with condition-based waits * fix: handle null values for size and granteeCount in infoGroups * fix(lint): add newline at end of file in useClipboardCopy hook * fix(ui-tests): page.goto URL * refactor: update import paths for useClipboardCopy --------- Co-authored-by: Ferenc Sárai <sarai.ferenc@gmail.com>
142 lines
3.6 KiB
TypeScript
142 lines
3.6 KiB
TypeScript
import { Bytes, PrivateKey } from '@ethersphere/bee-js'
|
|
import { FileInfo, FileStatus } from '@solarpunkltd/file-manager-lib'
|
|
import React from 'react'
|
|
|
|
import { LocalStorageKeys } from '../../../utils/localStorage'
|
|
import { lifetimeAdjustments } from '../constants/stamps'
|
|
|
|
export function getDaysLeft(expiryDate: Date): number {
|
|
const now = new Date()
|
|
|
|
const diffMs = expiryDate.getTime() - now.getTime()
|
|
|
|
return Math.max(0, Math.floor(diffMs / (1000 * 60 * 60 * 24)))
|
|
}
|
|
|
|
export const fromBytesConversion = (size: number, metric: string) => {
|
|
switch (metric) {
|
|
case 'GB':
|
|
return size / 1000 / 1000 / 1000
|
|
case 'MB':
|
|
return size / 1000 / 1000
|
|
default:
|
|
return 0
|
|
}
|
|
}
|
|
|
|
export function getExpiryDateByLifetime(lifetimeValue: number, actualValidity?: Date): Date {
|
|
const now = actualValidity || new Date()
|
|
|
|
const adjustDate = lifetimeAdjustments.get(lifetimeValue)
|
|
|
|
if (adjustDate) {
|
|
adjustDate(now)
|
|
}
|
|
|
|
return now
|
|
}
|
|
|
|
export const indexStrToBigint = (indexStr?: string): bigint | undefined => {
|
|
if (!indexStr) {
|
|
return undefined
|
|
}
|
|
|
|
const isHex = /[a-fA-F]/.test(indexStr) || indexStr.startsWith('0') || indexStr.length > 10
|
|
|
|
if (isHex) {
|
|
return BigInt(parseInt(indexStr, 16))
|
|
}
|
|
|
|
return BigInt(parseInt(indexStr, 10))
|
|
}
|
|
|
|
export const formatBytes = (v?: string | number): string | undefined => {
|
|
let n: number
|
|
|
|
if (typeof v === 'string') n = Number(v)
|
|
else if (typeof v === 'number') n = v
|
|
else n = NaN
|
|
|
|
if (!Number.isFinite(n) || n < 0) return undefined
|
|
|
|
if (n < 1000) return `${n} B`
|
|
|
|
const units = ['KB', 'MB', 'GB', 'TB'] as const
|
|
let val = n / 1000
|
|
let i = 0
|
|
while (val >= 1000 && i < units.length - 1) {
|
|
val /= 1000
|
|
i++
|
|
}
|
|
|
|
return `${val.toFixed(1)} ${units[i]}`
|
|
}
|
|
|
|
export const isTrashed = (fi: FileInfo): boolean => fi.status === FileStatus.Trashed
|
|
|
|
export type Point = { x: number; y: number }
|
|
export enum Dir {
|
|
Down = 'down',
|
|
Up = 'up',
|
|
}
|
|
|
|
export function getFileId(fi: FileInfo): string {
|
|
return fi.topic.toString()
|
|
}
|
|
|
|
export function getSigner(input: string): PrivateKey {
|
|
const normalized = input.trim().toLowerCase()
|
|
const inputBytes = Bytes.fromUtf8(normalized)
|
|
const privateKeyHex = Bytes.keccak256(inputBytes).toHex()
|
|
|
|
return new PrivateKey(privateKeyHex)
|
|
}
|
|
|
|
export function getSignerPk(): PrivateKey | undefined {
|
|
try {
|
|
const fromLocalPk = localStorage.getItem(LocalStorageKeys.fmPrivateKey)
|
|
|
|
if (!fromLocalPk) {
|
|
// eslint-disable-next-line no-console
|
|
console.error('Private key not found, cannot initialize')
|
|
|
|
return undefined
|
|
}
|
|
|
|
return new PrivateKey(fromLocalPk)
|
|
} catch (err) {
|
|
// eslint-disable-next-line no-console
|
|
console.error(`Private key error in localStorage under key "${LocalStorageKeys.fmPrivateKey}": `, err)
|
|
|
|
return undefined
|
|
}
|
|
}
|
|
|
|
export function setSignerPk(pk: string): void {
|
|
localStorage.setItem(LocalStorageKeys.fmPrivateKey, pk)
|
|
}
|
|
|
|
export function removeSignerPk(): void {
|
|
localStorage.removeItem(LocalStorageKeys.fmPrivateKey)
|
|
}
|
|
|
|
export const capitalizeFirstLetter = (str: string): string => str.charAt(0).toUpperCase() + str.slice(1)
|
|
|
|
export const safeSetState =
|
|
<T>(ref: React.RefObject<boolean>, setter: React.Dispatch<React.SetStateAction<T>>) =>
|
|
(value: React.SetStateAction<T>) => {
|
|
if (ref.current) setter(value)
|
|
}
|
|
|
|
export const truncateNameMiddle = (s: string, max = 40, start?: number, end?: number): string => {
|
|
if (s.length <= max) return s
|
|
|
|
if (start && end && start + end < s.length) {
|
|
return `${s.slice(0, start)}…${s.slice(-end)}`
|
|
}
|
|
|
|
const half = Math.floor((max - 1) / 2)
|
|
|
|
return `${s.slice(0, half)}…${s.slice(-half)}`
|
|
}
|