# Where the Facebook patches come from Hushfacebook started on 2026-09-24 as an attempt to put every working Facebook patch for Morphe in one place. Before writing anything, we went through every public patch source we could find that touches Facebook (`com.facebook.katana`), Messenger (`com.facebook.orca`) or Facebook Lite (`com.facebook.lite`). This page is what we found and what we took from each. Several Facebook patch sources sit among forks and copies, and Messenger has a bigger patch ecosystem than Facebook itself. Morphe's official bundle ships nothing for any of the three apps. This page is the readable version. The one the scripts hold us to is [sources/facebook-sources.json](../sources/facebook-sources.json), which records every source with its branches and the commits we last read them at, its licence and a hash of the licence text, the Facebook builds it declares, its features, and what we're allowed to take from it. The ledger retains 31 source records in 19 lineages. There are 30 active records and 1 retired record. Active means the recorded source remains present, including archived repositories and older targets. It doesn't mean a source patches the newest Facebook build. A retired source keeps its historical targets and immutable source pins. Unavailable means those historical source pins no longer resolve. Availability is separate from a source's licence disposition and the repository's archived flag. ## How a source gets in Each source in the ledger gets one of four answers: - **adopted** means Hushfacebook ships code from it. Only one source is adopted today. - **candidate** means its licence lets us port code, and we might, once the checks below pass. - **behavior-only** means we never port its code. We can read what it does and find the same thing in Facebook's own code, and that's all. - **rejected** means it's licensed but there's nothing there to take. A source with no licence, or one whose licence can't be combined with GPL-3.0, is behavior-only. So is a source whose Facebook code came from one of those, whatever its own licence says. Before code from a source can ship, the ledger needs the commit it came from, a compatible licence with its URL and hash, the source's name in [NOTICE](../NOTICE), a rule in [provenance.json](../provenance.json) naming that repository and commit, and a release receipt showing the patches applied to both Facebook builds the bundle declares. `scripts/test-facebook-sources.ps1` refuses a ledger that breaks any of that, and so does every local release. `scripts/audit-facebook-sources.ps1` keeps the ledger current. It reads the official Morphe bundle, the Morphe community directory, Awesome Morphe, the Morphe Patch Tracker, Jman's bundle index and the Morphe Archive, searches GitHub and attempts GitLab's configured code-search endpoint for code naming any of the three packages, and then walks every source's branches, forks and licence. It checks watched paths through tree metadata before reading their last changed commit, so a deletion commit can't count as a current source. Retired sources must keep reachable historical pins and stay absent from current branches. An unavailable pin returning, or a retired source returning on a branch, needs review. A repository whose files are byte for byte files the ledger already holds counts as a copy of that source, not as a new one. Anything else that moved (a new source, a licence that disappeared, a branch whose Facebook code changed, a fork we haven't seen) fails the audit with a report and leaves the ledger alone. Only a complete run with no findings, failed requests or skipped sources stamps the day's date. A release won't go out on a census more than 14 days old. The audit never downloads anyone's code. It reads what the forges' APIs say about a repository and hashes licence text in memory. The only files it writes are its report and the ledger's dates. Global GitLab code search wasn't run in the 2026-10-02 audit. The ledger retains that skip. All recorded GitLab sources were read. GitLab.com disables global code search, as its [advanced-search documentation](https://docs.gitlab.com/user/search/advanced_search/) and [exact-code-search documentation](https://docs.gitlab.com/user/search/exact_code_search/) explain, so adding a token doesn't establish complete coverage. A skipped, denied or malformed search now leaves the census unstamped and makes the audit fail. Completing this gate needs a supported global index or a separately verified exhaustive scan of public projects. A search of project names or the already known sources can't stand in for that coverage. ## The two Facebook sources that matter **[andrewliang25/morphe-patches](https://github.com/andrewliang25/morphe-patches)** (GPL-3.0) targets Facebook 577.0.0.50.72. It's the careful one. Facebook renames almost every class on every weekly release, and Andrew's patches never write one of those names down. They find what they need through names Facebook keeps (GraphQL models, log strings, enum names, method shapes) and fail loudly at patch time when an anchor moves, instead of shipping a patch that quietly does nothing. Most of Hushfacebook's patches are ported from here, with fixes, from commit 5db2e57e. The file headers and [provenance.json](../provenance.json) say which ones. It's the only adopted source. The bundle also patches LINE, so the audit only watches its Facebook, shared and extension code. **[SapitoSucio/FroggoMorphePatches](https://github.com/SapitoSucio/FroggoMorphePatches)** (GPL-3.0) targets Facebook 573.0.0.37.74 and has the most features, several of them only on its dev branch: feed auto-refresh blocking, story auto-advance, an AI-post filter, Material You colors and image downloads. It also hardcodes dozens of obfuscated class names that only exist in 573, so none of its code carries over to newer builds as it is. We took ideas and anchors from it, not code. The feed filter here is built differently because of one lesson from Froggo's tracker (issues 3, 19 and 22): stacking several guards with labels at the same instruction of the feed method produced VerifyErrors. Hushfacebook hooks that method once and runs every feed rule from a single Java filter. Two more GPL-3.0 repositories retain Froggo's work for 573. [ArunTS96/FroggoMorphePatches](https://github.com/ArunTS96/FroggoMorphePatches) adds suggested-post filtering and a Following-feed home, spread over several branches. [anemia004/xD-MorphePatches](https://github.com/anemia004/xD-MorphePatches) is archived with a reworked downloader. [nambara4-debug/Nambara-Facebook-Patches](https://github.com/nambara4-debug/Nambara-Facebook-Patches) holds two ZIP files of download variants and no licence, so it's behavior-only. [mben25/morphe-patches](https://github.com/mben25/morphe-patches) is retired as a Facebook source. Its [historical catalog at 4b5ce29f](https://github.com/mben25/morphe-patches/blob/4b5ce29fdbabc7417ed5f4c2108cdf24692896b0/patches-list.json) lists 11 patches for Facebook 573.0.0.37.74. The [source at that commit](https://github.com/mben25/morphe-patches/tree/4b5ce29fdbabc7417ed5f4c2108cdf24692896b0/patches/src/main/kotlin/app/facebook) retains a Material You resource map and Froggo's 573 AI filter. Its downloader saved videos through Facebook's full-screen Save button. Those are historical features and targets. Current main and dev have no Facebook patches in their catalog. The recorded [commit a3152bfc](https://github.com/mben25/morphe-patches/commit/a3152bfc4b204f92e1ed165918d596d46f8cee13) still resolves. It deleted the last Facebook source files, so the Facebook directory at that commit answers 404. The commit and repository aren't missing. The historical source stays a GPL-3.0 candidate under the same adoption checks. ## Older and smaller Facebook sources - [ReVanced](https://gitlab.com/ReVanced/revanced-patches) (GPL-3.0) has two Facebook patches, still pinned to 490.0.0.63.82, and the four Messenger patches most of the Messenger work descends from. Its [GitHub home](https://github.com/ReVanced/revanced-patches) has been blocked by a DMCA notice since March, so GitLab holds it for now. - [RookieEnough/De-Vanced](https://github.com/RookieEnough/De-Vanced) (GPL-3.0). Its dev branch replaced the old ReVanced pair on 2026-09-28, built on runtime method search and hooking rather than fingerprints. As of v1.5.0-dev.4 (its dev branch at commit 432f243f) it has 15 named Facebook patches across 17 source files for 580.0.0.51.74, plus the same eight Messenger patches as main, still pinned to 573.0.0.44.88. Reels playback speed and default playback quality are here too, written from Facebook's own code as Hold a reel for 2x and Default playback quality. Analytics blocking beyond ads, picture-in-picture and its Marketplace, theme and performance patches aren't here yet. - [meridianfresco/morphe-meta-patches](https://github.com/meridianfresco/morphe-meta-patches) (GPL-3.0) is a Morphe port of the ReVanced pair. - [chirag127/morphe-patches](https://github.com/chirag127/morphe-patches) has one Facebook patch, labelled STUB, and [Astronaut10/facebook-morphe-patches](https://github.com/Astronaut10/facebook-morphe-patches) is still the unmodified Morphe template. Both are rejected. More than twenty other repositories are copies of ReVanced's Facebook and Messenger files, most of them byte for byte and some from older releases. The ledger records them as copies of ReVanced rather than as sources, and so does the audit when it finds another one. Eighteen more are excluded: two WebView wrappers around facebook.com, and repositories that only name a Facebook package somewhere, like a launcher list, a localization table, a captured logcat or a build config. The 2026-10-02 review added four fork records without new lineages. Joan's extra work targets BaconReader, and Lenart12's targets BlockBlast. Their Facebook-family code remains upstream code. Alight Motion's [anxyis/anxy-patches](https://github.com/anxyis/anxy-patches) is another package-reference hit, not a Facebook patch source. ## Messenger Messenger isn't in this bundle yet, but it's the obvious next target, and the work already exists under GPL-3.0. [rushiranpise/morphe-patches](https://github.com/rushiranpise/morphe-patches) has the largest set (thirteen patches, including screen capture in encrypted chats and turning off media transcoding), De-Vanced has eight, and ReVanced has the four they all started from. The dev branch of [brskt/revanced-patches](https://gitlab.com/brskt/revanced-patches) removes Meta AI from the inbox, notifications and search. Its main branch is ReVanced's, commit for commit. That branch also found that Messenger 564 moved `onCreate` into an obfuscated superclass, which silently switches off every patch that hooks the application class by name. Two Xposed modules are MIT-licensed and worth reading for a Messenger sibling: [C10udburst/MessengerEx](https://github.com/C10udburst/MessengerEx) and its update [N01-r0/messenger-cleaner-lsposed](https://github.com/N01-r0/messenger-cleaner-lsposed), which also checks a Messenger build's structure before trusting it. [hyowonbernabe/Messenger-Z](https://github.com/hyowonbernabe/Messenger-Z), [Mino260806/MessengerPro](https://github.com/Mino260806/MessengerPro), [pedguedes090/Messenger-Pro](https://github.com/pedguedes090/Messenger-Pro), [NeonOrbit/ChatHeadEnabler](https://github.com/NeonOrbit/ChatHeadEnabler) and [TheRoughy/MessengerPeep](https://github.com/TheRoughy/MessengerPeep) have no licence, so they're behavior-only. Messenger-Z's notes on letting Messenger install beside Facebook are the useful part. ## Facebook Lite [ToThangGTVT/morphe-fb-lite](https://github.com/ToThangGTVT/morphe-fb-lite) declares six patches for Lite 530.0.0.8.106: sponsored posts, coexistence with Meta's app, settings, two font controls and video download with automatic next-Reel control. Main/dev carry that catalog; two older dependency branches retain three font/coexistence patches. Its GPL-3.0 license and source pins were checked on 2026-10-02. The ledger records a candidate. Before adoption, its [NOTICE](https://github.com/ToThangGTVT/morphe-fb-lite/blob/d69c0d6904a75f48256c7dede8559390b5e1e606/NOTICE) requires distinct derivative branding, and the origins of native stubs need independent proof. This doesn't establish Lite support in Hushfacebook. The dev branch of [ShuhaibNC/morphe-patches](https://github.com/ShuhaibNC/morphe-patches) sends Lite links to your own browser on any version. [Ashish-Bansal/OneTapVideoDownload](https://github.com/Ashish-Bansal/OneTapVideoDownload) has GPL-3.0 download hooks for Facebook and Lite from 2018. [BERTO-bid/FBLitePro](https://github.com/BERTO-bid/FBLitePro) hands out a rebuilt Lite APK that extracts cookies, has no licence, and is behavior-only. On 2026-10-02, rushiranpise's Messenger tree was unchanged, but its shared compatibility constants moved from the older source pin to 576.0.0.47.92. Those constants now have their own watch path. NexAlloy's new fix/tiktok-split-apk branches diverge from the removed sync-and-fix history; only FacebookAdHelpers.kt and ad/Fingerprints.kt changed in the Facebook tree comparison. Reels shopping hooks remain on root/nonroot. The new branches still lack them and retain the same behavior-only licensing restriction. ## Outside Morphe The widest map of Facebook's ad and clutter code is in LSPosed modules, not patch sources, and none of it can be ported. - [Loukious/FacebookAppAdsRemover](https://github.com/Loukious/FacebookAppAdsRemover) covers feed, story, Reels, Marketplace and game ads, plus feed filters and link unwrapping. It has no licence, so we only read its README for ideas and anchors, never its code. [gamer765/FacebookAppAdsRemover-Patched](https://github.com/gamer765/FacebookAppAdsRemover-Patched) writes down Facebook 577's Reels and commercial-break paths, and has no licence either. - [gnadgnaoh/NexAlloy-XES](https://github.com/gnadgnaoh/NexAlloy-XES) is GPL-3.0 at the repository level and adds hooks for in-stream ad breaks, profile timeline ads, search ads and link cleaning. Its Facebook master patch says it ports every FacebookAppAdsRemover hook, though, and that code has no licence. So its Facebook code is behavior-only like the original, until Loukious licenses it. - [ByRafaelSystem/FBadsRemoverPro](https://github.com/ByRafaelSystem/FBadsRemoverPro) describes an ad remover and contains only a README and a licence. - [rushiranpise/MetaPlusXposed](https://github.com/rushiranpise/MetaPlusXposed) unlocks the paid Meta Plus subscription, which we leave out. [FahadBinHussain/glitchdraft](https://github.com/FahadBinHussain/glitchdraft) syncs chat drafts through a server, and [ssyss501/XposedBase](https://github.com/ssyss501/XposedBase) is a starter project with one Facebook hook. ## Where Hushfacebook is listed The [Morphe Patch Tracker](https://drnx64.github.io/morphe-track-patches/#/bundle/sysadmindoc) and the [Morphe Archive](https://github.com/rushiforai/morphe-archive/tree/main/examplepatches/SysAdminDoc/Hushfacebook) list it. [Awesome Morphe](https://github.com/nvbangg/awesome-morphe/blob/main/data/bundles/SysAdminDoc~Hushfacebook~main.json) and [Jman's ReVanced Patch Bundles](https://github.com/Jman-Github/ReVanced-Patch-Bundles/blob/bundles/patch-bundles/hushfacebook-patch-bundles/hushfacebook-latest-patches-bundle.json) were also confirmed on 2026-09-27. The [Morphe community directory](https://morphe-patches.software/data/bundles.json) now lists it too, confirmed on 2026-09-30. ## What we left out - An age-verification bypass that one tracker asked for. It gets around a safety control. - Meta Plus and Meta AI premium unlocks. Those get around a paywall. - Exporting and importing login sessions. That handles people's credentials. - Prebuilt patched APKs. Hushfacebook publishes patches only, never Meta's app. ## What's next The gap people ask about most is hiding the Reels entry points, which at least one of the sources above has. Where that source is adopted or a candidate, a new patch can start from its code once the ledger's checks pass. Where it's behavior-only, the patch starts from Facebook's own code instead. Blocking the feed's auto-refresh and turning off story auto-advance led this list until 0.1.5 shipped Block background-return feed refresh and Stop Story auto-advance, both written here. Stripping tracking parameters from shared links was on this list until Sanitize sharing links, and so were the Stories tray and People You May Know until Hide Stories tray and the new switches of Hide suggested and promoted posts. All three were written here from Facebook's own code. The "Suggested for you" switch reads Facebook's recommendation flag to hide posts from accounts you don't follow or groups you haven't joined. Hiding posts Facebook detected as AI, which Froggo, Arun and mben do for 573, is Hide AI-detected posts here. Froggo's 573 member names don't exist in 577 or 580, so it finds the same flag again through the schema keys Facebook's own AI label reads. That label, AI info or AI content next to the poster's name, also shows on a post whose creator said it was made with AI. Reading the 577 and 580 builds showed that the label's plugin reads a second flag for that, on a model of its own beside the detected one, and shows the label on either flag. The industry markers Facebook looks for, like C2PA and IPTC, are listed on the detected model, so they reach the label through the detected flag. Also hide posts labelled as AI, a switch of the same patch, reads the creator's flag as well, found and checked the same way. Saving ordinary feed and Watch videos, asked for in [De-Vanced #148](https://github.com/RookieEnough/De-Vanced/issues/148), came off the list too. Download any video adds its own item to a post's menu and leaves Facebook's Save and Download rows as they are, where the 573 forks took over Facebook's Save. Stop update prompts, asked for on the r/MorpheApp thread, was written here from Facebook's own code as well. No source above touches it, and reading the 577 and 580 builds showed why the prompts can't be stopped from outside: Facebook has no installer of its own, only prompts that hand you to Meta App Manager or Google Play, so the patch takes those prompts and the one request it makes for an update. Drawing Facebook in the phone's own font, the first issue on the tracker, is Use the system font, written here at the exit of Facebook's typeface repository and of the variable-font builders its Bloks text uses. It takes a font file you pick as well, and it reaches the screens built with React Native through the resolver of React Native's own font manager, found by the refusal its typeface utilities log. On an account without Optimistic, Facebook's text engine draws in a Roboto made by one builder of its own, found by the message that builder logs when it can't make one, and a picked file takes that Roboto's place at the builder's exit. The names in bold at the top of a post or in a notification come from text spans that set Android's own default bold, so each read of Android's default typefaces in Facebook's code goes through the same swap. Don't send reel watch history was written here too, and no source above has anything like it. Reading the 577 and 580 builds showed that the Reels viewer sends the reels you watch in batches, as one mutation that carries only their ids. Facebook ranks your Reels feed with it and nobody else sees it, and the patch holds that one send back. Open on a chosen tab, the top request on the r/MorpheApp thread, is written here too. No source above lets you pick the tab Facebook opens on. Reading the 577 and 580 builds showed that Facebook's main screen opens the tab an extra of its launching intent names, the extra its own tab shortcuts and notifications use, so the patch adds that extra to a start from the launcher icon and leaves every other start alone. Marketplace only, which also hides the feed and the other tabs, came off the list as well. It drops those tabs where Facebook builds its tab list and opens on Marketplace through Open on a chosen tab's route. Tap to play, asked for by people whose profile Stories, Reels, Marketplace ads and songs on posts started on their own, is written here as well. No source above has it. Reading the 577 and 580 builds showed that nearly every surface starts its media through one player call that carries the reason for the start, and that Reels and the story viewer never ask Facebook's Autoplay setting, which is why turning that setting off didn't stop them. The patch holds each start at that call unless a tap has just ended, and has the setting read Off so the surfaces that do ask it draw their own play button. Opening comments in an order you choose, asked for by people whose comments kept going back to Most relevant, is Default comment order, written here too. No source above has it. Reading the 577 and 580 builds showed that an ordinary comment sheet's request names no order, so Facebook's servers pick one every time the comments load, even right after you picked another in the sheet's menu. The patch names your order in that request only where it names none, and leaves a pick, a link to one comment and a post's own page alone. Installing Meta's own Messenger beside a patched Facebook, asked for on the r/MorpheApp thread, is Install beside Meta's apps, written here too. Messenger-Z's notes found the two permissions Messenger and Facebook both declare, and take them out of Messenger. This patch renames them in Facebook instead, together with every place Facebook's code names them, so what they guard in Facebook stays guarded and Facebook's own broadcasts keep reaching it. Drawing emoji in the phone's own style, another request from that thread, is Use the phone's emoji. No source above has it either. Facebook draws the emoji in its text with an emoji font Meta downloads, and everything that draws with it gets it from one provider. The patch answers that provider with the phone's default typeface instead, whose fallback is the phone's own emoji font. A chat's big emoji is the exception in Facebook's code. It's a PNG of Meta's emoji, downloaded from an address one method makes, and Facebook draws the emoji with the provider's typeface only until the PNG arrives. That method already answers nothing for an emoji Meta has no picture of, and every screen that asks it then keeps drawing the emoji as text, so the patch has it answer nothing while the switch is on. Hiding the Get Messenger card in Facebook's own Chats was written here too, and no source above has it. Reading the 577 and 580 builds showed that Facebook already leaves the card out when Messenger is installed, but only counts a Messenger signed with its own key. A re-signed Facebook never matches Meta's, so the patch answers the card's own show question for it while Messenger is installed and leaves every other row of Chats alone. Hiding the Upgrades and Also from Meta sections of Facebook's Menu, asked for in issue #9, was written here too, and no source above has it. Reading the 577 and 580 builds showed that the Menu types each group below the shortcuts with one enum whose names Facebook keeps, UPSELL and PRODUCTS_FROM_FACEBOOK among them, and builds each group from two sections, the one it draws itself and one for what its server sends. The patch asks about the group in both and leaves every other group alone. Hushfacebook in the Menu, which puts a row for Hushfacebook's settings in Facebook's Menu, was written here too. The Menu's Settings and privacy group is a list of row items Facebook builds itself, the way it builds its Help rows, so the patch adds one more of Facebook's own rows at its end, known by an id of its own, and opens the settings when that row is tapped. Taking Meta AI's own answers and prompts out of search, which people said pushed the people, groups and posts they looked for further down, is Hide Meta AI in search, written here from Facebook's code. No source above touches search. Reading the 577 and 580 builds showed three decisions in Facebook's code: whether a results page adds a Meta AI answer, which result modules a page holds (each with a role Facebook names, eight of them Meta AI's answer and prompts), and whether a suggestion from Facebook's server opens Meta AI. The patch answers the first no, leaves those eight roles out of the second, and turns the third off. Facebook's server sends its answer card with the results even when the first says no, so the second is what takes it off a phone's screen. The Meta AI tab's own page is left whole, and the Meta AI button still works. Search and profile ads came off the list too, both written here and in no source above. Every page of search results is built from modules that each carry a role, an enum whose names Facebook keeps, and Facebook's own search module class keeps a set of the roles that are ads. Hide sponsored search results leaves a module with one of those roles out of the page before the page is built. On a profile or a Page, the component that draws each post asks the post for its sponsored data and tags an ad's row as sponsored, so Hide sponsored profile posts has it draw nothing for that row. Hiding the suggested groups row, asked for in issue #8, is a new switch of Hide suggested and promoted posts, written here from Facebook's code. No source above has it. Reading the 577 and 580 builds showed that the row shares its model class with People you may know and friend requests. That class tells the three apart by a type tag each, and it answers this row's type name through a table of strings instead of a literal of its own, so the patch checks the tag's case in that table and the switch goes by the name. A post from a group you're in is an ordinary story and stays. The "Stories you might like" row from issue #10 is a switch of the same patch, also written here. The builds show that Facebook sends a row of several people's Stories between posts as a unit of its own, drawn by its Discover unit component, and that the component reads one flag on the unit to open a row of Stories from people you aren't connected to as exactly that. The switch goes by the same flag, so a row of your friends' Stories stays, and so does the Stories tray. Quieting Facebook's promotional push notifications, asked for on r/facebook, is Block promotional notifications, written here too, and no source above has it. Reading the 577 and 580 builds showed that every push Facebook shows carries a type that Facebook reads as the name of one of its own constants, 473 of them, and that all of them are posted from one method of its tray manager. The patch asks about the type first thing in that method, so only the kinds you switch off stay out and a type it doesn't know always posts. Facebook's Android notification categories come from its server. Facebook already drops a push whose category you turned off, but the app can't say which categories an account gets. Viewing stories anonymously, which Loukious's and NexAlloy's modules both offer as hiding a story's seen status, is View stories anonymously here. Both are behavior-only, so it was written from Facebook's own code. The 577 and 580 builds report the stories you view as one mutation, DirectSeenMutation, and send it from one method, so the patch returns from that method before the request is built. Replies and reactions are sent from another class and still go out. Playing videos at a chosen quality, which De-Vanced offers for Reels and stories, is Default playback quality, written here from Facebook's own code. Reading the 577 and 580 builds showed that Facebook's quality menu applies a pick to one video only, through the custom-quality setter of the DASH format evaluator that picks the video's tracks, and that the evaluator keeps a preselected label its first choice hands to that setter, which nothing in Facebook fills in. The patch fills it in with the quality you chose, so each new video starts the way a pick in that menu would leave it. Hiding the stories Facebook suggests inside the Stories tray, asked for in issue #7, was written here too, and no source above has it. Reading the 577 and 580 builds showed that every answer of the tray's fetch, from the network or the cache, goes through one post-processing step that hands the stories, one bucket per person or Page, to one constructor, and that both of Facebook's trays draw from what it builds. Each bucket carries a flag, is_story_bucket_suggested, and a list of labels, and the tray's own card writes Suggested under a name when the flag is true or the first label is SUGGESTED. Hide suggested stories goes first in that constructor and leaves those buckets out, reading them through the tray's own flag accessor and Facebook's own label helper. The feed's row of Stories you might like (issue #10) is a different surface, and it has its own switch in Hide suggested and promoted posts. Marketplace ads came off the list too, with Hide sponsored Marketplace listings, written here and in no source above. Marketplace is drawn by React Native, so its listings and ads never pass through a list in Facebook's Java code. The requests its React Native code sends do, though. Facebook's own Networking module reads each request's body before it sends it, and Facebook's code keeps a list of the four Marketplace queries that fetch nothing but ads. The feed's own query declares two variables that ask the server to skip its ads and boosted listings. The patch sets those to true where the query names them, and the four ads-only queries don't go out. Search needed a second half. Its results query names neither variable and has no ads-only query beside it, so the ads come back among the listings. The same module hands each answer to React Native through its Tigon callbacks, a class Facebook keeps under its own name, and the patch takes the ads out there. A result is an ad when its story's type is an ad story or it carries sponsored data. Those names come from Facebook's web search, where uBlock Origin's filter list also looks for `MarketplaceFeedAdStory`. Video ads are the one Marketplace ad drawn by Facebook's own Litho components rather than React Native's, and De-Vanced's ad patch returns nothing from the two that draw them. Hushfacebook does the same, found in 577, 580 and 581 by the strings only each component holds. Instant Games ads are De-Vanced's idea too. Its ad patch drops a game's ad messages at the game bridge, which leaves the game waiting on an answer. Block Instant Games ads, written here, answers them instead, through the bridge's own call for rejecting a game's promise, with the code Facebook's game SDK uses for an ad it can't serve. Hiding posts by words you choose is Hide posts by words, written here from Facebook's code. Reading the 577 and 580 builds showed that GraphQLStory keeps a post's own words in its message, and that GraphQLStory's own toString calls that text "message.text" and reads it as the field `text`. The patch finds the message's accessor by the schema keys it loads, and the post a share wraps by its `attached_story` keys, and the extension reads both texts through the same kept reader. It matches plain phrases with case folded, lets a keep list win, keeps a post whose text it can't read, and never puts a word in the diagnostic report. Suggesting people to tag only after @, which [people on r/facebook](https://www.reddit.com/r/facebook/comments/1lhtflc/) asked for and [FB Purity](https://www.fbpurity.com/user-guide.htm) offers on the web, was written here too, and no source above has it for the app. Reading the 577 and 580 builds showed that every text box that can tag people, the post composer's and the comment composer's among them, is one Facebook view that decides on each edit whether the word at the cursor is a lookup. A word starting with @ or # always is, and so is any longer word without either, which Facebook's code calls an implicit mention. The view already has a switch of its own for that last kind. Once it has seen that a word doesn't start with @, it reads a flag, and when the flag is set it returns before looking anyone up. The patch answers that flag while its switch is on, so @ and # work as before and the text itself is never touched. Picking a long video up where you left it, which FacebookAppAdsRemover describes, is Resume long videos, written here from Facebook's own code, since that repository has no licence to reuse. Reading the 577 and 580 builds showed that nearly every video plays through one player class, which keeps two methods by name: one it runs when a video starts playing and one it runs when it stops. Its seek, release and bind hold trace strings Facebook keeps, and its position and length readers are the two its own remaining-time sum subtracts. The patch has those five places tell the extension about the video, which saves where a long one stopped and seeks there once the next time it starts from the beginning. A seek before that, yours or Facebook's own, wins. The video's id, length and kind come from the player's params, whose field names Facebook's own debug dump reports. Hiding the row of Meta AI questions under posts, asked for in issue #48, is Hide Meta AI questions under posts, written here from Facebook's own code. Reading the 577 and 580 builds showed that one static method draws every kind of row Facebook calls a deep dive pill under a post, and names itself DeepDivePillSocket. It goes through the pill plugins in a fixed order, loading each plugin's class name before asking whether that plugin applies to the post, and draws the first one that does. Meta AI's questions are GenAiDeepDivePillPlugin. The patch hands each answer to the extension with the plugin's name, and while the switch is on the answer for Meta AI's plugin is a no, so the socket goes on to the next plugin. A plugin that says yes without a look of its own gets the socket's default way of drawing a pill, which gives a pill typed meta_ai Meta AI's icon, and the default click handler's check doesn't look at the type. So the patch also hands the type that way reads, once every icon has been picked, to the extension, which drops a meta_ai pill while the switch is on. Keeping the date under the poster's name, asked for in issue #40, is Keep post dates, written here from Facebook's own code. Reading the 577 and 580 builds showed that the render of Facebook's newer post header subtitle, the class that names itself FDSPostHeaderSubtitle, works out whether to rotate that line, logs the answer as in_cycling_experiment right after the call that gives it, and only then branches. A yes with two or more texts from the header's subtitle plugins draws a component that rotates them, and a no draws the one line with the date that accounts outside the experiment get. The patch hands that answer to the extension at the log, which says no while the switch is on. No source above has it. Taking the header off the Feeds tab, asked for in issue #34, is Hide the Feeds header, written here from Facebook's own code. Reading the 577 and 580 builds showed that the Feeds tab is FeedFiltersFragment, which keeps its name and its members' names. The tab's chrome builds a title row only when that fragment's shouldInitializeNavBar says yes, so the patch hands each of its answers to the extension, which says no while the switch is on. The filters go in a container the fragment builds, adds to its view hidden and keeps in tabBarContainer, and onCreateView hands that container to the controller that fills it and shows it once the filters load. Right before that controller is made, while the switch is on, the patch hands it a new container built the same way, which is never on screen, so Facebook's own stays hidden. That alone left the posts as far down as the filters are tall. The fragment's feedFiltersFragmentContainerController posts a runnable, which Redex still names FeedFiltersFragmentContainerController$setViewPagerTopMargin$1, and its run() sets the posts' top margin to the filters' height when it's told they show and to nothing when they don't. The patch hands that answer to the extension right after run() reads it, and the extension says no for a tab whose filters went to the container that's never on screen, so the posts start at the top. Facebook asks again each time the filters load, so the answer goes by what was done with that tab's filters rather than by the switch, and flipping the switch with the tab open can't leave a gap or put the posts under filters that show. Opened from the menu, Feeds runs in an ImmersiveActivity that draws its own bar with back and search in place of the tab's title row, and that bar stays. No source above has it. Putting the tab bar at the bottom, asked for in issue #49, is Tab bar at the bottom, written here from Facebook's own code. Reading the 577 and 580 builds showed that Facebook keeps a preference of its own, fb4a_bottom_tabs_override_enabled, that overrides the server setting for where the tab bar goes, and that the two places deciding it read that preference as a three-way value and branch on it: yes for the bottom, no for the top, and unset leaving it to the server. The patch hands each answer to the extension, which says yes while the switch is on. Facebook's own tab menu writes the same preference and is left alone. No source above has it. Hide post prompts and Hide reel interest prompts came from andrewliang25's dev branch at commit 16464b2b, and Hide affiliate product links from commit a934b406, GPL-3.0 like the rest of that source. The first two remove the "Are you interested in this post?" strip on feed posts and the "Are you interested in this reel?" prompt. The third removes the shop cards a creator attaches to a post, on a reel, under a feed post and in the comment sheet, and leaves the "Commission eligible" disclosure label alone. All three use Andrew's anchors, with a switch in front of each so Pause reaches them. Holding back Facebook's analytics uploads, which De-Vanced's Disable analytics and telemetry does with early returns across many upload services, is Hold back analytics uploads, written here from Facebook's own code. Reading the 577, 580 and 581 builds showed that the XAnalytics logger's upload has one caller for its three-minute foreground upload and one for resuming the uploader at start-up, both in classes that keep their names, and that the Papaya job asks Facebook's config whether Papaya is on before it starts anything. The patch skips those two calls and answers that question with no, so a held Papaya job takes the path Facebook's own off switch takes. Allowing screenshots on the pages Facebook blocks them on is something ReVanced's universal Remove screenshot restriction patch, Loukious and NexAlloy all do. Allow screenshots is written here. Reading the 577, 580 and 581 builds showed Facebook marks a page secure through Android's own window calls and the flags of the window settings it builds dialogs with, so every one of those goes through Hushfacebook, which takes the secure flag out while the switch is on and passes the rest as Facebook asked. Keeping Facebook from noticing screenshots is ReVanced's universal Prevent screenshot detection, and Loukious and NexAlloy block capture detection too. Block screenshot detection is written here. In the 577, 580 and 581 builds every screenshot detector Facebook has shares one photo library observer that keeps its name, so a check goes first in it, and the Android 14 and 15 screen capture and recording requests go through Hushfacebook, which doesn't make them while the switch is on. Hiding single tabs is something Loukious does for the Marketplace and Games tabs. Hide tabs is written here, as one more rule of the tab bar filter Marketplace only and Hide the Reels tab already use, and it covers Feeds, Friends, Groups and Events too, each by the tab class Facebook keeps the name of. If you know of a Facebook patch source we missed, open an issue with a link.