From 537ea7bbe65c8493ec86fb1880af3b8aa0de97e9 Mon Sep 17 00:00:00 2001 From: Megghy Date: Thu, 21 Nov 2024 00:53:15 +0800 Subject: [PATCH] fix wrong langue value when adding songs --- src/api/api-models.ts | 2 +- src/assets/css/youtube/yt-html.css | 362 + src/assets/css/youtube/yt-icon.css | 30 + src/assets/css/youtube/yt-img-shadow.css | 68 + .../yt-live-chat-author-badge-renderer.css | 36 + .../css/youtube/yt-live-chat-author-chip.css | 64 + .../yt-live-chat-item-list-renderer.css | 140 + .../yt-live-chat-membership-item-renderer.css | 362 + .../yt-live-chat-paid-message-renderer.css | 380 + .../css/youtube/yt-live-chat-renderer.css | 252 + .../yt-live-chat-text-message-renderer.css | 232 + ...chat-ticker-paid-message-item-renderer.css | 80 + .../youtube/yt-live-chat-ticker-renderer.css | 65 + src/data/DanmakuClient.ts | 133 +- src/data/RTCClient.ts | 48 +- src/main.ts | 70 +- src/router/obs.ts | 34 +- src/store/useDanmakuClient.ts | 232 + src/store/useRTC.ts | 68 +- src/store/useVTsuruHub.ts | 7 +- src/views/ManageLayout.vue | 3 +- src/views/OpenLiveLayout.vue | 25 +- src/views/TestView.vue | 16 +- src/views/manage/DanmakuLayout.vue | 64 - src/views/manage/LiveLotteryManage.vue | 13 +- src/views/manage/SettingsManageView.vue | 4 +- src/views/manage/SongListManageView.vue | 13 +- src/views/manage/SongRequestManage.vue | 14 +- src/views/obs/DanmujiOBS.vue | 410 + src/views/obs/blivechat/AuthorBadge.vue | 60 + src/views/obs/blivechat/AuthorChip.vue | 51 + src/views/obs/blivechat/ImgShadow.vue | 38 + src/views/obs/blivechat/MembershipItem.vue | 52 + src/views/obs/blivechat/MessageRender.vue | 630 + src/views/obs/blivechat/PaidMessage.vue | 68 + src/views/obs/blivechat/TextMessage.vue | 106 + src/views/obs/blivechat/Ticker.vue | 201 + src/views/obs/blivechat/constants.js | 200 + src/views/obs/blivechat/models.js | 126 + src/views/obs/blivechat/utils/index.js | 51 + .../blivechat/utils/pronunciation/dictKana.js | 20902 ++++++++++++++++ .../utils/pronunciation/dictPinyin.js | 20902 ++++++++++++++++ .../blivechat/utils/pronunciation/index.js | 54 + src/views/obs/blivechat/utils/trie.js | 58 + src/views/open_live/LiveRequest.vue | 25 +- src/views/open_live/MusicRequest.vue | 17 +- src/views/open_live/OpenLiveIndex.vue | 11 +- src/views/open_live/OpenLottery.vue | 19 +- src/views/open_live/OpenQueue.vue | 19 +- src/views/open_live/ReadDanmaku.vue | 160 +- tsconfig.json | 2 +- vite.config.mts | 9 +- 52 files changed, 46594 insertions(+), 394 deletions(-) create mode 100644 src/assets/css/youtube/yt-html.css create mode 100644 src/assets/css/youtube/yt-icon.css create mode 100644 src/assets/css/youtube/yt-img-shadow.css create mode 100644 src/assets/css/youtube/yt-live-chat-author-badge-renderer.css create mode 100644 src/assets/css/youtube/yt-live-chat-author-chip.css create mode 100644 src/assets/css/youtube/yt-live-chat-item-list-renderer.css create mode 100644 src/assets/css/youtube/yt-live-chat-membership-item-renderer.css create mode 100644 src/assets/css/youtube/yt-live-chat-paid-message-renderer.css create mode 100644 src/assets/css/youtube/yt-live-chat-renderer.css create mode 100644 src/assets/css/youtube/yt-live-chat-text-message-renderer.css create mode 100644 src/assets/css/youtube/yt-live-chat-ticker-paid-message-item-renderer.css create mode 100644 src/assets/css/youtube/yt-live-chat-ticker-renderer.css create mode 100644 src/store/useDanmakuClient.ts delete mode 100644 src/views/manage/DanmakuLayout.vue create mode 100644 src/views/obs/DanmujiOBS.vue create mode 100644 src/views/obs/blivechat/AuthorBadge.vue create mode 100644 src/views/obs/blivechat/AuthorChip.vue create mode 100644 src/views/obs/blivechat/ImgShadow.vue create mode 100644 src/views/obs/blivechat/MembershipItem.vue create mode 100644 src/views/obs/blivechat/MessageRender.vue create mode 100644 src/views/obs/blivechat/PaidMessage.vue create mode 100644 src/views/obs/blivechat/TextMessage.vue create mode 100644 src/views/obs/blivechat/Ticker.vue create mode 100644 src/views/obs/blivechat/constants.js create mode 100644 src/views/obs/blivechat/models.js create mode 100644 src/views/obs/blivechat/utils/index.js create mode 100644 src/views/obs/blivechat/utils/pronunciation/dictKana.js create mode 100644 src/views/obs/blivechat/utils/pronunciation/dictPinyin.js create mode 100644 src/views/obs/blivechat/utils/pronunciation/index.js create mode 100644 src/views/obs/blivechat/utils/trie.js diff --git a/src/api/api-models.ts b/src/api/api-models.ts index ce31e5f..40b2ce0 100644 --- a/src/api/api-models.ts +++ b/src/api/api-models.ts @@ -72,7 +72,7 @@ export interface AccountInfo extends UserInfo { nextSendEmailTime?: number isServerFetcherOnline: boolean blackList: UserBasicInfo[] - biliBlackList: { [key: number]: string } + biliBlackList: { [key: string]: string } streamerInfo?: StreamerModel biliUserAuthInfo?: BiliAuthModel } diff --git a/src/assets/css/youtube/yt-html.css b/src/assets/css/youtube/yt-html.css new file mode 100644 index 0000000..75dc6fc --- /dev/null +++ b/src/assets/css/youtube/yt-html.css @@ -0,0 +1,362 @@ +html:not(.style-scope) { + --yt-live-chat-background-color: hsl(0, 0%, 100%); + --yt-live-chat-action-panel-background-color: hsla(0, 0%, 93.3%, .4); + --yt-live-chat-action-panel-background-color-transparent: hsla(0, 0%, 97%, .8); + --yt-live-chat-mode-change-background-color: hsla(0, 0%, 93.3%, .4); + --yt-live-chat-primary-text-color: hsl(0, 0%, 6.7%); + --yt-live-chat-secondary-text-color: hsla(0, 0%, 6.7%, .6); + --yt-live-chat-tertiary-text-color: hsla(0, 0%, 6.7%, .4); + --yt-live-chat-text-input-field-inactive-underline-color: #b8b8b8; + --yt-live-chat-text-input-field-placeholder-color: hsla(0, 0%, 6.7%, .6); + --yt-live-chat-icon-button-color: hsla(0, 0%, 6.7%, .4); + --yt-live-chat-enabled-send-button-color: #4285f4; + --yt-live-chat-disabled-icon-button-color: hsla(0, 0%, 6.7%, .2); + --yt-live-chat-picker-button-color: hsla(0, 0%, 6.7%, .4); + --yt-live-chat-picker-button-active-color: hsla(0, 0%, 6.7%, .8); + --yt-live-chat-picker-button-disabled-color: var(--yt-live-chat-disabled-icon-button-color); + --yt-live-chat-picker-button-hover-color: hsla(0, 0%, 6.7%, .6); + --yt-live-chat-mention-background-color: #ff5722; + --yt-live-chat-mention-text-color: hsl(0, 0%, 100%); + --yt-live-chat-deleted-message-color: rgba(0, 0, 0, .5); + --yt-live-chat-deleted-message-bar-color: rgba(11, 11, 11, .2); + --yt-live-chat-disabled-button-background-color: hsl(0, 0%, 93.3%); + --yt-live-chat-disabled-button-text-color: hsla(0, 0%, 6.7%, .4); + --yt-live-chat-sub-panel-background-color: hsl(0, 0%, 93.3%); + --yt-live-chat-sub-panel-background-color-transparent: hsla(0, 0%, 93%, .7); + --yt-live-chat-header-background-color: hsla(0, 0%, 93.3%, .4); + --yt-live-chat-header-button-color: hsl(0, 0%, 6.7%); + --yt-live-chat-error-message-color: hsl(10, 51%, 49%); + --yt-live-chat-reconnect-message-color: hsla(0, 0%, 7%, 0.2); + --yt-live-chat-moderator-color: hsl(225, 84%, 66%); + --yt-live-chat-owner-color: hsl(40, 76%, 55%); + --yt-live-chat-author-chip-owner-text-color: rgba(0,0,0,0.87); + --yt-live-chat-author-chip-verified-background-color: #CCCCCC; + --yt-live-chat-author-chip-verified-text-color: #606060; + --yt-live-chat-message-highlight-background-color: #f8f8f8; + --yt-live-chat-sponsor-color: #107516; + --yt-live-chat-overlay-color: hsla(0, 0%, 0%, 0.6); + --yt-live-chat-dialog-background-color: hsl(0, 0%, 100%); + --yt-live-chat-dialog-text-color: hsla(0, 0%, 6.7%, .6); + --yt-live-chat-poll-choice-text-color: var(--yt-spec-text-secondary); + --yt-live-chat-poll-choice-border-color: var(--yt-spec-10-percent-layer); + --yt-live-chat-poll-choice-vote-bar-background-color: hsla(0, 0%, 93.3%, .8); + --yt-live-chat-poll-choice-vote-bar-background-color-selected: #F2F8FF; + --yt-live-chat-poll-choice-color-selected: #065FD4; + --yt-live-chat-moderation-mode-hover-background-color: hsla(0, 0%, 6.7%, .2); + --yt-live-chat-additional-inline-action-button-color: hsl(0, 0%, 100%); + --yt-live-chat-additional-inline-action-button-background-color: hsla(0, 0%, 26%, 0.8); + --yt-live-chat-additional-inline-action-button-background-color-hover: hsla(0, 0%, 26%, 1.0); + --yt-formatted-string-emoji-size: 24px; + --yt-live-chat-emoji-size: 24px; + --yt-live-chat-text-input-field-suggestion-background-color: hsl(0, 0%, 100%); + --yt-live-chat-text-input-field-suggestion-background-color-hover: #eee; + --yt-live-chat-text-input-field-suggestion-text-color: #666; + --yt-live-chat-text-input-field-suggestion-text-color-hover: #333; + --yt-live-chat-ticker-arrow-background: hsl(0, 0%, 97.3%); + --yt-emoji-picker-category-background-color: var(--yt-live-chat-action-panel-background-color-transparent); + --yt-emoji-picker-category-color: var(--yt-live-chat-secondary-text-color); + --yt-emoji-picker-category-button-color: var(--yt-live-chat-picker-button-color); + --yt-emoji-picker-search-background-color: hsla(0, 0%, 100%, .6); + --yt-emoji-picker-search-color: hsla(0, 0%, 6.7%, .8); + --yt-emoji-picker-search-placeholder-color: hsla(0, 0%, 6.7%, .6); + --yt-live-chat-slider-active-color: #2196f3; + --yt-live-chat-slider-container-color: #c8c8c8; + --yt-live-chat-slider-markers-color: #505050; + --yt-live-chat-toast-background-color: hsl(0, 0%, 20%); + --yt-live-chat-toast-text-color: hsl(0, 0%, 100%); + --yt-live-chat-automod-button-background-color: hsl(0, 0%, 93.3%); + --yt-live-chat-automod-button-background-color-hover: hsla(0, 0%, 6.7%, .2); + --yt-live-chat-countdown-opacity: 0.3; + --yt-live-chat-shimmer-background-color: rgba(136, 136, 136, 0.2); + --yt-live-chat-shimmer-linear-gradient: linear-gradient(0deg, rgba(255, 255, 255, 0) 40%, rgba(255, 255, 255, 0.5) 50%, rgba(255, 255, 255, 0) 65%); + --yt-live-chat-vem-background-color: hsl(0, 0%, 93.3%); + --yt-live-chat-upsell-dialog-renderer-button-padding: 10px 16px; + --yt-live-chat-product-picker-icon-color: rgba(17, 17, 17, 0.6); + --yt-live-chat-product-picker-hover-color: rgba(17, 17, 16, 0.1); + --yt-live-chat-product-picker-disabled-icon-color: rgba(17, 17, 17, 0.4); + --yt-pdg-paid-stickers-tab-selection-bar-color: #065FD4; + --yt-pdg-paid-stickers-author-name-font-size: 13px; + --yt-pdg-paid-stickers-margin-left: 38px; +} + +html:not(.style-scope) { + --layout_-_display: flex; + ; + + --layout-inline_-_display: inline-flex; + ; + + --layout-horizontal_-_display: var(--layout_-_display); + --layout-horizontal_-_-ms-flex-direction: row; + --layout-horizontal_-_-webkit-flex-direction: row; + --layout-horizontal_-_flex-direction: row; + ; + + --layout-horizontal-reverse_-_display: var(--layout_-_display); + --layout-horizontal-reverse_-_-ms-flex-direction: row-reverse; + --layout-horizontal-reverse_-_-webkit-flex-direction: row-reverse; + --layout-horizontal-reverse_-_flex-direction: row-reverse; + ; + + --layout-vertical_-_display: var(--layout_-_display); + --layout-vertical_-_-ms-flex-direction: column; + --layout-vertical_-_-webkit-flex-direction: column; + --layout-vertical_-_flex-direction: column; + ; + + --layout-vertical-reverse_-_display: var(--layout_-_display); + --layout-vertical-reverse_-_-ms-flex-direction: column-reverse; + --layout-vertical-reverse_-_-webkit-flex-direction: column-reverse; + --layout-vertical-reverse_-_flex-direction: column-reverse; + ; + + --layout-wrap_-_-ms-flex-wrap: wrap; + --layout-wrap_-_-webkit-flex-wrap: wrap; + --layout-wrap_-_flex-wrap: wrap; + ; + + --layout-wrap-reverse_-_-ms-flex-wrap: wrap-reverse; + --layout-wrap-reverse_-_-webkit-flex-wrap: wrap-reverse; + --layout-wrap-reverse_-_flex-wrap: wrap-reverse; + ; + + --layout-flex-auto_-_-ms-flex: 1 1 auto; + --layout-flex-auto_-_-webkit-flex: 1 1 auto; + --layout-flex-auto_-_flex: 1 1 auto; + ; + + --layout-flex-none_-_-ms-flex: none; + --layout-flex-none_-_-webkit-flex: none; + --layout-flex-none_-_flex: none; + ; + + --layout-flex_-_-ms-flex: 1 1 0.000000001px; + --layout-flex_-_-webkit-flex: 1; + --layout-flex_-_flex: 1; + --layout-flex_-_-webkit-flex-basis: 0.000000001px; + --layout-flex_-_flex-basis: 0.000000001px; + ; + + --layout-flex-2_-_-ms-flex: 2; + --layout-flex-2_-_-webkit-flex: 2; + --layout-flex-2_-_flex: 2; + ; + + --layout-flex-3_-_-ms-flex: 3; + --layout-flex-3_-_-webkit-flex: 3; + --layout-flex-3_-_flex: 3; + ; + + --layout-flex-4_-_-ms-flex: 4; + --layout-flex-4_-_-webkit-flex: 4; + --layout-flex-4_-_flex: 4; + ; + + --layout-flex-5_-_-ms-flex: 5; + --layout-flex-5_-_-webkit-flex: 5; + --layout-flex-5_-_flex: 5; + ; + + --layout-flex-6_-_-ms-flex: 6; + --layout-flex-6_-_-webkit-flex: 6; + --layout-flex-6_-_flex: 6; + ; + + --layout-flex-7_-_-ms-flex: 7; + --layout-flex-7_-_-webkit-flex: 7; + --layout-flex-7_-_flex: 7; + ; + + --layout-flex-8_-_-ms-flex: 8; + --layout-flex-8_-_-webkit-flex: 8; + --layout-flex-8_-_flex: 8; + ; + + --layout-flex-9_-_-ms-flex: 9; + --layout-flex-9_-_-webkit-flex: 9; + --layout-flex-9_-_flex: 9; + ; + + --layout-flex-10_-_-ms-flex: 10; + --layout-flex-10_-_-webkit-flex: 10; + --layout-flex-10_-_flex: 10; + ; + + --layout-flex-11_-_-ms-flex: 11; + --layout-flex-11_-_-webkit-flex: 11; + --layout-flex-11_-_flex: 11; + ; + + --layout-flex-12_-_-ms-flex: 12; + --layout-flex-12_-_-webkit-flex: 12; + --layout-flex-12_-_flex: 12; + ; + + + + --layout-start_-_-ms-flex-align: start; + --layout-start_-_-webkit-align-items: flex-start; + --layout-start_-_align-items: flex-start; + ; + + --layout-center_-_-ms-flex-align: center; + --layout-center_-_-webkit-align-items: center; + --layout-center_-_align-items: center; + ; + + --layout-end_-_-ms-flex-align: end; + --layout-end_-_-webkit-align-items: flex-end; + --layout-end_-_align-items: flex-end; + ; + + --layout-baseline_-_-ms-flex-align: baseline; + --layout-baseline_-_-webkit-align-items: baseline; + --layout-baseline_-_align-items: baseline; + ; + + + + --layout-start-justified_-_-ms-flex-pack: start; + --layout-start-justified_-_-webkit-justify-content: flex-start; + --layout-start-justified_-_justify-content: flex-start; + ; + + --layout-center-justified_-_-ms-flex-pack: center; + --layout-center-justified_-_-webkit-justify-content: center; + --layout-center-justified_-_justify-content: center; + ; + + --layout-end-justified_-_-ms-flex-pack: end; + --layout-end-justified_-_-webkit-justify-content: flex-end; + --layout-end-justified_-_justify-content: flex-end; + ; + + --layout-around-justified_-_-ms-flex-pack: distribute; + --layout-around-justified_-_-webkit-justify-content: space-around; + --layout-around-justified_-_justify-content: space-around; + ; + + --layout-justified_-_-ms-flex-pack: justify; + --layout-justified_-_-webkit-justify-content: space-between; + --layout-justified_-_justify-content: space-between; + ; + + --layout-center-center_-_-ms-flex-align: var(--layout-center_-_-ms-flex-align); + --layout-center-center_-_-webkit-align-items: var(--layout-center_-_-webkit-align-items); + --layout-center-center_-_align-items: var(--layout-center_-_align-items); + --layout-center-center_-_-ms-flex-pack: var(--layout-center-justified_-_-ms-flex-pack); + --layout-center-center_-_-webkit-justify-content: var(--layout-center-justified_-_-webkit-justify-content); + --layout-center-center_-_justify-content: var(--layout-center-justified_-_justify-content); + ; + + + + --layout-self-start_-_-ms-align-self: flex-start; + --layout-self-start_-_-webkit-align-self: flex-start; + --layout-self-start_-_align-self: flex-start; + ; + + --layout-self-center_-_-ms-align-self: center; + --layout-self-center_-_-webkit-align-self: center; + --layout-self-center_-_align-self: center; + ; + + --layout-self-end_-_-ms-align-self: flex-end; + --layout-self-end_-_-webkit-align-self: flex-end; + --layout-self-end_-_align-self: flex-end; + ; + + --layout-self-stretch_-_-ms-align-self: stretch; + --layout-self-stretch_-_-webkit-align-self: stretch; + --layout-self-stretch_-_align-self: stretch; + ; + + --layout-self-baseline_-_-ms-align-self: baseline; + --layout-self-baseline_-_-webkit-align-self: baseline; + --layout-self-baseline_-_align-self: baseline; + ; + + + + --layout-start-aligned_-_-ms-flex-line-pack: start; + --layout-start-aligned_-_-ms-align-content: flex-start; + --layout-start-aligned_-_-webkit-align-content: flex-start; + --layout-start-aligned_-_align-content: flex-start; + ; + + --layout-end-aligned_-_-ms-flex-line-pack: end; + --layout-end-aligned_-_-ms-align-content: flex-end; + --layout-end-aligned_-_-webkit-align-content: flex-end; + --layout-end-aligned_-_align-content: flex-end; + ; + + --layout-center-aligned_-_-ms-flex-line-pack: center; + --layout-center-aligned_-_-ms-align-content: center; + --layout-center-aligned_-_-webkit-align-content: center; + --layout-center-aligned_-_align-content: center; + ; + + --layout-between-aligned_-_-ms-flex-line-pack: justify; + --layout-between-aligned_-_-ms-align-content: space-between; + --layout-between-aligned_-_-webkit-align-content: space-between; + --layout-between-aligned_-_align-content: space-between; + ; + + --layout-around-aligned_-_-ms-flex-line-pack: distribute; + --layout-around-aligned_-_-ms-align-content: space-around; + --layout-around-aligned_-_-webkit-align-content: space-around; + --layout-around-aligned_-_align-content: space-around; + ; + + + + --layout-block_-_display: block; + ; + + --layout-invisible_-_visibility: hidden !important; + ; + + --layout-relative_-_position: relative; + ; + + --layout-fit_-_position: absolute; + --layout-fit_-_top: 0; + --layout-fit_-_right: 0; + --layout-fit_-_bottom: 0; + --layout-fit_-_left: 0; + ; + + --layout-scroll_-_-webkit-overflow-scrolling: touch; + --layout-scroll_-_overflow: auto; + ; + + --layout-fullbleed_-_margin: 0; + --layout-fullbleed_-_height: 100vh; + ; + + + + --layout-fixed-top_-_position: fixed; + --layout-fixed-top_-_top: 0; + --layout-fixed-top_-_left: 0; + --layout-fixed-top_-_right: 0; + ; + + --layout-fixed-right_-_position: fixed; + --layout-fixed-right_-_top: 0; + --layout-fixed-right_-_right: 0; + --layout-fixed-right_-_bottom: 0; + ; + + --layout-fixed-bottom_-_position: fixed; + --layout-fixed-bottom_-_right: 0; + --layout-fixed-bottom_-_bottom: 0; + --layout-fixed-bottom_-_left: 0; + ; + + --layout-fixed-left_-_position: fixed; + --layout-fixed-left_-_top: 0; + --layout-fixed-left_-_bottom: 0; + --layout-fixed-left_-_left: 0; + ; +} diff --git a/src/assets/css/youtube/yt-icon.css b/src/assets/css/youtube/yt-icon.css new file mode 100644 index 0000000..c21acf2 --- /dev/null +++ b/src/assets/css/youtube/yt-icon.css @@ -0,0 +1,30 @@ +canvas.yt-icon, caption.yt-icon, center.yt-icon, cite.yt-icon, code.yt-icon, dd.yt-icon, del.yt-icon, dfn.yt-icon, div.yt-icon, dl.yt-icon, dt.yt-icon, em.yt-icon, embed.yt-icon, fieldset.yt-icon, font.yt-icon, form.yt-icon, h1.yt-icon, h2.yt-icon, h3.yt-icon, h4.yt-icon, h5.yt-icon, h6.yt-icon, hr.yt-icon, i.yt-icon, iframe.yt-icon, img.yt-icon, ins.yt-icon, kbd.yt-icon, label.yt-icon, legend.yt-icon, li.yt-icon, menu.yt-icon, object.yt-icon, ol.yt-icon, p.yt-icon, pre.yt-icon, q.yt-icon, s.yt-icon, samp.yt-icon, small.yt-icon, span.yt-icon, strike.yt-icon, strong.yt-icon, sub.yt-icon, sup.yt-icon, table.yt-icon, tbody.yt-icon, td.yt-icon, tfoot.yt-icon, th.yt-icon, thead.yt-icon, tr.yt-icon, tt.yt-icon, u.yt-icon, ul.yt-icon, var.yt-icon { + margin: 0; + padding: 0; + border: 0; + background: transparent; +} + +.yt-icon[hidden] { + display: none !important; +} + +yt-icon, .yt-icon-container.yt-icon { + display: inline-flex; + -ms-flex-align: center; + -webkit-align-items: center; + align-items: center; + -ms-flex-pack: center; + -webkit-justify-content: center; + justify-content: center; + position: relative; + vertical-align: middle; + fill: currentcolor; + stroke: none; + width: var(--iron-icon-width, 24px); + height: var(--iron-icon-height, 24px); +} + +yt-icon.external-container { + display: none !important; +} diff --git a/src/assets/css/youtube/yt-img-shadow.css b/src/assets/css/youtube/yt-img-shadow.css new file mode 100644 index 0000000..e4ea828 --- /dev/null +++ b/src/assets/css/youtube/yt-img-shadow.css @@ -0,0 +1,68 @@ +canvas.yt-img-shadow, caption.yt-img-shadow, center.yt-img-shadow, cite.yt-img-shadow, code.yt-img-shadow, dd.yt-img-shadow, del.yt-img-shadow, dfn.yt-img-shadow, div.yt-img-shadow, dl.yt-img-shadow, dt.yt-img-shadow, em.yt-img-shadow, embed.yt-img-shadow, fieldset.yt-img-shadow, font.yt-img-shadow, form.yt-img-shadow, h1.yt-img-shadow, h2.yt-img-shadow, h3.yt-img-shadow, h4.yt-img-shadow, h5.yt-img-shadow, h6.yt-img-shadow, hr.yt-img-shadow, i.yt-img-shadow, iframe.yt-img-shadow, img.yt-img-shadow, ins.yt-img-shadow, kbd.yt-img-shadow, label.yt-img-shadow, legend.yt-img-shadow, li.yt-img-shadow, menu.yt-img-shadow, object.yt-img-shadow, ol.yt-img-shadow, p.yt-img-shadow, pre.yt-img-shadow, q.yt-img-shadow, s.yt-img-shadow, samp.yt-img-shadow, small.yt-img-shadow, span.yt-img-shadow, strike.yt-img-shadow, strong.yt-img-shadow, sub.yt-img-shadow, sup.yt-img-shadow, table.yt-img-shadow, tbody.yt-img-shadow, td.yt-img-shadow, tfoot.yt-img-shadow, th.yt-img-shadow, thead.yt-img-shadow, tr.yt-img-shadow, tt.yt-img-shadow, u.yt-img-shadow, ul.yt-img-shadow, var.yt-img-shadow { + margin: 0; + padding: 0; + border: 0; + background: transparent; +} + +.yt-img-shadow[hidden] { + display: none !important; +} + +yt-img-shadow { + display: inline-block; + opacity: 0; + transition: opacity 0.2s; + -ms-flex: none; + -webkit-flex: none; + flex: none; +} + +yt-img-shadow.no-transition { + opacity: 1; + transition: none; +} + +yt-img-shadow.with-placeholder { + background-color: transparent; + min-height: unset; + min-width: unset; +} + +yt-img-shadow[loaded] { + opacity: 1; +} + +yt-img-shadow.empty img.yt-img-shadow { + visibility: hidden; +} + +yt-img-shadow[object-fit="FILL"] img.yt-img-shadow, yt-img-shadow[fit] img.yt-img-shadow { + width: 100%; + height: 100%; +} + +yt-img-shadow[object-fit="COVER"] img.yt-img-shadow { + width: 100%; + height: 100%; + object-fit: cover; +} + +yt-img-shadow[object-fit="CONTAIN"] img.yt-img-shadow { + width: 100%; + height: 100%; + object-fit: contain; +} + +yt-img-shadow[object-position="LEFT"] img.yt-img-shadow { + object-position: left; +} + +img.yt-img-shadow { + display: block; + margin-left: auto; + margin-right: auto; + max-height: none; + max-width: 100%; + border-radius: none; +} diff --git a/src/assets/css/youtube/yt-live-chat-author-badge-renderer.css b/src/assets/css/youtube/yt-live-chat-author-badge-renderer.css new file mode 100644 index 0000000..9a0b840 --- /dev/null +++ b/src/assets/css/youtube/yt-live-chat-author-badge-renderer.css @@ -0,0 +1,36 @@ +canvas.yt-live-chat-author-badge-renderer, caption.yt-live-chat-author-badge-renderer, center.yt-live-chat-author-badge-renderer, cite.yt-live-chat-author-badge-renderer, code.yt-live-chat-author-badge-renderer, dd.yt-live-chat-author-badge-renderer, del.yt-live-chat-author-badge-renderer, dfn.yt-live-chat-author-badge-renderer, div.yt-live-chat-author-badge-renderer, dl.yt-live-chat-author-badge-renderer, dt.yt-live-chat-author-badge-renderer, em.yt-live-chat-author-badge-renderer, embed.yt-live-chat-author-badge-renderer, fieldset.yt-live-chat-author-badge-renderer, font.yt-live-chat-author-badge-renderer, form.yt-live-chat-author-badge-renderer, h1.yt-live-chat-author-badge-renderer, h2.yt-live-chat-author-badge-renderer, h3.yt-live-chat-author-badge-renderer, h4.yt-live-chat-author-badge-renderer, h5.yt-live-chat-author-badge-renderer, h6.yt-live-chat-author-badge-renderer, hr.yt-live-chat-author-badge-renderer, i.yt-live-chat-author-badge-renderer, iframe.yt-live-chat-author-badge-renderer, img.yt-live-chat-author-badge-renderer, ins.yt-live-chat-author-badge-renderer, kbd.yt-live-chat-author-badge-renderer, label.yt-live-chat-author-badge-renderer, legend.yt-live-chat-author-badge-renderer, li.yt-live-chat-author-badge-renderer, menu.yt-live-chat-author-badge-renderer, object.yt-live-chat-author-badge-renderer, ol.yt-live-chat-author-badge-renderer, p.yt-live-chat-author-badge-renderer, pre.yt-live-chat-author-badge-renderer, q.yt-live-chat-author-badge-renderer, s.yt-live-chat-author-badge-renderer, samp.yt-live-chat-author-badge-renderer, small.yt-live-chat-author-badge-renderer, span.yt-live-chat-author-badge-renderer, strike.yt-live-chat-author-badge-renderer, strong.yt-live-chat-author-badge-renderer, sub.yt-live-chat-author-badge-renderer, sup.yt-live-chat-author-badge-renderer, table.yt-live-chat-author-badge-renderer, tbody.yt-live-chat-author-badge-renderer, td.yt-live-chat-author-badge-renderer, tfoot.yt-live-chat-author-badge-renderer, th.yt-live-chat-author-badge-renderer, thead.yt-live-chat-author-badge-renderer, tr.yt-live-chat-author-badge-renderer, tt.yt-live-chat-author-badge-renderer, u.yt-live-chat-author-badge-renderer, ul.yt-live-chat-author-badge-renderer, var.yt-live-chat-author-badge-renderer { + margin: 0; + padding: 0; + border: 0; + background: transparent; +} + +.yt-live-chat-author-badge-renderer[hidden] { + display: none !important; +} + +yt-live-chat-author-badge-renderer { + display: inline-block; +} + +yt-live-chat-author-badge-renderer[type='moderator'] { + color: var(--yt-live-chat-moderator-color, #5e84f1); +} + +yt-live-chat-author-badge-renderer[type='owner'] { + color: var(--yt-live-chat-owner-color, #ffd600); +} + +yt-live-chat-author-badge-renderer[type='member'] { + color: var(--yt-live-chat-sponsor-color, #107516); +} + +yt-live-chat-author-badge-renderer[type='verified'] { + color: #999; +} + +img.yt-live-chat-author-badge-renderer, yt-icon.yt-live-chat-author-badge-renderer { + display: block; + width: 16px; + height: 16px; +} diff --git a/src/assets/css/youtube/yt-live-chat-author-chip.css b/src/assets/css/youtube/yt-live-chat-author-chip.css new file mode 100644 index 0000000..2ce7ed4 --- /dev/null +++ b/src/assets/css/youtube/yt-live-chat-author-chip.css @@ -0,0 +1,64 @@ +canvas.yt-live-chat-author-chip, caption.yt-live-chat-author-chip, center.yt-live-chat-author-chip, cite.yt-live-chat-author-chip, code.yt-live-chat-author-chip, dd.yt-live-chat-author-chip, del.yt-live-chat-author-chip, dfn.yt-live-chat-author-chip, div.yt-live-chat-author-chip, dl.yt-live-chat-author-chip, dt.yt-live-chat-author-chip, em.yt-live-chat-author-chip, embed.yt-live-chat-author-chip, fieldset.yt-live-chat-author-chip, font.yt-live-chat-author-chip, form.yt-live-chat-author-chip, h1.yt-live-chat-author-chip, h2.yt-live-chat-author-chip, h3.yt-live-chat-author-chip, h4.yt-live-chat-author-chip, h5.yt-live-chat-author-chip, h6.yt-live-chat-author-chip, hr.yt-live-chat-author-chip, i.yt-live-chat-author-chip, iframe.yt-live-chat-author-chip, img.yt-live-chat-author-chip, ins.yt-live-chat-author-chip, kbd.yt-live-chat-author-chip, label.yt-live-chat-author-chip, legend.yt-live-chat-author-chip, li.yt-live-chat-author-chip, menu.yt-live-chat-author-chip, object.yt-live-chat-author-chip, ol.yt-live-chat-author-chip, p.yt-live-chat-author-chip, pre.yt-live-chat-author-chip, q.yt-live-chat-author-chip, s.yt-live-chat-author-chip, samp.yt-live-chat-author-chip, small.yt-live-chat-author-chip, span.yt-live-chat-author-chip, strike.yt-live-chat-author-chip, strong.yt-live-chat-author-chip, sub.yt-live-chat-author-chip, sup.yt-live-chat-author-chip, table.yt-live-chat-author-chip, tbody.yt-live-chat-author-chip, td.yt-live-chat-author-chip, tfoot.yt-live-chat-author-chip, th.yt-live-chat-author-chip, thead.yt-live-chat-author-chip, tr.yt-live-chat-author-chip, tt.yt-live-chat-author-chip, u.yt-live-chat-author-chip, ul.yt-live-chat-author-chip, var.yt-live-chat-author-chip { + margin: 0; + padding: 0; + border: 0; + background: transparent; +} + +.yt-live-chat-author-chip[hidden] { + display: none !important; +} + +yt-live-chat-author-chip { + display: inline-flex; + -ms-flex-align: baseline; + -webkit-align-items: baseline; + align-items: baseline; +} + +#author-name.yt-live-chat-author-chip { + box-sizing: border-box; + border-radius: 2px; + color: var(--yt-live-chat-secondary-text-color); + font-weight: 500; +} + +yt-live-chat-author-chip[is-highlighted] #author-name.yt-live-chat-author-chip { + padding: 2px 4px; + color: var(--yt-live-chat-author-chip-verified-text-color); + background-color: var(--yt-live-chat-author-chip-verified-background-color); +} + +#author-name.yt-live-chat-author-chip[type='moderator'] { + color: var(--yt-live-chat-moderator-color); +} + +yt-live-chat-author-chip[is-highlighted] #author-name.yt-live-chat-author-chip[type='owner'], #author-name.yt-live-chat-author-chip[type='owner'] { + background-color: #ffd600; + color: var(--yt-live-chat-author-chip-owner-text-color); +} + +#author-name.yt-live-chat-author-chip[type='member'] { + color: var(--yt-live-chat-sponsor-color); +} + +#chip-badges.yt-live-chat-author-chip:empty { + display: none; +} + +yt-live-chat-author-chip[is-highlighted] #chat-badges.yt-live-chat-author-chip:not(:empty) { + margin-left: 1px; +} + +yt-live-chat-author-badge-renderer.yt-live-chat-author-chip { + margin: 0 0 0 2px; + vertical-align: sub; +} + +yt-live-chat-author-chip[is-highlighted] #chip-badges.yt-live-chat-author-chip yt-live-chat-author-badge-renderer.yt-live-chat-author-chip { + color: inherit; +} + +#chip-badges.yt-live-chat-author-chip yt-live-chat-author-badge-renderer.yt-live-chat-author-chip:last-of-type { + margin-right: -2px; +} diff --git a/src/assets/css/youtube/yt-live-chat-item-list-renderer.css b/src/assets/css/youtube/yt-live-chat-item-list-renderer.css new file mode 100644 index 0000000..7eaad8b --- /dev/null +++ b/src/assets/css/youtube/yt-live-chat-item-list-renderer.css @@ -0,0 +1,140 @@ +canvas.yt-live-chat-item-list-renderer, caption.yt-live-chat-item-list-renderer, center.yt-live-chat-item-list-renderer, cite.yt-live-chat-item-list-renderer, code.yt-live-chat-item-list-renderer, dd.yt-live-chat-item-list-renderer, del.yt-live-chat-item-list-renderer, dfn.yt-live-chat-item-list-renderer, div.yt-live-chat-item-list-renderer, dl.yt-live-chat-item-list-renderer, dt.yt-live-chat-item-list-renderer, em.yt-live-chat-item-list-renderer, embed.yt-live-chat-item-list-renderer, fieldset.yt-live-chat-item-list-renderer, font.yt-live-chat-item-list-renderer, form.yt-live-chat-item-list-renderer, h1.yt-live-chat-item-list-renderer, h2.yt-live-chat-item-list-renderer, h3.yt-live-chat-item-list-renderer, h4.yt-live-chat-item-list-renderer, h5.yt-live-chat-item-list-renderer, h6.yt-live-chat-item-list-renderer, hr.yt-live-chat-item-list-renderer, i.yt-live-chat-item-list-renderer, iframe.yt-live-chat-item-list-renderer, img.yt-live-chat-item-list-renderer, ins.yt-live-chat-item-list-renderer, kbd.yt-live-chat-item-list-renderer, label.yt-live-chat-item-list-renderer, legend.yt-live-chat-item-list-renderer, li.yt-live-chat-item-list-renderer, menu.yt-live-chat-item-list-renderer, object.yt-live-chat-item-list-renderer, ol.yt-live-chat-item-list-renderer, p.yt-live-chat-item-list-renderer, pre.yt-live-chat-item-list-renderer, q.yt-live-chat-item-list-renderer, s.yt-live-chat-item-list-renderer, samp.yt-live-chat-item-list-renderer, small.yt-live-chat-item-list-renderer, span.yt-live-chat-item-list-renderer, strike.yt-live-chat-item-list-renderer, strong.yt-live-chat-item-list-renderer, sub.yt-live-chat-item-list-renderer, sup.yt-live-chat-item-list-renderer, table.yt-live-chat-item-list-renderer, tbody.yt-live-chat-item-list-renderer, td.yt-live-chat-item-list-renderer, tfoot.yt-live-chat-item-list-renderer, th.yt-live-chat-item-list-renderer, thead.yt-live-chat-item-list-renderer, tr.yt-live-chat-item-list-renderer, tt.yt-live-chat-item-list-renderer, u.yt-live-chat-item-list-renderer, ul.yt-live-chat-item-list-renderer, var.yt-live-chat-item-list-renderer { + margin: 0; + padding: 0; + border: 0; + background: transparent; +} + +.yt-live-chat-item-list-renderer[hidden] { + display: none !important; +} + +yt-live-chat-item-list-renderer { + position: relative; + display: block; + overflow: hidden; + z-index: 0; +} + +yt-live-chat-item-list-renderer[moderation-mode-enabled] { + --yt-live-chat-item-with-inline-actions-context-menu-display: none; + --yt-live-chat-inline-action-button-container-display: flex; +} + +#contents.yt-live-chat-item-list-renderer { + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; + display: flex; + -ms-flex-direction: column; + -webkit-flex-direction: column; + flex-direction: column; +} + +#empty-state-message.yt-live-chat-item-list-renderer { + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; + display: flex; + -ms-flex-direction: column; + -webkit-flex-direction: column; + flex-direction: column; + -ms-flex-pack: center; + -webkit-justify-content: center; + justify-content: center; +} + +#empty-state-message.yt-live-chat-item-list-renderer>yt-live-chat-message-renderer.yt-live-chat-item-list-renderer { + color: var(--yt-live-chat-tertiary-text-color); + background: transparent; + font-size: 18px; + --yt-live-chat-message-renderer-text-align: center; +} + +yt-icon-button.yt-live-chat-item-list-renderer { + background-color: #2196f3; + border-radius: 999px; + bottom: 0; + color: #fff; + cursor: pointer; + width: 32px; + height: 32px; + margin: 0 calc(50% - 16px) 8px calc(50% - 16px); + padding: 4px; + position: absolute; + transition-property: bottom; + transition-timing-function: cubic-bezier(0.0, 0.0, 0.2, 1); + transition-duration: 0.15s; + box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.14), 0 1px 5px 0 rgba(0, 0, 0, 0.12), 0 3px 1px -2px rgba(0, 0, 0, 0.2); +} + +yt-icon-button.yt-live-chat-item-list-renderer[disabled] { + bottom: -42px; + color: #fff; + transition-timing-function: cubic-bezier(0.4, 0.0, 1, 1); +} + +#item-scroller.yt-live-chat-item-list-renderer { + -ms-flex: 1 1 0.000000001px; + -webkit-flex: 1; + flex: 1; + -webkit-flex-basis: 0.000000001px; + flex-basis: 0.000000001px; + overflow-x: hidden; + overflow-y: hidden; + padding-right: var(--scrollbar-width); +} + +yt-live-chat-item-list-renderer[allow-scroll] #item-scroller.yt-live-chat-item-list-renderer { + overflow-y: scroll; + padding-right: 0; +} + +#item-offset.yt-live-chat-item-list-renderer { + position: relative; +} + +#item-scroller.animated.yt-live-chat-item-list-renderer #item-offset.yt-live-chat-item-list-renderer { + overflow: hidden; +} + +#items.yt-live-chat-item-list-renderer { + -ms-flex: 1 1 0.000000001px; + -webkit-flex: 1; + flex: 1; + -webkit-flex-basis: 0.000000001px; + flex-basis: 0.000000001px; + padding: var(--yt-live-chat-item-list-renderer-padding, 4px 0); +} + +#items.yt-live-chat-item-list-renderer>*.yt-live-chat-item-list-renderer:not(:first-child) { + border-top: var(--yt-live-chat-item-list-item-border, none); +} + +#item-scroller.animated.yt-live-chat-item-list-renderer #items.yt-live-chat-item-list-renderer { + bottom: 0; + left: 0; + position: absolute; + right: 0; + transform: translateY(0); +} + +#docked-messages.yt-live-chat-item-list-renderer { + z-index: 1; + position: absolute; + left: 0; + right: 0; + top: 0; +} + +yt-live-chat-paid-sticker-renderer.yt-live-chat-item-list-renderer { + padding: 4px 24px; +} + +yt-live-chat-paid-sticker-renderer.yt-live-chat-item-list-renderer[dashboard-money-feed] { + padding: 8px 16px; +} diff --git a/src/assets/css/youtube/yt-live-chat-membership-item-renderer.css b/src/assets/css/youtube/yt-live-chat-membership-item-renderer.css new file mode 100644 index 0000000..6a1c2ca --- /dev/null +++ b/src/assets/css/youtube/yt-live-chat-membership-item-renderer.css @@ -0,0 +1,362 @@ +#timestamp.yt-live-chat-membership-item-renderer { + display: var(--yt-live-chat-item-timestamp-display, inline); + margin: var(--yt-live-chat-item-timestamp-margin, 0 8px 0 0); + color: var(--yt-live-chat-tertiary-text-color); + font-size: 11px; +} + +#author-photo.yt-live-chat-membership-item-renderer { + display: block; + margin-right: 16px; + + overflow: hidden; + border-radius: 50%; + + -ms-flex: var(--layout-flex-none_-_-ms-flex); + -webkit-flex: var(--layout-flex-none_-_-webkit-flex); + flex: var(--layout-flex-none_-_flex); +} + +#menu-button.yt-live-chat-membership-item-renderer { + width: var(--yt-live-chat-32px-icon-button_-_width); + height: var(--yt-live-chat-32px-icon-button_-_height); + padding: var(--yt-live-chat-32px-icon-button_-_padding); +} + +#menu.yt-live-chat-membership-item-renderer { + position: absolute; + top: 0; + bottom: 0; + right: 0; + + + transform: translateX(100px); +} + +yt-live-chat-membership-item-renderer:hover #menu.yt-live-chat-membership-item-renderer, +yt-live-chat-membership-item-renderer[menu-visible] #menu.yt-live-chat-membership-item-renderer { + transform: none; +} + +yt-live-chat-membership-item-renderer:focus-within #menu.yt-live-chat-membership-item-renderer { + transform: none; +} + +#inline-action-button-container.yt-live-chat-membership-item-renderer { + position: absolute; + top: -4px; + right: 0; + bottom: -4px; + left: 0; + + background-color: var(--yt-live-chat-moderation-mode-hover-background-color); + display: none; + + -ms-flex-align: var(--layout-center-center_-_-ms-flex-align); + -webkit-align-items: var(--layout-center-center_-_-webkit-align-items); + align-items: var(--layout-center-center_-_align-items); + -ms-flex-pack: var(--layout-center-center_-_-ms-flex-pack); + -webkit-justify-content: var(--layout-center-center_-_-webkit-justify-content); + justify-content: var(--layout-center-center_-_justify-content); +} + +yt-live-chat-membership-item-renderer[has-inline-action-buttons]:hover #inline-action-button-container.yt-live-chat-membership-item-renderer { + display: var(--layout-horizontal_-_display); + -ms-flex-direction: var(--layout-horizontal_-_-ms-flex-direction); + -webkit-flex-direction: var(--layout-horizontal_-_-webkit-flex-direction); + flex-direction: var(--layout-horizontal_-_flex-direction); + + + display: var(--yt-live-chat-inline-action-button-container-display, none); +} + +yt-live-chat-membership-item-renderer[has-inline-action-buttons][hide-inline-action-buttons]:hover #inline-action-button-container.yt-live-chat-membership-item-renderer { + display: none; +} + +yt-live-chat-membership-item-renderer[has-inline-action-buttons]:hover #menu.yt-live-chat-membership-item-renderer { + display: var(--yt-live-chat-item-with-inline-actions-context-menu-display, block); +} + +#inline-action-buttons.yt-live-chat-membership-item-renderer>*.yt-live-chat-membership-item-renderer, +#additional-inline-action-buttons.yt-live-chat-membership-item-renderer>*.yt-live-chat-membership-item-renderer { + --yt-button-icon-size: 36px; + --yt-button-icon-padding: 6px; + + color: var(--yt-white); + border-radius: 2px; +} + +#inline-action-buttons.yt-live-chat-membership-item-renderer>*.yt-live-chat-membership-item-renderer { + background: var(--yt-luna-black-opacity-lighten-1); +} + +#inline-action-buttons.yt-live-chat-membership-item-renderer>.yt-live-chat-membership-item-renderer:hover { + background: var(--yt-luna-black); +} + +#additional-inline-action-buttons.yt-live-chat-membership-item-renderer>*.yt-live-chat-membership-item-renderer { + color: var(--yt-live-chat-additional-inline-action-button-color); + background: var(--yt-live-chat-additional-inline-action-button-background-color); +} + +#additional-inline-action-buttons.yt-live-chat-membership-item-renderer>.yt-live-chat-membership-item-renderer:hover { + background: var(--yt-live-chat-additional-inline-action-button-background-color-hover); +} + +#additional-inline-action-buttons.yt-live-chat-membership-item-renderer:not(:empty) { + margin-left: 32px; +} + +#inline-action-buttons.yt-live-chat-membership-item-renderer>*.yt-live-chat-membership-item-renderer:not(:first-child), +#additional-inline-action-buttons.yt-live-chat-membership-item-renderer>*.yt-live-chat-membership-item-renderer:not(:first-child) { + margin-left: 8px; +} + +yt-live-chat-membership-item-renderer { + position: relative; + display: block; + + --yt-live-chat-sponsor-header-color: #0a8043; + --yt-live-chat-sponsor-color: #0f9d58; + --yt-live-chat-sponsor-text-color: #fff; + --yt-live-chat-item-timestamp-display: var(--yt-live-chat-paid-message-timestamp-display, none); + + padding: 4px 24px; +} + +yt-live-chat-membership-item-renderer[dashboard-money-feed] { + padding: 0; + + --yt-live-chat-item-timestamp-display: block; +} + +#card.yt-live-chat-membership-item-renderer { + overflow: hidden; + font-size: 14px; + border-radius: 4px; + + display: var(--layout-vertical_-_display); + -ms-flex-direction: var(--layout-vertical_-_-ms-flex-direction); + -webkit-flex-direction: var(--layout-vertical_-_-webkit-flex-direction); + flex-direction: var(--layout-vertical_-_flex-direction); + box-shadow: var(--shadow-elevation-2dp_-_box-shadow); +} + +yt-live-chat-membership-item-renderer[dashboard-money-feed] #card.yt-live-chat-membership-item-renderer { + border-radius: 0; + box-shadow: none; +} + +#header.yt-live-chat-membership-item-renderer { + position: relative; + + background-color: var(--yt-live-chat-sponsor-header-color); + padding: 8px 16px; + color: #fff; + min-height: 20px; + + display: var(--layout-horizontal_-_display); + -ms-flex-direction: var(--layout-horizontal_-_-ms-flex-direction); + -webkit-flex-direction: var(--layout-horizontal_-_-webkit-flex-direction); + flex-direction: var(--layout-horizontal_-_flex-direction); + -ms-flex-align: var(--layout-center_-_-ms-flex-align); + -webkit-align-items: var(--layout-center_-_-webkit-align-items); + align-items: var(--layout-center_-_align-items); +} + +yt-live-chat-membership-item-renderer[show-only-header] #header.yt-live-chat-membership-item-renderer { + background-color: var(--yt-live-chat-sponsor-color); +} + +yt-live-chat-membership-item-renderer[dashboard-money-feed] #header.yt-live-chat-membership-item-renderer { + color: var(--yt-live-chat-secondary-text-color); + background-color: var(--yt-live-chat-background-color); + -ms-flex-align: var(--layout-start_-_-ms-flex-align); + -webkit-align-items: var(--layout-start_-_-webkit-align-items); + align-items: var(--layout-start_-_align-items); +} + +#header-content.yt-live-chat-membership-item-renderer { + display: var(--layout-horizontal_-_display); + -ms-flex-direction: var(--layout-horizontal_-_-ms-flex-direction); + -webkit-flex-direction: var(--layout-horizontal_-_-webkit-flex-direction); + flex-direction: var(--layout-horizontal_-_flex-direction); + -ms-flex-pack: var(--layout-justified_-_-ms-flex-pack); + -webkit-justify-content: var(--layout-justified_-_-webkit-justify-content); + justify-content: var(--layout-justified_-_justify-content); + -ms-flex: var(--layout-flex_-_-ms-flex); + -webkit-flex: var(--layout-flex_-_-webkit-flex); + flex: var(--layout-flex_-_flex); + -webkit-flex-basis: var(--layout-flex_-_-webkit-flex-basis); + flex-basis: var(--layout-flex_-_flex-basis); + -ms-flex-align: var(--layout-baseline_-_-ms-flex-align); + -webkit-align-items: var(--layout-baseline_-_-webkit-align-items); + align-items: var(--layout-baseline_-_align-items); +} + +yt-live-chat-membership-item-renderer[dashboard-money-feed] #header-content.yt-live-chat-membership-item-renderer { + display: var(--layout-vertical_-_display); + -ms-flex-direction: var(--layout-vertical_-_-ms-flex-direction); + -webkit-flex-direction: var(--layout-vertical_-_-webkit-flex-direction); + flex-direction: var(--layout-vertical_-_flex-direction); +} + +yt-live-chat-membership-item-renderer[dashboard-money-feed] #header-content-inner-column.yt-live-chat-membership-item-renderer { + margin-bottom: 4px; + + display: var(--layout-horizontal_-_display); + -ms-flex-direction: var(--layout-horizontal_-_-ms-flex-direction); + -webkit-flex-direction: var(--layout-horizontal_-_-webkit-flex-direction); + flex-direction: var(--layout-horizontal_-_flex-direction); + -ms-flex-align: var(--layout-center_-_-ms-flex-align); + -webkit-align-items: var(--layout-center_-_-webkit-align-items); + align-items: var(--layout-center_-_align-items); + -ms-flex: var(--layout-flex-none_-_-ms-flex); + -webkit-flex: var(--layout-flex-none_-_-webkit-flex); + flex: var(--layout-flex-none_-_flex); +} + +#author-photo.yt-live-chat-membership-item-renderer { + width: 40px; + height: 40px; +} + +yt-icon#author-photo.yt-live-chat-membership-item-renderer { + display: none; +} + +yt-live-chat-membership-item-renderer[dashboard-money-feed] yt-icon#author-photo.yt-live-chat-membership-item-renderer { + display: block; +} + +yt-live-chat-membership-item-renderer:not([dashboard-money-feed]) yt-live-chat-author-chip.yt-live-chat-membership-item-renderer { + --yt-live-chat-sponsor-color: var(--yt-live-chat-sponsor-text-color); + --yt-live-chat-secondary-text-color: var(--yt-live-chat-sponsor-text-color); +} + +yt-live-chat-membership-item-renderer[dashboard-money-feed] yt-live-chat-author-chip.yt-live-chat-membership-item-renderer { + margin-right: 8px; + font-weight: 500; + --yt-live-chat-sponsor-color: var(--yt-live-chat-secondary-text-color); +} + +#header-subtext.yt-live-chat-membership-item-renderer { + margin-top: 2px; + color: rgba(255, 255, 255, 0.7); + font-weight: 500; + font-size: 15px; +} + +#header-subtext.yt-live-chat-membership-item-renderer:empty { + display: none; +} + +yt-live-chat-membership-item-renderer[dashboard-money-feed] #header-subtext.yt-live-chat-membership-item-renderer { + margin: 4px 0 13px; + font-size: 11px; + font-weight: normal; + color: var(--yt-live-chat-secondary-text-color); +} + +#header-primary-text.yt-live-chat-membership-item-renderer { + word-wrap: break-word; + word-break: break-word; + font-weight: 500; + color: rgba(255, 255, 255, 1); +} + +#header-primary-text.yt-live-chat-membership-item-renderer:empty { + display: none; +} + +yt-live-chat-membership-item-renderer[has-primary-header-text]:not([dashboard-money-feed]) yt-live-chat-author-chip.yt-live-chat-membership-item-renderer, +yt-live-chat-membership-item-renderer[has-primary-header-text]:not([dashboard-money-feed]) #header-subtext.yt-live-chat-membership-item-renderer { + font-size: 12px; +} + +yt-live-chat-membership-item-renderer[dashboard-money-feed] #header-primary-text.yt-live-chat-membership-item-renderer { + display: inline; + height: 24px; + min-width: 16px; + border-radius: 12px; + margin-right: 8px; + padding: 0 12px; + background-color: var(--yt-live-chat-sponsor-color); + color: var(--yt-white); + display: var(--layout-inline_-_display, inline); + -ms-flex-align: var(--layout-center-center_-_-ms-flex-align); + -webkit-align-items: var(--layout-center-center_-_-webkit-align-items); + align-items: var(--layout-center-center_-_align-items); + -ms-flex-pack: var(--layout-center-center_-_-ms-flex-pack); + -webkit-justify-content: var(--layout-center-center_-_-webkit-justify-content); + justify-content: var(--layout-center-center_-_justify-content); + font-size: var(--ytd-badge_-_font-size); + font-weight: var(--ytd-badge_-_font-weight); + line-height: var(--ytd-badge_-_line-height); +} + +#content.yt-live-chat-membership-item-renderer { + background-color: var(--yt-live-chat-sponsor-color); + color: var(--yt-live-chat-sponsor-text-color); + padding: 8px 16px; + word-wrap: break-word; + word-break: break-word; + font-size: 15px; + line-height: 20px; +} + +yt-live-chat-membership-item-renderer[dashboard-money-feed] #content.yt-live-chat-membership-item-renderer { + background-color: unset; + font-size: unset; + color: var(--yt-live-chat-secondary-text-color); + padding: 0 0 16px 72px; +} + +#content.yt-live-chat-membership-item-renderer img.yt-live-chat-membership-item-renderer { + /* B站表情有不是正方形的 */ + /* width: var(--yt-live-chat-emoji-size); */ + width: auto; + height: var(--yt-live-chat-emoji-size); + + margin: -1px 2px 1px 2px; + vertical-align: middle; +} + +yt-live-chat-membership-item-renderer[show-only-header] #content.yt-live-chat-membership-item-renderer, +#deleted-state.yt-live-chat-membership-item-renderer:empty { + display: none; +} + +#deleted-state.yt-live-chat-membership-item-renderer { + display: block; + font-style: italic; + opacity: 0.7; +} + +a.yt-live-chat-membership-item-renderer { + display: inline; + text-decoration: underline; +} + +#message.yt-live-chat-membership-item-renderer a.yt-live-chat-membership-item-renderer { + word-break: break-all; +} + +#message.yt-live-chat-membership-item-renderer a.yt-live-chat-membership-item-renderer .mention.yt-live-chat-membership-item-renderer { + text-decoration: underline; +} + +#menu.yt-live-chat-membership-item-renderer { + background: linear-gradient(to right, transparent, var(--yt-live-chat-sponsor-header-color) 100%); + border-radius: 0 4px 4px 0; +} + +yt-live-chat-membership-item-renderer[show-only-header] #menu.yt-live-chat-membership-item-renderer { + background: linear-gradient(to right, transparent, var(--yt-live-chat-sponsor-color) 100%); +} + +yt-live-chat-membership-item-renderer[dashboard-money-feed] #menu.yt-live-chat-membership-item-renderer { + margin-top: 8px; + background: linear-gradient(to right, transparent, var(--yt-live-chat-background-color) 40%); +} diff --git a/src/assets/css/youtube/yt-live-chat-paid-message-renderer.css b/src/assets/css/youtube/yt-live-chat-paid-message-renderer.css new file mode 100644 index 0000000..639d609 --- /dev/null +++ b/src/assets/css/youtube/yt-live-chat-paid-message-renderer.css @@ -0,0 +1,380 @@ +canvas.yt-live-chat-paid-message-renderer, caption.yt-live-chat-paid-message-renderer, center.yt-live-chat-paid-message-renderer, cite.yt-live-chat-paid-message-renderer, code.yt-live-chat-paid-message-renderer, dd.yt-live-chat-paid-message-renderer, del.yt-live-chat-paid-message-renderer, dfn.yt-live-chat-paid-message-renderer, div.yt-live-chat-paid-message-renderer, dl.yt-live-chat-paid-message-renderer, dt.yt-live-chat-paid-message-renderer, em.yt-live-chat-paid-message-renderer, embed.yt-live-chat-paid-message-renderer, fieldset.yt-live-chat-paid-message-renderer, font.yt-live-chat-paid-message-renderer, form.yt-live-chat-paid-message-renderer, h1.yt-live-chat-paid-message-renderer, h2.yt-live-chat-paid-message-renderer, h3.yt-live-chat-paid-message-renderer, h4.yt-live-chat-paid-message-renderer, h5.yt-live-chat-paid-message-renderer, h6.yt-live-chat-paid-message-renderer, hr.yt-live-chat-paid-message-renderer, i.yt-live-chat-paid-message-renderer, iframe.yt-live-chat-paid-message-renderer, img.yt-live-chat-paid-message-renderer, ins.yt-live-chat-paid-message-renderer, kbd.yt-live-chat-paid-message-renderer, label.yt-live-chat-paid-message-renderer, legend.yt-live-chat-paid-message-renderer, li.yt-live-chat-paid-message-renderer, menu.yt-live-chat-paid-message-renderer, object.yt-live-chat-paid-message-renderer, ol.yt-live-chat-paid-message-renderer, p.yt-live-chat-paid-message-renderer, pre.yt-live-chat-paid-message-renderer, q.yt-live-chat-paid-message-renderer, s.yt-live-chat-paid-message-renderer, samp.yt-live-chat-paid-message-renderer, small.yt-live-chat-paid-message-renderer, span.yt-live-chat-paid-message-renderer, strike.yt-live-chat-paid-message-renderer, strong.yt-live-chat-paid-message-renderer, sub.yt-live-chat-paid-message-renderer, sup.yt-live-chat-paid-message-renderer, table.yt-live-chat-paid-message-renderer, tbody.yt-live-chat-paid-message-renderer, td.yt-live-chat-paid-message-renderer, tfoot.yt-live-chat-paid-message-renderer, th.yt-live-chat-paid-message-renderer, thead.yt-live-chat-paid-message-renderer, tr.yt-live-chat-paid-message-renderer, tt.yt-live-chat-paid-message-renderer, u.yt-live-chat-paid-message-renderer, ul.yt-live-chat-paid-message-renderer, var.yt-live-chat-paid-message-renderer { + margin: 0; + padding: 0; + border: 0; + background: transparent; +} + +.yt-live-chat-paid-message-renderer[hidden] { + display: none !important; +} + +#timestamp.yt-live-chat-paid-message-renderer { + display: var(--yt-live-chat-item-timestamp-display, inline); + margin: var(--yt-live-chat-item-timestamp-margin, 0 8px 0 0); + color: var(--yt-live-chat-tertiary-text-color); + font-size: 11px; +} + +#author-photo.yt-live-chat-paid-message-renderer { + display: block; + margin-right: 16px; + overflow: hidden; + border-radius: 50%; + -ms-flex: none; + -webkit-flex: none; + flex: none; +} + +#menu-button.yt-live-chat-paid-message-renderer { + width: 40px; + height: 40px; + padding: 8px; +} + +#menu.yt-live-chat-paid-message-renderer { + position: absolute; + top: 0; + bottom: 0; + right: 0; + transform: translateX(100px); +} + +yt-live-chat-paid-message-renderer:hover #menu.yt-live-chat-paid-message-renderer, yt-live-chat-paid-message-renderer[menu-visible] #menu.yt-live-chat-paid-message-renderer { + transform: none; +} + +yt-live-chat-paid-message-renderer:focus-within #menu.yt-live-chat-paid-message-renderer { + transform: none; +} + +#inline-action-button-container.yt-live-chat-paid-message-renderer { + position: absolute; + top: -4px; + right: 0; + bottom: -4px; + left: 0; + background-color: var(--yt-live-chat-moderation-mode-hover-background-color); + display: none; + -ms-flex-align: center; + -webkit-align-items: center; + align-items: center; + -ms-flex-pack: center; + -webkit-justify-content: center; + justify-content: center; +} + +yt-live-chat-paid-message-renderer[has-inline-action-buttons]:hover #inline-action-button-container.yt-live-chat-paid-message-renderer { + display: flex; + -ms-flex-direction: row; + -webkit-flex-direction: row; + flex-direction: row; + display: var(--yt-live-chat-inline-action-button-container-display, none); +} + +yt-live-chat-paid-message-renderer[has-inline-action-buttons][hide-inline-action-buttons]:hover #inline-action-button-container.yt-live-chat-paid-message-renderer { + display: none; +} + +yt-live-chat-paid-message-renderer[has-inline-action-buttons]:hover #menu.yt-live-chat-paid-message-renderer { + display: var(--yt-live-chat-item-with-inline-actions-context-menu-display, block); +} + +#inline-action-buttons.yt-live-chat-paid-message-renderer>*.yt-live-chat-paid-message-renderer, #additional-inline-action-buttons.yt-live-chat-paid-message-renderer>*.yt-live-chat-paid-message-renderer { + --yt-button-icon-size: 36px; + --yt-button-icon-padding: 6px; + color: hsl(0, 0%, 100%); + border-radius: 2px; +} + +#inline-action-buttons.yt-live-chat-paid-message-renderer>*.yt-live-chat-paid-message-renderer { + background: hsla(0, 0%, 6.7%, .8); +} + +#inline-action-buttons.yt-live-chat-paid-message-renderer>.yt-live-chat-paid-message-renderer:hover { + background: hsl(0, 0%, 6.7%); +} + +#additional-inline-action-buttons.yt-live-chat-paid-message-renderer>*.yt-live-chat-paid-message-renderer { + color: var(--yt-live-chat-additional-inline-action-button-color); + background: var(--yt-live-chat-additional-inline-action-button-background-color); +} + +#additional-inline-action-buttons.yt-live-chat-paid-message-renderer>.yt-live-chat-paid-message-renderer:hover { + background: var(--yt-live-chat-additional-inline-action-button-background-color-hover); +} + +#additional-inline-action-buttons.yt-live-chat-paid-message-renderer:not(:empty) { + margin-left: 32px; +} + +#inline-action-buttons.yt-live-chat-paid-message-renderer>*.yt-live-chat-paid-message-renderer:not(:first-child), #additional-inline-action-buttons.yt-live-chat-paid-message-renderer>*.yt-live-chat-paid-message-renderer:not(:first-child) { + margin-left: 8px; +} + +yt-live-chat-paid-message-renderer { + position: relative; + display: block; + padding: 4px 24px; + font-size: 15px; + --yt-live-chat-paid-message-background-color: var(--yt-live-chat-paid-message-primary-color); + --yt-live-chat-paid-message-header-background-color: var(--yt-live-chat-paid-message-secondary-color); + --yt-live-chat-text-input-field-placeholder-color: var(--yt-live-chat-paid-message-color); + --yt-live-chat-item-timestamp-display: var(--yt-live-chat-paid-message-timestamp-display, none); +} + +yt-live-chat-paid-message-renderer[dashboard-money-feed] { + padding: 0; + padding-bottom: 8px; + --yt-live-chat-paid-message-background-color: transparent; + --yt-live-chat-paid-message-header-background-color: transparent; + --yt-live-chat-item-timestamp-display: block; +} + +#card.yt-live-chat-paid-message-renderer { + border-radius: 4px; + display: flex; + -ms-flex-direction: column; + -webkit-flex-direction: column; + flex-direction: column; + box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.14), 0 1px 5px 0 rgba(0, 0, 0, 0.12), 0 3px 1px -2px rgba(0, 0, 0, 0.2); +} + +yt-live-chat-paid-message-renderer[dashboard-money-feed] #card.yt-live-chat-paid-message-renderer { + border-radius: 0; + box-shadow: none; +} + +#header.yt-live-chat-paid-message-renderer { + position: relative; + background-color: var(--yt-live-chat-paid-message-header-background-color, #125aac); + color: var(--yt-live-chat-paid-message-header-color, #fff); + font-weight: 500; + padding: 8px 16px; + min-height: 20px; + display: flex; + -ms-flex-direction: row; + -webkit-flex-direction: row; + flex-direction: row; + -ms-flex-align: center; + -webkit-align-items: center; + align-items: center; + border-top-left-radius: 4px; + border-top-right-radius: 4px; +} + +yt-live-chat-paid-message-renderer[show-only-header] #header.yt-live-chat-paid-message-renderer { + border-bottom-left-radius: 4px; + border-bottom-right-radius: 4px; +} + +yt-live-chat-paid-message-renderer[dashboard-money-feed] #header.yt-live-chat-paid-message-renderer { + color: var(--yt-live-chat-secondary-text-color); + padding-bottom: 0; +} + +#author-photo.yt-live-chat-paid-message-renderer { + width: 40px; + height: 40px; +} + +yt-icon#author-photo.yt-live-chat-paid-message-renderer { + display: none; +} + +yt-live-chat-paid-message-renderer[dashboard-money-feed] yt-icon#author-photo.yt-live-chat-paid-message-renderer { + display: block; +} + +#header-content.yt-live-chat-paid-message-renderer { + display: flex; + -ms-flex-direction: row; + -webkit-flex-direction: row; + flex-direction: row; + -ms-flex-pack: justify; + -webkit-justify-content: space-between; + justify-content: space-between; + -ms-flex: 1 1 0.000000001px; + -webkit-flex: 1; + flex: 1; + -webkit-flex-basis: 0.000000001px; + flex-basis: 0.000000001px; + -ms-flex-align: baseline; + -webkit-align-items: baseline; + align-items: baseline; +} + +yt-live-chat-paid-message-renderer[dashboard-money-feed] #header-content.yt-live-chat-paid-message-renderer { + display: flex; + -ms-flex-direction: column; + -webkit-flex-direction: column; + flex-direction: column; +} + +#header-content-primary-column.yt-live-chat-paid-message-renderer { + display: flex; + -ms-flex-direction: column; + -webkit-flex-direction: column; + flex-direction: column; + -ms-flex-pack: justify; + -webkit-justify-content: space-between; + justify-content: space-between; + -ms-flex: 1 1 0.000000001px; + -webkit-flex: 1; + flex: 1; + -webkit-flex-basis: 0.000000001px; + flex-basis: 0.000000001px; +} + +yt-live-chat-paid-message-renderer[dashboard-money-feed] #header-content-primary-column.yt-live-chat-paid-message-renderer { + margin-bottom: 4px; + display: flex; + -ms-flex-direction: row; + -webkit-flex-direction: row; + flex-direction: row; + -ms-flex-align: baseline; + -webkit-align-items: baseline; + align-items: baseline; + -ms-flex: none; + -webkit-flex: none; + flex: none; +} + +#author-name.yt-live-chat-paid-message-renderer { + color: var(--yt-live-chat-paid-message-author-name-color, rgba(255, 255, 255, 0.7)); + font-size: 14px; +} + +yt-live-chat-paid-message-renderer[dashboard-money-feed] #author-name.yt-live-chat-paid-message-renderer { + margin-right: 8px; +} + +yt-live-chat-paid-message-renderer[dashboard-money-feed] #purchase-amount.yt-live-chat-paid-message-renderer { + display: inline; + height: 24px; + min-width: 16px; + border-radius: 12px; + margin-right: 8px; + padding: 0 12px; + background-color: var(--yt-live-chat-paid-message-primary-color); + color: var(--yt-live-chat-paid-message-color); + display: inline-flex; + -ms-flex-align: center; + -webkit-align-items: center; + align-items: center; + -ms-flex-pack: center; + -webkit-justify-content: center; + justify-content: center; + font-size: 1.2rem; + font-weight: 500; + line-height: 1.2rem; +} + +yt-live-chat-paid-message-renderer[dashboard-money-feed] #author-name.yt-live-chat-paid-message-renderer { + display: block; + color: var(--yt-live-chat-secondary-text-color); +} + +yt-live-chat-paid-message-renderer[dashboard-money-feed] #author-name.yt-live-chat-paid-message-renderer[is-deleted] { + margin: 4px 0 0; + order: 1; +} + +yt-live-chat-paid-message-renderer[dashboard-money-feed] #author-name.yt-live-chat-paid-message-renderer[is-deleted].yt-live-chat-paid-message-renderer::before { + content: '​'; + display: inline; + width: 0; +} + +#menu.yt-live-chat-paid-message-renderer { + background: linear-gradient(to right, transparent, var(--yt-live-chat-paid-message-header-background-color, #125aac) 100%); + border-radius: 0 4px 4px 0; +} + +yt-live-chat-paid-message-renderer[dashboard-money-feed] #menu.yt-live-chat-paid-message-renderer { + margin-top: 8px; + background: linear-gradient(to right, transparent, var(--yt-live-chat-background-color) 40%); +} + +yt-live-chat-paid-message-renderer[allow-animations] #content.yt-live-chat-paid-message-renderer, yt-live-chat-paid-message-renderer[allow-animations] #header.yt-live-chat-paid-message-renderer { + transition-property: background-color, color; + transition-duration: 0.2s; +} + +#content.yt-live-chat-paid-message-renderer { + background-color: var(--yt-live-chat-paid-message-background-color, #1565c0); + color: var(--yt-live-chat-paid-message-color, #fff); + padding: 8px 16px; + word-wrap: break-word; + word-break: break-word; + border-bottom-left-radius: 4px; + border-bottom-right-radius: 4px; +} + +#content.yt-live-chat-paid-message-renderer img.yt-live-chat-paid-message-renderer { + /* B站表情有不是正方形的 */ + /* width: var(--yt-live-chat-emoji-size); */ + width: auto; + height: var(--yt-live-chat-emoji-size); + margin: -1px 2px 1px 2px; + vertical-align: middle; +} + +yt-live-chat-paid-message-renderer[dashboard-money-feed] #content.yt-live-chat-paid-message-renderer { + padding: 0; + padding-left: 72px; + color: var(--yt-live-chat-secondary-text-color); +} + +yt-live-chat-paid-message-renderer[show-only-header] #content.yt-live-chat-paid-message-renderer { + visibility: hidden; + padding: 0; +} + +a.yt-live-chat-paid-message-renderer { + display: inline; + text-decoration: underline; +} + +#message.yt-live-chat-paid-message-renderer a.yt-live-chat-paid-message-renderer { + word-break: break-all; +} + +yt-live-chat-paid-message-renderer[dashboard-money-feed] #message.yt-live-chat-paid-message-renderer { + margin-top: 4px; +} + +#message.yt-live-chat-paid-message-renderer a.yt-live-chat-paid-message-renderer .mention.yt-live-chat-paid-message-renderer { + text-decoration: underline; +} + +#message.yt-live-chat-paid-message-renderer:empty, #author-name.yt-live-chat-paid-message-renderer:empty:not([is-deleted]).yt-live-chat-paid-message-renderer, #deleted-state.yt-live-chat-paid-message-renderer:empty { + display: none; +} + +#deleted-state.yt-live-chat-paid-message-renderer { + display: block; + font-style: italic; + opacity: 0.7; +} + +yt-live-chat-paid-message-renderer[dashboard-money-feed] #deleted-state.yt-live-chat-paid-message-renderer[is-deleted] { + margin-top: 4px; +} + +yt-live-chat-paid-message-renderer[dashboard-money-feed] #author-name.yt-live-chat-paid-message-renderer { + -ms-flex: none; + -webkit-flex: none; + flex: none; +} + +yt-live-chat-paid-message-renderer[show-footer-divider] #footer.yt-live-chat-paid-message-renderer::before { + content: ""; + display: flex; + border-top: 1px solid rgba(0, 0, 0, 0.12); + margin: 8px 0; +} + +yt-live-chat-paid-message-renderer[is-user-editable] #footer.yt-live-chat-paid-message-renderer:not(:empty) { + padding-top: 8px; +} diff --git a/src/assets/css/youtube/yt-live-chat-renderer.css b/src/assets/css/youtube/yt-live-chat-renderer.css new file mode 100644 index 0000000..5e805f6 --- /dev/null +++ b/src/assets/css/youtube/yt-live-chat-renderer.css @@ -0,0 +1,252 @@ +yt-live-chat-renderer, yt-live-chat-item-list-renderer #item-scroller { + height: 100%; +} + +yt-live-chat-renderer ::-webkit-scrollbar { + content: ''; +} + +yt-live-chat-renderer ::-webkit-scrollbar-thumb { + background-color: hsla(0, 0%, 53.3%, .2); + border: 2px solid #fcfcfc; + min-height: 30px; +} + +yt-live-chat-renderer ::-webkit-scrollbar-track { + background-color: #fcfcfc; +} + + +canvas.yt-live-chat-renderer, caption.yt-live-chat-renderer, center.yt-live-chat-renderer, cite.yt-live-chat-renderer, code.yt-live-chat-renderer, dd.yt-live-chat-renderer, del.yt-live-chat-renderer, dfn.yt-live-chat-renderer, div.yt-live-chat-renderer, dl.yt-live-chat-renderer, dt.yt-live-chat-renderer, em.yt-live-chat-renderer, embed.yt-live-chat-renderer, fieldset.yt-live-chat-renderer, font.yt-live-chat-renderer, form.yt-live-chat-renderer, h1.yt-live-chat-renderer, h2.yt-live-chat-renderer, h3.yt-live-chat-renderer, h4.yt-live-chat-renderer, h5.yt-live-chat-renderer, h6.yt-live-chat-renderer, hr.yt-live-chat-renderer, i.yt-live-chat-renderer, iframe.yt-live-chat-renderer, img.yt-live-chat-renderer, ins.yt-live-chat-renderer, kbd.yt-live-chat-renderer, label.yt-live-chat-renderer, legend.yt-live-chat-renderer, li.yt-live-chat-renderer, menu.yt-live-chat-renderer, object.yt-live-chat-renderer, ol.yt-live-chat-renderer, p.yt-live-chat-renderer, pre.yt-live-chat-renderer, q.yt-live-chat-renderer, s.yt-live-chat-renderer, samp.yt-live-chat-renderer, small.yt-live-chat-renderer, span.yt-live-chat-renderer, strike.yt-live-chat-renderer, strong.yt-live-chat-renderer, sub.yt-live-chat-renderer, sup.yt-live-chat-renderer, table.yt-live-chat-renderer, tbody.yt-live-chat-renderer, td.yt-live-chat-renderer, tfoot.yt-live-chat-renderer, th.yt-live-chat-renderer, thead.yt-live-chat-renderer, tr.yt-live-chat-renderer, tt.yt-live-chat-renderer, u.yt-live-chat-renderer, ul.yt-live-chat-renderer, var.yt-live-chat-renderer { + margin: 0; + padding: 0; + border: 0; + background: transparent; +} + +.yt-live-chat-renderer[hidden] { + display: none !important; +} + +yt-live-chat-renderer { + font-size: 13px; + --yt-emoji-picker-renderer-height: 180px; + --yt-button-default-text-color: var(--yt-live-chat-button-default-text-color); + --yt-button-default-background-color: var(--yt-live-chat-button-default-background-color); + --yt-button-dark-text-color: var(--yt-live-chat-button-dark-text-color); + --yt-button-dark-background-color: var(--yt-live-chat-button-dark-background-color); + --yt-button-payment-background-color: var(--yt-live-chat-sponsor-color); +} + +yt-live-chat-renderer { + position: relative; + background: var(--yt-live-chat-background-color); + color: var(--yt-live-chat-primary-text-color); + overflow: hidden; + z-index: 0; + display: flex; + -ms-flex-direction: column; + -webkit-flex-direction: column; + flex-direction: column; +} + +yt-live-chat-renderer[hide-timestamps] { + --yt-live-chat-item-timestamp-display: none; +} + +#separator.yt-live-chat-renderer { + border-bottom: var(--yt-live-chat-header-bottom-border, none); +} + +#content-pages.yt-live-chat-renderer { + display: flex; + -ms-flex-direction: column; + -webkit-flex-direction: column; + flex-direction: column; + -ms-flex: 1 1 0.000000001px; + -webkit-flex: 1; + flex: 1; + -webkit-flex-basis: 0.000000001px; + flex-basis: 0.000000001px; +} + +#panel-pages.yt-live-chat-renderer { + max-height: 100%; + overflow-x: hidden; + overflow-y: auto; +} + +#contents.yt-live-chat-renderer { + overflow: hidden; + position: relative; + z-index: 0; +} + +#chat-messages.yt-live-chat-renderer, #contents.yt-live-chat-renderer, #item-list.yt-live-chat-renderer { + display: flex; + -ms-flex-direction: column; + -webkit-flex-direction: column; + flex-direction: column; + -ms-flex: 1 1 0.000000001px; + -webkit-flex: 1; + flex: 1; + -webkit-flex-basis: 0.000000001px; + flex-basis: 0.000000001px; +} + +#ticker.yt-live-chat-renderer { + z-index: 1; +} + +#chat.yt-live-chat-renderer { + position: relative; + display: flex; + -ms-flex-direction: column; + -webkit-flex-direction: column; + flex-direction: column; + -ms-flex: 1 1 0.000000001px; + -webkit-flex: 1; + flex: 1; + -webkit-flex-basis: 0.000000001px; + flex-basis: 0.000000001px; +} + +#chat.yt-live-chat-renderer::after { + content: ''; + display: none; + animation: gradient-slide 1.2s ease infinite; + animation-name: gradient-slide; + background-color: var(--yt-live-chat-shimmer-background-color); + background-image: var(--yt-live-chat-shimmer-linear-gradient); + background-size: 300% 300%; + transform: rotateX(180deg); + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; +} + +yt-live-chat-renderer[loading] #chat.yt-live-chat-renderer::after { + display: block; +} + +yt-live-chat-pinned-message-renderer.yt-live-chat-renderer { + bottom: 0; + left: 0; + position: absolute; + right: 0; + top: 0; +} + +yt-live-chat-item-list-renderer.yt-live-chat-renderer, yt-live-chat-ninja-message-renderer.yt-live-chat-renderer { + -ms-flex: 1 1 0.000000001px; + -webkit-flex: 1; + flex: 1; + -webkit-flex-basis: 0.000000001px; + flex-basis: 0.000000001px; +} + +#action-panel.yt-live-chat-renderer { + position: absolute; + bottom: 0; + left: 0; + right: 0; + overflow: hidden; +} + +yt-live-chat-renderer[has-action-panel-renderer] yt-live-chat-action-panel-renderer.yt-live-chat-renderer { + animation: slideUp cubic-bezier(0.05, 0.00, 0.00, 1.00) forwards; + animation-duration: 0.5s; +} + +#action-panel-backdrop.yt-live-chat-renderer { + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; + visibility: hidden; +} + +yt-live-chat-renderer[has-action-panel-renderer] #action-panel-backdrop.yt-live-chat-renderer { + visibility: visible; + animation: fadeIn cubic-bezier(0.05, 0.00, 0.00, 1.00) forwards; + animation-duration: 0.5s; +} + +#input-panel.yt-live-chat-renderer { + -ms-flex: none; + -webkit-flex: none; + flex: none; +} + +#input-panel.yt-live-chat-renderer:not(:empty) { + border-top: var(--yt-live-chat-action-panel-top-border, none); +} + +.hide-on-collapse.yt-live-chat-renderer { + transition: opacity 0.3s; +} + +yt-live-chat-renderer[collapsed] .hide-on-collapse.yt-live-chat-renderer { + opacity: 0; +} + +#loading.yt-live-chat-renderer { + height: 387px; + background-color: var(--yt-live-chat-action-panel-background-color); + display: flex; + -ms-flex-direction: column; + -webkit-flex-direction: column; + flex-direction: column; + -ms-flex-align: center; + -webkit-align-items: center; + align-items: center; + -ms-flex-pack: center; + -webkit-justify-content: center; + justify-content: center; +} + +#loading.yt-live-chat-renderer>paper-spinner-lite.yt-live-chat-renderer { + --paper-spinner-color: var(--yt-live-chat-primary-text-color); +} + +#nitrate-promo.yt-live-chat-renderer>*.yt-live-chat-renderer { + background: var(--yt-live-chat-overlay-color); + z-index: 3; + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; +} + +@keyframes gradient-slide { + 0% { + background-position: 100% 100%; + } + to { + background-position: 0% 0%; + } +} + +@keyframes slideUp { + 0% { + transform: translateY(15%); + opacity: 0; + } + 100% { + transform: translateY(0); + opacity: 1; + } +} + +@keyframes fadeIn { + 0% { + background-color: transparent; + } + 100% { + background-color: rgba(0, 0, 0, 0.60); + } +} diff --git a/src/assets/css/youtube/yt-live-chat-text-message-renderer.css b/src/assets/css/youtube/yt-live-chat-text-message-renderer.css new file mode 100644 index 0000000..bf1ed28 --- /dev/null +++ b/src/assets/css/youtube/yt-live-chat-text-message-renderer.css @@ -0,0 +1,232 @@ +canvas.yt-live-chat-text-message-renderer, caption.yt-live-chat-text-message-renderer, center.yt-live-chat-text-message-renderer, cite.yt-live-chat-text-message-renderer, code.yt-live-chat-text-message-renderer, dd.yt-live-chat-text-message-renderer, del.yt-live-chat-text-message-renderer, dfn.yt-live-chat-text-message-renderer, div.yt-live-chat-text-message-renderer, dl.yt-live-chat-text-message-renderer, dt.yt-live-chat-text-message-renderer, em.yt-live-chat-text-message-renderer, embed.yt-live-chat-text-message-renderer, fieldset.yt-live-chat-text-message-renderer, font.yt-live-chat-text-message-renderer, form.yt-live-chat-text-message-renderer, h1.yt-live-chat-text-message-renderer, h2.yt-live-chat-text-message-renderer, h3.yt-live-chat-text-message-renderer, h4.yt-live-chat-text-message-renderer, h5.yt-live-chat-text-message-renderer, h6.yt-live-chat-text-message-renderer, hr.yt-live-chat-text-message-renderer, i.yt-live-chat-text-message-renderer, iframe.yt-live-chat-text-message-renderer, img.yt-live-chat-text-message-renderer, ins.yt-live-chat-text-message-renderer, kbd.yt-live-chat-text-message-renderer, label.yt-live-chat-text-message-renderer, legend.yt-live-chat-text-message-renderer, li.yt-live-chat-text-message-renderer, menu.yt-live-chat-text-message-renderer, object.yt-live-chat-text-message-renderer, ol.yt-live-chat-text-message-renderer, p.yt-live-chat-text-message-renderer, pre.yt-live-chat-text-message-renderer, q.yt-live-chat-text-message-renderer, s.yt-live-chat-text-message-renderer, samp.yt-live-chat-text-message-renderer, small.yt-live-chat-text-message-renderer, span.yt-live-chat-text-message-renderer, strike.yt-live-chat-text-message-renderer, strong.yt-live-chat-text-message-renderer, sub.yt-live-chat-text-message-renderer, sup.yt-live-chat-text-message-renderer, table.yt-live-chat-text-message-renderer, tbody.yt-live-chat-text-message-renderer, td.yt-live-chat-text-message-renderer, tfoot.yt-live-chat-text-message-renderer, th.yt-live-chat-text-message-renderer, thead.yt-live-chat-text-message-renderer, tr.yt-live-chat-text-message-renderer, tt.yt-live-chat-text-message-renderer, u.yt-live-chat-text-message-renderer, ul.yt-live-chat-text-message-renderer, var.yt-live-chat-text-message-renderer { + margin: 0; + padding: 0; + border: 0; + background: transparent; +} + +.yt-live-chat-text-message-renderer[hidden] { + display: none !important; +} + +#timestamp.yt-live-chat-text-message-renderer { + display: var(--yt-live-chat-item-timestamp-display, inline); + margin: var(--yt-live-chat-item-timestamp-margin, 0 8px 0 0); + color: var(--yt-live-chat-tertiary-text-color); + font-size: 11px; +} + +#author-photo.yt-live-chat-text-message-renderer { + display: block; + margin-right: 16px; + overflow: hidden; + border-radius: 50%; + -ms-flex: none; + -webkit-flex: none; + flex: none; +} + +#menu-button.yt-live-chat-text-message-renderer { + width: 40px; + height: 40px; + padding: 8px; +} + +#menu.yt-live-chat-text-message-renderer { + position: absolute; + top: 0; + bottom: 0; + right: 0; + transform: translateX(100px); +} + +yt-live-chat-text-message-renderer:hover #menu.yt-live-chat-text-message-renderer, yt-live-chat-text-message-renderer[menu-visible] #menu.yt-live-chat-text-message-renderer { + transform: none; +} + +yt-live-chat-text-message-renderer:focus-within #menu.yt-live-chat-text-message-renderer { + transform: none; +} + +#inline-action-button-container.yt-live-chat-text-message-renderer { + position: absolute; + top: -4px; + right: 0; + bottom: -4px; + left: 0; + background-color: var(--yt-live-chat-moderation-mode-hover-background-color); + display: none; + -ms-flex-align: center; + -webkit-align-items: center; + align-items: center; + -ms-flex-pack: center; + -webkit-justify-content: center; + justify-content: center; +} + +yt-live-chat-text-message-renderer[has-inline-action-buttons]:hover #inline-action-button-container.yt-live-chat-text-message-renderer { + display: flex; + -ms-flex-direction: row; + -webkit-flex-direction: row; + flex-direction: row; + display: var(--yt-live-chat-inline-action-button-container-display, none); +} + +yt-live-chat-text-message-renderer[has-inline-action-buttons][hide-inline-action-buttons]:hover #inline-action-button-container.yt-live-chat-text-message-renderer { + display: none; +} + +yt-live-chat-text-message-renderer[has-inline-action-buttons]:hover #menu.yt-live-chat-text-message-renderer { + display: var(--yt-live-chat-item-with-inline-actions-context-menu-display, block); +} + +#inline-action-buttons.yt-live-chat-text-message-renderer>*.yt-live-chat-text-message-renderer, #additional-inline-action-buttons.yt-live-chat-text-message-renderer>*.yt-live-chat-text-message-renderer { + --yt-button-icon-size: 36px; + --yt-button-icon-padding: 6px; + color: hsl(0, 0%, 100%); + border-radius: 2px; +} + +#inline-action-buttons.yt-live-chat-text-message-renderer>*.yt-live-chat-text-message-renderer { + background: hsla(0, 0%, 6.7%, .8); +} + +#inline-action-buttons.yt-live-chat-text-message-renderer>.yt-live-chat-text-message-renderer:hover { + background: hsl(0, 0%, 6.7%); +} + +#additional-inline-action-buttons.yt-live-chat-text-message-renderer>*.yt-live-chat-text-message-renderer { + color: var(--yt-live-chat-additional-inline-action-button-color); + background: var(--yt-live-chat-additional-inline-action-button-background-color); +} + +#additional-inline-action-buttons.yt-live-chat-text-message-renderer>.yt-live-chat-text-message-renderer:hover { + background: var(--yt-live-chat-additional-inline-action-button-background-color-hover); +} + +#additional-inline-action-buttons.yt-live-chat-text-message-renderer:not(:empty) { + margin-left: 32px; +} + +#inline-action-buttons.yt-live-chat-text-message-renderer>*.yt-live-chat-text-message-renderer:not(:first-child), #additional-inline-action-buttons.yt-live-chat-text-message-renderer>*.yt-live-chat-text-message-renderer:not(:first-child) { + margin-left: 8px; +} + +yt-live-chat-text-message-renderer { + position: relative; + font-size: 13px; + padding: 4px 24px; + overflow: hidden; + --yt-endpoint-color: var(--yt-live-chat-primary-text-color, hsl(0, 0%, 6.7%)); + --yt-endpoint-hover-color: var(--yt-live-chat-primary-text-color, var(--yt-endpoint-color)); + display: flex; + -ms-flex-direction: row; + -webkit-flex-direction: row; + flex-direction: row; + -ms-flex-align: start; + -webkit-align-items: flex-start; + align-items: flex-start; +} + +yt-live-chat-text-message-renderer:hover { + overflow: initial; +} + +yt-live-chat-text-message-renderer[author-is-owner] { + background-color: var(--yt-live-chat-message-highlight-background-color); +} + +#content.yt-live-chat-text-message-renderer { + -ms-align-self: center; + -webkit-align-self: center; + align-self: center; + min-width: 0; +} + +yt-live-chat-author-chip.yt-live-chat-text-message-renderer { + margin-right: 8px; +} + +#message.yt-live-chat-text-message-renderer { + color: var(--yt-live-chat-primary-text-color, var(--yt-primary-text-color)); + line-height: 16px; + overflow: hidden; + overflow-wrap: break-word; + word-wrap: break-word; + word-break: break-word; + font-style: var(--yt-live-chat-text-message-renderer-message-message-style_-_font-style); + opacity: var(--yt-live-chat-text-message-renderer-message-message-style_-_opacity); +} + +#message.yt-live-chat-text-message-renderer .emoji.yt-live-chat-text-message-renderer { + /* B站表情有不是正方形的 */ + /* width: var(--yt-live-chat-emoji-size); */ + width: auto; + height: var(--yt-live-chat-emoji-size); + margin: -1px 2px 1px 2px; + vertical-align: middle; +} + +a.yt-live-chat-text-message-renderer { + display: inline; + text-decoration: underline; +} + +#message.yt-live-chat-text-message-renderer a.yt-live-chat-text-message-renderer { + display: inline; + text-decoration: underline; + word-break: break-all; +} + +#message.yt-live-chat-text-message-renderer a.yt-live-chat-text-message-renderer .mention.yt-live-chat-text-message-renderer { + text-decoration: underline; +} + +#show-original.yt-live-chat-text-message-renderer { + margin-left: 2px; +} + +#message.yt-live-chat-text-message-renderer:empty, #deleted-state.yt-live-chat-text-message-renderer:empty, #show-original.yt-live-chat-text-message-renderer:empty, yt-live-chat-text-message-renderer[show-original] #deleted-state.yt-live-chat-text-message-renderer, yt-live-chat-text-message-renderer[show-original] #show-original.yt-live-chat-text-message-renderer, yt-live-chat-text-message-renderer[is-deleted]:not([show-original]) #message.yt-live-chat-text-message-renderer { + display: none; +} + +#menu.yt-live-chat-text-message-renderer { + color: var(--yt-live-chat-secondary-text-color); + background: linear-gradient(to right, transparent, var(--yt-live-chat-background-color, hsl(0, 0%, 100%)) 100%); +} + +.mention.yt-live-chat-text-message-renderer { + background: var(--yt-live-chat-mention-background-color); + color: var(--yt-live-chat-mention-text-color); + padding: 2px 4px; + border-radius: 2px; +} + +#deleted-state.yt-live-chat-text-message-renderer, #show-original.yt-live-chat-text-message-renderer, yt-live-chat-text-message-renderer[is-deleted] #message.yt-live-chat-text-message-renderer { + font-style: italic; + color: var(--yt-live-chat-deleted-message-color, rgba(0, 0, 0, 0.5)); +} + +yt-live-chat-text-message-renderer[show-bar]::before { + content: ''; + position: absolute; + display: block; + left: 8px; + top: 4px; + bottom: 4px; + width: 4px; + box-sizing: border-box; + border-radius: 2px; +} + +yt-live-chat-text-message-renderer[is-deleted]::before { + background: var(--yt-live-chat-deleted-message-bar-color, rgba(0, 0, 0, 0.5)); +} + +yt-live-chat-text-message-renderer[is-dimmed] #message.yt-live-chat-text-message-renderer { + opacity: 0.25; +} + +yt-live-chat-text-message-renderer[is-dimmed]::before { + background: var(--yt-live-chat-error-message-color, #f44336); +} diff --git a/src/assets/css/youtube/yt-live-chat-ticker-paid-message-item-renderer.css b/src/assets/css/youtube/yt-live-chat-ticker-paid-message-item-renderer.css new file mode 100644 index 0000000..4844b66 --- /dev/null +++ b/src/assets/css/youtube/yt-live-chat-ticker-paid-message-item-renderer.css @@ -0,0 +1,80 @@ +canvas.yt-live-chat-ticker-paid-message-item-renderer, caption.yt-live-chat-ticker-paid-message-item-renderer, center.yt-live-chat-ticker-paid-message-item-renderer, cite.yt-live-chat-ticker-paid-message-item-renderer, code.yt-live-chat-ticker-paid-message-item-renderer, dd.yt-live-chat-ticker-paid-message-item-renderer, del.yt-live-chat-ticker-paid-message-item-renderer, dfn.yt-live-chat-ticker-paid-message-item-renderer, div.yt-live-chat-ticker-paid-message-item-renderer, dl.yt-live-chat-ticker-paid-message-item-renderer, dt.yt-live-chat-ticker-paid-message-item-renderer, em.yt-live-chat-ticker-paid-message-item-renderer, embed.yt-live-chat-ticker-paid-message-item-renderer, fieldset.yt-live-chat-ticker-paid-message-item-renderer, font.yt-live-chat-ticker-paid-message-item-renderer, form.yt-live-chat-ticker-paid-message-item-renderer, h1.yt-live-chat-ticker-paid-message-item-renderer, h2.yt-live-chat-ticker-paid-message-item-renderer, h3.yt-live-chat-ticker-paid-message-item-renderer, h4.yt-live-chat-ticker-paid-message-item-renderer, h5.yt-live-chat-ticker-paid-message-item-renderer, h6.yt-live-chat-ticker-paid-message-item-renderer, hr.yt-live-chat-ticker-paid-message-item-renderer, i.yt-live-chat-ticker-paid-message-item-renderer, iframe.yt-live-chat-ticker-paid-message-item-renderer, img.yt-live-chat-ticker-paid-message-item-renderer, ins.yt-live-chat-ticker-paid-message-item-renderer, kbd.yt-live-chat-ticker-paid-message-item-renderer, label.yt-live-chat-ticker-paid-message-item-renderer, legend.yt-live-chat-ticker-paid-message-item-renderer, li.yt-live-chat-ticker-paid-message-item-renderer, menu.yt-live-chat-ticker-paid-message-item-renderer, object.yt-live-chat-ticker-paid-message-item-renderer, ol.yt-live-chat-ticker-paid-message-item-renderer, p.yt-live-chat-ticker-paid-message-item-renderer, pre.yt-live-chat-ticker-paid-message-item-renderer, q.yt-live-chat-ticker-paid-message-item-renderer, s.yt-live-chat-ticker-paid-message-item-renderer, samp.yt-live-chat-ticker-paid-message-item-renderer, small.yt-live-chat-ticker-paid-message-item-renderer, span.yt-live-chat-ticker-paid-message-item-renderer, strike.yt-live-chat-ticker-paid-message-item-renderer, strong.yt-live-chat-ticker-paid-message-item-renderer, sub.yt-live-chat-ticker-paid-message-item-renderer, sup.yt-live-chat-ticker-paid-message-item-renderer, table.yt-live-chat-ticker-paid-message-item-renderer, tbody.yt-live-chat-ticker-paid-message-item-renderer, td.yt-live-chat-ticker-paid-message-item-renderer, tfoot.yt-live-chat-ticker-paid-message-item-renderer, th.yt-live-chat-ticker-paid-message-item-renderer, thead.yt-live-chat-ticker-paid-message-item-renderer, tr.yt-live-chat-ticker-paid-message-item-renderer, tt.yt-live-chat-ticker-paid-message-item-renderer, u.yt-live-chat-ticker-paid-message-item-renderer, ul.yt-live-chat-ticker-paid-message-item-renderer, var.yt-live-chat-ticker-paid-message-item-renderer { + margin: 0; + padding: 0; + border: 0; + background: transparent; +} + +.yt-live-chat-ticker-paid-message-item-renderer[hidden] { + display: none !important; +} + +canvas.yt-live-chat-ticker-paid-message-item-renderer, caption.yt-live-chat-ticker-paid-message-item-renderer, center.yt-live-chat-ticker-paid-message-item-renderer, cite.yt-live-chat-ticker-paid-message-item-renderer, code.yt-live-chat-ticker-paid-message-item-renderer, dd.yt-live-chat-ticker-paid-message-item-renderer, del.yt-live-chat-ticker-paid-message-item-renderer, dfn.yt-live-chat-ticker-paid-message-item-renderer, div.yt-live-chat-ticker-paid-message-item-renderer, dl.yt-live-chat-ticker-paid-message-item-renderer, dt.yt-live-chat-ticker-paid-message-item-renderer, em.yt-live-chat-ticker-paid-message-item-renderer, embed.yt-live-chat-ticker-paid-message-item-renderer, fieldset.yt-live-chat-ticker-paid-message-item-renderer, font.yt-live-chat-ticker-paid-message-item-renderer, form.yt-live-chat-ticker-paid-message-item-renderer, h1.yt-live-chat-ticker-paid-message-item-renderer, h2.yt-live-chat-ticker-paid-message-item-renderer, h3.yt-live-chat-ticker-paid-message-item-renderer, h4.yt-live-chat-ticker-paid-message-item-renderer, h5.yt-live-chat-ticker-paid-message-item-renderer, h6.yt-live-chat-ticker-paid-message-item-renderer, hr.yt-live-chat-ticker-paid-message-item-renderer, i.yt-live-chat-ticker-paid-message-item-renderer, iframe.yt-live-chat-ticker-paid-message-item-renderer, img.yt-live-chat-ticker-paid-message-item-renderer, ins.yt-live-chat-ticker-paid-message-item-renderer, kbd.yt-live-chat-ticker-paid-message-item-renderer, label.yt-live-chat-ticker-paid-message-item-renderer, legend.yt-live-chat-ticker-paid-message-item-renderer, li.yt-live-chat-ticker-paid-message-item-renderer, menu.yt-live-chat-ticker-paid-message-item-renderer, object.yt-live-chat-ticker-paid-message-item-renderer, ol.yt-live-chat-ticker-paid-message-item-renderer, p.yt-live-chat-ticker-paid-message-item-renderer, pre.yt-live-chat-ticker-paid-message-item-renderer, q.yt-live-chat-ticker-paid-message-item-renderer, s.yt-live-chat-ticker-paid-message-item-renderer, samp.yt-live-chat-ticker-paid-message-item-renderer, small.yt-live-chat-ticker-paid-message-item-renderer, span.yt-live-chat-ticker-paid-message-item-renderer, strike.yt-live-chat-ticker-paid-message-item-renderer, strong.yt-live-chat-ticker-paid-message-item-renderer, sub.yt-live-chat-ticker-paid-message-item-renderer, sup.yt-live-chat-ticker-paid-message-item-renderer, table.yt-live-chat-ticker-paid-message-item-renderer, tbody.yt-live-chat-ticker-paid-message-item-renderer, td.yt-live-chat-ticker-paid-message-item-renderer, tfoot.yt-live-chat-ticker-paid-message-item-renderer, th.yt-live-chat-ticker-paid-message-item-renderer, thead.yt-live-chat-ticker-paid-message-item-renderer, tr.yt-live-chat-ticker-paid-message-item-renderer, tt.yt-live-chat-ticker-paid-message-item-renderer, u.yt-live-chat-ticker-paid-message-item-renderer, ul.yt-live-chat-ticker-paid-message-item-renderer, var.yt-live-chat-ticker-paid-message-item-renderer { + margin: 0; + padding: 0; + border: 0; + background: transparent; +} + +.yt-live-chat-ticker-paid-message-item-renderer[hidden] { + display: none !important; +} + +yt-live-chat-ticker-paid-message-item-renderer { + display: inline-block; + font-size: 14px; + outline: none; + transition: width 0.2s; + vertical-align: top; + cursor: pointer; + -moz-user-select: none; + -ms-user-select: none; + -webkit-user-select: none; + user-select: none; +} + +#container.yt-live-chat-ticker-paid-message-item-renderer { + border-radius: 999px; + padding: 4px; +} + +yt-live-chat-ticker-paid-message-item-renderer.sliding-down #container.yt-live-chat-ticker-paid-message-item-renderer { + opacity: 0.5; + transform: translateY(44px); + transition: opacity 0.2s, transform 0.2s cubic-bezier(0.4, 0.0, 1, 1); +} + +yt-live-chat-ticker-paid-message-item-renderer.collapsing { + margin-right: 0; + transition: margin-right 0.2s cubic-bezier(0.4, 0.0, 0.2, 1), width 0.2s cubic-bezier(0.4, 0.0, 0.2, 1); +} + +yt-live-chat-ticker-paid-message-item-renderer[dimmed] { + opacity: 0.5; +} + +yt-img-shadow.yt-live-chat-ticker-paid-message-item-renderer { + margin-right: -4px; + overflow: hidden; + border-radius: 50%; +} + +#content.yt-live-chat-ticker-paid-message-item-renderer { + height: 24px; + display: flex; + -ms-flex-direction: row; + -webkit-flex-direction: row; + flex-direction: row; + -ms-flex-align: center; + -webkit-align-items: center; + align-items: center; +} + +#text.yt-live-chat-ticker-paid-message-item-renderer { + margin: 0 8px; + font-weight: 500; +} + +yt-live-chat-ticker-paid-message-item-renderer[is-deleted] #author-photo.yt-live-chat-ticker-paid-message-item-renderer { + display: none; +} diff --git a/src/assets/css/youtube/yt-live-chat-ticker-renderer.css b/src/assets/css/youtube/yt-live-chat-ticker-renderer.css new file mode 100644 index 0000000..029720d --- /dev/null +++ b/src/assets/css/youtube/yt-live-chat-ticker-renderer.css @@ -0,0 +1,65 @@ +canvas.yt-live-chat-ticker-renderer, caption.yt-live-chat-ticker-renderer, center.yt-live-chat-ticker-renderer, cite.yt-live-chat-ticker-renderer, code.yt-live-chat-ticker-renderer, dd.yt-live-chat-ticker-renderer, del.yt-live-chat-ticker-renderer, dfn.yt-live-chat-ticker-renderer, div.yt-live-chat-ticker-renderer, dl.yt-live-chat-ticker-renderer, dt.yt-live-chat-ticker-renderer, em.yt-live-chat-ticker-renderer, embed.yt-live-chat-ticker-renderer, fieldset.yt-live-chat-ticker-renderer, font.yt-live-chat-ticker-renderer, form.yt-live-chat-ticker-renderer, h1.yt-live-chat-ticker-renderer, h2.yt-live-chat-ticker-renderer, h3.yt-live-chat-ticker-renderer, h4.yt-live-chat-ticker-renderer, h5.yt-live-chat-ticker-renderer, h6.yt-live-chat-ticker-renderer, hr.yt-live-chat-ticker-renderer, i.yt-live-chat-ticker-renderer, iframe.yt-live-chat-ticker-renderer, img.yt-live-chat-ticker-renderer, ins.yt-live-chat-ticker-renderer, kbd.yt-live-chat-ticker-renderer, label.yt-live-chat-ticker-renderer, legend.yt-live-chat-ticker-renderer, li.yt-live-chat-ticker-renderer, menu.yt-live-chat-ticker-renderer, object.yt-live-chat-ticker-renderer, ol.yt-live-chat-ticker-renderer, p.yt-live-chat-ticker-renderer, pre.yt-live-chat-ticker-renderer, q.yt-live-chat-ticker-renderer, s.yt-live-chat-ticker-renderer, samp.yt-live-chat-ticker-renderer, small.yt-live-chat-ticker-renderer, span.yt-live-chat-ticker-renderer, strike.yt-live-chat-ticker-renderer, strong.yt-live-chat-ticker-renderer, sub.yt-live-chat-ticker-renderer, sup.yt-live-chat-ticker-renderer, table.yt-live-chat-ticker-renderer, tbody.yt-live-chat-ticker-renderer, td.yt-live-chat-ticker-renderer, tfoot.yt-live-chat-ticker-renderer, th.yt-live-chat-ticker-renderer, thead.yt-live-chat-ticker-renderer, tr.yt-live-chat-ticker-renderer, tt.yt-live-chat-ticker-renderer, u.yt-live-chat-ticker-renderer, ul.yt-live-chat-ticker-renderer, var.yt-live-chat-ticker-renderer { + margin: 0; + padding: 0; + border: 0; + background: transparent; +} + +.yt-live-chat-ticker-renderer[hidden] { + display: none !important; +} + +yt-live-chat-ticker-renderer { + display: block; + background-color: var(--yt-live-chat-header-background-color); +} + +#container.yt-live-chat-ticker-renderer { + position: relative; +} + +#items.yt-live-chat-ticker-renderer { + height: 32px; + overflow: hidden; + white-space: nowrap; + padding: 0 24px 8px 24px; +} + +#items.yt-live-chat-ticker-renderer>*.yt-live-chat-ticker-renderer { + margin-right: 8px; +} + +#left-arrow-container.yt-live-chat-ticker-renderer { + background: linear-gradient(to right, var(--yt-live-chat-ticker-arrow-background) 0, var(--yt-live-chat-ticker-arrow-background) 52px, transparent 60px); + left: 0; + padding: 0 16px 0 12px; +} + +#right-arrow-container.yt-live-chat-ticker-renderer { + background: linear-gradient(to left, var(--yt-live-chat-ticker-arrow-background) 0, var(--yt-live-chat-ticker-arrow-background) 52px, transparent 60px); + right: 0; + padding: 0 12px 0 16px; +} + +#container.yt-live-chat-ticker-renderer:hover #left-arrow-container.yt-live-chat-ticker-renderer, #container.yt-live-chat-ticker-renderer:hover #right-arrow-container.yt-live-chat-ticker-renderer { + opacity: 1; +} + +#left-arrow-container.yt-live-chat-ticker-renderer, #right-arrow-container.yt-live-chat-ticker-renderer { + height: 32px; + opacity: 0; + position: absolute; + text-align: center; + top: 0; + transition: opacity 0.3s 0.1s; +} + +yt-icon.yt-live-chat-ticker-renderer { + background-color: #2196f3; + border-radius: 999px; + color: #fff; + cursor: pointer; + height: 24px; + padding: 4px; + width: 24px; +} diff --git a/src/data/DanmakuClient.ts b/src/data/DanmakuClient.ts index 22d0a31..d33f1dd 100644 --- a/src/data/DanmakuClient.ts +++ b/src/data/DanmakuClient.ts @@ -1,10 +1,10 @@ import { EventDataTypes, EventModel, OpenLiveInfo } from '@/api/api-models' import { QueryGetAPI, QueryPostAPI } from '@/api/query' +// @ts-expect-error 忽略js错误 import ChatClientDirectOpenLive from '@/data/chat/ChatClientDirectOpenLive.js' -import { ref } from 'vue' +import { GuidUtils } from '@/Utils' import { clearInterval, setInterval } from 'worker-timers' import { OPEN_LIVE_API_URL } from './constants' -import { GuidUtils } from '@/Utils' export interface DanmakuInfo { room_id: number @@ -71,7 +71,7 @@ export interface SCInfo { fans_medal_name: string // 对应房间勋章名字 (新增) fans_medal_wearing_status: boolean // 该房间粉丝勋章佩戴情况 (新增) } -interface GuardInfo { +export interface GuardInfo { user_info: { uid: number // 用户uid open_id: string @@ -139,6 +139,7 @@ interface AnchorInfo { * 主播uid */ uid: number + open_id: string } export interface RoomAuthInfo { /** @@ -154,7 +155,7 @@ export interface RoomAuthInfo { */ anchor_info: AnchorInfo } -interface DanmakuEventsMap { +export interface DanmakuEventsMap { danmaku: (arg1: DanmakuInfo, arg2?: any) => void gift: (arg1: GiftInfo, arg2?: any) => void sc: (arg1: SCInfo, arg2?: any) => void @@ -172,12 +173,12 @@ export default class DanmakuClient { private isStarting = false public authInfo: AuthInfo | null - public roomAuthInfo = ref({} as RoomAuthInfo) + public roomAuthInfo: RoomAuthInfo | undefined public authCode: string | undefined public isRunning: boolean = false - private events: { + public events: { danmaku: ((arg1: DanmakuInfo, arg2?: any) => void)[] gift: ((arg1: GiftInfo, arg2?: any) => void)[] sc: ((arg1: SCInfo, arg2?: any) => void)[] @@ -188,9 +189,9 @@ export default class DanmakuClient { gift: [], sc: [], guard: [], - all: [], + all: [] } - private eventsAsModel: { + public eventsAsModel: { danmaku: ((arg1: EventModel, arg2?: any) => void)[] gift: ((arg1: EventModel, arg2?: any) => void)[] sc: ((arg1: EventModel, arg2?: any) => void)[] @@ -201,20 +202,20 @@ export default class DanmakuClient { gift: [], sc: [], guard: [], - all: [], + all: [] } public async Start(): Promise<{ success: boolean; message: string }> { if (this.isRunning) { return { - success: false, - message: '弹幕客户端已启动', + success: true, + message: '弹幕客户端已启动' } } if (this.isStarting) { return { success: false, - message: '弹幕客户端正在启动', + message: '弹幕客户端正在启动' } } this.isStarting = true @@ -233,7 +234,7 @@ export default class DanmakuClient { console.warn('[OPEN-LIVE] 弹幕客户端已被启动过') return { success: false, - message: '弹幕客户端已被启动过', + message: '弹幕客户端已被启动过' } } } finally { @@ -260,14 +261,14 @@ export default class DanmakuClient { gift: [], sc: [], guard: [], - all: [], + all: [] } this.eventsAsModel = { danmaku: [], gift: [], sc: [], guard: [], - all: [], + all: [] } } private sendHeartbeat() { @@ -277,7 +278,10 @@ export default class DanmakuClient { return } const query = this.authInfo - ? QueryPostAPI(OPEN_LIVE_API_URL + 'heartbeat', this.authInfo) + ? QueryPostAPI( + OPEN_LIVE_API_URL + 'heartbeat', + this.authInfo + ) : QueryGetAPI(OPEN_LIVE_API_URL + 'heartbeat-internal') query.then((data) => { if (data.code != 200) { @@ -289,7 +293,7 @@ export default class DanmakuClient { }) } - private onRawMessage = (command: any) => { + public onRawMessage = (command: any) => { this.eventsAsModel.all?.forEach((d) => { d(command) }) @@ -298,7 +302,7 @@ export default class DanmakuClient { }) } - private onDanmaku = (command: any) => { + public onDanmaku = (command: any) => { const data = command.data as DanmakuInfo this.events.danmaku?.forEach((d) => { @@ -321,13 +325,13 @@ export default class DanmakuClient { emoji: data.dm_type == 1 ? data.emoji_img_url : undefined, uface: data.uface, open_id: data.open_id, - ouid: data.open_id ?? GuidUtils.numToGuid(data.uid), + ouid: data.open_id ?? GuidUtils.numToGuid(data.uid) }, - command, + command ) }) } - private onGift = (command: any) => { + public onGift = (command: any) => { const data = command.data as GiftInfo const price = (data.price * data.gift_num) / 1000 this.events.gift?.forEach((d) => { @@ -349,13 +353,13 @@ export default class DanmakuClient { fans_medal_wearing_status: data.fans_medal_wearing_status, uface: data.uface, open_id: data.open_id, - ouid: data.open_id ?? GuidUtils.numToGuid(data.uid), + ouid: data.open_id ?? GuidUtils.numToGuid(data.uid) }, - command, + command ) }) } - private onSC = (command: any) => { + public onSC = (command: any) => { const data = command.data as SCInfo this.events.sc?.forEach((d) => { d(data, command) @@ -376,13 +380,13 @@ export default class DanmakuClient { fans_medal_wearing_status: data.fans_medal_wearing_status, uface: data.uface, open_id: data.open_id, - ouid: data.open_id ?? GuidUtils.numToGuid(data.uid), + ouid: data.open_id ?? GuidUtils.numToGuid(data.uid) }, - command, + command ) }) } - private onGuard = (command: any) => { + public onGuard = (command: any) => { const data = command.data as GuardInfo this.events.guard?.forEach((d) => { d(data, command) @@ -393,7 +397,14 @@ export default class DanmakuClient { type: EventDataTypes.Guard, name: data.user_info.uname, uid: data.user_info.uid, - msg: data.guard_level == 1 ? '总督' : data.guard_level == 2 ? '提督' : data.guard_level == 3 ? '舰长' : '', + msg: + data.guard_level == 1 + ? '总督' + : data.guard_level == 2 + ? '提督' + : data.guard_level == 3 + ? '舰长' + : '', price: 0, num: data.guard_num, time: data.timestamp, @@ -403,9 +414,10 @@ export default class DanmakuClient { fans_medal_wearing_status: data.fans_medal_wearing_status, uface: data.user_info.uface, open_id: data.user_info.open_id, - ouid: data.user_info.open_id ?? GuidUtils.numToGuid(data.user_info.uid), + ouid: + data.user_info.open_id ?? GuidUtils.numToGuid(data.user_info.uid) }, - command, + command ) }) } @@ -413,26 +425,47 @@ export default class DanmakuClient { public on(eventName: 'gift', listener: DanmakuEventsMap['gift']): this public on(eventName: 'sc', listener: DanmakuEventsMap['sc']): this public on(eventName: 'guard', listener: DanmakuEventsMap['guard']): this - public on(eventName: 'danmaku' | 'gift' | 'sc' | 'guard', listener: (...args: any[]) => void): this { + public on( + eventName: 'danmaku' | 'gift' | 'sc' | 'guard', + listener: (...args: any[]) => void + ): this { if (!this.events[eventName]) { this.events[eventName] = [] } this.events[eventName].push(listener) return this } - public onEvent(eventName: 'danmaku', listener: (arg1: EventModel, arg2?: any) => void): this - public onEvent(eventName: 'gift', listener: (arg1: EventModel, arg2?: any) => void): this - public onEvent(eventName: 'sc', listener: (arg1: EventModel, arg2?: any) => void): this - public onEvent(eventName: 'guard', listener: (arg1: EventModel, arg2?: any) => void): this + public onEvent( + eventName: 'danmaku', + listener: (arg1: EventModel, arg2?: any) => void + ): this + public onEvent( + eventName: 'gift', + listener: (arg1: EventModel, arg2?: any) => void + ): this + public onEvent( + eventName: 'sc', + listener: (arg1: EventModel, arg2?: any) => void + ): this + public onEvent( + eventName: 'guard', + listener: (arg1: EventModel, arg2?: any) => void + ): this public onEvent(eventName: 'all', listener: (arg1: any) => void): this - public onEvent(eventName: 'danmaku' | 'gift' | 'sc' | 'guard' | 'all', listener: (...args: any[]) => void): this { + public onEvent( + eventName: 'danmaku' | 'gift' | 'sc' | 'guard' | 'all', + listener: (...args: any[]) => void + ): this { if (!this.eventsAsModel[eventName]) { this.eventsAsModel[eventName] = [] } this.eventsAsModel[eventName].push(listener) return this } - public off(eventName: 'danmaku' | 'gift' | 'sc' | 'guard', listener: (...args: any[]) => void): this { + public off( + eventName: 'danmaku' | 'gift' | 'sc' | 'guard', + listener: (...args: any[]) => void + ): this { if (this.events[eventName]) { const index = this.events[eventName].indexOf(listener) if (index > -1) { @@ -441,7 +474,10 @@ export default class DanmakuClient { } return this } - public offEvent(eventName: 'danmaku' | 'gift' | 'sc' | 'guard', listener: (...args: any[]) => void): this { + public offEvent( + eventName: 'danmaku' | 'gift' | 'sc' | 'guard', + listener: (...args: any[]) => void + ): this { if (this.eventsAsModel[eventName]) { const index = this.eventsAsModel[eventName].indexOf(listener) if (index > -1) { @@ -457,43 +493,46 @@ export default class DanmakuClient { //chatClient.msgHandler = this; chatClient.CMD_CALLBACK_MAP = this.CMD_CALLBACK_MAP chatClient.start() - this.roomAuthInfo.value = auth.data + this.roomAuthInfo = auth.data as RoomAuthInfo this.client = chatClient console.log('[OPEN-LIVE] 已连接房间: ' + auth.data.anchor_info.room_id) return { success: true, - message: '', + message: '' } } else { console.log('[OPEN-LIVE] 无法开启场次: ' + auth.message) return { success: false, - message: auth.message, + message: auth.message } } } - private async getAuthInfo(): Promise<{ data: OpenLiveInfo | null; message: string }> { + private async getAuthInfo(): Promise<{ + data: OpenLiveInfo | null + message: string + }> { try { const data = await QueryPostAPI( OPEN_LIVE_API_URL + 'start', - this.authInfo?.Code ? this.authInfo : undefined, + this.authInfo?.Code ? this.authInfo : undefined ) if (data.code == 200) { console.log('[OPEN-LIVE] 已获取场次信息') return { data: data.data, - message: '', + message: '' } } else { return { data: null, - message: data.message, + message: data.message } } } catch (err) { return { data: null, - message: err?.toString() || '未知错误', + message: err?.toString() || '未知错误' } } } @@ -503,6 +542,6 @@ export default class DanmakuClient { LIVE_OPEN_PLATFORM_SEND_GIFT: this.onGift.bind(this), LIVE_OPEN_PLATFORM_SUPER_CHAT: this.onSC.bind(this), LIVE_OPEN_PLATFORM_GUARD: this.onGuard.bind(this), - RAW_MESSAGE: this.onRawMessage.bind(this), + RAW_MESSAGE: this.onRawMessage.bind(this) } } diff --git a/src/data/RTCClient.ts b/src/data/RTCClient.ts index a1cc30a..7de9590 100644 --- a/src/data/RTCClient.ts +++ b/src/data/RTCClient.ts @@ -1,7 +1,6 @@ import { useAccount } from '@/api/account' import { useVTsuruHub } from '@/store/useVTsuruHub' import Peer, { DataConnection } from 'peerjs' -import { Ref, ref } from 'vue' export interface ComponentsEventHubModel { IsMaster: boolean @@ -27,29 +26,34 @@ abstract class BaseRTCClient { public peer?: Peer protected connections: DataConnection[] = [] + protected handledEvents: { [key: string]: string[] } = {} protected events: { - [key: string]: ((args: unknown) => void)[] + [key: string]: ((args: any) => void)[] } = {} abstract type: 'master' | 'slave' - public on(eventName: string, listener: (args: unknown) => void) { + public on(eventName: string, listener: (args: any) => void) { eventName = eventName.toLowerCase() if (!this.events[eventName]) { this.events[eventName] = [] } this.events[eventName].push(listener) + + this.send('VTsuru.RTCEvent.On', eventName) } - public off(eventName: string, listener: (args: unknown) => void) { + public off(eventName: string, listener: (args: any) => void) { if (this.events[eventName]) { const index = this.events[eventName].indexOf(listener) if (index > -1) { this.events[eventName].splice(index, 1) } } + + this.send('VTsuru.RTCEvent.Off', eventName) } - public send(eventName: string, data: unknown) { + public send(eventName: string, data: any) { this.connections.forEach((item) => item.send({ Key: eventName, @@ -93,10 +97,18 @@ abstract class BaseRTCClient { this.peer?.reconnect() }) } - public processData(data: RTCData) { + public processData(conn: DataConnection, data: RTCData) { //console.log(data) - if (data.Key == 'Heartbeat') return - if (this.events[data.Key.toLowerCase()]) { + if (data.Key == 'Heartbeat') { // 心跳 + return + } else if (data.Key == 'VTsuru.RTCEvent.On') { // 添加事件 + this.handledEvents[conn.peer].push(data.Data) + } else if (data.Key == 'VTsuru.RTCEvent.Off') { // 移除事件 + const i = this.handledEvents[conn.peer].indexOf(data.Data) + if (i > -1) { + this.handledEvents[conn.peer].splice(i, 1) + } + } else if (this.events[data.Key.toLowerCase()]) { this.events[data.Key].forEach((item) => item(data.Data)) } } @@ -107,6 +119,8 @@ abstract class BaseRTCClient { } protected onConnectionClose(id: string) { this.connections = this.connections.filter((item) => item.peer != id) + delete this.handledEvents[id] + console.log( `[Components-Event] <${this.connections.length}> ${this.type == 'master' ? 'Slave' : 'Master'} 下线: ` + id @@ -140,17 +154,20 @@ export class SlaveRTCClient extends BaseRTCClient { //console.log('[Components-Event] 正在连接到现有 Master: ' + item.Token) }) } - public connectToMaster(token: string) { - if (this.connections.some((conn) => conn.peer == token)) return - const c = this.peer?.connect(token) + public connectToMaster(id: string) { + if (this.connections.some((conn) => conn.peer == id)) return + const c = this.peer?.connect(id) c?.on('open', () => { this.connections.push(c) + + this.handledEvents[id] = [] + console.log( `[Components-Event] <${this.connections.length}> ==> Master 连接已建立: ` + - token + id ) }) - c?.on('data', (data) => this.processData(data as RTCData)) + c?.on('data', (data) => this.processData(c, data as RTCData)) c?.on('close', () => this.onConnectionClose(c.peer)) } public Init() { @@ -171,21 +188,24 @@ export class MasterRTCClient extends BaseRTCClient { super(user, pass) } type: 'master' = 'master' as const + public connectRTC() { super.connectRTC() this.peer?.on('connection', (conn) => { conn.on('open', () => { this.connections.push(conn) + this.handledEvents[conn.peer] = [] console.log( `[Components-Event] <${this.connections.length}> Slave 上线: ` + conn.peer ) }) - conn.on('data', (data) => this.processData(data as RTCData)) + conn.on('data', (d) => this.processData(conn, d as RTCData)) conn.on('error', (err) => console.error(err)) conn.on('close', () => this.onConnectionClose(conn.peer)) }) } + public Init() { return super.Init() } diff --git a/src/main.ts b/src/main.ts index fa7d834..79dd434 100644 --- a/src/main.ts +++ b/src/main.ts @@ -9,6 +9,7 @@ import { GetSelfAccount, UpdateAccountLoop, useAccount } from './api/account' import { GetNotifactions } from './data/notifactions' import router from './router' import { useAuthStore } from './store/useAuthStore' +import { useVTsuruHub } from './store/useVTsuruHub' const pinia = createPinia() @@ -35,41 +36,59 @@ QueryGetAPI(BASE_API_URL + 'vtsuru/version') title: '发现新的版本更新', content: '将自动刷新页面', duration: 5000, - meta: () => h(NText, { depth: 3 }, () => currentVersion), + meta: () => h(NText, { depth: 3 }, () => currentVersion) }) } else { setInterval(() => { if (isHaveNewVersion) { return } - QueryGetAPI(BASE_API_URL + 'vtsuru/version').then((keepCheckData) => { - if (keepCheckData.code == 200 && keepCheckData.data != currentVersion) { - isHaveNewVersion = true - currentVersion = keepCheckData.data - localStorage.setItem('Version', currentVersion) - console.log('[vtsuru] 发现新版本: ' + currentVersion) + QueryGetAPI(BASE_API_URL + 'vtsuru/version').then( + (keepCheckData) => { + if ( + keepCheckData.code == 200 && + keepCheckData.data != currentVersion + ) { + isHaveNewVersion = true + currentVersion = keepCheckData.data + localStorage.setItem('Version', currentVersion) + console.log('[vtsuru] 发现新版本: ' + currentVersion) - const url = new URL(window.location.href) - const path = url.pathname + const url = new URL(window.location.href) + const path = url.pathname - if (!path.startsWith('/obs')) { - const n = notification.info({ - title: '发现新的版本更新', - content: '是否现在刷新?', - meta: () => h(NText, { depth: 3 }, () => currentVersion), - action: () => - h(NFlex, null, () => [ - h( - NButton, - { text: true, type: 'primary', onClick: () => location.reload(), size: 'small' }, - { default: () => '刷新' }, - ), - h(NButton, { text: true, onClick: () => n.destroy(), size: 'small' }, { default: () => '稍后' }), - ]), - }) + if (!path.startsWith('/obs')) { + const n = notification.info({ + title: '发现新的版本更新', + content: '是否现在刷新?', + meta: () => h(NText, { depth: 3 }, () => currentVersion), + action: () => + h(NFlex, null, () => [ + h( + NButton, + { + text: true, + type: 'primary', + onClick: () => location.reload(), + size: 'small' + }, + { default: () => '刷新' } + ), + h( + NButton, + { + text: true, + onClick: () => n.destroy(), + size: 'small' + }, + { default: () => '稍后' } + ) + ]) + }) + } } } - }) + ) }, 60 * 1000) } } @@ -82,6 +101,7 @@ QueryGetAPI(BASE_API_URL + 'vtsuru/version') //加载其他数据 await GetSelfAccount() const account = useAccount() + const vhub = useVTsuruHub().Init(account.value.token) const useAuth = useAuthStore() if (account.value.id) { if (account.value.biliUserAuthInfo && !useAuth.currentToken) { diff --git a/src/router/obs.ts b/src/router/obs.ts index 7c8e091..d4caeea 100644 --- a/src/router/obs.ts +++ b/src/router/obs.ts @@ -7,8 +7,8 @@ export default { name: 'obs-live-lottery', component: () => import('@/views/obs/LiveLotteryOBS.vue'), meta: { - title: '直播抽奖', - }, + title: '直播抽奖' + } }, { path: 'live-request', @@ -16,40 +16,48 @@ export default { alias: 'song-request', component: () => import('@/views/obs/LiveRequestOBS.vue'), meta: { - title: '弹幕点歌 (歌势', - }, + title: '弹幕点歌 (歌势' + } }, { path: 'queue', name: 'obs-queue', component: () => import('@/views/obs/QueueOBS.vue'), meta: { - title: '弹幕排队', - }, + title: '弹幕排队' + } }, { path: 'music-request', name: 'obs-music-request', component: () => import('@/views/obs/MusicRequestOBS.vue'), meta: { - title: '弹幕排队 (播放', - }, + title: '弹幕排队 (播放' + } }, { path: 'question-display', name: 'obs-question-display', component: () => import('@/views/obs/QuestionDisplayOBS.vue'), meta: { - title: '棉花糖展示', - }, + title: '棉花糖展示' + } }, { path: 'web-fetcher', name: 'obs-web-fetcher', component: () => import('@/views/obs/WebFetcherOBS.vue'), meta: { - title: '弹幕收集器 (OBS版', - }, + title: '弹幕收集器 (OBS版' + } }, - ], + { + path: 'danmuji', + name: 'obs-danmuji', + component: () => import('@/views/obs/DanmujiOBS.vue'), + meta: { + title: '弹幕机' + } + } + ] } diff --git a/src/store/useDanmakuClient.ts b/src/store/useDanmakuClient.ts new file mode 100644 index 0000000..3767f4c --- /dev/null +++ b/src/store/useDanmakuClient.ts @@ -0,0 +1,232 @@ +import DanmakuClient, { AuthInfo, RoomAuthInfo } from '@/data/DanmakuClient' +import { defineStore } from 'pinia' +import { computed, ref } from 'vue' + +export interface BCMessage { + type: string + data: string +} + +export const useDanmakuClient = defineStore('DanmakuClient', () => { + const danmakuClient = ref(new DanmakuClient(null)) + let bc: BroadcastChannel + const isOwnedDanmakuClient = ref(false) + const status = ref<'waiting' | 'initializing' | 'listening' | 'running'>( + 'waiting' + ) + const connected = computed( + () => status.value === 'running' || status.value === 'listening' + ) + const authInfo = ref() + + let existOtherClient = false + let isInitializing = false + + function on( + eventName: 'danmaku' | 'gift' | 'sc' | 'guard', + listener: (...args: any[]) => void + ) { + if (!danmakuClient.value.events[eventName]) { + danmakuClient.value.events[eventName] = [] + } + danmakuClient.value.events[eventName].push(listener) + } + function onEvent( + eventName: 'danmaku' | 'gift' | 'sc' | 'guard' | 'all', + listener: (...args: any[]) => void + ) { + if (!danmakuClient.value.eventsAsModel[eventName]) { + danmakuClient.value.eventsAsModel[eventName] = [] + } + danmakuClient.value.eventsAsModel[eventName].push(listener) + } + + function off( + eventName: 'danmaku' | 'gift' | 'sc' | 'guard', + listener: (...args: any[]) => void + ) { + if (danmakuClient.value.events[eventName]) { + const index = danmakuClient.value.events[eventName].indexOf(listener) + if (index > -1) { + danmakuClient.value.events[eventName].splice(index, 1) + } + } + } + + function offEvent( + eventName: 'danmaku' | 'gift' | 'sc' | 'guard' | 'all', + listener: (...args: any[]) => void + ) { + if (danmakuClient.value.eventsAsModel[eventName]) { + const index = + danmakuClient.value.eventsAsModel[eventName].indexOf(listener) + if (index > -1) { + danmakuClient.value.eventsAsModel[eventName].splice(index, 1) + } + } + } + + async function initClient(auth?: AuthInfo) { + if (!isInitializing && !connected.value) { + isInitializing = true + navigator.locks.request( + 'danmakuClientInit', + { ifAvailable: true }, + async (lock) => { + if (lock) { + status.value = 'initializing' + bc = new BroadcastChannel('vtsuru.danmaku') + bc.onmessage = (event) => { + const message: BCMessage = event.data as BCMessage + const data = message.data ? JSON.parse(message.data) : {} + switch (message.type) { + case 'check-client': + sendBCMessage('response-client-status', { + status: status.value, + auth: authInfo.value + }) + break + case 'response-client-status': + switch ( + data.status //如果存在已经在运行或者正在启动的客户端, 状态设为 listening + ) { + case 'running': + case 'initializing': + status.value = 'listening' + existOtherClient = true + authInfo.value = data.auth + break + } + break + case 'on-danmaku': + const danmaku = JSON.parse(data) + switch (danmaku.cmd) { + case 'LIVE_OPEN_PLATFORM_DM': + danmakuClient.value.onDanmaku(danmaku) + break + case 'LIVE_OPEN_PLATFORM_SEND_GIFT': + danmakuClient.value.onGift(danmaku) + break + case 'LIVE_OPEN_PLATFORM_SUPER_CHAT': + danmakuClient.value.onSC(danmaku) + break + case 'LIVE_OPEN_PLATFORM_GUARD': + danmakuClient.value.onGuard(danmaku) + break + default: + danmakuClient.value.onRawMessage(danmaku) + break + } + break + } + } + console.log('[DanmakuClient] 正在检查客户端状态...') + sendBCMessage('check-client') + setTimeout(() => { + if (!connected.value) { + isOwnedDanmakuClient.value = true + initClientInternal(auth) + } else { + console.log( + '[DanmakuClient] 已存在其他页面弹幕客户端, 开始监听 BroadcastChannel...' + ) + } + + setInterval(checkClientStatus, 500) + }, 1000) + } + } + ) + } + isInitializing = false + return useDanmakuClient() + } + function sendBCMessage(type: string, data?: any) { + bc.postMessage({ + type, + data: JSON.stringify(data) + }) + } + function checkClientStatus() { + if (!existOtherClient && !isOwnedDanmakuClient.value) { + //当不存在其他客户端, 且自己不是弹幕客户端 + //则自己成为新的弹幕客户端 + if (status.value != 'initializing') { + console.log('[DanmakuClient] 其他 Client 离线, 开始初始化...') + initClientInternal() + } + } else { + existOtherClient = false //假设其他客户端不存在 + sendBCMessage('check-client') //检查其他客户端是否存在 + } + } + + async function initClientInternal(auth?: AuthInfo) { + status.value = 'initializing' + await navigator.locks.request( + 'danmakuClientInitInternal', + { + ifAvailable: true + }, + async (lock) => { + if (lock) { + // 有锁 + isOwnedDanmakuClient.value = true + const events = danmakuClient.value.events + const eventsAsModel = danmakuClient.value.eventsAsModel + + danmakuClient.value = new DanmakuClient(auth || null) + + danmakuClient.value.events = events + danmakuClient.value.eventsAsModel = eventsAsModel + const init = async () => { + const result = await danmakuClient.value.Start() + if (result.success) { + authInfo.value = danmakuClient.value.roomAuthInfo + status.value = 'running' + console.log('[DanmakuClient] 初始化成功') + sendBCMessage('response-client-status', { + status: 'running', + auth: authInfo.value + }) + danmakuClient.value.onEvent('all', (data) => { + sendBCMessage('on-danmaku', data) + }) + return true + } else { + console.log( + '[DanmakuClient] 初始化失败, 5秒后重试: ' + result.message + ) + return false + } + } + while (!(await init())) { + await new Promise((resolve) => { + setTimeout(() => { + resolve(true) + }, 5000) + }) + } + } else { + // 无锁 + console.log('[DanmakuClient] 正在等待其他页面弹幕客户端初始化...') + status.value = 'listening' + isOwnedDanmakuClient.value = false + } + } + ) + } + + return { + danmakuClient, + isOwnedDanmakuClient, + status, + connected, + authInfo, + on, + off, + onEvent, + offEvent, + initClient + } +}) diff --git a/src/store/useRTC.ts b/src/store/useRTC.ts index 808fa5f..ae49664 100644 --- a/src/store/useRTC.ts +++ b/src/store/useRTC.ts @@ -7,30 +7,52 @@ export const useWebRTC = defineStore('WebRTC', () => { const masterClient = ref() const slaveClient = ref() const accountInfo = useAccount() + let isInitializing = false - function Init(type: 'master' | 'slave') { - if (type == 'master') { - if (masterClient.value) { - return masterClient - } else { - masterClient.value = new MasterRTCClient( - accountInfo.value.id.toString(), - accountInfo.value.token - ) - masterClient.value.Init() - return masterClient - } - } else { - if (slaveClient.value) { - return slaveClient - } else { - slaveClient.value = new SlaveRTCClient( - accountInfo.value.id.toString(), - accountInfo.value.token - ) - slaveClient.value.Init() - return slaveClient - } + function Init(type: 'master' | 'slave'): MasterRTCClient | SlaveRTCClient | undefined { + if (isInitializing) { + return + } + try { + isInitializing = true + navigator.locks.request( + 'rtcClientInit', + { + ifAvailable: true + }, + async (lock) => { + if (lock) { + if (type == 'master') { + if (masterClient.value) { + return masterClient + } else { + masterClient.value = new MasterRTCClient( + accountInfo.value.id.toString(), + accountInfo.value.token + ) + masterClient.value.Init() + return masterClient + } + } else { + if (slaveClient.value) { + return slaveClient + } else { + slaveClient.value = new SlaveRTCClient( + accountInfo.value.id?.toString(), + accountInfo.value.token + ) + slaveClient.value.Init() + return slaveClient + } + } + } + } + ) + } catch (e) { + console.error(e) + throw e + } finally { + isInitializing = false } } diff --git a/src/store/useVTsuruHub.ts b/src/store/useVTsuruHub.ts index 66afa7e..6a46e41 100644 --- a/src/store/useVTsuruHub.ts +++ b/src/store/useVTsuruHub.ts @@ -10,17 +10,17 @@ import { acceptHMRUpdate, defineStore } from 'pinia' import { ref } from 'vue' export const useVTsuruHub = defineStore('VTsuruHub', () => { - const accountInfo = useAccount() const signalRClient = ref() const isInited = ref(false) const isIniting = ref(false) + let token = '' async function connectSignalR() { if (isIniting.value) return isIniting.value = true //console.log('[Components-Event] 正在连接到 VTsuru 服务器...') const connection = new HubConnectionBuilder() - .withUrl(BASE_HUB_URL + 'main?token=' + accountInfo.value.token, { + .withUrl(BASE_HUB_URL + 'main?token=' + token, { skipNegotiation: true, transport: HttpTransportType.WebSockets, logger: LogLevel.Error @@ -91,7 +91,8 @@ export const useVTsuruHub = defineStore('VTsuruHub', () => { signalRClient.value?.onreconnected(listener) } - function Init() { + function Init(_token: string) { + token = _token if (!isInited.value) { connectSignalR() } diff --git a/src/views/ManageLayout.vue b/src/views/ManageLayout.vue index 61dd76f..e5b8e63 100644 --- a/src/views/ManageLayout.vue +++ b/src/views/ManageLayout.vue @@ -549,8 +549,7 @@ onMounted(() => { - - + @@ -856,13 +817,8 @@ onUnmounted(() => { 支持的变量: - + {{ item.words }} | {{ item.name }} @@ -889,14 +845,10 @@ onUnmounted(() => { 设置 - + 是否启用礼物合并