tangled
alpha
login
or
join now
leaflet.pub
/
leaflet
289
fork
atom
a tool for shared writing and social publishing
289
fork
atom
overview
issues
28
pulls
pipelines
extract out page component to lineardocumentpage
awarm.space
4 months ago
ce10575f
b5227eac
+179
-108
5 changed files
expand all
collapse all
unified
split
actions
publishToPublication.ts
app
lish
[did]
[publication]
[rkey]
LinearDocumentPage.tsx
PostContent.tsx
PostPages.tsx
components
Blocks
BlockCommands.tsx
+1
actions/publishToPublication.ts
···
228
228
if (b.type === "card") {
229
229
let [page] = scan.eav(b.value, "block/card");
230
230
if (!page) return;
231
231
+
let [pageType] = scan.eav(page.data.value, "page/type");
231
232
let blocks = getBlocksWithTypeLocal(facts, page.data.value);
232
233
pages.push({
233
234
id: page.data.value,
+152
app/lish/[did]/[publication]/[rkey]/LinearDocumentPage.tsx
···
1
1
+
"use client";
2
2
+
import {
3
3
+
PubLeafletComment,
4
4
+
PubLeafletDocument,
5
5
+
PubLeafletPagesLinearDocument,
6
6
+
PubLeafletPublication,
7
7
+
} from "lexicons/api";
8
8
+
import { PostPageData } from "./getPostPageData";
9
9
+
import { ProfileViewDetailed } from "@atproto/api/dist/client/types/app/bsky/actor/defs";
10
10
+
import { getPublicationURL } from "app/lish/createPub/getPublicationURL";
11
11
+
import { SubscribeWithBluesky } from "app/lish/Subscribe";
12
12
+
import { EditTiny } from "components/Icons/EditTiny";
13
13
+
import { Interactions } from "./Interactions/Interactions";
14
14
+
import { PostContent } from "./PostContent";
15
15
+
import { PostHeader } from "./PostHeader/PostHeader";
16
16
+
import { useIdentityData } from "components/IdentityProvider";
17
17
+
import { AppBskyFeedDefs } from "@atproto/api";
18
18
+
import { useDrawerOpen } from "./Interactions/InteractionDrawer";
19
19
+
import { PageWrapper } from "components/Pages/Page";
20
20
+
import { decodeQuotePosition } from "./quotePosition";
21
21
+
22
22
+
export function LinearDocumentPage({
23
23
+
document,
24
24
+
blocks,
25
25
+
did,
26
26
+
profile,
27
27
+
preferences,
28
28
+
pubRecord,
29
29
+
prerenderedCodeBlocks,
30
30
+
bskyPostData,
31
31
+
document_uri,
32
32
+
pageId,
33
33
+
pageOptions,
34
34
+
fullPageScroll,
35
35
+
}: {
36
36
+
document_uri: string;
37
37
+
document: PostPageData;
38
38
+
blocks: PubLeafletPagesLinearDocument.Block[];
39
39
+
profile?: ProfileViewDetailed;
40
40
+
pubRecord: PubLeafletPublication.Record;
41
41
+
did: string;
42
42
+
prerenderedCodeBlocks?: Map<string, string>;
43
43
+
bskyPostData: AppBskyFeedDefs.PostView[];
44
44
+
preferences: { showComments?: boolean };
45
45
+
pageId?: string;
46
46
+
pageOptions?: React.ReactNode;
47
47
+
fullPageScroll: boolean;
48
48
+
}) {
49
49
+
let { identity } = useIdentityData();
50
50
+
let drawer = useDrawerOpen(document_uri);
51
51
+
52
52
+
if (!document || !document.documents_in_publications[0].publications)
53
53
+
return null;
54
54
+
55
55
+
let hasPageBackground = !!pubRecord.theme?.showPageBackground;
56
56
+
let record = document.data as PubLeafletDocument.Record;
57
57
+
58
58
+
const isSubpage = !!pageId;
59
59
+
60
60
+
return (
61
61
+
<>
62
62
+
<PageWrapper
63
63
+
pageType="doc"
64
64
+
fullPageScroll={fullPageScroll}
65
65
+
cardBorderHidden={!hasPageBackground}
66
66
+
id={pageId ? `post-page-${pageId}` : "post-page"}
67
67
+
drawerOpen={
68
68
+
!!drawer && (pageId ? drawer.pageId === pageId : !drawer.pageId)
69
69
+
}
70
70
+
pageOptions={pageOptions}
71
71
+
>
72
72
+
{!isSubpage && profile && (
73
73
+
<PostHeader
74
74
+
data={document}
75
75
+
profile={profile}
76
76
+
preferences={preferences}
77
77
+
/>
78
78
+
)}
79
79
+
<PostContent
80
80
+
pages={record.pages as PubLeafletPagesLinearDocument.Main[]}
81
81
+
pageId={pageId}
82
82
+
bskyPostData={bskyPostData}
83
83
+
blocks={blocks}
84
84
+
did={did}
85
85
+
prerenderedCodeBlocks={prerenderedCodeBlocks}
86
86
+
/>
87
87
+
<Interactions
88
88
+
pageId={pageId}
89
89
+
showComments={preferences.showComments}
90
90
+
quotesCount={
91
91
+
pageId
92
92
+
? document.document_mentions_in_bsky.filter((q) =>
93
93
+
q.link.includes(pageId),
94
94
+
).length
95
95
+
: document.document_mentions_in_bsky.filter((q) => {
96
96
+
const url = new URL(q.link);
97
97
+
const quoteParam = url.pathname.split("/l-quote/")[1];
98
98
+
if (!quoteParam) return null;
99
99
+
const quotePosition = decodeQuotePosition(quoteParam);
100
100
+
return !quotePosition?.pageId;
101
101
+
}).length
102
102
+
}
103
103
+
commentsCount={
104
104
+
pageId
105
105
+
? document.comments_on_documents.filter(
106
106
+
(c) =>
107
107
+
(c.record as PubLeafletComment.Record)?.onPage === pageId,
108
108
+
).length
109
109
+
: document.comments_on_documents.filter(
110
110
+
(c) => !(c.record as PubLeafletComment.Record)?.onPage,
111
111
+
).length
112
112
+
}
113
113
+
/>
114
114
+
{!isSubpage && (
115
115
+
<>
116
116
+
<hr className="border-border-light mb-4 mt-4 sm:mx-4 mx-3" />
117
117
+
<div className="pb-6 sm:px-4 px-3">
118
118
+
{identity &&
119
119
+
identity.atp_did ===
120
120
+
document.documents_in_publications[0]?.publications
121
121
+
?.identity_did ? (
122
122
+
<a
123
123
+
href={`https://leaflet.pub/${document.leaflets_in_publications[0]?.leaflet}`}
124
124
+
className="flex gap-2 items-center hover:!no-underline selected-outline px-2 py-0.5 bg-accent-1 text-accent-2 font-bold w-fit rounded-lg !border-accent-1 !outline-accent-1 mx-auto"
125
125
+
>
126
126
+
<EditTiny /> Edit Post
127
127
+
</a>
128
128
+
) : (
129
129
+
<SubscribeWithBluesky
130
130
+
isPost
131
131
+
base_url={getPublicationURL(
132
132
+
document.documents_in_publications[0].publications,
133
133
+
)}
134
134
+
pub_uri={
135
135
+
document.documents_in_publications[0].publications.uri
136
136
+
}
137
137
+
subscribers={
138
138
+
document.documents_in_publications[0].publications
139
139
+
.publication_subscriptions
140
140
+
}
141
141
+
pubName={
142
142
+
document.documents_in_publications[0].publications.name
143
143
+
}
144
144
+
/>
145
145
+
)}
146
146
+
</div>
147
147
+
</>
148
148
+
)}
149
149
+
</PageWrapper>
150
150
+
</>
151
151
+
);
152
152
+
}
+1
-1
app/lish/[did]/[publication]/[rkey]/PostContent.tsx
···
73
73
);
74
74
}
75
75
76
76
-
let Block = ({
76
76
+
export let Block = ({
77
77
block,
78
78
did,
79
79
isList,
+25
-106
app/lish/[did]/[publication]/[rkey]/PostPages.tsx
···
1
1
"use client";
2
2
import {
3
3
-
PubLeafletComment,
4
3
PubLeafletDocument,
5
4
PubLeafletPagesLinearDocument,
6
5
PubLeafletPublication,
7
6
} from "lexicons/api";
8
7
import { PostPageData } from "./getPostPageData";
9
8
import { ProfileViewDetailed } from "@atproto/api/dist/client/types/app/bsky/actor/defs";
10
10
-
import { getPublicationURL } from "app/lish/createPub/getPublicationURL";
11
11
-
import { SubscribeWithBluesky } from "app/lish/Subscribe";
12
12
-
import { EditTiny } from "components/Icons/EditTiny";
13
13
-
import { Interactions } from "./Interactions/Interactions";
14
14
-
import { PostContent } from "./PostContent";
15
15
-
import { PostHeader } from "./PostHeader/PostHeader";
16
16
-
import { useIdentityData } from "components/IdentityProvider";
17
9
import { AppBskyFeedDefs } from "@atproto/api";
18
10
import { create } from "zustand/react";
19
11
import {
···
23
15
import { BookendSpacer, SandwichSpacer } from "components/LeafletLayout";
24
16
import { PageOptionButton } from "components/Pages/PageOptions";
25
17
import { CloseTiny } from "components/Icons/CloseTiny";
26
26
-
import { PageWrapper } from "components/Pages/Page";
27
18
import { Fragment, useEffect } from "react";
28
19
import { flushSync } from "react-dom";
29
20
import { scrollIntoView } from "src/utils/scrollIntoView";
30
21
import { useParams } from "next/navigation";
31
22
import { decodeQuotePosition } from "./quotePosition";
23
23
+
import { LinearDocumentPage } from "./LinearDocumentPage";
32
24
33
25
const usePostPageUIState = create(() => ({
34
26
pages: [] as string[],
···
124
116
bskyPostData: AppBskyFeedDefs.PostView[];
125
117
preferences: { showComments?: boolean };
126
118
}) {
127
127
-
let { identity } = useIdentityData();
128
119
let drawer = useDrawerOpen(document_uri);
129
120
useInitializeOpenPages();
130
121
let pages = useOpenPages();
···
132
123
return null;
133
124
134
125
let hasPageBackground = !!pubRecord.theme?.showPageBackground;
126
126
+
let record = document.data as PubLeafletDocument.Record;
127
127
+
135
128
let fullPageScroll = !hasPageBackground && !drawer && pages.length === 0;
136
136
-
let record = document.data as PubLeafletDocument.Record;
137
129
return (
138
130
<>
139
131
{!fullPageScroll && <BookendSpacer />}
140
140
-
<PageWrapper
141
141
-
pageType="doc"
132
132
+
<LinearDocumentPage
133
133
+
document={document}
134
134
+
blocks={blocks}
135
135
+
did={did}
136
136
+
profile={profile}
142
137
fullPageScroll={fullPageScroll}
143
143
-
cardBorderHidden={!hasPageBackground}
144
144
-
id={"post-page"}
145
145
-
drawerOpen={!!drawer && !drawer.pageId}
146
146
-
>
147
147
-
<PostHeader
148
148
-
data={document}
149
149
-
profile={profile}
150
150
-
preferences={preferences}
151
151
-
/>
152
152
-
<PostContent
153
153
-
pages={record.pages as PubLeafletPagesLinearDocument.Main[]}
154
154
-
bskyPostData={bskyPostData}
155
155
-
blocks={blocks}
156
156
-
did={did}
157
157
-
prerenderedCodeBlocks={prerenderedCodeBlocks}
158
158
-
/>
159
159
-
<Interactions
160
160
-
showComments={preferences.showComments}
161
161
-
quotesCount={
162
162
-
document.document_mentions_in_bsky.filter((q) => {
163
163
-
const url = new URL(q.link);
164
164
-
const quoteParam = url.pathname.split("/l-quote/")[1];
165
165
-
if (!quoteParam) return null;
166
166
-
const quotePosition = decodeQuotePosition(quoteParam);
167
167
-
return !quotePosition?.pageId;
168
168
-
}).length
169
169
-
}
170
170
-
commentsCount={
171
171
-
document.comments_on_documents.filter(
172
172
-
(c) => !(c.record as PubLeafletComment.Record)?.onPage,
173
173
-
).length
174
174
-
}
175
175
-
/>
176
176
-
<hr className="border-border-light mb-4 mt-4 sm:mx-4 mx-3" />
177
177
-
<div className="pb-6 sm:px-4 px-3">
178
178
-
{identity &&
179
179
-
identity.atp_did ===
180
180
-
document.documents_in_publications[0]?.publications
181
181
-
?.identity_did ? (
182
182
-
<a
183
183
-
href={`https://leaflet.pub/${document.leaflets_in_publications[0]?.leaflet}`}
184
184
-
className="flex gap-2 items-center hover:!no-underline selected-outline px-2 py-0.5 bg-accent-1 text-accent-2 font-bold w-fit rounded-lg !border-accent-1 !outline-accent-1 mx-auto"
185
185
-
>
186
186
-
<EditTiny /> Edit Post
187
187
-
</a>
188
188
-
) : (
189
189
-
<SubscribeWithBluesky
190
190
-
isPost
191
191
-
base_url={getPublicationURL(
192
192
-
document.documents_in_publications[0].publications,
193
193
-
)}
194
194
-
pub_uri={document.documents_in_publications[0].publications.uri}
195
195
-
subscribers={
196
196
-
document.documents_in_publications[0].publications
197
197
-
.publication_subscriptions
198
198
-
}
199
199
-
pubName={document.documents_in_publications[0].publications.name}
200
200
-
/>
201
201
-
)}
202
202
-
</div>
203
203
-
</PageWrapper>
138
138
+
preferences={preferences}
139
139
+
pubRecord={pubRecord}
140
140
+
prerenderedCodeBlocks={prerenderedCodeBlocks}
141
141
+
bskyPostData={bskyPostData}
142
142
+
document_uri={document_uri}
143
143
+
/>
204
144
205
145
{drawer && !drawer.pageId && (
206
146
<InteractionDrawer
···
223
163
return (
224
164
<Fragment key={p}>
225
165
<SandwichSpacer />
226
226
-
{/*JARED TODO : drawerOpen here is checking whether the drawer is open on the first page, rather than if it's open on this page. Please rewire this when you add drawers per page!*/}
227
227
-
<PageWrapper
228
228
-
pageType="doc"
229
229
-
cardBorderHidden={!hasPageBackground}
230
230
-
id={`post-page-${p}`}
166
166
+
<LinearDocumentPage
231
167
fullPageScroll={false}
232
232
-
drawerOpen={!!drawer && drawer.pageId === page.id}
168
168
+
document={document}
169
169
+
blocks={page.blocks}
170
170
+
did={did}
171
171
+
preferences={preferences}
172
172
+
pubRecord={pubRecord}
173
173
+
prerenderedCodeBlocks={prerenderedCodeBlocks}
174
174
+
bskyPostData={bskyPostData}
175
175
+
document_uri={document_uri}
176
176
+
pageId={page.id}
233
177
pageOptions={
234
178
<PageOptions
235
179
onClick={() => closePage(page?.id!)}
236
180
hasPageBackground={hasPageBackground}
237
181
/>
238
182
}
239
239
-
>
240
240
-
<PostContent
241
241
-
pages={record.pages as PubLeafletPagesLinearDocument.Main[]}
242
242
-
pageId={page.id}
243
243
-
bskyPostData={bskyPostData}
244
244
-
blocks={page.blocks}
245
245
-
did={did}
246
246
-
prerenderedCodeBlocks={prerenderedCodeBlocks}
247
247
-
/>
248
248
-
<Interactions
249
249
-
pageId={page.id}
250
250
-
showComments={preferences.showComments}
251
251
-
quotesCount={
252
252
-
document.document_mentions_in_bsky.filter((q) =>
253
253
-
q.link.includes(page.id!),
254
254
-
).length
255
255
-
}
256
256
-
commentsCount={
257
257
-
document.comments_on_documents.filter(
258
258
-
(c) =>
259
259
-
(c.record as PubLeafletComment.Record)?.onPage ===
260
260
-
page.id,
261
261
-
).length
262
262
-
}
263
263
-
/>
264
264
-
</PageWrapper>
183
183
+
/>
265
184
{drawer && drawer.pageId === page.id && (
266
185
<InteractionDrawer
267
186
pageId={page.id}
-1
components/Blocks/BlockCommands.tsx
···
369
369
name: "New Canvas",
370
370
icon: <BlockCanvasPageSmall />,
371
371
type: "page",
372
372
-
hiddenInPublication: true,
373
372
onSelect: async (rep, props, um) => {
374
373
props.entityID && clearCommandSearchText(props.entityID);
375
374
let entity = await createBlockWithType(rep, props, "card");