Use SVG icons for toast notifications

This commit is contained in:
Frédéric Guillot 2021-03-07 11:55:43 -08:00 committed by fguillot
parent f6ed2feab4
commit 548c4d4efe
5 changed files with 62 additions and 43 deletions

View File

@ -46,9 +46,7 @@
data-entries-status-url="{{ route "updateEntriesStatus" }}" data-entries-status-url="{{ route "updateEntriesStatus" }}"
data-refresh-all-feeds-url="{{ route "refreshAllFeeds" }}" data-refresh-all-feeds-url="{{ route "refreshAllFeeds" }}"
{{ if .user }}{{ if not .user.KeyboardShortcuts }}data-disable-keyboard-shortcuts="true"{{ end }}{{ end }}> {{ if .user }}{{ if not .user.KeyboardShortcuts }}data-disable-keyboard-shortcuts="true"{{ end }}{{ end }}>
<div class="toast-wrap">
<span class="toast-msg"></span>
</div>
{{ if .user }} {{ if .user }}
<header class="header"> <header class="header">
<nav> <nav>
@ -157,10 +155,16 @@
</div> </div>
</div> </div>
</template> </template>
<template id="icon_read">{{ icon "read" }}</template>
<template id="icon_unread">{{ icon "unread" }}</template> <template id="icon-read">{{ icon "read" }}</template>
<template id="icon_star">{{ icon "star" }}</template> <template id="icon-unread">{{ icon "unread" }}</template>
<template id="icon_unstar">{{ icon "unstar" }}</template> <template id="icon-star">{{ icon "star" }}</template>
<template id="icon-unstar">{{ icon "unstar" }}</template>
<template id="icon-save">{{ icon "save" }}</template>
<div id="toast-wrapper" role="alert" aria-live="assertive" aria-atomic="true">
<span id="toast-msg"></span>
</div>
</body> </body>
</html> </html>
{{ end }} {{ end }}

View File

@ -15,8 +15,8 @@
data-toggle-status="true" data-toggle-status="true"
data-label-unread="{{ t "entry.status.unread" }}" data-label-unread="{{ t "entry.status.unread" }}"
data-label-read="{{ t "entry.status.read" }}" data-label-read="{{ t "entry.status.read" }}"
data-toast-unread="&nbsp;{{ t "entry.status.toast.unread" }}" data-toast-unread="{{ t "entry.status.toast.unread" }}"
data-toast-read="✔︎&nbsp;{{ t "entry.status.toast.read" }}" data-toast-read="{{ t "entry.status.toast.read" }}"
data-value="{{ if eq .entry.Status "read" }}read{{ else }}unread{{ end }}" data-value="{{ if eq .entry.Status "read" }}read{{ else }}unread{{ end }}"
>{{ if eq .entry.Status "unread" }}{{ icon "read" }}{{ else }}{{ icon "unread" }}{{ end }}<span class="icon-label">{{ if eq .entry.Status "unread" }}{{ t "entry.status.read" }}{{ else }}{{ t "entry.status.unread" }}{{ end }}</span></a> >{{ if eq .entry.Status "unread" }}{{ icon "read" }}{{ else }}{{ icon "unread" }}{{ end }}<span class="icon-label">{{ if eq .entry.Status "unread" }}{{ t "entry.status.read" }}{{ else }}{{ t "entry.status.unread" }}{{ end }}</span></a>
</li> </li>
@ -27,8 +27,8 @@
data-label-loading="{{ t "entry.state.saving" }}" data-label-loading="{{ t "entry.state.saving" }}"
data-label-star="{{ t "entry.bookmark.toggle.on" }}" data-label-star="{{ t "entry.bookmark.toggle.on" }}"
data-label-unstar="{{ t "entry.bookmark.toggle.off" }}" data-label-unstar="{{ t "entry.bookmark.toggle.off" }}"
data-toast-star="&nbsp;{{ t "entry.bookmark.toast.on" }}" data-toast-star="{{ t "entry.bookmark.toast.on" }}"
data-toast-unstar="&nbsp;{{ t "entry.bookmark.toast.off" }}" data-toast-unstar="{{ t "entry.bookmark.toast.off" }}"
data-value="{{ if .entry.Starred }}star{{ else }}unstar{{ end }}" data-value="{{ if .entry.Starred }}star{{ else }}unstar{{ end }}"
>{{ if .entry.Starred }}{{ icon "unstar" }}{{ else }}{{ icon "star" }}{{ end }}<span class="icon-label">{{ if .entry.Starred }}{{ t "entry.bookmark.toggle.off" }}{{ else }}{{ t "entry.bookmark.toggle.on" }}{{ end }}</span></a> >{{ if .entry.Starred }}{{ icon "unstar" }}{{ else }}{{ icon "star" }}{{ end }}<span class="icon-label">{{ if .entry.Starred }}{{ t "entry.bookmark.toggle.off" }}{{ else }}{{ t "entry.bookmark.toggle.on" }}{{ end }}</span></a>
</li> </li>

View File

@ -22,6 +22,8 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE. SOFTWARE.
Source: https://github.com/tabler/tabler-icons
--> -->
<svg xmlns="http://www.w3.org/2000/svg"> <svg xmlns="http://www.w3.org/2000/svg">
<symbol id="icon-read" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"> <symbol id="icon-read" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round">
@ -43,10 +45,10 @@ SOFTWARE.
<path fill="currentColor" d="M12 17.75l-6.172 3.245 1.179-6.873-4.993-4.867 6.9-1.002L12 2l3.086 6.253 6.9 1.002-4.993 4.867 1.179 6.873z" /> <path fill="currentColor" d="M12 17.75l-6.172 3.245 1.179-6.873-4.993-4.867 6.9-1.002L12 2l3.086 6.253 6.9 1.002-4.993 4.867 1.179 6.873z" />
</symbol> </symbol>
<symbol id="icon-save" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"> <symbol id="icon-save" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round">
<path stroke="none" d="M0 0h24v24H0z"/> <path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
<path d="M4 17v2a2 2 0 0 0 2 2h12a2 2 0 0 0 2 -2v-2" /> <path d="M6 4h10l4 4v10a2 2 0 0 1 -2 2h-12a2 2 0 0 1 -2 -2v-12a2 2 0 0 1 2 -2"></path>
<polyline points="7 11 12 16 17 11" /> <circle cx="12" cy="14" r="2"></circle>
<line x1="12" y1="4" x2="12" y2="16" /> <polyline points="14 4 14 8 8 8 8 4"></polyline>
</symbol> </symbol>
<symbol id="icon-scraper" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"> <symbol id="icon-scraper" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round">
<path stroke="none" d="M0 0h24v24H0z"/> <path stroke="none" d="M0 0h24v24H0z"/>
@ -90,9 +92,10 @@ SOFTWARE.
<line x1="16" y1="5" x2="19" y2="8" /> <line x1="16" y1="5" x2="19" y2="8" />
</symbol> </symbol>
<symbol id="icon-feeds" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"> <symbol id="icon-feeds" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round">
<path stroke="none" d="M0 0h24v24H0z"/> <path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
<path d="M9 4h3l2 2h5a2 2 0 0 1 2 2v7a2 2 0 0 1 -2 2h-10a2 2 0 0 1 -2 -2v-9a2 2 0 0 1 2 -2" /> <circle cx="5" cy="19" r="1"></circle>
<path d="M17 17v2a2 2 0 0 1 -2 2h-10a2 2 0 0 1 -2 -2v-9a2 2 0 0 1 2 -2h2" /> <path d="M4 4a16 16 0 0 1 16 16"></path>
<path d="M4 11a9 9 0 0 1 9 9"></path>
</symbol> </symbol>
<symbol id="icon-entries" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"> <symbol id="icon-entries" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round">
<path stroke="none" d="M0 0h24v24H0z"/> <path stroke="none" d="M0 0h24v24H0z"/>

View File

@ -184,7 +184,7 @@ a:hover {
} }
/* Notification - "Toast" */ /* Notification - "Toast" */
.toast-wrap { #toast-wrapper {
visibility: hidden; visibility: hidden;
opacity: 0; opacity: 0;
position: fixed; position: fixed;
@ -195,13 +195,15 @@ a:hover {
text-align: center; text-align: center;
} }
.toast-msg { #toast-msg {
background-color: rgba(0,0,0,0.7); background-color: rgba(0,0,0,0.7);
padding: 2px 5px; padding-bottom: 4px;
padding-left: 4px;
padding-right: 5px;
border-radius: 5px; border-radius: 5px;
} }
.toastAnimate { .toast-animate {
animation: toastKeyFrames 2s; animation: toastKeyFrames 2s;
} }

View File

@ -136,23 +136,23 @@ function toggleEntryStatus(element, toasting) {
updateEntriesStatus([entryID], newStatus); updateEntriesStatus([entryID], newStatus);
let icon, label; let iconElement, label;
if (currentStatus === "read") { if (currentStatus === "read") {
icon = document.querySelector("template#icon_read"); iconElement = document.querySelector("template#icon-read");
label = link.dataset.labelRead; label = link.dataset.labelRead;
if (toasting) { if (toasting) {
toast(link.dataset.toastUnread); showToast(link.dataset.toastUnread, iconElement);
} }
} else { } else {
icon = document.querySelector("template#icon_unread"); iconElement = document.querySelector("template#icon-unread");
label = link.dataset.labelUnread; label = link.dataset.labelUnread;
if (toasting) { if (toasting) {
toast(link.dataset.toastRead); showToast(link.dataset.toastRead, iconElement);
} }
} }
link.innerHTML = icon.innerHTML + '<span class="icon-label">' + label + '</span>'; link.innerHTML = iconElement.innerHTML + '<span class="icon-label">' + label + '</span>';
link.dataset.value = newStatus; link.dataset.value = newStatus;
if (element.classList.contains("item-status-" + currentStatus)) { if (element.classList.contains("item-status-" + currentStatus)) {
@ -227,7 +227,8 @@ function saveEntry(element, toasting) {
element.innerHTML = previousInnerHTML; element.innerHTML = previousInnerHTML;
element.dataset.completed = true; element.dataset.completed = true;
if (toasting) { if (toasting) {
toast(element.dataset.toastDone); let iconElement = document.querySelector("template#icon-save");
showToast(element.dataset.toastDone, iconElement);
} }
}); });
request.execute(); request.execute();
@ -257,23 +258,23 @@ function toggleBookmark(parentElement, toasting) {
let currentStarStatus = element.dataset.value; let currentStarStatus = element.dataset.value;
let newStarStatus = currentStarStatus === "star" ? "unstar" : "star"; let newStarStatus = currentStarStatus === "star" ? "unstar" : "star";
let icon, label; let iconElement, label;
if (currentStarStatus === "star") { if (currentStarStatus === "star") {
icon = document.querySelector("template#icon_star"); iconElement = document.querySelector("template#icon-star");
label = element.dataset.labelStar; label = element.dataset.labelStar;
if (toasting) { if (toasting) {
toast(element.dataset.toastUnstar); showToast(element.dataset.toastUnstar, iconElement);
} }
} else { } else {
icon = document.querySelector("template#icon_unstar"); iconElement = document.querySelector("template#icon-unstar");
label = element.dataset.labelUnstar; label = element.dataset.labelUnstar;
if (toasting) { if (toasting) {
toast(element.dataset.toastStar); showToast(element.dataset.toastStar, iconElement);
} }
} }
element.innerHTML = icon.innerHTML + '<span class="icon-label">' + label + '</span>'; element.innerHTML = iconElement.innerHTML + '<span class="icon-label">' + label + '</span>';
element.dataset.value = newStarStatus; element.dataset.value = newStarStatus;
}); });
request.execute(); request.execute();
@ -592,12 +593,21 @@ function handleConfirmationMessage(linkElement, callback) {
containerElement.appendChild(questionElement); containerElement.appendChild(questionElement);
} }
function toast(msg) { function showToast(label, iconElement) {
if (!msg) return; if (!label || !iconElement) {
document.querySelector('.toast-wrap .toast-msg').innerHTML = msg; return;
let toastWrapper = document.querySelector('.toast-wrap'); }
toastWrapper.classList.remove('toastAnimate');
setTimeout(function () { const toastMsgElement = document.getElementById("toast-msg");
toastWrapper.classList.add('toastAnimate'); if (toastMsgElement) {
}, 100); toastMsgElement.innerHTML = iconElement.innerHTML + '<span class="icon-label">' + label + '</span>';
const toastElementWrapper = document.getElementById("toast-wrapper");
if (toastElementWrapper) {
toastElementWrapper.classList.remove('toast-animate');
setTimeout(function () {
toastElementWrapper.classList.add('toast-animate');
}, 100);
}
}
} }