chore: update shortcut view

This commit is contained in:
Steven 2023-11-12 11:34:09 +08:00
parent 4a25fbb2f6
commit cb3e3bfaef
8 changed files with 68 additions and 121 deletions

View File

@ -28,7 +28,7 @@ const ShortcutView = (props: Props) => {
<div className="w-full flex flex-row justify-start items-center">
<span className={classNames("w-5 h-5 flex justify-center items-center overflow-clip shrink-0")}>
{favicon ? (
<img className="w-full h-auto rounded-full" src={favicon} decoding="async" loading="lazy" />
<img className="w-full h-auto rounded-lg" src={favicon} decoding="async" loading="lazy" />
) : (
<Icon.CircleSlash className="w-full h-auto text-gray-400" />
)}

View File

@ -3,13 +3,15 @@ import { useState } from "react";
import { useTranslation } from "react-i18next";
import { Link } from "react-router-dom";
import useNavigateTo from "@/hooks/useNavigateTo";
import useResponsiveWidth from "@/hooks/useResponsiveWidth";
import { useAppSelector } from "@/stores";
import useCollectionStore from "@/stores/v1/collection";
import { Collection } from "@/types/proto/api/v2/collection_service";
import { Visibility } from "@/types/proto/api/v2/common";
import { showCommonDialog } from "./Alert";
import CreateCollectionDialog, { ShortcutItem } from "./CreateCollectionDialog";
import CreateCollectionDialog from "./CreateCollectionDialog";
import Icon from "./Icon";
import ShortcutView from "./ShortcutView";
import Dropdown from "./common/Dropdown";
interface Props {
@ -19,6 +21,7 @@ interface Props {
const CollectionView = (props: Props) => {
const { collection } = props;
const { t } = useTranslation();
const { sm } = useResponsiveWidth();
const navigateTo = useNavigateTo();
const collectionStore = useCollectionStore();
const { shortcutList } = useAppSelector((state) => state.shortcut);
@ -82,7 +85,9 @@ const CollectionView = (props: Props) => {
</div>
<div className="w-full p-3 flex flex-row justify-start items-start flex-wrap gap-3">
{shortcuts.map((shortcut) => {
return <ShortcutItem key={shortcut.id} shortcut={shortcut} onClick={() => handleShortcutClick(shortcut)} />;
return (
<ShortcutView key={shortcut.id} shortcut={shortcut} alwaysShowLink={!sm} onClick={() => handleShortcutClick(shortcut)} />
);
})}
</div>
</div>

View File

@ -1,12 +1,8 @@
import { Button, Input, Modal, ModalDialog, Radio, RadioGroup } from "@mui/joy";
import classNames from "classnames";
import { isUndefined } from "lodash-es";
import { useEffect, useState } from "react";
import { toast } from "react-hot-toast";
import { useTranslation } from "react-i18next";
import { Link } from "react-router-dom";
import { getFaviconWithGoogleS2 } from "@/helpers/utils";
import useResponsiveWidth from "@/hooks/useResponsiveWidth";
import { useAppSelector } from "@/stores";
import useCollectionStore from "@/stores/v1/collection";
import { Collection } from "@/types/proto/api/v2/collection_service";
@ -14,6 +10,7 @@ import { Visibility } from "@/types/proto/api/v2/common";
import { convertVisibilityFromPb } from "@/utils/visibility";
import useLoading from "../hooks/useLoading";
import Icon from "./Icon";
import ShortcutView from "./ShortcutView";
interface Props {
collectionId?: number;
@ -206,7 +203,7 @@ const CreateCollectionDialog: React.FC<Props> = (props: Props) => {
<div className="w-full py-1 flex flex-row justify-start items-start flex-wrap overflow-hidden gap-2">
{selectedShortcuts.map((shortcut) => {
return (
<ShortcutItem
<ShortcutView
key={shortcut.id}
className="bg-gray-100 shadow dark:bg-zinc-800 dark:border-zinc-700 dark:text-gray-400"
shortcut={shortcut}
@ -218,7 +215,7 @@ const CreateCollectionDialog: React.FC<Props> = (props: Props) => {
})}
{unselectedShortcuts.map((shortcut) => {
return (
<ShortcutItem
<ShortcutView
key={shortcut.id}
className="border-dashed"
shortcut={shortcut}
@ -245,58 +242,4 @@ const CreateCollectionDialog: React.FC<Props> = (props: Props) => {
);
};
interface ShortcutItemProps {
shortcut: Shortcut;
className?: string;
onClick?: () => void;
}
export const ShortcutItem = (props: ShortcutItemProps) => {
const { shortcut, className, onClick } = props;
const { sm } = useResponsiveWidth();
const favicon = getFaviconWithGoogleS2(shortcut.link);
return (
<div
className={classNames(
"group w-auto select-none px-2 py-1 flex flex-row justify-start items-center border rounded-lg hover:bg-gray-100 dark:border-zinc-800 dark:hover:bg-zinc-800 cursor-pointer",
className
)}
onClick={onClick}
>
<span className={classNames("w-5 h-5 flex justify-center items-center overflow-clip shrink-0")}>
{favicon ? (
<img className="w-full h-auto rounded-full" src={favicon} decoding="async" loading="lazy" />
) : (
<Icon.CircleSlash className="w-full h-auto text-gray-400" />
)}
</span>
<div className="ml-1 w-full flex flex-col justify-start items-start truncate">
<div className="w-full flex flex-row justify-start items-center">
<span className={classNames("max-w-full flex flex-row px-1 justify-start items-center rounded-md")}>
<div className="truncate">
<span className="dark:text-gray-400">{shortcut.title}</span>
{shortcut.title ? (
<span className="text-gray-500">(s/{shortcut.name})</span>
) : (
<>
<span className="text-gray-400 dark:text-gray-500">s/</span>
<span className="truncate dark:text-gray-400">{shortcut.name}</span>
</>
)}
</div>
</span>
</div>
</div>
<Link
className={classNames("w-6 h-6 p-1 rounded-lg bg-gray-200 dark:bg-zinc-900 hover:opacity-80", sm && "hidden group-hover:block")}
to={`/s/${shortcut.name}`}
target="_blank"
>
<Icon.ArrowUpRight className="w-4 h-auto text-gray-400 shrink-0" />
</Link>
</div>
);
};
export default CreateCollectionDialog;

View File

@ -37,7 +37,7 @@ const ShortcutCard = (props: Props) => {
<div className="w-[calc(100%-16px)] flex flex-row justify-start items-center mr-1 shrink-0">
<Link to={`/shortcut/${shortcut.id}`} className={classNames("w-8 h-8 flex justify-center items-center overflow-clip shrink-0")}>
{favicon ? (
<img className="w-full h-auto rounded-full" src={favicon} decoding="async" loading="lazy" />
<img className="w-full h-auto rounded-lg" src={favicon} decoding="async" loading="lazy" />
) : (
<Icon.CircleSlash className="w-full h-auto text-gray-400" />
)}

View File

@ -1,69 +1,65 @@
import classNames from "classnames";
import { Link } from "react-router-dom";
import { absolutifyLink, getFaviconWithGoogleS2 } from "../helpers/utils";
import { getFaviconWithGoogleS2 } from "../helpers/utils";
import Icon from "./Icon";
import ShortcutActionsDropdown from "./ShortcutActionsDropdown";
interface Props {
shortcut: Shortcut;
className?: string;
showActions?: boolean;
alwaysShowLink?: boolean;
onClick?: () => void;
}
const ShortcutView = (props: Props) => {
const { shortcut, className } = props;
const shortcutLink = absolutifyLink(`/s/${shortcut.name}`);
const { shortcut, className, showActions, alwaysShowLink, onClick } = props;
const favicon = getFaviconWithGoogleS2(shortcut.link);
return (
<>
<div
className={classNames(
"group w-full px-3 py-2 flex flex-col justify-start items-start border rounded-lg hover:bg-gray-100 hover:shadow dark:border-zinc-800 dark:hover:bg-zinc-800",
className
<div
className={classNames(
"group w-full px-3 py-2 flex flex-row justify-start items-center border rounded-lg hover:bg-gray-100 dark:border-zinc-800 dark:hover:bg-zinc-800",
className
)}
onClick={onClick}
>
<Link to={`/shortcut/${shortcut.id}`} className={classNames("w-5 h-5 flex justify-center items-center overflow-clip shrink-0")}>
{favicon ? (
<img className="w-full h-auto rounded-lg" src={favicon} decoding="async" loading="lazy" />
) : (
<Icon.CircleSlash className="w-full h-auto text-gray-400" />
)}
</Link>
<div className="ml-1 w-full truncate">
{shortcut.title ? (
<>
<span className="dark:text-gray-400">{shortcut.title}</span>
<span className="text-gray-500">(s/{shortcut.name})</span>
</>
) : (
<>
<span className="text-gray-400 dark:text-gray-500">s/</span>
<span className="dark:text-gray-400">{shortcut.name}</span>
</>
)}
>
<div className="w-full flex flex-row justify-between items-center">
<div className="w-[calc(100%-16px)] flex flex-row justify-start items-center mr-1 shrink-0">
<Link to={`/shortcut/${shortcut.id}`} className={classNames("w-5 h-5 flex justify-center items-center overflow-clip shrink-0")}>
{favicon ? (
<img className="w-full h-auto rounded-full" src={favicon} decoding="async" loading="lazy" />
) : (
<Icon.CircleSlash className="w-full h-auto text-gray-400" />
)}
</Link>
<div className="ml-1 w-[calc(100%-20px)] flex flex-col justify-start items-start">
<div className="w-full flex flex-row justify-start items-center">
<a
className={classNames(
"max-w-full flex flex-row px-1 mr-1 justify-start items-center cursor-pointer rounded-md hover:underline"
)}
href={shortcutLink}
target="_blank"
>
<div className="truncate">
<span className="dark:text-gray-400">{shortcut.title}</span>
{shortcut.title ? (
<span className="text-gray-500">(s/{shortcut.name})</span>
) : (
<>
<span className="text-gray-400 dark:text-gray-500">s/</span>
<span className="truncate dark:text-gray-400">{shortcut.name}</span>
</>
)}
</div>
<span className="hidden group-hover:block ml-1 cursor-pointer shrink-0">
<Icon.ExternalLink className="w-4 h-auto text-gray-600" />
</span>
</a>
</div>
</div>
</div>
<div className="flex flex-row justify-end items-center">
<ShortcutActionsDropdown shortcut={shortcut} />
</div>
</div>
</div>
</>
<Link
className={classNames(
"hidden group-hover:block ml-1 w-6 h-6 p-1 shrink-0 rounded-lg bg-gray-200 dark:bg-zinc-900 hover:opacity-80",
alwaysShowLink && "!block"
)}
to={`/s/${shortcut.name}`}
target="_blank"
>
<Icon.ArrowUpRight className="w-4 h-auto text-gray-400 shrink-0" />
</Link>
{showActions && (
<div className="ml-1 flex flex-row justify-end items-center shrink-0">
<ShortcutActionsDropdown shortcut={shortcut} />
</div>
)}
</div>
);
};

View File

@ -21,7 +21,7 @@ const ShortcutsContainer: React.FC<Props> = (props: Props) => {
)}
>
{shortcutList.map((shortcut) => {
return <ShortcutItemView key={shortcut.id} shortcut={shortcut} />;
return <ShortcutItemView key={shortcut.id} shortcut={shortcut} showActions={true} />;
})}
</div>
);

View File

@ -2,8 +2,8 @@ import { Divider } from "@mui/joy";
import classNames from "classnames";
import { useEffect, useState } from "react";
import { Link, useParams } from "react-router-dom";
import { ShortcutItem } from "@/components/CreateCollectionDialog";
import Icon from "@/components/Icon";
import ShortcutView from "@/components/ShortcutView";
import useResponsiveWidth from "@/hooks/useResponsiveWidth";
import useCollectionStore from "@/stores/v1/collection";
import useShortcutStore from "@/stores/v1/shortcut";
@ -66,16 +66,19 @@ const CollectionSpace = () => {
<p className="text-gray-500 text-sm">{collection.description}</p>
<Divider className="!my-2" />
</div>
<div className="w-full flex flex-col justify-start items-start gap-1">
<div className="w-full flex flex-col justify-start items-start gap-2 sm:gap-1 px-px">
{shortcuts.map((shortcut) => {
return (
<ShortcutItem
<ShortcutView
className={classNames(
"w-full py-2",
selectedShortcut?.id === shortcut.id ? "bg-gray-100 dark:bg-zinc-800" : "border-transparent dark:border-transparent"
"w-full py-2 cursor-pointer",
selectedShortcut?.id === shortcut.id
? "bg-gray-100 dark:bg-zinc-800"
: "sm:border-transparent dark:sm:border-transparent"
)}
key={shortcut.name}
shortcut={convertShortcutFromPb(shortcut)}
alwaysShowLink={!sm}
onClick={() => handleShortcutClick(shortcut)}
/>
);

View File

@ -59,7 +59,7 @@ const ShortcutDetail = () => {
<div className="mx-auto max-w-8xl w-full px-3 md:px-12 pt-4 pb-6 flex flex-col justify-start items-start">
<div className="mt-8 w-12 h-12 flex justify-center items-center overflow-clip">
{favicon ? (
<img className="w-full h-auto rounded-full" src={favicon} decoding="async" loading="lazy" />
<img className="w-full h-auto rounded-lg" src={favicon} decoding="async" loading="lazy" />
) : (
<Icon.CircleSlash className="w-full h-auto text-gray-400" />
)}