a tool for shared writing and social publishing
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

wire up backdating posts from the publish flow. still broken from update button

celine cf5110e7 3875b4e9

+36 -97
-86
actions/backdatePost.ts
··· 1 - "use server"; 2 - 3 - import { AtpBaseClient, PubLeafletDocument } from "lexicons/api"; 4 - import { restoreOAuthSession, OAuthSessionError } from "src/atproto-oauth"; 5 - import { getIdentityData } from "actions/getIdentityData"; 6 - import { supabaseServerClient } from "supabase/serverClient"; 7 - import { Json } from "supabase/database.types"; 8 - import { AtUri } from "@atproto/syntax"; 9 - 10 - type BackdateResult = 11 - | { success: true; publishedAt: string } 12 - | { success: false; error?: OAuthSessionError | string }; 13 - 14 - export async function backdatePost({ 15 - uri, 16 - publishedAt, 17 - }: { 18 - uri: string; 19 - publishedAt: string; 20 - }): Promise<BackdateResult> { 21 - let identity = await getIdentityData(); 22 - if (!identity || !identity.atp_did) { 23 - return { 24 - success: false, 25 - error: "Not authenticated", 26 - }; 27 - } 28 - 29 - const sessionResult = await restoreOAuthSession(identity.atp_did); 30 - if (!sessionResult.ok) { 31 - return { success: false, error: sessionResult.error }; 32 - } 33 - let credentialSession = sessionResult.value; 34 - let agent = new AtpBaseClient( 35 - credentialSession.fetchHandler.bind(credentialSession), 36 - ); 37 - 38 - // Get the existing document 39 - let { data: existingDoc } = await supabaseServerClient 40 - .from("documents") 41 - .select("*") 42 - .eq("uri", uri) 43 - .single(); 44 - 45 - if (!existingDoc) { 46 - return { success: false, error: "Document not found" }; 47 - } 48 - 49 - let record = existingDoc.data as PubLeafletDocument.Record; 50 - 51 - // Check if the user is the author 52 - if (record.author !== identity.atp_did) { 53 - return { success: false, error: "Not authorized" }; 54 - } 55 - 56 - let aturi = new AtUri(uri); 57 - 58 - // Update the record with the new publishedAt date 59 - let updatedRecord: PubLeafletDocument.Record = { 60 - ...record, 61 - publishedAt, 62 - }; 63 - 64 - // Update the record on ATP 65 - let result = await agent.com.atproto.repo.putRecord({ 66 - repo: credentialSession.did!, 67 - rkey: aturi.rkey, 68 - record: updatedRecord, 69 - collection: record.$type, 70 - validate: false, 71 - }); 72 - 73 - // Optimistically write to our db 74 - let { error } = await supabaseServerClient 75 - .from("documents") 76 - .update({ 77 - data: updatedRecord as Json, 78 - }) 79 - .eq("uri", uri); 80 - 81 - if (error) { 82 - return { success: false, error: error.message }; 83 - } 84 - 85 - return { success: true, publishedAt }; 86 - }
+1 -1
actions/publishToPublication.ts
··· 201 201 } 202 202 }), 203 203 publishedAt: 204 - existingRecord?.publishedAt || publishedAt || new Date().toISOString(), 204 + publishedAt || existingRecord?.publishedAt || new Date().toISOString(), 205 205 }; 206 206 207 207 // Keep the same rkey if updating an existing document
+7
app/[leaflet_id]/actions/PublishButton.tsx
··· 95 95 tx.get<string | null>("publication_cover_image"), 96 96 ); 97 97 98 + // Get localPublishedAt from Replicache state 99 + let localPublishedAt = useSubscribe(rep, (tx) => 100 + tx.get<string | null>("publication_local_published_at"), 101 + ); 102 + console.log("local: " + localPublishedAt); 103 + 98 104 return ( 99 105 <ActionButton 100 106 primary ··· 111 117 description: currentDescription, 112 118 tags: currentTags, 113 119 cover_image: coverImage, 120 + ...(localPublishedAt && { publishedAt: localPublishedAt }), 114 121 }); 115 122 setIsLoading(false); 116 123 mutate();
+2 -3
app/[leaflet_id]/publish/PublishPost.tsx
··· 92 92 ); 93 93 94 94 // Use Replicache tags only when we have a draft 95 - const hasDraft = props.hasDraft; 96 - const currentTags = hasDraft 95 + const currentTags = props.hasDraft 97 96 ? Array.isArray(replicacheTags) 98 97 ? replicacheTags 99 98 : [] ··· 101 100 102 101 // Update tags via Replicache mutation or local state depending on context 103 102 const handleTagsChange = async (newTags: string[]) => { 104 - if (hasDraft) { 103 + if (props.hasDraft) { 105 104 await rep?.mutate.updatePublicationDraft({ 106 105 tags: newTags, 107 106 });
+22 -5
components/Pages/Backdater.tsx
··· 4 4 import { timeAgo } from "src/utils/timeAgo"; 5 5 import { Popover } from "components/Popover"; 6 6 import { Separator } from "react-aria-components"; 7 + import { useReplicache } from "src/replicache"; 7 8 8 9 export const Backdater = (props: { publishedAt: string }) => { 10 + let { rep } = useReplicache(); 9 11 let [localPublishedAt, setLocalPublishedAt] = useState( 10 12 new Date(props.publishedAt), 11 13 ); ··· 16 18 17 19 let currentTime = `${new Date().getHours().toString().padStart(2, "0")}:${new Date().getMinutes().toString().padStart(2, "0")}`; 18 20 19 - const handleTimeChange = (time: string) => { 21 + const handleTimeChange = async (time: string) => { 20 22 setTimeValue(time); 21 23 const [hours, minutes] = time.split(":").map((str) => parseInt(str, 10)); 22 24 const newDate = new Date(localPublishedAt); ··· 27 29 if (newDate > currentDate) { 28 30 setLocalPublishedAt(currentDate); 29 31 setTimeValue(currentTime); 30 - } else setLocalPublishedAt(newDate); 32 + await rep?.mutate.updatePublicationDraft({ 33 + localPublishedAt: currentDate.toISOString(), 34 + }); 35 + } else { 36 + setLocalPublishedAt(newDate); 37 + await rep?.mutate.updatePublicationDraft({ 38 + localPublishedAt: newDate.toISOString(), 39 + }); 40 + } 31 41 }; 32 42 33 - const handleDateChange = (date: Date | undefined) => { 43 + const handleDateChange = async (date: Date | undefined) => { 34 44 if (!date) return; 35 45 const [hours, minutes] = timeValue 36 46 .split(":") ··· 43 53 if (newDate > currentDate) { 44 54 setLocalPublishedAt(currentDate); 45 55 setTimeValue(currentTime); 46 - } else setLocalPublishedAt(newDate); 56 + await rep?.mutate.updatePublicationDraft({ 57 + localPublishedAt: currentDate.toISOString(), 58 + }); 59 + } else { 60 + setLocalPublishedAt(newDate); 61 + await rep?.mutate.updatePublicationDraft({ 62 + localPublishedAt: newDate.toISOString(), 63 + }); 64 + } 47 65 }; 48 - console.log(localPublishedAt); 49 66 50 67 return ( 51 68 <Popover
+4 -2
src/replicache/mutations.ts
··· 637 637 description?: string; 638 638 tags?: string[]; 639 639 cover_image?: string | null; 640 + localPublishedAt?: string | null; 640 641 }> = async (args, ctx) => { 641 642 await ctx.runOnServer(async (serverCtx) => { 642 643 console.log("updating"); ··· 670 671 } 671 672 }); 672 673 await ctx.runOnClient(async ({ tx }) => { 673 - if (args.title !== undefined) 674 - await tx.set("publication_title", args.title); 674 + if (args.title !== undefined) await tx.set("publication_title", args.title); 675 675 if (args.description !== undefined) 676 676 await tx.set("publication_description", args.description); 677 677 if (args.tags !== undefined) await tx.set("publication_tags", args.tags); 678 678 if (args.cover_image !== undefined) 679 679 await tx.set("publication_cover_image", args.cover_image); 680 + if (args.localPublishedAt !== undefined) 681 + await tx.set("publication_local_published_at", args.localPublishedAt); 680 682 }); 681 683 }; 682 684