@shaxpir/duiduidui-models 1.37.4 → 1.38.0

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.
@@ -96,38 +96,28 @@ export declare class Device extends Content {
96
96
  */
97
97
  get searchHistory(): SearchHistory;
98
98
  /**
99
- * Gets the current search state (at the cursor position), or undefined if history is empty.
99
+ * Gets the current search state (top of stack), or undefined if history is empty.
100
100
  */
101
101
  get currentSearchState(): SearchState | undefined;
102
102
  /**
103
103
  * Returns true if back navigation is possible.
104
- * Skips over empty entries to find a non-empty one.
104
+ * Requires at least two entries with a non-empty entry below the top.
105
105
  */
106
106
  get canGoBack(): boolean;
107
- /**
108
- * Returns true if forward navigation is possible.
109
- * Skips over empty entries to find a non-empty one.
110
- */
111
- get canGoForward(): boolean;
112
107
  /**
113
108
  * Pushes a new search state onto the history stack.
114
- * - Deduplicates: won't push if identical to current state
115
- * - Discards forward history (entries after cursor)
109
+ * - Deduplicates: won't push if identical to current top
116
110
  * - Respects max entries limit (drops oldest when full)
117
111
  *
118
- * @returns The new search state at the cursor, or undefined if deduplicated
112
+ * @returns The new search state, or undefined if deduplicated
119
113
  */
120
114
  pushSearchState(state: SearchState): SearchState | undefined;
121
115
  /**
122
- * Navigates back in search history, skipping over empty entries.
123
- * @returns The search state at the new cursor position, or undefined if can't go back
116
+ * Navigates back in search history by popping the top entry.
117
+ * Skips over empty entries to find a non-empty one.
118
+ * @returns The search state at the new top of stack, or undefined if can't go back
124
119
  */
125
120
  goBack(): SearchState | undefined;
126
- /**
127
- * Navigates forward in search history, skipping over empty entries.
128
- * @returns The search state at the new cursor position, or undefined if can't go forward
129
- */
130
- goForward(): SearchState | undefined;
131
121
  /**
132
122
  * Clears the entire search history stack.
133
123
  */
@@ -320,40 +320,25 @@ class Device extends Content_1.Content {
320
320
  return this.payload.search_history;
321
321
  }
322
322
  /**
323
- * Gets the current search state (at the cursor position), or undefined if history is empty.
323
+ * Gets the current search state (top of stack), or undefined if history is empty.
324
324
  */
325
325
  get currentSearchState() {
326
326
  this.checkDisposed("Device.currentSearchState");
327
327
  const history = this.searchHistory;
328
- if (history.cursor < 0 || history.cursor >= history.entries.length) {
328
+ if (history.entries.length === 0) {
329
329
  return undefined;
330
330
  }
331
- return history.entries[history.cursor];
331
+ return history.entries[history.entries.length - 1];
332
332
  }
333
333
  /**
334
334
  * Returns true if back navigation is possible.
335
- * Skips over empty entries to find a non-empty one.
335
+ * Requires at least two entries with a non-empty entry below the top.
336
336
  */
337
337
  get canGoBack() {
338
338
  this.checkDisposed("Device.canGoBack");
339
339
  const history = this.searchHistory;
340
- // Look for any non-empty entry before the cursor
341
- for (let i = history.cursor - 1; i >= 0; i--) {
342
- if (!(0, SearchState_1.isEmptySearchState)(history.entries[i])) {
343
- return true;
344
- }
345
- }
346
- return false;
347
- }
348
- /**
349
- * Returns true if forward navigation is possible.
350
- * Skips over empty entries to find a non-empty one.
351
- */
352
- get canGoForward() {
353
- this.checkDisposed("Device.canGoForward");
354
- const history = this.searchHistory;
355
- // Look for any non-empty entry after the cursor
356
- for (let i = history.cursor + 1; i < history.entries.length; i++) {
340
+ // Look for any non-empty entry below the top of the stack
341
+ for (let i = history.entries.length - 2; i >= 0; i--) {
357
342
  if (!(0, SearchState_1.isEmptySearchState)(history.entries[i])) {
358
343
  return true;
359
344
  }
@@ -362,48 +347,39 @@ class Device extends Content_1.Content {
362
347
  }
363
348
  /**
364
349
  * Pushes a new search state onto the history stack.
365
- * - Deduplicates: won't push if identical to current state
366
- * - Discards forward history (entries after cursor)
350
+ * - Deduplicates: won't push if identical to current top
367
351
  * - Respects max entries limit (drops oldest when full)
368
352
  *
369
- * @returns The new search state at the cursor, or undefined if deduplicated
353
+ * @returns The new search state, or undefined if deduplicated
370
354
  */
371
355
  pushSearchState(state) {
372
356
  this.checkDisposed("Device.pushSearchState");
373
357
  const history = this.searchHistory;
374
- // Deduplicate: don't push if identical to current state
375
- const currentState = history.cursor >= 0 && history.cursor < history.entries.length
376
- ? history.entries[history.cursor]
358
+ // Deduplicate: don't push if identical to current top
359
+ const currentState = history.entries.length > 0
360
+ ? history.entries[history.entries.length - 1]
377
361
  : undefined;
378
362
  if ((0, SearchState_1.areSearchStatesEqual)(state, currentState)) {
379
363
  return undefined;
380
364
  }
381
- // Build new entries array
382
- // Discard any entries after the current cursor (browser-style)
383
- let newEntries = history.cursor >= 0
384
- ? history.entries.slice(0, history.cursor + 1)
385
- : [];
386
- // Add the new state
387
- newEntries.push(state);
365
+ let newEntries = [...history.entries, state];
388
366
  // Enforce max entries limit - drop oldest entries
389
- let newCursor = newEntries.length - 1;
390
367
  if (newEntries.length > SearchState_1.SEARCH_HISTORY_MAX_ENTRIES) {
391
368
  const overflow = newEntries.length - SearchState_1.SEARCH_HISTORY_MAX_ENTRIES;
392
369
  newEntries = newEntries.slice(overflow);
393
- newCursor = newEntries.length - 1;
394
370
  }
395
371
  // Commit the update
396
372
  const batch = new Operation_1.BatchOperation(this);
397
373
  batch.setPathValue(['payload', 'search_history'], {
398
374
  entries: newEntries,
399
- cursor: newCursor
400
375
  });
401
376
  batch.commit();
402
377
  return state;
403
378
  }
404
379
  /**
405
- * Navigates back in search history, skipping over empty entries.
406
- * @returns The search state at the new cursor position, or undefined if can't go back
380
+ * Navigates back in search history by popping the top entry.
381
+ * Skips over empty entries to find a non-empty one.
382
+ * @returns The search state at the new top of stack, or undefined if can't go back
407
383
  */
408
384
  goBack() {
409
385
  this.checkDisposed("Device.goBack");
@@ -411,41 +387,22 @@ class Device extends Content_1.Content {
411
387
  return undefined;
412
388
  }
413
389
  const history = this.searchHistory;
414
- // Find the first non-empty entry before the cursor
415
- let newCursor = history.cursor - 1;
416
- while (newCursor >= 0 && (0, SearchState_1.isEmptySearchState)(history.entries[newCursor])) {
417
- newCursor--;
418
- }
419
- if (newCursor < 0) {
420
- return undefined;
421
- }
422
- const batch = new Operation_1.BatchOperation(this);
423
- batch.setPathValue(['payload', 'search_history', 'cursor'], newCursor);
424
- batch.commit();
425
- return history.entries[newCursor];
426
- }
427
- /**
428
- * Navigates forward in search history, skipping over empty entries.
429
- * @returns The search state at the new cursor position, or undefined if can't go forward
430
- */
431
- goForward() {
432
- this.checkDisposed("Device.goForward");
433
- if (!this.canGoForward) {
434
- return undefined;
435
- }
436
- const history = this.searchHistory;
437
- // Find the first non-empty entry after the cursor
438
- let newCursor = history.cursor + 1;
439
- while (newCursor < history.entries.length && (0, SearchState_1.isEmptySearchState)(history.entries[newCursor])) {
440
- newCursor++;
390
+ // Pop entries from the top until we find a non-empty one below
391
+ let newEntries = [...history.entries];
392
+ newEntries.pop(); // Remove current top
393
+ // Skip over any empty entries
394
+ while (newEntries.length > 0 && (0, SearchState_1.isEmptySearchState)(newEntries[newEntries.length - 1])) {
395
+ newEntries.pop();
441
396
  }
442
- if (newCursor >= history.entries.length) {
397
+ if (newEntries.length === 0) {
443
398
  return undefined;
444
399
  }
445
400
  const batch = new Operation_1.BatchOperation(this);
446
- batch.setPathValue(['payload', 'search_history', 'cursor'], newCursor);
401
+ batch.setPathValue(['payload', 'search_history'], {
402
+ entries: newEntries,
403
+ });
447
404
  batch.commit();
448
- return history.entries[newCursor];
405
+ return newEntries[newEntries.length - 1];
449
406
  }
450
407
  /**
451
408
  * Clears the entire search history stack.
@@ -21,20 +21,19 @@ export interface SearchState {
21
21
  */
22
22
  export declare const SEARCH_HISTORY_MAX_ENTRIES = 50;
23
23
  /**
24
- * Search history with browser-style back/forward navigation.
24
+ * Search history as a simple stack (push/pop).
25
25
  *
26
- * - `entries`: Stack of search states
27
- * - `cursor`: Current position in the stack (0-indexed)
26
+ * - `entries`: Stack of search states, current state is the last entry
28
27
  *
29
28
  * Navigation behavior:
30
- * - Back: decrements cursor (if cursor > 0)
31
- * - Forward: increments cursor (if cursor < entries.length - 1)
32
- * - New search: discards entries after cursor, pushes new entry, cursor moves to end
29
+ * - Back: pops the last entry, returns the new top
30
+ * - New search: pushes new entry onto the end
33
31
  * - Clear: empties the entire stack
34
32
  */
35
33
  export interface SearchHistory {
36
34
  entries: SearchState[];
37
- cursor: number;
35
+ /** @deprecated No longer used — current state is always the last entry. Kept for backwards compatibility with existing persisted data. */
36
+ cursor?: number;
38
37
  }
39
38
  /**
40
39
  * Creates an empty search history.
@@ -15,7 +15,6 @@ exports.SEARCH_HISTORY_MAX_ENTRIES = 50;
15
15
  function createEmptySearchHistory() {
16
16
  return {
17
17
  entries: [],
18
- cursor: -1
19
18
  };
20
19
  }
21
20
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@shaxpir/duiduidui-models",
3
- "version": "1.37.4",
3
+ "version": "1.38.0",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "https://github.com/shaxpir/duiduidui-models"