Files
coop/src/commons.ts

189 lines
4.0 KiB
TypeScript

import { ask, message, open } from "@tauri-apps/plugin-dialog";
import { readFile } from "@tauri-apps/plugin-fs";
import { relaunch } from "@tauri-apps/plugin-process";
import { check } from "@tauri-apps/plugin-updater";
import { type ClassValue, clsx } from "clsx";
import dayjs from "dayjs";
import relativeTime from "dayjs/plugin/relativeTime";
import updateLocale from "dayjs/plugin/updateLocale";
import { type NostrEvent, nip19 } from "nostr-tools";
import { twMerge } from "tailwind-merge";
dayjs.extend(relativeTime);
dayjs.extend(updateLocale);
dayjs.updateLocale("en", {
relativeTime: {
past: "%s",
s: "now",
m: "1m",
mm: "%dm",
h: "1h",
hh: "%dh",
d: "1d",
dd: "%dd",
},
});
export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs));
}
export function npub(pubkey: string, len: number) {
if (pubkey.length <= len) return pubkey;
const npub = pubkey.startsWith("npub1") ? pubkey : nip19.npubEncode(pubkey);
const separator = " ... ";
const sepLen = separator.length;
const charsToShow = len - sepLen;
const frontChars = Math.ceil(charsToShow / 2);
const backChars = Math.floor(charsToShow / 2);
return (
npub.substring(0, frontChars) +
separator +
npub.substring(npub.length - backChars)
);
}
export function ago(time: number) {
let formated: string;
const now = dayjs();
const inputTime = dayjs.unix(time);
const diff = now.diff(inputTime, "hour");
if (diff < 24) {
formated = inputTime.from(now, true);
} else {
formated = inputTime.format("MMM DD");
}
return formated;
}
export function time(time: number) {
const input = new Date(time * 1000);
const formattedTime = input.toLocaleTimeString([], {
hour: "2-digit",
minute: "2-digit",
hour12: true,
});
return formattedTime;
}
export function getReceivers(tags: string[][]) {
const p = tags.map((tag) => tag[0] === "p" && tag[1]);
return p;
}
export function groupEventByDate(events: NostrEvent[]) {
const groups = Object.groupBy(events, (event) => {
return dayjs.unix(event.created_at).startOf("day").format("MMM DD, YYYY");
});
return groups;
}
/*
export function isEmojiOnly(str: string) {
const stringToTest = str.replace(/ /g, "");
const emojiRegex =
/^(?:(?:\p{RI}\p{RI}|\p{Emoji}(?:\p{Emoji_Modifier}|\u{FE0F}\u{20E3}?|[\u{E0020}-\u{E007E}]+\u{E007F})?(?:\u{200D}\p{Emoji}(?:\p{Emoji_Modifier}|\u{FE0F}\u{20E3}?|[\u{E0020}-\u{E007E}]+\u{E007F})?)*)|[\u{1f900}-\u{1f9ff}\u{2600}-\u{26ff}\u{2700}-\u{27bf}])+$/u;
return emojiRegex.test(stringToTest) && Number.isNaN(Number(stringToTest));
}
*/
export async function checkForAppUpdates(silent: boolean) {
try {
const update = await check();
if (!update) {
if (silent) return;
await message("You are on the latest version. Stay awesome!", {
title: "No Update Available",
kind: "info",
okLabel: "OK",
});
return;
}
if (update?.available) {
const yes = await ask(
`Update to ${update.version} is available!\n\nRelease notes: ${update.body}`,
{
title: "Update Available",
kind: "info",
okLabel: "Update",
cancelLabel: "Cancel",
},
);
if (yes) {
await update.downloadAndInstall();
await relaunch();
}
return;
}
} catch {
return;
}
}
export async function upload() {
const allowExts = [
"png",
"jpeg",
"jpg",
"gif",
"mp4",
"mp3",
"webm",
"mkv",
"avi",
"mov",
];
const selected = await open({
multiple: false,
filters: [
{
name: "Media",
extensions: allowExts,
},
],
});
// User cancelled action
if (!selected) return null;
try {
const selectedPath = selected.path;
const file = await readFile(selectedPath);
const blob = new Blob([file]);
const data = new FormData();
data.append("fileToUpload", blob);
data.append("submit", "Upload Image");
const res = await fetch("https://nostr.build/api/v2/upload/files", {
method: "POST",
body: data,
});
if (!res.ok) return null;
const json = await res.json();
const content = json.data[0];
return content.url as string;
} catch (e) {
return null;
}
}