From fc7dc6eab27db22153459bcd0bf7425fa30ff32b Mon Sep 17 00:00:00 2001 From: FlaminSarge Date: Tue, 17 Sep 2024 05:46:26 -0700 Subject: [PATCH 01/14] Show YT's AI chat summary in a 'pinned'-style box if it is present --- src/components/ChatSummary.svelte | 68 +++++++++++++++++++++++++++++++ src/components/Hyperchat.svelte | 20 +++++++-- src/ts/chat-parser.ts | 26 +++++++++++- src/ts/typings/ytc.d.ts | 29 ++++++++++++- 4 files changed, 136 insertions(+), 7 deletions(-) create mode 100644 src/components/ChatSummary.svelte diff --git a/src/components/ChatSummary.svelte b/src/components/ChatSummary.svelte new file mode 100644 index 00000000..a23c6deb --- /dev/null +++ b/src/components/ChatSummary.svelte @@ -0,0 +1,68 @@ + + +{#if !dismissed} +
+
+
+ + + {#if shorten} + expand_more + {:else} + expand_less + {/if} + + + {#each summary.header as run} + {#if run.type === 'text'} + {run.text} + {/if} + {/each} +
+
+ + { dismissed = true; }} + > + close + + Dismiss + +
+
+ {#if !shorten && !dismissed} +
+ +
+ {/if} +
+{/if} diff --git a/src/components/Hyperchat.svelte b/src/components/Hyperchat.svelte index c92607f3..7bbbf696 100644 --- a/src/components/Hyperchat.svelte +++ b/src/components/Hyperchat.svelte @@ -6,6 +6,7 @@ import WelcomeMessage from './WelcomeMessage.svelte'; import Message from './Message.svelte'; import PinnedMessage from './PinnedMessage.svelte'; + import ChatSummary from './ChatSummary.svelte'; import PaidMessage from './PaidMessage.svelte'; import MembershipItem from './MembershipItem.svelte'; import ReportBanDialog from './ReportBanDialog.svelte'; @@ -53,6 +54,7 @@ let messageActions: (Chat.MessageAction | Welcome)[] = []; const messageKeys = new Set(); let pinned: Ytc.ParsedPinned | null; + let summary: Ytc.ParsedSummary | null; let div: HTMLElement; let isAtBottom = true; let truncateInterval: number; @@ -183,6 +185,9 @@ case 'delete': onDelete(action.deletion); break; + case 'summary': + summary = action; + break; case 'pin': pinned = action; break; @@ -393,11 +398,18 @@ {/each} - {#if pinned} + {#if summary || pinned}
-
- -
+ {#if summary} +
+ +
+ {/if} + {#if pinned} +
+ +
+ {/if}
{/if} {#if !isAtBottom} diff --git a/src/ts/chat-parser.ts b/src/ts/chat-parser.ts index 1c2443d8..b8b12399 100644 --- a/src/ts/chat-parser.ts +++ b/src/ts/chat-parser.ts @@ -61,6 +61,25 @@ const parseMessageRuns = (runs?: Ytc.MessageRun[]): Ytc.ParsedRun[] => { return parsedRuns; }; +const parseChatSummary = (renderer: Ytc.AddChatItem, isEphemeral: boolean | undefined, bannerTimeoutMs: number | undefined): Ytc.ParsedSummary | undefined => { + const baseRenderer = renderer.liveChatBannerChatSummaryRenderer!; + const runs = parseMessageRuns(renderer.liveChatBannerChatSummaryRenderer?.chatSummary.runs); + if (runs[2].type === 'text') { + runs[2].text = '(' + runs[2].text + ')'; + } + const item: Ytc.ParsedSummary = { + type: 'summary', + header: runs.slice(0, 3), + summary: runs.slice(4), + icon: baseRenderer.icon && { + iconType: baseRenderer.icon?.iconType.toLowerCase(), + }, + id: baseRenderer.liveChatSummaryId, + showtime: isEphemeral ? (bannerTimeoutMs ?? 0) / 1000 : 0, + }; + return item; +} + const parseAddChatItemAction = (action: Ytc.AddChatItemAction, isReplay = false, liveTimeoutOrReplayMs = 0): Ytc.ParsedMessage | undefined => { const actionItem = action.item; const renderer = actionItem.liveChatTextMessageRenderer ?? @@ -183,8 +202,11 @@ const parseMessageDeletedAction = (action: Ytc.MessageDeletedAction): Ytc.Parsed }; }; -const parsePinnedMessageAction = (action: Ytc.AddPinnedAction): Ytc.ParsedPinned | undefined => { +const parseBannerAction = (action: Ytc.AddPinnedAction): Ytc.ParsedPinned | Ytc.ParsedSummary | undefined => { const baseRenderer = action.bannerRenderer.liveChatBannerRenderer; + if (baseRenderer.contents.liveChatBannerChatSummaryRenderer) { + return parseChatSummary(baseRenderer.contents, action.bannerProperties?.isEphemeral, action.bannerProperties?.bannerTimeoutMs); + } const parsedContents = parseAddChatItemAction( { item: baseRenderer.contents }, true ); @@ -229,7 +251,7 @@ const processCommonAction = ( if (action.addChatItemAction) { return parseAddChatItemAction(action.addChatItemAction, isReplay, liveTimeoutOrReplayMs); } else if (action.addBannerToLiveChatCommand) { - return parsePinnedMessageAction(action.addBannerToLiveChatCommand); + return parseBannerAction(action.addBannerToLiveChatCommand); } else if (action.removeBannerForLiveChatCommand) { return { type: 'unpin' } as const; } else if (action.addLiveChatTickerItemAction) { diff --git a/src/ts/typings/ytc.d.ts b/src/ts/typings/ytc.d.ts index 0674c419..1eca85bb 100644 --- a/src/ts/typings/ytc.d.ts +++ b/src/ts/typings/ytc.d.ts @@ -88,6 +88,10 @@ declare namespace Ytc { }; }; }; + bannerProperties?: { + isEphemeral: boolean; + bannerTimeoutMs: number; + } } interface AddTickerAction { @@ -227,6 +231,15 @@ declare namespace Ytc { }; } + interface ChatSummaryRenderer { + liveChatSummaryId: string; + chatSummary: RunsObj; + icon?: { + /** Unlocalized string */ + iconType: string; + }; + } + interface PlaceholderRenderer { // No idea what the purpose of this is id: string; timestampUsec: IntString; @@ -248,6 +261,8 @@ declare namespace Ytc { liveChatSponsorshipsGiftPurchaseAnnouncementRenderer?: MembershipGiftPurchaseRenderer; /** Membership gift redemption */ liveChatSponsorshipsGiftRedemptionAnnouncementRenderer?: TextMessageRenderer; + /** AI Chat Summary */ + liveChatBannerChatSummaryRenderer?: ChatSummaryRenderer; /** ??? */ liveChatPlaceholderItemRenderer?: PlaceholderRenderer; } @@ -365,13 +380,25 @@ declare namespace Ytc { }; } + interface ParsedSummary { + type: 'summary'; + header: ParsedRun[]; + summary: ParsedRun[]; + id: string; + icon?: { + /** Unlocalized string */ + iconType: string; + }; + showtime: number; + } + interface ParsedTicker extends ParsedMessage { type: 'ticker'; tickerDuration: number; detailText?: string; } - type ParsedMisc = ParsedPinned | { type: 'unpin'}; + type ParsedMisc = ParsedPinned | ParsedSummary | { type: 'unpin' }; type ParsedTimedItem = ParsedMessage | ParsedTicker; From 008ee63887062746a3502cc8c9d076ac86062bc6 Mon Sep 17 00:00:00 2001 From: FlaminSarge Date: Tue, 17 Sep 2024 06:05:08 -0700 Subject: [PATCH 02/14] Move second summary line to subheader --- src/components/ChatSummary.svelte | 3 +++ src/ts/chat-parser.ts | 6 ++---- src/ts/typings/ytc.d.ts | 1 + 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/components/ChatSummary.svelte b/src/components/ChatSummary.svelte index a23c6deb..07c50b5f 100644 --- a/src/components/ChatSummary.svelte +++ b/src/components/ChatSummary.svelte @@ -60,6 +60,9 @@ {#if !shorten && !dismissed} +
+ +
diff --git a/src/ts/chat-parser.ts b/src/ts/chat-parser.ts index b8b12399..d12803bd 100644 --- a/src/ts/chat-parser.ts +++ b/src/ts/chat-parser.ts @@ -64,12 +64,10 @@ const parseMessageRuns = (runs?: Ytc.MessageRun[]): Ytc.ParsedRun[] => { const parseChatSummary = (renderer: Ytc.AddChatItem, isEphemeral: boolean | undefined, bannerTimeoutMs: number | undefined): Ytc.ParsedSummary | undefined => { const baseRenderer = renderer.liveChatBannerChatSummaryRenderer!; const runs = parseMessageRuns(renderer.liveChatBannerChatSummaryRenderer?.chatSummary.runs); - if (runs[2].type === 'text') { - runs[2].text = '(' + runs[2].text + ')'; - } const item: Ytc.ParsedSummary = { type: 'summary', - header: runs.slice(0, 3), + header: [runs[0]], + subheader: [runs[2]], summary: runs.slice(4), icon: baseRenderer.icon && { iconType: baseRenderer.icon?.iconType.toLowerCase(), diff --git a/src/ts/typings/ytc.d.ts b/src/ts/typings/ytc.d.ts index 1eca85bb..71d3fa72 100644 --- a/src/ts/typings/ytc.d.ts +++ b/src/ts/typings/ytc.d.ts @@ -383,6 +383,7 @@ declare namespace Ytc { interface ParsedSummary { type: 'summary'; header: ParsedRun[]; + subheader: ParsedRun[]; summary: ParsedRun[]; id: string; icon?: { From 724fb29f036e350ace73ddb1c5461457d9af26f5 Mon Sep 17 00:00:00 2001 From: FlaminSarge Date: Tue, 17 Sep 2024 17:30:05 -0700 Subject: [PATCH 03/14] Better structure and parsing for summary object --- src/components/ChatSummary.svelte | 6 +++--- src/ts/chat-parser.ts | 25 ++++++++++++++++++++++--- src/ts/typings/ytc.d.ts | 8 +++++--- 3 files changed, 30 insertions(+), 9 deletions(-) diff --git a/src/components/ChatSummary.svelte b/src/components/ChatSummary.svelte index 07c50b5f..fded6f1e 100644 --- a/src/components/ChatSummary.svelte +++ b/src/components/ChatSummary.svelte @@ -40,7 +40,7 @@ {/if} - {#each summary.header as run} + {#each summary.item.header as run} {#if run.type === 'text'} {run.text} {/if} @@ -61,10 +61,10 @@ {#if !shorten && !dismissed}
- +
- +
{/if} diff --git a/src/ts/chat-parser.ts b/src/ts/chat-parser.ts index d12803bd..f25b0a6f 100644 --- a/src/ts/chat-parser.ts +++ b/src/ts/chat-parser.ts @@ -61,14 +61,33 @@ const parseMessageRuns = (runs?: Ytc.MessageRun[]): Ytc.ParsedRun[] => { return parsedRuns; }; +const splitRunsByNewline = (runs: Ytc.ParsedRun[], maxSplit: number = -1): Ytc.ParsedRun[][] => { + // takes an array of runs, finds newline-only runs, and splits the array by them, up to maxSplit times + let currSplit = 0; + const output: Ytc.ParsedRun[][] = []; + output.push(runs.reduce((acc: Ytc.ParsedRun[], run: Ytc.ParsedRun) => { + if (run.type === 'text' && run.text === '\n' && (maxSplit == -1 || currSplit < maxSplit)) { + currSplit++; + output.push(acc); + return []; + } + acc.push(run); + return acc; + }, [])); + return output; +} + const parseChatSummary = (renderer: Ytc.AddChatItem, isEphemeral: boolean | undefined, bannerTimeoutMs: number | undefined): Ytc.ParsedSummary | undefined => { const baseRenderer = renderer.liveChatBannerChatSummaryRenderer!; const runs = parseMessageRuns(renderer.liveChatBannerChatSummaryRenderer?.chatSummary.runs); + const splitRuns = splitRunsByNewline(runs, 2); const item: Ytc.ParsedSummary = { type: 'summary', - header: [runs[0]], - subheader: [runs[2]], - summary: runs.slice(4), + item: { + header: splitRuns[0], + subheader: splitRuns[1], + message: splitRuns[2], + }, icon: baseRenderer.icon && { iconType: baseRenderer.icon?.iconType.toLowerCase(), }, diff --git a/src/ts/typings/ytc.d.ts b/src/ts/typings/ytc.d.ts index 71d3fa72..95b10615 100644 --- a/src/ts/typings/ytc.d.ts +++ b/src/ts/typings/ytc.d.ts @@ -382,9 +382,11 @@ declare namespace Ytc { interface ParsedSummary { type: 'summary'; - header: ParsedRun[]; - subheader: ParsedRun[]; - summary: ParsedRun[]; + item: { + header: ParsedRun[]; + subheader: ParsedRun[]; + message: ParsedRun[]; + }; id: string; icon?: { /** Unlocalized string */ From f1c56c151a8c86f212da74b61040bee6ae8b1397 Mon Sep 17 00:00:00 2001 From: FlaminSarge Date: Tue, 17 Sep 2024 17:52:18 -0700 Subject: [PATCH 04/14] Convert the subheader for the summary to a link to the YT experiment description on Google's support site --- src/ts/chat-parser.ts | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/ts/chat-parser.ts b/src/ts/chat-parser.ts index f25b0a6f..f633d4f3 100644 --- a/src/ts/chat-parser.ts +++ b/src/ts/chat-parser.ts @@ -81,11 +81,18 @@ const parseChatSummary = (renderer: Ytc.AddChatItem, isEphemeral: boolean | unde const baseRenderer = renderer.liveChatBannerChatSummaryRenderer!; const runs = parseMessageRuns(renderer.liveChatBannerChatSummaryRenderer?.chatSummary.runs); const splitRuns = splitRunsByNewline(runs, 2); + const subheader = splitRuns[1].map(run => { + if (run.type === 'text') { + return { type: 'link', text: run.text, url: 'https://support.google.com/youtube/thread/18138167?hl=en&msgid=284199217' } as Ytc.ParsedLinkRun; + } else { + return run; + } + }); const item: Ytc.ParsedSummary = { type: 'summary', item: { header: splitRuns[0], - subheader: splitRuns[1], + subheader: subheader, message: splitRuns[2], }, icon: baseRenderer.icon && { From 7ef94379c9e86e43038673886d6a109281497c2f Mon Sep 17 00:00:00 2001 From: FlaminSarge Date: Tue, 17 Sep 2024 17:56:05 -0700 Subject: [PATCH 05/14] Add some safety to summary handling --- src/ts/chat-parser.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/ts/chat-parser.ts b/src/ts/chat-parser.ts index f633d4f3..9c27b673 100644 --- a/src/ts/chat-parser.ts +++ b/src/ts/chat-parser.ts @@ -81,6 +81,10 @@ const parseChatSummary = (renderer: Ytc.AddChatItem, isEphemeral: boolean | unde const baseRenderer = renderer.liveChatBannerChatSummaryRenderer!; const runs = parseMessageRuns(renderer.liveChatBannerChatSummaryRenderer?.chatSummary.runs); const splitRuns = splitRunsByNewline(runs, 2); + if (splitRuns.length < 3) { + // YT probably changed the format, refuse to do anything to avoid breaking + return; + } const subheader = splitRuns[1].map(run => { if (run.type === 'text') { return { type: 'link', text: run.text, url: 'https://support.google.com/youtube/thread/18138167?hl=en&msgid=284199217' } as Ytc.ParsedLinkRun; From 8f59f9a576f4bc22fb7e8ea7cc138d101cfa879b Mon Sep 17 00:00:00 2001 From: FlaminSarge Date: Tue, 17 Sep 2024 18:23:44 -0700 Subject: [PATCH 06/14] Add setting to hide chat summary --- src/components/Hyperchat.svelte | 5 +++-- src/components/settings/InterfaceSettings.svelte | 4 +++- src/ts/storage.ts | 1 + 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/components/Hyperchat.svelte b/src/components/Hyperchat.svelte index 7bbbf696..6fe727d9 100644 --- a/src/components/Hyperchat.svelte +++ b/src/components/Hyperchat.svelte @@ -29,6 +29,7 @@ showUsernames, showTimestamps, showUserBadges, + showChatSummary, refreshScroll, emojiRenderMode, useSystemEmojis, @@ -398,9 +399,9 @@ {/each} - {#if summary || pinned} + {#if (summary && $showChatSummary) || pinned}
- {#if summary} + {#if summary && $showChatSummary}
diff --git a/src/components/settings/InterfaceSettings.svelte b/src/components/settings/InterfaceSettings.svelte index 7ddbdd36..ff9ac8d7 100644 --- a/src/components/settings/InterfaceSettings.svelte +++ b/src/components/settings/InterfaceSettings.svelte @@ -11,7 +11,8 @@ useSystemEmojis, isDark, enableStickySuperchatBar, - enableHighlightedMentions + enableHighlightedMentions, + showChatSummary } from '../../ts/storage'; import { themeItems, emojiRenderItems } from '../../ts/chat-constants'; import Card from '../common/Card.svelte'; @@ -59,6 +60,7 @@ + diff --git a/src/ts/storage.ts b/src/ts/storage.ts index 1578e43d..1b8c7e89 100644 --- a/src/ts/storage.ts +++ b/src/ts/storage.ts @@ -49,6 +49,7 @@ export const showProfileIcons = stores.addSyncStore('hc.messages.showProfileIcon export const showUsernames = stores.addSyncStore('hc.messages.showUsernames', true); export const showTimestamps = stores.addSyncStore('hc.messages.showTimestamps', false); export const showUserBadges = stores.addSyncStore('hc.messages.showUserBadges', true); +export const showChatSummary = stores.addSyncStore('hc.messages.showChatSummary', true); export const lastClosedVersion = stores.addSyncStore('hc.lastClosedVersion', ''); export const showOnlyMemberChat = stores.addSyncStore('hc.showOnlyMemberChat', false); export const emojiRenderMode = stores.addSyncStore('hc.emojiRenderMode', YoutubeEmojiRenderMode.SHOW_ALL); From 0a63555042a3c1263aa32250f771a68f49e5822a Mon Sep 17 00:00:00 2001 From: FlaminSarge Date: Tue, 17 Sep 2024 18:56:35 -0700 Subject: [PATCH 07/14] Better null-safety --- src/ts/chat-parser.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/ts/chat-parser.ts b/src/ts/chat-parser.ts index 9c27b673..0da846d5 100644 --- a/src/ts/chat-parser.ts +++ b/src/ts/chat-parser.ts @@ -78,6 +78,9 @@ const splitRunsByNewline = (runs: Ytc.ParsedRun[], maxSplit: number = -1): Ytc.P } const parseChatSummary = (renderer: Ytc.AddChatItem, isEphemeral: boolean | undefined, bannerTimeoutMs: number | undefined): Ytc.ParsedSummary | undefined => { + if (!renderer.liveChatBannerChatSummaryRenderer) { + return; + } const baseRenderer = renderer.liveChatBannerChatSummaryRenderer!; const runs = parseMessageRuns(renderer.liveChatBannerChatSummaryRenderer?.chatSummary.runs); const splitRuns = splitRunsByNewline(runs, 2); From d23d502220cd5b73c020f96cc79d8346e34eabaf Mon Sep 17 00:00:00 2001 From: FlaminSarge Date: Tue, 17 Sep 2024 19:00:25 -0700 Subject: [PATCH 08/14] Move null checks up for bannerProperties fields --- src/ts/chat-parser.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/ts/chat-parser.ts b/src/ts/chat-parser.ts index 0da846d5..174fedb8 100644 --- a/src/ts/chat-parser.ts +++ b/src/ts/chat-parser.ts @@ -77,7 +77,7 @@ const splitRunsByNewline = (runs: Ytc.ParsedRun[], maxSplit: number = -1): Ytc.P return output; } -const parseChatSummary = (renderer: Ytc.AddChatItem, isEphemeral: boolean | undefined, bannerTimeoutMs: number | undefined): Ytc.ParsedSummary | undefined => { +const parseChatSummary = (renderer: Ytc.AddChatItem, isEphemeral: boolean, bannerTimeoutMs: number): Ytc.ParsedSummary | undefined => { if (!renderer.liveChatBannerChatSummaryRenderer) { return; } @@ -106,7 +106,7 @@ const parseChatSummary = (renderer: Ytc.AddChatItem, isEphemeral: boolean | unde iconType: baseRenderer.icon?.iconType.toLowerCase(), }, id: baseRenderer.liveChatSummaryId, - showtime: isEphemeral ? (bannerTimeoutMs ?? 0) / 1000 : 0, + showtime: isEphemeral ? (bannerTimeoutMs / 1000) : 0, }; return item; } @@ -236,7 +236,7 @@ const parseMessageDeletedAction = (action: Ytc.MessageDeletedAction): Ytc.Parsed const parseBannerAction = (action: Ytc.AddPinnedAction): Ytc.ParsedPinned | Ytc.ParsedSummary | undefined => { const baseRenderer = action.bannerRenderer.liveChatBannerRenderer; if (baseRenderer.contents.liveChatBannerChatSummaryRenderer) { - return parseChatSummary(baseRenderer.contents, action.bannerProperties?.isEphemeral, action.bannerProperties?.bannerTimeoutMs); + return parseChatSummary(baseRenderer.contents, action.bannerProperties?.isEphemeral ?? false, action.bannerProperties?.bannerTimeoutMs ?? 0); } const parsedContents = parseAddChatItemAction( { item: baseRenderer.contents }, true From 363447c611d0ad718d5c0cf036b3a4d412395558 Mon Sep 17 00:00:00 2001 From: FlaminSarge Date: Wed, 18 Sep 2024 06:31:45 -0700 Subject: [PATCH 09/14] Remove icon from ParsedSummary --- src/ts/chat-parser.ts | 3 --- src/ts/typings/ytc.d.ts | 4 ---- 2 files changed, 7 deletions(-) diff --git a/src/ts/chat-parser.ts b/src/ts/chat-parser.ts index 174fedb8..1d8c8dcb 100644 --- a/src/ts/chat-parser.ts +++ b/src/ts/chat-parser.ts @@ -102,9 +102,6 @@ const parseChatSummary = (renderer: Ytc.AddChatItem, isEphemeral: boolean, banne subheader: subheader, message: splitRuns[2], }, - icon: baseRenderer.icon && { - iconType: baseRenderer.icon?.iconType.toLowerCase(), - }, id: baseRenderer.liveChatSummaryId, showtime: isEphemeral ? (bannerTimeoutMs / 1000) : 0, }; diff --git a/src/ts/typings/ytc.d.ts b/src/ts/typings/ytc.d.ts index 95b10615..3daf38cf 100644 --- a/src/ts/typings/ytc.d.ts +++ b/src/ts/typings/ytc.d.ts @@ -388,10 +388,6 @@ declare namespace Ytc { message: ParsedRun[]; }; id: string; - icon?: { - /** Unlocalized string */ - iconType: string; - }; showtime: number; } From bfa048f8fbfa5618cbc07963e3672fe3e34a38f2 Mon Sep 17 00:00:00 2001 From: FlaminSarge Date: Wed, 18 Sep 2024 16:12:41 -0700 Subject: [PATCH 10/14] Add comment about subheader link --- src/ts/chat-parser.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/ts/chat-parser.ts b/src/ts/chat-parser.ts index 1d8c8dcb..48a10f12 100644 --- a/src/ts/chat-parser.ts +++ b/src/ts/chat-parser.ts @@ -90,6 +90,7 @@ const parseChatSummary = (renderer: Ytc.AddChatItem, isEphemeral: boolean, banne } const subheader = splitRuns[1].map(run => { if (run.type === 'text') { + // turn subheader into a link to YT's support page detailing the AI summary feature return { type: 'link', text: run.text, url: 'https://support.google.com/youtube/thread/18138167?hl=en&msgid=284199217' } as Ytc.ParsedLinkRun; } else { return run; From 2c5f28c29cee0cf338afaa97446d6949b8cfcc19 Mon Sep 17 00:00:00 2001 From: FlaminSarge Date: Sat, 21 Sep 2024 23:27:46 -0700 Subject: [PATCH 11/14] Rework splitRunsByNewline (identical behavior) --- src/ts/chat-parser.ts | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/src/ts/chat-parser.ts b/src/ts/chat-parser.ts index 48a10f12..9c9a1107 100644 --- a/src/ts/chat-parser.ts +++ b/src/ts/chat-parser.ts @@ -61,21 +61,18 @@ const parseMessageRuns = (runs?: Ytc.MessageRun[]): Ytc.ParsedRun[] => { return parsedRuns; }; -const splitRunsByNewline = (runs: Ytc.ParsedRun[], maxSplit: number = -1): Ytc.ParsedRun[][] => { - // takes an array of runs, finds newline-only runs, and splits the array by them, up to maxSplit times - let currSplit = 0; - const output: Ytc.ParsedRun[][] = []; - output.push(runs.reduce((acc: Ytc.ParsedRun[], run: Ytc.ParsedRun) => { - if (run.type === 'text' && run.text === '\n' && (maxSplit == -1 || currSplit < maxSplit)) { - currSplit++; - output.push(acc); - return []; +// takes an array of runs, finds newline-only runs, and splits the array by them, up to maxSplit times +// final output will have maximum length of maxSplit + 1 +// maxSplit = -1 will have no limit for splits +const splitRunsByNewline = (runs: Ytc.ParsedRun[], maxSplit: number = -1): Ytc.ParsedRun[][] => + runs.reduce((acc: Ytc.ParsedRun[][], run: Ytc.ParsedRun) => { + if (run.type === 'text' && run.text === '\n' && (maxSplit == -1 || acc.length <= maxSplit)) { + acc.push([]); + } else { + acc[acc.length - 1].push(run); } - acc.push(run); return acc; - }, [])); - return output; -} + }, [[]]); const parseChatSummary = (renderer: Ytc.AddChatItem, isEphemeral: boolean, bannerTimeoutMs: number): Ytc.ParsedSummary | undefined => { if (!renderer.liveChatBannerChatSummaryRenderer) { From db974c84039df51daf34be1d6c68ac23e039a35e Mon Sep 17 00:00:00 2001 From: FlaminSarge Date: Wed, 25 Sep 2024 00:10:13 -0700 Subject: [PATCH 12/14] Remove hl=en param from google support link for AI summary subheader --- src/ts/chat-parser.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ts/chat-parser.ts b/src/ts/chat-parser.ts index 9c9a1107..a026e51b 100644 --- a/src/ts/chat-parser.ts +++ b/src/ts/chat-parser.ts @@ -88,7 +88,7 @@ const parseChatSummary = (renderer: Ytc.AddChatItem, isEphemeral: boolean, banne const subheader = splitRuns[1].map(run => { if (run.type === 'text') { // turn subheader into a link to YT's support page detailing the AI summary feature - return { type: 'link', text: run.text, url: 'https://support.google.com/youtube/thread/18138167?hl=en&msgid=284199217' } as Ytc.ParsedLinkRun; + return { type: 'link', text: run.text, url: 'https://support.google.com/youtube/thread/18138167?msgid=284199217' } as Ytc.ParsedLinkRun; } else { return run; } From 1daa12c733454801420f966ce66c855ccc3d4ee3 Mon Sep 17 00:00:00 2001 From: Kento Nishi Date: Sun, 15 Dec 2024 20:54:26 -0500 Subject: [PATCH 13/14] change label --- src/components/settings/InterfaceSettings.svelte | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/settings/InterfaceSettings.svelte b/src/components/settings/InterfaceSettings.svelte index ff9ac8d7..d44ae7b1 100644 --- a/src/components/settings/InterfaceSettings.svelte +++ b/src/components/settings/InterfaceSettings.svelte @@ -60,7 +60,7 @@ - + From f8155be698d3ef30934d769f1b0a00ded1c00ab4 Mon Sep 17 00:00:00 2001 From: Kento Nishi Date: Sun, 15 Dec 2024 21:29:06 -0500 Subject: [PATCH 14/14] rephrase --- src/components/settings/InterfaceSettings.svelte | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/settings/InterfaceSettings.svelte b/src/components/settings/InterfaceSettings.svelte index d44ae7b1..0c90f3e8 100644 --- a/src/components/settings/InterfaceSettings.svelte +++ b/src/components/settings/InterfaceSettings.svelte @@ -60,7 +60,7 @@ - +