2023-11-20 01:47:07 +00:00
|
|
|
import { v4 as uuidv4 } from 'uuid';
|
|
|
|
import sha256 from 'js-sha256';
|
|
|
|
|
|
|
|
//////////////////////////
|
|
|
|
// Helper functions
|
|
|
|
//////////////////////////
|
|
|
|
|
|
|
|
export const splitStream = (splitOn) => {
|
|
|
|
let buffer = '';
|
|
|
|
return new TransformStream({
|
|
|
|
transform(chunk, controller) {
|
|
|
|
buffer += chunk;
|
|
|
|
const parts = buffer.split(splitOn);
|
|
|
|
parts.slice(0, -1).forEach((part) => controller.enqueue(part));
|
|
|
|
buffer = parts[parts.length - 1];
|
|
|
|
},
|
|
|
|
flush(controller) {
|
|
|
|
if (buffer) controller.enqueue(buffer);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
|
|
|
export const convertMessagesToHistory = (messages) => {
|
2024-01-03 22:33:57 +00:00
|
|
|
const history = {
|
2023-11-20 01:47:07 +00:00
|
|
|
messages: {},
|
|
|
|
currentId: null
|
|
|
|
};
|
|
|
|
|
|
|
|
let parentMessageId = null;
|
|
|
|
let messageId = null;
|
|
|
|
|
|
|
|
for (const message of messages) {
|
|
|
|
messageId = uuidv4();
|
|
|
|
|
|
|
|
if (parentMessageId !== null) {
|
|
|
|
history.messages[parentMessageId].childrenIds = [
|
|
|
|
...history.messages[parentMessageId].childrenIds,
|
|
|
|
messageId
|
|
|
|
];
|
|
|
|
}
|
|
|
|
|
|
|
|
history.messages[messageId] = {
|
|
|
|
...message,
|
|
|
|
id: messageId,
|
|
|
|
parentId: parentMessageId,
|
|
|
|
childrenIds: []
|
|
|
|
};
|
|
|
|
|
|
|
|
parentMessageId = messageId;
|
|
|
|
}
|
|
|
|
|
|
|
|
history.currentId = messageId;
|
|
|
|
return history;
|
|
|
|
};
|
|
|
|
|
|
|
|
export const getGravatarURL = (email) => {
|
|
|
|
// Trim leading and trailing whitespace from
|
|
|
|
// an email address and force all characters
|
|
|
|
// to lower case
|
|
|
|
const address = String(email).trim().toLowerCase();
|
|
|
|
|
|
|
|
// Create a SHA256 hash of the final string
|
|
|
|
const hash = sha256(address);
|
|
|
|
|
|
|
|
// Grab the actual image URL
|
|
|
|
return `https://www.gravatar.com/avatar/${hash}`;
|
|
|
|
};
|
2023-12-19 02:48:51 +00:00
|
|
|
|
2023-12-26 20:50:52 +00:00
|
|
|
export const copyToClipboard = (text) => {
|
2023-12-19 02:48:51 +00:00
|
|
|
if (!navigator.clipboard) {
|
2023-12-26 20:50:52 +00:00
|
|
|
const textArea = document.createElement('textarea');
|
2023-12-19 02:48:51 +00:00
|
|
|
textArea.value = text;
|
|
|
|
|
|
|
|
// Avoid scrolling to bottom
|
|
|
|
textArea.style.top = '0';
|
|
|
|
textArea.style.left = '0';
|
|
|
|
textArea.style.position = 'fixed';
|
|
|
|
|
|
|
|
document.body.appendChild(textArea);
|
|
|
|
textArea.focus();
|
|
|
|
textArea.select();
|
|
|
|
|
|
|
|
try {
|
2023-12-26 20:50:52 +00:00
|
|
|
const successful = document.execCommand('copy');
|
|
|
|
const msg = successful ? 'successful' : 'unsuccessful';
|
2023-12-19 02:48:51 +00:00
|
|
|
console.log('Fallback: Copying text command was ' + msg);
|
|
|
|
} catch (err) {
|
|
|
|
console.error('Fallback: Oops, unable to copy', err);
|
|
|
|
}
|
|
|
|
|
|
|
|
document.body.removeChild(textArea);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
navigator.clipboard.writeText(text).then(
|
|
|
|
function () {
|
|
|
|
console.log('Async: Copying to clipboard was successful!');
|
|
|
|
},
|
|
|
|
function (err) {
|
|
|
|
console.error('Async: Could not copy text: ', err);
|
|
|
|
}
|
|
|
|
);
|
|
|
|
};
|
2023-12-26 21:10:50 +00:00
|
|
|
|
|
|
|
export const checkVersion = (required, current) => {
|
2023-12-27 06:52:53 +00:00
|
|
|
// Returns true when current version is below required
|
2023-12-27 06:51:52 +00:00
|
|
|
return current === '0.0.0'
|
2023-12-27 06:52:53 +00:00
|
|
|
? false
|
2023-12-27 06:51:52 +00:00
|
|
|
: current.localeCompare(required, undefined, {
|
|
|
|
numeric: true,
|
|
|
|
sensitivity: 'case',
|
|
|
|
caseFirst: 'upper'
|
|
|
|
}) < 0;
|
2023-12-26 21:10:50 +00:00
|
|
|
};
|
2024-01-02 08:55:28 +00:00
|
|
|
|
|
|
|
export const findWordIndices = (text) => {
|
|
|
|
const regex = /\[([^\]]+)\]/g;
|
2024-01-03 22:33:57 +00:00
|
|
|
const matches = [];
|
2024-01-02 08:55:28 +00:00
|
|
|
let match;
|
|
|
|
|
|
|
|
while ((match = regex.exec(text)) !== null) {
|
|
|
|
matches.push({
|
|
|
|
word: match[1],
|
|
|
|
startIndex: match.index,
|
|
|
|
endIndex: regex.lastIndex - 1
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
return matches;
|
|
|
|
};
|
2024-01-07 08:57:10 +00:00
|
|
|
|
|
|
|
export const calculateSHA256 = async (file) => {
|
|
|
|
console.log(file);
|
|
|
|
// Create a FileReader to read the file asynchronously
|
|
|
|
const reader = new FileReader();
|
|
|
|
|
|
|
|
// Define a promise to handle the file reading
|
|
|
|
const readFile = new Promise((resolve, reject) => {
|
|
|
|
reader.onload = () => resolve(reader.result);
|
|
|
|
reader.onerror = reject;
|
|
|
|
});
|
|
|
|
|
|
|
|
// Read the file as an ArrayBuffer
|
|
|
|
reader.readAsArrayBuffer(file);
|
|
|
|
|
|
|
|
try {
|
|
|
|
// Wait for the FileReader to finish reading the file
|
|
|
|
const buffer = await readFile;
|
|
|
|
|
|
|
|
// Convert the ArrayBuffer to a Uint8Array
|
|
|
|
const uint8Array = new Uint8Array(buffer);
|
|
|
|
|
|
|
|
// Calculate the SHA-256 hash using Web Crypto API
|
|
|
|
const hashBuffer = await crypto.subtle.digest('SHA-256', uint8Array);
|
|
|
|
|
|
|
|
// Convert the hash to a hexadecimal string
|
|
|
|
const hashArray = Array.from(new Uint8Array(hashBuffer));
|
|
|
|
const hashHex = hashArray.map((byte) => byte.toString(16).padStart(2, '0')).join('');
|
|
|
|
|
|
|
|
return `sha256:${hashHex}`;
|
|
|
|
} catch (error) {
|
|
|
|
console.error('Error calculating SHA-256 hash:', error);
|
|
|
|
throw error;
|
|
|
|
}
|
|
|
|
};
|