diff --git a/README.md b/README.md index c3f0bc2e..e8651d46 100644 --- a/README.md +++ b/README.md @@ -1,17 +1,18 @@
@@ -71,10 +72,14 @@ We've forked the old version from the current repository into [this repo](https:
- ⬇️ Import and export your bookmarks.
- 🔐 SSO integration. (Enterprise and Self-hosted users only)
- 📦 Installable Progressive Web App (PWA).
+- 🍏 iOS and MacOS Apps, maintained by [JGeek00](https://github.com/JGeek00).
- 🍎 iOS Shortcut to save links to Linkwarden.
- 🔑 API keys.
- ✅ Bulk actions.
-- ✨ And so many more features!
+- 👥 User administration.
+- 🌐 Support for Other Languages (i18n).
+- 📁 Image and PDF Uploads.
+- ✨ And many more features. (Literally!)
## Like what we're doing? Give us a Star ⭐
@@ -98,7 +103,7 @@ We _usually_ go after the [popular suggestions](https://github.com/linkwarden/li
Make sure to check out our [public roadmap](https://github.com/orgs/linkwarden/projects/1).
-## Docs
+## Documentation
For information on how to get started or to set up your own instance, please visit the [documentation](https://docs.linkwarden.app).
@@ -110,7 +115,7 @@ If you want to contribute, Thanks! Start by checking our [public roadmap](https:
If you found a security vulnerability, please do **not** create a public issue, instead send an email to [security@linkwarden.app](mailto:security@linkwarden.app) stating the vulnerability. Thanks!
-## Support ❤
+## Support <3
Other than using our official [Cloud](https://linkwarden.app/#pricing) offering, any [donations](https://opencollective.com/linkwarden) are highly appreciated as well!
diff --git a/components/CollectionCard.tsx b/components/CollectionCard.tsx
index 208a7d58..abcdfa43 100644
--- a/components/CollectionCard.tsx
+++ b/components/CollectionCard.tsx
@@ -8,12 +8,12 @@ import ProfilePhoto from "./ProfilePhoto";
import usePermissions from "@/hooks/usePermissions";
import useLocalSettingsStore from "@/store/localSettings";
import getPublicUserData from "@/lib/client/getPublicUserData";
-import useAccountStore from "@/store/account";
import EditCollectionModal from "./ModalContent/EditCollectionModal";
import EditCollectionSharingModal from "./ModalContent/EditCollectionSharingModal";
import DeleteCollectionModal from "./ModalContent/DeleteCollectionModal";
import { dropdownTriggerer } from "@/lib/client/utils";
import { useTranslation } from "next-i18next";
+import { useUser } from "@/hooks/store/user";
export default function CollectionCard({
collection,
@@ -22,7 +22,7 @@ export default function CollectionCard({
}) {
const { t } = useTranslation();
const { settings } = useLocalSettingsStore();
- const { account } = useAccountStore();
+ const { data: user = {} } = useUser();
const formattedDate = new Date(collection.createdAt as string).toLocaleString(
"en-US",
@@ -41,18 +41,18 @@ export default function CollectionCard({
useEffect(() => {
const fetchOwner = async () => {
- if (collection && collection.ownerId !== account.id) {
+ if (collection && collection.ownerId !== user.id) {
const owner = await getPublicUserData(collection.ownerId as number);
setCollectionOwner(owner);
- } else if (collection && collection.ownerId === account.id) {
+ } else if (collection && collection.ownerId === user.id) {
setCollectionOwner({
- id: account.id as number,
- name: account.name,
- username: account.username,
- image: account.image,
- archiveAsScreenshot: account.archiveAsScreenshot,
- archiveAsMonolith: account.archiveAsMonolith,
- archiveAsPDF: account.archiveAsPDF,
+ id: user.id as number,
+ name: user.name,
+ username: user.username as string,
+ image: user.image as string,
+ archiveAsScreenshot: user.archiveAsScreenshot as boolean,
+ archiveAsMonolith: user.archiveAsMonolith as boolean,
+ archiveAsPDF: user.archiveAsPDF as boolean,
});
}
};
@@ -76,7 +76,7 @@ export default function CollectionCard({
>
- {t("you_have_no_collections")} diff --git a/components/FilterSearchDropdown.tsx b/components/FilterSearchDropdown.tsx index 68bb55bd..a0adc371 100644 --- a/components/FilterSearchDropdown.tsx +++ b/components/FilterSearchDropdown.tsx @@ -29,7 +29,7 @@ export default function FilterSearchDropdown({ > -
{collection?.name}
- + <> + { + e.stopPropagation(); + }} + className="flex items-center gap-1 max-w-full w-fit hover:opacity-70 duration-100 select-none" + title={collection?.name} + > + +{collection?.name}
+ + > ); } diff --git a/components/LinkViews/LinkList.tsx b/components/LinkViews/LinkComponents/LinkList.tsx similarity index 91% rename from components/LinkViews/LinkList.tsx rename to components/LinkViews/LinkComponents/LinkList.tsx index 0abffc9f..745e96f7 100644 --- a/components/LinkViews/LinkList.tsx +++ b/components/LinkViews/LinkComponents/LinkList.tsx @@ -4,7 +4,6 @@ import { } from "@/types/global"; import { useEffect, useState } from "react"; import useLinkStore from "@/store/links"; -import useCollectionStore from "@/store/collections"; import unescapeString from "@/lib/client/unescapeString"; import LinkActions from "@/components/LinkViews/LinkComponents/LinkActions"; import LinkDate from "@/components/LinkViews/LinkComponents/LinkDate"; @@ -12,11 +11,13 @@ import LinkCollection from "@/components/LinkViews/LinkComponents/LinkCollection import LinkIcon from "@/components/LinkViews/LinkComponents/LinkIcon"; import { isPWA } from "@/lib/client/utils"; import { generateLinkHref } from "@/lib/client/generateLinkHref"; -import useAccountStore from "@/store/account"; import usePermissions from "@/hooks/usePermissions"; import toast from "react-hot-toast"; -import LinkTypeBadge from "./LinkComponents/LinkTypeBadge"; +import LinkTypeBadge from "./LinkTypeBadge"; import { useTranslation } from "next-i18next"; +import { useCollections } from "@/hooks/store/collections"; +import { useUser } from "@/hooks/store/user"; +import { useLinks } from "@/hooks/store/links"; type Props = { link: LinkIncludingShortenedCollectionAndTags; @@ -33,9 +34,12 @@ export default function LinkCardCompact({ }: Props) { const { t } = useTranslation(); - const { collections } = useCollectionStore(); - const { account } = useAccountStore(); - const { links, setSelectedLinks, selectedLinks } = useLinkStore(); + const { data: collections = [] } = useCollections(); + + const { data: user = {} } = useUser(); + const { setSelectedLinks, selectedLinks } = useLinkStore(); + + const { links } = useLinks(); useEffect(() => { if (!editMode) { @@ -119,7 +123,7 @@ export default function LinkCardCompact({{t("shift_key_tip")}
-+
{t("viewer")}
-{t("viewer_desc")}
++ {t("viewer_desc")} +
+
{t("contributor")}
-{t("contributor_desc")}
++ {t("contributor_desc")} +
+
{t("admin")}
-{t("admin_desc")}
++ {t("admin_desc")} +
{t("preserved_formats")}
{screenshotAvailable(link) || - pdfAvailable(link) || - readabilityAvailable(link) || - monolithAvailable(link) ? ( + pdfAvailable(link) || + readabilityAvailable(link) || + monolithAvailable(link) ? ({t("available_formats")}
) : ( "" @@ -159,7 +149,7 @@ export default function PreservedFormatsModal({ onClose, activeLink }: Props) { name={t("webpage")} icon={"bi-filetype-html"} format={ArchivedFormat.monolith} - activeLink={link} + link={link} downloadable={true} /> )} @@ -173,7 +163,7 @@ export default function PreservedFormatsModal({ onClose, activeLink }: Props) { ? ArchivedFormat.png : ArchivedFormat.jpeg } - activeLink={link} + link={link} downloadable={true} /> )} @@ -183,7 +173,7 @@ export default function PreservedFormatsModal({ onClose, activeLink }: Props) { name={t("pdf")} icon={"bi-file-earmark-pdf"} format={ArchivedFormat.pdf} - activeLink={link} + link={link} downloadable={true} /> )} @@ -193,7 +183,7 @@ export default function PreservedFormatsModal({ onClose, activeLink }: Props) { name={t("readable")} icon={"bi-file-earmark-text"} format={ArchivedFormat.readability} - activeLink={link} + link={link} /> )} @@ -224,9 +214,8 @@ export default function PreservedFormatsModal({ onClose, activeLink }: Props) { )}{title}
+{title}
{activeCollection.members.length > 0 && - activeCollection.members.length === 1 + activeCollection.members.length === 1 ? t("by_author_and_other", { + author: collectionOwner.name, + count: activeCollection.members.length, + }) + : activeCollection.members.length > 0 && + activeCollection.members.length !== 1 + ? t("by_author_and_others", { author: collectionOwner.name, count: activeCollection.members.length, }) - : activeCollection.members.length > 0 && - activeCollection.members.length !== 1 - ? t("by_author_and_others", { - author: collectionOwner.name, - count: activeCollection.members.length, - }) : t("by_author", { - author: collectionOwner.name, - })} + author: collectionOwner.name, + })}
{activeCollection?._count?.links === 1 ? t("showing_count_result", { - count: activeCollection?._count?.links, - }) + count: activeCollection?._count?.links, + }) : t("showing_count_results", { - count: activeCollection?._count?.links, - })} + count: activeCollection?._count?.links, + })}
- {links.some((e) => e.collectionId === Number(router.query.id)) ? ( -+ {decodeURIComponent(router.query.email)} +
+ )} +{t("verification_email_sent_desc")}
{t("import_links")}
{t("collection_is_empty")}
)} diff --git a/pages/public/preserved/[id].tsx b/pages/public/preserved/[id].tsx index fdb332ac..2f415ae1 100644 --- a/pages/public/preserved/[id].tsx +++ b/pages/public/preserved/[id].tsx @@ -1,5 +1,4 @@ import React, { useEffect, useState } from "react"; -import useLinkStore from "@/store/links"; import { useRouter } from "next/router"; import { ArchivedFormat, @@ -7,20 +6,20 @@ import { } from "@/types/global"; import ReadableView from "@/components/ReadableView"; import getServerSideProps from "@/lib/client/getServerSideProps"; +import { useGetLink, useLinks } from "@/hooks/store/links"; export default function Index() { - const { links, getLink } = useLinkStore(); + const { links } = useLinks(); + const getLink = useGetLink(); const [link, setLink] = useState{t("nothing_found")}
- ) : links[0] ? ( -{t("nothing_found")}
} +{t("language")}