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

🟣 Release 5.3.0 #6370

Merged
merged 10 commits into from
Jun 4, 2024
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
17 changes: 17 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,23 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [5.3.0] - 2024-06-04

### Added

- Optimistic video updates

### Fixed

- Portfolio table actions
- Show correct potential revenue share on portfolio
- Small UI fixes

### Changed

- Make rewards drawers initially collapsed
- Seperate marketplace into 2 pages

## [5.2.3] - 2024-05-24

### Added
Expand Down
2 changes: 1 addition & 1 deletion packages/atlas/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@joystream/atlas",
"description": "UI for consuming Joystream - a user governed video platform",
"version": "5.2.3",
"version": "5.3.0",
"license": "GPL-3.0",
"scripts": {
"start": "vite",
Expand Down
18 changes: 17 additions & 1 deletion packages/atlas/src/api/client/cache.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { FieldPolicy, FieldReadFunction } from '@apollo/client/cache/inmemory/po
import { offsetLimitPagination, relayStylePagination } from '@apollo/client/utilities'
import { parseISO } from 'date-fns'

import { QueryCommentReactionsConnectionArgs } from '../../../../atlas-meta-server/src/api/__generated__/sdk'
import {
Query,
QueryChannelsConnectionArgs,
Expand Down Expand Up @@ -119,7 +120,19 @@ const getCommentKeyArgs = (
const parentCommentId = args?.where?.parentComment?.id_eq
const videoId = args?.where?.video?.id_eq ?? ctx.variables?.videoId
const orderBy = args?.orderBy || []
return `${parentCommentId}:${videoId}:${orderBy}`
return `parentId-${parentCommentId}-:id-${videoId}-:${orderBy}`
}

const getCommentReactionsKeyArgs = (
args: Partial<QueryCommentReactionsConnectionArgs> | null,
ctx: {
variables?: Record<string, unknown>
}
) => {
const memberId = args?.where?.member?.id_eq
const videoId = args?.where?.video?.id_eq ?? ctx.variables?.videoId
const orderBy = args?.orderBy || []
return `memberId-${memberId}-:videoId-${videoId}-:${orderBy}`
}

const createDateHandler = () => ({
Expand Down Expand Up @@ -216,6 +229,9 @@ const queryCacheFields: CachePolicyFields<keyof Query> = {
return existing?.slice(offset, offset + limit)
},
},
commentReactions: {
...offsetLimitPagination(getCommentReactionsKeyArgs),
},
commentsConnection: relayStylePagination(getCommentKeyArgs),
channelById: (existing, { toReference, args }) => {
return (
Expand Down
16 changes: 15 additions & 1 deletion packages/atlas/src/api/client/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,20 @@ import { GraphQLWsLink } from '@apollo/client/link/subscriptions'
import { getMainDefinition } from '@apollo/client/utilities'
import { createClient } from 'graphql-ws'

import { ORION_GRAPHQL_URL, QUERY_NODE_GRAPHQL_SUBSCRIPTION_URL } from '@/config/env'
import {
FAUCET_URL,
ORION_AUTH_URL,
ORION_GRAPHQL_URL,
QUERY_NODE_GRAPHQL_SUBSCRIPTION_URL,
YPP_FAUCET_URL,
} from '@/config/env'
import { useUserLocationStore } from '@/providers/userLocation'
import { UserEventsLogger } from '@/utils/logs'

import { cache } from './cache'

const followedRequests = [YPP_FAUCET_URL, ORION_GRAPHQL_URL, ORION_AUTH_URL, FAUCET_URL]

const initializePerformanceObserver = () => {
try {
const observer = new PerformanceObserver((list) => {
Expand All @@ -17,6 +25,12 @@ const initializePerformanceObserver = () => {
const queryString = entry.name.split('?')?.[1]
const params = new URLSearchParams(queryString)
const queryType = params.get('queryName')

// Only follow requests to Atlas infra
if (!queryType && !followedRequests.some((allowedUrl) => entry.name.includes(allowedUrl))) {
return
}

UserEventsLogger.logUserEvent('request-response-time', {
requestName: queryType ?? entry.name,
timeToComplete: entry.duration,
Expand Down
12 changes: 9 additions & 3 deletions packages/atlas/src/api/hooks/comments.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ export const useComment = (
}
}

export type UserCommentReactions = Record<string, number[]>
export type UserCommentReactions = Record<string, { reactionId: number; reactionServerId: string }[]>
export const useUserCommentsReactions = (videoId?: string | null, memberId?: string | null) => {
const { data } = useGetUserCommentsReactionsQuery({
variables: {
Expand All @@ -42,9 +42,15 @@ export const useUserCommentsReactions = (videoId?: string | null, memberId?: str

return useMemo(
() => ({
userReactions: data?.commentReactions.reduce<Record<string, number[]>>((acc, item) => {
userReactions: data?.commentReactions.reduce<UserCommentReactions>((acc, item) => {
if (item) {
acc[item.comment.id] = [...(acc[item.comment.id] ? acc[item.comment.id] : []), item.reactionId]
acc[item.comment.id] = [
...(acc[item.comment.id] ? acc[item.comment.id] : []),
{
reactionId: item.reactionId,
reactionServerId: item.id,
},
]
}
return acc
}, {}),
Expand Down
38 changes: 38 additions & 0 deletions packages/atlas/src/api/hooks/useCommentSectionComments.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { QueryHookOptions } from '@apollo/client'

import { UNCONFIRMED } from '@/hooks/useOptimisticActions'
import { createLookup } from '@/utils/data'

import {
GetUserCommentsAndVideoCommentsConnectionQuery,
GetUserCommentsAndVideoCommentsConnectionQueryVariables,
useGetUserCommentsAndVideoCommentsConnectionQuery,
} from '../queries/__generated__/comments.generated'

export const useCommentSectionComments = (
variables?: GetUserCommentsAndVideoCommentsConnectionQueryVariables,
opts?: QueryHookOptions<
GetUserCommentsAndVideoCommentsConnectionQuery,
GetUserCommentsAndVideoCommentsConnectionQueryVariables
>
) => {
const { data, loading, ...rest } = useGetUserCommentsAndVideoCommentsConnectionQuery({ ...opts, variables })
const userComments = data?.userComments
const userCommentLookup = data?.userComments && createLookup(data?.userComments)
const unconfirmedComments = data?.videoCommentsConnection.edges
.map((edge) => edge.node)
.filter((node) => node.id.includes(UNCONFIRMED))
const unconfirmedCommentLookup = unconfirmedComments && createLookup(unconfirmedComments)

const videoComments = data?.videoCommentsConnection?.edges
.map((edge) => edge.node)
.filter((comment) => userCommentLookup && !userCommentLookup[comment.id] && !unconfirmedCommentLookup?.[comment.id])

return {
userComments,
comments: data ? [...(unconfirmedComments || []), ...(userComments || []), ...(videoComments || [])] : undefined,
loading: loading,
pageInfo: data?.videoCommentsConnection?.pageInfo,
...rest,
}
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions packages/atlas/src/api/queries/comments.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ query GetUserCommentsAndVideoCommentsConnection(
# CHANGE: ID is now `String`
query GetUserCommentsReactions($memberId: String!, $videoId: String!) {
commentReactions(where: { member: { id_eq: $memberId }, video: { id_eq: $videoId } }, limit: 1000) {
id
reactionId
comment {
# CHANGE: `commentId` no longer exists, use `comment.id`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,11 @@ export const KebabMenuIconButton = styled(Button)<{ isActive: boolean }>`
}
`

export const CommentWrapper = styled.div<{ shouldShowKebabButton: boolean }>`
export const CommentWrapper = styled.div<{ shouldShowKebabButton: boolean; isUnconfirmed?: boolean }>`
display: grid;
gap: ${sizes(3)};
align-items: start;
opacity: ${(props) => (props.isUnconfirmed ? '0.8' : 'unset')};

/* comment content, kebab button */
grid-template-columns: 1fr auto;
Expand Down
75 changes: 47 additions & 28 deletions packages/atlas/src/components/_comments/Comment/Comment.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import BN from 'bn.js'
import { Dispatch, FC, SetStateAction, memo, useCallback, useRef, useState } from 'react'

import { useComment } from '@/api/hooks/comments'
import { UserCommentReactions, useComment } from '@/api/hooks/comments'
import { CommentStatus } from '@/api/queries/__generated__/baseTypes.generated'
import { CommentFieldsFragment, FullVideoFieldsFragment } from '@/api/queries/__generated__/fragments.generated'
import { DialogModal } from '@/components/_overlays/DialogModal'
Expand All @@ -25,7 +25,7 @@ import { CommentRowProps } from '../CommentRow'
export type CommentProps = {
commentId?: string
video?: FullVideoFieldsFragment | null
userReactions?: number[]
userReactions?: UserCommentReactions[string]
isReplyable?: boolean
setHighlightedCommentId?: Dispatch<SetStateAction<string | null>>
setRepliesOpen?: Dispatch<SetStateAction<boolean>>
Expand Down Expand Up @@ -102,8 +102,10 @@ export const Comment: FC<CommentProps> = memo(
closeModal()
isChannelOwner
? await moderateComment(comment.id, video?.channel.id, comment.author.handle, video?.id)
: await deleteComment(comment.id, video?.title || '', video?.id)
setIsCommentProcessing(false)
: await deleteComment(comment.id, video?.title || '', video?.id, {
onUnconfirmed: () => setIsCommentProcessing(false),
onTxSign: () => setIsCommentProcessing(false),
})
},
},
secondaryButton: {
Expand Down Expand Up @@ -155,27 +157,25 @@ export const Comment: FC<CommentProps> = memo(
}

setEditCommentInputIsProcessing(true)
const success = await updateComment({
await updateComment({
videoId: video.id,
commentBody: editCommentInputText ?? '',
commentId: comment.id,
videoTitle: video.title,
optimisticOpts: {
onTxSign: () => {
setEditCommentInputIsProcessing(false)
setEditCommentInputText('')
setHighlightedCommentId?.(comment?.id ?? null)
setIsEditingComment(false)
},
onUnconfirmed: () => {
setEditCommentInputIsProcessing(false)
setEditCommentInputText('')
setIsEditingComment(false)
},
},
})
setEditCommentInputIsProcessing(false)

if (success) {
setEditCommentInputText('')
setHighlightedCommentId?.(comment?.id ?? null)
setIsEditingComment(false)
}
}
const handleCommentReaction = async (commentId: string, reactionId: CommentReaction) => {
setProcessingReactionsIds((previous) => [...previous, reactionId])
const fee =
reactionFee ||
(await getReactToVideoCommentFee(memberId && comment?.id ? [memberId, comment.id, reactionId] : undefined))
await reactToComment(commentId, video?.id || '', reactionId, comment?.author.handle || '', fee)
setProcessingReactionsIds((previous) => previous.filter((r) => r !== reactionId))
}

const handleOnBoardingPopoverOpen = async (reactionId: number) => {
Expand All @@ -190,19 +190,23 @@ export const Comment: FC<CommentProps> = memo(
}

setReplyCommentInputIsProcessing(true)
const newCommentId = await addComment({
await addComment({
videoId: video.id,
commentBody: replyCommentInputText,
parentCommentId: comment.id,
videoTitle: video.title,
commentAuthorHandle: comment.author.handle,
optimisticOpts: {
onTxSign: (newCommentId) => {
setReplyCommentInputIsProcessing(false)
setReplyCommentInputText('')
setHighlightedCommentId?.(newCommentId || null)
onReplyPosted?.(newCommentId || '')
setRepliesOpen?.(true)
setReplyInputOpen(false)
},
},
})
setReplyCommentInputIsProcessing(false)
setReplyCommentInputText('')
setHighlightedCommentId?.(newCommentId || null)
onReplyPosted?.(newCommentId || '')
setRepliesOpen?.(true)
setReplyInputOpen(false)
}

const handleReplyClick = () => {
Expand Down Expand Up @@ -250,13 +254,28 @@ export const Comment: FC<CommentProps> = memo(
const reactions =
(comment &&
getCommentReactions({
userReactionsIds: userReactions,
userReactionsIds: userReactions?.map((uR) => uR.reactionId),
reactionsCount: comment.reactionsCountByReactionId || [],
processingReactionsIds,
deleted: commentType === 'deleted',
})) ||
undefined

const handleCommentReaction = async (commentId: string, reactionId: CommentReaction) => {
setProcessingReactionsIds((previous) => [...previous, reactionId])
const fee =
reactionFee ||
(await getReactToVideoCommentFee(memberId && comment?.id ? [memberId, comment.id, reactionId] : undefined))
await reactToComment(commentId, video?.id || '', reactionId, comment?.author.handle || '', fee, {
prevReactionServerId:
userReactions?.find((reaction) => reaction.reactionId === reactionId)?.reactionServerId ?? '',
videoId: video?.id ?? '',
onUnconfirmedComment: () => setProcessingReactionsIds((previous) => previous.filter((r) => r !== reactionId)),
onTxSign: () => setProcessingReactionsIds((previous) => previous.filter((r) => r !== reactionId)),
})
setProcessingReactionsIds((previous) => previous.filter((r) => r !== reactionId))
}

if (isEditingComment) {
return (
<CommentInput
Expand Down
Loading
Loading