|
|
@@ -177,6 +177,67 @@ function setIconAndLabelElement(parentElement, iconName, labelText) {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+/**
|
|
|
+ * Set the button to a loading state and return a clone of the original button element.
|
|
|
+ *
|
|
|
+ * @param {Element} buttonElement - The button element to set to loading state.
|
|
|
+ * @return {Element} The original button element cloned before modification.
|
|
|
+ */
|
|
|
+function setButtonToLoadingState(buttonElement) {
|
|
|
+ const originalButtonElement = buttonElement.cloneNode(true);
|
|
|
+
|
|
|
+ buttonElement.textContent = "";
|
|
|
+ buttonElement.appendChild(createIconLabelElement(buttonElement.dataset.labelLoading));
|
|
|
+
|
|
|
+ return originalButtonElement;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * Restore the button to its original state.
|
|
|
+ *
|
|
|
+ * @param {Element} buttonElement The button element to restore.
|
|
|
+ * @param {Element} originalButtonElement The original button element to restore from.
|
|
|
+ * @returns {void}
|
|
|
+ */
|
|
|
+function restoreButtonState(buttonElement, originalButtonElement) {
|
|
|
+ buttonElement.textContent = "";
|
|
|
+ buttonElement.appendChild(originalButtonElement);
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * Set the button to a saved state.
|
|
|
+ *
|
|
|
+ * @param {Element} buttonElement The button element to set to saved state.
|
|
|
+ */
|
|
|
+function setButtonToSavedState(buttonElement) {
|
|
|
+ buttonElement.dataset.completed = "true";
|
|
|
+ setIconAndLabelElement(buttonElement, "save", buttonElement.dataset.labelDone);
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * Set the bookmark button state.
|
|
|
+ *
|
|
|
+ * @param {Element} buttonElement - The button element to update.
|
|
|
+ * @param {string} newState - The new state to set ("star" or "unstar").
|
|
|
+ */
|
|
|
+function setBookmarkButtonState(buttonElement, newState) {
|
|
|
+ buttonElement.dataset.value = newState;
|
|
|
+ const iconType = newState === "star" ? "unstar" : "star";
|
|
|
+ setIconAndLabelElement(buttonElement, iconType, buttonElement.dataset[newState === "star" ? "labelUnstar" : "labelStar"]);
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * Set the read status button state.
|
|
|
+ *
|
|
|
+ * @param {Element} buttonElement - The button element to update.
|
|
|
+ * @param {string} newState - The new state to set ("read" or "unread").
|
|
|
+ */
|
|
|
+function setReadStatusButtonState(buttonElement, newState) {
|
|
|
+ buttonElement.dataset.value = newState;
|
|
|
+ const iconType = newState === "read" ? "unread" : "read";
|
|
|
+ setIconAndLabelElement(buttonElement, iconType, buttonElement.dataset[newState === "read" ? "labelUnread" : "labelRead"]);
|
|
|
+}
|
|
|
+
|
|
|
/**
|
|
|
* Show a toast notification.
|
|
|
*
|
|
|
@@ -202,29 +263,7 @@ function showToastNotification(iconType, notificationMessage) {
|
|
|
|
|
|
document.body.appendChild(toastElementWrapper);
|
|
|
|
|
|
- setTimeout(() => {
|
|
|
- toastElementWrapper.classList.add("toast-animate");
|
|
|
-
|
|
|
- }, 100);
|
|
|
-}
|
|
|
-
|
|
|
-/**
|
|
|
- * Insert an icon label element into the parent element.
|
|
|
- *
|
|
|
- * @param {Element} parentElement The parent element to insert the icon label into.
|
|
|
- * @param {string} iconLabelText The text to display in the icon label.
|
|
|
- * @param {boolean} clearParentTextcontent If true, clear the parent's text content before appending the icon label.
|
|
|
- * @returns {void}
|
|
|
- */
|
|
|
-function insertIconLabelElement(parentElement, iconLabelText, clearParentTextcontent = true) {
|
|
|
- const span = document.createElement('span');
|
|
|
- span.classList.add('icon-label');
|
|
|
- span.textContent = iconLabelText;
|
|
|
-
|
|
|
- if (clearParentTextcontent) {
|
|
|
- parentElement.textContent = '';
|
|
|
- }
|
|
|
- parentElement.appendChild(span);
|
|
|
+ setTimeout(() => toastElementWrapper.classList.add("toast-animate"), 100);
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
@@ -584,36 +623,21 @@ function handleEntryStatus(navigationDirection, element, setToRead) {
|
|
|
*/
|
|
|
function toggleEntryStatus(element, toasting) {
|
|
|
const entryID = parseInt(element.dataset.id, 10);
|
|
|
- const link = element.querySelector(":is(a, button)[data-toggle-status]");
|
|
|
- if (!link) {
|
|
|
- return;
|
|
|
- }
|
|
|
+ const buttonElement = element.querySelector(":is(a, button)[data-toggle-status]");
|
|
|
+ if (!buttonElement) return;
|
|
|
|
|
|
- const currentStatus = link.dataset.value;
|
|
|
+ const currentStatus = buttonElement.dataset.value;
|
|
|
const newStatus = currentStatus === "read" ? "unread" : "read";
|
|
|
|
|
|
- link.querySelector("span").textContent = link.dataset.labelLoading;
|
|
|
+ setButtonToLoadingState(buttonElement);
|
|
|
+
|
|
|
updateEntriesStatus([entryID], newStatus, () => {
|
|
|
- let iconElement, label;
|
|
|
+ setReadStatusButtonState(buttonElement, newStatus);
|
|
|
|
|
|
- if (currentStatus === "read") {
|
|
|
- iconElement = document.querySelector("template#icon-read");
|
|
|
- label = link.dataset.labelRead;
|
|
|
- if (toasting) {
|
|
|
- showToastNotification("read", link.dataset.toastUnread);
|
|
|
- }
|
|
|
- } else {
|
|
|
- iconElement = document.querySelector("template#icon-unread");
|
|
|
- label = link.dataset.labelUnread;
|
|
|
- if (toasting) {
|
|
|
- showToastNotification("unread", link.dataset.toastUnread);
|
|
|
- }
|
|
|
+ if (toasting) {
|
|
|
+ showToastNotification(currentStatus, currentStatus === "read" ? buttonElement.dataset.toastUnread : buttonElement.dataset.toastRead);
|
|
|
}
|
|
|
|
|
|
- link.replaceChildren(iconElement.content.cloneNode(true));
|
|
|
- insertIconLabelElement(link, label, false);
|
|
|
- link.dataset.value = newStatus;
|
|
|
-
|
|
|
if (element.classList.contains("item-status-" + currentStatus)) {
|
|
|
element.classList.remove("item-status-" + currentStatus);
|
|
|
element.classList.add("item-status-" + newStatus);
|
|
|
@@ -667,11 +691,10 @@ function handleSaveEntryAction(element = null) {
|
|
|
const buttonElement = currentEntry.querySelector(":is(a, button)[data-save-entry]");
|
|
|
if (!buttonElement || buttonElement.dataset.completed) return;
|
|
|
|
|
|
- insertIconLabelElement(buttonElement, buttonElement.dataset.labelLoading);
|
|
|
+ setButtonToLoadingState(buttonElement);
|
|
|
|
|
|
sendPOSTRequest(buttonElement.dataset.saveUrl).then(() => {
|
|
|
- insertIconLabelElement(buttonElement, buttonElement.dataset.labelDone);
|
|
|
- buttonElement.dataset.completed = "true";
|
|
|
+ setButtonToSavedState(buttonElement);
|
|
|
if (isEntryView()) {
|
|
|
showToastNotification("save", buttonElement.dataset.toastDone);
|
|
|
}
|
|
|
@@ -690,19 +713,13 @@ function handleBookmarkAction(element) {
|
|
|
const buttonElement = currentEntry.querySelector(":is(a, button)[data-toggle-bookmark]");
|
|
|
if (!buttonElement) return;
|
|
|
|
|
|
- insertIconLabelElement(buttonElement, buttonElement.dataset.labelLoading);
|
|
|
+ setButtonToLoadingState(buttonElement);
|
|
|
|
|
|
sendPOSTRequest(buttonElement.dataset.bookmarkUrl).then(() => {
|
|
|
- const currentStarStatus = buttonElement.dataset.value;
|
|
|
- const newStarStatus = currentStarStatus === "star" ? "unstar" : "star";
|
|
|
- const isStarred = currentStarStatus === "star";
|
|
|
+ const isStarred = buttonElement.dataset.value === "star";
|
|
|
+ const newStarStatus = isStarred ? "unstar" : "star";
|
|
|
|
|
|
- const iconElement = document.querySelector(isStarred ? "template#icon-star" : "template#icon-unstar");
|
|
|
- const label = isStarred ? buttonElement.dataset.labelStar : buttonElement.dataset.labelUnstar;
|
|
|
-
|
|
|
- buttonElement.replaceChildren(iconElement.content.cloneNode(true));
|
|
|
- insertIconLabelElement(buttonElement, label, false);
|
|
|
- buttonElement.dataset.value = newStarStatus;
|
|
|
+ setBookmarkButtonState(buttonElement, newStarStatus);
|
|
|
|
|
|
if (isEntryView()) {
|
|
|
showToastNotification(newStarStatus, buttonElement.dataset[isStarred ? "toastUnstar" : "toastStar"]);
|
|
|
@@ -721,13 +738,10 @@ function handleFetchOriginalContentAction() {
|
|
|
const buttonElement = document.querySelector(":is(a, button)[data-fetch-content-entry]");
|
|
|
if (!buttonElement) return;
|
|
|
|
|
|
- const previousElement = buttonElement.cloneNode(true);
|
|
|
-
|
|
|
- insertIconLabelElement(buttonElement, buttonElement.dataset.labelLoading);
|
|
|
+ const originalButtonElement = setButtonToLoadingState(buttonElement);
|
|
|
|
|
|
sendPOSTRequest(buttonElement.dataset.fetchContentUrl).then((response) => {
|
|
|
- buttonElement.textContent = '';
|
|
|
- buttonElement.appendChild(previousElement);
|
|
|
+ restoreButtonState(buttonElement, originalButtonElement);
|
|
|
|
|
|
response.json().then((data) => {
|
|
|
if (data.content && data.reading_time) {
|