Skip to content

Commit 20fd58f

Browse files
authored
Merge pull request #16 from webdevsk/dev - Now works in "Watch" page as well. Fixed missing comment box. Improved location detection
Now works in "Watch" page as well. Fixed missing comment box. Improved location detection
2 parents 18d48a3 + 73a0007 commit 20fd58f

7 files changed

Lines changed: 77 additions & 22 deletions

File tree

CONTRIBUTION.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ bun run build:greasyfork
4141

4242
* [dist](dist) - Built files (Output)
4343
* [src](src) - Source files
44-
+ [config.ts](src/config.ts) - Global config like devMode, pathnameMatches, node selectors, theme configuration, etc
44+
+ [config.ts](src/config.ts) - Global config like devMode, runScriptOn, node selectors, theme configuration, etc
4545
+ [index.ts](src/index.ts) - Entry point. Code starts here
4646
+ [data](src/data) - Data files
4747
- [filters-database.ts](src/data/filters-database.ts) - Filter database. This is where you can add new categories, as well as the entries for settings menu

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "fb-mobile-clean-my-feeds",
3-
"version": "1.00",
3+
"version": "1.01",
44
"author": "https://github.com/webdevsk",
55
"repository": {
66
"type": "git",
@@ -44,6 +44,7 @@
4444
"@icon": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAAbwAAAG8B8aLcQwAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAAHZSURBVDiNnZFLSFRxFMa/c1/jjIzYpGEjxFQUCC5a9BKJIAtRzEXEFaJFZXRrIQMtk3a1lWo3iwqkTS0kZyGCA4VNFNEmWwU9MIoiscZp7jzuvf9zWogXogS9Z3fO4fv4feeQiCBKjY8M9Nca3lUtkhqAUnwNoPcUheC63b+z5qm3nmelIxGwkMMir+/MzJSNzYodZ7/ZolKXADoDAJsmSJXahpXiXxPThdlIBlCSFUh+rd1wBNvuttLu1sOGae7zYjy4Nt8QgXpoXbzf9/HVYNfi3O+KK5XP5V3rEti2rde3pHvyuVtFAMB8/JjWJLlEU0M7nlnE0e1fjGVqPgVg4b8E0rHnHoSeDY1mx/CCUiIyiVZdQ8YE7bVgdpCWCqrj6xIQ0Rtm/qlB3okXywHoDJcxAnWa0OPtpb8M8nPP06V6tVD3/Mqj2zcOApjA0/g5AU6HYl7llcAANP4WHnH6SfEQ65hPJuJdvh8cuDs165y8nO1bqiZb4KoyVhhYVoDLqxEDAwT+EBqwwAGwm4jQmmyGF/g3Y3pi+MLU2U9UCjKUwCga/BUmAT8CiDIAnRfCyI8LxSNCeABgh1uro+zWlq7YQ9v++WXe7GWDziu/bcS0+AQGvr8EgD/aK7uaswjePgAAAABJRU5ErkJggg==",
4545
"@require": [],
4646
"@grant": [
47+
"unsafeWindow",
4748
"GM_getValue",
4849
"GM_setValue",
4950
"GM_addStyle",

src/config.ts

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,6 @@
22
* Enables verbose console logging and counter
33
*/
44
export const devMode = false
5-
/**
6-
* pathnameMatches is the list of paths to match. If any of them matches, the script will run
7-
*/
8-
export const pathnameMatches = ["/"]
95
/**
106
* bodyId is the id of the body element. Comes with HTML. It will surely be there
117
*/
@@ -26,13 +22,34 @@ export const postContainerSelector = "[data-pull-to-refresh-action-id]"
2622
/**
2723
* possibleTargetsInPost are the elements which may contain our target keywords
2824
*/
25+
2926
export const possibleTargetsSelectorInPost =
3027
"span.f2:not(.a), span.f5, [style^='margin-top:9px; height:21px'] > .native-text"
3128

3229
/**
3330
* navBarSelector is the element which contains the navigation bar
3431
*/
3532
export const navBarSelector = "[role='tablist']"
33+
/**
34+
* aria-label of the main navigation bar buttons. The active one should have the attribute aria-selected="true"
35+
*/
36+
export const ariaLabelOfNavBarButtons = {
37+
feed: "feed",
38+
friends: "friends",
39+
messages: "messages",
40+
videos: "videos",
41+
notifications: "notifications",
42+
marketplace: "marketplace",
43+
} as const
44+
/**
45+
* Main pages based on navigation bar buttons
46+
*/
47+
export type MainPagesBasedOnNavBarButtons =
48+
(typeof ariaLabelOfNavBarButtons)[keyof typeof ariaLabelOfNavBarButtons]
49+
/**
50+
* pages to run the script on
51+
*/
52+
export const runScriptOn: MainPagesBasedOnNavBarButtons[] = ["feed", "videos"]
3653
/**
3754
* showPlaceholder is whether to show placeholder or not
3855
*/

src/index.ts

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { bodyId, devMode } from "@/config"
22
import { BlockCounter } from "@/lib/block-counter"
3+
import { getCurrentPage } from "@/lib/get-current-page"
34
import { makeNavbarSticky } from "@/lib/make-navbar-sticky"
45
import { MenuButtonsInjector } from "@/lib/menu-buttons-injector"
56
import { onReadyForScripting } from "@/lib/on-ready-for-scripting"
@@ -9,28 +10,33 @@ import { SettingsMenuInjector } from "@/lib/settings-menu-injector"
910
import { updateThemeConfigWhenPossible } from "@/lib/updateThemeConfigWhenPossible"
1011
import { WhitelistedFiltersStorage } from "@/lib/whitelisted-filters-storage"
1112
import STYLES from "@/styles/style.css"
12-
1313
;(() => {
1414
// Make sure this is the React-Mobile version of facebook
1515
if (document.body.id !== bodyId) {
1616
console.error("ID 'app-body' not found.")
1717
return
1818
}
19-
if (!document.head.contains(GM_addStyle(STYLES)))
20-
console.error("Failed to add style node")
2119

2220
onReadyForScripting(() => {
2321
console.log("Ready for scripting")
22+
const styleNode = GM_addStyle(STYLES)
2423
// Store all abort functions
2524
const aborts: Array<() => void> = [
2625
updateThemeConfigWhenPossible(),
2726
// Show counter on top
2827
...(devMode ? [BlockCounter.getInstance().register()] : []),
2928
WhitelistedFiltersStorage.getInstance().register(),
30-
// Inject menu buttons [settings, feed]
31-
MenuButtonsInjector.getInstance().inject(),
32-
// Setup settingsMenu listeners and return cleanup function
33-
SettingsMenuInjector.getInstance().inject(),
29+
30+
// Inject menu buttons and settingsMenu only if we are on the feed page
31+
...(getCurrentPage() === "feed"
32+
? [
33+
// Inject menu buttons [settings, feed]
34+
MenuButtonsInjector.getInstance().inject(),
35+
// Setup settingsMenu listeners and return cleanup function
36+
SettingsMenuInjector.getInstance().inject(),
37+
]
38+
: []),
39+
3440
// Main cleaner
3541
runFeedsCleaner(),
3642
// Auto reload after idle
@@ -41,6 +47,7 @@ import STYLES from "@/styles/style.css"
4147

4248
return () => {
4349
console.log("Not Ready for scripting")
50+
styleNode.remove()
4451
// Cleanup code like removing dom nodes and destroying event listeners
4552
aborts.forEach(abort => abort?.())
4653
aborts.length = 0

src/lib/get-current-page.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import { type MainPagesBasedOnNavBarButtons, navBarSelector } from "@/config"
2+
3+
/**
4+
* Returns the current page based on navigation bar buttons. Must be called after ensuring routeNode is present.
5+
* @returns The current page based on navigation bar buttons
6+
*/
7+
export const getCurrentPage = (): MainPagesBasedOnNavBarButtons | "unknown" => {
8+
return (
9+
(document
10+
.querySelector(`${navBarSelector} > [aria-selected="true"]`)
11+
?.getAttribute("aria-label")
12+
?.split(",")[0] as MainPagesBasedOnNavBarButtons) ?? "unknown"
13+
)
14+
}

src/lib/on-ready-for-scripting.ts

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
import {
22
devMode,
3-
pathnameMatches,
43
postContainerSelector,
54
routeNodeSelector,
5+
runScriptOn,
66
screenRootSelector,
77
} from "@/config"
8+
import { getCurrentPage } from "@/lib/get-current-page"
89
import { watchForSelectorsPromise } from "@/utils/watch-for-selectors"
910

1011
type CleanupFn = () => void | PromiseLike<void>
@@ -31,10 +32,13 @@ export const onReadyForScripting = async (
3132
// Wait for screen root to be present
3233
await watchForSelectorsPromise([screenRootSelector])
3334
onNavigation((routeNode: HTMLElement) => {
34-
if (devMode) console.log("onNavigation callback called")
35-
// Terminate if we are not on the main page
36-
if (!pathnameMatches.some(pathname => pathname === location.pathname)) {
37-
if (devMode) console.log("Not on main page. Terminating...")
35+
if (devMode) {
36+
console.log("onNavigation callback called")
37+
console.log("Current page: ", getCurrentPage())
38+
}
39+
// Terminate if we are not on the target pages
40+
if (!runScriptOn.some(page => getCurrentPage() === page)) {
41+
if (devMode) console.log("Not on target pages. Terminating...")
3842
return () => null
3943
}
4044
// Run main function if the target node is present

src/utils/location-change.event.ts

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,16 @@ export interface LocationChangeDetail {
55
oldUrl: URL
66
}
77

8+
/** Refers to the root window object. unsafeWindow in userscripts and window in other contexts */
9+
const _window = unsafeWindow || window
10+
const WATCHER_KEY = "__spa_locationchange_watcher__"
11+
12+
declare global {
13+
interface Window {
14+
[WATCHER_KEY]: boolean
15+
}
16+
}
17+
818
/**
919
* Fires "spa:locationchange" event when url changes
1020
* @returns {Object} An object with a `run` method to start the location watcher.
@@ -22,21 +32,23 @@ export interface LocationChangeDetail {
2232
export function createLocationWatcher() {
2333
let interval: number | null = null
2434
let oldUrl: URL | null = null
35+
console.log("watcher", _window[WATCHER_KEY])
2536
return {
2637
/**
2738
* Ensure the location watcher is actively looking for URL changes. If it's already watching,
2839
* this is a noop.
2940
*/
3041
run() {
31-
if (interval != null) return
42+
if (interval != null || _window[WATCHER_KEY] === true) return
43+
_window[WATCHER_KEY] = true
3244
oldUrl = new URL(location.href)
33-
interval = window.setInterval(() => {
45+
interval = _window.setInterval(() => {
3446
const newUrl = new URL(location.href)
3547
if (oldUrl && newUrl.href !== oldUrl.href) {
36-
window.dispatchEvent(
48+
_window.dispatchEvent(
3749
new CustomEvent("spa:locationchange", {
3850
detail: { newUrl, oldUrl },
39-
}),
51+
})
4052
)
4153
oldUrl = newUrl
4254
}

0 commit comments

Comments
 (0)