@parhelia/core 0.1.12910 → 0.1.12911

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. package/dist/editor/ai/Agents.js +17 -23
  2. package/dist/editor/ai/Agents.js.map +1 -1
  3. package/dist/editor/ai/agentCollection.d.ts +2 -0
  4. package/dist/editor/ai/agentCollection.js +8 -0
  5. package/dist/editor/ai/agentCollection.js.map +1 -0
  6. package/dist/editor/ai/agentMessageHelpers.d.ts +1 -0
  7. package/dist/editor/ai/agentMessageHelpers.js +4 -1
  8. package/dist/editor/ai/agentMessageHelpers.js.map +1 -1
  9. package/dist/editor/ai/terminal/agentSessionSnapshot.js +4 -1
  10. package/dist/editor/ai/terminal/agentSessionSnapshot.js.map +1 -1
  11. package/dist/editor/ai/terminal/components/AgentLoadingContent.js +2 -2
  12. package/dist/editor/ai/terminal/components/AgentLoadingContent.js.map +1 -1
  13. package/dist/editor/ai/terminal/components/AiResponseMessage.js +9 -3
  14. package/dist/editor/ai/terminal/components/AiResponseMessage.js.map +1 -1
  15. package/dist/editor/ai/terminal/useAgentDraftInitializer.js +3 -1
  16. package/dist/editor/ai/terminal/useAgentDraftInitializer.js.map +1 -1
  17. package/dist/editor/ai/terminal/useAgentLoadErrorHandler.js +3 -1
  18. package/dist/editor/ai/terminal/useAgentLoadErrorHandler.js.map +1 -1
  19. package/dist/editor/ai/terminal/useAgentSessionFacade.js +7 -3
  20. package/dist/editor/ai/terminal/useAgentSessionFacade.js.map +1 -1
  21. package/dist/editor/client/EditorShell.js +177 -19
  22. package/dist/editor/client/EditorShell.js.map +1 -1
  23. package/dist/editor/client/editContext.d.ts +5 -1
  24. package/dist/editor/client/editContext.js.map +1 -1
  25. package/dist/editor/media-selector/AiImageSearchPrompt.js +8 -17
  26. package/dist/editor/media-selector/AiImageSearchPrompt.js.map +1 -1
  27. package/dist/editor/page-editor-chrome/BridgeInlineFormatOverlay.js +6 -5
  28. package/dist/editor/page-editor-chrome/BridgeInlineFormatOverlay.js.map +1 -1
  29. package/dist/editor/page-editor-chrome/overlay/IframeOverlayProvider.d.ts +3 -1
  30. package/dist/editor/page-editor-chrome/overlay/IframeOverlayProvider.js +34 -2
  31. package/dist/editor/page-editor-chrome/overlay/IframeOverlayProvider.js.map +1 -1
  32. package/dist/editor/page-viewer/MiniMap.d.ts +5 -1
  33. package/dist/editor/page-viewer/MiniMap.js +21 -9
  34. package/dist/editor/page-viewer/MiniMap.js.map +1 -1
  35. package/dist/editor/page-viewer/PageViewerFrame.js +2 -2
  36. package/dist/editor/page-viewer/PageViewerFrame.js.map +1 -1
  37. package/dist/editor/reviews/CreateReviewConfirmStep.d.ts +1 -2
  38. package/dist/editor/reviews/CreateReviewConfirmStep.js +3 -3
  39. package/dist/editor/reviews/CreateReviewConfirmStep.js.map +1 -1
  40. package/dist/editor/reviews/CreateReviewDialog.js +27 -3
  41. package/dist/editor/reviews/CreateReviewDialog.js.map +1 -1
  42. package/dist/editor/services/contentService.d.ts +3 -2
  43. package/dist/editor/services/contentService.js +19 -5
  44. package/dist/editor/services/contentService.js.map +1 -1
  45. package/dist/editor/services/contextService.d.ts +8 -0
  46. package/dist/editor/services/contextService.js +19 -0
  47. package/dist/editor/services/contextService.js.map +1 -1
  48. package/dist/editor/sidebar/EditHistory.js +11 -3
  49. package/dist/editor/sidebar/EditHistory.js.map +1 -1
  50. package/dist/editor/ui/LoadingState.js +4 -4
  51. package/dist/editor/ui/LoadingState.js.map +1 -1
  52. package/dist/revision.d.ts +2 -2
  53. package/dist/revision.js +2 -2
  54. package/dist/splash-screen/ModernSplashScreen.d.ts +2 -0
  55. package/dist/splash-screen/ModernSplashScreen.js +8 -3
  56. package/dist/splash-screen/ModernSplashScreen.js.map +1 -1
  57. package/package.json +1 -1
@@ -22,6 +22,7 @@ import "react-json-view-lite/dist/index.css";
22
22
  import { MediaSelector, } from "../media-selector/MediaSelector";
23
23
  import { getComponentCommands } from "../commands/componentCommands";
24
24
  import { getLanguagesAndVersions, } from "../services/contentService";
25
+ import { getEditorSettings } from "../services/systemService";
25
26
  import { getAllFavorites } from "../services/favouritesService";
26
27
  import ConfirmationDialog from "../ConfirmationDialog";
27
28
  import { getItemDescriptor } from "../utils";
@@ -67,12 +68,37 @@ import { useGlobalEditorKeyDown } from "./hooks/useGlobalEditorKeyDown";
67
68
  import { useStartupChecks } from "../settings/status/index";
68
69
  import { EditorLoadingOverlay } from "../EditorLoadingOverlay";
69
70
  import { FeatureGate, LicenseFeatures, LicenseProvider, LicenseOverlay, } from "../../licensing";
71
+ const GLOBAL_SESSION_HISTORY_LIMIT = 200;
72
+ const GLOBAL_HISTORY_LIMIT = 200;
73
+ const GLOBAL_SESSION_HISTORY_LOAD_MORE_INCREMENT = 50;
74
+ const GLOBAL_HISTORY_LOAD_MORE_INCREMENT = 100;
75
+ function getInitialGlobalHistoryLimit(filterBySession) {
76
+ return filterBySession ? GLOBAL_SESSION_HISTORY_LIMIT : GLOBAL_HISTORY_LIMIT;
77
+ }
78
+ function getGlobalHistoryLoadMoreIncrement(filterBySession) {
79
+ return filterBySession
80
+ ? GLOBAL_SESSION_HISTORY_LOAD_MORE_INCREMENT
81
+ : GLOBAL_HISTORY_LOAD_MORE_INCREMENT;
82
+ }
70
83
  // Sentinel written to the `sidebar` URL param when the user has explicitly closed
71
84
  // every sidebar. Distinguishes "no preference yet" (param absent) from "user wants
72
85
  // nothing open" (param present with this value) so reload can honor the user's intent.
73
86
  const SIDEBAR_NONE_SENTINEL = "none";
87
+ const PARHELIA_SETTINGS_ITEM_ID = "a2f3c168bb2841ff9673ee7f3cc624af";
88
+ const PARHELIA_SETTINGS_ITEM_PATH = "/sitecore/system/parhelia/settings";
89
+ const PARHELIA_SHOW_MINIMAP_FIELD_ID = "e75976d2179e4578b4140147b7525fa5";
74
90
  const sidebarUrlValue = (ids) => ids.length ? ids.join(",") : SIDEBAR_NONE_SENTINEL;
75
91
  // moved to hooks/useQuota
92
+ function isParheliaSettingsSnapshotChange(changes) {
93
+ return changes.some((change) => {
94
+ const changedItemId = cleanId(change.item?.id);
95
+ const changedItemPath = change.item?.path?.toLowerCase();
96
+ const changedFieldIds = change.changes.fields?.map((fieldId) => cleanId(fieldId));
97
+ return (changedItemId === PARHELIA_SETTINGS_ITEM_ID ||
98
+ changedItemPath === PARHELIA_SETTINGS_ITEM_PATH ||
99
+ changedFieldIds?.includes(PARHELIA_SHOW_MINIMAP_FIELD_ID));
100
+ });
101
+ }
76
102
  function getInitialOpenSidebars(configuration, workspaceId) {
77
103
  const workspace = configuration.editor.workspaces?.find((candidate) => candidate.id === workspaceId);
78
104
  if (workspace?.supportsSidebars && workspace.defaultSidebars?.length) {
@@ -143,6 +169,10 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
143
169
  const router = useRouter();
144
170
  const pathname = usePathname();
145
171
  const searchParams = useSearchParams();
172
+ const [effectiveParheliaSettings, setEffectiveParheliaSettings] = useState(parheliaSettings);
173
+ const [effectiveParheliaSettingsLoaded, setEffectiveParheliaSettingsLoaded] = useState(parheliaSettingsLoaded === true);
174
+ const parheliaSettingsRefreshInFlightRef = useRef(null);
175
+ const minimapEnabledInSettings = effectiveParheliaSettings?.showMinimap !== false;
146
176
  const [selection, setSelection] = useState([]);
147
177
  const [contentTreeSelection, setContentTreeSelection] = useState([]);
148
178
  const [selectedForInsertion, setSelectedForInsertion] = useState("");
@@ -159,6 +189,34 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
159
189
  const confirmationDialogRef = useRef(null);
160
190
  const contextMenuRef = useRef(null);
161
191
  const editContextRef = useRef(undefined);
192
+ useEffect(() => {
193
+ setEffectiveParheliaSettings(parheliaSettings);
194
+ setEffectiveParheliaSettingsLoaded(parheliaSettingsLoaded === true);
195
+ }, [parheliaSettings, parheliaSettingsLoaded]);
196
+ const refreshParheliaSettings = useCallback(async () => {
197
+ if (parheliaSettingsRefreshInFlightRef.current) {
198
+ return parheliaSettingsRefreshInFlightRef.current;
199
+ }
200
+ const refresh = getEditorSettings()
201
+ .then((result) => {
202
+ if (result.type === "success" && result.data) {
203
+ setEffectiveParheliaSettings(result.data);
204
+ setEffectiveParheliaSettingsLoaded(true);
205
+ return;
206
+ }
207
+ console.warn("Failed to refresh Parhelia settings:", result.summary || result.details);
208
+ })
209
+ .catch((error) => {
210
+ console.error("Failed to refresh Parhelia settings:", error);
211
+ });
212
+ parheliaSettingsRefreshInFlightRef.current = refresh;
213
+ void refresh.finally(() => {
214
+ if (parheliaSettingsRefreshInFlightRef.current === refresh) {
215
+ parheliaSettingsRefreshInFlightRef.current = null;
216
+ }
217
+ });
218
+ return refresh;
219
+ }, []);
162
220
  const [currentOverlay, setCurrentOverlay] = useState();
163
221
  const [contextMenuSource, setContextMenuSource] = useState();
164
222
  const [item, setItem] = useState();
@@ -192,6 +250,12 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
192
250
  const [showOnlyMyChanges, setShowOnlyMyChanges] = useState(true);
193
251
  const [filterByCurrentLanguage, setFilterByCurrentLanguage] = useState(true);
194
252
  const [historySearchQuery, setHistorySearchQuery] = useState("");
253
+ const [isHistoryLoading, setIsHistoryLoading] = useState(false);
254
+ const [isHistoryLoadingMore, setIsHistoryLoadingMore] = useState(false);
255
+ const [canLoadMoreHistory, setCanLoadMoreHistory] = useState(false);
256
+ const [globalHistoryLimit, setGlobalHistoryLimit] = useState(GLOBAL_SESSION_HISTORY_LIMIT);
257
+ const historyLoadingRequestCountRef = useRef(0);
258
+ const historyLoadingMoreRequestCountRef = useRef(0);
195
259
  const [recentEdits, setRecentEdits] = useState([]);
196
260
  const addRecentEdit = useCallback((edit) => {
197
261
  setRecentEdits((prevEditedFields) => {
@@ -696,6 +760,7 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
696
760
  const [editorFormHintVisible, setEditorFormHintVisible] = useState(false);
697
761
  const editorFormToggleButtonRef = useRef(null);
698
762
  const [showMinimap, setShowMinimap] = useState(userPreferences.showMinimap ?? true);
763
+ const effectiveShowMinimap = minimapEnabledInSettings && showMinimap;
699
764
  const [showHelpTerminal, setShowHelpTerminal] = useState(false);
700
765
  const [helpTerminalInitialPrompt, setHelpTerminalInitialPrompt] = useState(undefined);
701
766
  const [helpTerminalProfileName, setHelpTerminalProfileName] = useState(undefined);
@@ -803,13 +868,29 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
803
868
  const [currentPageItem, setCurrentPageItem] = useState();
804
869
  // Create itemsRepository with current page item (will be updated when page loads)
805
870
  const itemsRepository = useItemsRepository(addRecentEdit, currentPageItem, getFieldModificationStores);
871
+ // The fallback is a null-object: it backs activePageViewContext only when no slot
872
+ // context is registered (the startup gap, or all slots closed). Its *resolved page* is
873
+ // rendered on screen ONLY by the fullscreen branch (the <PageViewerFrame> in the
874
+ // `fullscreen ? (...)` render); in non-fullscreen the visible iframe comes from the
875
+ // slot's own primaryPageViewContext. So only feed it a descriptor when it is actually
876
+ // the render source — otherwise it pointlessly re-resolves the page the slot already
877
+ // resolves, producing a duplicate /parhelia/resolve at startup.
878
+ const hasActiveSlotContext = !!(activeSlotId && slotContexts.get(activeSlotId));
806
879
  const fallbackPageViewContext = usePageViewContext({
807
- pageItemDescriptor: currentItemDescriptor,
880
+ pageItemDescriptor: fullscreen && !hasActiveSlotContext ? currentItemDescriptor : undefined,
808
881
  itemsRepository,
809
882
  configuration,
810
- parheliaSettings,
883
+ parheliaSettings: effectiveParheliaSettings,
811
884
  layoutMode,
812
885
  });
886
+ useEffect(() => {
887
+ return itemsRepository.subscribeItemsChanged((changes) => {
888
+ const persistedChanges = changes.filter((change) => change.source !== "local-field-update");
889
+ if (isParheliaSettingsSnapshotChange(persistedChanges)) {
890
+ void refreshParheliaSettings();
891
+ }
892
+ });
893
+ }, [itemsRepository, refreshParheliaSettings]);
813
894
  const registerSlotContext = useCallback((slotId, ctx) => {
814
895
  setSlotContexts((prev) => {
815
896
  if (prev.get(slotId) === ctx)
@@ -1929,6 +2010,34 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
1929
2010
  }
1930
2011
  return [];
1931
2012
  }, []);
2013
+ const getEditHistoryWithLoading = useCallback(async (options, loadingMode = "initial") => {
2014
+ const loadingMore = loadingMode === "more";
2015
+ if (loadingMore) {
2016
+ historyLoadingMoreRequestCountRef.current += 1;
2017
+ setIsHistoryLoadingMore(true);
2018
+ }
2019
+ else {
2020
+ historyLoadingRequestCountRef.current += 1;
2021
+ setIsHistoryLoading(true);
2022
+ }
2023
+ try {
2024
+ return await getEditHistory(options);
2025
+ }
2026
+ finally {
2027
+ if (loadingMore) {
2028
+ historyLoadingMoreRequestCountRef.current = Math.max(0, historyLoadingMoreRequestCountRef.current - 1);
2029
+ if (historyLoadingMoreRequestCountRef.current === 0) {
2030
+ setIsHistoryLoadingMore(false);
2031
+ }
2032
+ }
2033
+ else {
2034
+ historyLoadingRequestCountRef.current = Math.max(0, historyLoadingRequestCountRef.current - 1);
2035
+ if (historyLoadingRequestCountRef.current === 0) {
2036
+ setIsHistoryLoading(false);
2037
+ }
2038
+ }
2039
+ }
2040
+ }, []);
1932
2041
  useEffect(() => {
1933
2042
  // Read fresh page from the mutable slot context ref chain.
1934
2043
  // The slot context uses a stable ref that is mutated in-place (see editorSlotContext.ts),
@@ -1949,11 +2058,19 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
1949
2058
  const loadHistory = useDebouncedCallback(async () => {
1950
2059
  if (!sessionId)
1951
2060
  return;
1952
- const result = await getEditHistory({ sessionId });
2061
+ const requestedLimit = GLOBAL_SESSION_HISTORY_LIMIT;
2062
+ const result = await getEditHistoryWithLoading({
2063
+ sessionId,
2064
+ limit: requestedLimit + 1,
2065
+ });
1953
2066
  if (handleErrorResult(result, ui, state))
1954
2067
  return;
2068
+ const nextOperations = normalizeEditHistoryPayload(result.data);
2069
+ const limitedOperations = nextOperations.slice(0, requestedLimit);
2070
+ setGlobalHistoryLimit(requestedLimit);
2071
+ setCanLoadMoreHistory(nextOperations.length > requestedLimit);
1955
2072
  setEditHistory((prev) => {
1956
- const next = normalizeEditHistoryPayload(result.data);
2073
+ const next = limitedOperations;
1957
2074
  if (!prev.length)
1958
2075
  return sortEditHistoryByDateDesc(next);
1959
2076
  if (!next.length)
@@ -2004,7 +2121,7 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
2004
2121
  return sortEditHistoryByDateDesc(merged);
2005
2122
  });
2006
2123
  }, 600);
2007
- const refreshHistory = useCallback(async (mode, filterBySession, filterByLanguage) => {
2124
+ const refreshHistory = useCallback(async (mode, filterBySession, filterByLanguage, historyLimitOverride, loadingMode = "initial") => {
2008
2125
  const currentMode = mode || historyMode;
2009
2126
  // Use showOnlyMyChanges state if filterBySession not explicitly provided
2010
2127
  const shouldFilterBySession = filterBySession !== undefined ? filterBySession : showOnlyMyChanges;
@@ -2045,14 +2162,16 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
2045
2162
  if (currentMode === "global") {
2046
2163
  // Global mode: optionally filter by session and/or language
2047
2164
  const currentLanguage = item?.descriptor?.language || currentItemDescriptor?.language;
2048
- const result = await getEditHistory({
2165
+ const requestedLimit = historyLimitOverride ??
2166
+ getInitialGlobalHistoryLimit(shouldFilterBySession);
2167
+ const result = await getEditHistoryWithLoading({
2049
2168
  sessionId: shouldFilterBySession ? sessionId : undefined,
2050
- limit: shouldFilterBySession ? 100 : 500,
2169
+ limit: requestedLimit + 1,
2051
2170
  language: shouldFilterByLanguage && currentLanguage
2052
2171
  ? currentLanguage
2053
2172
  : undefined,
2054
2173
  query: historyQuery,
2055
- });
2174
+ }, loadingMode);
2056
2175
  if (handleErrorResult(result, ui, state)) {
2057
2176
  console.error("[EditorShell] Failed to load history:", result);
2058
2177
  return;
@@ -2060,8 +2179,12 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
2060
2179
  if (isStaleHistoryResponse()) {
2061
2180
  return;
2062
2181
  }
2182
+ const nextOperations = normalizeEditHistoryPayload(result.data);
2183
+ const limitedOperations = nextOperations.slice(0, requestedLimit);
2184
+ setGlobalHistoryLimit(requestedLimit);
2185
+ setCanLoadMoreHistory(nextOperations.length > requestedLimit);
2063
2186
  setEditHistory((prev) => {
2064
- const next = normalizeEditHistoryPayload(result.data);
2187
+ const next = limitedOperations;
2065
2188
  const scope = {
2066
2189
  mode: currentMode,
2067
2190
  filterBySession: shouldFilterBySession,
@@ -2130,19 +2253,24 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
2130
2253
  if (!currentItem) {
2131
2254
  console.warn(`[EditorShell] Cannot load ${currentMode} history: no item loaded`);
2132
2255
  setEditHistory([]);
2256
+ setCanLoadMoreHistory(false);
2133
2257
  return;
2134
2258
  }
2135
2259
  // For page-centric/timeline: fetch all versions (itemId + language only)
2136
2260
  // For current-version: fetch specific version (itemId + language + version)
2137
2261
  const itemFilter = currentMode === "page-centric" || currentMode === "timeline"
2138
- ? { id: currentItem.id, language: currentItem.language, version: 0 } // version 0 signals "all versions" to backend
2262
+ ? {
2263
+ id: currentItem.id,
2264
+ language: currentItem.language,
2265
+ version: 0,
2266
+ } // version 0 signals "all versions" to backend
2139
2267
  : currentItem;
2140
2268
  // Request item-scoped history, optionally filtered by session
2141
- const result = await getEditHistory({
2269
+ const result = await getEditHistoryWithLoading({
2142
2270
  item: itemFilter,
2143
2271
  sessionId: shouldFilterBySession ? sessionId : undefined,
2144
2272
  query: historyQuery,
2145
- });
2273
+ }, loadingMode);
2146
2274
  if (handleErrorResult(result, ui, state)) {
2147
2275
  console.error("[EditorShell] Failed to load item history:", result);
2148
2276
  return;
@@ -2150,6 +2278,7 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
2150
2278
  if (isStaleHistoryResponse()) {
2151
2279
  return;
2152
2280
  }
2281
+ setCanLoadMoreHistory(false);
2153
2282
  let operations = normalizeEditHistoryPayload(result.data);
2154
2283
  // Client-side version filtering for current-version mode
2155
2284
  if (currentMode === "current-version") {
@@ -2232,10 +2361,26 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
2232
2361
  historySearchQuery,
2233
2362
  item,
2234
2363
  currentItemDescriptor,
2364
+ getEditHistoryWithLoading,
2235
2365
  matchesHistoryScope,
2236
2366
  normalizeEditHistoryPayload,
2237
2367
  sortEditHistoryByDateDesc,
2238
2368
  ]);
2369
+ const loadMoreHistory = useCallback(async () => {
2370
+ if (historyMode !== "global" || isHistoryLoading || isHistoryLoadingMore) {
2371
+ return;
2372
+ }
2373
+ const nextLimit = globalHistoryLimit + getGlobalHistoryLoadMoreIncrement(showOnlyMyChanges);
2374
+ await refreshHistory("global", showOnlyMyChanges, filterByCurrentLanguage, nextLimit, "more");
2375
+ }, [
2376
+ filterByCurrentLanguage,
2377
+ globalHistoryLimit,
2378
+ historyMode,
2379
+ isHistoryLoading,
2380
+ isHistoryLoadingMore,
2381
+ refreshHistory,
2382
+ showOnlyMyChanges,
2383
+ ]);
2239
2384
  // Debounced history refresh to avoid hammering `/parhelia/editHistory` on rapid UI changes.
2240
2385
  const debouncedRefreshHistory = useDebouncedCallback((mode) => {
2241
2386
  void refreshHistory(mode);
@@ -2289,11 +2434,14 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
2289
2434
  // from being displayed while the new data is loading
2290
2435
  if (prevHistoryModeRef.current !== historyMode) {
2291
2436
  setEditHistory([]);
2437
+ setCanLoadMoreHistory(false);
2292
2438
  prevHistoryModeRef.current = historyMode;
2293
2439
  }
2294
2440
  // Cancel any in-flight scheduled refresh before deciding what to do next.
2295
2441
  debouncedRefreshHistoryRef.current.cancel();
2296
2442
  if (historyMode === "global" && sessionId) {
2443
+ setGlobalHistoryLimit(getInitialGlobalHistoryLimit(showOnlyMyChanges));
2444
+ setCanLoadMoreHistory(false);
2297
2445
  // Use refreshHistory for immediate load on first initialization; debounce thereafter.
2298
2446
  if (!historyInitialLoadDoneRef.current) {
2299
2447
  historyInitialLoadDoneRef.current = true;
@@ -2304,6 +2452,7 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
2304
2452
  }
2305
2453
  }
2306
2454
  else if (historyMode !== "global" && currentItemDescriptor) {
2455
+ setCanLoadMoreHistory(false);
2307
2456
  // Always load immediately for page-centric/current-version/timeline so we don't show
2308
2457
  // an empty history list for the debounce window (e.g. 600ms). The effect only runs on
2309
2458
  // mode or item id/lang/version change, not on every keystroke, so this avoids flaky
@@ -2316,6 +2465,7 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
2316
2465
  else if (historyMode !== "global" && !currentItemDescriptor) {
2317
2466
  // Clear history if no item loaded in page-centric modes
2318
2467
  setEditHistory([]);
2468
+ setCanLoadMoreHistory(false);
2319
2469
  }
2320
2470
  // Note: refreshHistory and debouncedRefreshHistory are accessed via refs to avoid
2321
2471
  // re-running this effect when contentEditorItem changes (which would happen on every keystroke).
@@ -3150,9 +3300,9 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
3150
3300
  requestQuota: requestQuotaAndUpdate,
3151
3301
  sendClientInfo,
3152
3302
  setSocketDiagnostics,
3153
- enableWebSocketTransport: parheliaSettings?.enableWebSocketTransport ?? true,
3154
- enableSseFallback: parheliaSettings?.enableSseFallback ?? true,
3155
- transportSettingsReady: parheliaSettingsLoaded === true,
3303
+ enableWebSocketTransport: effectiveParheliaSettings?.enableWebSocketTransport ?? true,
3304
+ enableSseFallback: effectiveParheliaSettings?.enableSseFallback ?? true,
3305
+ transportSettingsReady: effectiveParheliaSettingsLoaded === true,
3156
3306
  });
3157
3307
  useEffect(() => {
3158
3308
  const hasMySession = activeSessions.some((s) => s.sessionId === sessionId);
@@ -4692,6 +4842,10 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
4692
4842
  setHistorySearchQuery,
4693
4843
  refreshHistory,
4694
4844
  isRefreshing,
4845
+ isHistoryLoading,
4846
+ canLoadMoreHistory,
4847
+ isHistoryLoadingMore,
4848
+ loadMoreHistory,
4695
4849
  activeSessions,
4696
4850
  remoteCarets,
4697
4851
  unlockField: async () => {
@@ -4950,7 +5104,7 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
4950
5104
  showEditorFormHint,
4951
5105
  dismissEditorFormHint,
4952
5106
  editorFormToggleButtonRef,
4953
- showMinimap,
5107
+ showMinimap: effectiveShowMinimap,
4954
5108
  setShowMinimap: handleSetShowMinimap,
4955
5109
  showHelpTerminal,
4956
5110
  setShowHelpTerminal: handleSetShowHelpTerminal,
@@ -4979,7 +5133,7 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
4979
5133
  webSocketMessages,
4980
5134
  clearWebSocketMessages: () => setWebSocketMessages([]),
4981
5135
  userInfo: userInfo,
4982
- parheliaSettings,
5136
+ parheliaSettings: effectiveParheliaSettings,
4983
5137
  setUserPreferences,
4984
5138
  currentWizardId,
4985
5139
  setCurrentWizardId,
@@ -5094,9 +5248,13 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
5094
5248
  showResolvedComments,
5095
5249
  reviews,
5096
5250
  userInfo,
5097
- parheliaSettings,
5251
+ effectiveParheliaSettings,
5098
5252
  setUserPreferences,
5099
5253
  isRefreshing,
5254
+ isHistoryLoading,
5255
+ canLoadMoreHistory,
5256
+ isHistoryLoadingMore,
5257
+ loadMoreHistory,
5100
5258
  favorites,
5101
5259
  loadFavorites,
5102
5260
  refreshFavorites,
@@ -5143,7 +5301,7 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
5143
5301
  showEditorFormHint,
5144
5302
  dismissEditorFormHint,
5145
5303
  editorFormToggleButtonRef,
5146
- showMinimap,
5304
+ effectiveShowMinimap,
5147
5305
  handleSetShowMinimap,
5148
5306
  showHelpTerminal,
5149
5307
  toggleHelpTerminal,