saltfish 0.3.45 → 0.3.47

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.
@@ -2460,8 +2460,7 @@ class PlaylistValidator {
2460
2460
  return { isValid: false, error: "Playlist not found in backend list" };
2461
2461
  }
2462
2462
  const hasTriggers = (foundPlaylist == null ? void 0 : foundPlaylist.hasTriggers) ?? (foundPlaylist == null ? void 0 : foundPlaylist.autoStart) ?? false;
2463
- const wasTriggered = (options == null ? void 0 : options._triggeredByTriggerManager) === true;
2464
- if (hasTriggers && wasTriggered) {
2463
+ if (hasTriggers) {
2465
2464
  const triggerValidation = await this.validateTriggerConditions(
2466
2465
  playlistId,
2467
2466
  foundPlaylist,
@@ -2535,12 +2534,14 @@ class PlaylistValidator {
2535
2534
  const watchedPlaylists = ((_a = currentStore.userData) == null ? void 0 : _a.watchedPlaylists) || {};
2536
2535
  const hasTriggers = foundPlaylist.hasTriggers ?? foundPlaylist.autoStart ?? false;
2537
2536
  const playlistData = watchedPlaylists[playlistId];
2538
- if (hasTriggers && ((_b = foundPlaylist.triggers) == null ? void 0 : _b.once) && playlistData && (playlistData.status === "completed" || playlistData.status === "dismissed")) {
2539
- info(`Playlist ${playlistId} has hasTriggers enabled with once:true and has already been ${playlistData.status}. Skipping playlist start.`, {
2537
+ const maxVisits = (_b = foundPlaylist.triggers) == null ? void 0 : _b.maxVisits;
2538
+ const visitCount = (playlistData == null ? void 0 : playlistData.visitCount) ?? 0;
2539
+ if (hasTriggers && maxVisits !== null && maxVisits !== void 0 && visitCount >= maxVisits) {
2540
+ info(`Playlist ${playlistId} has hasTriggers enabled with maxVisits:${maxVisits} and user has ${visitCount} visits. Skipping playlist start.`, {
2540
2541
  watchedPlaylists,
2541
2542
  triggers: foundPlaylist.triggers
2542
2543
  });
2543
- return { isValid: false, error: `Playlist already ${playlistData.status} with once=true policy` };
2544
+ return { isValid: false, error: `Playlist visit limit reached (${visitCount}/${maxVisits})` };
2544
2545
  }
2545
2546
  return { isValid: true };
2546
2547
  }
@@ -9664,7 +9665,7 @@ class TriggerManager {
9664
9665
  log(`TriggerManager: Registered ${this.triggeredPlaylists.length} playlists with triggers`);
9665
9666
  this.triggeredPlaylists.forEach((playlist) => {
9666
9667
  var _a, _b, _c, _d;
9667
- log(`TriggerManager: Registered trigger for playlist ${playlist.id} - URL: ${(_a = playlist.triggers) == null ? void 0 : _a.url}, ElementClick: ${(_b = playlist.triggers) == null ? void 0 : _b.elementClicked}, ElementVisible: ${(_c = playlist.triggers) == null ? void 0 : _c.elementVisible}, Once: ${(_d = playlist.triggers) == null ? void 0 : _d.once}`);
9668
+ log(`TriggerManager: Registered trigger for playlist ${playlist.id} - URL: ${(_a = playlist.triggers) == null ? void 0 : _a.url}, ElementClick: ${(_b = playlist.triggers) == null ? void 0 : _b.elementClicked}, ElementVisible: ${(_c = playlist.triggers) == null ? void 0 : _c.elementVisible}, MaxVisits: ${(_d = playlist.triggers) == null ? void 0 : _d.maxVisits}`);
9668
9669
  });
9669
9670
  this.setupElementClickListeners();
9670
9671
  this.setupElementVisibleObservers();
@@ -9702,7 +9703,6 @@ class TriggerManager {
9702
9703
  * @param playlist - The playlist to evaluate triggers for
9703
9704
  */
9704
9705
  evaluatePlaylistTrigger(playlist) {
9705
- var _a, _b, _c;
9706
9706
  if (!playlist.triggers) {
9707
9707
  return;
9708
9708
  }
@@ -9716,15 +9716,16 @@ class TriggerManager {
9716
9716
  return;
9717
9717
  }
9718
9718
  const conditions = [];
9719
- const onceCondition = this.evaluateOnceCondition(triggers.once, playlistId, ((_a = store.userData) == null ? void 0 : _a.watchedPlaylists) || {});
9720
- conditions.push(onceCondition);
9719
+ const watchedPlaylists = this.getWatchedPlaylists();
9720
+ const maxVisitsCondition = this.evaluateMaxVisitsCondition(triggers.maxVisits, playlistId, watchedPlaylists);
9721
+ conditions.push(maxVisitsCondition);
9721
9722
  const urlCondition = this.evaluateURLCondition(triggers);
9722
9723
  conditions.push(urlCondition);
9723
9724
  log(`TriggerManager: URL condition for playlist ${playlistId}: ${urlCondition} (pattern: ${triggers.url})`);
9724
- const playlistSeenCondition = this.evaluatePlaylistSeenCondition(triggers.playlistSeen, ((_b = store.userData) == null ? void 0 : _b.watchedPlaylists) || {});
9725
+ const playlistSeenCondition = this.evaluatePlaylistSeenCondition(triggers.playlistSeen, watchedPlaylists);
9725
9726
  conditions.push(playlistSeenCondition);
9726
9727
  log(`TriggerManager: PlaylistSeen condition for playlist ${playlistId}: ${playlistSeenCondition} (required: ${JSON.stringify(triggers.playlistSeen)})`);
9727
- const playlistNotSeenCondition = this.evaluatePlaylistNotSeenCondition(triggers.playlistNotSeen, ((_c = store.userData) == null ? void 0 : _c.watchedPlaylists) || {});
9728
+ const playlistNotSeenCondition = this.evaluatePlaylistNotSeenCondition(triggers.playlistNotSeen, watchedPlaylists);
9728
9729
  conditions.push(playlistNotSeenCondition);
9729
9730
  log(`TriggerManager: PlaylistNotSeen condition for playlist ${playlistId}: ${playlistNotSeenCondition} (forbidden: ${JSON.stringify(triggers.playlistNotSeen)})`);
9730
9731
  const elementClickedCondition = this.evaluateElementClickCondition(triggers.elementClicked);
@@ -9743,17 +9744,43 @@ class TriggerManager {
9743
9744
  }
9744
9745
  }
9745
9746
  /**
9746
- * Evaluates the 'once' condition for a playlist
9747
- * @param once - Whether playlist should only trigger once per user
9747
+ * Gets watched playlists from backend userData or localStorage (for anonymous users)
9748
+ * @returns WatchedPlaylists object
9749
+ */
9750
+ getWatchedPlaylists() {
9751
+ var _a, _b;
9752
+ const store = getSaltfishStore();
9753
+ if (((_a = store.userData) == null ? void 0 : _a.watchedPlaylists) && Object.keys(store.userData.watchedPlaylists).length > 0) {
9754
+ return store.userData.watchedPlaylists;
9755
+ }
9756
+ const storageManager2 = StorageManager.getInstance();
9757
+ const progressData = storageManager2.getProgress((_b = store.user) == null ? void 0 : _b.id);
9758
+ if (!progressData) {
9759
+ return {};
9760
+ }
9761
+ const watchedPlaylists = {};
9762
+ for (const playlistId of Object.keys(progressData)) {
9763
+ watchedPlaylists[playlistId] = {
9764
+ status: "in_progress",
9765
+ timestamp: Date.now()
9766
+ };
9767
+ }
9768
+ log(`TriggerManager: Built watchedPlaylists from localStorage: ${JSON.stringify(Object.keys(watchedPlaylists))}`);
9769
+ return watchedPlaylists;
9770
+ }
9771
+ /**
9772
+ * Evaluates the 'maxVisits' condition for a playlist
9773
+ * @param maxVisits - Maximum number of times user can see this playlist (null = unlimited)
9748
9774
  * @param playlistId - The playlist ID to check
9749
9775
  * @param watchedPlaylists - User's watched playlists data
9750
9776
  */
9751
- evaluateOnceCondition(once, playlistId, watchedPlaylists) {
9752
- if (!once) {
9777
+ evaluateMaxVisitsCondition(maxVisits, playlistId, watchedPlaylists) {
9778
+ if (maxVisits === null) {
9753
9779
  return true;
9754
9780
  }
9755
- const hasWatched = watchedPlaylists && watchedPlaylists[playlistId];
9756
- return !hasWatched;
9781
+ const playlistData = watchedPlaylists && watchedPlaylists[playlistId];
9782
+ const visitCount = (playlistData == null ? void 0 : playlistData.visitCount) ?? 0;
9783
+ return visitCount < maxVisits;
9757
9784
  }
9758
9785
  /**
9759
9786
  * Normalizes a URL by removing trailing slash (unless it's the root path)
@@ -10660,14 +10687,19 @@ class PlaylistManager extends EventSubscriberManager {
10660
10687
  const store = getSaltfishStore();
10661
10688
  const currentUserData = store.userData || {};
10662
10689
  const currentWatchedPlaylists = currentUserData.watchedPlaylists || {};
10690
+ const existingPlaylistData = currentWatchedPlaylists[playlistId];
10691
+ const previousStatus = existingPlaylistData == null ? void 0 : existingPlaylistData.status;
10692
+ const currentVisitCount = (existingPlaylistData == null ? void 0 : existingPlaylistData.visitCount) ?? 0;
10693
+ const shouldIncrementVisitCount = (status === "completed" || status === "dismissed") && previousStatus !== status;
10663
10694
  const updatedPlaylistData = {
10664
10695
  status,
10665
10696
  // Don't save currentStepId for completed playlists - they should restart from beginning
10666
10697
  currentStepId: status === "completed" ? null : currentStepId || store.currentStepId || null,
10667
10698
  timestamp: Date.now(),
10668
10699
  // Use timestamp for consistency with checkAndResumeInProgressPlaylist
10669
- lastProgressAt: Date.now()
10700
+ lastProgressAt: Date.now(),
10670
10701
  // Keep for backward compatibility
10702
+ visitCount: shouldIncrementVisitCount ? currentVisitCount + 1 : currentVisitCount
10671
10703
  };
10672
10704
  const updatedWatchedPlaylists = {
10673
10705
  ...currentWatchedPlaylists,
@@ -10726,13 +10758,18 @@ class PlaylistManager extends EventSubscriberManager {
10726
10758
  if (!anonymousUserData.watchedPlaylists) {
10727
10759
  anonymousUserData.watchedPlaylists = {};
10728
10760
  }
10761
+ const existingPlaylistData = anonymousUserData.watchedPlaylists[playlistId];
10762
+ const previousStatus = existingPlaylistData == null ? void 0 : existingPlaylistData.status;
10763
+ const currentVisitCount = (existingPlaylistData == null ? void 0 : existingPlaylistData.visitCount) ?? 0;
10764
+ const shouldIncrementVisitCount = (status === "completed" || status === "dismissed") && previousStatus !== status;
10729
10765
  anonymousUserData.watchedPlaylists[playlistId] = {
10730
10766
  status,
10731
10767
  currentStepId: currentStepId || null,
10732
10768
  timestamp: Date.now(),
10733
10769
  // Use timestamp for consistency with checkAndResumeInProgressPlaylist
10734
- lastProgressAt: Date.now()
10770
+ lastProgressAt: Date.now(),
10735
10771
  // Keep for backward compatibility
10772
+ visitCount: shouldIncrementVisitCount ? currentVisitCount + 1 : currentVisitCount
10736
10773
  };
10737
10774
  anonymousUserData.timestamp = Date.now();
10738
10775
  this.storageManager.setAnonymousUserData(anonymousUserData);
@@ -12001,7 +12038,7 @@ const SaltfishPlayer$1 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.de
12001
12038
  __proto__: null,
12002
12039
  SaltfishPlayer
12003
12040
  }, Symbol.toStringTag, { value: "Module" }));
12004
- const version = "0.3.45";
12041
+ const version = "0.3.47";
12005
12042
  const packageJson = {
12006
12043
  version
12007
12044
  };