|
|
@@ -17,11 +17,14 @@ document.addEventListener("alpine:init", () => {
|
|
|
Alpine.data("playlistManager", () => ({
|
|
|
playlists: {},
|
|
|
currentIndices: {},
|
|
|
+ history: {},
|
|
|
+ sortedHistory: [],
|
|
|
openMenus: new Set(), // Track which menus are open
|
|
|
currentView: 'playlists', // Track current view: 'playlists' or 'history'
|
|
|
|
|
|
init() {
|
|
|
this.loadPlaylists();
|
|
|
+ this.loadHistory();
|
|
|
// Add document click handler to close menus
|
|
|
document.addEventListener('click', (e) => {
|
|
|
// If click is not on a more button or menu, close all menus
|
|
|
@@ -59,6 +62,80 @@ document.addEventListener("alpine:init", () => {
|
|
|
}
|
|
|
},
|
|
|
|
|
|
+ async loadHistory() {
|
|
|
+ try {
|
|
|
+ const result = await browser.storage.local.get("history");
|
|
|
+ console.log("LOAD HISTORY RESULT", result.history);
|
|
|
+ this.history = result.history || {};
|
|
|
+ this.sortHistoryByRecentInteraction();
|
|
|
+ } catch (error) {
|
|
|
+ console.error("Error loading history:", error);
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ sortHistoryByRecentInteraction() {
|
|
|
+ // Convert history object to array with video ID and sort by most recent interaction
|
|
|
+ this.sortedHistory = Object.entries(this.history)
|
|
|
+ .map(([videoId, videoData]) => {
|
|
|
+ const lastInteraction = videoData.history.length > 0
|
|
|
+ ? Math.max(...videoData.history.map(event => event.timestamp))
|
|
|
+ : 0;
|
|
|
+
|
|
|
+ // Pre-process events with formatted data for CSP compliance
|
|
|
+ const processedEvents = videoData.history
|
|
|
+ .slice()
|
|
|
+ .reverse()
|
|
|
+ .map((event, index) => ({
|
|
|
+ ...event,
|
|
|
+ formattedAction: this.formatActionName(event.action),
|
|
|
+ formattedPosition: `at ${this.formatVideoPosition(event.position)}`,
|
|
|
+ formattedTimestamp: this.formatTimestamp(event.timestamp),
|
|
|
+ uniqueKey: `${videoId}-${event.timestamp}-${index}`
|
|
|
+ }));
|
|
|
+
|
|
|
+ return {
|
|
|
+ videoId,
|
|
|
+ formattedVideoId: `(${videoId})`,
|
|
|
+ ...videoData,
|
|
|
+ lastInteraction,
|
|
|
+ processedEvents
|
|
|
+ };
|
|
|
+ })
|
|
|
+ .sort((a, b) => b.lastInteraction - a.lastInteraction);
|
|
|
+ },
|
|
|
+
|
|
|
+ formatTimestamp(timestamp) {
|
|
|
+ const date = new Date(timestamp);
|
|
|
+ const now = new Date();
|
|
|
+ const diffMs = now - date;
|
|
|
+ const diffMins = Math.floor(diffMs / (1000 * 60));
|
|
|
+ const diffHours = Math.floor(diffMs / (1000 * 60 * 60));
|
|
|
+ const diffDays = Math.floor(diffMs / (1000 * 60 * 60 * 24));
|
|
|
+
|
|
|
+ if (diffMins < 1) return 'Just now';
|
|
|
+ if (diffMins < 60) return `${diffMins} minute${diffMins > 1 ? 's' : ''} ago`;
|
|
|
+ if (diffHours < 24) return `${diffHours} hour${diffHours > 1 ? 's' : ''} ago`;
|
|
|
+ if (diffDays < 7) return `${diffDays} day${diffDays > 1 ? 's' : ''} ago`;
|
|
|
+
|
|
|
+ return date.toLocaleDateString() + ' ' + date.toLocaleTimeString([], {hour: '2-digit', minute:'2-digit'});
|
|
|
+ },
|
|
|
+
|
|
|
+ formatVideoPosition(seconds) {
|
|
|
+ const minutes = Math.floor(seconds / 60);
|
|
|
+ const remainingSeconds = Math.floor(seconds % 60);
|
|
|
+ return `${minutes}:${remainingSeconds.toString().padStart(2, '0')}`;
|
|
|
+ },
|
|
|
+
|
|
|
+ formatActionName(action) {
|
|
|
+ const actionMap = {
|
|
|
+ 'play': 'Started',
|
|
|
+ 'playing': 'Playing',
|
|
|
+ 'pause': 'Paused',
|
|
|
+ 'ended': 'Finished'
|
|
|
+ };
|
|
|
+ return actionMap[action] || action;
|
|
|
+ },
|
|
|
+
|
|
|
formatPlaylistName(name) {
|
|
|
// Convert "listening-1" to "Listening - 1"
|
|
|
return name
|
|
|
@@ -422,6 +499,7 @@ document.addEventListener("alpine:init", () => {
|
|
|
// View navigation methods
|
|
|
showHistory() {
|
|
|
this.currentView = 'history';
|
|
|
+ this.loadHistory(); // Refresh history data when switching to history view
|
|
|
},
|
|
|
|
|
|
showPlaylists() {
|
|
|
@@ -471,5 +549,12 @@ document.addEventListener("alpine:init", () => {
|
|
|
return this.currentView === 'playlists';
|
|
|
},
|
|
|
},
|
|
|
+
|
|
|
+ // History-specific bindings for CSP compliance
|
|
|
+ historyEmptyState: {
|
|
|
+ ["x-show"]() {
|
|
|
+ return this.sortedHistory.length === 0;
|
|
|
+ },
|
|
|
+ },
|
|
|
}));
|
|
|
});
|