Questify: Make ignored quests less likely to be overwritten when switching accounts. (#332)
* Switch to IDs and remove public facing setting. * Allow claimed to be ignored to prevent account switching from overwriting it. * Fix unclaimed counting & context option. * Fix array undefined check. * Fix mark all ignored. * Technically allow ignoring claimed quests. * Technically allow ignoring expired quests. * Prepare a setting for picking shared or private ignores. * Implement ignore profile. * Restructure settings.
This commit is contained in:
parent
6f8e93d128
commit
e3a7d7fbbf
4 changed files with 170 additions and 142 deletions
|
|
@ -14,31 +14,39 @@ import definePlugin, { StartAt } from "@utils/types";
|
|||
import { ContextMenuApi, Menu, NavigationRouter } from "@webpack/common";
|
||||
import { JSX } from "react";
|
||||
|
||||
import { addIgnoredQuest, autoFetchCompatible, fetchAndAlertQuests, maximumAutoFetchIntervalValue, minimumAutoFetchIntervalValue, removeIgnoredQuest, rerenderQuests, settings, startAutoFetchingQuests, stopAutoFetchingQuests, validateAndOverwriteIgnoredQuests } from "./settings";
|
||||
import { GuildlessServerListItem, Quest, QuestIcon, QuestMap, QuestStatus, RGB } from "./utils/components";
|
||||
import { adjustRGB, decimalToRGB, fetchAndDispatchQuests, formatLowerBadge, getFormattedNow, getQuestStatus, isDarkish, leftClick, middleClick, normalizeQuestName, q, QuestifyLogger, questPath, QuestsStore, refreshQuest, reportPlayGameQuestProgress, reportVideoQuestProgress, rightClick, waitUntilEnrolled } from "./utils/misc";
|
||||
import { addIgnoredQuest, autoFetchCompatible, fetchAndAlertQuests, maximumAutoFetchIntervalValue, minimumAutoFetchIntervalValue, questIsIgnored, removeIgnoredQuest, rerenderQuests, settings, startAutoFetchingQuests, stopAutoFetchingQuests, validateAndOverwriteIgnoredQuests } from "./settings";
|
||||
import { ExcludedQuestMap, GuildlessServerListItem, Quest, QuestIcon, QuestMap, QuestStatus, RGB } from "./utils/components";
|
||||
import { adjustRGB, decimalToRGB, fetchAndDispatchQuests, formatLowerBadge, getFormattedNow, getIgnoredQuestIDs, getQuestStatus, isDarkish, leftClick, middleClick, normalizeQuestName, q, QuestifyLogger, questPath, QuestsStore, refreshQuest, reportPlayGameQuestProgress, reportVideoQuestProgress, rightClick, setIgnoredQuestIDs, waitUntilEnrolled } from "./utils/misc";
|
||||
|
||||
const patchedMobileQuests = new Set<string>();
|
||||
export const activeQuestIntervals = new Map<string, { progressTimeout: NodeJS.Timeout; rerenderTimeout: NodeJS.Timeout; progress: number; duration: number, type: string; }>();
|
||||
|
||||
function questMenuUnignoreClicked(): void {
|
||||
validateAndOverwriteIgnoredQuests("");
|
||||
function questMenuUnignoreAllClicked(): void {
|
||||
validateAndOverwriteIgnoredQuests([]);
|
||||
}
|
||||
|
||||
function questMenuIgnoreClicked(): void {
|
||||
function questMenuIgnoreAllClicked(): void {
|
||||
const quests = (QuestsStore.quests as QuestMap);
|
||||
const ignoredQuestsSet = new Set();
|
||||
const excludedQuests = (QuestsStore.excludedQuests as ExcludedQuestMap);
|
||||
const ignoredQuestsSet = new Set<string>();
|
||||
const ignoredQuestIDs = getIgnoredQuestIDs();
|
||||
|
||||
for (const quest of quests.values()) {
|
||||
const questName = normalizeQuestName(quest.config.messages.questName);
|
||||
const questID = quest.id;
|
||||
const questStatus = getQuestStatus(quest, false);
|
||||
|
||||
if (questStatus === QuestStatus.Unclaimed) {
|
||||
ignoredQuestsSet.add(questName);
|
||||
if (questStatus === QuestStatus.Unclaimed || ignoredQuestIDs.includes(questID)) {
|
||||
ignoredQuestsSet.add(questID);
|
||||
}
|
||||
}
|
||||
|
||||
settings.store.ignoredQuests = Array.from(ignoredQuestsSet).join("\n");
|
||||
for (const quest of excludedQuests.values()) {
|
||||
if (ignoredQuestIDs.includes(quest.id)) {
|
||||
ignoredQuestsSet.add(quest.id);
|
||||
}
|
||||
}
|
||||
|
||||
setIgnoredQuestIDs(Array.from(ignoredQuestsSet));
|
||||
settings.store.unclaimedUnignoredQuests = 0;
|
||||
}
|
||||
|
||||
|
|
@ -86,14 +94,14 @@ export function QuestButton(): JSX.Element {
|
|||
<Menu.MenuItem
|
||||
id={q("ignore-quests-option")}
|
||||
label="Mark All Ignored"
|
||||
action={questMenuIgnoreClicked}
|
||||
action={questMenuIgnoreAllClicked}
|
||||
disabled={!unclaimedUnignoredQuests}
|
||||
/>
|
||||
<Menu.MenuItem
|
||||
id={q("unignore-quests-option")}
|
||||
label="Reset Ignored List"
|
||||
action={questMenuUnignoreClicked}
|
||||
disabled={!settings.store.ignoredQuests}
|
||||
action={questMenuUnignoreAllClicked}
|
||||
disabled={!getIgnoredQuestIDs().length}
|
||||
/>
|
||||
<Menu.MenuItem
|
||||
id={q("fetch-quests-option")}
|
||||
|
|
@ -198,10 +206,10 @@ function shouldHideFriendsListActiveNowPromotion(): boolean {
|
|||
}
|
||||
|
||||
function shouldDisableQuestTileOptions(quest: Quest, shouldBeIgnored: boolean): boolean {
|
||||
const questStatus = getQuestStatus(quest);
|
||||
const isIgnored = questIsIgnored(quest.id);
|
||||
|
||||
return !(
|
||||
(shouldBeIgnored ? questStatus === QuestStatus.Ignored : questStatus === QuestStatus.Unclaimed)
|
||||
(shouldBeIgnored ? isIgnored : !isIgnored)
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -212,13 +220,13 @@ function QuestTileContextMenu(children: React.ReactNode[], props: { quest: any;
|
|||
id={q("ignore-quests")}
|
||||
label="Mark as Ignored"
|
||||
disabled={shouldDisableQuestTileOptions(props.quest, false)}
|
||||
action={() => { addIgnoredQuest(props.quest.config.messages.questName); }}
|
||||
action={() => { addIgnoredQuest(props.quest.id); }}
|
||||
/>
|
||||
<Menu.MenuItem
|
||||
id={q("unignore-quests")}
|
||||
label="Unmark as Ignored"
|
||||
disabled={shouldDisableQuestTileOptions(props.quest, true)}
|
||||
action={() => { removeIgnoredQuest(props.quest.config.messages.questName); }}
|
||||
action={() => { removeIgnoredQuest(props.quest.id); }}
|
||||
/>
|
||||
{activeQuestIntervals.has(props.quest.id) &&
|
||||
<Menu.MenuItem
|
||||
|
|
@ -242,19 +250,21 @@ function QuestTileContextMenu(children: React.ReactNode[], props: { quest: any;
|
|||
|
||||
export function getQuestTileClasses(originalClasses: string, quest: Quest, color: number | null | undefined, gradient: string | undefined): string {
|
||||
const {
|
||||
ignoredQuestIDs,
|
||||
ignoredQuestProfile,
|
||||
restyleQuestsUnclaimed,
|
||||
restyleQuestsClaimed,
|
||||
restyleQuestsIgnored,
|
||||
restyleQuestsExpired,
|
||||
restyleQuestsGradient,
|
||||
ignoredQuests
|
||||
restyleQuestsGradient
|
||||
} = settings.use([
|
||||
"ignoredQuestIDs",
|
||||
"ignoredQuestProfile",
|
||||
"restyleQuestsUnclaimed",
|
||||
"restyleQuestsClaimed",
|
||||
"restyleQuestsIgnored",
|
||||
"restyleQuestsExpired",
|
||||
"restyleQuestsGradient",
|
||||
"ignoredQuests"
|
||||
"restyleQuestsGradient"
|
||||
]);
|
||||
|
||||
const customClasses = [
|
||||
|
|
@ -284,12 +294,12 @@ export function getQuestTileClasses(originalClasses: string, quest: Quest, color
|
|||
} else if (questStatus === QuestStatus.Unclaimed && (color || restyleQuestsUnclaimed !== null)) {
|
||||
returnClasses.push(q("quest-item-restyle"));
|
||||
isRestyledAndDarkish = isDarkish(decimalToRGB(color ?? restyleQuestsUnclaimed), 0.875);
|
||||
} else if (questStatus === QuestStatus.Ignored && (color || restyleQuestsIgnored !== null)) {
|
||||
returnClasses.push(q("quest-item-restyle"));
|
||||
isRestyledAndDarkish = isDarkish(decimalToRGB(color ?? restyleQuestsIgnored), 0.875);
|
||||
} else if (questStatus === QuestStatus.Expired && (color || restyleQuestsExpired !== null)) {
|
||||
returnClasses.push(q("quest-item-restyle"));
|
||||
isRestyledAndDarkish = isDarkish(decimalToRGB(color ?? restyleQuestsExpired), 0.875);
|
||||
} else if (questStatus === QuestStatus.Ignored && (color || restyleQuestsIgnored !== null)) {
|
||||
returnClasses.push(q("quest-item-restyle"));
|
||||
isRestyledAndDarkish = isDarkish(decimalToRGB(color ?? restyleQuestsIgnored), 0.875);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -316,7 +326,8 @@ export function getQuestTileClasses(originalClasses: string, quest: Quest, color
|
|||
|
||||
function preprocessQuests(quests: Quest[]): Quest[] {
|
||||
const {
|
||||
ignoredQuests,
|
||||
ignoredQuestIDs,
|
||||
ignoredQuestProfile,
|
||||
reorderQuests,
|
||||
unclaimedSubsort,
|
||||
claimedSubsort,
|
||||
|
|
@ -327,7 +338,8 @@ function preprocessQuests(quests: Quest[]): Quest[] {
|
|||
completeGameQuestsInBackground,
|
||||
triggerQuestsRerender
|
||||
} = settings.use([
|
||||
"ignoredQuests",
|
||||
"ignoredQuestIDs",
|
||||
"ignoredQuestProfile",
|
||||
"reorderQuests",
|
||||
"unclaimedSubsort",
|
||||
"claimedSubsort",
|
||||
|
|
@ -387,10 +399,10 @@ function preprocessQuests(quests: Quest[]): Quest[] {
|
|||
questGroups.claimed.push(quest);
|
||||
} else if (questStatus === QuestStatus.Unclaimed) {
|
||||
questGroups.unclaimed.push(quest);
|
||||
} else if (questStatus === QuestStatus.Ignored) {
|
||||
questGroups.ignored.push(quest);
|
||||
} else if (questStatus === QuestStatus.Expired) {
|
||||
questGroups.expired.push(quest);
|
||||
} else if (questStatus === QuestStatus.Ignored) {
|
||||
questGroups.ignored.push(quest);
|
||||
} else {
|
||||
questGroups.unknown.push(quest);
|
||||
}
|
||||
|
|
@ -453,10 +465,12 @@ function preprocessQuests(quests: Quest[]): Quest[] {
|
|||
export function getQuestTileStyle(quest: Quest | null): Record<string, string> {
|
||||
const {
|
||||
restyleQuests,
|
||||
ignoredQuests,
|
||||
ignoredQuestIDs,
|
||||
ignoredQuestProfile
|
||||
} = settings.use([
|
||||
"restyleQuests",
|
||||
"ignoredQuests",
|
||||
"ignoredQuestIDs",
|
||||
"ignoredQuestProfile"
|
||||
]);
|
||||
|
||||
const style: Record<string, string> = {};
|
||||
|
|
@ -479,10 +493,10 @@ export function getQuestTileStyle(quest: Quest | null): Record<string, string> {
|
|||
themeColor = dummyProvided ? dummyColor : claimedColor || null;
|
||||
} else if (questStatus === QuestStatus.Unclaimed) {
|
||||
themeColor = dummyProvided ? dummyColor : unclaimedColor || null;
|
||||
} else if (questStatus === QuestStatus.Ignored) {
|
||||
themeColor = dummyProvided ? dummyColor : ignoredColor || null;
|
||||
} else if (questStatus === QuestStatus.Expired) {
|
||||
themeColor = dummyProvided ? dummyColor : expiredColor || null;
|
||||
} else if (questStatus === QuestStatus.Ignored) {
|
||||
themeColor = dummyProvided ? dummyColor : ignoredColor || null;
|
||||
}
|
||||
|
||||
if (!themeColor) return style;
|
||||
|
|
|
|||
|
|
@ -9,12 +9,12 @@ import { ErrorBoundary } from "@components/index";
|
|||
import { Logger } from "@utils/Logger";
|
||||
import { OptionType } from "@utils/types";
|
||||
import { findLazy } from "@webpack";
|
||||
import { Button, ColorPicker, ContextMenuApi, Forms, Menu, Select, TextArea, TextInput, useEffect, useRef, useState } from "@webpack/common";
|
||||
import { Button, ColorPicker, ContextMenuApi, Forms, Menu, Select, TextInput, useEffect, useRef, useState } from "@webpack/common";
|
||||
import { JSX } from "react";
|
||||
|
||||
import { activeQuestIntervals, getQuestTileClasses, getQuestTileStyle } from "./index";
|
||||
import { DynamicDropdown, DynamicDropdownSettingOption, GuildlessServerListItem, Quest, QuestIcon, QuestStatus, QuestTile, RadioGroup, RadioOption, SelectOption, SoundIcon } from "./utils/components";
|
||||
import { AudioPlayer, decimalToRGB, fetchAndDispatchQuests, getFormattedNow, getQuestStatus, isDarkish, isSoundAllowed, leftClick, middleClick, normalizeQuestName, q, QuestifyLogger, QuestsStore, rightClick, validCommaSeparatedList } from "./utils/misc";
|
||||
import { DynamicDropdown, DynamicDropdownSettingOption, ExcludedQuest, GuildlessServerListItem, Quest, QuestIcon, QuestStatus, QuestTile, RadioGroup, RadioOption, SelectOption, SoundIcon } from "./utils/components";
|
||||
import { AudioPlayer, decimalToRGB, fetchAndDispatchQuests, getFormattedNow, getIgnoredQuestIDs, getQuestStatus, isDarkish, isSoundAllowed, leftClick, middleClick, q, QuestifyLogger, QuestsStore, rightClick, setIgnoredQuestIDs, validCommaSeparatedList } from "./utils/misc";
|
||||
|
||||
let defaultSounds: string[] | null = null;
|
||||
let autoFetchInterval: null | ReturnType<typeof setInterval> = null;
|
||||
|
|
@ -129,49 +129,54 @@ export const intervalScales = {
|
|||
}
|
||||
};
|
||||
|
||||
export function removeIgnoredQuest(questName: string): void {
|
||||
const ignoredQuests = settings.store.ignoredQuests.split("\n");
|
||||
validateAndOverwriteIgnoredQuests(ignoredQuests.filter(name => normalizeQuestName(name) !== normalizeQuestName(questName)).join("\n"));
|
||||
export function removeIgnoredQuest(questID: string): void {
|
||||
const ignoredQuests = getIgnoredQuestIDs();
|
||||
const newIgnoredQuests = ignoredQuests.filter(id => id !== questID);
|
||||
validateAndOverwriteIgnoredQuests(newIgnoredQuests);
|
||||
}
|
||||
|
||||
export function addIgnoredQuest(questName: string): void {
|
||||
const { ignoredQuests } = settings.store;
|
||||
validateAndOverwriteIgnoredQuests(ignoredQuests + "\n" + normalizeQuestName(questName));
|
||||
export function addIgnoredQuest(questID: string): void {
|
||||
const ignoredQuests = getIgnoredQuestIDs();
|
||||
const newIgnoredQuests = ignoredQuests.concat(questID);
|
||||
validateAndOverwriteIgnoredQuests(newIgnoredQuests);
|
||||
}
|
||||
|
||||
export function questIsIgnored(questName: string): boolean {
|
||||
const ignoredQuests = new Set(settings.store.ignoredQuests.split("\n").map(normalizeQuestName));
|
||||
return ignoredQuests.has(normalizeQuestName(questName));
|
||||
export function questIsIgnored(questID: string): boolean {
|
||||
const ignoredQuests = getIgnoredQuestIDs();
|
||||
return ignoredQuests.includes(questID);
|
||||
}
|
||||
|
||||
export function validateIgnoredQuests(ignoredQuests?: string, questsData?: Quest[]): [string, number] {
|
||||
export function validateIgnoredQuests(ignoredQuests?: string[], questsData?: Quest[]): [string[], number] {
|
||||
const quests = questsData ?? Array.from(QuestsStore.quests.values()) as Quest[];
|
||||
const currentlyIgnored = new Set((ignoredQuests ?? settings.store.ignoredQuests).split("\n").map(normalizeQuestName));
|
||||
const excludedQuests = Array.from(QuestsStore.excludedQuests.values()) as ExcludedQuest[];
|
||||
const currentlyIgnored = ignoredQuests ? new Set(ignoredQuests) : new Set(getIgnoredQuestIDs());
|
||||
const validIgnored = new Set<string>();
|
||||
let numUnclaimedUnignoredQuests = 0;
|
||||
|
||||
for (const quest of quests) {
|
||||
const questStatus = getQuestStatus(quest, false);
|
||||
const normalizedName = normalizeQuestName(quest.config.messages.questName);
|
||||
|
||||
if (questStatus === QuestStatus.Unclaimed) {
|
||||
if (currentlyIgnored.has(normalizedName)) {
|
||||
validIgnored.add(normalizedName);
|
||||
} else {
|
||||
numUnclaimedUnignoredQuests++;
|
||||
}
|
||||
if (currentlyIgnored.has(quest.id)) {
|
||||
validIgnored.add(quest.id);
|
||||
} else if (questStatus === QuestStatus.Unclaimed) {
|
||||
numUnclaimedUnignoredQuests++;
|
||||
}
|
||||
}
|
||||
|
||||
const ignoredStr = Array.from(validIgnored).join("\n");
|
||||
return [ignoredStr, numUnclaimedUnignoredQuests];
|
||||
for (const quest of excludedQuests) {
|
||||
if (currentlyIgnored.has(quest.id)) {
|
||||
validIgnored.add(quest.id);
|
||||
}
|
||||
}
|
||||
|
||||
return [Array.from(validIgnored), numUnclaimedUnignoredQuests];
|
||||
}
|
||||
|
||||
export function validateAndOverwriteIgnoredQuests(ignoredQuests?: string, questsData?: Quest[]): string {
|
||||
const [ignoredStr, numUnclaimedUnignoredQuests] = validateIgnoredQuests(ignoredQuests, questsData);
|
||||
export function validateAndOverwriteIgnoredQuests(ignoredQuests?: string[], questsData?: Quest[]): string[] {
|
||||
const [validIgnored, numUnclaimedUnignoredQuests] = validateIgnoredQuests(ignoredQuests, questsData);
|
||||
settings.store.unclaimedUnignoredQuests = numUnclaimedUnignoredQuests;
|
||||
settings.store.ignoredQuests = ignoredStr;
|
||||
return ignoredStr;
|
||||
setIgnoredQuestIDs(validIgnored);
|
||||
return validIgnored;
|
||||
}
|
||||
|
||||
interface DummyQuestButtonProps {
|
||||
|
|
@ -689,48 +694,6 @@ function DisableQuestsSetting(): JSX.Element {
|
|||
);
|
||||
}
|
||||
|
||||
function IgnoredQuestsSetting(): JSX.Element {
|
||||
const [ignoredQuests, setIgnoredQuests] = useState(settings.store.ignoredQuests);
|
||||
validateAndOverwriteIgnoredQuests(ignoredQuests);
|
||||
|
||||
return (
|
||||
<ErrorBoundary>
|
||||
<Forms.FormDivider className={q("setting-divider")} />
|
||||
<div className={q("setting", "ignored-quests-setting")}>
|
||||
<Forms.FormSection>
|
||||
<div>
|
||||
<Forms.FormTitle className={q("form-title")}>
|
||||
Ignored Quests
|
||||
</Forms.FormTitle>
|
||||
<Forms.FormText className={q("form-description")}>
|
||||
A list of Quest names to exclude from the <span className={q("inline-code-block")}>Unclaimed Indicator</span>.
|
||||
<br /><br />
|
||||
One Quest name per line. Names must match the spelling displayed on the Quests page.
|
||||
Alternatively, click the three dots on a Quest tile and select the <span className={q("inline-code-block")}>Mark as Ignored</span> option.
|
||||
</Forms.FormText>
|
||||
</div>
|
||||
<div>
|
||||
<TextArea
|
||||
className={q("text-area")}
|
||||
value={ignoredQuests}
|
||||
onChange={newValue => {
|
||||
setIgnoredQuests(newValue);
|
||||
const [validated, badgeNum] = validateIgnoredQuests(newValue);
|
||||
|
||||
if (validated.trim() === newValue.trim()) {
|
||||
settings.store.ignoredQuests = validated;
|
||||
settings.store.unclaimedUnignoredQuests = badgeNum;
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</Forms.FormSection>
|
||||
</div>
|
||||
<Forms.FormDivider className={q("setting-divider")} />
|
||||
</ErrorBoundary>
|
||||
);
|
||||
}
|
||||
|
||||
const DummyQuestPreview = ({ quest, dummyColor, dummyGradient }: { quest: Quest; dummyColor: number | null; dummyGradient: string; }) => {
|
||||
const classes = getQuestTileClasses("", quest, dummyColor, dummyGradient);
|
||||
|
||||
|
|
@ -749,14 +712,16 @@ function RestyleQuestsSetting() {
|
|||
restyleQuestsIgnored,
|
||||
restyleQuestsExpired,
|
||||
restyleQuestsGradient,
|
||||
restyleQuestsPreload
|
||||
restyleQuestsPreload,
|
||||
ignoredQuestProfile
|
||||
} = settings.use([
|
||||
"restyleQuestsUnclaimed",
|
||||
"restyleQuestsClaimed",
|
||||
"restyleQuestsIgnored",
|
||||
"restyleQuestsExpired",
|
||||
"restyleQuestsGradient",
|
||||
"restyleQuestsPreload"
|
||||
"restyleQuestsPreload",
|
||||
"ignoredQuestProfile"
|
||||
]);
|
||||
|
||||
const [unclaimedColor, setUnclaimedColor] = useState<number | null>(restyleQuestsUnclaimed);
|
||||
|
|
@ -874,8 +839,58 @@ function RestyleQuestsSetting() {
|
|||
</Forms.FormTitle>
|
||||
<Forms.FormText className={q("form-description")}>
|
||||
Highlight Quests with optional theme colors for visibility.
|
||||
<br /><br />
|
||||
Claimed and Expired Quest styles will take precedence even if a Quest is ignored.
|
||||
</Forms.FormText>
|
||||
</div>
|
||||
<div className={q("main-inline-group")}>
|
||||
<div className={q("gradient-setting-group", "inline-group-item", "flex-35")}>
|
||||
<Forms.FormTitle className={q("form-subtitle")}>
|
||||
Gradient Style
|
||||
</Forms.FormTitle>
|
||||
<Select
|
||||
options={gradientOptions}
|
||||
className={q("select")}
|
||||
popoutPosition="top"
|
||||
serialize={String}
|
||||
isSelected={(value: string) => value === restyleQuestsGradientValue}
|
||||
select={handleGradientChange}
|
||||
/>
|
||||
</div>
|
||||
<div className={q("preload-setting-group", "inline-group-item", "flex-65")}>
|
||||
<Forms.FormTitle className={q("form-subtitle")}>
|
||||
Asset Preload
|
||||
</Forms.FormTitle>
|
||||
<Select
|
||||
options={preloadOptions}
|
||||
className={q("select")}
|
||||
popoutPosition="top"
|
||||
serialize={String}
|
||||
isSelected={(value: boolean) => value === restyleQuestsPreloadValue}
|
||||
select={handlePreloadChange}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className={q("main-inline-group")}>
|
||||
<div className={q("inline-group-item")}>
|
||||
<Forms.FormTitle className={q("form-subtitle")}>
|
||||
Ignored Quest Profile
|
||||
</Forms.FormTitle>
|
||||
<Select
|
||||
options={[
|
||||
{ label: "Shared: All accounts on this client share ignores.", value: "shared" },
|
||||
{ label: "Private: All accounts on this client have separate ignores.", value: "private" }
|
||||
]}
|
||||
className={q("select")}
|
||||
popoutPosition="bottom"
|
||||
serialize={String}
|
||||
isSelected={(value: string) => value === ignoredQuestProfile}
|
||||
select={(value: string) => {
|
||||
settings.store.ignoredQuestProfile = value;
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className={q("color-picker-container")}>
|
||||
{colorPickers.map(({ label, idx, defaultValue, value }) => (
|
||||
<div
|
||||
|
|
@ -909,34 +924,6 @@ function RestyleQuestsSetting() {
|
|||
</div>
|
||||
))}
|
||||
</div>
|
||||
<div className={q("main-inline-group")}>
|
||||
<div className={q("gradient-setting-group", "inline-group-item", "flex-35")}>
|
||||
<Forms.FormTitle className={q("form-subtitle")}>
|
||||
Gradient Style
|
||||
</Forms.FormTitle>
|
||||
<Select
|
||||
options={gradientOptions}
|
||||
className={q("select")}
|
||||
popoutPosition="top"
|
||||
serialize={String}
|
||||
isSelected={(value: string) => value === restyleQuestsGradientValue}
|
||||
select={handleGradientChange}
|
||||
/>
|
||||
</div>
|
||||
<div className={q("preload-setting-group", "inline-group-item", "flex-65")}>
|
||||
<Forms.FormTitle className={q("form-subtitle")}>
|
||||
Asset Preload
|
||||
</Forms.FormTitle>
|
||||
<Select
|
||||
options={preloadOptions}
|
||||
className={q("select")}
|
||||
popoutPosition="top"
|
||||
serialize={String}
|
||||
isSelected={(value: boolean) => value === restyleQuestsPreloadValue}
|
||||
select={handlePreloadChange}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className={q("dummy-quest-preview")} style={dummyQuestStyle}>
|
||||
{hasQuests && dummyQuest && (
|
||||
<DummyQuestPreview quest={dummyQuest} dummyColor={dummyColor} dummyGradient={dummyGradient} />
|
||||
|
|
@ -1644,11 +1631,6 @@ export const settings = definePluginSettings({
|
|||
default: "Expiring DESC", // "Recent ASC", "Recent DESC", "Expiring ASC", "Expiring DESC"
|
||||
hidden: true
|
||||
},
|
||||
ignoredQuests: {
|
||||
type: OptionType.COMPONENT,
|
||||
default: "",
|
||||
component: IgnoredQuestsSetting
|
||||
},
|
||||
unclaimedUnignoredQuests: {
|
||||
type: OptionType.NUMBER,
|
||||
description: "Tracks the number of unclaimed and unignored Quests.",
|
||||
|
|
@ -1667,4 +1649,16 @@ export const settings = definePluginSettings({
|
|||
default: false,
|
||||
hidden: true
|
||||
},
|
||||
ignoredQuestProfile: {
|
||||
type: OptionType.STRING,
|
||||
description: "The profile used for ignored Quests.",
|
||||
default: "private", // "shared", "private"
|
||||
hidden: true
|
||||
},
|
||||
ignoredQuestIDs: {
|
||||
type: OptionType.CUSTOM,
|
||||
description: "An array of Quest IDs that are ignored.",
|
||||
default: {} as Record<string, string[]>,
|
||||
hidden: true,
|
||||
}
|
||||
});
|
||||
|
|
|
|||
|
|
@ -55,8 +55,14 @@ export interface RGB {
|
|||
b: number;
|
||||
}
|
||||
|
||||
export type ExcludedQuestMap = Map<string, ExcludedQuest>;
|
||||
|
||||
export type QuestMap = Map<string, Quest>;
|
||||
|
||||
export interface ExcludedQuest {
|
||||
id: string;
|
||||
}
|
||||
|
||||
export interface Quest {
|
||||
questifyNumber: number;
|
||||
id: string;
|
||||
|
|
|
|||
|
|
@ -7,9 +7,9 @@
|
|||
import { classNameFactory } from "@api/Styles";
|
||||
import { Logger } from "@utils/Logger";
|
||||
import { findByCodeLazy, findStoreLazy } from "@webpack";
|
||||
import { FluxDispatcher, RestAPI } from "@webpack/common";
|
||||
import { FluxDispatcher, RestAPI, UserStore } from "@webpack/common";
|
||||
|
||||
import { questIsIgnored } from "../settings";
|
||||
import { questIsIgnored, settings } from "../settings";
|
||||
import { Quest, QuestStatus, RGB } from "./components";
|
||||
|
||||
export const q = classNameFactory("questify-");
|
||||
|
|
@ -25,16 +25,30 @@ export const leftClick = 0;
|
|||
export const middleClick = 1;
|
||||
export const rightClick = 2;
|
||||
|
||||
export function setIgnoredQuestIDs(questIDs: string[]): void {
|
||||
const currentUserID = UserStore.getCurrentUser().id;
|
||||
const { ignoredQuestProfile } = settings.store;
|
||||
const key = ignoredQuestProfile === "shared" ? "shared" : currentUserID;
|
||||
settings.store.ignoredQuestIDs[key] = questIDs;
|
||||
}
|
||||
|
||||
export function getIgnoredQuestIDs(): string[] {
|
||||
const currentUserID = UserStore.getCurrentUser().id;
|
||||
const { ignoredQuestIDs, ignoredQuestProfile } = settings.store;
|
||||
const key = ignoredQuestProfile === "shared" ? "shared" : currentUserID;
|
||||
ignoredQuestIDs[key] ??= [];
|
||||
return ignoredQuestIDs[key];
|
||||
}
|
||||
|
||||
export function getQuestStatus(quest: Quest, checkIgnored: boolean = true): QuestStatus {
|
||||
const questName = normalizeQuestName(quest.config.messages.questName);
|
||||
const completedQuest = quest.userStatus?.completedAt;
|
||||
const claimedQuest = quest.userStatus?.claimedAt;
|
||||
const expiredQuest = new Date(quest.config.expiresAt) < new Date();
|
||||
const questIgnored = questIsIgnored(questName);
|
||||
const questIgnored = questIsIgnored(quest.id);
|
||||
|
||||
if (claimedQuest) {
|
||||
return QuestStatus.Claimed;
|
||||
} else if (checkIgnored && questIgnored) {
|
||||
} else if (checkIgnored && questIgnored && (!expiredQuest || completedQuest)) {
|
||||
return QuestStatus.Ignored;
|
||||
} else if (completedQuest || !expiredQuest) {
|
||||
return QuestStatus.Unclaimed;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue