Schedule posts to Bluesky with Cloudflare workers. skyscheduler.work
cf tool bsky-tool cloudflare bluesky schedule bsky service social-media cloudflare-workers

add more titles on sidebar buttons

for accessibility

+20 -24
+5 -3
assets/js/repostHelper.js
··· 115 115 if (contentTabs !== null) { 116 116 contentTabs.switchTab("dashtabs", 1); 117 117 scrollToObject(repostRecordURL); 118 - // set current time to value of now. 119 - document.getElementById("repostTime").value = convertTimeValueLocally(Date.now()); 118 + // set current time to value of now + 1 hour 119 + const curDate = new Date(); 120 + curDate.setHours(curDate.getHours() + 1); 121 + document.getElementById("repostTime").value = convertTimeValueLocally(curDate); 120 122 return; 121 123 } 122 124 } 123 - console.warn("could not find valid repost target"); 125 + pushToast("cannot add reposts to this post", false); 124 126 }); 125 127 126 128
+1 -6
assets/logo.svg
··· 1 1 <?xml version="1.0" encoding="UTF-8"?> 2 - <svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"> 3 - <path class="cls-1" fill="#80b3e0" d="M512,307.73c0-57.89-46.93-104.82-104.81-104.82-2.69,0-5.37.1-8.01.3-10.59-59.01-62.19-103.8-124.25-103.8-54.49,0-100.91,34.52-118.6,82.88-7.61-3.13-15.94-4.86-24.68-4.86-35.92,0-65.04,29.12-65.04,65.04,0,.73.03,1.46.06,2.19C28.54,253.02,0,286.97,0,327.6c0,46.3,37.05,83.92,83.11,84.89v.05l344.3.05h.25c48.21-9.43,84.33-53.89,84.33-104.86Z"/> 4 - <path fill="#64a1d7" d="M83.11,412.49v.05h344.29l.34-.03c48.21-9.42,84.25-53.82,84.25-104.79,0-9.3-1.22-18.31-3.49-26.89-60.13,108.31-147.38,45.08-147.38,45.08,0,0-49.7,50.69-103.27,49.19-53.57-1.5-78.58-33.38-78.58-33.38C48.21,401.84,0,327.6,0,327.6c0,46.3,37.05,83.92,83.11,84.89Z"/> 5 - <circle fill="#fff" cx="266.08" cy="279.09" r="110.23"/> 6 - <path fill="#3c5479" d="M338.56,233.6l-17.64-17.6-56.69,56.7-22.05-22.03-17.65,17.57v-.24s-.05.08-.07.12c.02.16,0,.33-.02.49.02.02.04.05.07.07v-.31s39.71,39.71,39.71,39.71l74.37-74.37-.02-.1Z"/> 7 - </svg> 2 + <svg xmlns="http://www.w3.org/2000/svg" id="Layer_1" data-name="Layer 1" viewBox="0 0 512 512"><path fill="#80b3e0" d="M512 307.73c0-57.89-46.93-104.82-104.81-104.82-2.69 0-5.37.1-8.01.3-10.59-59.01-62.19-103.8-124.25-103.8-54.49 0-100.91 34.52-118.6 82.88a64.7 64.7 0 0 0-24.68-4.86c-35.92 0-65.04 29.12-65.04 65.04 0 .73.03 1.46.06 2.19C28.54 253.02 0 286.97 0 327.6c0 46.3 37.05 83.92 83.11 84.89v.05l344.3.05h.25c48.21-9.43 84.33-53.89 84.33-104.86Z" class="cls-1"/><path fill="#64a1d7" d="M83.11 412.49v.05H427.4l.34-.03c48.21-9.42 84.25-53.82 84.25-104.79 0-9.3-1.22-18.31-3.49-26.89-60.13 108.31-147.38 45.08-147.38 45.08s-49.7 50.69-103.27 49.19-78.58-33.38-78.58-33.38C48.21 401.84 0 327.6 0 327.6c0 46.3 37.05 83.92 83.11 84.89"/><circle cx="266.08" cy="279.09" r="110.23" fill="#fff"/><path fill="#3c5479" d="M338.56 233.6 320.92 216l-56.69 56.7-22.05-22.03-17.65 17.57V268s-.05.08-.07.12c.02.16 0 .33-.02.49.02.02.04.05.07.07v-.31l39.71 39.71 74.37-74.37-.02-.1Z"/></svg>
+4 -2
src/layout/posts/buttons.tsx
··· 1 1 // Buttons for post header tags 2 2 export function AddPostToThreadButton() { 3 - return (<button class="addThreadPost btn-sm primary outline" listen="false"> 3 + return (<button class="addThreadPost btn-sm primary outline" listen="false" 4 + title="Add a post underneath this one"> 4 5 <span data-tooltip="Add a post to thread" data-placement="right"> 5 6 <img src="/icons/reply.svg" alt="threaded post icon" width="20px" height="20px" /> 6 7 </span> ··· 8 9 } 9 10 10 11 export function AddRepostsButton() { 11 - return (<button class="addRepostsButton btn-sm primary outline" listen="false"> 12 + return (<button class="addRepostsButton btn-sm primary outline" listen="false" 13 + title="Add additional reposts to this post"> 12 14 <span data-placement="right" data-tooltip="Add reposts"> 13 15 <img src="/icons/add-repost.svg" alt="add reposts icon" width="20px" height="20px" /> 14 16 </span>
+10 -13
src/layout/posts/wrappers.tsx
··· 1 1 import { raw } from "hono/html"; 2 - import isEmpty from "just-is-empty"; 3 2 import { Post } from "../../classes/post"; 4 3 import { AddPostToThreadButton, AddRepostsButton, DeletePostButton, EditPostButton } from "./buttons"; 5 4 import { RepostCountElement, RepostStatusIcon } from "./repostData"; ··· 39 38 export function PostDataFooter(props: PostDataFooterOptions) { 40 39 const content: Post = props.content; 41 40 const hasPosted: boolean = props.posted; 42 - return (<footer> 43 - <small> 44 - <a class="secondary" hidden={!hasPosted} tabindex={hasPosted ? undefined : -1} 45 - data-uri={content.uri} 46 - href={content.getURI() || undefined} 47 - target="_blank" title="link to post">{content.isRepost ? "Repost on" : "Posted on"}</a> 48 - <span hidden={hasPosted}>Scheduled for</span>: 49 - &nbsp;<span class="timestamp">{raw(content.scheduledDate!)}</span> 50 - {content.hasEmbeds() ? ' | Embeds: ' + content.embeds?.length : null} 51 - <RepostCountElement count={content.repostCount} repostInfo={content.repostInfo} /> 52 - </small> 53 - </footer>); 41 + return (<footer><small> 42 + <a class="secondary" hidden={!hasPosted} tabindex={hasPosted ? undefined : -1} 43 + data-uri={content.uri} 44 + href={content.getURI() || undefined} 45 + target="_blank" title="link to post">{content.isRepost ? "Repost on" : "Posted on"}</a> 46 + <span hidden={hasPosted}>Scheduled for</span>: 47 + &nbsp;<span class="timestamp">{raw(content.scheduledDate!)}</span> 48 + {content.hasEmbeds() ? ' | Embeds: ' + content.embeds!.length : null} 49 + <RepostCountElement count={content.repostCount} repostInfo={content.repostInfo} /> 50 + </small></footer>); 54 51 };