Improve some things. (#355)

This commit is contained in:
Etorix 2025-08-21 11:02:43 -07:00 • committed by GitHub
parent 0165d01ed0
commit 382153f9ed
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 64 additions and 47 deletions

View file

@ -430,7 +430,7 @@ function preprocessQuests(quests: Quest[]): Quest[] {
const unclaimedSortFunction = createSortFunction(unclaimedSubsort || "Recent DESC");
// Divide unclaimed quests by completion status before applying subsort.
// Divide unclaimed Quests by completion status before applying subsort.
questGroups.unclaimed.sort((a: Quest, b: Quest) => {
const aCompleted = !!a.userStatus?.completedAt;
const bCompleted = !!b.userStatus?.completedAt;
@ -688,12 +688,12 @@ function processQuestForAutoComplete(quest: Quest): boolean {
if (quest.userStatus?.completedAt || existingInterval) {
return true;
} else if (!playType && !watchType) {
QuestifyLogger.warn(`[${getFormattedNow()}] Could not recognize the quest type for ${questName}.`);
QuestifyLogger.warn(`[${getFormattedNow()}] Could not recognize the Quest type for ${questName}.`);
return true;
} else if ((watchType && !completeVideoQuestsInBackground) || (playType && (!completeGameQuestsInBackground || !IS_DISCORD_DESKTOP))) {
return true;
} else if (!questDuration) {
QuestifyLogger.warn(`[${getFormattedNow()}] Could not find duration for quest ${questName}.`);
QuestifyLogger.warn(`[${getFormattedNow()}] Could not find duration for Quest ${questName}.`);
return true;
} else if (watchType) {
startVideoProgressTracking(quest, questDuration);
@ -747,7 +747,7 @@ function getQuestAcceptedButtonText(quest: Quest): string | null {
return null;
}
function getActiveQuestClosestToCompletion(): Quest | null {
function getQuestPanelOverride(): Quest | null {
let closestQuest: Quest | null = null;
let closestTimeRemaining = Infinity;
@ -766,6 +766,23 @@ function getActiveQuestClosestToCompletion(): Quest | null {
}
});
if (!closestQuest) {
const completedQuests = Array.from(QuestsStore.quests.values() as Quest[]).filter(q => q.userStatus?.completedAt).sort((a, b) => {
const aTime = new Date(a.userStatus?.completedAt as string);
const bTime = new Date(b.userStatus?.completedAt as string);
return bTime.getTime() - aTime.getTime();
});
completedQuests.forEach(quest => {
const completedQuest = quest.userStatus?.completedAt;
const questStatus = getQuestStatus(quest);
if (completedQuest && questStatus === QuestStatus.Unclaimed) {
closestQuest = quest;
}
});
}
return closestQuest;
}
@ -789,7 +806,7 @@ export default definePlugin({
shouldHideGiftInventoryRelocationNotice,
shouldHideFriendsListActiveNowPromotion,
shouldDisableQuestAcceptedButton,
getActiveQuestClosestToCompletion,
getQuestPanelOverride,
getQuestAcceptedButtonText,
processQuestForAutoComplete,
activeQuestIntervals,
@ -858,7 +875,7 @@ export default definePlugin({
},
{
// Hides the new Quest popup above the account panel.
// Allows in-progress quests to still show.
// Allows in-progress Quests to still show.
find: "QUESTS_BAR,questId",
replacement: {
match: /return null==(\i)\?null:\(/,
@ -871,7 +888,7 @@ export default definePlugin({
find: "questDeliveryOverride)?",
replacement: {
match: /(\i=)(\i.\i.questDeliveryOverride)/,
replace: "$1$self.getActiveQuestClosestToCompletion()??$2"
replace: "$1$self.getQuestPanelOverride()??$2"
}
},
{
@ -957,7 +974,7 @@ export default definePlugin({
group: true,
replacement: [
{
// Restyles quest tiles with colors.
// Restyles Quest tiles with colors.
match: /className:(\i\(\)\(\i.container,\i\)),/,
replace: "className:$self.getQuestTileClasses($1,arguments[0].quest),style:$self.getQuestTileStyle(arguments[0].quest),"
},
@ -974,7 +991,7 @@ export default definePlugin({
]
},
{
// Sorts the "All Quests" tab quest tiles.
// Sorts the "All Quests" tab Quest tiles.
// Also sets mobile-only Quests as desktop compatible if the setting is enabled.
find: ".ALL);return(",
replacement: {
@ -983,7 +1000,7 @@ export default definePlugin({
}
},
{
// Sorts the "Claimed Quests" tab quest tiles.
// Sorts the "Claimed Quests" tab Quest tiles.
find: ".ALL)}):(",
replacement: {
match: /(claimedQuests:(\i).{0,50}?;)/,

View file

@ -50,10 +50,10 @@ export function fetchAndAlertQuests(source: string, logger: Logger): void {
const shouldAlert = settings.store.fetchingQuestsAlert;
if (shouldAlert) {
logger.info(`[${getFormattedNow()}] New quests detected. Playing alert sound.`);
logger.info(`[${getFormattedNow()}] New Quests detected. Playing alert sound.`);
AudioPlayer(shouldAlert, 1).play();
} else {
logger.info(`[${getFormattedNow()}] New quests detected.`);
logger.info(`[${getFormattedNow()}] New Quests detected.`);
}
}
}
@ -75,13 +75,13 @@ export function startAutoFetchingQuests(seconds?: number): void {
}
const interval = seconds ? seconds * 1000 : settings.store.fetchingQuestsInterval * 1000;
QuestifyLogger.info(`[${getFormattedNow()}] Starting AutoFetch of quests every ${(interval / 60000).toFixed(2)} minutes.`);
QuestifyLogger.info(`[${getFormattedNow()}] Starting AutoFetch of Quests every ${(interval / 60000).toFixed(2)} minutes.`);
autoFetchInterval = setInterval(() => { fetchAndAlertQuests("Questify-AutoFetch", QuestifyLogger); }, interval);
}
export function stopAutoFetchingQuests(): void {
if (autoFetchInterval) {
QuestifyLogger.info(`[${getFormattedNow()}] Stopping AutoFetch of quests.`);
QuestifyLogger.info(`[${getFormattedNow()}] Stopping AutoFetch of Quests.`);
clearInterval(autoFetchInterval);
autoFetchInterval = null;
}
@ -712,8 +712,7 @@ function RestyleQuestsSetting() {
restyleQuestsIgnored,
restyleQuestsExpired,
restyleQuestsGradient,
restyleQuestsPreload,
ignoredQuestProfile
restyleQuestsPreload
} = settings.use([
"restyleQuestsUnclaimed",
"restyleQuestsClaimed",
@ -721,7 +720,6 @@ function RestyleQuestsSetting() {
"restyleQuestsExpired",
"restyleQuestsGradient",
"restyleQuestsPreload",
"ignoredQuestProfile"
]);
const [unclaimedColor, setUnclaimedColor] = useState<number | null>(restyleQuestsUnclaimed);
@ -871,26 +869,6 @@ function RestyleQuestsSetting() {
/>
</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
@ -942,12 +920,14 @@ function ReorderQuestsSetting(): JSX.Element {
unclaimedSubsort,
claimedSubsort,
ignoredSubsort,
expiredSubsort
expiredSubsort,
ignoredQuestProfile
} = settings.use([
"unclaimedSubsort",
"claimedSubsort",
"ignoredSubsort",
"expiredSubsort"
"expiredSubsort",
"ignoredQuestProfile"
]);
const getSubsortOptions = (source: string): SelectOption[] => {
@ -1083,6 +1063,26 @@ function ReorderQuestsSetting(): JSX.Element {
/>
</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>
</Forms.FormSection>
</div>
</ErrorBoundary>
@ -1314,7 +1314,7 @@ function FetchingQuestsSetting(): JSX.Element {
<Forms.FormText className={q("form-description")}>
Configure how often to fetch Quests from Discord and set up alerts for new Quests.
<br /><br />
By default, Discord only fetches quests on load and when visiting the Quests page.
By default, Discord only fetches Quests on load and when visiting the Quests page.
This means that without a fetch interval defined below, this plugin will become unaware
of new Quests added throughout the day.
<br /><br />
@ -1609,25 +1609,25 @@ export const settings = definePluginSettings({
},
unclaimedSubsort: {
type: OptionType.STRING,
description: "Subsort method for unclaimed quests.",
description: "Subsort method for unclaimed Quests.",
default: "Expiring ASC", // "Recent ASC", "Recent DESC", "Expiring ASC", "Expiring DESC"
hidden: true
},
claimedSubsort: {
type: OptionType.STRING,
description: "Subsort method for claimed quests.",
description: "Subsort method for claimed Quests.",
default: "Claimed DESC", // "Recent ASC", "Recent DESC", "Claimed ASC", "Claimed DESC"
hidden: true
},
ignoredSubsort: {
type: OptionType.STRING,
description: "Subsort method for ignored quests.",
description: "Subsort method for ignored Quests.",
default: "Recent DESC", // "Recent ASC", "Recent DESC", "Expiring ASC", "Expiring DESC"
hidden: true
},
expiredSubsort: {
type: OptionType.STRING,
description: "Subsort method for expired quests.",
description: "Subsort method for expired Quests.",
default: "Expiring DESC", // "Recent ASC", "Recent DESC", "Expiring ASC", "Expiring DESC"
hidden: true
},
@ -1639,7 +1639,7 @@ export const settings = definePluginSettings({
},
onQuestsPage: {
type: OptionType.BOOLEAN,
description: "Whether the user is currently on the quests page.",
description: "Whether the user is currently on the Quests page.",
default: false,
hidden: true
},

View file

@ -18,7 +18,7 @@ export const QuestifyLogger = new Logger("Questify");
export const PlayAudio = findByCodeLazy("Unable to find sound for pack name:");
// Takes an audio name or URL, volume, and a callback function. Plays when play() is called.
const AudioPlayerConstructor = findByCodeLazy("sound has no duration");
export function AudioPlayer(name: string, volume: number = 1, callback?: () => void): any { return new AudioPlayerConstructor(name, null, volume, "default", callback || (() => { })); }
export function AudioPlayer(name: string, volume: number = 1, callback?: () => void): any { return new AudioPlayerConstructor(name, null, volume, "default", callback ?? (() => { })); }
export const QuestsStore = findStoreLazy("QuestsStore");
export const questPath = "/discovery/quests";
export const leftClick = 0;
@ -267,7 +267,7 @@ export async function reportPlayGameQuestProgress(quest: Quest, terminal: boolea
const progress = progressPlayType?.value || 1;
if (!questPlayType) {
logger?.warn(`[${getFormattedNow()}] Could not recognize the quest type for Quest ${questName}.`);
logger?.warn(`[${getFormattedNow()}] Could not recognize the Quest type for Quest ${questName}.`);
return { progress: null };
}