lspatch & better hook support #1

Open
aartzz wants to merge 11 commits from aartzz/Plugins-Telegram:feat/exteragram-compat into main
First-time contributor
tested on [Inugram 12.10.1-bbc3d7c](https://github.com/teidesu/inugram/releases/tag/v12.10.1-43) + [aartzz's re:extera 3be81ef](https://github.com/fossSquad/re-extera)
Plugins compiled against exteraGram reference com.exteragram.* classes, so on
other clients their dex fails to link and the plugin cannot start at all
(NoClassDefFoundError for the plugin main class). This adds a minimal,
hand-written compatibility layer that maps the API surface such plugins use
onto the plain Telegram client:

- com/exteragram/**: the settings screen base (a UniversalRecyclerView based
  preferences activity), settings registry, dialogs, drawer/menu helpers,
  vibration and text helpers, plugin/menu constants.
- HostCompat: exposes those classes to plugin class loaders. Plugin dexes are
  loaded with the host app class loader as parent, which cannot see
  com.exteragram.* or de.robv.android.xposed.*, so the InMemoryDexClassLoader
  and DexClassLoader constructors are hooked and such parents are replaced by
  a loader that serves those names from the module APK (or from the host when
  the real exteraGram class is present) and delegates everything else.
- :host-stubs: compile-only signatures of the host API the compatibility
  layer needs. It is never packaged: the real classes are always the ones
  from the hooked application.
Plugin on_click and on_change handlers can open fragments, dialogs and
bulletins, so they have to run on the main thread, the same way exteraGram
calls them. Executing them on the engine queue made such plugins fail with
"Can't create handler inside thread Thread[RePlugins,5,main] that has not
called Looper.prepare()" when they tried to present their settings screen.
ReflBaseFragment.CreateFragment() added a new createView hook on
LanguageSelectActivity on every call, and each hook built its own root layout
while all of them passed the same "is this our fragment" check. The second
addView(actionBar) then threw IllegalStateException: The specified child
already has a parent, which left the plugin list pointing at a detached
layout and the screen rendered empty.
Move compile-only stubs project under app/ directory and resolve theme
keys dynamically to avoid javac inlining compile-time constants.
Record link aliases for fragment options and build https://t.me/exteraSettings
links to match exteraGram behavior.
Parse **bold** and __italic__ markup into StyleSpan spans so plugin
descriptions and labels render properly on plain Telegram clients.
LSPatch keeps the module APK in a writable cache directory, causing ART to
refuse loading DEX files. Mark the file read-only before constructing DexClassLoader.
Introduce DexCompatPatcher to rewrite exteraGram-specific method calls (e.g.
UItem.setTransparent) on hosts lacking them, and hook DexClassLoader and
InMemoryDexClassLoader to apply bytecode patches and handle read-only file
constraints.
feat(hooks): add support for Inugram LSPatch package
Some checks failed
Android CI / build (pull_request) Has been cancelled
d7d14b326c
Add desu.inugram.lsp to the hooked package lists in HookInit and array.xml.
aartzz changed title from lspatch & better hook support to WIP: lspatch & better hook support 2026-09-21 14:21:19 +03:00
feat(plugins): redesign plugin manager UI with card layout
Some checks are pending
Android CI / build (pull_request) Blocked by required conditions
1a0f4c343a
- Rewrite pluginRow() as a full card: icon with initial, name/version/author,
  description, action row (settings + delete)
- Add dynamic theme colors via themeColorOr() reading Telegram Theme keys
- Add scroll background via ReflBaseFragment.SetScrollBackground()
- Style android.widget.Switch with Telegram accent color tint
- Hook SettingsActivity.fillItems to add Plugins entry (id=100)
- Hook SettingsActivity.onClick to open plugin manager from Settings
- Add install bottom sheet: copy URI to temp, parse metadata, show dialog
- Parse plugin metadata including multiline descriptions in parentheses
- Strip leading @ from author field to avoid double @@ in display
- Add linkifyUsernames() for clickable @mentions in install sheet
- Add icon field to PluginInfo and PluginsEngine from plugin metadata
- Add SetScrollBackground() to ReflBaseFragment for themed scroll bg
- Fix static counter i replaced with index parameter in pluginRow()
- Untrack local.properties (already in .gitignore)
aartzz changed title from WIP: lspatch & better hook support to lspatch & better hook support 2026-09-30 15:24:16 +03:00
Some checks are pending
Android CI / build (pull_request) Blocked by required conditions
This pull request can be merged automatically.
Some workflows are waiting to be reviewed.
You are not authorized to merge this pull request.
View command line instructions

Checkout

From your project repository, check out a new branch and test the changes.
git fetch -u feat/exteragram-compat:aartzz-feat/exteragram-compat
git switch aartzz-feat/exteragram-compat

Merge

Merge the changes and update on Forgejo.

Warning: The "Autodetect manual merge" setting is not enabled for this repository, you will have to mark this pull request as manually merged afterwards.

git switch main
git merge --no-ff aartzz-feat/exteragram-compat
git switch aartzz-feat/exteragram-compat
git rebase main
git switch main
git merge --ff-only aartzz-feat/exteragram-compat
git switch aartzz-feat/exteragram-compat
git rebase main
git switch main
git merge --no-ff aartzz-feat/exteragram-compat
git switch main
git merge --squash aartzz-feat/exteragram-compat
git switch main
git merge --ff-only aartzz-feat/exteragram-compat
git switch main
git merge aartzz-feat/exteragram-compat
git push origin main
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
shithappens/Plugins-Telegram!1
No description provided.