diff options
| author | 2025-05-10 21:06:58 +0200 | |
|---|---|---|
| committer | 2025-05-10 21:06:58 +0200 | |
| commit | 84d4aeb9e613a70b53d87c62d07bb4c4635290c3 (patch) | |
| tree | 31c5144a7b40df5cefceb732abd7fe318dddc6d1 /p | |
| parent | 5f74634c8324affda1ceec0b81fc50021775c6e3 (diff) | |
Implement loading spinner for marking as favorite/read, read/unread (#7564)
* Implement loading spinner for marking as favorite
* Ensure that the correct previous icon gets set
* Remove delay
* Improve compatibility with various parsers
Co-authored-by: Alexandre Alapetite <alexandre@alapetite.fr>
* Support multiple icons (top, bottom)
* Remove preload for now
* Fix CSS, remove !important
* Implement read/unread and alt
* Ensure correct bookmark icon gets set after error
---------
Co-authored-by: Alexandre Alapetite <alexandre@alapetite.fr>
Diffstat (limited to 'p')
| -rw-r--r-- | p/scripts/main.js | 26 | ||||
| -rw-r--r-- | p/themes/Alternative-Dark/adark.css | 12 | ||||
| -rw-r--r-- | p/themes/Alternative-Dark/adark.rtl.css | 12 | ||||
| -rw-r--r-- | p/themes/Dark/dark.css | 12 | ||||
| -rw-r--r-- | p/themes/Dark/dark.rtl.css | 12 | ||||
| -rw-r--r-- | p/themes/Origine/origine.css | 4 | ||||
| -rw-r--r-- | p/themes/Origine/origine.rtl.css | 4 | ||||
| -rw-r--r-- | p/themes/icons/spinner.svg | 1 |
8 files changed, 83 insertions, 0 deletions
diff --git a/p/scripts/main.js b/p/scripts/main.js index 73ac27ddd..c0e31ef98 100644 --- a/p/scripts/main.js +++ b/p/scripts/main.js @@ -224,6 +224,10 @@ function send_mark_read_queue(queue, asRead, callback) { req.responseType = 'json'; req.onerror = function (e) { for (let i = queue.length - 1; i >= 0; i--) { + const div = document.getElementById('flux_' + queue[i]); + div.querySelectorAll('a.read > .icon').forEach(icon => { + icon.outerHTML = div.classList.contains('not_read') ? context.icons.unread : context.icons.read; + }); delete pending_entries['flux_' + queue[i]]; } badAjax(this.status == 403); @@ -315,6 +319,12 @@ function mark_read(div, only_not_read, asBatch) { } pending_entries[div.id] = true; + div.querySelectorAll('a.read > .icon').forEach(icon => { + icon.src = context.icons.spinner; + icon.alt = '⏳'; + icon.classList.add('spinner'); + }); + const asRead = div.classList.contains('not_read'); const entryId = div.id.replace(/^flux_/, ''); if (asRead && asBatch) { @@ -351,10 +361,26 @@ function mark_favorite(div) { } pending_entries[div.id] = true; + let originalIcon; + + div.querySelectorAll('a.bookmark > .icon').forEach(icon => { + originalIcon = { + src: icon.getAttribute('src'), + alt: icon.getAttribute('alt') + }; + icon.src = context.icons.spinner; + icon.alt = '⏳'; + icon.classList.add('spinner'); + }); + const req = new XMLHttpRequest(); req.open('POST', url, true); req.responseType = 'json'; req.onerror = function (e) { + div.querySelectorAll('a.bookmark > .icon').forEach(icon => { + icon.src = originalIcon.src; + icon.alt = originalIcon.alt; + }); delete pending_entries[div.id]; badAjax(this.status == 403); }; diff --git a/p/themes/Alternative-Dark/adark.css b/p/themes/Alternative-Dark/adark.css index fa0b45dec..7b8af5f41 100644 --- a/p/themes/Alternative-Dark/adark.css +++ b/p/themes/Alternative-Dark/adark.css @@ -274,6 +274,18 @@ th { box-shadow: none; } +.spinner { + filter: invert(1); +} + +a:hover > .spinner { + filter: invert(1) brightness(2); +} + +.flux .item.manage .read:hover .icon.spinner { + filter: invert(1) grayscale(0.8) brightness(1.7); +} + /*=== switches */ .switch.active { background-color: var(--contrast-background-color); diff --git a/p/themes/Alternative-Dark/adark.rtl.css b/p/themes/Alternative-Dark/adark.rtl.css index 5cabd1f24..147d05fcf 100644 --- a/p/themes/Alternative-Dark/adark.rtl.css +++ b/p/themes/Alternative-Dark/adark.rtl.css @@ -274,6 +274,18 @@ th { box-shadow: none; } +.spinner { + filter: invert(1); +} + +a:hover > .spinner { + filter: invert(1) brightness(2); +} + +.flux .item.manage .read:hover .icon.spinner { + filter: invert(1) grayscale(0.8) brightness(1.7); +} + /*=== switches */ .switch.active { background-color: var(--contrast-background-color); diff --git a/p/themes/Dark/dark.css b/p/themes/Dark/dark.css index 412ff9cd4..b2ddf8f2b 100644 --- a/p/themes/Dark/dark.css +++ b/p/themes/Dark/dark.css @@ -118,6 +118,18 @@ p.help .icon, filter: brightness(.6) contrast(1.2); } +.spinner { + filter: invert(1) brightness(.6) contrast(1.2); +} + +.bookmark:hover > .spinner { + filter: invert(1) brightness(1.1); +} + +a:hover .icon.spinner { + filter: invert(1) brightness(1.5); +} + /*=== Forms */ legend { border-bottom: 1px solid var(--dark-border-color); diff --git a/p/themes/Dark/dark.rtl.css b/p/themes/Dark/dark.rtl.css index aead74393..4656ca241 100644 --- a/p/themes/Dark/dark.rtl.css +++ b/p/themes/Dark/dark.rtl.css @@ -118,6 +118,18 @@ p.help .icon, filter: brightness(.6) contrast(1.2); } +.spinner { + filter: invert(1) brightness(.6) contrast(1.2); +} + +.bookmark:hover > .spinner { + filter: invert(1) brightness(1.1); +} + +a:hover .icon.spinner { + filter: invert(1) brightness(1.5); +} + /*=== Forms */ legend { border-bottom: 1px solid var(--dark-border-color); diff --git a/p/themes/Origine/origine.css b/p/themes/Origine/origine.css index 8f405ea19..5c658345c 100644 --- a/p/themes/Origine/origine.css +++ b/p/themes/Origine/origine.css @@ -1323,4 +1323,8 @@ a:hover .icon { :root.darkMode_auto .btn:active .icon { filter: brightness(1.4); } + + :root.darkMode_auto .spinner { + filter: invert(1) brightness(2); + } } diff --git a/p/themes/Origine/origine.rtl.css b/p/themes/Origine/origine.rtl.css index 4f5f3bc45..417a9003c 100644 --- a/p/themes/Origine/origine.rtl.css +++ b/p/themes/Origine/origine.rtl.css @@ -1323,4 +1323,8 @@ a:hover .icon { :root.darkMode_auto .btn:active .icon { filter: brightness(1.4); } + + :root.darkMode_auto .spinner { + filter: invert(1) brightness(2); + } } diff --git a/p/themes/icons/spinner.svg b/p/themes/icons/spinner.svg new file mode 100644 index 000000000..772d0c39f --- /dev/null +++ b/p/themes/icons/spinner.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24"><style>@keyframes spinner_svv2{to{transform:rotate(360deg)}}</style><path d="M10.14 1.16a11 11 0 0 0-9 8.92A1.59 1.59 0 0 0 2.46 12a1.52 1.52 0 0 0 1.65-1.3 8 8 0 0 1 6.66-6.61A1.42 1.42 0 0 0 12 2.69a1.57 1.57 0 0 0-1.86-1.53Z" style="transform-origin:center;animation:spinner_svv2 .75s infinite linear"/></svg>
\ No newline at end of file |
