|
@@ -77,7 +77,10 @@ export const maybeWithBearerAuth = (headers, token) => {
|
|
|
return headers;
|
|
return headers;
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
-export const withBasicAuth = (headers, username, password) => ({ ...headers, Authorization: basicAuth(username, password) });
|
|
|
|
|
|
|
+export const withBasicAuth = (headers, username, password) => ({
|
|
|
|
|
+ ...headers,
|
|
|
|
|
+ Authorization: basicAuth(username, password)
|
|
|
|
|
+});
|
|
|
|
|
|
|
|
export const maybeWithAuth = (headers, user) => {
|
|
export const maybeWithAuth = (headers, user) => {
|
|
|
if (user?.password) {
|
|
if (user?.password) {
|
|
@@ -139,7 +142,7 @@ export const getKebabCaseLangStr = (language) => language.replace(/_/g, "-");
|
|
|
export const formatShortDateTime = (timestamp, language) =>
|
|
export const formatShortDateTime = (timestamp, language) =>
|
|
|
new Intl.DateTimeFormat(getKebabCaseLangStr(language), {
|
|
new Intl.DateTimeFormat(getKebabCaseLangStr(language), {
|
|
|
dateStyle: "short",
|
|
dateStyle: "short",
|
|
|
- timeStyle: "short",
|
|
|
|
|
|
|
+ timeStyle: "short"
|
|
|
}).format(new Date(timestamp * 1000));
|
|
}).format(new Date(timestamp * 1000));
|
|
|
|
|
|
|
|
export const formatShortDate = (timestamp, language) =>
|
|
export const formatShortDate = (timestamp, language) =>
|
|
@@ -178,32 +181,32 @@ export const openUrl = (url) => {
|
|
|
export const sounds = {
|
|
export const sounds = {
|
|
|
ding: {
|
|
ding: {
|
|
|
file: ding,
|
|
file: ding,
|
|
|
- label: "Ding",
|
|
|
|
|
|
|
+ label: "Ding"
|
|
|
},
|
|
},
|
|
|
juntos: {
|
|
juntos: {
|
|
|
file: juntos,
|
|
file: juntos,
|
|
|
- label: "Juntos",
|
|
|
|
|
|
|
+ label: "Juntos"
|
|
|
},
|
|
},
|
|
|
pristine: {
|
|
pristine: {
|
|
|
file: pristine,
|
|
file: pristine,
|
|
|
- label: "Pristine",
|
|
|
|
|
|
|
+ label: "Pristine"
|
|
|
},
|
|
},
|
|
|
dadum: {
|
|
dadum: {
|
|
|
file: dadum,
|
|
file: dadum,
|
|
|
- label: "Dadum",
|
|
|
|
|
|
|
+ label: "Dadum"
|
|
|
},
|
|
},
|
|
|
pop: {
|
|
pop: {
|
|
|
file: pop,
|
|
file: pop,
|
|
|
- label: "Pop",
|
|
|
|
|
|
|
+ label: "Pop"
|
|
|
},
|
|
},
|
|
|
"pop-swoosh": {
|
|
"pop-swoosh": {
|
|
|
file: popSwoosh,
|
|
file: popSwoosh,
|
|
|
- label: "Pop swoosh",
|
|
|
|
|
|
|
+ label: "Pop swoosh"
|
|
|
},
|
|
},
|
|
|
beep: {
|
|
beep: {
|
|
|
file: beep,
|
|
file: beep,
|
|
|
- label: "Beep",
|
|
|
|
|
- },
|
|
|
|
|
|
|
+ label: "Beep"
|
|
|
|
|
+ }
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
export const playSound = async (id) => {
|
|
export const playSound = async (id) => {
|
|
@@ -216,7 +219,7 @@ export const playSound = async (id) => {
|
|
|
export async function* fetchLinesIterator(fileURL, headers) {
|
|
export async function* fetchLinesIterator(fileURL, headers) {
|
|
|
const utf8Decoder = new TextDecoder("utf-8");
|
|
const utf8Decoder = new TextDecoder("utf-8");
|
|
|
const response = await fetch(fileURL, {
|
|
const response = await fetch(fileURL, {
|
|
|
- headers,
|
|
|
|
|
|
|
+ headers
|
|
|
});
|
|
});
|
|
|
const reader = response.body.getReader();
|
|
const reader = response.body.getReader();
|
|
|
let { value: chunk, done: readerDone } = await reader.read();
|
|
let { value: chunk, done: readerDone } = await reader.read();
|
|
@@ -225,7 +228,7 @@ export async function* fetchLinesIterator(fileURL, headers) {
|
|
|
const re = /\n|\r|\r\n/gm;
|
|
const re = /\n|\r|\r\n/gm;
|
|
|
let startIndex = 0;
|
|
let startIndex = 0;
|
|
|
|
|
|
|
|
- for (;;) {
|
|
|
|
|
|
|
+ for (; ;) {
|
|
|
const result = re.exec(chunk);
|
|
const result = re.exec(chunk);
|
|
|
if (!result) {
|
|
if (!result) {
|
|
|
if (readerDone) {
|
|
if (readerDone) {
|
|
@@ -270,3 +273,21 @@ export const urlB64ToUint8Array = (base64String) => {
|
|
|
}
|
|
}
|
|
|
return outputArray;
|
|
return outputArray;
|
|
|
};
|
|
};
|
|
|
|
|
+
|
|
|
|
|
+export const copyToClipboard = (text) => {
|
|
|
|
|
+ if (navigator.clipboard && window.isSecureContext) {
|
|
|
|
|
+ return navigator.clipboard.writeText(text);
|
|
|
|
|
+ } else {
|
|
|
|
|
+ const textarea = document.createElement("textarea");
|
|
|
|
|
+ textarea.value = text;
|
|
|
|
|
+ textarea.setAttribute("readonly", ""); // Avoid mobile keyboards from popping up
|
|
|
|
|
+ textarea.style.position = "fixed"; // Avoid scroll jump
|
|
|
|
|
+ textarea.style.left = "-9999px";
|
|
|
|
|
+ document.body.appendChild(textarea);
|
|
|
|
|
+ textarea.focus();
|
|
|
|
|
+ textarea.select();
|
|
|
|
|
+ document.execCommand("copy");
|
|
|
|
|
+ document.body.removeChild(textarea);
|
|
|
|
|
+ return Promise.resolve();
|
|
|
|
|
+ }
|
|
|
|
|
+};
|