fix: harden favorites controller lifecycle
This commit is contained in:
@@ -87,6 +87,26 @@ export function syncFavoriteRowPickers(options: {
|
||||
}
|
||||
}
|
||||
|
||||
export function disposeFavoriteRowPickers(document: Document): void {
|
||||
const state = pickerDocumentStates.get(document);
|
||||
if (state) {
|
||||
closeFavoritePicker(document, state);
|
||||
state.contextByButton.forEach((_context, button) => {
|
||||
button.onclick = null;
|
||||
button.remove();
|
||||
});
|
||||
state.contextByButton.clear();
|
||||
state.pendingOperations.clear();
|
||||
pickerDocumentStates.delete(document);
|
||||
}
|
||||
|
||||
document.querySelectorAll<HTMLButtonElement>(ACTION_SELECTOR).forEach((button) => {
|
||||
button.onclick = null;
|
||||
button.remove();
|
||||
});
|
||||
removeFavoritePickerRoots(document);
|
||||
}
|
||||
|
||||
type FavoritePickerContext = {
|
||||
button: HTMLButtonElement;
|
||||
creator: FavoriteCreatorInput;
|
||||
|
||||
@@ -17,7 +17,10 @@ import { promptForAuthorIds } from "./author-id-dialog";
|
||||
import { promptForBatchName } from "./batch-name-dialog";
|
||||
import { createBatchPayload, type BatchPayload } from "./batch-payload";
|
||||
import { promptForFavoriteFolderName } from "./favorite-folder-dialog";
|
||||
import { syncFavoriteRowPickers } from "./favorite-row-picker";
|
||||
import {
|
||||
disposeFavoriteRowPickers,
|
||||
syncFavoriteRowPickers
|
||||
} from "./favorite-row-picker";
|
||||
import {
|
||||
createFavoritesDrawer,
|
||||
type FavoritesDrawerController
|
||||
@@ -232,6 +235,7 @@ export function createMarketController(options: CreateMarketControllerOptions) {
|
||||
let cachedFavoritesState: FavoritesStateV1 | undefined;
|
||||
let favoritesRefreshVersion = 0;
|
||||
let favoriteActionButtons: HTMLButtonElement[] = [];
|
||||
let needsFavoritesRefresh = false;
|
||||
const favoritesDrawer: FavoritesDrawerController = createFavoritesDrawer(
|
||||
options.document,
|
||||
{
|
||||
@@ -277,6 +281,9 @@ export function createMarketController(options: CreateMarketControllerOptions) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (favoriteControlsMissing) {
|
||||
needsFavoritesRefresh = true;
|
||||
}
|
||||
scheduleSync();
|
||||
});
|
||||
const observationRoot = options.document.body ?? options.document.documentElement;
|
||||
@@ -522,7 +529,6 @@ export function createMarketController(options: CreateMarketControllerOptions) {
|
||||
const ready = (async () => {
|
||||
await runSyncCycle();
|
||||
await refreshFavorites();
|
||||
await waitForDomSettled();
|
||||
})();
|
||||
|
||||
return {
|
||||
@@ -533,6 +539,7 @@ export function createMarketController(options: CreateMarketControllerOptions) {
|
||||
options.window.clearTimeout(scheduledSyncTimeoutId);
|
||||
scheduledSyncTimeoutId = null;
|
||||
}
|
||||
disposeFavoriteRowPickers(options.document);
|
||||
favoritesDrawer.dispose();
|
||||
},
|
||||
ready
|
||||
@@ -725,6 +732,9 @@ export function createMarketController(options: CreateMarketControllerOptions) {
|
||||
return;
|
||||
}
|
||||
|
||||
cachedFavoritesState = undefined;
|
||||
favoriteActionButtons = [];
|
||||
disposeFavoriteRowPickers(options.document);
|
||||
favoritesDrawer.setError("收藏夹暂不可用");
|
||||
}
|
||||
}
|
||||
@@ -842,8 +852,9 @@ export function createMarketController(options: CreateMarketControllerOptions) {
|
||||
try {
|
||||
return await mutation();
|
||||
} catch (error) {
|
||||
favoritesDrawer.setError(readFavoriteOperationError(error));
|
||||
throw error;
|
||||
const message = readFavoriteOperationError(error);
|
||||
favoritesDrawer.setError(message);
|
||||
throw new Error(message);
|
||||
} finally {
|
||||
favoritesDrawer.setBusy(false);
|
||||
}
|
||||
@@ -1828,6 +1839,10 @@ export function createMarketController(options: CreateMarketControllerOptions) {
|
||||
try {
|
||||
toolbar = ensurePluginToolbar(options.document, toolbarHandlers);
|
||||
await hydrateCurrentPage();
|
||||
if (needsFavoritesRefresh) {
|
||||
needsFavoritesRefresh = false;
|
||||
await refreshFavorites();
|
||||
}
|
||||
applyCurrentView();
|
||||
lastKnownPageSignature = readMarketPageSignature(options.document);
|
||||
} finally {
|
||||
|
||||
Reference in New Issue
Block a user