From e39a8eeccc5af538fadcf5d93d2bb51b8d9e7417 Mon Sep 17 00:00:00 2001 From: "byte[]" Date: Mon, 2 Dec 2019 09:55:48 -0500 Subject: [PATCH] automatic updating notifications --- assets/js/boorujs.js | 18 ++++++------ assets/js/notifications.js | 28 ++++++------------- .../controllers/conversation_controller.ex | 4 +++ .../controllers/image_controller.ex | 3 ++ .../notification/unread_controller.ex | 10 +++++++ .../controllers/topic_controller.ex | 3 ++ .../plugs/notification_count_plug.ex | 4 +++ lib/philomena_web/router.ex | 3 ++ 8 files changed, 43 insertions(+), 30 deletions(-) create mode 100644 lib/philomena_web/controllers/notification/unread_controller.ex diff --git a/assets/js/boorujs.js b/assets/js/boorujs.js index 52a62934..7968f10f 100644 --- a/assets/js/boorujs.js +++ b/assets/js/boorujs.js @@ -8,7 +8,6 @@ import { $ } from './utils/dom'; import { fetchHtml, handleError } from './utils/requests'; import { showBlock } from './utils/image'; import { addTag } from './tagsinput'; -import { markRead } from './notifications'; // Event types and any qualifying conditions - return true to not run action const types = { @@ -30,7 +29,8 @@ const actions = { disable(data) { selectorCb(data.base, data.value, el => el.disabled = true); }, - copy(data) { document.querySelector(data.value).select(); document.execCommand('copy'); }, + copy(data) { document.querySelector(data.value).select(); + document.execCommand('copy'); }, inputvalue(data) { document.querySelector(data.value).value = data.el.dataset.setValue; }, @@ -46,8 +46,8 @@ const actions = { tab(data) { const block = data.el.parentNode.parentNode, - newTab = $(`.block__tab[data-tab="${data.value}"]`), - loadTab = data.el.dataset.loadTab; + newTab = $(`.block__tab[data-tab="${data.value}"]`), + loadTab = data.el.dataset.loadTab; // Switch tab const selectedTab = block.querySelector('.selected'); @@ -74,8 +74,6 @@ const actions = { unfilter(data) { showBlock(data.el.closest('.image-show-container')); }, - markRead, - }; // Use this function to apply a callback to elements matching the selectors @@ -87,9 +85,9 @@ function matchAttributes(event) { if (!types[event.type](event)) { for (const action in actions) { - const attr = `data-${event.type}-${action.toLowerCase()}`, - el = event.target && event.target.closest(`[${attr}]`), - value = el && el.getAttribute(attr); + const attr = `data-${event.type}-${action.toLowerCase()}`, + el = event.target && event.target.closest(`[${attr}]`), + value = el && el.getAttribute(attr); if (el) { // Return true if you don't want to preventDefault @@ -104,4 +102,4 @@ function registerEvents() { for (const type in types) document.addEventListener(type, matchAttributes); } -export { registerEvents }; +export { registerEvents }; \ No newline at end of file diff --git a/assets/js/notifications.js b/assets/js/notifications.js index 4926c739..1ec35615 100644 --- a/assets/js/notifications.js +++ b/assets/js/notifications.js @@ -3,18 +3,17 @@ */ import { fetchJson, handleError } from './utils/requests'; -import { $, $$, hideEl, toggleEl } from './utils/dom'; +import { $ } from './utils/dom'; import { delegate } from './utils/events'; import store from './utils/store'; const NOTIFICATION_INTERVAL = 600000, - NOTIFICATION_EXPIRES = 300000; + NOTIFICATION_EXPIRES = 300000; -function makeRequest(verb, action, body) { - return fetchJson(verb, `${window.booru.apiEndpoint}notifications/${action}.json`, body).then(handleError); +function makeRequest(verb) { + return fetchJson(verb, '/notifications/unread').then(handleError); } - function bindSubscriptionLinks() { delegate(document, 'fetchcomplete', { '.js-subscription-link': event => { @@ -26,28 +25,17 @@ function bindSubscriptionLinks() { }); } -function markRead(data) { - const notificationId = data.value; - const notification = $(`.js-notification-id-${notificationId}`); - - makeRequest('PUT', 'mark_read', { id: notificationId }) - .then(() => hideEl(notification)) - .catch(() => data.el.textContent = 'Error!'); -} - - function getNewNotifications() { if (document.hidden || !store.hasExpired('notificationCount')) { return; } - makeRequest('GET', 'unread').then(response => response.json()).then(({ data }) => { - updateNotificationTicker(data.length); - storeNotificationCount(data.length); + makeRequest('GET').then(response => response.json()).then(({ notifications }) => { + updateNotificationTicker(notifications); + storeNotificationCount(notifications); }); } - function updateNotificationTicker(notificationCount) { const ticker = $('.js-notification-ticker'); const parsedNotificationCount = Number(notificationCount); @@ -78,4 +66,4 @@ function setupNotifications() { bindSubscriptionLinks(); } -export { setupNotifications, markRead }; +export { setupNotifications }; \ No newline at end of file diff --git a/lib/philomena_web/controllers/conversation_controller.ex b/lib/philomena_web/controllers/conversation_controller.ex index 8128aa81..047d9cb7 100644 --- a/lib/philomena_web/controllers/conversation_controller.ex +++ b/lib/philomena_web/controllers/conversation_controller.ex @@ -1,6 +1,7 @@ defmodule PhilomenaWeb.ConversationController do use PhilomenaWeb, :controller + alias PhilomenaWeb.NotificationCountPlug alias Philomena.{Conversations, Conversations.Conversation, Conversations.Message} alias Philomena.Textile.Renderer alias Philomena.Repo @@ -47,6 +48,9 @@ defmodule PhilomenaWeb.ConversationController do conversation |> Conversations.mark_conversation_read(user) + # Update the conversation ticker in the header + conn = NotificationCountPlug.call(conn) + render(conn, "show.html", conversation: conversation, messages: messages, changeset: changeset) end diff --git a/lib/philomena_web/controllers/image_controller.ex b/lib/philomena_web/controllers/image_controller.ex index 0d83bf0e..5abd44ed 100644 --- a/lib/philomena_web/controllers/image_controller.ex +++ b/lib/philomena_web/controllers/image_controller.ex @@ -33,6 +33,9 @@ defmodule PhilomenaWeb.ImageController do Images.clear_notification(image, user) + # Update the notification ticker in the header + conn = NotificationCountPlug.call(conn) + comments = Comment |> where(image_id: ^image.id) diff --git a/lib/philomena_web/controllers/notification/unread_controller.ex b/lib/philomena_web/controllers/notification/unread_controller.ex new file mode 100644 index 00000000..ef091dd5 --- /dev/null +++ b/lib/philomena_web/controllers/notification/unread_controller.ex @@ -0,0 +1,10 @@ +defmodule PhilomenaWeb.Notification.UnreadController do + use PhilomenaWeb, :controller + + def index(conn, _params) do + json(conn, %{ + notifications: conn.assigns.notification_count, + conversations: conn.assigns.conversation_count + }) + end +end \ No newline at end of file diff --git a/lib/philomena_web/controllers/topic_controller.ex b/lib/philomena_web/controllers/topic_controller.ex index 3b3e8b22..c0ac5bea 100644 --- a/lib/philomena_web/controllers/topic_controller.ex +++ b/lib/philomena_web/controllers/topic_controller.ex @@ -27,6 +27,9 @@ defmodule PhilomenaWeb.TopicController do Topics.clear_notification(topic, user) Forums.clear_notification(forum, user) + # Update the notification ticker in the header + conn = NotificationCountPlug.call(conn) + conn = conn |> assign(:topic, topic) %{page_number: page} = conn.assigns.pagination diff --git a/lib/philomena_web/plugs/notification_count_plug.ex b/lib/philomena_web/plugs/notification_count_plug.ex index 00e1d328..cb0a3d75 100644 --- a/lib/philomena_web/plugs/notification_count_plug.ex +++ b/lib/philomena_web/plugs/notification_count_plug.ex @@ -15,6 +15,10 @@ defmodule PhilomenaWeb.NotificationCountPlug do @spec init(any()) :: any() def init(opts), do: opts + @doc false + @spec call(Plug.Conn.t()) :: Plug.Conn.t() + def call(conn), do: call(conn, nil) + @doc false @spec call(Plug.Conn.t(), any()) :: Plug.Conn.t() def call(conn, _opts) do diff --git a/lib/philomena_web/router.ex b/lib/philomena_web/router.ex index a6635301..d5f107bf 100644 --- a/lib/philomena_web/router.ex +++ b/lib/philomena_web/router.ex @@ -75,6 +75,9 @@ defmodule PhilomenaWeb.Router do scope "/", PhilomenaWeb do pipe_through [:browser, :ensure_totp, :protected] + scope "/notifications", Notification, as: :notification do + resources "/unread", UnreadController, only: [:index] + end resources "/notifications", NotificationController, only: [:index, :delete] resources "/conversations", ConversationController, only: [:index, :show, :new, :create] do resources "/messages", Conversation.MessageController, only: [:create]