diff --git a/links/templates/links/link_list.html b/links/templates/links/link_list.html index 22b4a5a..c380302 100644 --- a/links/templates/links/link_list.html +++ b/links/templates/links/link_list.html @@ -208,6 +208,10 @@ .apple-btn-primary:hover { background: var(--apple-blue-hover); color: #fff; } .apple-btn-danger { background: transparent; color: var(--apple-red); border: 1px solid rgba(255, 59, 48, 0.4); } .apple-btn-danger:hover { background: rgba(255, 59, 48, 0.08); } + .apple-btn-danger:disabled { + opacity: 0.45; color: var(--apple-gray); border-color: rgba(0, 0, 0, 0.12); + cursor: default; pointer-events: none; background: transparent; + } /* ---------- Link library (table) ---------- */ .library-header { @@ -579,7 +583,19 @@ /* ---------- Small screens ---------- */ @media (max-width: 640px) { .library-header { padding: 1.35rem 1.1rem 1rem; } - .library-footer { padding: 1rem 1.1rem 1.25rem; } + .library-footer { + position: sticky; bottom: 0; z-index: 5; + background: rgba(245, 245, 247, 0.88); + -webkit-backdrop-filter: blur(20px) saturate(180%); + backdrop-filter: blur(20px) saturate(180%); + border-top: 1px solid rgba(0, 0, 0, 0.05); + border-radius: 0 0 var(--apple-radius-lg) var(--apple-radius-lg); + margin: 0 -1.1rem -1.25rem; + padding: 0.7rem 1.1rem calc(0.7rem + env(safe-area-inset-bottom, 0px)); + } + /* Search takes the full row on mobile (it is the primary interaction) */ + .library-filter { flex: 1 1 100%; } + .library-filter input { width: 100%; height: 48px; font-size: 1rem; } .apple-table thead th, .apple-table tbody td { padding-left: 0.8rem; padding-right: 0.8rem; } .hero-stats { gap: 1.25rem; } .posts-panel-header { padding: 1.15rem 1.1rem 0.6rem; } @@ -965,7 +981,7 @@ {% endif %}
@@ -1406,6 +1422,7 @@ /* ---------- Load more links ---------- */ const loadMoreBtn = document.getElementById('load-more-links'); + const tbody = document.getElementById('links-table-body'); if (loadMoreBtn && tbody) { loadMoreBtn.addEventListener('click', function () { const offset = loadMoreBtn.dataset.offset; @@ -1444,6 +1461,8 @@ if (!selectionHint) return; const count = document.querySelectorAll('input[name="selected_links"]:checked').length; selectionHint.textContent = count > 0 ? count + ' {% trans "selected" %}' : ''; + const delBtn = document.getElementById('delete-selected-btn'); + if (delBtn) delBtn.disabled = count === 0; } if (selectAll) { diff --git a/links/views.py b/links/views.py index ab84216..17901a0 100644 --- a/links/views.py +++ b/links/views.py @@ -47,7 +47,7 @@ from .search_views import search_aliases, search logger = logging.getLogger(__name__) # Number of link rows rendered on the initial home page load / per "Load more" click. -LINKS_PAGE_SIZE = 50 +LINKS_PAGE_SIZE = 20 def _ordering_for(sort_by, order): @@ -74,14 +74,14 @@ class LinkListView(ListView): def get_queryset(self): queryset = super().get_queryset() - sort_by = self.request.GET.get('sort', 'click_count') - order = self.request.GET.get('order', 'asc') + sort_by = self.request.GET.get('sort', 'updated_at') + order = self.request.GET.get('order', 'desc') return queryset.order_by(_ordering_for(sort_by, order)) def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) - context['current_sort'] = self.request.GET.get('sort', 'click_count') - context['current_order'] = self.request.GET.get('order', 'asc') + context['current_sort'] = self.request.GET.get('sort', 'updated_at') + context['current_order'] = self.request.GET.get('order', 'desc') # Modern color palette colors = [ @@ -128,8 +128,8 @@ def load_more_links(request): """Return the next page of link rows (rendered as