From 6d757857cb6af4255470ddb442138fed9e85675a Mon Sep 17 00:00:00 2001 From: Ajay Date: Sun, 18 Sep 2022 03:15:20 -0400 Subject: [PATCH] Add tooltip about chapters feature --- public/_locales/en/messages.json | 4 ++++ src/background.ts | 3 +++ src/config.ts | 4 ++-- src/content.ts | 40 ++++++++++++++++++++++++++++---- src/render/Tooltip.tsx | 12 ++++++++-- src/utils/licenseKey.ts | 2 ++ 6 files changed, 56 insertions(+), 9 deletions(-) diff --git a/public/_locales/en/messages.json b/public/_locales/en/messages.json index 8863c703..753992e3 100644 --- a/public/_locales/en/messages.json +++ b/public/_locales/en/messages.json @@ -1170,6 +1170,10 @@ "message": "Note: Permission to submit chapters is still based on calculated reputation. Purchasing a license only allows you to view chapters submitted by others", "description": "On the chapters page for getting access to the paid chapters feature" }, + "chapterNewFeature": { + "message": "New Feature: Crowd-sourced custom chapters. These are custom-named sections in videos that can be stacked to get more and more precise. Purchase a license to view the chapters submitted on this video such as: ", + "description": "After the comma, a list of chapters for this video will appear" + }, "unsubmittedSegmentCounts": { "message": "You currently have {0} on {1}", "description": "Example: You currently have 12 unsubmitted segments on 5 videos" diff --git a/src/background.ts b/src/background.ts index 80f0cd8d..3b55743b 100644 --- a/src/background.ts +++ b/src/background.ts @@ -63,6 +63,9 @@ chrome.runtime.onMessage.addListener(function (request, sender, callback) { case "openHelp": chrome.tabs.create({url: chrome.runtime.getURL('help/index.html')}); return; + case "openUpsell": + chrome.tabs.create({url: chrome.runtime.getURL('upsell/index.html')}); + return; case "openPage": chrome.tabs.create({url: chrome.runtime.getURL(request.url)}); return; diff --git a/src/config.ts b/src/config.ts index eda7ed63..73c31200 100644 --- a/src/config.ts +++ b/src/config.ts @@ -62,9 +62,9 @@ interface SBConfig { }, scrollToEditTimeUpdate: boolean, categoryPillUpdate: boolean, + showChapterInfoMessage: boolean, darkMode: boolean, showCategoryGuidelines: boolean, - chaptersAvailable: boolean, showCategoryWithoutPermission: boolean, // Used to cache calculated text color info @@ -193,9 +193,9 @@ const Config: SBObject = { autoSkipOnMusicVideos: false, scrollToEditTimeUpdate: false, // false means the tooltip will be shown categoryPillUpdate: false, + showChapterInfoMessage: true, darkMode: true, showCategoryGuidelines: true, - chaptersAvailable: true, showCategoryWithoutPermission: false, categoryPillColors: {}, diff --git a/src/content.ts b/src/content.ts index 3ceab508..8c431124 100644 --- a/src/content.ts +++ b/src/content.ts @@ -37,6 +37,8 @@ import { logDebug } from "./utils/logger"; import { importTimes } from "./utils/exporter"; import { ChapterVote } from "./render/ChapterVote"; import { openWarningDialog } from "./utils/warnings"; +import { Tooltip } from "./render/Tooltip"; +import { noRefreshFetchingChaptersAllowed } from "./utils/licenseKey"; const utils = new Utils(); @@ -941,8 +943,14 @@ async function sponsorsLookup(keepOldSubmissions = true) { setupVideoMutationListener(); - // Create categories list + const showChapterMessage = Config.config.payments.lastCheck !== 0 + && !noRefreshFetchingChaptersAllowed() + && Config.config.showChapterInfoMessage + && Config.config.skipCount > 200 + && Math.random() > 0.8; + const categories: string[] = Config.config.categorySelections.map((category) => category.name); + if (showChapterMessage && !categories.includes("chapter")) categories.push("chapter"); const extraRequestData: Record = {}; const hashParams = getHashParams(); @@ -951,7 +959,7 @@ async function sponsorsLookup(keepOldSubmissions = true) { const hashPrefix = (await utils.getHash(sponsorVideoID, 1)).slice(0, 4) as VideoID & HashedValue; const response = await utils.asyncRequestToServer('GET', "/api/skipSegments/" + hashPrefix, { categories, - actionTypes: getEnabledActionTypes(), + actionTypes: getEnabledActionTypes(showChapterMessage), userAgent: `${chrome.runtime.id}`, ...extraRequestData }); @@ -960,7 +968,7 @@ async function sponsorsLookup(keepOldSubmissions = true) { lastResponseStatus = response?.status; if (response?.ok) { - const recievedSegments: SponsorTime[] = JSON.parse(response.responseText) + let recievedSegments: SponsorTime[] = JSON.parse(response.responseText) ?.filter((video) => video.videoID === sponsorVideoID) ?.map((video) => video.segments)?.[0] ?.map((segment) => ({ @@ -974,6 +982,28 @@ async function sponsorsLookup(keepOldSubmissions = true) { return; } + if (showChapterMessage) { + const chapterSegments = recievedSegments.filter((s) => s.actionType === ActionType.Chapter); + if (chapterSegments.length > 3) { + const prependElement = document.querySelector(".ytp-chrome-bottom") as HTMLElement; + if (prependElement) { + Config.config.showChapterInfoMessage = false; + new Tooltip({ + text: `🟨${chrome.i18n.getMessage("chapterNewFeature")}${chapterSegments.slice(0, 3).map((s) => s.description).join(", ")}`, + linkOnClick: () => void chrome.runtime.sendMessage({ "message": "openUpsell" }), + referenceNode: prependElement.parentElement, + prependElement, + timeout: 1500, + leftOffset: "20px", + positionRealtive: false + }); + } + + } + + recievedSegments = recievedSegments.filter((s) => s.actionType !== ActionType.Chapter); + } + sponsorDataFound = true; // Check if any old submissions should be kept @@ -1056,12 +1086,12 @@ function importExistingChapters(wait: boolean) { } } -function getEnabledActionTypes(): ActionType[] { +function getEnabledActionTypes(forceFullVideo = false): ActionType[] { const actionTypes = [ActionType.Skip, ActionType.Poi, ActionType.Chapter]; if (Config.config.muteSegments) { actionTypes.push(ActionType.Mute); } - if (Config.config.fullVideoSegments) { + if (Config.config.fullVideoSegments || forceFullVideo) { actionTypes.push(ActionType.Full); } diff --git a/src/render/Tooltip.tsx b/src/render/Tooltip.tsx index d59728fe..dd9a26cc 100644 --- a/src/render/Tooltip.tsx +++ b/src/render/Tooltip.tsx @@ -5,6 +5,7 @@ import { ButtonListener } from "../types"; export interface TooltipProps { text?: string; link?: string; + linkOnClick?: () => void; referenceNode: HTMLElement; prependElement?: HTMLElement; // Element to append before bottomOffset?: string; @@ -16,6 +17,7 @@ export interface TooltipProps { extraClass?: string; showLogo?: boolean; showGotIt?: boolean; + positionRealtive?: boolean; buttons?: ButtonListener[]; } @@ -34,11 +36,12 @@ export class Tooltip { props.extraClass ??= ""; props.showLogo ??= true; props.showGotIt ??= true; + props.positionRealtive ??= true; this.text = props.text; this.container = document.createElement('div'); this.container.id = "sponsorTooltip" + props.text; - this.container.style.position = "relative"; + if (props.positionRealtive) this.container.style.position = "relative"; if (props.prependElement) { props.referenceNode.insertBefore(this.container, props.prependElement); @@ -71,7 +74,12 @@ export class Tooltip { href={props.link}> {chrome.i18n.getMessage("LearnMore")} - : null} + : (props.linkOnClick ? + + {chrome.i18n.getMessage("LearnMore")} + + : null)} : null} diff --git a/src/utils/licenseKey.ts b/src/utils/licenseKey.ts index c93e7636..02a328ff 100644 --- a/src/utils/licenseKey.ts +++ b/src/utils/licenseKey.ts @@ -12,6 +12,7 @@ export async function checkLicenseKey(licenseKey: string): Promise { try { if (result.ok && JSON.parse(result.responseText).allowed) { Config.config.payments.chaptersAllowed = true; + Config.config.showChapterInfoMessage = false; Config.config.payments.lastCheck = Date.now(); Config.forceSyncUpdate("payments"); @@ -60,6 +61,7 @@ export async function fetchingChaptersAllowed(): Promise { if (userInfo.freeChaptersAccess) { Config.config.payments.freeAccess = true; Config.config.payments.chaptersAllowed = true; + Config.config.showChapterInfoMessage = false; Config.forceSyncUpdate("payments"); return true;