Skip to content
This repository has been archived by the owner on Dec 21, 2023. It is now read-only.

Commit

Permalink
feat: last message on creator tokens
Browse files Browse the repository at this point in the history
  • Loading branch information
alantoa committed Nov 10, 2023
1 parent 0b40a9d commit 011f682
Show file tree
Hide file tree
Showing 4 changed files with 159 additions and 38 deletions.
164 changes: 132 additions & 32 deletions packages/app/components/creator-token/creator-token-users.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,15 @@
import { useMemo } from "react";
import { Platform } from "react-native";

import { BlurView } from "expo-blur";

import { Avatar } from "@showtime-xyz/universal.avatar";
import { useIsDarkMode } from "@showtime-xyz/universal.hooks";
import { GoldHexagon, ShowtimeRounded } from "@showtime-xyz/universal.icon";
import {
ChevronRight,
GoldHexagon,
ShowtimeRounded,
} from "@showtime-xyz/universal.icon";
import { PressableHover } from "@showtime-xyz/universal.pressable-hover";
import { useRouter } from "@showtime-xyz/universal.router";
import { Skeleton } from "@showtime-xyz/universal.skeleton";
Expand All @@ -12,12 +19,21 @@ import { VerificationBadge } from "@showtime-xyz/universal.verification-badge";
import { View, ViewProps } from "@showtime-xyz/universal.view";

import {
CreatorTokenItem,
CreatorTokenUser,
NewCreatorTokenItem,
TopCreatorTokenUser,
} from "app/hooks/creator-token/use-creator-tokens";
import { linkifyDescription } from "app/lib/linkify";
import { useHeaderHeight } from "app/lib/react-navigation/elements";
import { formatAddressShort } from "app/utilities";
import {
cleanUserTextInput,
formatAddressShort,
limitLineBreaks,
removeTags,
} from "app/utilities";

import { generateLoremIpsum } from "../creator-channels/utils";
import { PlatformBuyButton } from "../profile/buy-and-sell-buttons";

export const CreatorTokensTitle = ({ title }: { title: string }) => {
Expand Down Expand Up @@ -135,15 +151,17 @@ export const TopCreatorTokenItem = ({
}) => {
const router = useRouter();
const isDark = useIsDarkMode();

const token = (item as NewCreatorTokenItem)?.creator_token
? ((item as NewCreatorTokenItem).creator_token as CreatorTokenItem)
: (item as CreatorTokenItem);
return (
<PressableHover
tw={["mb-2 py-1.5", tw].join(" ")}
onPress={() => {
router.push(
item.owner_profile?.username
? `/@${item.owner_profile?.username}`
: `/@${item.owner_address}`
token?.owner_profile?.username
? `/@${token?.owner_profile?.username}`
: `/@${token?.owner_address}`
);
}}
{...rest}
Expand All @@ -168,19 +186,19 @@ export const TopCreatorTokenItem = ({
) : null}
</View>
<View tw="ml-1 flex-1 flex-row items-center">
<Avatar url={item?.owner_profile?.img_url} size={34} />
<Avatar url={token?.owner_profile?.img_url} size={34} />
<View tw="ml-2 flex-1 justify-center">
<View tw="flex-row items-center">
<Text
tw="text-sm font-semibold text-gray-900 dark:text-white"
numberOfLines={1}
>
@
{item.owner_profile?.username
? item.owner_profile?.username
: formatAddressShort(item.owner_address)}
{token?.owner_profile?.username
? token?.owner_profile?.username
: formatAddressShort(token?.owner_address)}
</Text>
{Boolean(item.owner_profile?.verified) && (
{Boolean(token?.owner_profile?.verified) && (
<View tw="ml-1">
<VerificationBadge size={14} />
</View>
Expand All @@ -191,7 +209,7 @@ export const TopCreatorTokenItem = ({
tw="text-xs font-semibold text-gray-900 dark:text-white"
numberOfLines={1}
>
{item.nft_count}
{token?.nft_count}
</Text>
<View tw="w-1" />
<ShowtimeRounded
Expand Down Expand Up @@ -221,14 +239,39 @@ export const TopCreatorTokenListItem = ({
}) => {
const isDark = useIsDarkMode();
const router = useRouter();
const token = (item as NewCreatorTokenItem)?.creator_token
? ((item as NewCreatorTokenItem).creator_token as CreatorTokenItem)
: (item as CreatorTokenItem);
const lastMessage = (item as NewCreatorTokenItem)?.last_channel_message;
const loremText = useMemo(
() =>
lastMessage?.body_text_length > 0
? generateLoremIpsum(lastMessage?.body_text_length)
: "",
[lastMessage?.body_text_length]
);
const linkifiedMessage = useMemo(
() =>
lastMessage?.body
? linkifyDescription(
limitLineBreaks(
cleanUserTextInput(removeTags(lastMessage.body)),
10
),
"!text-indigo-600 dark:!text-blue-400"
)
: "",
[lastMessage?.body]
);

return (
<PressableHover
tw={["flex-row py-2.5", tw].join(" ")}
onPress={() => {
router.push(
item.owner_profile?.username
? `/@${item.owner_profile?.username}`
: `/@${item.owner_address}`
token.owner_profile?.username
? `/@${token.owner_profile?.username}`
: `/@${token.owner_address}`
);
}}
{...rest}
Expand All @@ -252,23 +295,23 @@ export const TopCreatorTokenListItem = ({
)
) : null}
</View>
<Avatar url={item?.owner_profile?.img_url} size={34} />
<Avatar url={token?.owner_profile?.img_url} size={34} />
</View>
<View tw="web:flex-1 ml-2 flex-row">
<View tw="w-[168px] justify-center md:w-[320px]">
<View tw="w-[168px] justify-center md:w-[200px]">
<View tw="min-w-[180px] flex-row">
<Text
tw="max-w-[150px] text-sm font-semibold text-gray-900 dark:text-white"
numberOfLines={1}
style={{ lineHeight: 20 }}
>
@
{item.owner_profile?.username
? item.owner_profile?.username
: formatAddressShort(item.owner_address)}
{token.owner_profile?.username
? token.owner_profile?.username
: formatAddressShort(token.owner_address)}
</Text>
<View tw="h-1" />
{Boolean(item.owner_profile?.verified) && (
{Boolean(token.owner_profile?.verified) && (
<View tw="ml-1">
<VerificationBadge size={14} />
</View>
Expand All @@ -281,17 +324,17 @@ export const TopCreatorTokenListItem = ({
tw="text-xs text-gray-500 dark:text-gray-400"
numberOfLines={2}
>
{item.owner_profile?.bio}
{token.owner_profile?.bio}
</Text>
</>
) : null}
</View>
<View tw="ml-4 min-w-[50px] flex-row items-center md:ml-10">
<View tw="ml-4 min-w-[50px] flex-row items-center md:ml-6">
<Text
tw="text-sm font-semibold text-gray-900 dark:text-white"
numberOfLines={1}
>
{item.nft_count}
{token.nft_count}
</Text>
<View tw="w-1" />
<ShowtimeRounded
Expand All @@ -300,13 +343,67 @@ export const TopCreatorTokenListItem = ({
color={isDark ? colors.white : colors.gray[900]}
/>
</View>
<View tw="ml-auto lg:ml-0">
<PlatformBuyButton
style={{ backgroundColor: "#08F6CC", height: 26 }}
username={token.owner_profile?.username}
/>
</View>
</View>
<View tw="ml-auto">
<PlatformBuyButton
style={{ backgroundColor: "#08F6CC", height: 26 }}
username={item.owner_profile?.username}
/>
</View>
{!lastMessage ? null : (
<View tw="ml-auto hidden w-full max-w-[200px] flex-row items-center justify-between lg:flex">
{lastMessage.is_payment_gated ? (
<View tw="select-none overflow-hidden px-2 py-0.5">
{Platform.OS === "web" ? (
// INFO: I had to do it like that because blur-sm would crash for no reason even with web prefix
<View tw="blur-sm">
<Text tw="text-sm text-gray-900 dark:text-gray-100">
{loremText}
</Text>
</View>
) : (
<>
<Text tw="py-1.5 text-sm text-gray-900 dark:text-gray-100">
{loremText}
</Text>
<BlurView
intensity={10}
style={{
left: 0,
height: "200%",
width: "200%",
position: "absolute",
}}
/>
</>
)}
</View>
) : (
<>
{lastMessage.body_text_length > 0 ? (
<Text
tw={"text-sm text-gray-900 dark:text-gray-100"}
style={
Platform.OS === "web"
? {
// @ts-ignore
wordBreak: "break-word",
}
: {}
}
>
{linkifiedMessage}
</Text>
) : null}
</>
)}
<ChevronRight
width={14}
height={14}
color={isDark ? colors.white : colors.gray[900]}
/>
</View>
)}
</PressableHover>
);
};
Expand Down Expand Up @@ -342,13 +439,16 @@ export const TopCreatorTokenListItemSkeleton = ({
<Skeleton width={16} height={16} show radius={8} />
<View tw="w-2.5" />
<Skeleton width={34} height={34} show radius={999} />
<View tw="ml-2 w-[178px] md:w-[354px]">
<View tw="ml-2 w-[178px] md:w-[234px]">
<Skeleton width={140} height={13} show radius={4} />
</View>
<Skeleton width={30} height={14} show radius={4} />
<View tw="ml-auto">
<View tw="ml-auto lg:ml-8">
<Skeleton width={42} height={24} show radius={999} />
</View>
<View tw="hidden lg:ml-4 lg:flex">
<Skeleton width={200} height={14} show radius={999} />
</View>
</View>
</View>
);
Expand Down
22 changes: 18 additions & 4 deletions packages/app/components/creator-token/top-creator-token.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ import { View } from "@showtime-xyz/universal.view";
import { EmptyPlaceholder } from "app/components/empty-placeholder";
import { ErrorBoundary } from "app/components/error-boundary";
import {
CreatorTokenItem,
NewCreatorTokenItem,
TopCreatorTokenUser,
useTopCreatorToken,
} from "app/hooks/creator-token/use-creator-tokens";
Expand Down Expand Up @@ -63,7 +65,7 @@ const Header = () => {
#
</Text>
<Text
tw="w-[186px] text-xs text-gray-600 dark:text-gray-500 md:w-[362px]"
tw="w-[186px] text-xs text-gray-600 dark:text-gray-500 md:w-[228px]"
style={{
fontSize: 11,
}}
Expand All @@ -78,12 +80,26 @@ const Header = () => {
>
COLLECTED
</Text>
<Text
tw="hidden text-xs text-gray-600 dark:text-gray-500 lg:block"
style={{
fontSize: 11,
marginLeft: 72,
}}
>
LAST MESSAGE
</Text>
</View>
</View>
</>
);
};
const keyExtractor = (item: TopCreatorTokenUser) => `${item.id}`;
const keyExtractor = (item: TopCreatorTokenUser) =>
`${
(item as CreatorTokenItem)?.id
? (item as CreatorTokenItem)?.id
: (item as NewCreatorTokenItem)?.creator_token.id
}`;
export const TopCreatorTokens = ({
isSimplified,
disableFetchMore,
Expand All @@ -93,9 +109,7 @@ export const TopCreatorTokens = ({
disableFetchMore?: boolean;
limit?: number;
}) => {
const bottom = usePlatformBottomHeight();
const headerHeight = useHeaderHeight();

const { height: screenHeight, width } = useWindowDimensions();
const {
data: list,
Expand Down
2 changes: 1 addition & 1 deletion packages/app/constants/layout.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ const MAX_HEADER_WIDTH = 1440;
const MOBILE_WEB_TABS_HEIGHT = 50;
const WEB_HEADER_HEIGHT = 0;
const MOBILE_WEB_HEADER_HEIGHT = 48;
const DESKTOP_CONTENT_WIDTH = 580;
const DESKTOP_CONTENT_WIDTH = 630;
const DESKTOP_LEFT_MENU_WIDTH = 263;
const DESKTOP_PROFILE_WIDTH = 896;

Expand Down
9 changes: 8 additions & 1 deletion packages/app/hooks/creator-token/use-creator-tokens.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { useMemo, useCallback } from "react";

import useSWR from "swr";

import { ChannelMessage } from "app/components/creator-channels/types";
import {
fetcher,
useInfiniteListQuerySWR,
Expand All @@ -18,14 +19,20 @@ export type CreatorTokenUser = {
wallet_address_nonens: string;
img_url: string;
};
export type TopCreatorTokenUser = {
export type CreatorTokenItem = {
id: number;
owner_profile?: Profile;
owner_address: string;
name: string;
token_uri: string;
nft_count: number;
};
export type NewCreatorTokenItem = {
creator_token: CreatorTokenItem;
last_channel_message: ChannelMessage;
};
export type TopCreatorTokenUser = NewCreatorTokenItem | CreatorTokenItem;

export type CreatorTokenCollectors = {
profiles: CreatorTokenUser[];
};
Expand Down

0 comments on commit 011f682

Please sign in to comment.