fix: align market selection checkboxes with rows
- Fix checkbox column misalignment with creator list items - Add syncContentCellHeight to keep selection cells aligned with native rows - Add MarketAlignmentDiagnostic for debugging alignment issues - Update documentation to clarify dist-release folder usage - Add npm run build:release step to colleague setup guide
This commit is contained in:
@@ -99,10 +99,39 @@ export interface MarketTableDom {
|
||||
rows: MarketRowDom[];
|
||||
}
|
||||
|
||||
export interface MarketAlignmentDiagnostic {
|
||||
authorId: string;
|
||||
authorName: string;
|
||||
checkboxTop: number;
|
||||
rowTop: number;
|
||||
topDelta: number;
|
||||
}
|
||||
|
||||
export function syncMarketTable(root: ParentNode): MarketTableDom | null {
|
||||
return syncSyntheticMarketTable(root) ?? syncDivGridMarketTable(root);
|
||||
}
|
||||
|
||||
export function readMarketAlignmentDiagnostics(
|
||||
table: MarketTableDom
|
||||
): MarketAlignmentDiagnostic[] {
|
||||
return table.rows.map((rowDom) => {
|
||||
const selectionCell = rowDom.selectionCheckbox.parentElement;
|
||||
const selectionRect = selectionCell?.getBoundingClientRect();
|
||||
const rowRect = rowDom.row.getBoundingClientRect();
|
||||
|
||||
const checkboxTop = selectionRect?.top ?? Number.NaN;
|
||||
const rowTop = rowRect.top ?? Number.NaN;
|
||||
|
||||
return {
|
||||
authorId: rowDom.authorId,
|
||||
authorName: rowDom.authorName,
|
||||
checkboxTop,
|
||||
rowTop,
|
||||
topDelta: checkboxTop - rowTop
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
export function readMarketPageSignature(root: ParentNode): string {
|
||||
const document = getOwnerDocument(root);
|
||||
const explicitPageIndex =
|
||||
@@ -801,14 +830,15 @@ function syncDivColumnCells(
|
||||
const templateCells = getDirectContentCells(templateColumn);
|
||||
for (let index = 0; index < rowCount; index += 1) {
|
||||
const existingCell = getDirectContentCells(column)[index] ?? null;
|
||||
const templateCell =
|
||||
templateCells[index] ?? templateCells[templateCells.length - 1] ?? null;
|
||||
if (existingCell) {
|
||||
existingCell.dataset.marketRowCell = field;
|
||||
applyPluginContentCellStyles(existingCell);
|
||||
syncContentCellHeight(existingCell, templateCell);
|
||||
continue;
|
||||
}
|
||||
|
||||
const templateCell =
|
||||
templateCells[index] ?? templateCells[templateCells.length - 1] ?? null;
|
||||
const nextCell =
|
||||
field === SELECTION_COLUMN_KEY
|
||||
? templateCell
|
||||
@@ -820,11 +850,31 @@ function syncDivColumnCells(
|
||||
nextCell.dataset.marketRowCell = field;
|
||||
applyColumnWidth(nextCell, field);
|
||||
applyPluginContentCellStyles(nextCell);
|
||||
syncContentCellHeight(nextCell, templateCell);
|
||||
nextCell.textContent = "";
|
||||
column.appendChild(nextCell);
|
||||
}
|
||||
}
|
||||
|
||||
function syncContentCellHeight(
|
||||
cell: HTMLElement,
|
||||
templateCell: HTMLElement | null
|
||||
): void {
|
||||
if (!templateCell) {
|
||||
return;
|
||||
}
|
||||
|
||||
const measuredHeight = Math.round(templateCell.getBoundingClientRect().height);
|
||||
const nextHeight =
|
||||
measuredHeight > 0 ? `${measuredHeight}px` : templateCell.style.height;
|
||||
|
||||
if (nextHeight) {
|
||||
cell.style.height = nextHeight;
|
||||
} else {
|
||||
cell.style.removeProperty("height");
|
||||
}
|
||||
}
|
||||
|
||||
function applyPluginHeaderCellStyles(cell: HTMLElement): void {
|
||||
cell.style.display = "flex";
|
||||
cell.style.alignItems = "center";
|
||||
|
||||
@@ -4,6 +4,7 @@ import { createBatchPayload, type BatchPayload } from "./batch-payload";
|
||||
import {
|
||||
applyRowOrder,
|
||||
applyRowVisibility,
|
||||
readMarketAlignmentDiagnostics,
|
||||
readMarketPageSignature,
|
||||
renderMarketRowState,
|
||||
syncPluginSortHeaders,
|
||||
@@ -396,6 +397,7 @@ export function createMarketController(options: CreateMarketControllerOptions) {
|
||||
applyRowOrder(table, records.map((record) => record.authorId));
|
||||
bindSelectionControls(table);
|
||||
syncMarketSelectionState(table, selectedAuthorIds);
|
||||
logMarketAlignmentDiagnosticsIfEnabled(options.window, table, "applyCurrentView");
|
||||
lastKnownPageSignature = readMarketPageSignature(options.document);
|
||||
});
|
||||
}
|
||||
@@ -662,12 +664,23 @@ export function createMarketController(options: CreateMarketControllerOptions) {
|
||||
}
|
||||
|
||||
const step = Math.max(scrollContainer.clientHeight, 240);
|
||||
logMarketScrollTraceIfEnabled(options.window, {
|
||||
event: "start",
|
||||
maxScrollTop,
|
||||
originalScrollTop,
|
||||
step
|
||||
});
|
||||
for (
|
||||
let nextScrollTop = Math.min(originalScrollTop + step, maxScrollTop);
|
||||
nextScrollTop > originalScrollTop && nextScrollTop <= maxScrollTop;
|
||||
nextScrollTop = Math.min(nextScrollTop + step, maxScrollTop)
|
||||
) {
|
||||
setScrollTop(scrollContainer, nextScrollTop);
|
||||
logMarketScrollTraceIfEnabled(options.window, {
|
||||
event: "step",
|
||||
nextScrollTop,
|
||||
scrollTop: scrollContainer.scrollTop
|
||||
});
|
||||
hydrationSnapshot = await collectCurrentPageSnapshotsUntilSettled();
|
||||
if (
|
||||
hydrationSnapshot.missingDefaultFieldCount === 0 &&
|
||||
@@ -683,6 +696,10 @@ export function createMarketController(options: CreateMarketControllerOptions) {
|
||||
|
||||
if (scrollContainer.scrollTop !== originalScrollTop) {
|
||||
setScrollTop(scrollContainer, originalScrollTop);
|
||||
logMarketScrollTraceIfEnabled(options.window, {
|
||||
event: "restore",
|
||||
restoredScrollTop: scrollContainer.scrollTop
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1009,6 +1026,45 @@ function setScrollTop(element: HTMLElement, top: number): void {
|
||||
element.dispatchEvent(new Event("scroll"));
|
||||
}
|
||||
|
||||
function logMarketAlignmentDiagnosticsIfEnabled(
|
||||
window: Window,
|
||||
table: ReturnType<typeof syncMarketTable>,
|
||||
label: string
|
||||
): void {
|
||||
if (!isMarketDebugLoggingEnabled(window) || !table) {
|
||||
return;
|
||||
}
|
||||
|
||||
const diagnostics = readMarketAlignmentDiagnostics(table);
|
||||
console.info(`[SCES debug] ${label} alignment`, diagnostics);
|
||||
}
|
||||
|
||||
function logMarketScrollTraceIfEnabled(
|
||||
window: Window,
|
||||
payload: Record<string, unknown>
|
||||
): void {
|
||||
if (!isMarketDebugLoggingEnabled(window)) {
|
||||
return;
|
||||
}
|
||||
|
||||
console.info("[SCES debug] submit/export scroll", payload);
|
||||
}
|
||||
|
||||
function isMarketDebugLoggingEnabled(window: Window): boolean {
|
||||
try {
|
||||
const searchParams = new URL(window.location.href).searchParams;
|
||||
if (searchParams.get("scesDebug") === "1") {
|
||||
return true;
|
||||
}
|
||||
} catch {}
|
||||
|
||||
try {
|
||||
return window.localStorage.getItem("scesDebugMarket") === "1";
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function readCurrentPageRows(document: Document): MarketRowSnapshot[] {
|
||||
const table = syncMarketTable(document);
|
||||
if (!table) {
|
||||
|
||||
Reference in New Issue
Block a user