@linktr.ee/messaging-react 2.0.0 → 2.0.1-rc-1778656305
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/Card-CAC3fPjy.js +107 -0
- package/dist/Card-CAC3fPjy.js.map +1 -0
- package/dist/Card-DLUBUg_w.js +132 -0
- package/dist/Card-DLUBUg_w.js.map +1 -0
- package/dist/Card-_StSlnYh.js +163 -0
- package/dist/Card-_StSlnYh.js.map +1 -0
- package/dist/LockedThumbnail-p5RsFOug.js +220 -0
- package/dist/LockedThumbnail-p5RsFOug.js.map +1 -0
- package/dist/assets/index.css +1 -1
- package/dist/{index-Brz9orsI.js → index-B1h46F9x.js} +811 -772
- package/dist/index-B1h46F9x.js.map +1 -0
- package/dist/index.d.ts +87 -28
- package/dist/index.js +3 -3
- package/package.json +1 -1
- package/src/components/ChannelView.test.tsx +11 -0
- package/src/components/ChannelView.tsx +35 -32
- package/src/components/CustomMessage/index.tsx +2 -3
- package/src/components/CustomTypingIndicator/CustomTypingIndicator.stories.tsx +57 -17
- package/src/components/CustomTypingIndicator/CustomTypingIndicator.test.tsx +187 -0
- package/src/components/CustomTypingIndicator/DmAgentContext.ts +3 -0
- package/src/components/CustomTypingIndicator/index.tsx +101 -37
- package/src/components/LockedAttachment/LockedAttachment.stories.tsx +230 -89
- package/src/components/LockedAttachment/components/Composer/Card.tsx +221 -0
- package/src/components/LockedAttachment/components/Composer/index.ts +2 -0
- package/src/components/LockedAttachment/components/Received/Card.tsx +191 -0
- package/src/components/LockedAttachment/components/Received/CardActions.tsx +91 -0
- package/src/components/LockedAttachment/components/Received/index.ts +2 -0
- package/src/components/LockedAttachment/components/Sent/Card.tsx +177 -0
- package/src/components/LockedAttachment/components/Sent/index.ts +2 -0
- package/src/components/LockedAttachment/components/_shared/CardBody.tsx +94 -0
- package/src/components/LockedAttachment/components/_shared/GalleryThumbnail.tsx +178 -0
- package/src/components/LockedAttachment/components/_shared/LockBadge.tsx +39 -0
- package/src/components/LockedAttachment/components/_shared/LockedCardShell.tsx +36 -0
- package/src/components/LockedAttachment/components/_shared/LockedThumbnail.tsx +128 -0
- package/src/components/LockedAttachment/index.tsx +43 -12
- package/src/components/LockedAttachment/types.ts +17 -0
- package/src/components/MediaMessage/index.tsx +2 -2
- package/src/index.ts +6 -1
- package/src/styles.css +7 -0
- package/dist/Card-BHknCeHw.js +0 -138
- package/dist/Card-BHknCeHw.js.map +0 -1
- package/dist/Card-DT7_ms2p.js +0 -127
- package/dist/Card-DT7_ms2p.js.map +0 -1
- package/dist/index-Brz9orsI.js.map +0 -1
- package/src/components/LockedAttachment/components/Creator/Card.tsx +0 -210
- package/src/components/LockedAttachment/components/Creator/index.tsx +0 -2
- package/src/components/LockedAttachment/components/Visitor/Card.tsx +0 -155
- package/src/components/LockedAttachment/components/Visitor/CardActions.tsx +0 -62
- package/src/components/LockedAttachment/components/Visitor/LockBadge.tsx +0 -12
- package/src/components/LockedAttachment/components/Visitor/index.ts +0 -2
|
@@ -1,6 +1,8 @@
|
|
|
1
|
-
import React from 'react'
|
|
2
|
-
import type { Event } from 'stream-chat'
|
|
1
|
+
import React, { useContext } from 'react'
|
|
2
|
+
import type { Event, UserResponse } from 'stream-chat'
|
|
3
3
|
import {
|
|
4
|
+
AIStates,
|
|
5
|
+
useAIState,
|
|
4
6
|
useChannelStateContext,
|
|
5
7
|
useChatContext,
|
|
6
8
|
useTypingContext,
|
|
@@ -8,6 +10,8 @@ import {
|
|
|
8
10
|
|
|
9
11
|
import { Avatar } from '../Avatar'
|
|
10
12
|
|
|
13
|
+
import { DmAgentEnabledContext } from './DmAgentContext'
|
|
14
|
+
|
|
11
15
|
interface CustomTypingIndicatorProps {
|
|
12
16
|
threadList?: boolean
|
|
13
17
|
}
|
|
@@ -25,10 +29,38 @@ const Circle = ({ cx, index }: { cx: string; index: number }) => (
|
|
|
25
29
|
</circle>
|
|
26
30
|
)
|
|
27
31
|
|
|
32
|
+
const AI_ACTIVE_STATES = new Set<string>([
|
|
33
|
+
AIStates.Thinking,
|
|
34
|
+
AIStates.Generating,
|
|
35
|
+
AIStates.ExternalSources,
|
|
36
|
+
])
|
|
37
|
+
|
|
28
38
|
const CustomTypingIndicator = ({ threadList }: CustomTypingIndicatorProps) => {
|
|
29
39
|
const { channel, channelConfig, thread } = useChannelStateContext()
|
|
30
40
|
const { client } = useChatContext()
|
|
31
41
|
const { typing = {} } = useTypingContext()
|
|
42
|
+
const { aiState } = useAIState(channel)
|
|
43
|
+
const dmAgentEnabled = useContext(DmAgentEnabledContext)
|
|
44
|
+
|
|
45
|
+
// Show the AI indicator whenever the consumer agent is producing a reply.
|
|
46
|
+
// This event stream is independent of `typing.start`/`typing.stop`, so it is
|
|
47
|
+
// intentionally NOT gated by `channelConfig.typing_events`. Gate strictly on
|
|
48
|
+
// `dmAgentEnabled` so stale or off-surface ai_indicator events never surface
|
|
49
|
+
// the bubble on channels where the agent is not active.
|
|
50
|
+
const isAiActive =
|
|
51
|
+
!threadList && dmAgentEnabled && AI_ACTIVE_STATES.has(aiState)
|
|
52
|
+
|
|
53
|
+
if (isAiActive) {
|
|
54
|
+
const agentUser = findOtherChannelUser(channel, client.user?.id)
|
|
55
|
+
return (
|
|
56
|
+
<TypingBubble
|
|
57
|
+
avatarId={agentUser?.id ?? 'ai-agent'}
|
|
58
|
+
avatarName={agentUser?.name ?? agentUser?.id ?? 'Agent'}
|
|
59
|
+
avatarImage={agentUser?.image}
|
|
60
|
+
testId="typing-indicator-ai"
|
|
61
|
+
/>
|
|
62
|
+
)
|
|
63
|
+
}
|
|
32
64
|
|
|
33
65
|
if (channelConfig?.typing_events === false) {
|
|
34
66
|
return null
|
|
@@ -59,43 +91,75 @@ const CustomTypingIndicator = ({ threadList }: CustomTypingIndicatorProps) => {
|
|
|
59
91
|
? channel.state.members[typingUser.id].user
|
|
60
92
|
: undefined
|
|
61
93
|
|
|
62
|
-
const avatarId = typingUser?.id ?? memberUser?.id ?? 'typing-user'
|
|
63
|
-
const avatarName =
|
|
64
|
-
typingUser?.name ?? memberUser?.name ?? typingUser?.id ?? 'Typing user'
|
|
65
|
-
const avatarImage = typingUser?.image ?? memberUser?.image
|
|
66
|
-
|
|
67
94
|
return (
|
|
68
|
-
<
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
name={avatarName}
|
|
77
|
-
image={avatarImage}
|
|
78
|
-
size={24}
|
|
79
|
-
shape="circle"
|
|
80
|
-
/>
|
|
81
|
-
</div>
|
|
82
|
-
|
|
83
|
-
<div className="px-4 py-3 rounded-lg bg-[#E9EAED] h-12 flex flex-col justify-end">
|
|
84
|
-
<svg
|
|
85
|
-
aria-hidden="true"
|
|
86
|
-
className="block overflow-visible mb-[0.2rem]"
|
|
87
|
-
viewBox="0 0 32 8"
|
|
88
|
-
width="32"
|
|
89
|
-
height="8"
|
|
90
|
-
overflow="visible"
|
|
91
|
-
>
|
|
92
|
-
<Circle cx="4" index={0} />
|
|
93
|
-
<Circle cx="16" index={1} />
|
|
94
|
-
<Circle cx="28" index={2} />
|
|
95
|
-
</svg>
|
|
96
|
-
</div>
|
|
97
|
-
</div>
|
|
95
|
+
<TypingBubble
|
|
96
|
+
avatarId={typingUser?.id ?? memberUser?.id ?? 'typing-user'}
|
|
97
|
+
avatarName={
|
|
98
|
+
typingUser?.name ?? memberUser?.name ?? typingUser?.id ?? 'Typing user'
|
|
99
|
+
}
|
|
100
|
+
avatarImage={typingUser?.image ?? memberUser?.image}
|
|
101
|
+
testId="typing-indicator"
|
|
102
|
+
/>
|
|
98
103
|
)
|
|
99
104
|
}
|
|
100
105
|
|
|
106
|
+
const TypingBubble = ({
|
|
107
|
+
avatarId,
|
|
108
|
+
avatarName,
|
|
109
|
+
avatarImage,
|
|
110
|
+
testId,
|
|
111
|
+
}: {
|
|
112
|
+
avatarId: string
|
|
113
|
+
avatarName: string
|
|
114
|
+
avatarImage?: string | null
|
|
115
|
+
testId: string
|
|
116
|
+
}) => (
|
|
117
|
+
<div
|
|
118
|
+
className="str-chat__typing-indicator !items-end !bg-transparent"
|
|
119
|
+
data-testid={testId}
|
|
120
|
+
style={{ insetInlineStart: 0, insetInlineEnd: 'auto' }}
|
|
121
|
+
>
|
|
122
|
+
<div className="shrink-0" aria-hidden="true">
|
|
123
|
+
<Avatar
|
|
124
|
+
id={avatarId}
|
|
125
|
+
name={avatarName}
|
|
126
|
+
image={avatarImage ?? undefined}
|
|
127
|
+
size={24}
|
|
128
|
+
shape="circle"
|
|
129
|
+
/>
|
|
130
|
+
</div>
|
|
131
|
+
|
|
132
|
+
<div className="px-4 py-3 rounded-lg bg-[#E9EAED] h-12 flex flex-col justify-end">
|
|
133
|
+
<svg
|
|
134
|
+
aria-hidden="true"
|
|
135
|
+
className="block overflow-visible mb-[0.2rem]"
|
|
136
|
+
viewBox="0 0 32 8"
|
|
137
|
+
width="32"
|
|
138
|
+
height="8"
|
|
139
|
+
overflow="visible"
|
|
140
|
+
>
|
|
141
|
+
<Circle cx="4" index={0} />
|
|
142
|
+
<Circle cx="16" index={1} />
|
|
143
|
+
<Circle cx="28" index={2} />
|
|
144
|
+
</svg>
|
|
145
|
+
</div>
|
|
146
|
+
</div>
|
|
147
|
+
)
|
|
148
|
+
|
|
149
|
+
type ChannelLike = ReturnType<typeof useChannelStateContext>['channel']
|
|
150
|
+
|
|
151
|
+
function findOtherChannelUser(
|
|
152
|
+
channel: ChannelLike,
|
|
153
|
+
selfId: string | undefined
|
|
154
|
+
): UserResponse | undefined {
|
|
155
|
+
const members = channel?.state?.members ?? {}
|
|
156
|
+
for (const member of Object.values(members)) {
|
|
157
|
+
const memberUser = member?.user
|
|
158
|
+
if (memberUser && memberUser.id !== selfId) {
|
|
159
|
+
return memberUser
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
return undefined
|
|
163
|
+
}
|
|
164
|
+
|
|
101
165
|
export default CustomTypingIndicator
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import type { Meta, StoryFn } from '@storybook/react'
|
|
2
2
|
import React, { useState } from 'react'
|
|
3
3
|
|
|
4
|
+
import type { LockedAttachmentGalleryItem } from './types'
|
|
5
|
+
|
|
4
6
|
import LockedAttachment from '.'
|
|
5
7
|
|
|
6
8
|
const VIDEO_THUMBNAIL_BLURRED = '/video-thumbnail-blurred.jpg'
|
|
@@ -73,6 +75,37 @@ const VARIANTS = [
|
|
|
73
75
|
},
|
|
74
76
|
]
|
|
75
77
|
|
|
78
|
+
/**
|
|
79
|
+
* A mixed-media collection (a video + 3 photos) used by the Gallery stories
|
|
80
|
+
* below. Each `LockedAttachment.*` card accepts a `gallery` prop and renders
|
|
81
|
+
* a carousel of these items when 2+ items are provided.
|
|
82
|
+
*/
|
|
83
|
+
const GALLERY_ITEMS: LockedAttachmentGalleryItem[] = [
|
|
84
|
+
{
|
|
85
|
+
mimeType: 'video/mp4',
|
|
86
|
+
thumbnailUrl: VIDEO_THUMBNAIL_BLURRED,
|
|
87
|
+
sourceUrl: VIDEO_SOURCE,
|
|
88
|
+
},
|
|
89
|
+
{
|
|
90
|
+
mimeType: 'image/jpeg',
|
|
91
|
+
thumbnailUrl: IMAGE_THUMBNAIL_BLURRED,
|
|
92
|
+
sourceUrl: IMAGE_SOURCE,
|
|
93
|
+
},
|
|
94
|
+
{
|
|
95
|
+
mimeType: 'image/jpeg',
|
|
96
|
+
thumbnailUrl: DOCUMENT_THUMBNAIL_BLURRED,
|
|
97
|
+
sourceUrl: DOCUMENT_SOURCE,
|
|
98
|
+
},
|
|
99
|
+
{
|
|
100
|
+
mimeType: 'image/jpeg',
|
|
101
|
+
thumbnailUrl: AUDIO_THUMBNAIL_BLURRED,
|
|
102
|
+
sourceUrl: AUDIO_SOURCE,
|
|
103
|
+
},
|
|
104
|
+
]
|
|
105
|
+
|
|
106
|
+
const GALLERY_DETAIL = '1 video, 3 photos'
|
|
107
|
+
const GALLERY_TITLE = 'Workout Guide'
|
|
108
|
+
|
|
76
109
|
const Table = ({ children }: { children: React.ReactNode }) => (
|
|
77
110
|
<div className="min-h-screen w-full p-12 bg-[#F9F7F4]">
|
|
78
111
|
<table className="border-separate border-spacing-4">{children}</table>
|
|
@@ -99,91 +132,7 @@ const TableHead = ({
|
|
|
99
132
|
</thead>
|
|
100
133
|
)
|
|
101
134
|
|
|
102
|
-
export const
|
|
103
|
-
const [isPaid, setPaid] = useState<string | undefined>()
|
|
104
|
-
const [isUnlocking, setUnlocking] = useState<string | undefined>()
|
|
105
|
-
|
|
106
|
-
return (
|
|
107
|
-
<Table>
|
|
108
|
-
<TableHead variants={VARIANTS} />
|
|
109
|
-
<tbody>
|
|
110
|
-
<tr>
|
|
111
|
-
<td className="text-xs text-right font-medium text-black/40 pr-4 align-top pt-2">
|
|
112
|
-
Locked
|
|
113
|
-
</td>
|
|
114
|
-
{VARIANTS.map(
|
|
115
|
-
({
|
|
116
|
-
title,
|
|
117
|
-
mimeType,
|
|
118
|
-
detail,
|
|
119
|
-
thumbnailUrl,
|
|
120
|
-
thumbnailUnlockedUrl,
|
|
121
|
-
sourceUrl,
|
|
122
|
-
}) => (
|
|
123
|
-
<td key={mimeType} className="align-top">
|
|
124
|
-
<LockedAttachment.Visitor
|
|
125
|
-
title={title}
|
|
126
|
-
thumbnailUrl={thumbnailUrl}
|
|
127
|
-
mimeType={mimeType}
|
|
128
|
-
detail={detail}
|
|
129
|
-
paymentStatus={isPaid === mimeType ? 'paid' : undefined}
|
|
130
|
-
amountText="AU$9.99"
|
|
131
|
-
isUnlocking={isUnlocking === mimeType}
|
|
132
|
-
onUnlockClick={() => {
|
|
133
|
-
setUnlocking(mimeType)
|
|
134
|
-
setTimeout(() => {
|
|
135
|
-
setUnlocking(undefined)
|
|
136
|
-
setPaid(mimeType)
|
|
137
|
-
}, 1500)
|
|
138
|
-
}}
|
|
139
|
-
onDownloadClick={() => alert('Download clicked')}
|
|
140
|
-
onFetchSource={async () => ({
|
|
141
|
-
sourceUrl: sourceUrl,
|
|
142
|
-
thumbnailUrl: thumbnailUnlockedUrl,
|
|
143
|
-
})}
|
|
144
|
-
/>
|
|
145
|
-
</td>
|
|
146
|
-
)
|
|
147
|
-
)}
|
|
148
|
-
</tr>
|
|
149
|
-
<tr>
|
|
150
|
-
<td className="text-xs text-right font-medium text-black/40 pr-4 align-top pt-2">
|
|
151
|
-
Unlocked
|
|
152
|
-
</td>
|
|
153
|
-
{VARIANTS.map(
|
|
154
|
-
({
|
|
155
|
-
title,
|
|
156
|
-
mimeType,
|
|
157
|
-
detail,
|
|
158
|
-
thumbnailUrl,
|
|
159
|
-
thumbnailUnlockedUrl,
|
|
160
|
-
sourceUrl,
|
|
161
|
-
}) => (
|
|
162
|
-
<td key={mimeType} className="align-top">
|
|
163
|
-
<LockedAttachment.Visitor
|
|
164
|
-
title={title}
|
|
165
|
-
thumbnailUrl={thumbnailUrl}
|
|
166
|
-
mimeType={mimeType}
|
|
167
|
-
detail={detail}
|
|
168
|
-
amountText="AU$9.99"
|
|
169
|
-
paymentStatus="paid"
|
|
170
|
-
onUnlockClick={() => alert('Unlock clicked')}
|
|
171
|
-
onDownloadClick={() => alert('Download clicked')}
|
|
172
|
-
onFetchSource={async () => ({
|
|
173
|
-
sourceUrl: sourceUrl,
|
|
174
|
-
thumbnailUrl: thumbnailUnlockedUrl,
|
|
175
|
-
})}
|
|
176
|
-
/>
|
|
177
|
-
</td>
|
|
178
|
-
)
|
|
179
|
-
)}
|
|
180
|
-
</tr>
|
|
181
|
-
</tbody>
|
|
182
|
-
</Table>
|
|
183
|
-
)
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
export const Sent: StoryFn = () => (
|
|
135
|
+
export const Composer: StoryFn = () => (
|
|
187
136
|
<Table>
|
|
188
137
|
<TableHead variants={VARIANTS} />
|
|
189
138
|
<tbody>
|
|
@@ -200,7 +149,7 @@ export const Sent: StoryFn = () => (
|
|
|
200
149
|
sourceUrl,
|
|
201
150
|
}) => (
|
|
202
151
|
<td key={mimeType} className="align-top">
|
|
203
|
-
<LockedAttachment.
|
|
152
|
+
<LockedAttachment.Composer
|
|
204
153
|
placeholderTitle="Attachment title"
|
|
205
154
|
placeholderAmountText="AU$0.00"
|
|
206
155
|
thumbnailUrl={thumbnailUrl}
|
|
@@ -224,7 +173,7 @@ export const Sent: StoryFn = () => (
|
|
|
224
173
|
</td>
|
|
225
174
|
{VARIANTS.map(({ title, mimeType, detail, thumbnailUrl }) => (
|
|
226
175
|
<td key={mimeType} className="align-top">
|
|
227
|
-
<LockedAttachment.
|
|
176
|
+
<LockedAttachment.Composer
|
|
228
177
|
title={title}
|
|
229
178
|
thumbnailUrl={thumbnailUrl}
|
|
230
179
|
mimeType={mimeType}
|
|
@@ -235,6 +184,14 @@ export const Sent: StoryFn = () => (
|
|
|
235
184
|
</td>
|
|
236
185
|
))}
|
|
237
186
|
</tr>
|
|
187
|
+
</tbody>
|
|
188
|
+
</Table>
|
|
189
|
+
)
|
|
190
|
+
|
|
191
|
+
export const Sent: StoryFn = () => (
|
|
192
|
+
<Table>
|
|
193
|
+
<TableHead variants={VARIANTS} />
|
|
194
|
+
<tbody>
|
|
238
195
|
<tr>
|
|
239
196
|
<td className="text-xs text-right font-medium text-black/40 pr-4 align-top pt-2">
|
|
240
197
|
Sent
|
|
@@ -249,7 +206,7 @@ export const Sent: StoryFn = () => (
|
|
|
249
206
|
sourceUrl,
|
|
250
207
|
}) => (
|
|
251
208
|
<td key={mimeType} className="align-top">
|
|
252
|
-
<LockedAttachment.
|
|
209
|
+
<LockedAttachment.Sent
|
|
253
210
|
title={title}
|
|
254
211
|
thumbnailUrl={thumbnailUrl}
|
|
255
212
|
mimeType={mimeType}
|
|
@@ -281,7 +238,7 @@ export const Sent: StoryFn = () => (
|
|
|
281
238
|
sourceUrl,
|
|
282
239
|
}) => (
|
|
283
240
|
<td key={mimeType} className="align-top">
|
|
284
|
-
<LockedAttachment.
|
|
241
|
+
<LockedAttachment.Sent
|
|
285
242
|
title={title}
|
|
286
243
|
thumbnailUrl={thumbnailUrl}
|
|
287
244
|
mimeType={mimeType}
|
|
@@ -303,3 +260,187 @@ export const Sent: StoryFn = () => (
|
|
|
303
260
|
</tbody>
|
|
304
261
|
</Table>
|
|
305
262
|
)
|
|
263
|
+
|
|
264
|
+
export const Gallery: StoryFn = () => {
|
|
265
|
+
const [isPaid, setPaid] = useState(false)
|
|
266
|
+
const [isUnlocking, setUnlocking] = useState(false)
|
|
267
|
+
|
|
268
|
+
return (
|
|
269
|
+
<Table>
|
|
270
|
+
<thead>
|
|
271
|
+
<tr>
|
|
272
|
+
<th className="text-left text-xs font-medium text-black/40 pb-2" />
|
|
273
|
+
<th className="text-left text-xs font-medium text-black/40 pb-2">
|
|
274
|
+
Composer
|
|
275
|
+
</th>
|
|
276
|
+
<th className="text-left text-xs font-medium text-black/40 pb-2">
|
|
277
|
+
Sent
|
|
278
|
+
</th>
|
|
279
|
+
<th className="text-left text-xs font-medium text-black/40 pb-2">
|
|
280
|
+
Received
|
|
281
|
+
</th>
|
|
282
|
+
</tr>
|
|
283
|
+
</thead>
|
|
284
|
+
<tbody>
|
|
285
|
+
<tr>
|
|
286
|
+
<td className="text-xs text-right font-medium text-black/40 pr-4 align-top pt-2">
|
|
287
|
+
Locked
|
|
288
|
+
</td>
|
|
289
|
+
<td className="align-top">
|
|
290
|
+
<LockedAttachment.Composer
|
|
291
|
+
title={GALLERY_TITLE}
|
|
292
|
+
detail={GALLERY_DETAIL}
|
|
293
|
+
amountText="AU$50.00"
|
|
294
|
+
gallery={GALLERY_ITEMS}
|
|
295
|
+
onDismiss={() => alert('Dismissed gallery')}
|
|
296
|
+
onEditClick={() => alert('Edit gallery')}
|
|
297
|
+
/>
|
|
298
|
+
</td>
|
|
299
|
+
<td className="align-top">
|
|
300
|
+
<LockedAttachment.Sent
|
|
301
|
+
title={GALLERY_TITLE}
|
|
302
|
+
detail={GALLERY_DETAIL}
|
|
303
|
+
amountText="AU$50.00"
|
|
304
|
+
gallery={GALLERY_ITEMS}
|
|
305
|
+
/>
|
|
306
|
+
</td>
|
|
307
|
+
<td className="align-top">
|
|
308
|
+
<LockedAttachment.Received
|
|
309
|
+
title={GALLERY_TITLE}
|
|
310
|
+
detail={GALLERY_DETAIL}
|
|
311
|
+
amountText="AU$50.00"
|
|
312
|
+
gallery={GALLERY_ITEMS}
|
|
313
|
+
paymentStatus={isPaid ? 'paid' : undefined}
|
|
314
|
+
isUnlocking={isUnlocking}
|
|
315
|
+
onUnlockClick={() => {
|
|
316
|
+
setUnlocking(true)
|
|
317
|
+
setTimeout(() => {
|
|
318
|
+
setUnlocking(false)
|
|
319
|
+
setPaid(true)
|
|
320
|
+
}, 1500)
|
|
321
|
+
}}
|
|
322
|
+
onDownloadClick={() => alert('Download gallery')}
|
|
323
|
+
/>
|
|
324
|
+
</td>
|
|
325
|
+
</tr>
|
|
326
|
+
<tr>
|
|
327
|
+
<td className="text-xs text-right font-medium text-black/40 pr-4 align-top pt-2">
|
|
328
|
+
Sold / Purchased
|
|
329
|
+
</td>
|
|
330
|
+
<td className="align-top">
|
|
331
|
+
<LockedAttachment.Composer
|
|
332
|
+
title={GALLERY_TITLE}
|
|
333
|
+
detail={GALLERY_DETAIL}
|
|
334
|
+
amountText="AU$50.00"
|
|
335
|
+
gallery={GALLERY_ITEMS}
|
|
336
|
+
onEditClick={() => alert('Edit gallery')}
|
|
337
|
+
/>
|
|
338
|
+
</td>
|
|
339
|
+
<td className="align-top">
|
|
340
|
+
<LockedAttachment.Sent
|
|
341
|
+
title={GALLERY_TITLE}
|
|
342
|
+
detail={GALLERY_DETAIL}
|
|
343
|
+
amountText="AU$50.00"
|
|
344
|
+
paymentStatus="paid"
|
|
345
|
+
gallery={GALLERY_ITEMS}
|
|
346
|
+
/>
|
|
347
|
+
</td>
|
|
348
|
+
<td className="align-top">
|
|
349
|
+
<LockedAttachment.Received
|
|
350
|
+
title={GALLERY_TITLE}
|
|
351
|
+
detail={GALLERY_DETAIL}
|
|
352
|
+
amountText="AU$50.00"
|
|
353
|
+
paymentStatus="paid"
|
|
354
|
+
gallery={GALLERY_ITEMS}
|
|
355
|
+
onDownloadClick={() => alert('Download gallery')}
|
|
356
|
+
/>
|
|
357
|
+
</td>
|
|
358
|
+
</tr>
|
|
359
|
+
</tbody>
|
|
360
|
+
</Table>
|
|
361
|
+
)
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
export const Received: StoryFn = () => {
|
|
365
|
+
const [isPaid, setPaid] = useState<string | undefined>()
|
|
366
|
+
const [isUnlocking, setUnlocking] = useState<string | undefined>()
|
|
367
|
+
|
|
368
|
+
return (
|
|
369
|
+
<Table>
|
|
370
|
+
<TableHead variants={VARIANTS} />
|
|
371
|
+
<tbody>
|
|
372
|
+
<tr>
|
|
373
|
+
<td className="text-xs text-right font-medium text-black/40 pr-4 align-top pt-2">
|
|
374
|
+
Locked
|
|
375
|
+
</td>
|
|
376
|
+
{VARIANTS.map(
|
|
377
|
+
({
|
|
378
|
+
title,
|
|
379
|
+
mimeType,
|
|
380
|
+
detail,
|
|
381
|
+
thumbnailUrl,
|
|
382
|
+
thumbnailUnlockedUrl,
|
|
383
|
+
sourceUrl,
|
|
384
|
+
}) => (
|
|
385
|
+
<td key={mimeType} className="align-top">
|
|
386
|
+
<LockedAttachment.Received
|
|
387
|
+
title={title}
|
|
388
|
+
thumbnailUrl={thumbnailUrl}
|
|
389
|
+
mimeType={mimeType}
|
|
390
|
+
detail={detail}
|
|
391
|
+
paymentStatus={isPaid === mimeType ? 'paid' : undefined}
|
|
392
|
+
amountText="AU$9.99"
|
|
393
|
+
isUnlocking={isUnlocking === mimeType}
|
|
394
|
+
onUnlockClick={() => {
|
|
395
|
+
setUnlocking(mimeType)
|
|
396
|
+
setTimeout(() => {
|
|
397
|
+
setUnlocking(undefined)
|
|
398
|
+
setPaid(mimeType)
|
|
399
|
+
}, 1500)
|
|
400
|
+
}}
|
|
401
|
+
onDownloadClick={() => alert('Download clicked')}
|
|
402
|
+
onFetchSource={async () => ({
|
|
403
|
+
sourceUrl: sourceUrl,
|
|
404
|
+
thumbnailUrl: thumbnailUnlockedUrl,
|
|
405
|
+
})}
|
|
406
|
+
/>
|
|
407
|
+
</td>
|
|
408
|
+
)
|
|
409
|
+
)}
|
|
410
|
+
</tr>
|
|
411
|
+
<tr>
|
|
412
|
+
<td className="text-xs text-right font-medium text-black/40 pr-4 align-top pt-2">
|
|
413
|
+
Unlocked
|
|
414
|
+
</td>
|
|
415
|
+
{VARIANTS.map(
|
|
416
|
+
({
|
|
417
|
+
title,
|
|
418
|
+
mimeType,
|
|
419
|
+
detail,
|
|
420
|
+
thumbnailUrl,
|
|
421
|
+
thumbnailUnlockedUrl,
|
|
422
|
+
sourceUrl,
|
|
423
|
+
}) => (
|
|
424
|
+
<td key={mimeType} className="align-top">
|
|
425
|
+
<LockedAttachment.Received
|
|
426
|
+
title={title}
|
|
427
|
+
thumbnailUrl={thumbnailUrl}
|
|
428
|
+
mimeType={mimeType}
|
|
429
|
+
detail={detail}
|
|
430
|
+
amountText="AU$9.99"
|
|
431
|
+
paymentStatus="paid"
|
|
432
|
+
onUnlockClick={() => alert('Unlock clicked')}
|
|
433
|
+
onDownloadClick={() => alert('Download clicked')}
|
|
434
|
+
onFetchSource={async () => ({
|
|
435
|
+
sourceUrl: sourceUrl,
|
|
436
|
+
thumbnailUrl: thumbnailUnlockedUrl,
|
|
437
|
+
})}
|
|
438
|
+
/>
|
|
439
|
+
</td>
|
|
440
|
+
)
|
|
441
|
+
)}
|
|
442
|
+
</tr>
|
|
443
|
+
</tbody>
|
|
444
|
+
</Table>
|
|
445
|
+
)
|
|
446
|
+
}
|