From d170ade8de13a668ee81bb69ab21c3625bbf1028 Mon Sep 17 00:00:00 2001 From: Marcus Date: Sun, 14 May 2023 14:54:49 -0700 Subject: [PATCH 01/14] copy postblock options Co-Authored-By: April Sylph <28949509+AprilSylph@users.noreply.github.com> --- .../notificationblock/options/index.css | 69 +++++++++++++++++++ .../notificationblock/options/index.html | 29 ++++++++ .../notificationblock/options/index.js | 61 ++++++++++++++++ 3 files changed, 159 insertions(+) create mode 100644 src/scripts/notificationblock/options/index.css create mode 100644 src/scripts/notificationblock/options/index.html create mode 100644 src/scripts/notificationblock/options/index.js diff --git a/src/scripts/notificationblock/options/index.css b/src/scripts/notificationblock/options/index.css new file mode 100644 index 0000000000..ab64eca696 --- /dev/null +++ b/src/scripts/notificationblock/options/index.css @@ -0,0 +1,69 @@ +:root { + --black: 21, 20, 25; + --white: 255, 255, 255; + --grey: 207, 207, 216; + --accent: 10, 132, 255; +} + +@media (prefers-color-scheme: dark) { + :root { + --black: 251, 251, 254; + --white: 66, 65, 77; + --grey: 91, 91, 102; + --accent: 54, 213, 255; + } +} + +html { + font-size: 14px; + scrollbar-color: rgb(var(--grey)) transparent; + scrollbar-width: thin; + overflow-y: hidden; +} + +body { + background-color: rgb(var(--white)); + color: rgb(var(--black)); + font-family: "Helvetica Neue", "HelveticaNeue", Helvetica, Arial, sans-serif; + font-size: 100%; + -webkit-user-select: none; + user-select: none; +} + +header { + display: flex; + flex-direction: row; + justify-content: space-between; + align-items: center; + margin-bottom: 1em; +} + +#posts-blocked-count { + font-weight: bold; +} + +#blocked-posts { + padding: 0; + border-bottom: 1px solid rgb(var(--grey)); + margin: 0; +} + +.blocked-post { + display: flex; + flex-direction: row; + justify-content: space-between; + align-items: center; + padding: 1ch 0; + border-top: 1px solid rgb(var(--grey)); +} + +.blocked-post button { + padding: 0; + border: none; + + appearance: none; + background-color: transparent; + color: rgb(var(--accent)); + cursor: pointer; + font-weight: bold; +} diff --git a/src/scripts/notificationblock/options/index.html b/src/scripts/notificationblock/options/index.html new file mode 100644 index 0000000000..1a4705a428 --- /dev/null +++ b/src/scripts/notificationblock/options/index.html @@ -0,0 +1,29 @@ + + + + + + XKit: Manage blocked posts + + + + + + + + + +
+
+ + Unblocking a post will immediately unhide it. +
+ +
+ + diff --git a/src/scripts/notificationblock/options/index.js b/src/scripts/notificationblock/options/index.js new file mode 100644 index 0000000000..c9e6a84b73 --- /dev/null +++ b/src/scripts/notificationblock/options/index.js @@ -0,0 +1,61 @@ + +const postsBlockedCount = document.getElementById('posts-blocked-count'); +const blockedPostList = document.getElementById('blocked-posts'); +const blockedPostTemplate = document.getElementById('blocked-post'); + +const storageKey = 'postblock.blockedPostRootIDs'; +const uuidsStorageKey = 'postblock.uuids'; +const toOpenStorageKey = 'postblock.toOpen'; + +const unblockPost = async function ({ currentTarget }) { + let { [storageKey]: blockedPostRootIDs = [] } = await browser.storage.local.get(storageKey); + + blockedPostRootIDs = blockedPostRootIDs.filter(id => id !== currentTarget.dataset.postId); + await browser.storage.local.set({ [storageKey]: blockedPostRootIDs }); + + currentTarget.remove(); +}; + +const renderBlockedPosts = async function () { + const { [storageKey]: blockedPostRootIDs = [] } = await browser.storage.local.get(storageKey); + const { [uuidsStorageKey]: uuids = {} } = await browser.storage.local.get(uuidsStorageKey); + + postsBlockedCount.textContent = `${blockedPostRootIDs.length} blocked ${blockedPostRootIDs.length === 1 ? 'post' : 'posts'}`; + blockedPostList.textContent = ''; + + for (const blockedPostID of blockedPostRootIDs) { + const templateClone = blockedPostTemplate.content.cloneNode(true); + const spanElement = templateClone.querySelector('span'); + const unblockButton = templateClone.querySelector('button'); + + spanElement.textContent = blockedPostID; + unblockButton.dataset.postId = blockedPostID; + unblockButton.addEventListener('click', unblockPost); + + if (uuids[blockedPostID]) { + const a = document.createElement('a'); + a.href = 'javascript:void(0);'; + a.addEventListener('click', async () => { + await browser.storage.local.set({ + [toOpenStorageKey]: { uuid: uuids[blockedPostID], blockedPostID } + }); + window.open('https://www.tumblr.com/'); + }); + spanElement.replaceWith(a); + a.append(spanElement); + } + + blockedPostList.append(templateClone); + } +}; + +browser.storage.onChanged.addListener((changes, areaName) => { + if ( + areaName === 'local' && + (Object.keys(changes).includes(storageKey) || Object.keys(changes).includes(uuidsStorageKey)) + ) { + renderBlockedPosts(); + } +}); + +renderBlockedPosts(); From 4f3557eb8067d058bec796416852c77b7d47e20e Mon Sep 17 00:00:00 2001 From: Marcus Date: Fri, 12 May 2023 13:59:52 -0700 Subject: [PATCH 02/14] partial implementation --- src/scripts/notificationblock.js | 28 ++++++++++++++++++- src/scripts/notificationblock.json | 9 +++++- .../notificationblock/options/index.css | 8 +++--- .../notificationblock/options/index.html | 13 ++++----- .../notificationblock/options/index.js | 20 ++++++------- 5 files changed, 55 insertions(+), 23 deletions(-) diff --git a/src/scripts/notificationblock.js b/src/scripts/notificationblock.js index 0bbc42ca7d..27027ca889 100644 --- a/src/scripts/notificationblock.js +++ b/src/scripts/notificationblock.js @@ -6,8 +6,12 @@ import { keyToCss } from '../util/css_map.js'; import { showModal, hideModal, modalCancelButton } from '../util/modals.js'; import { dom } from '../util/dom.js'; import { userBlogNames } from '../util/user.js'; +import { apiFetch, navigate } from '../util/tumblr_helpers.js'; +import { notify } from '../util/notifications.js'; const storageKey = 'notificationblock.blockedPostTargetIDs'; +const uuidsStorageKey = 'notificationblock.uuids'; +const toOpenStorageKey = 'notificationblock.toOpen'; const meatballButtonBlockId = 'notificationblock-block'; const meatballButtonBlockLabel = 'Block notifications'; const meatballButtonUnblockId = 'notificationblock-unblock'; @@ -15,6 +19,7 @@ const meatballButtonUnblockLabel = 'Unblock notifications'; const notificationSelector = keyToCss('notification'); let blockedPostTargetIDs; +let uuids = {}; const styleElement = buildStyle(); const buildCss = () => `:is(${ @@ -95,7 +100,13 @@ const unblockPostFilter = async ({ id, rebloggedRootId }) => { }; export const onStorageChanged = (changes, areaName) => { - if (Object.keys(changes).includes(storageKey)) { + const { [storageKey]: blockedPostChanges, [uuidsStorageKey]: uuidsChanges } = changes; + + if (uuidsChanges) { + ({ newValue: uuids } = uuidsChanges); + } + + if (blockedPostChanges) { blockedPostTargetIDs = changes[storageKey].newValue; styleElement.textContent = buildCss(); } @@ -103,6 +114,8 @@ export const onStorageChanged = (changes, areaName) => { export const main = async function () { ({ [storageKey]: blockedPostTargetIDs = [] } = await browser.storage.local.get(storageKey)); + ({ [uuidsStorageKey]: uuids = {} } = await browser.storage.local.get(uuidsStorageKey)); + styleElement.textContent = buildCss(); document.documentElement.append(styleElement); @@ -110,6 +123,19 @@ export const main = async function () { registerMeatballItem({ id: meatballButtonBlockId, label: meatballButtonBlockLabel, onclick: onButtonClicked, postFilter: blockPostFilter }); registerMeatballItem({ id: meatballButtonUnblockId, label: meatballButtonUnblockLabel, onclick: onButtonClicked, postFilter: unblockPostFilter }); + + const { [toOpenStorageKey]: toOpen } = await browser.storage.local.get(toOpenStorageKey); + if (toOpen) { + browser.storage.local.remove(toOpenStorageKey); + + try { + const { uuid, blockedPostID } = toOpen; + const { response: { blog: { name } } } = await apiFetch(`/v2/blog/${uuid}/info`); + navigate(`/${name}/${blockedPostID}`); + } catch (e) { + notify('Failed to open post!'); + } + } }; export const clean = async function () { diff --git a/src/scripts/notificationblock.json b/src/scripts/notificationblock.json index e0fd41b1b1..7eccd36224 100644 --- a/src/scripts/notificationblock.json +++ b/src/scripts/notificationblock.json @@ -7,5 +7,12 @@ "background_color": "#f5223c" }, "help": "https://github.com/AprilSylph/XKit-Rewritten/wiki/Features#notificationblock", - "relatedTerms": [ "activity" ] + "relatedTerms": [ "activity" ], + "preferences": { + "manageBlockedPosts": { + "type": "iframe", + "label": "Manage posts with blocked notifications", + "src": "/scripts/notificationblock/options/index.html" + } + } } diff --git a/src/scripts/notificationblock/options/index.css b/src/scripts/notificationblock/options/index.css index ab64eca696..55e45b4d48 100644 --- a/src/scripts/notificationblock/options/index.css +++ b/src/scripts/notificationblock/options/index.css @@ -38,17 +38,17 @@ header { margin-bottom: 1em; } -#posts-blocked-count { +#notification-blocked-count { font-weight: bold; } -#blocked-posts { +#notification-blocked-posts { padding: 0; border-bottom: 1px solid rgb(var(--grey)); margin: 0; } -.blocked-post { +.notification-blocked-post { display: flex; flex-direction: row; justify-content: space-between; @@ -57,7 +57,7 @@ header { border-top: 1px solid rgb(var(--grey)); } -.blocked-post button { +.notification-blocked-post button { padding: 0; border: none; diff --git a/src/scripts/notificationblock/options/index.html b/src/scripts/notificationblock/options/index.html index 1a4705a428..5e759a7292 100644 --- a/src/scripts/notificationblock/options/index.html +++ b/src/scripts/notificationblock/options/index.html @@ -3,7 +3,7 @@ - XKit: Manage blocked posts + XKit: Manage posts with blocked notifications @@ -12,18 +12,17 @@ -