Skip to content

v3.18.35: dev → master merge#1

Merged
jouki merged 23 commits intomasterfrom
dev
Apr 12, 2026
Merged

v3.18.35: dev → master merge#1
jouki merged 23 commits intomasterfrom
dev

Conversation

@jouki
Copy link
Copy Markdown
Owner

@jouki jouki commented Apr 12, 2026

Summary

  • Optimistic message upgrade: sent messages now upgrade to real IRC messages (color, badges, ID)
  • Color system fix: _savePlatformColor only tracks own messages, prevents wrong colors on optimistic messages
  • Emotes + badges in cache: loaded BEFORE cache render so cached messages display correctly
  • Settings UI: merged save button, readonly username (dev mode to edit), depersonalized placeholders, removed "Vše" filter, status dot tooltips
  • @mention autocomplete: deduplicated entries, fixed YouTube @@ prefix, optimistic messages always pass dedup
  • Reply improvements: parent message text preserved in cache + optimistic, reply context wraps instead of truncating, replies TO user highlighted as mentions
  • Display name: uses Twitch IRC display-name casing instead of login cookie
  • Backend: nickname rate limit 300s → 10s
  • Landing: dev page reads version from manifest.json

Test plan

  • Send message → appears with correct color + badges immediately
  • Reply to message → reply context shows parent text
  • Reload panel → cached messages have emotes, badges, reply text
  • Settings: save color without nickname → "Barva uložena"
  • @mention autocomplete → no duplicates
  • Status dots show tooltip on hover

🤖 Generated with Claude Code

jouki and others added 23 commits April 12, 2026 20:09
Optimistic messages used defaultColors (#9146ff purple for Twitch)
when user's actual color wasn't tracked. The real IRC message with
correct orange color got content-deduped → purple stayed.

Fix:
- Removed hardcoded defaultColors map
- Added _platformColors tracking: when an incoming message matches
  the user's platform username, save its color
- Optimistic messages use ucProfile.color → _platformColors → null
  (no more purple fallback)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Button was placed inside the collapse toggle's parent element:
- Inherited "Sbalit" tooltip from parent
- Click was captured by parent's handler → OPEN_SIDE_PANEL never fired

Fix: insert directly into header row as sibling of the toggle wrapper
(not inside it). Own title attribute "Otevřít UnityChat" shows correctly.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1. Insert as header.children[1] (right after collapse toggle area)
2. Click now also clicks the collapse toggle button to hide vanilla
   Twitch chat, then opens UnityChat side panel

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Button is now position:absolute inside the header (left:34px, centered
vertically). Doesn't participate in flex layout → no shifting of
collapse arrow or "Chat streamu" text. Header gets position:relative.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Absolute positioning was clipped by header overflow:hidden.
Back to inline flex child with order:1, zero margin/padding,
flexShrink:0 to prevent squishing. Console log on inject.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The img icon wasn't rendering (extension URL might not resolve in
some contexts). Replaced with a simple orange gradient text button
'UC' — always visible, no external dependencies.

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

1. findChatHeader() now ONLY uses .stream-chat-header (no fallback
   that climbed to wrong parent container)
2. Replaced MutationObserver with setInterval(2s) polling — checks
   querySelectorAll length to avoid duplicates
3. If header doesn't exist yet → skip, retry in 2s (no wrong placement)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Find #chat-room-header-label inside .stream-chat-header specifically,
then insert button before its parent wrapper div. No class-based
selectors, no fallbacks — precise DOM targeting.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
_platformColors was lost on reload → optimistic messages had no
color (white). Now saved to config._platformColors and loaded on
startup. Once the user's Twitch color is detected from IRC, it
persists across reloads.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Two color detection paths:
1. _lastSentText match: when IRC echoes back our exact sent text,
   save msg.color for that platform (most reliable)
2. Username match: when msg.username matches _platformUsernames
   (backup for messages not sent through UnityChat)

Both call _savePlatformColor() which dedupes + persists to config.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Root cause: IRC echo was content-key deduped (same text as optimistic
message) → color tracking code inside UC marker block never ran.

Fix: extract color tracking to the very start of _addMessage, before
any dedup. Checks UC_MARKER in raw message, matches _lastSentText
against cleaned text, saves color even if the message itself gets
deduped immediately after.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
When a new platform color is detected, scan all visible .un elements
matching the platform + username and apply the color to any that
don't have one set yet (un.style.color empty = white/default).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…e fallback

Removed !un.style.color check — just set color on all matching
elements. Added config.username as fallback when _platformUsernames
doesn't have the platform entry.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
_chatUsers already maps username → { color } from incoming messages.
Optimistic message now uses: ucProfile.color → _chatUsers color →
_platformColors → null. No need for separate tracking — the map
is populated from every incoming IRC/API message.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Color lookup at render time: UC custom color → _chatUsers map
(populated from ALL incoming messages) → msg.color fallback.

Cached messages without color field now get the correct color
from the username map. Optimistic messages get the color as soon
as any message from the same user has been seen.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Color is now a property of the USERNAME, not the message:
- _chatUsers map stores username → { name, platform, color }
- Persisted to chrome.storage.local as uc_user_colors
- Loaded on startup before cached messages render
- Updated from ALL incoming messages (including pre-dedup echoes)
- Render always looks up from map: ucProfile.color → _chatUsers → msg.color

YouTube = red by default
Twitch/Kick = platform-set color by default
UC users = can override via nickname DB color

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1. Color map keys changed from 'username' to 'platform:username'
   to prevent cross-platform color bleed (Kick green overwriting
   Twitch orange for same username).

2. Save button now works with just color (no nickname required).
   If nick is empty but color is set, saves with original username
   as nickname (= just color override, no rename). Both empty = delete.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Fix: _setActivePlatform only updates settings fields on platform change
  (detect loop runs every 3s, was overwriting user-typed color values)
- Fix: nickname save uses _platformUsernames (matching display lookup)
- Fix: _savePlatformColor only for own messages (prevents wrong optimistic colors)
- Fix: optimistic messages upgrade to real on IRC echo (_upgradeOptimistic)
- Fix: emotes+badges load BEFORE cache (cached messages render correctly)
- UI: merged save button for nickname+color, centered below color field
- UI: username field readonly (editable only in dev mode)
- UI: depersonalized placeholders, autocomplete=off on all inputs
- UI: removed "Vse" filter button, status dot tooltips
- Backend: rate limit 300s -> 10s
- Landing: dev page reads version from manifest.json instead of dev API

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…eply wrap

- Fix: @mention autocomplete deduplicates by display name (no more 3x entries)
- Fix: YouTube @@ double prefix stripped in autocomplete
- Fix: replies TO user highlighted as mentions (checks nickname + platform username)
- Fix: reply parent message text preserved in cache (was stripped by _compactMsg)
- Fix: reply context wraps instead of truncating (removed nowrap/ellipsis CSS)
- Fix: optimistic messages always pass through content dedup (fixes missing replies)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
_setReply now captures original message text, passed through to
optimistic replyTo so the reply context shows the parent message
immediately (not just after IRC echo).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Update _platformUsernames with IRC display-name casing (e.g. "Jouki728")
  instead of login cookie ("jouki728") — USERNAME field shows proper casing
- When saving only color (no custom nickname), use display name from chat
  as the nickname value so it looks unchanged
- Status text: "Barva uložena" when no custom nickname, not "Přezdívka"

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@jouki jouki merged commit 6a61ff5 into master Apr 12, 2026
jouki added a commit that referenced this pull request Apr 15, 2026
….38.35)

Diagnostic dump z UC-pinned zprávy ukázal:

  <p class="iQZxnA">
    [textNode "Připnuto uživatelem "]
    <span><div><img mod-badge></div></span>
    [textNode "Jouki728"]
  </p>
  <p class="pinned-chat__message">peepoHey ⠀</p>

V card-root div je textContent = "Připnuto uživatelem Jouki728peepoHey ⠀"
(38 chars, pod 60 limit). Greedy regex [\p{L}\p{N}_-]+ zachytil
"Jouki728peepoHey" jako pinnedBy → bug "Jouki728pee...".

Fix #1 (pinnedBy):
- Scan DIRECT child text nodes elementu (skip descendant text)
- Pokud první přímý text matchuje label, pinner je extracted z
  same-element direct text za labelem
- Tight regex [A-Za-z0-9_]{2,25}\b (Twitch username chars + length cap)

Fix #2 (body):
- Selector [class*="pinned-chat-message"] (hyphen) NEnematchoval
  real Twitch class "pinned-chat__message" (double underscore)
- Přidány .pinned-chat__message + [class*="pinned-chat__message"]
- Body extract teď najde correct element s emote fragments

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
jouki added a commit that referenced this pull request Apr 15, 2026
User report:
1. peepoHey emote nezresolvněn (zobrazí se jako text)
2. Ostrý okraj místo zaoblených rohů

Fix #1 (emote resolve):
Twitch's pin DOM keeps body as <span class="text-fragment">peepoHey ⠀</span>
plain text. 7TV/BTTV/FFZ Vue replacer doesn't penetrate pin subtree
(only chat-line containers). Body segments arrive as text type.

_buildPinCard teď tokenizuje text segmenty (split na whitespace)
a resolve každý token proti emote library order:
twitchNative → channel7tv → global7tv → bttvEmotes → ffzEmotes
→ kickNative → ucEmotes. Resolved emotes render jako <img>,
unresolved fallback na linkified text. Plus strip UC marker
(Braille blank ⠀).

Fix #2 (rounded corners):
border-image: linear-gradient(...) v Chrome ignoruje
border-radius (spec implementation-defined behaviour). Rohy
byly ostré navzdory border-radius: 10px.

Nahrazeno: solid amber border + multi-layer box-shadow
(combination outer glow + inner ring + bottom-edge accent)
which together replicate the gradient ring effect WHILE
border-radius drží.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant