mirror of
https://github.com/aykhans/slash-e.git
synced 2025-04-20 14:01:24 +00:00
chore: update shortcut view
This commit is contained in:
parent
4a25fbb2f6
commit
cb3e3bfaef
@ -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" />
|
||||
)}
|
||||
|
@ -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>
|
||||
|
@ -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;
|
||||
|
@ -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" />
|
||||
)}
|
||||
|
@ -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>
|
||||
);
|
||||
};
|
||||
|
||||
|
@ -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>
|
||||
);
|
||||
|
@ -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)}
|
||||
/>
|
||||
);
|
||||
|
@ -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" />
|
||||
)}
|
||||
|
Loading…
x
Reference in New Issue
Block a user