a tool for shared writing and social publishing
0

Configure Feed

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

updates to leaflet to accomodate sidebar changes

celine (May 1, 2026, 4:41 PM EDT) 55119ef2 3812a658

+69 -25
+16 -4
app/[leaflet_id]/Footer.tsx
··· 6 6 import { Toolbar } from "components/Toolbar"; 7 7 import { FootnoteToolbar } from "components/Toolbar/FootnoteToolbarWrapper"; 8 8 import { ShareOptions } from "app/[leaflet_id]/actions/ShareOptions"; 9 - import { HomeButton } from "app/[leaflet_id]/actions/HomeButton"; 9 + import { 10 + AddToHomeButton, 11 + HomeButton, 12 + } from "app/[leaflet_id]/actions/HomeButton"; 10 13 import { PublishButton } from "./actions/PublishButton"; 11 14 import { useEntitySetContext } from "components/EntitySetProvider"; 12 15 import { Watermark } from "components/Watermark"; 13 16 import { BackToPubButton } from "./actions/BackToPubButton"; 14 17 import { useLeafletPublicationData } from "components/PageSWRDataProvider"; 15 18 import { useIdentityData } from "components/IdentityProvider"; 16 - import { useEntity } from "src/replicache"; 19 + import { useEntity, useReplicache } from "src/replicache"; 17 20 import { block } from "sharp"; 18 21 import { PostSettings } from "components/PostSettings"; 19 22 ··· 29 32 } 30 33 export function LeafletFooter(props: { entityID: string }) { 31 34 let focusedBlock = useUIState((s) => s.focusedEntity); 32 - 33 35 let entity_set = useEntitySetContext(); 34 36 let { identity } = useIdentityData(); 37 + let { permission_token } = useReplicache(); 35 38 let { data: pub } = useLeafletPublicationData(); 36 39 let blockType = useEntity(focusedBlock?.entityID || null, "block/type")?.data 37 40 .value; ··· 77 80 ) : ( 78 81 <HomeButton /> 79 82 )} 83 + 80 84 <div className="mobileLeafletActions flex gap-2 shrink-0"> 81 - <PublishButton entityID={props.entityID} /> 85 + {identity && 86 + !identity.permission_token_on_homepage.find( 87 + (pth) => pth.permission_tokens.id === permission_token.id, 88 + ) ? ( 89 + <AddToHomeButton primary /> 90 + ) : ( 91 + <PublishButton entityID={props.entityID} /> 92 + )} 93 + 82 94 <ShareOptions /> 83 95 <PostSettings /> 84 96 <ThemePopover entityID={props.entityID} />
+15 -3
app/[leaflet_id]/Sidebar.tsx
··· 2 2 import { Sidebar } from "components/ActionBar/Sidebar"; 3 3 import { useEntitySetContext } from "components/EntitySetProvider"; 4 4 import { HelpButton } from "app/[leaflet_id]/actions/HelpButton"; 5 - import { HomeButton } from "app/[leaflet_id]/actions/HomeButton"; 5 + import { 6 + AddToHomeButton, 7 + HomeButton, 8 + } from "app/[leaflet_id]/actions/HomeButton"; 6 9 import { Media } from "components/Media"; 7 10 import { useLeafletPublicationData } from "components/PageSWRDataProvider"; 8 11 import { ShareOptions } from "app/[leaflet_id]/actions/ShareOptions"; ··· 19 22 let { rootEntity } = useReplicache(); 20 23 let { data: pub } = useLeafletPublicationData(); 21 24 let { identity } = useIdentityData(); 25 + let { permission_token } = useReplicache(); 22 26 23 27 return ( 24 28 <Media mobile={false} className="w-0 h-full relative"> ··· 28 32 > 29 33 <div className="sidebarContainer flex flex-col justify-end h-full w-16 relative"> 30 34 {entity_set.permissions.write && ( 31 - <Sidebar> 32 - <PublishButton entityID={rootEntity} /> 35 + <Sidebar className="my-0!"> 36 + {identity && 37 + !identity.permission_token_on_homepage.find( 38 + (pth) => pth.permission_tokens.id === permission_token.id, 39 + ) ? ( 40 + <AddToHomeButton /> 41 + ) : ( 42 + <PublishButton entityID={rootEntity} /> 43 + )} 44 + 33 45 <ShareOptions /> 34 46 <PostSettings /> 35 47 <ThemePopover entityID={rootEntity} />
+7 -11
app/[leaflet_id]/actions/HomeButton.tsx
··· 23 23 className="hover:no-underline" 24 24 style={{ textDecorationLine: "none !important" }} 25 25 > 26 - <ActionButton icon={<HomeSmall />} label="Go Home" /> 26 + <ActionButton icon={<HomeSmall />} label="Back Home" /> 27 27 </Link> 28 - {<AddToHomeButton />} 29 28 </> 30 29 ); 31 30 } 32 31 33 - const AddToHomeButton = (props: {}) => { 32 + export const AddToHomeButton = (props: { primary?: boolean }) => { 34 33 let { permission_token } = useReplicache(); 35 34 let { identity, mutate } = useIdentityData(); 36 35 let smoker = useSmoker(); 37 - if ( 38 - identity?.permission_token_on_homepage.find( 39 - (pth) => pth.permission_tokens.id === permission_token.id, 40 - ) || 41 - !identity 42 - ) 43 - return null; 36 + 44 37 return ( 45 38 <ActionButton 39 + primary 40 + labelOnMobile 41 + className="sm:w-full! w-fit!" 46 42 onClick={async (e) => { 47 43 await addLeafletToHome(permission_token.id); 48 44 mutate((identity) => { ··· 68 64 }); 69 65 }} 70 66 icon={<AddToHomeSmall />} 71 - label="Add to Home" 67 + label="Save to Home" 72 68 /> 73 69 ); 74 70 };
+6
app/[leaflet_id]/actions/PublishButton.tsx
··· 52 52 return ( 53 53 <ActionButton 54 54 primary 55 + labelOnMobile 56 + className="w-fit!" 55 57 icon={<PublishSmall className="shrink-0" />} 56 58 label={"Publish!"} 57 59 onClick={() => { ··· 116 118 return ( 117 119 <ActionButton 118 120 primary 121 + className="w-fit!" 122 + labelOnMobile 119 123 icon={<PublishSmall className="shrink-0" />} 120 124 label={isLoading ? <DotLoader /> : "Update!"} 121 125 onClick={async () => { ··· 192 196 trigger={ 193 197 <ActionButton 194 198 primary 199 + className="w-fit!" 200 + labelOnMobile 195 201 icon={<PublishSmall className="shrink-0" />} 196 202 label={"Publish"} 197 203 />
+2
app/[leaflet_id]/actions/ShareOptions/index.tsx
··· 63 63 trigger={ 64 64 <ActionButton 65 65 icon=<ShareSmall /> 66 + className="sm:w-full! w-fit!" 66 67 secondary 67 68 label={`Share ${pub ? "Draft" : ""}`} 69 + labelOnMobile 68 70 /> 69 71 } 70 72 >
+2 -1
components/ActionBar/ActionButton.tsx
··· 52 52 {...buttonProps} 53 53 ref={ref} 54 54 className={` 55 - actionButton relative 55 + actionButton relative shrink-0 56 + h-fit 56 57 rounded-md border 57 58 py-0.5 px-1 58 59 flex gap-2 items-start justify-start
+1 -1
components/ActionBar/Publications.tsx
··· 67 67 <ActionButton 68 68 labelOnMobile 69 69 icon=<div className="group-hover/new-pub:border-accent-contrast m-0.5 w-5 h-5 border-border border-2 border-dashed rounded-full" /> 70 - label="New" 70 + label="New Publication" 71 71 className="text-tertiary!" 72 72 /> 73 73 </SpeedyLink>
+13 -4
components/ActionBar/Sidebar.tsx
··· 36 36 }} 37 37 > 38 38 <div 39 - style={{ height: "-webkit-fill-available" }} 39 + style={ 40 + props.alwaysOpen 41 + ? { height: "-webkit-fill-available" } 42 + : { height: "fit-content" } 43 + } 40 44 className={` 41 45 actionSidebar 42 - ${!props.alwaysOpen ? "absolute top-0 left-0 z-10 w-max" : "w-56"} 43 - p-[6px] my-6 46 + 47 + ${ 48 + !props.alwaysOpen 49 + ? ` w-max hover:w-48 absolute top-0 left-0 z-10 opaque-container` 50 + : `my-6 w-56 ${cardBorderHidden ? "light-container" : "frosted-container"}` 51 + } 52 + p-[6px] 44 53 flex flex-col gap-0.5 justify-start border 45 - rounded-md ${cardBorderHidden ? "light-container" : "frosted-container"} 54 + rounded-md 46 55 ${props.className} 47 56 `} 48 57 onMouseOver={() => {
+7 -1
components/ThemeManager/ThemeSetter.tsx
··· 65 65 asChild 66 66 side={isMobile ? "top" : "right"} 67 67 align={isMobile ? "center" : "start"} 68 - trigger={<ActionButton secondary icon={<PaintSmall />} label="Theme" />} 68 + trigger={ 69 + <ActionButton 70 + icon={<PaintSmall />} 71 + label="Theme" 72 + className="sm:w-full! w-fit!" 73 + /> 74 + } 69 75 > 70 76 <ThemeSetterContent {...props} /> 71 77 </Popover>