Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add mirror dropdown #3017

Merged
merged 5 commits into from
Jun 7, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion apps/web/src/components/Composer/Actions/Attachment.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -94,8 +94,8 @@ const Attachment: FC = () => {
<MenuTransition show={showMenu}>
<Menu.Items
ref={dropdownRef}
static
className="absolute z-[5] mt-2 rounded-xl border bg-white py-1 shadow-sm focus:outline-none dark:border-gray-700 dark:bg-gray-900"
static
>
<Menu.Item
as="label"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Menu } from '@headlessui/react';
import { SwitchHorizontalIcon } from '@heroicons/react/outline';
import { LensHub } from '@lenster/abis';
import { Errors } from '@lenster/data';
import { LENSHUB_PROXY } from '@lenster/data/constants';
import { Errors, LENSHUB_PROXY } from '@lenster/data';
import type {
CreateDataAvailabilityMirrorRequest,
CreateMirrorRequest,
Expand All @@ -16,36 +16,28 @@ import {
import { useApolloClient } from '@lenster/lens/apollo';
import { publicationKeyFields } from '@lenster/lens/apollo/lib';
import getSignature from '@lenster/lib/getSignature';
import humanize from '@lenster/lib/humanize';
import nFormatter from '@lenster/lib/nFormatter';
import { Spinner, Tooltip } from '@lenster/ui';
import errorToast from '@lib/errorToast';
import { Leafwatch } from '@lib/leafwatch';
import { t } from '@lingui/macro';
import { t, Trans } from '@lingui/macro';
import clsx from 'clsx';
import { motion } from 'framer-motion';
import type { FC } from 'react';
import { useState } from 'react';
import toast from 'react-hot-toast';
import { type FC, useState } from 'react';
import { toast } from 'react-hot-toast';
import { useAppStore } from 'src/store/app';
import { useNonceStore } from 'src/store/nonce';
import { PUBLICATION } from 'src/tracking';
import { useContractWrite, useSignTypedData } from 'wagmi';

interface MirrorProps {
interface DeleteProps {
publication: Publication;
showCount: boolean;
setIsLoading: (isLoading: boolean) => void;
isLoading: boolean;
}

const Mirror: FC<MirrorProps> = ({ publication, showCount }) => {
const Mirror: FC<DeleteProps> = ({ publication, setIsLoading, isLoading }) => {
const isMirror = publication.__typename === 'Mirror';
const userSigNonce = useNonceStore((state) => state.userSigNonce);
const setUserSigNonce = useNonceStore((state) => state.setUserSigNonce);
const currentProfile = useAppStore((state) => state.currentProfile);
const [isLoading, setIsLoading] = useState(false);
const count = isMirror
? publication?.mirrorOf?.stats?.totalAmountOfMirrors
: publication?.stats?.totalAmountOfMirrors;
const [mirrored, setMirrored] = useState(
isMirror
? publication?.mirrorOf?.mirrors?.length > 0
Expand All @@ -62,6 +54,7 @@ const Mirror: FC<MirrorProps> = ({ publication, showCount }) => {
cache.modify({
id: publicationKeyFields(isMirror ? publication?.mirrorOf : publication),
fields: {
mirrors: (mirrors) => [...mirrors, currentProfile?.id],
stats: (stats) => ({
...stats,
totalAmountOfMirrors: stats.totalAmountOfMirrors + 1
Expand Down Expand Up @@ -210,46 +203,24 @@ const Mirror: FC<MirrorProps> = ({ publication, showCount }) => {
}
};

const iconClassName = showCount
? 'w-[17px] sm:w-[20px]'
: 'w-[15px] sm:w-[18px]';

return (
<div
className={clsx(
mirrored ? 'text-green-500' : 'text-brand',
'flex items-center space-x-1'
)}
<Menu.Item
as="div"
className={({ active }) =>
clsx(
{ 'dropdown-active': active },
mirrored ? 'text-green-500' : 'text-brand',
'm-2 block cursor-pointer rounded-lg px-4 py-1.5 text-sm'
)
}
onClick={createMirror}
disabled={isLoading}
>
<motion.button
whileTap={{ scale: 0.9 }}
onClick={createMirror}
disabled={isLoading}
aria-label="Mirror"
>
<div
className={clsx(
mirrored ? 'hover:bg-green-300/20' : 'hover:bg-brand-300/20',
'rounded-full p-1.5'
)}
>
{isLoading ? (
<Spinner variant={mirrored ? 'success' : 'primary'} size="xs" />
) : (
<Tooltip
placement="top"
content={count > 0 ? t`${humanize(count)} Mirrors` : t`Mirror`}
withDelay
>
<SwitchHorizontalIcon className={iconClassName} />
</Tooltip>
)}
</div>
</motion.button>
{count > 0 && !showCount && (
<span className="text-[11px] sm:text-xs">{nFormatter(count)}</span>
)}
</div>
<div className="flex items-center space-x-2">
<SwitchHorizontalIcon className="h-4 w-4" />
<div>{mirrored ? <Trans>Unmirror</Trans> : <Trans>Mirror</Trans>}</div>
</div>
</Menu.Item>
);
};

Expand Down
85 changes: 85 additions & 0 deletions apps/web/src/components/Publication/Actions/Share/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
import MenuTransition from '@components/Shared/MenuTransition';
import { Menu } from '@headlessui/react';
import { SwitchHorizontalIcon } from '@heroicons/react/outline';
import type { Publication } from '@lenster/lens';
import humanize from '@lenster/lib/humanize';
import nFormatter from '@lenster/lib/nFormatter';
import stopEventPropagation from '@lenster/lib/stopEventPropagation';
import { Spinner, Tooltip } from '@lenster/ui';
import { t } from '@lingui/macro';
import clsx from 'clsx';
import type { FC } from 'react';
import { Fragment, useState } from 'react';

import Mirror from './Mirror';

interface PublicationMenuProps {
publication: Publication;
showCount: boolean;
}

const ShareMenu: FC<PublicationMenuProps> = ({ publication, showCount }) => {
const [isLoading, setIsLoading] = useState(false);

const isMirror = publication.__typename === 'Mirror';
const count = isMirror
? publication?.mirrorOf?.stats?.totalAmountOfMirrors
: publication?.stats?.totalAmountOfMirrors;
const mirrored = isMirror
? publication?.mirrorOf?.mirrors?.length > 0
: // @ts-expect-error
publication?.mirrors?.length > 0;
const iconClassName = 'w-[15px] sm:w-[18px]';

return (
<div
className={clsx(
mirrored ? 'text-green-500' : 'text-brand',
'flex items-center space-x-1'
)}
>
<Menu as="div" className="relative">
<Menu.Button as={Fragment}>
<button
className="rounded-full p-1.5 hover:bg-gray-300/20"
onClick={stopEventPropagation}
aria-label="Mirror"
>
{isLoading ? (
<Spinner
variant={mirrored ? 'success' : 'primary'}
size="xs"
className="mr-0.5"
/>
) : (
<Tooltip
placement="top"
content={count > 0 ? t`${humanize(count)} Mirrors` : t`Mirror`}
withDelay
>
<SwitchHorizontalIcon className={iconClassName} />
</Tooltip>
)}
</button>
</Menu.Button>
<MenuTransition>
<Menu.Items
className="absolute z-[5] mt-1 w-max rounded-xl border bg-white shadow-sm focus:outline-none dark:border-gray-700 dark:bg-gray-900"
static
>
<Mirror
publication={publication}
setIsLoading={setIsLoading}
isLoading={isLoading}
/>
</Menu.Items>
</MenuTransition>
</Menu>
{count > 0 && !showCount && (
<span className="text-[11px] sm:text-xs">{nFormatter(count)}</span>
)}
</div>
);
};

export default ShareMenu;
6 changes: 4 additions & 2 deletions apps/web/src/components/Publication/Actions/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ import { useAppStore } from 'src/store/app';
import Collect from './Collect';
import Comment from './Comment';
import Like from './Like';
import Mirror from './Mirror';
import Mod from './Mod';
import ShareMenu from './Share';

interface PublicationActionsProps {
publication: Publication;
Expand All @@ -33,7 +33,9 @@ const PublicationActions: FC<PublicationActionsProps> = ({
aria-hidden="true"
>
<Comment publication={publication} showCount={showCount} />
{canMirror && <Mirror publication={publication} showCount={showCount} />}
{canMirror && (
<ShareMenu publication={publication} showCount={showCount} />
)}
<Like publication={publication} showCount={showCount} />
{collectModuleType !== 'RevertCollectModuleSettings' && (
<Collect
Expand Down
10 changes: 6 additions & 4 deletions apps/web/src/components/Publication/PublicationBody.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import Attachments from '@components/Shared/Attachments';
import Profile from '@components/Shared/Embed/Publication';
import Quote from '@components/Shared/Embed/Quote';
import Markup from '@components/Shared/Markup';
import Oembed from '@components/Shared/Oembed';
import Snapshot from '@components/Shared/Snapshot';
Expand All @@ -18,11 +18,13 @@ import DecryptedPublicationBody from './DecryptedPublicationBody';
interface PublicationBodyProps {
publication: Publication;
showMore?: boolean;
nestedEmbeds?: boolean;
}

const PublicationBody: FC<PublicationBodyProps> = ({
publication,
showMore = false
showMore = false,
nestedEmbeds = true
}) => {
const canShowMore = publication?.metadata?.content?.length > 450 && showMore;
const urls = getURLs(publication?.metadata?.content);
Expand All @@ -49,7 +51,7 @@ const PublicationBody: FC<PublicationBodyProps> = ({

const showAttachments = publication?.metadata?.media?.length > 0;
const showSnapshot = snapshotProposalId;
const showPublicationEmbed = renderPublications.length > 0;
const showPublicationEmbed = renderPublications.length > 0 && nestedEmbeds;
const showOembed =
hasURLs && !showAttachments && !showSnapshot && !showPublicationEmbed;

Expand Down Expand Up @@ -79,7 +81,7 @@ const PublicationBody: FC<PublicationBodyProps> = ({
/>
) : null}
{showPublicationEmbed ? (
<Profile publicationIds={renderPublications} />
<Quote publicationIds={renderPublications} />
) : null}
{showSnapshot ? <Snapshot proposalId={snapshotProposalId} /> : null}
{showOembed ? <Oembed url={urls[0]} /> : null}
Expand Down
35 changes: 35 additions & 0 deletions apps/web/src/components/Publication/QuotedPublication.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import PublicationWrapper from '@components/Shared/PublicationWrapper';
import type { Publication } from '@lenster/lens';
import type { FC } from 'react';

import HiddenPublication from './HiddenPublication';
import PublicationBody from './PublicationBody';
import PublicationHeader from './PublicationHeader';

interface QuotedPublicationProps {
publication: Publication;
}

const QuotedPublication: FC<QuotedPublicationProps> = ({ publication }) => {
return (
<PublicationWrapper
className="cursor-pointer p-5 first:rounded-t-xl last:rounded-b-xl hover:bg-gray-100 dark:hover:bg-gray-900"
publication={publication}
>
<PublicationHeader publication={publication} />
<div className="ml-[53px]">
{publication?.hidden ? (
<HiddenPublication type={publication.__typename} />
) : (
<PublicationBody
publication={publication}
showMore
nestedEmbeds={false}
/>
)}
</div>
</PublicationWrapper>
);
};

export default QuotedPublication;
16 changes: 4 additions & 12 deletions apps/web/src/components/Publication/SinglePublication.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import ActionType from '@components/Home/Timeline/EventType';
import PublicationWrapper from '@components/Shared/PublicationWrapper';
import type { ElectedMirror, FeedItem, Publication } from '@lenster/lens';
import { useRouter } from 'next/router';
import type { FC } from 'react';

import PublicationActions from './Actions';
Expand Down Expand Up @@ -29,7 +29,6 @@ const SinglePublication: FC<SinglePublicationProps> = ({
showThread = true,
showMore = true
}) => {
const { push } = useRouter();
const firstComment = feedItem?.comments && feedItem.comments[0];
const rootPublication = feedItem
? firstComment
Expand All @@ -38,16 +37,9 @@ const SinglePublication: FC<SinglePublicationProps> = ({
: publication;

return (
<article
<PublicationWrapper
className="cursor-pointer p-5 first:rounded-t-xl last:rounded-b-xl hover:bg-gray-100 dark:hover:bg-gray-900"
onClick={() => {
const selection = window.getSelection();
if (!selection || selection.toString().length === 0) {
push(`/posts/${rootPublication?.id}`);
}
}}
data-testid={`publication-${publication.id}`}
aria-hidden="true"
publication={publication}
>
{feedItem ? (
<ActionType feedItem={feedItem} />
Expand Down Expand Up @@ -83,7 +75,7 @@ const SinglePublication: FC<SinglePublicationProps> = ({
</>
)}
</div>
</article>
</PublicationWrapper>
);
};

Expand Down
16 changes: 3 additions & 13 deletions apps/web/src/components/Publication/ThreadBody.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import PublicationWrapper from '@components/Shared/PublicationWrapper';
import type { Publication } from '@lenster/lens';
import { useRouter } from 'next/router';
import type { FC } from 'react';

import PublicationActions from './Actions';
Expand All @@ -12,18 +12,8 @@ interface ThreadBodyProps {
}

const ThreadBody: FC<ThreadBodyProps> = ({ publication }) => {
const { push } = useRouter();

return (
<article
onClick={() => {
const selection = window.getSelection();
if (!selection || selection.toString().length === 0) {
push(`/posts/${publication?.id}`);
}
}}
aria-hidden="true"
>
<PublicationWrapper publication={publication}>
<PublicationHeader publication={publication} />
<div className="flex">
<div className="-my-6 ml-5 mr-8 border-[0.8px] border-gray-300 bg-gray-300 dark:border-gray-700 dark:bg-gray-700" />
Expand All @@ -38,7 +28,7 @@ const ThreadBody: FC<ThreadBodyProps> = ({ publication }) => {
)}
</div>
</div>
</article>
</PublicationWrapper>
);
};

Expand Down
Loading