a tool for shared writing and social publishing
0
fork

Configure Feed

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

make static quote buttons for ios

Squashed commit of the following:

commit 4105f65911ba98d59b7a3223c98707417d9b00e4
Author: Jared Pereira <jared@awarm.space>
Date: Tue Aug 26 16:07:00 2025 +0900

make quote buttons static to work on ios

+43 -49
+43 -49
app/lish/[did]/[publication]/[rkey]/QuoteHandler.tsx
··· 7 7 import { useInteractionState } from "./Interactions/Interactions"; 8 8 import { encodeQuotePosition } from "./useHighlight"; 9 9 import { useParams } from "next/navigation"; 10 + import { decodeQuotePosition, QuotePosition } from "./quotePosition"; 10 11 11 12 export function QuoteHandler() { 12 - let [position, setPosition] = useState<{ top: number; left: number } | null>( 13 - null, 14 - ); 13 + let [position, setPosition] = useState<{ 14 + top: number; 15 + left: number; 16 + position: string; 17 + } | null>(null); 15 18 useEffect(() => { 16 19 const handleSelectionChange = (e: Event) => { 17 20 const selection = document.getSelection(); ··· 40 43 } 41 44 42 45 let dir = selection.direction; 46 + const range = selection.getRangeAt(0); 43 47 if (!dir) { 44 - const range = selection.getRangeAt(0); 45 48 const startContainer = range.startContainer; 46 49 const endContainer = range.endContainer; 47 50 const startOffset = range.startOffset; ··· 65 68 selectionTop += quoteRect.height + 8; 66 69 } 67 70 71 + let startIndex = findDataIndex(range.startContainer); 72 + let endIndex = findDataIndex(range.endContainer); 73 + if (!startIndex || !endIndex) return; 74 + let startOffset = calculateOffsetFromDataParent( 75 + range.startContainer, 76 + range.startOffset, 77 + startIndex?.element, 78 + ); 79 + let endOffset = calculateOffsetFromDataParent( 80 + range.endContainer, 81 + range.endOffset, 82 + endIndex?.element, 83 + ); 84 + let position: QuotePosition = { 85 + start: { 86 + block: startIndex?.index.split(".").map(parseInt), 87 + offset: startOffset, 88 + }, 89 + end: { 90 + block: endIndex.index.split(".").map(parseInt), 91 + offset: endOffset, 92 + }, 93 + }; 68 94 setPosition({ 69 95 top: selectionTop, 70 96 left: selectionLeft, 97 + position: encodeQuotePosition(position), 71 98 }); 72 99 }; 73 100 ··· 88 115 left: position.left, 89 116 }} 90 117 > 91 - <QuoteOptionButtons /> 118 + <QuoteOptionButtons position={position.position} /> 92 119 </div> 93 120 ); 94 121 } 95 122 } 96 123 97 - export const QuoteOptionButtons = () => { 124 + export const QuoteOptionButtons = (props: { position: string }) => { 98 125 let smoker = useSmoker(); 99 - const getURL = () => { 100 - let selection = document.getSelection()?.getRangeAt(0); 101 - if (!selection) return; 102 - let startResult = findDataIndex(selection.startContainer); 103 - let endResult = findDataIndex(selection.endContainer); 104 - if (!startResult || !endResult) return; 105 - 106 - let startOffset = calculateOffsetFromDataParent( 107 - selection.startContainer, 108 - selection.startOffset, 109 - startResult.element, 110 - ); 111 - let endOffset = calculateOffsetFromDataParent( 112 - selection.endContainer, 113 - selection.endOffset, 114 - endResult.element, 115 - ); 116 - 117 - let quotePosition = encodeQuotePosition({ 118 - start: { 119 - block: startResult.index.split(".").map((i) => parseInt(i)), 120 - offset: startOffset, 121 - }, 122 - end: { 123 - block: endResult.index.split(".").map((i) => parseInt(i)), 124 - offset: endOffset, 125 - }, 126 - }); 126 + let url = useMemo(() => { 127 127 let currentUrl = new URL(window.location.href); 128 + let pos = decodeQuotePosition(props.position); 128 129 if (currentUrl.pathname.includes("/l-quote/")) { 129 130 currentUrl.pathname = currentUrl.pathname.split("/l-quote/")[0]; 130 131 } 131 - currentUrl.pathname = currentUrl.pathname + `/l-quote/${quotePosition}`; 132 + currentUrl.pathname = currentUrl.pathname + `/l-quote/${props.position}`; 132 133 133 - currentUrl.hash = `#${startResult.index}_${startOffset}`; 134 + currentUrl.hash = `#${pos?.start.block.join(".")}_${pos?.start.offset}`; 134 135 return currentUrl.toString(); 135 - }; 136 + }, [props.position]); 136 137 137 138 return ( 138 139 <> 139 140 <div className="">Share Quote via</div> 140 141 141 - <button 142 + <a 142 143 className="flex gap-1 items-center hover:font-bold p-1" 143 144 role="link" 144 - onClick={() => { 145 - let url = getURL(); 146 - if (!url) return; 147 - window.open( 148 - `https://bsky.app/intent/compose?text=${encodeURIComponent(url.toString())}`, 149 - "_blank", 150 - ); 151 - }} 145 + href={`https://bsky.app/intent/compose?text=${encodeURIComponent(url)}`} 146 + target="_blank" 152 147 > 153 148 <BlueskyLinkTiny className="shrink-0" /> 154 149 Bluesky 155 - </button> 150 + </a> 156 151 <Separator classname="h-3" /> 157 152 <button 158 153 id="copy-quote-link" ··· 161 156 let rect = document 162 157 .getElementById("copy-quote-link") 163 158 ?.getBoundingClientRect(); 164 - let url = getURL(); 165 159 if (!url) return; 166 - navigator.clipboard.writeText(url.toString()); 160 + navigator.clipboard.writeText(url); 167 161 168 162 smoker({ 169 163 text: <strong>Copied Link</strong>,