Merge pull request #459 from IsaacWise06/issue/367

feat(links): Allow users to choose what happens when they click a link
This commit is contained in:
Daniel 2024-02-08 17:15:41 +03:30 committed by GitHub
commit aef55d65a1
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 134 additions and 30 deletions

View File

@ -14,8 +14,8 @@ import Image from "next/image";
import { previewAvailable } from "@/lib/shared/getArchiveValidity";
import Link from "next/link";
import LinkIcon from "./LinkComponents/LinkIcon";
import LinkGroupedIconURL from "./LinkComponents/LinkGroupedIconURL";
import useOnScreen from "@/hooks/useOnScreen";
import { generateLinkHref } from "@/lib/client/generateLinkHref";
type Props = {
link: LinkIncludingShortenedCollectionAndTags;
@ -26,8 +26,6 @@ type Props = {
export default function LinkGrid({
link,
count,
className,
flipDropdown,
}: Props) {
const { collections } = useCollectionStore();
@ -88,7 +86,7 @@ export default function LinkGrid({
className="border border-solid border-neutral-content bg-base-200 shadow-md hover:shadow-none duration-100 rounded-2xl relative"
>
<Link
href={link.url || ""}
href={generateLinkHref(link)}
target="_blank"
className="rounded-2xl cursor-pointer"
>

View File

@ -18,7 +18,7 @@ type Props = {
className?: string;
};
export default function LinkGrid({ link, count, className }: Props) {
export default function LinkGrid({ link }: Props) {
const { collections } = useCollectionStore();
const { links } = useLinkStore();
@ -101,7 +101,7 @@ export default function LinkGrid({ link, count, className }: Props) {
</div>
<LinkActions
toggleShowInfo={() => {}}
toggleShowInfo={() => { }}
linkInfo={false}
link={link}
collection={collection}

View File

@ -12,6 +12,7 @@ import LinkCollection from "@/components/LinkViews/LinkComponents/LinkCollection
import LinkIcon from "@/components/LinkViews/LinkComponents/LinkIcon";
import Link from "next/link";
import { isPWA } from "@/lib/client/utils";
import { generateLinkHref } from "@/lib/client/generateLinkHref";
type Props = {
link: LinkIncludingShortenedCollectionAndTags;
@ -22,12 +23,9 @@ type Props = {
export default function LinkCardCompact({
link,
count,
className,
flipDropdown,
}: Props) {
const { collections } = useCollectionStore();
const { links } = useLinkStore();
let shortendURL;
@ -58,12 +56,11 @@ export default function LinkCardCompact({
return (
<>
<div
className={`border-neutral-content relative ${
!showInfo && !isPWA() ? "hover:bg-base-300 p-3" : "py-3"
} duration-200 rounded-lg`}
className={`border-neutral-content relative ${!showInfo && !isPWA() ? "hover:bg-base-300 p-3" : "py-3"
} duration-200 rounded-lg`}
>
<Link
href={link.url || ""}
href={generateLinkHref(link)}
target="_blank"
className="flex items-start cursor-pointer"
>
@ -102,8 +99,8 @@ export default function LinkCardCompact({
collection={collection}
position="top-3 right-3"
flipDropdown={flipDropdown}
// toggleShowInfo={() => setShowInfo(!showInfo)}
// linkInfo={showInfo}
// toggleShowInfo={() => setShowInfo(!showInfo)}
// linkInfo={showInfo}
/>
{showInfo ? (
<div>

View File

@ -97,18 +97,18 @@ export default async function updateUserById(
id: { not: userId },
OR: emailEnabled
? [
{
username: data.username.toLowerCase(),
},
{
email: data.email?.toLowerCase(),
},
]
{
username: data.username.toLowerCase(),
},
{
email: data.email?.toLowerCase(),
},
]
: [
{
username: data.username.toLowerCase(),
},
],
{
username: data.username.toLowerCase(),
},
],
},
});
@ -186,6 +186,7 @@ export default async function updateUserById(
archiveAsScreenshot: data.archiveAsScreenshot,
archiveAsPDF: data.archiveAsPDF,
archiveAsWaybackMachine: data.archiveAsWaybackMachine,
linksRouteTo: data.linksRouteTo,
password:
data.newPassword && data.newPassword !== ""
? newHashedPassword

View File

@ -0,0 +1,29 @@
import useAccountStore from "@/store/account";
import { ArchivedFormat, LinkIncludingShortenedCollectionAndTags } from "@/types/global";
import { LinksRouteTo } from "@prisma/client";
import { pdfAvailable, readabilityAvailable, screenshotAvailable } from "../shared/getArchiveValidity";
export const generateLinkHref = (link: LinkIncludingShortenedCollectionAndTags): string => {
const { account } = useAccountStore();
// 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

@ -1,4 +1,6 @@
export function screenshotAvailable(link: any) {
import { LinkIncludingShortenedCollectionAndTags } from "@/types/global";
export function screenshotAvailable(link: LinkIncludingShortenedCollectionAndTags) {
return (
link &&
link.image &&
@ -7,13 +9,13 @@ export function screenshotAvailable(link: any) {
);
}
export function pdfAvailable(link: any) {
export function pdfAvailable(link: LinkIncludingShortenedCollectionAndTags) {
return (
link && link.pdf && link.pdf !== "pending" && link.pdf !== "unavailable"
);
}
export function readabilityAvailable(link: any) {
export function readabilityAvailable(link: LinkIncludingShortenedCollectionAndTags) {
return (
link &&
link.readable &&

View File

@ -7,6 +7,7 @@ import React from "react";
import useLocalSettingsStore from "@/store/localSettings";
import Checkbox from "@/components/Checkbox";
import SubmitButton from "@/components/SubmitButton";
import { LinksRouteTo } from "@prisma/client";
export default function Appearance() {
const { updateSettings } = useLocalSettingsStore();
@ -20,6 +21,9 @@ export default function Appearance() {
const [archiveAsPDF, setArchiveAsPDF] = useState<boolean>(false);
const [archiveAsWaybackMachine, setArchiveAsWaybackMachine] =
useState<boolean>(false);
const [linksRouteTo, setLinksRouteTo] = useState<LinksRouteTo>(
user.linksRouteTo
);
useEffect(() => {
setUser({
@ -27,8 +31,15 @@ export default function Appearance() {
archiveAsScreenshot,
archiveAsPDF,
archiveAsWaybackMachine,
linksRouteTo,
});
}, [account, archiveAsScreenshot, archiveAsPDF, archiveAsWaybackMachine]);
}, [
account,
archiveAsScreenshot,
archiveAsPDF,
archiveAsWaybackMachine,
linksRouteTo,
]);
function objectIsEmpty(obj: object) {
return Object.keys(obj).length === 0;
@ -39,6 +50,7 @@ export default function Appearance() {
setArchiveAsScreenshot(account.archiveAsScreenshot);
setArchiveAsPDF(account.archiveAsPDF);
setArchiveAsWaybackMachine(account.archiveAsWaybackMachine);
setLinksRouteTo(account.linksRouteTo);
}
}, [account]);
@ -134,6 +146,71 @@ export default function Appearance() {
<div className="divider my-3"></div>
<p>Clicking on Links should:</p>
<div className="p-3">
<label
className="label cursor-pointer flex gap-2 justify-start"
tabIndex={0}
role="button"
>
<input
type="radio"
name="link-preference-radio"
className="radio checked:bg-primary"
value="Original"
checked={linksRouteTo === LinksRouteTo.ORIGINAL}
onChange={() => setLinksRouteTo(LinksRouteTo.ORIGINAL)}
/>
<span className="label-text">Open the original content</span>
</label>
<label
className="label cursor-pointer flex gap-2 justify-start"
tabIndex={0}
role="button"
>
<input
type="radio"
name="link-preference-radio"
className="radio checked:bg-primary"
value="PDF"
checked={linksRouteTo === LinksRouteTo.PDF}
onChange={() => setLinksRouteTo(LinksRouteTo.PDF)}
/>
<span className="label-text">Open PDF, if available</span>
</label>
<label
className="label cursor-pointer flex gap-2 justify-start"
tabIndex={0}
role="button"
>
<input
type="radio"
name="link-preference-radio"
className="radio checked:bg-primary"
value="Readable"
checked={linksRouteTo === LinksRouteTo.READABLE}
onChange={() => setLinksRouteTo(LinksRouteTo.READABLE)}
/>
<span className="label-text">Open Readable, if available</span>
</label>
<label
className="label cursor-pointer flex gap-2 justify-start"
tabIndex={0}
role="button"
>
<input
type="radio"
name="link-preference-radio"
className="radio checked:bg-primary"
value="Screenshot"
checked={linksRouteTo === LinksRouteTo.SCREENSHOT}
onChange={() => setLinksRouteTo(LinksRouteTo.SCREENSHOT)}
/>
<span className="label-text">Open Screenshot, if available</span>
</label>
</div>
</div>
<SubmitButton