This commit is contained in:
2024-04-21 14:42:52 +02:00
parent 4b69674ede
commit 8a25f53c99
10700 changed files with 55767 additions and 14201 deletions

View File

@ -0,0 +1,47 @@
import { CollectionIncludingMembersAndLinkCount, Member } from "@/types/global";
import getPublicUserData from "./getPublicUserData";
import { toast } from "react-hot-toast";
const addMemberToCollection = async (
ownerUsername: string,
memberUsername: string,
collection: CollectionIncludingMembersAndLinkCount,
setMember: (newMember: Member) => null | undefined
) => {
const checkIfMemberAlreadyExists = collection.members.find((e) => {
const username = (e.user.username || "").toLowerCase();
return username === memberUsername.toLowerCase();
});
if (
// no duplicate members
!checkIfMemberAlreadyExists &&
// member can't be empty
memberUsername.trim() !== "" &&
// member can't be the owner
memberUsername.trim().toLowerCase() !== ownerUsername.toLowerCase()
) {
// Lookup, get data/err, list ...
const user = await getPublicUserData(memberUsername.trim().toLowerCase());
if (user.username) {
setMember({
collectionId: collection.id,
canCreate: false,
canUpdate: false,
canDelete: false,
userId: user.id,
user: {
id: user.id,
name: user.name,
username: user.username,
image: user.image,
},
});
}
} else if (checkIfMemberAlreadyExists) toast.error("User already exists.");
else if (memberUsername.trim().toLowerCase() === ownerUsername.toLowerCase())
toast.error("You are already the collection owner.");
};
export default addMemberToCollection;

View File

@ -0,0 +1,39 @@
import {
AccountSettings,
ArchivedFormat,
LinkIncludingShortenedCollectionAndTags,
} from "@/types/global";
import { LinksRouteTo } from "@prisma/client";
import {
pdfAvailable,
readabilityAvailable,
screenshotAvailable,
} from "../shared/getArchiveValidity";
export const generateLinkHref = (
link: LinkIncludingShortenedCollectionAndTags,
account: AccountSettings
): string => {
// Return the links href based on the account's preference
// If the user's preference is not available, return the original link
switch (account.linksRouteTo) {
case LinksRouteTo.ORIGINAL:
return link.url || "";
case LinksRouteTo.PDF:
if (!pdfAvailable(link)) return link.url || "";
return `/preserved/${link?.id}?format=${ArchivedFormat.pdf}`;
case LinksRouteTo.READABLE:
if (!readabilityAvailable(link)) return link.url || "";
return `/preserved/${link?.id}?format=${ArchivedFormat.readability}`;
case LinksRouteTo.SCREENSHOT:
if (!screenshotAvailable(link)) return link.url || "";
return `/preserved/${link?.id}?format=${
link?.image?.endsWith("png") ? ArchivedFormat.png : ArchivedFormat.jpeg
}`;
default:
return link.url || "";
}
};

View File

@ -0,0 +1,16 @@
export default async function getLatestVersion(setShowAnnouncement: Function) {
const announcementId = localStorage.getItem("announcementId");
const response = await fetch(
`https://blog.linkwarden.app/latest-announcement.json`
);
const data = await response.json();
const latestAnnouncement = data.id;
if (announcementId !== latestAnnouncement) {
setShowAnnouncement(true);
localStorage.setItem("announcementId", latestAnnouncement);
}
}

View File

@ -0,0 +1,19 @@
import { CollectionIncludingMembersAndLinkCount } from "@/types/global";
import { Dispatch, SetStateAction } from "react";
const getPublicCollectionData = async (
collectionId: number,
setData: Dispatch<
SetStateAction<CollectionIncludingMembersAndLinkCount | undefined>
>
) => {
const res = await fetch("/api/v1/public/collections/" + collectionId);
const data = await res.json();
setData(data.response);
return data;
};
export default getPublicCollectionData;

View File

@ -0,0 +1,11 @@
import { toast } from "react-hot-toast";
export default async function getPublicUserData(id: number | string) {
const response = await fetch(`/api/v1/public/users/${id}`);
const data = await response.json();
if (!response.ok) toast.error(data.response);
return data.response;
}

View File

@ -0,0 +1,17 @@
import Resizer from "react-image-file-resizer";
export const resizeImage = (file: File): Promise<Blob> =>
new Promise<Blob>((resolve) => {
Resizer.imageFileResizer(
file,
150, // target width
150, // target height
"JPEG", // output format
100, // quality
0, // rotation
(uri: any) => {
resolve(uri as Blob);
},
"blob" // output type
);
});

View File

@ -0,0 +1,4 @@
export default function unescapeString(input: string) {
var doc = new DOMParser().parseFromString(input, "text/html");
return doc.documentElement.textContent;
}

View File

@ -0,0 +1,20 @@
export function isPWA() {
return (
window.matchMedia("(display-mode: standalone)").matches ||
(window.navigator as any).standalone ||
document.referrer.includes("android-app://")
);
}
export function isIphone() {
return /iPhone/.test(navigator.userAgent) && !(window as any).MSStream;
}
export function dropdownTriggerer(e: any) {
let targetEl = e.currentTarget;
if (targetEl && targetEl.matches(":focus")) {
setTimeout(function () {
targetEl.blur();
}, 0);
}
}