This commit is contained in:
rosetta
2026-01-30 05:01:05 +02:00
commit 83f38dc63f
327 changed files with 18725 additions and 0 deletions

303
app/utils/utils.ts Normal file
View File

@@ -0,0 +1,303 @@
import { MantineColor } from "@mantine/core";
import { MESSAGE_MAX_TIME_TO_DELEVERED_S } from "../constants";
import { decode, encode } from "blurhash";
export function generateRandomKey(length: number): string {
const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
let result = '';
const charactersLength = characters.length;
for (let i = 0; i < length; i++) {
result += characters.charAt(Math.floor(Math.random() * charactersLength));
}
return result;
}
export function murmurHash3_32_gc(key: string, seed: number = 0): number {
let remainder = key.length & 3;
let bytes = key.length - remainder;
let h1 = seed;
let c1 = 0xcc9e2d51;
let c2 = 0x1b873593;
let i = 0;
while (i < bytes) {
let k1 =
((key.charCodeAt(i) & 0xff)) |
((key.charCodeAt(++i) & 0xff) << 8) |
((key.charCodeAt(++i) & 0xff) << 16) |
((key.charCodeAt(++i) & 0xff) << 24);
++i;
k1 = (((k1 & 0xffff) * c1) + ((((k1 >>> 16) * c1) & 0xffff) << 16)) & 0xffffffff;
k1 = (k1 << 15) | (k1 >>> 17);
k1 = (((k1 & 0xffff) * c2) + ((((k1 >>> 16) * c2) & 0xffff) << 16)) & 0xffffffff;
h1 ^= k1;
h1 = (h1 << 13) | (h1 >>> 19);
let h1b = (((h1 & 0xffff) * 5) + ((((h1 >>> 16) * 5) & 0xffff) << 16)) & 0xffffffff;
h1 = ((h1b & 0xffff) + 0x6b64) + ((((h1b >>> 16) + 0xe654) & 0xffff) << 16);
}
let k1 = 0;
switch (remainder) {
case 3:
k1 ^= (key.charCodeAt(i + 2) & 0xff) << 16;
case 2:
k1 ^= (key.charCodeAt(i + 1) & 0xff) << 8;
case 1:
k1 ^= (key.charCodeAt(i) & 0xff);
k1 = (((k1 & 0xffff) * c1) + ((((k1 >>> 16) * c1) & 0xffff) << 16)) & 0xffffffff;
k1 = (k1 << 15) | (k1 >>> 17);
k1 = (((k1 & 0xffff) * c2) + ((((k1 >>> 16) * c2) & 0xffff) << 16)) & 0xffffffff;
h1 ^= k1;
}
h1 ^= key.length;
h1 ^= h1 >>> 16;
h1 = (((h1 & 0xffff) * 0x85ebca6b) + ((((h1 >>> 16) * 0x85ebca6b) & 0xffff) << 16)) & 0xffffffff;
h1 ^= h1 >>> 13;
h1 = (((h1 & 0xffff) * 0xc2b2ae35) + ((((h1 >>> 16) * 0xc2b2ae35) & 0xffff) << 16)) & 0xffffffff;
h1 ^= h1 >>> 16;
return h1 >>> 0;
}
export function generateRandomKeyFormSeed(length: number, seed: string): string {
const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
let result = '';
const charactersLength = characters.length;
let seedHash = murmurHash3_32_gc(seed, 1028);
let state = Math.abs(seedHash);
for (let i = 0; i < length; i++) {
state = (state * 1664525 + 1013904223) % 4294967296;
const randomIndex = state % charactersLength;
result += characters.charAt(randomIndex);
}
return result;
}
function hashCode(input: string) {
let hash = 0;
for (let i = 0; i < input.length; i += 1) {
const char = input.charCodeAt(i);
hash = (hash << 5) - hash + char;
hash |= 0;
}
return hash;
}
const defaultColors: MantineColor[] = [
'blue',
'cyan',
'grape',
'green',
'indigo',
'lime',
'orange',
'pink',
'red',
'teal',
'violet',
];
export function getInitialsColor(name: string, colors: MantineColor[] = defaultColors) {
const hash = hashCode(name);
const index = Math.abs(hash) % colors.length;
return colors[index];
}
export function isMessageDeliveredByTime(messageTime: number, attachmentsCount: number): boolean {
let maxMessageDeliveredTime = MESSAGE_MAX_TIME_TO_DELEVERED_S * 1000;;
//((props.time && (Date.now() - props.time * 1000 > ((MESSAGE_MAX_TIME_TO_DELEVERED * 1000) * props.attachmentsCount || 1))
if (attachmentsCount == 0) {
let t = Date.now() - messageTime < maxMessageDeliveredTime;
return t;
}
return Date.now() - messageTime < (maxMessageDeliveredTime * attachmentsCount);
}
export function filePrapareForNetworkTransfer(file : File){
return new Promise<string>((resolve, reject) => {
const reader = new FileReader();
reader.onload = () => {
if(!reader.result){
reject();
return;
}
resolve(reader.result.toString());
}
reader.readAsDataURL(file);
})
}
export function humanFilesize(size: number) {
const suffixes = ['B', 'KB', 'MB', 'GB'];
if(size >= (1024 * 1024 * 1024)){
return Math.floor(size / (1024 * 1024 * 1024)) + suffixes[3];
}
if(size >= (1024 * 1024)){
return Math.floor(size / (1024 * 1024)) + suffixes[2];
}
if(size >= 1024){
return Math.floor(size / 1024) + suffixes[1];
}
return size + suffixes[0];
}
export function imagePrepareForNetworkTransfer(file: File) {
/**
* Нужно приводить все изображения к одному формату (png) чтобы избежать проблем с отображением
* в разных платформах (ios, android, web)
*/
return new Promise<string>((resolve, reject) => {
const reader = new FileReader();
reader.onload = async () => {
if (!reader.result) {
reject();
return;
}
let base64 = reader.result.toString();
if (file.type === 'image/png') {
resolve(base64);
return;
}
try {
const jpegBlob = file;
const pngBlob = await convertJpegBlobToPngBlob(jpegBlob);
const pngBase64 = await blobToBase64(pngBlob);
resolve(pngBase64);
} catch (error) {
reject(error);
}
};
reader.readAsDataURL(file);
});
}
export function blobToBase64(blob: Blob): Promise<string> {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onloadend = () => {
if (reader.result && typeof reader.result === "string") {
resolve(reader.result);
} else {
reject("Failed to convert blob to base64");
}
};
reader.onerror = reject;
reader.readAsDataURL(blob);
});
}
export function createBlobFromBase64Image(base64Image: string): Blob {
// Split the data URL to get the MIME type and the base64 data
const parts = base64Image.split(';');
const mimeType = parts[0].split(':')[1];
const base64 = parts[1].split(',')[1];
// Decode the base64 string
const byteCharacters = atob(base64);
const byteNumbers = new Array(byteCharacters.length);
// Convert to a Uint8Array
for (let i = 0; i < byteCharacters.length; i++) {
byteNumbers[i] = byteCharacters.charCodeAt(i);
}
const byteArray = new Uint8Array(byteNumbers);
// Create the Blob
const blob = new Blob([byteArray], { type: mimeType });
return blob;
}
export function convertJpegBlobToPngBlob(jpegBlob: Blob): Promise<Blob> {
return new Promise((resolve, reject) => {
const img = new Image();
img.onload = () => {
const canvas = document.createElement('canvas');
canvas.width = img.width;
canvas.height = img.height;
const ctx = canvas.getContext('2d');
ctx?.drawImage(img, 0, 0);
// Convert the canvas content to a PNG Blob
canvas.toBlob((pngBlob) => {
if (pngBlob) {
resolve(pngBlob);
} else {
reject(new Error('Failed to create PNG blob.'));
}
}, 'image/png', 1);
};
img.onerror = (error) => reject(error);
img.src = URL.createObjectURL(jpegBlob);
});
}
export function dotMessageIfNeeded(message: string, maxLength: number): string {
if (message.length <= maxLength) {
return message;
}
return message.substring(0, maxLength).trim() + '...';
}
export function dotCenterIfNeeded(message: string, maxLength : number, viewSymbols : number = 3) {
if(message.length <= maxLength){
return message;
}
return message.slice(0, viewSymbols) + "..." + message.slice(-viewSymbols)
}
export function isImage(blob : string) : boolean {
if(!blob){
return false;
}
return blob.startsWith('data:image/');
}
export function blurhashToBase64Image(blurhash: string, width: number, height: number): string {
const pixels = decode(blurhash, width, height);
const canvas = document.createElement('canvas');
canvas.width = width;
canvas.height = height;
const ctx = canvas.getContext('2d');
const imageData = ctx?.createImageData(width, height);
if (imageData) {
imageData.data.set(pixels);
ctx?.putImageData(imageData, 0, 0);
return canvas.toDataURL();
}
return '';
}
export function base64ImageToBlurhash(base64Image: string): Promise<string> {
const img = new Image();
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
return new Promise<string>((resolve, reject) => {
img.onload = () => {
canvas.width = img.width;
canvas.height = img.height;
ctx?.drawImage(img, 0, 0);
const imageData = ctx?.getImageData(0, 0, canvas.width, canvas.height);
if (imageData) {
const blurhash = encode(
imageData.data,
imageData.width,
imageData.height,
4,
4
);
resolve(blurhash);
} else {
reject('Failed to get image data from canvas.');
}
};
img.onerror = (error) => reject(error);
img.src = base64Image;
});
}