Skip to content

Commit

Permalink
Merge branch 'main' into MI-771
Browse files Browse the repository at this point in the history
  • Loading branch information
AmarTrebinjac authored Jan 27, 2025
2 parents 56cafdb + f2c0cd4 commit fbf7e45
Show file tree
Hide file tree
Showing 30 changed files with 329 additions and 83 deletions.
9 changes: 9 additions & 0 deletions packages/extension/__tests__/setup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,4 +71,13 @@ Object.defineProperty(global, 'open', {
value: jest.fn(),
});

Object.defineProperty(global, 'TransformStream', {
writable: true,
value: jest.fn().mockImplementation(() => ({
backpressure: jest.fn(),
readable: jest.fn(),
writable: jest.fn(),
})),
});

structuredCloneJsonPolyfill();
1 change: 1 addition & 0 deletions packages/extension/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
"date-fns": "^2.25.0",
"date-fns-tz": "1.2.2",
"dompurify": "^2.5.4",
"fetch-event-stream": "^0.1.5",
"focus-visible": "^5.2.1",
"graphql": "^16.9.0",
"graphql-request": "^3.6.1",
Expand Down
2 changes: 1 addition & 1 deletion packages/extension/src/companion/Companion.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import { useBackgroundRequest } from '@dailydotdev/shared/src/hooks/companion';
import {
getPostByIdKey,
updatePostCache,
} from '@dailydotdev/shared/src/hooks/usePostById';
} from '@dailydotdev/shared/src/lib/query';
import { getCompanionWrapper } from '@dailydotdev/shared/src/lib/extension';
import CompanionMenu from './CompanionMenu';
import CompanionContent from './CompanionContent';
Expand Down
9 changes: 9 additions & 0 deletions packages/shared/__tests__/setup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,15 @@ Object.defineProperty(global, 'open', {
value: jest.fn(),
});

Object.defineProperty(global, 'TransformStream', {
writable: true,
value: jest.fn().mockImplementation(() => ({
backpressure: jest.fn(),
readable: jest.fn(),
writable: jest.fn(),
})),
});

jest.mock('next/router', () => ({
useRouter: jest.fn().mockImplementation(
() =>
Expand Down
1 change: 1 addition & 0 deletions packages/shared/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@
"@paddle/paddle-js": "^1.3.2",
"@tippyjs/react": "^4.2.6",
"check-password-strength": "^2.0.10",
"fetch-event-stream": "^0.1.5",
"graphql-ws": "^5.5.5",
"node-fetch": "^2.6.6",
"react-markdown": "^8.0.7",
Expand Down
7 changes: 2 additions & 5 deletions packages/shared/src/components/PostOptionsMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -46,14 +46,11 @@ import {
useToastNotification,
} from '../hooks';
import type { AllFeedPages } from '../lib/query';
import { generateQueryKey, RequestKey } from '../lib/query';
import { generateQueryKey, getPostByIdKey, RequestKey } from '../lib/query';
import AuthContext from '../contexts/AuthContext';
import { LogEvent, Origin } from '../lib/log';
import { usePostMenuActions } from '../hooks/usePostMenuActions';
import usePostById, {
getPostByIdKey,
invalidatePostCacheById,
} from '../hooks/usePostById';
import usePostById, { invalidatePostCacheById } from '../hooks/usePostById';
import { useLazyModal } from '../hooks/useLazyModal';
import { LazyModal } from './modals/common/types';
import { labels } from '../lib';
Expand Down
3 changes: 3 additions & 0 deletions packages/shared/src/graphql/feed.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,9 @@ export const FEED_POST_FRAGMENT = gql`
}
slug
clickbaitTitleDetected
translation {
title
}
}
trending
feedMeta
Expand Down
6 changes: 6 additions & 0 deletions packages/shared/src/graphql/fragments.ts
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,9 @@ export const FEED_POST_INFO_FRAGMENT = gql`
}
slug
clickbaitTitleDetected
translation {
title
}
}
`;

Expand Down Expand Up @@ -269,6 +272,9 @@ export const SHARED_POST_INFO_FRAGMENT = gql`
slug
domain
clickbaitTitleDetected
translation {
title
}
}
${PRIVILEGED_MEMBERS_FRAGMENT}
${SOURCE_BASE_FRAGMENT}
Expand Down
1 change: 1 addition & 0 deletions packages/shared/src/graphql/posts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,7 @@ export interface Post {
bookmarkList?: BookmarkFolder;
domain?: string;
clickbaitTitleDetected?: boolean;
translation?: { title?: boolean };
}

export type RelatedPost = Pick<
Expand Down
2 changes: 1 addition & 1 deletion packages/shared/src/hooks/bookmark/useFeedBookmarkPost.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import type { UseBookmarkPost } from '../useBookmarkPost';
import { mutateBookmarkFeedPost, useBookmarkPost } from '../useBookmarkPost';
import type { UseBookmarkMutationProps } from './types';
import { bookmarkMutationMatcher } from './types';
import { updatePostCache } from '../usePostById';
import { updatePostCache } from '../../lib/query';

export type UseFeedBookmarkPost = {
feedName: string;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { useMutation, useQueryClient } from '@tanstack/react-query';
import type { MoveBookmarkToFolderProps } from '../../graphql/bookmarks';
import { moveBookmarkToFolder } from '../../graphql/bookmarks';
import type { EmptyResponse } from '../../graphql/emptyResponse';
import { getPostByIdKey } from '../usePostById';
import { getPostByIdKey } from '../../lib/query';
import type { PostData } from '../../graphql/posts';
import { useToastNotification } from '../useToastNotification';

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,8 @@ import type {
} from '../../graphql/bookmarks';
import { setBookmarkReminder } from '../../graphql/bookmarks';
import { useToastNotification } from '../useToastNotification';
import { updatePostCache } from '../usePostById';
import { useActiveFeedContext } from '../../contexts';
import { updateCachedPagePost } from '../../lib/query';
import { updateCachedPagePost, updatePostCache } from '../../lib/query';
import { optimisticPostUpdateInFeed, postLogEvent } from '../../lib/feed';
import type { EmptyResponse } from '../../graphql/emptyResponse';
import { useLogContext } from '../../contexts/LogContext';
Expand Down
2 changes: 1 addition & 1 deletion packages/shared/src/hooks/post/useBlockPostPanel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ export const useBlockPostPanel = (
const client = useQueryClient();
const { user } = useAuthContext();
const { checkHasCompleted, completeAction } = useActions();
const key = generateQueryKey(RequestKey.PostKey, user, `block:${post?.id}`);
const key = generateQueryKey(RequestKey.Post, user, `block:${post?.id}`);
const { data } = useQuery<BlockData>({
queryKey: key,
queryFn: () => client.getQueryData(key),
Expand Down
2 changes: 1 addition & 1 deletion packages/shared/src/hooks/post/useMutateComment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ import {
generateQueryKey,
getAllCommentsQuery,
RequestKey,
updatePostCache,
} from '../../lib/query';
import { useBackgroundRequest } from '../companion';
import { updatePostCache } from '../usePostById';
import type { Edge } from '../../graphql/common';
import { useLogContext } from '../../contexts/LogContext';
import { useRequestProtocol } from '../useRequestProtocol';
Expand Down
2 changes: 1 addition & 1 deletion packages/shared/src/hooks/post/useRelatedPosts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,10 @@ import {
import {
generateQueryKey,
getNextPageParam,
getPostByIdKey,
RequestKey,
StaleTime,
} from '../../lib/query';
import { getPostByIdKey } from '../usePostById';
import { useRequestProtocol } from '../useRequestProtocol';

export type UseRelatedPostsProps = {
Expand Down
5 changes: 2 additions & 3 deletions packages/shared/src/hooks/post/useSmartTitle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,9 @@ import { useQuery, useQueryClient } from '@tanstack/react-query';
import { gqlClient } from '../../graphql/common';
import type { Post } from '../../graphql/posts';
import { POST_FETCH_SMART_TITLE_QUERY } from '../../graphql/posts';
import { getPostByIdKey } from '../usePostById';
import { usePlusSubscription } from '../usePlusSubscription';
import { useAuthContext } from '../../contexts/AuthContext';
import { generateQueryKey, RequestKey } from '../../lib/query';
import { generateQueryKey, getPostByIdKey, RequestKey } from '../../lib/query';
import { disabledRefetch } from '../../lib/func';
import { useActions } from '../useActions';
import { ActionType } from '../../graphql/actions';
Expand Down Expand Up @@ -115,7 +114,7 @@ export const useSmartTitle = (post: Post): UseSmartTitle => {
return fetchedSmartTitle
? smartTitle
: post?.title || post?.sharedPost?.title;
}, [fetchedSmartTitle, smartTitle, post]);
}, [fetchedSmartTitle, smartTitle, post?.title, post?.sharedPost?.title]);

const shieldActive = useMemo(() => {
return (
Expand Down
166 changes: 166 additions & 0 deletions packages/shared/src/hooks/translation/useTranslation.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
import { useCallback, useEffect, useRef } from 'react';
import type { InfiniteData, QueryKey } from '@tanstack/react-query';
import { useQueryClient } from '@tanstack/react-query';
import { events } from 'fetch-event-stream';
import { useAuthContext } from '../../contexts/AuthContext';
import { apiUrl } from '../../lib/config';
import type { FeedData, Post } from '../../graphql/posts';
import {
updateCachedPagePost,
findIndexOfPostInData,
updatePostCache,
} from '../../lib/query';
import { useSettingsContext } from '../../contexts/SettingsContext';

export enum ServerEvents {
Connect = 'connect',
Message = 'message',
Disconnect = 'disconnect',
Error = 'error',
}

type UseTranslation = (props: {
queryKey: QueryKey;
queryType: 'post' | 'feed';
}) => {
fetchTranslations: (id: Post[]) => void;
};

type TranslateEvent = {
id: string;
title: string;
};

const updateTranslation = (post: Post, translation: TranslateEvent): Post => {
const updatedPost = post;
if (post.title) {
updatedPost.title = translation.title;
updatedPost.translation = { title: !!translation.title };
} else {
updatedPost.sharedPost.title = translation.title;
updatedPost.sharedPost.translation = { title: !!translation.title };
}

return updatedPost;
};

export const useTranslation: UseTranslation = ({ queryKey, queryType }) => {
const abort = useRef<AbortController>();
const { user, accessToken, isLoggedIn } = useAuthContext();
const { flags } = useSettingsContext();
const queryClient = useQueryClient();

const { language } = user || {};
const isStreamActive = isLoggedIn && !!language;

const updateFeed = useCallback(
(translatedPost: TranslateEvent) => {
const updatePost = updateCachedPagePost(queryKey, queryClient);
const feedData =
queryClient.getQueryData<InfiniteData<FeedData>>(queryKey);
const { pageIndex, index } = findIndexOfPostInData(
feedData,
translatedPost.id,
true,
);
if (index > -1) {
updatePost(
pageIndex,
index,
updateTranslation(
feedData.pages[pageIndex].page.edges[index].node,
translatedPost,
),
);
}
},
[queryKey, queryClient],
);

const updatePost = useCallback(
(translatedPost: TranslateEvent) => {
updatePostCache(queryClient, translatedPost.id, (post) =>
updateTranslation(post, translatedPost),
);
},
[queryClient],
);

const fetchTranslations = useCallback(
async (posts: Post[]) => {
if (!isStreamActive) {
return;
}
if (posts.length === 0) {
return;
}

const postIds = posts
.filter((node) =>
node?.title
? !node?.translation?.title
: !node?.sharedPost?.translation?.title,
)
.filter((node) =>
flags?.clickbaitShieldEnabled && node?.title
? !node.clickbaitTitleDetected
: !node.sharedPost?.clickbaitTitleDetected,
)
.filter(Boolean)
.map((node) => (node?.title ? node.id : node?.sharedPost.id));

if (postIds.length === 0) {
return;
}

const params = new URLSearchParams();
postIds.forEach((id) => {
params.append('id', id);
});

const response = await fetch(`${apiUrl}/translate/post/title?${params}`, {
signal: abort.current?.signal,
headers: {
Accept: 'text/event-stream',
Authorization: `Bearer ${accessToken?.token}`,
'Content-Language': language as string,
},
});

if (!response.ok) {
return;
}

// eslint-disable-next-line no-restricted-syntax
for await (const message of events(response)) {
if (message.event === ServerEvents.Message) {
const post = JSON.parse(message.data) as TranslateEvent;
if (queryType === 'feed') {
updateFeed(post);
} else {
updatePost(post);
}
}
}
},
[
accessToken?.token,
flags?.clickbaitShieldEnabled,
isStreamActive,
language,
queryType,
updateFeed,
updatePost,
],
);

useEffect(() => {
abort.current = new AbortController();

return () => {
abort.current?.abort();
};
}, []);

return { fetchTranslations };
};
2 changes: 1 addition & 1 deletion packages/shared/src/hooks/useBookmarkPost.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import LogContext from '../contexts/LogContext';
import { useToastNotification } from './useToastNotification';
import { useRequestProtocol } from './useRequestProtocol';
import AuthContext from '../contexts/AuthContext';
import { updatePostCache } from './usePostById';
import { updatePostCache } from '../lib/query';
import { AuthTriggers } from '../lib/auth';
import type { Origin } from '../lib/log';
import { LogEvent } from '../lib/log';
Expand Down
Loading

0 comments on commit fbf7e45

Please sign in to comment.