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 sharing support #264

Merged
merged 16 commits into from
Mar 4, 2024
34 changes: 33 additions & 1 deletion packages/frontend/src/api/hooks/useActivityLogger.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,19 @@ import {
EActivityLogEventTypes,
EActivityLogObjectTypes,
} from "src/api/services/activity-log/types";
import { ECookieChoice, EWalletConnectionMethod } from "src/api/types";
import {
ECookieChoice,
EWalletConnectionMethod,
TSuperfeedItem,
} from "src/api/types";
import { Logger } from "../utils/logging";

interface IActivityLogger {
logCookieChoice: (choice: ECookieChoice) => void;
logViewVisited: (id: number) => void;
logKeywordSelected: (id: number) => void;
logWalletConnection: (method: EWalletConnectionMethod) => void;
logShareSuperfeedItem: (item: TSuperfeedItem) => void;
}

export const useActivityLogger = (): IActivityLogger => {
Expand Down Expand Up @@ -103,10 +108,37 @@ export const useActivityLogger = (): IActivityLogger => {
);
};

const logShareSuperfeedItem = (item: TSuperfeedItem) => {
sendActivityLog({
event_type: EActivityLogEventTypes.ShareSuperfeedItem,
object_type: EActivityLogObjectTypes.ShareSuperfeedItem,
object_id: item.id,
data: {
title: item.title,
text: item.shortDescription ?? item.title,
url: item.url,
},
})
.unwrap()
.then((resp) =>
Logger.debug(
"useActivityLogger::logShareSuperfeedItem: updated share superfeed item activity log",
resp
)
)
.catch((err) =>
Logger.error(
"useActivityLogger::logShareSuperfeedItem: error updating share superfeed item activity log",
err
)
);
};

return {
logViewVisited,
logCookieChoice,
logKeywordSelected,
logWalletConnection,
logShareSuperfeedItem,
};
};
12 changes: 11 additions & 1 deletion packages/frontend/src/api/services/activity-log/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,15 @@ export enum EActivityLogEventTypes {
KeywordSelected = "KEYWORD_SELECTED",
CookieChoiceSet = "COOKIE_CHOICE_SET",
WalletConnection = "WALLET_CONNECT",
ShareSuperfeedItem = "SHARE_ITEM",
}

export enum EActivityLogObjectTypes {
Keyword = 1,
Widget,
View,
WalletConnection,
ShareSuperfeedItem,
}

export type TKeywordActivityLog = {
Expand Down Expand Up @@ -45,12 +47,20 @@ export type TWalletConnectionActivityLog = {
data?: JSONValue;
};

export type TShareSuperfeedItemActivityLog = {
event_type: EActivityLogEventTypes.ShareSuperfeedItem;
object_type: EActivityLogObjectTypes.ShareSuperfeedItem;
object_id: number;
data: JSONValue;
};

export type TRemoteActivityLog =
| TKeywordActivityLog
| TWidgetActivityLog
| TViewActivityLog
| TCookieActivityLog
| TWalletConnectionActivityLog;
| TWalletConnectionActivityLog
| TShareSuperfeedItemActivityLog;

export type TActivityLogRequest = TRemoteActivityLog;
export type TActivityLogResponse = TRemoteActivityLog;
33 changes: 33 additions & 0 deletions packages/frontend/src/api/utils/shareUtils.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { canShare, shareData } from "./shareUtils";

describe("shareUtils", () => {
describe("canShare", () => {
it("should return true if the Web Share API is supported", () => {
expect(canShare()).toBe(true);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

weird that this is true during a test, which is run on node 🤔

});

it("should return false if the Web Share API is not supported", () => {
// @ts-expect-error navigator is read-only, we're just testing
navigator.share = undefined;
expect(canShare()).toBe(false);
});
});

describe("shareData", () => {
it("should share the provided data using the Web Share API", () => {
// eslint-disable-next-line @typescript-eslint/no-floating-promises
expect(shareData({ title: "Test", text: "Test" })).resolves.toBe(
undefined
);
});

it("should not share the data if the Web Share API is not supported", () => {
// @ts-expect-error navigator is read-only, we're just testing
navigator.share = undefined;
// eslint-disable-next-line @typescript-eslint/no-floating-promises
expect(shareData({ title: "Test", text: "Test" })).rejects.toThrow(
"Sharing not supported"
);
});
});
});
20 changes: 20 additions & 0 deletions packages/frontend/src/api/utils/shareUtils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/**
* Checks if the current environment supports the Web Share API.
*
* @returns Returns true if the Web Share API is supported, otherwise false.
*/
export function canShare() {
return navigator.share !== undefined && navigator.canShare !== undefined;
}

/**
* Shares the provided data using the Web Share API if it is supported by the browser.
*
* @param data - The data to be shared.
*/
export function shareData(data: ShareData) {
if (canShare() && navigator.canShare(data)) {
return navigator.share(data);
}
return Promise.reject(new Error("Sharing not supported"));
}
4 changes: 4 additions & 0 deletions packages/frontend/src/mobile-components/Superfeed.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ interface ISuperfeedModule {
feed: TSuperfeedItem[] | undefined;
handlePaginate: (type: "next" | "previous") => void;
toggleShowFeedFilters: () => void;
onShareItem: (item: TSuperfeedItem) => Promise<void>;
selectedPodcast: TSuperfeedItem | null;
setSelectedPodcast: React.Dispatch<
React.SetStateAction<TSuperfeedItem | null>
Expand Down Expand Up @@ -63,6 +64,7 @@ const SuperfeedModule: FC<ISuperfeedModule> = ({
toggleShowFeedFilters,
selectedPodcast,
setSelectedPodcast,
onShareItem,
}) => {
const handleScrollEvent = useCallback(
({ currentTarget }: FormEvent<HTMLElement>) => {
Expand All @@ -85,6 +87,8 @@ const SuperfeedModule: FC<ISuperfeedModule> = ({
item={item}
selectedPodcast={selectedPodcast}
setSelectedPodcast={setSelectedPodcast}
onLike={() => {}}
onShare={() => onShareItem(item)}
/>
))}
</ScrollBar>
Expand Down
9 changes: 5 additions & 4 deletions packages/frontend/src/mobile-components/feed/BlogCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@ import {

export const BlogCard: FC<{
item: TSuperfeedItem;
}> = ({ item }) => {
onLike: () => MaybeAsync<void>;
onShare: () => MaybeAsync<void>;
}> = ({ item, onLike, onShare }) => {
const {
title,
tags,
Expand All @@ -27,7 +29,6 @@ export const BlogCard: FC<{
shortDescription,
date,
} = item;
const onLike = () => {};
const isLiked = false;

return (
Expand Down Expand Up @@ -72,7 +73,7 @@ export const BlogCard: FC<{
<ActionButtons
onLike={onLike}
onCommentClick={onLike}
onShare={onLike}
onShare={onShare}
likes={likes}
comments={comments}
isLiked={isLiked}
Expand Down Expand Up @@ -100,7 +101,7 @@ export const BlogCard: FC<{
<ActionButtons
onLike={onLike}
onCommentClick={onLike}
onShare={onLike}
onShare={onShare}
likes={likes}
comments={comments}
isLiked={isLiked}
Expand Down
11 changes: 7 additions & 4 deletions packages/frontend/src/mobile-components/feed/EventCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,11 @@ const eventDateFormatter = (date: string) => {
);
};

export const EventCard: FC<{ item: TSuperfeedItem }> = ({ item }) => {
export const EventCard: FC<{
item: TSuperfeedItem;
onLike: () => MaybeAsync<void>;
onShare: () => MaybeAsync<void>;
}> = ({ item, onLike, onShare }) => {
const {
title,
tags,
Expand All @@ -56,7 +60,6 @@ export const EventCard: FC<{ item: TSuperfeedItem }> = ({ item }) => {
const location = "location";
const category = "category";

const onLike = () => {};
const isLiked = false;

return (
Expand Down Expand Up @@ -116,7 +119,7 @@ export const EventCard: FC<{ item: TSuperfeedItem }> = ({ item }) => {
<ActionButtons
onLike={onLike}
onCommentClick={onLike}
onShare={onLike}
onShare={onShare}
likes={likes}
comments={comments}
isLiked={isLiked}
Expand Down Expand Up @@ -161,7 +164,7 @@ export const EventCard: FC<{ item: TSuperfeedItem }> = ({ item }) => {
<ActionButtons
onLike={onLike}
onCommentClick={onLike}
onShare={onLike}
onShare={onShare}
likes={likes}
comments={comments}
isLiked={isLiked}
Expand Down
30 changes: 18 additions & 12 deletions packages/frontend/src/mobile-components/feed/FeedCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,46 +15,52 @@ interface IFeedCard {
setSelectedPodcast: React.Dispatch<
React.SetStateAction<TSuperfeedItem | null>
>;
onLike: () => MaybeAsync<void>;
onShare: () => MaybeAsync<void>;
}

export const FeedCard: FC<IFeedCard> = ({
item,
selectedPodcast,
setSelectedPodcast,
onLike,
onShare,
}) => {
switch (item.type) {
case EFeedItemType.NEWS:
return <NewsCard item={item} />;
return <NewsCard item={item} onLike={onLike} onShare={onShare} />;
case EFeedItemType.BLOG:
return <BlogCard item={item} />;
return <BlogCard item={item} onLike={onLike} onShare={onShare} />;
case EFeedItemType.FORUM:
return <BlogCard item={item} />;
return <BlogCard item={item} onLike={onLike} onShare={onShare} />;
case EFeedItemType.PERSON:
return <BlogCard item={item} />;
return <BlogCard item={item} onLike={onLike} onShare={onShare} />;
case EFeedItemType.VIDEO:
return <VideoCard item={item} />;
return <VideoCard item={item} onLike={onLike} onShare={onShare} />;
case EFeedItemType.PODCAST:
return (
<PodcastCard
item={item}
selectedPodcast={selectedPodcast}
setSelectedPodcast={setSelectedPodcast}
onLike={onLike}
onShare={onShare}
/>
);
case EFeedItemType.EVENT:
return <EventCard item={item} />;
return <EventCard item={item} onLike={onLike} onShare={onShare} />;
case EFeedItemType.MEME:
return <ImageCard item={item} />;
return <ImageCard item={item} onLike={onLike} onShare={onShare} />;
case EFeedItemType.IMAGE:
return <ImageCard item={item} />;
return <ImageCard item={item} onLike={onLike} onShare={onShare} />;
case EFeedItemType.REDDIT:
return <SocialCard item={item} />;
return <SocialCard item={item} onLike={onLike} onShare={onShare} />;
case EFeedItemType.DISCORD:
return <SocialCard item={item} />;
return <SocialCard item={item} onLike={onLike} onShare={onShare} />;
case EFeedItemType.MARKET:
return <MarketCard item={item} />;
return <MarketCard item={item} onLike={onLike} onShare={onShare} />;
case EFeedItemType.TVL:
return <MarketCard item={item} />;
return <MarketCard item={item} onLike={onLike} onShare={onShare} />;
default:
return null;
}
Expand Down
6 changes: 3 additions & 3 deletions packages/frontend/src/mobile-components/feed/FeedElements.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@ export const getFeedItemIcon = (type: EFeedItemType, isDown?: boolean) => {
};

export const ActionButtons: FC<{
onLike: () => void;
onCommentClick: () => void;
onShare: () => void;
onLike: () => MaybeAsync<void>;
onCommentClick: () => MaybeAsync<void>;
onShare: () => MaybeAsync<void>;
likes: number;
comments: number;
isLiked: boolean;
Expand Down
11 changes: 7 additions & 4 deletions packages/frontend/src/mobile-components/feed/ImageCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,11 @@ import {
getFeedItemIcon,
} from "./FeedElements";

export const ImageCard: FC<{ item: TSuperfeedItem }> = ({ item }) => {
export const ImageCard: FC<{
item: TSuperfeedItem;
onLike: () => MaybeAsync<void>;
onShare: () => MaybeAsync<void>;
}> = ({ item, onLike, onShare }) => {
const {
title,
tags,
Expand All @@ -26,7 +30,6 @@ export const ImageCard: FC<{ item: TSuperfeedItem }> = ({ item }) => {
shortDescription,
} = item;

const onLike = () => {};
const isLiked = false;

return (
Expand Down Expand Up @@ -80,7 +83,7 @@ export const ImageCard: FC<{ item: TSuperfeedItem }> = ({ item }) => {
<ActionButtons
onLike={onLike}
onCommentClick={onLike}
onShare={onLike}
onShare={onShare}
likes={likes}
comments={comments}
isLiked={isLiked}
Expand Down Expand Up @@ -114,7 +117,7 @@ export const ImageCard: FC<{ item: TSuperfeedItem }> = ({ item }) => {
<ActionButtons
onLike={onLike}
onCommentClick={onLike}
onShare={onLike}
onShare={onShare}
likes={likes}
comments={comments}
isLiked={isLiked}
Expand Down
Loading
Loading