draw things doodl.waow.tech
draw atproto
0

Configure Feed

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

explore: mark remixes quietly + credit the original artist

a remixed drawing now reads as one at a glance, in the zds register (subtle
color-mix accent-tinted edge, muted micro-credit — no loud borders):
- the card gets a faint accent-tinted border
- a credit line under the handle shows the ORIGINAL artist (root of the chain,
resolved lazily so the grid never waits), linking to their drawing
- the remix mark is the viewer's own `remix` slot drawing — redraw everything;
it's the same mark as the remix button, defaulting to its label otherwise

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

+34 -2
+3
src/explore.ts
··· 21 21 imageUrl: string; 22 22 avatar?: string; 23 23 createdAt?: string; 24 + parentUri?: string; // present if this drawing is a remix 24 25 }; 25 26 26 27 // batch-resolve avatars via typeahead's getProfiles (handles tangled + bsky, ··· 52 53 image?: { ref?: { $link?: string } }; 53 54 createdAt?: string; 54 55 prefs?: PrefMap; 56 + parent?: { uri?: string }; 55 57 }; 56 58 time_us?: number; 57 59 }; ··· 141 143 rkey: rec.rkey, 142 144 avatar: avatars.get(rec.did), 143 145 createdAt: rec.record?.createdAt, 146 + parentUri: rec.record?.parent?.uri, 144 147 imageUrl: `${who.pds}/xrpc/com.atproto.sync.getBlob?did=${rec.did}&cid=${cid}`, 145 148 } as LogoItem; 146 149 })
+20 -2
src/main.ts
··· 26 26 type PrefMap, 27 27 type PrefKey, 28 28 } from "./prefs"; 29 - import { REMIX } from "./lineage"; 29 + import { REMIX, resolveLineage } from "./lineage"; 30 30 import { fetchGallery } from "./explore"; 31 31 import { mountLogin } from "./login"; 32 32 import { getMode, setMode, type ThemeMode } from "./theme"; ··· 516 516 who.className = "who"; 517 517 who.textContent = `@${l.handle}`; 518 518 519 + // remix: a quiet accent-tinted card + the viewer's own drawn remix mark 520 + // and the original artist, credited at a glance. lineage resolves lazily 521 + // so the grid never waits on it. 522 + let credit: HTMLAnchorElement | null = null; 523 + if (l.parentUri) { 524 + card.classList.add("remix"); 525 + credit = el("a", { class: "remix-credit" }, [slotNode("remix")]); 526 + credit.addEventListener("click", (e) => e.stopPropagation()); 527 + resolveLineage({ value: { parent: { uri: l.parentUri } } }) 528 + .then((chain) => { 529 + const orig = chain[chain.length - 1]; 530 + if (!orig || !credit) return; 531 + credit.href = `${location.origin}/l/${orig.did}/${orig.rkey}`; 532 + credit.append(` @${orig.handle}`); 533 + }) 534 + .catch(() => {}); 535 + } 536 + 519 537 // subtle corner actions, top-right, never covering the handle 520 538 const actions = document.createElement("div"); 521 539 actions.className = "card-actions"; ··· 555 573 actions.append(del); 556 574 } 557 575 558 - card.append(ava, img, who, actions); 576 + card.append(ava, img, who, ...(credit ? [credit] : []), actions); 559 577 g.append(card); 560 578 } 561 579 } catch (err) {
+11
src/style.css
··· 351 351 .card-img { width: 100%; aspect-ratio: 1; object-fit: contain; } 352 352 .card .who { font-size: .72rem; color: var(--muted); margin-top: .4rem; word-break: break-all; } 353 353 354 + /* a remix reads as such at a glance: a quiet accent-tinted edge + a credit to 355 + the original artist, marked with your own drawn remix glyph (a slot) */ 356 + .card.remix { border-color: color-mix(in srgb, var(--accent) 32%, var(--line)); } 357 + .card.remix:hover { border-color: color-mix(in srgb, var(--accent) 55%, var(--line)); } 358 + .remix-credit { 359 + display: inline-flex; align-items: center; gap: .25rem; max-width: 100%; 360 + margin-top: .15rem; font-size: .66rem; color: var(--muted); text-decoration: none; 361 + } 362 + .remix-credit:hover { color: var(--accent); } 363 + .remix-credit .slot-img { height: 1.15em; width: auto; } 364 + 354 365 /* avatar tucked in the top-left, always visible, out of the way */ 355 366 .card-ava { 356 367 position: absolute;