a tool for shared writing and social publishing

updates to toggle, added post options to pub settings, updates build script so lexgen works on mac

+185 -71
+84 -9
app/lish/[did]/[publication]/dashboard/settings/PostOptions.tsx
··· 1 + import { PubLeafletPublication } from "lexicons/api"; 2 + import { usePublicationData } from "../PublicationSWRProvider"; 1 3 import { PubSettingsHeader } from "./PublicationSettings"; 4 + import { useState } from "react"; 5 + import { Toggle } from "components/Toggle"; 6 + import { updatePublication } from "app/lish/createPub/updatePublication"; 7 + import { useToaster } from "components/Toast"; 8 + import { mutate } from "swr"; 2 9 3 10 export const PostOptions = (props: { 4 11 backToMenu: () => void; 5 12 loading: boolean; 6 13 setLoading: (l: boolean) => void; 7 14 }) => { 15 + let { data } = usePublicationData(); 16 + 17 + let { publication: pubData } = data || {}; 18 + let record = pubData?.record as PubLeafletPublication.Record; 19 + 20 + let [showComments, setShowComments] = useState( 21 + record?.preferences?.showComments === undefined 22 + ? true 23 + : record.preferences.showComments, 24 + ); 25 + let [showMentions, setShowMentions] = useState(true); 26 + let [showPrevNext, setShowPrevNext] = useState(true); 27 + 28 + let toast = useToaster(); 8 29 return ( 9 - <div className="text-primary flex flex-col"> 30 + <form 31 + onSubmit={async (e) => { 32 + if (!pubData) return; 33 + e.preventDefault(); 34 + props.setLoading(true); 35 + let data = await updatePublication({ 36 + uri: pubData.uri, 37 + name: nameValue, 38 + description: descriptionValue, 39 + iconFile: iconFile, 40 + preferences: { 41 + showInDiscover: showInDiscover, 42 + showComments: showComments, 43 + }, 44 + }); 45 + toast({ type: "success", content: "Posts Updated!" }); 46 + props.setLoading(false); 47 + mutate("publication-data"); 48 + }} 49 + className="text-primary flex flex-col" 50 + > 10 51 <PubSettingsHeader 11 52 loading={props.loading} 12 53 setLoadingAction={props.setLoading} ··· 15 56 > 16 57 Post Options 17 58 </PubSettingsHeader> 18 - <h4>Layout</h4> 19 - <div>Post Width</div> 20 - <div>Show Prev Next Buttons</div> 21 - <hr /> 22 - <h4>Interactions</h4> 23 - <div>Show Comments</div> 24 - <div>Show Mentions</div> 25 - </div> 59 + <h4 className="mb-1">Layout</h4> 60 + <div>Max Post Width</div> 61 + <Toggle 62 + toggle={showPrevNext} 63 + onToggle={() => { 64 + setShowPrevNext(!showPrevNext); 65 + }} 66 + > 67 + <div className="flex flex-col justify-start"> 68 + <div className="font-bold">Show Prev/Next Buttons</div> 69 + <div className="text-tertiary text-sm leading-tight"> 70 + Show buttons that navigate to the previous and next posts 71 + </div> 72 + </div> 73 + </Toggle> 74 + <hr className="my-2 border-border-light" /> 75 + <h4 className="mb-1">Interactions</h4> 76 + <div className="flex flex-col gap-2"> 77 + <Toggle 78 + toggle={showComments} 79 + onToggle={() => { 80 + setShowComments(!showComments); 81 + }} 82 + > 83 + <div className="font-bold">Show Comments</div> 84 + </Toggle> 85 + 86 + <Toggle 87 + toggle={showMentions} 88 + onToggle={() => { 89 + setShowMentions(!showMentions); 90 + }} 91 + > 92 + <div className="flex flex-col justify-start"> 93 + <div className="font-bold">Show Mentions</div> 94 + <div className="text-tertiary text-sm leading-tight"> 95 + Display a list of posts on Bluesky that mention your post 96 + </div> 97 + </div> 98 + </Toggle> 99 + </div> 100 + </form> 26 101 ); 27 102 };
+12 -18
components/ThemeManager/Pickers/PageThemePickers.tsx
··· 394 394 395 395 return ( 396 396 <> 397 - <div className="flex gap-2 items-center"> 398 - <Toggle 399 - toggleOn={!pageBorderHidden} 400 - setToggleOn={() => { 401 - handleToggle(); 402 - }} 403 - disabledColor1="#8C8C8C" 404 - disabledColor2="#DBDBDB" 405 - /> 406 - <button 407 - className="flex gap-2 items-center" 408 - onClick={() => { 409 - handleToggle(); 410 - }} 411 - > 397 + <Toggle 398 + toggle={!pageBorderHidden} 399 + onToggle={() => { 400 + handleToggle(); 401 + }} 402 + disabledColor1="#8C8C8C" 403 + disabledColor2="#DBDBDB" 404 + > 405 + <div className="flex gap-2"> 412 406 <div className="font-bold">Page Background</div> 413 407 <div className="italic text-[#8C8C8C]"> 414 - {pageBorderHidden ? "hidden" : ""} 408 + {pageBorderHidden ? "none" : ""} 415 409 </div> 416 - </button> 417 - </div> 410 + </div> 411 + </Toggle> 418 412 </> 419 413 ); 420 414 };
+8 -13
components/ThemeManager/PubPickers/PubBackgroundPickers.tsx
··· 95 95 <hr className="border-border-light" /> 96 96 <div className="flex gap-2 items-center"> 97 97 <Toggle 98 - toggleOn={props.hasPageBackground} 99 - setToggleOn={() => { 98 + toggle={props.hasPageBackground} 99 + onToggle={() => { 100 100 props.setHasPageBackground(!props.hasPageBackground); 101 101 props.hasPageBackground && 102 102 props.openPicker === "page" && ··· 104 104 }} 105 105 disabledColor1="#8C8C8C" 106 106 disabledColor2="#DBDBDB" 107 - /> 108 - <button 109 - className="flex gap-2 items-center" 110 - onClick={() => { 111 - props.setHasPageBackground(!props.hasPageBackground); 112 - props.hasPageBackground && props.setOpenPicker("null"); 113 - }} 114 107 > 115 - <div className="font-bold">Page Background</div> 116 - <div className="italic text-[#8C8C8C]"> 117 - {props.hasPageBackground ? "" : "hidden"} 108 + <div className="flex gap-2"> 109 + <div className="font-bold">Page Background</div> 110 + <div className="italic text-[#8C8C8C]"> 111 + {props.hasPageBackground ? "" : "none"} 112 + </div> 118 113 </div> 119 - </button> 114 + </Toggle> 120 115 </div> 121 116 </> 122 117 );
+4 -10
components/ThemeManager/ThemeSetter.tsx
··· 220 220 return ( 221 221 <div className="flex gap-2 items-start mt-0.5"> 222 222 <Toggle 223 - toggleOn={!!checked?.data.value} 224 - setToggleOn={() => { 223 + toggle={!!checked?.data.value} 224 + onToggle={() => { 225 225 handleToggle(); 226 226 }} 227 227 disabledColor1="#8C8C8C" 228 228 disabledColor2="#DBDBDB" 229 - /> 230 - <button 231 - className="flex gap-2 items-center -mt-0.5" 232 - onClick={() => { 233 - handleToggle(); 234 - }} 235 229 > 236 - <div className="flex flex-col gap-0 items-start"> 230 + <div className="flex flex-col gap-0 items-start "> 237 231 <div className="font-bold">Show Leaflet Watermark</div> 238 232 <div className="text-sm text-[#969696]">Help us spread the word!</div> 239 233 </div> 240 - </button> 234 + </Toggle> 241 235 </div> 242 236 ); 243 237 }
+32 -20
components/Toggle.tsx
··· 1 1 import { theme } from "tailwind.config"; 2 2 3 3 export const Toggle = (props: { 4 - toggleOn: boolean; 5 - setToggleOn: (s: boolean) => void; 4 + toggle: boolean; 5 + onToggle: () => void; 6 6 disabledColor1?: string; 7 7 disabledColor2?: string; 8 + children: React.ReactNode; 8 9 }) => { 9 10 return ( 10 11 <button 11 - className="toggle selected-outline transparent-outline flex items-center h-[20px] w-6 rounded-md border-border" 12 - style={{ 13 - border: props.toggleOn 14 - ? "1px solid " + theme.colors["accent-2"] 15 - : "1px solid " + props.disabledColor2 || theme.colors["border-light"], 16 - justifyContent: props.toggleOn ? "flex-end" : "flex-start", 17 - background: props.toggleOn 18 - ? theme.colors["accent-1"] 19 - : props.disabledColor1 || theme.colors["tertiary"], 12 + type="button" 13 + className="toggle flex gap-2 items-start justify-start text-left" 14 + onClick={() => { 15 + props.onToggle(); 20 16 }} 21 - onClick={() => props.setToggleOn(!props.toggleOn)} 22 17 > 23 - <div 24 - className="h-[14px] w-[10px] m-0.5 rounded-[2px]" 25 - style={{ 26 - background: props.toggleOn 27 - ? theme.colors["accent-2"] 28 - : props.disabledColor2 || theme.colors["border-light"], 29 - }} 30 - /> 18 + <div className="h-6 flex place-items-center"> 19 + <div 20 + className="selected-outline transparent-outline flex items-center h-[20px] w-6 rounded-md border-border" 21 + style={{ 22 + border: props.toggle 23 + ? "1px solid " + theme.colors["accent-2"] 24 + : "1px solid " + props.disabledColor2 || 25 + theme.colors["border-light"], 26 + justifyContent: props.toggle ? "flex-end" : "flex-start", 27 + background: props.toggle 28 + ? theme.colors["accent-1"] 29 + : props.disabledColor1 || theme.colors["tertiary"], 30 + }} 31 + > 32 + <div 33 + className="h-[14px] w-[10px] m-0.5 rounded-[2px]" 34 + style={{ 35 + background: props.toggle 36 + ? theme.colors["accent-2"] 37 + : props.disabledColor2 || theme.colors["border-light"], 38 + }} 39 + /> 40 + </div> 41 + </div> 42 + {props.children} 31 43 </button> 32 44 ); 33 45 };
+44
lexicons/fix-extensions.ts
··· 1 + import * as fs from "fs"; 2 + import * as path from "path"; 3 + 4 + /** 5 + * Recursively processes all files in a directory and removes .js extensions from imports 6 + */ 7 + function fixExtensionsInDirectory(dir: string): void { 8 + const entries = fs.readdirSync(dir, { withFileTypes: true }); 9 + 10 + for (const entry of entries) { 11 + const fullPath = path.join(dir, entry.name); 12 + 13 + if (entry.isDirectory()) { 14 + fixExtensionsInDirectory(fullPath); 15 + } else if (entry.isFile() && (entry.name.endsWith(".ts") || entry.name.endsWith(".js"))) { 16 + fixExtensionsInFile(fullPath); 17 + } 18 + } 19 + } 20 + 21 + /** 22 + * Removes .js extensions from import/export statements in a file 23 + */ 24 + function fixExtensionsInFile(filePath: string): void { 25 + const content = fs.readFileSync(filePath, "utf-8"); 26 + const fixedContent = content.replace(/\.js'/g, "'"); 27 + 28 + if (content !== fixedContent) { 29 + fs.writeFileSync(filePath, fixedContent, "utf-8"); 30 + console.log(`Fixed: ${filePath}`); 31 + } 32 + } 33 + 34 + // Get the directory to process from command line arguments 35 + const targetDir = process.argv[2] || "./lexicons/api"; 36 + 37 + if (!fs.existsSync(targetDir)) { 38 + console.error(`Directory not found: ${targetDir}`); 39 + process.exit(1); 40 + } 41 + 42 + console.log(`Fixing extensions in: ${targetDir}`); 43 + fixExtensionsInDirectory(targetDir); 44 + console.log("Done!");
+1 -1
package.json
··· 7 7 "dev": "TZ=UTC next dev --turbo", 8 8 "publish-lexicons": "tsx lexicons/publish.ts", 9 9 "generate-db-types": "supabase gen types --local > supabase/database.types.ts && drizzle-kit introspect && rm -rf ./drizzle/*.sql ./drizzle/meta", 10 - "lexgen": "tsx ./lexicons/build.ts && lex gen-api ./lexicons/api ./lexicons/pub/leaflet/document.json ./lexicons/pub/leaflet/comment.json ./lexicons/pub/leaflet/publication.json ./lexicons/pub/leaflet/*/* ./lexicons/com/atproto/*/* ./lexicons/app/bsky/*/* --yes && find './lexicons/api' -type f -exec sed -i 's/\\.js'/'/g' {} \\;", 10 + "lexgen": "tsx ./lexicons/build.ts && lex gen-api ./lexicons/api ./lexicons/pub/leaflet/document.json ./lexicons/pub/leaflet/comment.json ./lexicons/pub/leaflet/publication.json ./lexicons/pub/leaflet/*/* ./lexicons/com/atproto/*/* ./lexicons/app/bsky/*/* --yes && tsx ./lexicons/fix-extensions.ts ./lexicons/api", 11 11 "wrangler-dev": "wrangler dev", 12 12 "build-appview": "esbuild appview/index.ts --outfile=appview/dist/index.js --bundle --platform=node", 13 13 "build-feed-service": "esbuild feeds/index.ts --outfile=feeds/dist/index.js --bundle --platform=node",