mirror of
https://github.com/monkeytypegame/monkeytype.git
synced 2025-03-04 18:53:26 +08:00
impr(commandline): add "add/remove quote to favorites" commands
closes #5368
This commit is contained in:
parent
9c652d29e8
commit
38fb774dd3
4 changed files with 151 additions and 31 deletions
|
@ -59,6 +59,7 @@ import KeymapShowTopRowCommands from "./lists/keymap-show-top-row";
|
|||
import EnableAdsCommands from "./lists/enable-ads";
|
||||
import MonkeyPowerLevelCommands from "./lists/monkey-power-level";
|
||||
import BailOutCommands from "./lists/bail-out";
|
||||
import QuoteFavoriteCommands from "./lists/quote-favorites";
|
||||
import ResultSavingCommands from "./lists/result-saving";
|
||||
import NavigationCommands from "./lists/navigation";
|
||||
import FontSizeCommands from "./lists/font-size";
|
||||
|
@ -205,6 +206,7 @@ export const commands: MonkeyTypes.CommandsSubgroup = {
|
|||
},
|
||||
shouldFocusTestUI: false,
|
||||
},
|
||||
...QuoteFavoriteCommands,
|
||||
...BailOutCommands,
|
||||
{
|
||||
id: "shareTestSettings",
|
||||
|
|
75
frontend/src/ts/commandline/lists/quote-favorites.ts
Normal file
75
frontend/src/ts/commandline/lists/quote-favorites.ts
Normal file
|
@ -0,0 +1,75 @@
|
|||
import Config from "../../config";
|
||||
import QuotesController from "../../controllers/quotes-controller";
|
||||
import * as Notifications from "../../elements/notifications";
|
||||
import { isAuthenticated } from "../../firebase";
|
||||
import { createErrorMessage } from "../../utils/misc";
|
||||
import * as Loader from "../../elements/loader";
|
||||
|
||||
const commands: MonkeyTypes.Command[] = [
|
||||
{
|
||||
id: "addQuoteToFavorite",
|
||||
display: "Add current quote to favorite",
|
||||
icon: "fa-heart",
|
||||
available: (): boolean => {
|
||||
const currentQuote = QuotesController.getCurrentQuote();
|
||||
return (
|
||||
isAuthenticated() &&
|
||||
currentQuote !== null &&
|
||||
Config.mode === "quote" &&
|
||||
!QuotesController.isQuoteFavorite(currentQuote)
|
||||
);
|
||||
},
|
||||
exec: async (): Promise<void> => {
|
||||
try {
|
||||
Loader.show();
|
||||
await QuotesController.setQuoteFavorite(
|
||||
QuotesController.getCurrentQuote() as MonkeyTypes.Quote,
|
||||
true
|
||||
);
|
||||
Loader.hide();
|
||||
Notifications.add("Quote added to favorites", 1);
|
||||
} catch (e) {
|
||||
Loader.hide();
|
||||
const message = createErrorMessage(
|
||||
e,
|
||||
"Failed to add quote to favorites"
|
||||
);
|
||||
Notifications.add(message, -1);
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
id: "removeQuoteFromFavorite",
|
||||
display: "Remove current quote from favorite",
|
||||
icon: "fa-heart-broken",
|
||||
available: (): boolean => {
|
||||
const currentQuote = QuotesController.getCurrentQuote();
|
||||
return (
|
||||
isAuthenticated() &&
|
||||
currentQuote !== null &&
|
||||
Config.mode === "quote" &&
|
||||
QuotesController.isQuoteFavorite(currentQuote)
|
||||
);
|
||||
},
|
||||
exec: async (): Promise<void> => {
|
||||
try {
|
||||
Loader.show();
|
||||
await QuotesController.setQuoteFavorite(
|
||||
QuotesController.getCurrentQuote() as MonkeyTypes.Quote,
|
||||
false
|
||||
);
|
||||
Loader.hide();
|
||||
Notifications.add("Quote removed from favorites", 1);
|
||||
} catch (e) {
|
||||
Loader.hide();
|
||||
const message = createErrorMessage(
|
||||
e,
|
||||
"Failed to remove quote from favorites"
|
||||
);
|
||||
Notifications.add(message, -1);
|
||||
}
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
export default commands;
|
|
@ -3,6 +3,7 @@ import { randomElementFromArray, shuffle } from "../utils/arrays";
|
|||
import { cachedFetchJson } from "../utils/json-data";
|
||||
import { subscribe } from "../observables/config-event";
|
||||
import * as DB from "../db";
|
||||
import Ape from "../ape";
|
||||
|
||||
type JsonQuote = {
|
||||
text: string;
|
||||
|
@ -212,6 +213,51 @@ class QuotesController {
|
|||
|
||||
return matchedLanguage !== undefined;
|
||||
}
|
||||
|
||||
async setQuoteFavorite(
|
||||
quote: MonkeyTypes.Quote,
|
||||
isFavorite: boolean
|
||||
): Promise<void> {
|
||||
const snapshot = DB.getSnapshot();
|
||||
if (!snapshot) {
|
||||
throw new Error("Snapshot is not available");
|
||||
}
|
||||
|
||||
if (!isFavorite) {
|
||||
// Remove from favorites
|
||||
const response = await Ape.users.removeQuoteFromFavorites(
|
||||
quote.language,
|
||||
`${quote.id}`
|
||||
);
|
||||
|
||||
if (response.status === 200) {
|
||||
const quoteIndex = snapshot.favoriteQuotes?.[quote.language]?.indexOf(
|
||||
`${quote.id}`
|
||||
) as number;
|
||||
snapshot.favoriteQuotes?.[quote.language]?.splice(quoteIndex, 1);
|
||||
} else {
|
||||
throw new Error(response.message);
|
||||
}
|
||||
} else {
|
||||
// Remove from favorites
|
||||
const response = await Ape.users.addQuoteToFavorites(
|
||||
quote.language,
|
||||
`${quote.id}`
|
||||
);
|
||||
|
||||
if (response.status === 200) {
|
||||
if (snapshot.favoriteQuotes === undefined) {
|
||||
snapshot.favoriteQuotes = {};
|
||||
}
|
||||
if (!snapshot.favoriteQuotes[quote.language]) {
|
||||
snapshot.favoriteQuotes[quote.language] = [];
|
||||
}
|
||||
snapshot.favoriteQuotes[quote.language]?.push(`${quote.id}`);
|
||||
} else {
|
||||
throw new Error(response.message);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const quoteController = new QuotesController();
|
||||
|
|
|
@ -20,6 +20,7 @@ import SlimSelect from "slim-select";
|
|||
import * as TestState from "../test/test-state";
|
||||
import AnimatedModal, { ShowOptions } from "../utils/animated-modal";
|
||||
import * as TestLogic from "../test/test-logic";
|
||||
import { createErrorMessage } from "../utils/misc";
|
||||
|
||||
const searchServiceCache: Record<string, SearchService<MonkeyTypes.Quote>> = {};
|
||||
|
||||
|
@ -352,47 +353,43 @@ async function toggleFavoriteForQuote(quoteId: string): Promise<void> {
|
|||
return;
|
||||
}
|
||||
|
||||
const quote = {
|
||||
language: quoteLang,
|
||||
id: parseInt(quoteId, 10),
|
||||
} as MonkeyTypes.Quote;
|
||||
|
||||
const alreadyFavorited = QuotesController.isQuoteFavorite(quote);
|
||||
|
||||
const $button = $(
|
||||
`#quoteSearchModal .searchResult[data-quote-id=${quoteId}] .textButton.favorite i`
|
||||
);
|
||||
const dbSnapshot = DB.getSnapshot();
|
||||
if (!dbSnapshot) return;
|
||||
|
||||
if ($button.hasClass("fas")) {
|
||||
// Remove from favorites
|
||||
Loader.show();
|
||||
const response = await Ape.users.removeQuoteFromFavorites(
|
||||
quoteLang,
|
||||
quoteId
|
||||
);
|
||||
Loader.hide();
|
||||
|
||||
Notifications.add(response.message, response.status === 200 ? 1 : -1);
|
||||
|
||||
if (response.status === 200) {
|
||||
if (alreadyFavorited) {
|
||||
try {
|
||||
Loader.show();
|
||||
await QuotesController.setQuoteFavorite(quote, false);
|
||||
Loader.hide();
|
||||
$button.removeClass("fas").addClass("far");
|
||||
const quoteIndex = dbSnapshot.favoriteQuotes?.[quoteLang]?.indexOf(
|
||||
quoteId
|
||||
) as number;
|
||||
dbSnapshot.favoriteQuotes?.[quoteLang]?.splice(quoteIndex, 1);
|
||||
} catch (e) {
|
||||
Loader.hide();
|
||||
const message = createErrorMessage(
|
||||
e,
|
||||
"Failed to remove quote from favorites"
|
||||
);
|
||||
Notifications.add(message, -1);
|
||||
}
|
||||
} else {
|
||||
// Add to favorites
|
||||
Loader.show();
|
||||
const response = await Ape.users.addQuoteToFavorites(quoteLang, quoteId);
|
||||
Loader.hide();
|
||||
|
||||
Notifications.add(response.message, response.status === 200 ? 1 : -1);
|
||||
|
||||
if (response.status === 200) {
|
||||
try {
|
||||
Loader.show();
|
||||
await QuotesController.setQuoteFavorite(quote, true);
|
||||
Loader.hide();
|
||||
$button.removeClass("far").addClass("fas");
|
||||
if (dbSnapshot.favoriteQuotes === undefined) {
|
||||
dbSnapshot.favoriteQuotes = {};
|
||||
}
|
||||
if (!dbSnapshot.favoriteQuotes[quoteLang]) {
|
||||
dbSnapshot.favoriteQuotes[quoteLang] = [];
|
||||
}
|
||||
dbSnapshot.favoriteQuotes[quoteLang]?.push(quoteId);
|
||||
} catch (e) {
|
||||
Loader.hide();
|
||||
const message = createErrorMessage(e, "Failed to add quote to favorites");
|
||||
Notifications.add(message, -1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue