diff --git a/shaarli-pro/css/style.css b/shaarli-pro/css/style.css
index 640f63b..8ebec5b 100644
--- a/shaarli-pro/css/style.css
+++ b/shaarli-pro/css/style.css
@@ -3093,3 +3093,23 @@ select:focus {
font-size: 14px;
}
+
+/* Filter Badge Indicator */
+.filter-badge {
+ position: absolute;
+ top: 2px;
+ right: 2px;
+ width: 8px;
+ height: 8px;
+ background: #ef4444;
+ border-radius: 50%;
+ border: 2px solid var(--header-bg);
+}
+
+.header-action-btn {
+ position: relative;
+}
+
+.header-action-btn.has-active-filter {
+ background: rgba(239, 68, 68, 0.2);
+}
diff --git a/shaarli-pro/js/script.js b/shaarli-pro/js/script.js
index 9250a32..177b0f6 100644
--- a/shaarli-pro/js/script.js
+++ b/shaarli-pro/js/script.js
@@ -410,15 +410,7 @@ document.addEventListener('DOMContentLoaded', () => {
let basePath = (typeof shaarli !== 'undefined' && shaarli.basePath) ? shaarli.basePath : '';
let url = basePath + '/';
- // Save filter state to localStorage before navigation
- const filterState = {
- private: isPrivate,
- public: isPublic,
- untagged: isUntagged,
- timestamp: Date.now()
- };
- localStorage.setItem('shaarliFilterState', JSON.stringify(filterState));
- console.log('[Filter] Saved filter state:', filterState);
+ console.log('[Filter] Applying filters - private:', isPrivate, 'public:', isPublic, 'untagged:', isUntagged);
// Build the URL based on selected filters using the correct Shaarli admin paths
if (isPrivate && isUntagged) {
@@ -430,22 +422,18 @@ document.addEventListener('DOMContentLoaded', () => {
} else if (isPublic) {
url = basePath + '/admin/visibility/public';
} else if (isUntagged) {
- url = basePath + '/untagged-only';
- } else {
- // No filter selected - clear the state
- localStorage.removeItem('shaarliFilterState');
+ url = basePath + '/?searchtags=';
}
+ // else: no filter, url stays as basePath + '/'
console.log('[Filter] Navigating to:', url);
window.location.href = url;
}
- // Clear filters function
- function clearFilters() {
- localStorage.removeItem('shaarliFilterState');
- if (filterPrivate) filterPrivate.checked = false;
- if (filterPublic) filterPublic.checked = false;
- if (filterUntagged) filterUntagged.checked = false;
+ // Clear all filters and go to home
+ function clearAllFilters() {
+ const basePath = (typeof shaarli !== 'undefined' && shaarli.basePath) ? shaarli.basePath : '';
+ window.location.href = basePath + '/';
}
// Private and public are mutually exclusive
@@ -467,34 +455,24 @@ document.addEventListener('DOMContentLoaded', () => {
applyFilters();
});
- // Initialize filter states from localStorage (since Shaarli redirects after applying filters)
+ // Initialize filter states from URL (detect current filter state from page URL)
(function initFilterStates() {
console.log('[Filter Debug] ========================================');
- // Try to read filter state from localStorage
- let savedState = null;
- try {
- const savedJson = localStorage.getItem('shaarliFilterState');
- if (savedJson) {
- savedState = JSON.parse(savedJson);
- console.log('[Filter Debug] Found saved filter state:', savedState);
+ // Detect filter state from current URL path
+ const currentPath = window.location.pathname;
+ const currentSearch = window.location.search;
- // Check if state is not too old (30 seconds max)
- const age = Date.now() - (savedState.timestamp || 0);
- if (age > 30000) {
- console.log('[Filter Debug] Saved state is too old, ignoring');
- localStorage.removeItem('shaarliFilterState');
- savedState = null;
- }
- }
- } catch (e) {
- console.log('[Filter Debug] Error reading saved state:', e);
- }
+ // Detect visibility filter from URL path
+ let isPrivateActive = currentPath.includes('/visibility/private') || currentPath.includes('/admin/visibility/private');
+ let isPublicActive = currentPath.includes('/visibility/public') || currentPath.includes('/admin/visibility/public');
- // Determine active filters from saved state
- let isPrivateActive = savedState?.private || false;
- let isPublicActive = savedState?.public || false;
- let isUntaggedActive = savedState?.untagged || false;
+ // Detect untagged filter
+ let isUntaggedActive = currentPath.includes('/untagged-only') ||
+ (currentSearch.includes('searchtags=') && !currentSearch.match(/searchtags=[^&]+/));
+
+ console.log('[Filter Debug] URL path:', currentPath);
+ console.log('[Filter Debug] URL search:', currentSearch);
console.log('[Filter Debug] isPrivateActive:', isPrivateActive);
console.log('[Filter Debug] isPublicActive:', isPublicActive);
@@ -534,24 +512,31 @@ document.addEventListener('DOMContentLoaded', () => {
// Create and display the filter info banner
if (hasActiveFilter && !document.getElementById('filter-info-banner')) {
- // Build the message - describe the active filter without count
+ // Get result count from page
+ let resultCount = '';
+ const pagingStats = document.querySelector('.paging-stats strong:last-child');
+ if (pagingStats) {
+ resultCount = pagingStats.textContent;
+ }
+
+ // Build the message with result count like "X results with status private"
let filterParts = [];
if (isPrivateActive) {
- filterParts.push('private links');
+ filterParts.push('with status private');
} else if (isPublicActive) {
- filterParts.push('public links');
+ filterParts.push('with status public');
}
if (isUntaggedActive) {
if (filterParts.length > 0) {
- filterParts.push('without tags');
+ filterParts.push('and untagged');
} else {
- filterParts.push('links without tags');
+ filterParts.push('untagged');
}
}
- let message = 'Showing ' + filterParts.join(' ');
+ let message = resultCount ? resultCount + ' results ' + filterParts.join(' ') : 'Showing ' + filterParts.join(' ') + ' links';
console.log('[Filter Debug] filterParts:', filterParts);
console.log('[Filter Debug] message:', message);
@@ -599,8 +584,7 @@ document.addEventListener('DOMContentLoaded', () => {
// Add click handler to clear button
document.getElementById('filter-clear-btn')?.addEventListener('click', () => {
- localStorage.removeItem('shaarliFilterState');
- console.log('[Filter] Cleared filter state from localStorage');
+ console.log('[Filter] Clear button clicked, navigating to home');
window.location.href = basePath + '/';
});
}