LihonT 2 Luna pre-release

Avatar shapes (circle, flower, rounded square, hexagon, heart, triangle): the own shape everywhere and, through
the members service, the shapes other members published after proving the account with the code in the bio.
Own accent colour and AMOLED, compact bottom bar, Material 3 profile and plus button, save menu (quality, audio
only, photo posts without the watermark), fixed comment cards, "Luna (pre-release)" in the mod screen.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
cheb0chik
2026-10-23 19:03:48 +03:00
parent ce1d870d54
commit e63ca75eac
50 changed files with 5422 additions and 1661 deletions

View File

@@ -136,11 +136,97 @@ class ContextRewriteTest(unittest.TestCase):
self.assertEqual(text.count(".method "), patched.count(".method "), "no method added or lost")
SAVE = """\
.class public final LX/0qv6;
.super LX/0qvW;
.method public final LJ(Landroid/content/Context;LX/0qvX;)V
.registers 18
.prologue
move-object/from16 v2, p2
return-void
.end method
.method public final LJIL(LX/0bqR;)V
.registers 3
return-void
.end method
"""
PHOTO = """\
.class public final Lcom/ss/android/ugc/aweme/share/improve/handler/AwemePhotoDownloadShareAbilityHandler;
.super Lcom/ss/android/ugc/aweme/share/handler/TTShareDefaultHandler;
.method public final LJIILIIL(Landroid/content/Context;Lcom/ss/android/ugc/aweme/share/base/model/BaseSharePackage;LX/0qrm;Landroid/view/View;LX/01h3;)Ljava/lang/Object;
.registers 7
.annotation system Ldalvik/annotation/Signature;
.end annotation
invoke-super/range {p0 .. p5}, Lx/Y;->LJIILIIL()V
move-result-object v0
return-object v0
.end method
"""
class GateRewriteTest(unittest.TestCase):
def test_the_save_gate_comes_first_and_can_end_the_method(self):
patched = media_patch.rewrite_save(SAVE)
self.assertIn(" .registers 18\n\n" + media_patch.SAVE_GATE, patched)
self.assertLess(patched.index(media_patch.SAVE_GATE), patched.index("move-object/from16 v2, p2"))
gate = media_patch.SAVE_GATE
# the arguments are passed as a range, so registers above v15 (p1, p2 here) are fine
self.assertIn("invoke-static/range {p0 .. p2}, " + media_patch.GATE, gate)
self.assertEqual(1, gate.count("return-void"))
self.assertEqual(1, sum(1 for line in gate.splitlines() if line.strip() == ":lihont_go"))
self.assertEqual(1, gate.count("if-eqz v0, :lihont_go"))
for register in ("v1", "v2", "v3"):
self.assertNotIn(register, gate)
self.assertEqual(SAVE.count(".method "), patched.count(".method "))
def test_the_photo_gate_completes_a_taken_over_click_with_true(self):
patched = media_patch.rewrite_photo(PHOTO)
gate = media_patch.PHOTO_GATE
self.assertIn(" .registers 7\n\n" + gate, patched)
self.assertIn("sget-object v0, Ljava/lang/Boolean;->TRUE:Ljava/lang/Boolean;\n\n return-object v0", gate)
self.assertLess(patched.index(gate), patched.index("invoke-super/range"))
def test_second_passes_and_foreign_classes_are_refused(self):
with self.assertRaises(ValueError):
media_patch.rewrite_save(media_patch.rewrite_save(SAVE))
with self.assertRaises(ValueError):
media_patch.rewrite_photo(media_patch.rewrite_photo(PHOTO))
with self.assertRaises(ValueError):
media_patch.rewrite_save(".class public Lx;\n.super Ljava/lang/Object;\n")
with self.assertRaises(ValueError):
media_patch.rewrite_photo(PHOTO.replace("LJIILIIL(", "LJIILIIX("))
def test_the_gates_are_aimed_at_the_menu_class(self):
self.assertEqual({"LX/0qv6;", "LX/0qvL;", "LX/0qvu;"}, set(media_patch.SAVE_OWNERS))
self.assertIn("lihont/two/media/DownloadMenu;->gate(", media_patch.GATE)
self.assertIn("lihont/two/media/DownloadMenu;->gatePhoto(", media_patch.GATE_PHOTO)
REAL_SAVE = ROOT / "work" / "dl" / "smali" / "X" / "0qv6.smali"
@unittest.skipUnless(REAL_SAVE.exists(), "the disassembled X.0qv6 is not in work/")
def test_the_real_save_action_is_rewritten(self):
text = self.REAL_SAVE.read_text(encoding="utf-8").replace(chr(13) + chr(10), chr(10))
patched = media_patch.rewrite_save(text)
self.assertEqual(1, patched.count(media_patch.GATE))
self.assertEqual(text.count(".method "), patched.count(".method "))
class RuntimeTest(unittest.TestCase):
def test_runtime_targets_are_what_the_rewrites_call(self):
both = media_patch.rewrite_source(SOURCE) + media_patch.rewrite_context(CONTEXT)
everything = (media_patch.rewrite_source(SOURCE) + media_patch.rewrite_context(CONTEXT)
+ media_patch.rewrite_save(SAVE) + media_patch.rewrite_photo(PHOTO))
for target in media_patch.runtime_targets():
self.assertIn(target, both)
self.assertIn(target, everything)
if __name__ == "__main__":