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
29
pulls
pipelines
add published page block preview
awarm.space
5 months ago
f2fa8ff3
92a3e163
+191
-12
4 changed files
expand all
collapse all
unified
split
app
lish
[did]
[publication]
[rkey]
Interactions
Quotes.tsx
PostContent.tsx
PostPages.tsx
PublishedPageBlock.tsx
+6
-2
app/lish/[did]/[publication]/[rkey]/Interactions/Quotes.tsx
···
26
26
}) => {
27
27
let data = useContext(PostPageContext);
28
28
const document_uri = data?.uri;
29
29
-
if (!document_uri) throw new Error('document_uri not available in PostPageContext');
29
29
+
if (!document_uri)
30
30
+
throw new Error("document_uri not available in PostPageContext");
30
31
31
32
return (
32
33
<div className="flex flex-col gap-2">
···
34
35
Quotes
35
36
<button
36
37
className="text-tertiary"
37
37
-
onClick={() => setInteractionState(document_uri, { drawerOpen: false })}
38
38
+
onClick={() =>
39
39
+
setInteractionState(document_uri, { drawerOpen: false })
40
40
+
}
38
41
>
39
42
<CloseTiny />
40
43
</button>
···
125
128
>
126
129
<div className="italic border border-border-light rounded-md px-2 pt-1">
127
130
<PostContent
131
131
+
pages={[]}
128
132
bskyPostData={[]}
129
133
blocks={content}
130
134
did={props.did}
+20
-7
app/lish/[did]/[publication]/[rkey]/PostContent.tsx
···
26
26
import { AppBskyFeedDefs } from "@atproto/api";
27
27
import { PubBlueskyPostBlock } from "./PublishBskyPostBlock";
28
28
import { openPage } from "./PostPages";
29
29
+
import { PageLinkBlock } from "components/Blocks/PageLinkBlock";
30
30
+
import { PublishedPageLinkBlock } from "./PublishedPageBlock";
29
31
30
32
export function PostContent({
31
33
blocks,
···
35
37
prerenderedCodeBlocks,
36
38
bskyPostData,
37
39
pageId,
40
40
+
pages,
38
41
}: {
39
42
blocks: PubLeafletPagesLinearDocument.Block[];
40
43
pageId?: string;
···
43
46
className?: string;
44
47
prerenderedCodeBlocks?: Map<string, string>;
45
48
bskyPostData: AppBskyFeedDefs.PostView[];
49
49
+
pages: PubLeafletPagesLinearDocument.Main[];
46
50
}) {
47
51
return (
48
52
<div
···
53
57
return (
54
58
<Block
55
59
pageId={pageId}
60
60
+
pages={pages}
56
61
bskyPostData={bskyPostData}
57
62
block={b}
58
63
did={did}
···
78
83
prerenderedCodeBlocks,
79
84
bskyPostData,
80
85
pageId,
86
86
+
pages,
81
87
}: {
82
88
pageId?: string;
83
89
preview?: boolean;
···
85
91
block: PubLeafletPagesLinearDocument.Block;
86
92
did: string;
87
93
isList?: boolean;
94
94
+
pages: PubLeafletPagesLinearDocument.Main[];
88
95
previousBlock?: PubLeafletPagesLinearDocument.Block;
89
96
prerenderedCodeBlocks?: Map<string, string>;
90
97
bskyPostData: AppBskyFeedDefs.PostView[];
···
123
130
switch (true) {
124
131
case PubLeafletBlocksPage.isMain(b.block): {
125
132
let id = b.block.id;
133
133
+
let page = pages.find((p) => p.id === id);
134
134
+
if (!page) return;
126
135
return (
127
127
-
<div
128
128
-
onClick={() => {
129
129
-
openPage(pageId, id);
130
130
-
}}
131
131
-
>
132
132
-
ITS A BLOCK
133
133
-
</div>
136
136
+
<PublishedPageLinkBlock
137
137
+
blocks={page.blocks}
138
138
+
pageId={id}
139
139
+
parentPageId={pageId}
140
140
+
did={did}
141
141
+
bskyPostData={bskyPostData}
142
142
+
/>
134
143
);
135
144
}
136
145
case PubLeafletBlocksBskyPost.isMain(b.block): {
···
159
168
<ul className="-ml-px sm:ml-[9px] pb-2">
160
169
{b.block.children.map((child, i) => (
161
170
<ListItem
171
171
+
pages={pages}
162
172
bskyPostData={bskyPostData}
163
173
index={[...index, i]}
164
174
item={child}
···
316
326
317
327
function ListItem(props: {
318
328
index: number[];
329
329
+
pages: PubLeafletPagesLinearDocument.Main[];
319
330
item: PubLeafletBlocksUnorderedList.ListItem;
320
331
did: string;
321
332
className?: string;
···
325
336
<ul className="-ml-[7px] sm:ml-[7px]">
326
337
{props.item.children.map((child, index) => (
327
338
<ListItem
339
339
+
pages={props.pages}
328
340
bskyPostData={props.bskyPostData}
329
341
index={[...props.index, index]}
330
342
item={child}
···
343
355
/>
344
356
<div className="flex flex-col w-full">
345
357
<Block
358
358
+
pages={props.pages}
346
359
bskyPostData={props.bskyPostData}
347
360
block={{ block: props.item.content }}
348
361
did={props.did}
+6
-3
app/lish/[did]/[publication]/[rkey]/PostPages.tsx
···
21
21
import { PageOptionButton } from "components/Pages/PageOptions";
22
22
import { CloseTiny } from "components/Icons/CloseTiny";
23
23
import { PageWrapper } from "components/Pages/Page";
24
24
+
import { Fragment } from "react";
24
25
export const usePostPageUIState = create(() => ({
25
26
pages: [] as string[],
26
27
}));
···
73
74
74
75
let hasPageBackground = !!pubRecord.theme?.showPageBackground;
75
76
let fullPageScroll = !hasPageBackground && !drawerOpen && pages.length === 0;
77
77
+
let record = document.data as PubLeafletDocument.Record;
76
78
return (
77
79
<>
78
80
{!fullPageScroll && <BookendSpacer />}
···
88
90
preferences={preferences}
89
91
/>
90
92
<PostContent
93
93
+
pages={record.pages as PubLeafletPagesLinearDocument.Main[]}
91
94
bskyPostData={bskyPostData}
92
95
blocks={blocks}
93
96
did={did}
···
141
144
)}
142
145
143
146
{pages.map((p) => {
144
144
-
let record = document.data as PubLeafletDocument.Record;
145
147
let page = record.pages.find(
146
148
(page) => (page as PubLeafletPagesLinearDocument.Main).id === p,
147
149
) as PubLeafletPagesLinearDocument.Main | undefined;
148
150
if (!page) return null;
149
151
return (
150
150
-
<>
152
152
+
<Fragment key={p}>
151
153
<SandwichSpacer />
152
154
<PageWrapper
153
155
cardBorderHidden={!hasPageBackground}
···
161
163
}
162
164
>
163
165
<PostContent
166
166
+
pages={record.pages as PubLeafletPagesLinearDocument.Main[]}
164
167
pageId={page.id}
165
168
bskyPostData={bskyPostData}
166
169
blocks={page.blocks}
···
168
171
prerenderedCodeBlocks={prerenderedCodeBlocks}
169
172
/>
170
173
</PageWrapper>
171
171
-
</>
174
174
+
</Fragment>
172
175
);
173
176
})}
174
177
{!fullPageScroll && <BookendSpacer />}
+159
app/lish/[did]/[publication]/[rkey]/PublishedPageBlock.tsx
···
1
1
+
"use client";
2
2
+
3
3
+
import { useEntity, useReplicache } from "src/replicache";
4
4
+
import { useUIState } from "src/useUIState";
5
5
+
import { CSSProperties, useContext, useRef } from "react";
6
6
+
import { useCardBorderHidden } from "components/Pages/useCardBorderHidden";
7
7
+
import { PostContent } from "./PostContent";
8
8
+
import {
9
9
+
PubLeafletBlocksHeader,
10
10
+
PubLeafletBlocksText,
11
11
+
PubLeafletPagesLinearDocument,
12
12
+
PubLeafletPublication,
13
13
+
} from "lexicons/api";
14
14
+
import { AppBskyFeedDefs } from "@atproto/api";
15
15
+
import { TextBlock } from "./TextBlock";
16
16
+
import { PostPageContext } from "./PostPageContext";
17
17
+
import { openPage, usePostPageUIState } from "./PostPages";
18
18
+
19
19
+
export function PublishedPageLinkBlock(props: {
20
20
+
blocks: PubLeafletPagesLinearDocument.Block[];
21
21
+
parentPageId: string | undefined;
22
22
+
pageId: string;
23
23
+
did: string;
24
24
+
preview?: boolean;
25
25
+
className?: string;
26
26
+
prerenderedCodeBlocks?: Map<string, string>;
27
27
+
bskyPostData: AppBskyFeedDefs.PostView[];
28
28
+
}) {
29
29
+
//switch to use actually state
30
30
+
let isOpen = usePostPageUIState((s) => s.pages.includes(props.pageId));
31
31
+
return (
32
32
+
<div
33
33
+
className={`w-full cursor-pointer
34
34
+
pageLinkBlockWrapper relative group/pageLinkBlock
35
35
+
bg-bg-page shadow-sm
36
36
+
flex overflow-clip
37
37
+
block-border
38
38
+
${isOpen && "!border-tertiary"}
39
39
+
`}
40
40
+
onClick={(e) => {
41
41
+
if (e.isDefaultPrevented()) return;
42
42
+
if (e.shiftKey) return;
43
43
+
e.preventDefault();
44
44
+
e.stopPropagation();
45
45
+
46
46
+
console.log("yoo@");
47
47
+
48
48
+
openPage(props.parentPageId, props.pageId);
49
49
+
//open the damn thing somehow
50
50
+
}}
51
51
+
>
52
52
+
<DocLinkBlock {...props} />
53
53
+
</div>
54
54
+
);
55
55
+
}
56
56
+
export function DocLinkBlock(props: {
57
57
+
blocks: PubLeafletPagesLinearDocument.Block[];
58
58
+
pageId?: string;
59
59
+
did: string;
60
60
+
preview?: boolean;
61
61
+
className?: string;
62
62
+
prerenderedCodeBlocks?: Map<string, string>;
63
63
+
bskyPostData: AppBskyFeedDefs.PostView[];
64
64
+
}) {
65
65
+
let { rep } = useReplicache();
66
66
+
let [title, description] = props.blocks
67
67
+
.map((b) => b.block)
68
68
+
.filter(
69
69
+
(b) => PubLeafletBlocksText.isMain(b) || PubLeafletBlocksHeader.isMain(b),
70
70
+
);
71
71
+
72
72
+
return (
73
73
+
<div
74
74
+
style={{ "--list-marker-width": "20px" } as CSSProperties}
75
75
+
className={`
76
76
+
w-full h-[104px]
77
77
+
`}
78
78
+
>
79
79
+
<>
80
80
+
<div className="pageLinkBlockContent w-full flex overflow-clip cursor-pointer h-full">
81
81
+
<div className="my-2 ml-3 grow min-w-0 text-sm bg-transparent overflow-clip ">
82
82
+
{title && (
83
83
+
<div
84
84
+
className={`pageBlockOne outline-none resize-none align-top flex gap-2 ${title.$type === "pub.leaflet.blocks.header" ? "font-bold text-base" : ""}`}
85
85
+
>
86
86
+
<TextBlock
87
87
+
facets={title.facets}
88
88
+
plaintext={title.plaintext}
89
89
+
index={[]}
90
90
+
preview
91
91
+
/>
92
92
+
</div>
93
93
+
)}
94
94
+
{description && (
95
95
+
<div
96
96
+
className={`pageBlockLineTwo outline-none resize-none align-top flex gap-2 ${description.$type === "pub.leaflet.blocks.header" ? "font-bold" : ""}`}
97
97
+
>
98
98
+
<TextBlock
99
99
+
facets={description.facets}
100
100
+
plaintext={description.plaintext}
101
101
+
index={[]}
102
102
+
preview
103
103
+
/>
104
104
+
</div>
105
105
+
)}
106
106
+
</div>
107
107
+
{!props.preview && (
108
108
+
<PagePreview blocks={props.blocks} did={props.did} />
109
109
+
)}
110
110
+
</div>
111
111
+
</>
112
112
+
</div>
113
113
+
);
114
114
+
}
115
115
+
116
116
+
export function PagePreview(props: {
117
117
+
did: string;
118
118
+
blocks: PubLeafletPagesLinearDocument.Block[];
119
119
+
}) {
120
120
+
let previewRef = useRef<HTMLDivElement | null>(null);
121
121
+
let { rootEntity } = useReplicache();
122
122
+
let data = useContext(PostPageContext);
123
123
+
let theme = data?.documents_in_publications[0]?.publications
124
124
+
?.record as PubLeafletPublication.Record;
125
125
+
let pageWidth = `var(--page-width-unitless)`;
126
126
+
let cardBorderHidden = !theme.theme?.showPageBackground;
127
127
+
return (
128
128
+
<div
129
129
+
ref={previewRef}
130
130
+
className={`pageLinkBlockPreview w-[120px] overflow-clip mx-3 mt-3 -mb-2 border rounded-md shrink-0 border-border-light flex flex-col gap-0.5 rotate-[4deg] origin-center ${cardBorderHidden ? "" : "bg-bg-page"}`}
131
131
+
>
132
132
+
<div
133
133
+
className="absolute top-0 left-0 origin-top-left pointer-events-none "
134
134
+
style={{
135
135
+
width: `calc(1px * ${pageWidth})`,
136
136
+
height: `calc(100vh - 64px)`,
137
137
+
transform: `scale(calc((120 / ${pageWidth} )))`,
138
138
+
backgroundColor: "rgba(var(--bg-page), var(--bg-page-alpha))",
139
139
+
}}
140
140
+
>
141
141
+
{!cardBorderHidden && (
142
142
+
<div
143
143
+
className={`pageLinkBlockBackground
144
144
+
absolute top-0 left-0 right-0 bottom-0
145
145
+
pointer-events-none
146
146
+
`}
147
147
+
/>
148
148
+
)}
149
149
+
<PostContent
150
150
+
pages={[]}
151
151
+
did={props.did}
152
152
+
blocks={props.blocks}
153
153
+
preview
154
154
+
bskyPostData={[]}
155
155
+
/>
156
156
+
</div>
157
157
+
</div>
158
158
+
);
159
159
+
}