diff --git a/Chaturbate/chaturbate-thumbnails-2x.user.js b/Chaturbate/chaturbate-thumbnails-2x.user.js index 2ce4263..c5f6ad7 100644 --- a/Chaturbate/chaturbate-thumbnails-2x.user.js +++ b/Chaturbate/chaturbate-thumbnails-2x.user.js @@ -1,7 +1,7 @@ // ==UserScript== // @name Chaturbate 缩略图放大 2 倍 // @namespace https://chaturbate.com/ -// @version 0.10.7 +// @version 0.11.0 // @description 放大当前 Chaturbate 房间列表、发现页轮播、关注下拉与悬停预览缩略图 // @match https://chaturbate.com/* // @match https://*.chaturbate.com/* @@ -58,11 +58,11 @@ const DEBUG = true; // =========================== - const VER = "0.10.7"; + const VER = "0.11.0"; // 缓存只保存“站点原始尺寸”,不要保存乘过倍率后的尺寸。 // 这样以后只改 THUMBNAIL_SCALE / CARD_HEIGHT_SCALE 时,可以让缓存自动失效并重新探测,避免旧倍率污染新布局。 - const CACHE_KEY = "tm-thumb-scale:size-cache:v7"; - const CACHE_SCHEMA = 7; + const CACHE_KEY = "tm-thumb-scale:size-cache:v9"; + const CACHE_SCHEMA = 9; const log = (...args) => { if (DEBUG) console.log("[tm-thumb-scale]", ...args); }; @@ -87,8 +87,8 @@ /* * home 模块: * - 适用范围:主页、分类页等普通 #roomlist_root 房间列表。 - * - 探测值:卡片原始宽高 + 缩略图原始宽高。 - * - 放大方式:卡片和缩略图分别按自己的原始宽高乘倍率。 + * - 探测值:卡片原始宽度。 + * - 放大方式:只放大 grid 列宽;缩略图保持 100% / auto,跟随卡片自然缩放。 * - 注意:关注页列表单独用 followingList 模块,不和 home 共用缓存。 */ html[data-tm-thumb-scale-home="1"] #main #roomlist_root ul.RoomCardGrid, @@ -108,14 +108,11 @@ width: auto !important; min-width: 0 !important; max-width: none !important; - height: var(--tm-thumb-home-card-height) !important; - min-height: var(--tm-thumb-home-card-height) !important; - max-height: var(--tm-thumb-home-card-height) !important; } html[data-tm-thumb-scale-home="1"] #roomlist_root ul.RoomCardGrid .RoomCardThumbnail, html[data-tm-thumb-scale-home="1"] #roomlist_root ul.list:has(li.roomCard) .room_thumbnail_container { - width: var(--tm-thumb-home-thumb-width) !important; - height: var(--tm-thumb-home-thumb-height) !important; + width: 100% !important; + height: auto !important; display: block !important; max-width: none !important; box-sizing: border-box !important; @@ -123,8 +120,8 @@ html[data-tm-thumb-scale-home="1"] #roomlist_root ul.RoomCardGrid .RoomCardThumbnail img, html[data-tm-thumb-scale-home="1"] #roomlist_root ul.list:has(li.roomCard) .room_thumbnail_container img, html[data-tm-thumb-scale-home="1"] #roomlist_root ul.list:has(li.roomCard) .room_thumbnail { - width: var(--tm-thumb-home-thumb-width) !important; - height: var(--tm-thumb-home-thumb-height) !important; + width: 100% !important; + height: auto !important; /* block 可以消掉图片 inline baseline 带来的细小空隙。 */ display: block !important; max-width: none !important; @@ -137,7 +134,9 @@ * - 适用范围:/followed-cams/ 关注页里的 #roomlist_root 房间列表。 * - 为什么和 home 分开:两者 DOM 选择器很像,但站点可能给不同页面不同原始列宽。 * - 缓存也单独存 followingList,避免首页探测值污染关注页。 - * - 探测值同样是 card 宽高 + thumb 宽高四项。 + * - 和 home 一样只放大 grid 最小列宽;图片跟随卡片自然缩放。 + * - 注意:这里仍保留 minmax(..., 1fr),让站点原来的整行拉伸/对齐逻辑继续工作。 + * 不能改成固定列宽,否则宽屏下会出现大空洞,看起来比原站更乱。 */ html[data-tm-thumb-scale-following-list="1"] #main #roomlist_root ul.RoomCardGrid, html[data-tm-thumb-scale-following-list="1"] #roomlist_root ul.RoomCardGrid, @@ -152,14 +151,11 @@ width: auto !important; min-width: 0 !important; max-width: none !important; - height: var(--tm-thumb-following-list-card-height) !important; - min-height: var(--tm-thumb-following-list-card-height) !important; - max-height: var(--tm-thumb-following-list-card-height) !important; } html[data-tm-thumb-scale-following-list="1"] #roomlist_root ul.RoomCardGrid .RoomCardThumbnail, html[data-tm-thumb-scale-following-list="1"] #roomlist_root ul.list:has(li.roomCard) .room_thumbnail_container { - width: var(--tm-thumb-following-list-thumb-width) !important; - height: var(--tm-thumb-following-list-thumb-height) !important; + width: 100% !important; + height: auto !important; display: block !important; max-width: none !important; box-sizing: border-box !important; @@ -167,8 +163,8 @@ html[data-tm-thumb-scale-following-list="1"] #roomlist_root ul.RoomCardGrid .RoomCardThumbnail img, html[data-tm-thumb-scale-following-list="1"] #roomlist_root ul.list:has(li.roomCard) .room_thumbnail_container img, html[data-tm-thumb-scale-following-list="1"] #roomlist_root ul.list:has(li.roomCard) .room_thumbnail { - width: var(--tm-thumb-following-list-thumb-width) !important; - height: var(--tm-thumb-following-list-thumb-height) !important; + width: 100% !important; + height: auto !important; display: block !important; max-width: none !important; box-sizing: border-box !important; @@ -514,20 +510,10 @@ // 缓存命中时直接写 CSS 变量并打开模块开关。 // 这里仍然通过 setVar() 乘倍率,因此缓存中始终保持原始尺寸。 - if (name === "home" && !isFollowingListPage() && isRect(data.homeCard) && isRect(data.homeThumb)) { - moduleReady.home = [ - setVar("--tm-thumb-home-width", data.homeCard.width), - setCardHeightVar("--tm-thumb-home-card-height", data.homeCard.height), - setVar("--tm-thumb-home-thumb-width", data.homeThumb.width), - setVar("--tm-thumb-home-thumb-height", data.homeThumb.height), - ].every(Boolean); - } else if (name === "followingList" && isFollowingListPage() && isRect(data.followingListCard) && isRect(data.followingListThumb)) { - moduleReady.followingList = [ - setVar("--tm-thumb-following-list-width", data.followingListCard.width), - setCardHeightVar("--tm-thumb-following-list-card-height", data.followingListCard.height), - setVar("--tm-thumb-following-list-thumb-width", data.followingListThumb.width), - setVar("--tm-thumb-following-list-thumb-height", data.followingListThumb.height), - ].every(Boolean); + if (name === "home" && !isFollowingListPage() && isRect(data.homeCard)) { + moduleReady.home = setVar("--tm-thumb-home-width", data.homeCard.width); + } else if (name === "followingList" && isFollowingListPage() && isRect(data.followingListCard)) { + moduleReady.followingList = setVar("--tm-thumb-following-list-width", data.followingListCard.width); } else if (name === "related" && isRect(data.relatedCard) && isRect(data.relatedThumb)) { const widthReady = setVar("--tm-thumb-related-width", data.relatedCard.width); const cardHeightReady = setCardHeightVar("--tm-thumb-related-card-height", data.relatedCard.height); @@ -628,12 +614,10 @@ */ const followingListPage = isFollowingListPage(); const measured = { - // 首页普通房间列表:卡片宽高 + 缩略图宽高四项独立探测。 + // 首页普通房间列表:只探测卡片宽度。缩略图跟随卡片自然缩放,避免重复放大。 homeCard: moduleReady.home || followingListPage ? null : firstRect("#roomlist_root li.RoomCard, #roomlist_root li.roomCard"), - homeThumb: moduleReady.home || followingListPage ? null : firstRect("#roomlist_root .RoomCardThumbnail, #roomlist_root .room_thumbnail_container"), - // 关注页房间列表:选择器和首页相似,但独立探测、独立缓存、独立 CSS 变量。 + // 关注页房间列表:只探测卡片宽度;独立缓存,避免和首页混用。 followingListCard: moduleReady.followingList || !followingListPage ? null : firstRect("#roomlist_root li.RoomCard, #roomlist_root li.roomCard"), - followingListThumb: moduleReady.followingList || !followingListPage ? null : firstRect("#roomlist_root .RoomCardThumbnail, #roomlist_root .room_thumbnail_container"), // 频道页“更多这样的房间”:卡片宽高和缩略图宽高都要探测,否则放大后行高容易不齐。 relatedCard: moduleReady.related ? null : firstRect(".BaseRoomContents ul.RoomCardGrid > li.RoomCard, #main.roomPage ul.list:has(li.roomCard) li.roomCard, .BaseRoomContents ul.list:has(li.roomCard) li.roomCard"), relatedThumb: moduleReady.related ? null : firstRect(".BaseRoomContents ul.RoomCardGrid .RoomCardThumbnail, #main.roomPage ul.list:has(li.roomCard) .room_thumbnail_container, .BaseRoomContents ul.list:has(li.roomCard) .room_thumbnail_container"), @@ -655,35 +639,23 @@ }; if (!moduleReady.home && !followingListPage) { - // home 依赖 card/thumb 各自宽高;成功后立刻缓存,后续普通列表页面可直接套用。 - moduleReady.home = [ - setVar("--tm-thumb-home-width", measured.homeCard && measured.homeCard.width), - setCardHeightVar("--tm-thumb-home-card-height", measured.homeCard && measured.homeCard.height), - setVar("--tm-thumb-home-thumb-width", measured.homeThumb && measured.homeThumb.width), - setVar("--tm-thumb-home-thumb-height", measured.homeThumb && measured.homeThumb.height), - ].every(Boolean); + // home 只依赖卡片宽度;成功后立刻缓存,后续普通列表页面可直接套用。 + moduleReady.home = setVar("--tm-thumb-home-width", measured.homeCard && measured.homeCard.width); setModuleReady("home", moduleReady.home); if (moduleReady.home) { updateCacheModule("home", { homeCard: cloneRect(measured.homeCard), - homeThumb: cloneRect(measured.homeThumb), }); } } if (!moduleReady.followingList && followingListPage) { // followingList 单独缓存,避免关注页拿到首页的原始宽度。 - moduleReady.followingList = [ - setVar("--tm-thumb-following-list-width", measured.followingListCard && measured.followingListCard.width), - setCardHeightVar("--tm-thumb-following-list-card-height", measured.followingListCard && measured.followingListCard.height), - setVar("--tm-thumb-following-list-thumb-width", measured.followingListThumb && measured.followingListThumb.width), - setVar("--tm-thumb-following-list-thumb-height", measured.followingListThumb && measured.followingListThumb.height), - ].every(Boolean); + moduleReady.followingList = setVar("--tm-thumb-following-list-width", measured.followingListCard && measured.followingListCard.width); setModuleReady("followingList", moduleReady.followingList); if (moduleReady.followingList) { updateCacheModule("followingList", { followingListCard: cloneRect(measured.followingListCard), - followingListThumb: cloneRect(measured.followingListThumb), }); } } diff --git a/tests/followed-dropdown-css.test.js b/tests/followed-dropdown-css.test.js index a28a660..412140f 100644 --- a/tests/followed-dropdown-css.test.js +++ b/tests/followed-dropdown-css.test.js @@ -89,6 +89,11 @@ assert.match( /data-tm-thumb-scale-following-list="1"[\s\S]*--tm-thumb-following-list-width/, "followed-cams list should be separated from homepage list sizing", ); +assert.match( + capturedCss, + /data-tm-thumb-scale-following-list="1"[\s\S]*grid-template-columns:\s*repeat\(auto-fill,\s*minmax\(var\(--tm-thumb-following-list-width\),\s*1fr\)\)\s*!important/, + "followed-cams list should keep the site's stretching grid alignment while using detected minimum width", +); assert.match( capturedCss, /#main\.roomPage\s+ul\.list:has\(li\.roomCard\)\s+\.room_thumbnail_container[\s\S]*width:\s*var\(--tm-thumb-related-thumb-width\)\s*!important[\s\S]*height:\s*var\(--tm-thumb-related-height\)\s*!important/, @@ -251,8 +256,8 @@ const cacheFakeDocument = { addEventListener() {}, }; const cacheStore = new Map([ - ["tm-thumb-scale:size-cache:v7", JSON.stringify({ - schema: 7, + ["tm-thumb-scale:size-cache:v9", JSON.stringify({ + schema: 9, scale: 2, cardHeightScale: 1.55, modules: { @@ -345,17 +350,15 @@ vm.runInNewContext(source, { localStorage: { getItem() { return JSON.stringify({ - schema: 7, + schema: 9, scale: 2, cardHeightScale: 1.55, modules: { home: { homeCard: { width: 174, height: 120 }, - homeThumb: { width: 174, height: 98 }, }, followingList: { followingListCard: { width: 190, height: 120 }, - followingListThumb: { width: 188, height: 106 }, }, }, }); @@ -382,7 +385,7 @@ vm.runInNewContext(source, { assert.equal(followingAttrs.get("data-tm-thumb-scale-following-list"), "1", "followed-cams should use its own cached list module"); assert.equal(followingAttrs.get("data-tm-thumb-scale-home"), undefined, "followed-cams should not apply homepage cache"); assert.equal(followingVars.get("--tm-thumb-following-list-width"), "380px"); -assert.equal(followingVars.get("--tm-thumb-following-list-card-height"), "186px"); -assert.equal(followingVars.get("--tm-thumb-following-list-thumb-width"), "376px"); -assert.equal(followingVars.get("--tm-thumb-following-list-thumb-height"), "212px"); +assert.equal(followingVars.get("--tm-thumb-following-list-card-height"), undefined); +assert.equal(followingVars.get("--tm-thumb-following-list-thumb-width"), undefined); +assert.equal(followingVars.get("--tm-thumb-following-list-thumb-height"), undefined); assert.equal(followingVars.get("--tm-thumb-home-width"), undefined);