forked from AprilSylph/XKit-Rewritten
-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathnotificationblock.js
More file actions
122 lines (102 loc) · 5.01 KB
/
notificationblock.js
File metadata and controls
122 lines (102 loc) · 5.01 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
import { buildStyle } from '../utils/interface.js';
import { registerMeatballItem, unregisterMeatballItem } from '../utils/meatballs.js';
import { onNewNotifications } from '../utils/mutations.js';
import { showModal, hideModal, modalCancelButton } from '../utils/modals.js';
import { dom } from '../utils/dom.js';
import { userBlogNames } from '../utils/user.js';
import { apiFetch } from '../utils/tumblr_helpers.js';
import { notificationObject } from '../utils/react_props.js';
const storageKey = 'notificationblock.blockedPostTargetIDs';
const meatballButtonBlockId = 'notificationblock-block';
const meatballButtonBlockLabel = 'Block notifications';
const meatballButtonUnblockId = 'notificationblock-unblock';
const meatballButtonUnblockLabel = 'Unblock notifications';
let blockedPostTargetIDs;
export const styleElement = buildStyle();
const buildCss = () => `:is(${blockedPostTargetIDs.map(rootId => `[data-target-root-post-id="${rootId}"]`).join(', ')
}) { display: none !important; }`;
const processNotifications = (notificationElements) => {
notificationElements.forEach(async notificationElement => {
const notification = await notificationObject(notificationElement);
if (notification !== undefined) {
const { targetRootPostId, targetPostId } = notification;
// available on "replied to your post" notifications, which appear to always target the root post
const blockablePostId = notification.actions?.longTap?.meta?.postId;
notificationElement.dataset.targetRootPostId = targetRootPostId || targetPostId || blockablePostId || '';
}
});
};
const muteNotificationsMessage = [
'\n\n',
'Unlike Tumblr\'s option to "Mute notifications", this will not prevent notifications for this post from being created, so they will still increment your unread notification count.',
'\n\n',
'You can use "Mute Notifications" in addition to or instead of this feature. ',
'It will completely prevent the post from generating notifications while it is enabled, and can be applied temporarily or permanently.'
];
const onButtonClicked = async function ({ currentTarget }) {
const { id, rebloggedRootId, blog: { uuid } } = currentTarget.__timelineObjectData;
const { response: { muted } } = await apiFetch(`/v2/blog/${uuid}/posts/${id}`);
const rootId = rebloggedRootId || id;
const shouldBlockNotifications = blockedPostTargetIDs.includes(rootId) === false;
const title = shouldBlockNotifications
? 'Block this post\'s notifications?'
: 'Unblock this post\'s notifications?';
const message = shouldBlockNotifications
? [
'Notifications for this post will be hidden from your activity feed.',
...(muted ? [] : muteNotificationsMessage)
]
: ['Notifications for this post will appear in your activity feed again.'];
const textContent = shouldBlockNotifications
? 'Block notifications'
: 'Unblock notifications';
const className = shouldBlockNotifications
? 'red'
: 'blue';
const saveNotificationPreference = shouldBlockNotifications
? () => { blockedPostTargetIDs.push(rootId); browser.storage.local.set({ [storageKey]: blockedPostTargetIDs }); }
: () => browser.storage.local.set({ [storageKey]: blockedPostTargetIDs.filter(blockedId => blockedId !== rootId) });
showModal({
title,
message,
buttons: [
modalCancelButton,
dom('button', { class: className }, {
click () {
hideModal();
saveNotificationPreference();
}
}, [textContent])
]
});
};
const blockPostFilter = async ({ blogName, rebloggedRootName, rebloggedFromName, id, rebloggedRootId, community, postAuthor }) => {
const rootId = rebloggedRootId || id;
const canReceiveActivity = userBlogNames.includes(blogName) ||
userBlogNames.includes(rebloggedFromName) ||
userBlogNames.includes(rebloggedRootName) ||
(community && userBlogNames.includes(postAuthor));
return canReceiveActivity && blockedPostTargetIDs.includes(rootId) === false;
};
const unblockPostFilter = async ({ id, rebloggedRootId }) => {
const rootId = rebloggedRootId || id;
return blockedPostTargetIDs.includes(rootId);
};
export const onStorageChanged = (changes, areaName) => {
if (Object.keys(changes).includes(storageKey)) {
blockedPostTargetIDs = changes[storageKey].newValue;
styleElement.textContent = buildCss();
}
};
export const main = async function () {
({ [storageKey]: blockedPostTargetIDs = [] } = await browser.storage.local.get(storageKey));
styleElement.textContent = buildCss();
onNewNotifications.addListener(processNotifications);
registerMeatballItem({ id: meatballButtonBlockId, label: meatballButtonBlockLabel, onclick: onButtonClicked, postFilter: blockPostFilter });
registerMeatballItem({ id: meatballButtonUnblockId, label: meatballButtonUnblockLabel, onclick: onButtonClicked, postFilter: unblockPostFilter });
};
export const clean = async function () {
onNewNotifications.removeListener(processNotifications);
unregisterMeatballItem(meatballButtonBlockId);
unregisterMeatballItem(meatballButtonUnblockId);
};