a tool for shared writing and social publishing
0
fork

Configure Feed

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

add facet the complicated way to handle overlaps

+118 -3
+118 -3
app/lish/[did]/[publication]/[rkey]/TextBlock.tsx
··· 17 17 let facets = [...(props.facets || [])]; 18 18 if (!props.preview) { 19 19 for (let highlight of highlights) { 20 - facets.push({ 21 - $type: "pub.leaflet.richtext.facet", 20 + facets = addFacet(facets, { 22 21 index: { 23 22 byteStart: highlight.startOffset 24 23 ? new UnicodeString( ··· 33 32 { $type: "pub.leaflet.richtext.facet#highlight" }, 34 33 { 35 34 $type: "pub.leaflet.richtext.facet#id", 36 - id: `${props.index.join(".")}_${highlight.startOffset}`, 35 + id: `${props.index.join(".")}_${highlight.startOffset || 0}`, 37 36 }, 38 37 ], 39 38 }); ··· 146 145 } 147 146 } 148 147 } 148 + 149 + function addFacet(facets: Facet[], facet: Facet) { 150 + // Handle empty facets array 151 + if (facets.length === 0) { 152 + return [facet]; 153 + } 154 + 155 + const newStart = facet.index.byteStart; 156 + const newEnd = facet.index.byteEnd; 157 + 158 + // Find facets that overlap with the new facet 159 + const overlapping: number[] = []; 160 + for (let i = 0; i < facets.length; i++) { 161 + const existing = facets[i]; 162 + const existingStart = existing.index.byteStart; 163 + const existingEnd = existing.index.byteEnd; 164 + 165 + // Check if there's any overlap 166 + if (newEnd > existingStart && newStart < existingEnd) { 167 + overlapping.push(i); 168 + } 169 + } 170 + 171 + // No overlaps - just insert the new facet at the right position 172 + if (overlapping.length === 0) { 173 + // Find the correct position to insert (maintain sorted order) 174 + let insertIndex = facets.length; 175 + for (let i = 0; i < facets.length; i++) { 176 + if (newStart < facets[i].index.byteStart) { 177 + insertIndex = i; 178 + break; 179 + } 180 + } 181 + 182 + let newFacets = [...facets]; 183 + newFacets.splice(insertIndex, 0, facet); 184 + return newFacets; 185 + } 186 + 187 + // Handle overlaps by splitting and merging 188 + const newFacets: Facet[] = []; 189 + let processedUpTo = 0; 190 + 191 + for (let i = 0; i < facets.length; i++) { 192 + const existing = facets[i]; 193 + const existingStart = existing.index.byteStart; 194 + const existingEnd = existing.index.byteEnd; 195 + 196 + // Add non-overlapping facets before the current one 197 + if (!overlapping.includes(i)) { 198 + newFacets.push(existing); 199 + continue; 200 + } 201 + 202 + // Split the existing facet based on overlap with new facet 203 + const overlapStart = Math.max(existingStart, newStart); 204 + const overlapEnd = Math.min(existingEnd, newEnd); 205 + 206 + // Part before overlap 207 + if (existingStart < overlapStart) { 208 + newFacets.push({ 209 + index: { 210 + byteStart: existingStart, 211 + byteEnd: overlapStart, 212 + }, 213 + features: [...existing.features], 214 + }); 215 + } 216 + 217 + // Overlapping part - merge features 218 + newFacets.push({ 219 + index: { 220 + byteStart: overlapStart, 221 + byteEnd: overlapEnd, 222 + }, 223 + features: [...existing.features, ...facet.features], 224 + }); 225 + 226 + // Part after overlap 227 + if (overlapEnd < existingEnd) { 228 + newFacets.push({ 229 + index: { 230 + byteStart: overlapEnd, 231 + byteEnd: existingEnd, 232 + }, 233 + features: [...existing.features], 234 + }); 235 + } 236 + 237 + // Track what part of the new facet we've processed 238 + if (newStart < overlapStart && processedUpTo < overlapStart) { 239 + // Add the part of new facet before this overlap 240 + newFacets.push({ 241 + index: { 242 + byteStart: newStart, 243 + byteEnd: overlapStart, 244 + }, 245 + features: [...facet.features], 246 + }); 247 + } 248 + processedUpTo = overlapEnd; 249 + } 250 + 251 + // Add any remaining part of the new facet after all overlaps 252 + if (processedUpTo < newEnd) { 253 + newFacets.push({ 254 + index: { 255 + byteStart: processedUpTo, 256 + byteEnd: newEnd, 257 + }, 258 + features: [...facet.features], 259 + }); 260 + } 261 + 262 + return newFacets.sort((a, b) => a.index.byteStart - b.index.byteStart); 263 + }