This commit is contained in:
+146
-84
@@ -19,127 +19,189 @@
|
||||
}
|
||||
"""
|
||||
|
||||
priority = 0
|
||||
__author__ = "wowlikon <wowlikon@gmail.com>"
|
||||
__version__ = "1.0.0"
|
||||
from typing import Any, Dict
|
||||
|
||||
# imports
|
||||
from lxml import etree
|
||||
from typing import Dict, Any
|
||||
from pydantic import Field, BaseModel
|
||||
from pydantic import BaseModel, Field, model_validator
|
||||
|
||||
from utils.config import PatchTemplate
|
||||
from utils.public import change_color, insert_after_color, insert_after_public
|
||||
|
||||
from utils.config import PatchConfig
|
||||
from utils.public import (
|
||||
insert_after_public,
|
||||
insert_after_color,
|
||||
change_color,
|
||||
)
|
||||
|
||||
#Config
|
||||
class Gradient(BaseModel):
|
||||
priority: int = Field(frozen=True, exclude=True, default=0)
|
||||
angle: float = Field(0.0, description="Угол градиента")
|
||||
start_color: str = Field("#ffccff00", description="Начальный цвет градиента")
|
||||
end_color: str = Field("#ffcccc00", description="Конечный цвет градиента")
|
||||
|
||||
|
||||
class Logo(BaseModel):
|
||||
gradient: Gradient = Field(Gradient(), description="Настройки градиента") # type: ignore [reportCallIssue]
|
||||
gradient: Gradient = Field(
|
||||
default_factory=Gradient, description="Настройки градиента"
|
||||
)
|
||||
ears_color: str = Field("#ffd0d0d0", description="Цвет ушей логотипа")
|
||||
|
||||
|
||||
class Colors(BaseModel):
|
||||
primary: str = Field("#ccff00", description="Основной цвет")
|
||||
secondary: str = Field("#ffcccc00", description="Вторичный цвет")
|
||||
background: str = Field("#ffffff", description="Фоновый цвет")
|
||||
text: str = Field("#000000", description="Цвет текста")
|
||||
|
||||
class Config(PatchConfig):
|
||||
logo: Logo = Field(Logo(), description="Настройки цветов логотипа") # type: ignore [reportCallIssue]
|
||||
colors: Colors = Field(Colors(), description="Настройки цветов") # type: ignore [reportCallIssue]
|
||||
|
||||
# Patch
|
||||
def apply(config: Config, base: Dict[str, Any]) -> bool:
|
||||
main_color = config.colors.primary
|
||||
splash_color = config.colors.secondary
|
||||
class Patch(PatchTemplate):
|
||||
priority: int = Field(frozen=True, exclude=True, default=0)
|
||||
logo: Logo = Field(default_factory=Logo, description="Настройки цветов логотипа")
|
||||
colors: Colors = Field(default_factory=Colors, description="Настройки цветов")
|
||||
|
||||
# Обновление сообщения об отсутствии подключения
|
||||
with open("./decompiled/assets/no_connection.html", "r", encoding="utf-8") as file:
|
||||
file_contents = file.read()
|
||||
@model_validator(mode="before")
|
||||
@classmethod
|
||||
def validate_nested(cls, data):
|
||||
if isinstance(data, dict):
|
||||
if "logo" in data and isinstance(data["logo"], dict):
|
||||
data["logo"] = Logo(**data["logo"])
|
||||
if "colors" in data and isinstance(data["colors"], dict):
|
||||
data["colors"] = Colors(**data["colors"])
|
||||
return data
|
||||
|
||||
new_contents = file_contents.replace("#f04e4e", main_color)
|
||||
def hex_to_lottie(hex_color: str) -> tuple[float, float, float]:
|
||||
hex_color = hex_color.lstrip("#")
|
||||
hex_color = hex_color[2:] if len(hex_color) == 8 else hex_color
|
||||
return (
|
||||
int(hex_color[:2], 16) / 255.0,
|
||||
int(hex_color[2:4], 16) / 255.0,
|
||||
int(hex_color[4:6], 16) / 255.0,
|
||||
)
|
||||
|
||||
with open("./decompiled/assets/no_connection.html", "w", encoding="utf-8") as file:
|
||||
file.write(new_contents)
|
||||
def apply(self, base: Dict[str, Any]) -> bool:
|
||||
main_color = self.colors.primary
|
||||
splash_color = self.colors.secondary
|
||||
|
||||
# Суффиксы лого
|
||||
drawable_types = ["", "-night"]
|
||||
# Обновление сообщения об отсутствии подключения
|
||||
with open(
|
||||
"./decompiled/assets/no_connection.html", "r", encoding="utf-8"
|
||||
) as file:
|
||||
file_contents = file.read()
|
||||
|
||||
for drawable_type in drawable_types:
|
||||
# Градиент лого приложения
|
||||
file_path = f"./decompiled/res/drawable{drawable_type}/$logo__0.xml"
|
||||
new_contents = file_contents.replace("#f04e4e", main_color)
|
||||
|
||||
parser = etree.XMLParser(remove_blank_text=True)
|
||||
tree = etree.parse(file_path, parser)
|
||||
root = tree.getroot()
|
||||
with open(
|
||||
"./decompiled/assets/no_connection.html", "w", encoding="utf-8"
|
||||
) as file:
|
||||
file.write(new_contents)
|
||||
|
||||
# Замена атрибутов значениями из конфигурации
|
||||
root.set(f"{{{base['xml_ns']['android']}}}angle", str(config.logo.gradient.angle))
|
||||
root.set(f"{{{base['xml_ns']['android']}}}startColor", config.logo.gradient.start_color)
|
||||
root.set(f"{{{base['xml_ns']['android']}}}endColor", config.logo.gradient.end_color)
|
||||
# Суффиксы лого
|
||||
drawable_types = ["", "-night"]
|
||||
|
||||
# Сохранение
|
||||
tree.write(file_path, pretty_print=True, xml_declaration=True, encoding="utf-8")
|
||||
for drawable_type in drawable_types:
|
||||
# Градиент лого приложения
|
||||
file_path = f"./decompiled/res/drawable{drawable_type}/$logo__0.xml"
|
||||
|
||||
# Замена анимации лого
|
||||
file_path = f"./decompiled/res/drawable{drawable_type}/$logo_splash_anim__0.xml"
|
||||
parser = etree.XMLParser(remove_blank_text=True)
|
||||
tree = etree.parse(file_path, parser)
|
||||
root = tree.getroot()
|
||||
|
||||
parser = etree.XMLParser(remove_blank_text=True)
|
||||
tree = etree.parse(file_path, parser)
|
||||
root = tree.getroot()
|
||||
# Замена атрибутов значениями из конфигурации
|
||||
root.set(
|
||||
f"{{{base['xml_ns']['android']}}}angle", str(self.logo.gradient.angle)
|
||||
)
|
||||
root.set(
|
||||
f"{{{base['xml_ns']['android']}}}startColor",
|
||||
self.logo.gradient.start_color,
|
||||
)
|
||||
root.set(
|
||||
f"{{{base['xml_ns']['android']}}}endColor", self.logo.gradient.end_color
|
||||
)
|
||||
|
||||
for el in root.findall("path", namespaces=base["xml_ns"]):
|
||||
name = el.get(f"{{{base['xml_ns']['android']}}}name")
|
||||
if name == "path":
|
||||
el.set(f"{{{base['xml_ns']['android']}}}fillColor", config.colors.secondary)
|
||||
elif name in ["path_1", "path_2"]:
|
||||
el.set(f"{{{base['xml_ns']['android']}}}fillColor", config.logo.ears_color)
|
||||
# Сохранение
|
||||
tree.write(
|
||||
file_path, pretty_print=True, xml_declaration=True, encoding="utf-8"
|
||||
)
|
||||
|
||||
# Сохранение
|
||||
tree.write(file_path, pretty_print=True, xml_declaration=True, encoding="utf-8")
|
||||
# Замена анимации лого
|
||||
file_path = (
|
||||
f"./decompiled/res/drawable{drawable_type}/$logo_splash_anim__0.xml"
|
||||
)
|
||||
|
||||
for filename in ["$ic_launcher_foreground__0", "$ic_banner_foreground__0"]:
|
||||
file_path = f"./decompiled/res/drawable-v24/{filename}.xml"
|
||||
parser = etree.XMLParser(remove_blank_text=True)
|
||||
tree = etree.parse(file_path, parser)
|
||||
root = tree.getroot()
|
||||
|
||||
parser = etree.XMLParser(remove_blank_text=True)
|
||||
tree = etree.parse(file_path, parser)
|
||||
root = tree.getroot()
|
||||
for el in root.findall("path", namespaces=base["xml_ns"]):
|
||||
name = el.get(f"{{{base['xml_ns']['android']}}}name")
|
||||
if name == "path":
|
||||
el.set(
|
||||
f"{{{base['xml_ns']['android']}}}fillColor",
|
||||
self.colors.secondary,
|
||||
)
|
||||
elif name in ["path_1", "path_2"]:
|
||||
el.set(
|
||||
f"{{{base['xml_ns']['android']}}}fillColor",
|
||||
self.logo.ears_color,
|
||||
)
|
||||
|
||||
# Замена атрибутов значениями из конфигурации
|
||||
root.set(f"{{{base['xml_ns']['android']}}}angle", str(config.logo.gradient.angle))
|
||||
items = root.findall("item", namespaces=base['xml_ns'])
|
||||
assert len(items) == 2
|
||||
items[0].set(f"{{{base['xml_ns']['android']}}}color", config.logo.gradient.start_color)
|
||||
items[1].set(f"{{{base['xml_ns']['android']}}}color", config.logo.gradient.end_color)
|
||||
# Сохранение
|
||||
tree.write(
|
||||
file_path, pretty_print=True, xml_declaration=True, encoding="utf-8"
|
||||
)
|
||||
|
||||
# Сохранение
|
||||
tree.write(file_path, pretty_print=True, xml_declaration=True, encoding="utf-8")
|
||||
for filename in ["$ic_launcher_foreground__0", "$ic_banner_foreground__0"]:
|
||||
file_path = f"./decompiled/res/drawable-v24/{filename}.xml"
|
||||
|
||||
# Добаление новых цветов для темы
|
||||
insert_after_public("carmine", "custom_color")
|
||||
insert_after_public("carmine_alpha_10", "custom_color_alpha_10")
|
||||
insert_after_color("carmine", "custom_color", main_color[0]+'ff'+main_color[1:])
|
||||
insert_after_color("carmine_alpha_10", "custom_color_alpha_10", main_color[0]+'1a'+main_color[1:])
|
||||
parser = etree.XMLParser(remove_blank_text=True)
|
||||
tree = etree.parse(file_path, parser)
|
||||
root = tree.getroot()
|
||||
|
||||
# Замена цветов
|
||||
change_color("accent_alpha_10", main_color[0]+'1a'+main_color[1:])
|
||||
change_color("accent_alpha_20", main_color[0]+'33'+main_color[1:])
|
||||
change_color("accent_alpha_50", main_color[0]+'80'+main_color[1:])
|
||||
change_color("accent_alpha_70", main_color[0]+'b3'+main_color[1:])
|
||||
# Замена атрибутов значениями из конфигурации
|
||||
root.set(
|
||||
f"{{{base['xml_ns']['android']}}}angle", str(self.logo.gradient.angle)
|
||||
)
|
||||
items = root.findall("item", namespaces=base["xml_ns"])
|
||||
assert len(items) == 2
|
||||
items[0].set(
|
||||
f"{{{base['xml_ns']['android']}}}color", self.logo.gradient.start_color
|
||||
)
|
||||
items[1].set(
|
||||
f"{{{base['xml_ns']['android']}}}color", self.logo.gradient.end_color
|
||||
)
|
||||
|
||||
change_color("colorAccent", main_color[0]+'ff'+main_color[1:])
|
||||
change_color("link_color", main_color[0]+'ff'+main_color[1:])
|
||||
change_color("link_color_alpha_70", main_color[0]+'b3'+main_color[1:])
|
||||
change_color("refresh_progress", main_color[0]+'ff'+main_color[1:])
|
||||
# Сохранение
|
||||
tree.write(
|
||||
file_path, pretty_print=True, xml_declaration=True, encoding="utf-8"
|
||||
)
|
||||
|
||||
change_color("ic_launcher_background", "#ff000000")
|
||||
change_color("bottom_nav_indicator_active", "#ffffffff")
|
||||
change_color("bottom_nav_indicator_icon_checked", main_color[0]+'ff'+main_color[1:])
|
||||
change_color("bottom_nav_indicator_label_checked", main_color[0]+'ff'+main_color[1:])
|
||||
# Добаление новых цветов для темы
|
||||
insert_after_public("carmine", "custom_color")
|
||||
insert_after_public("carmine_alpha_10", "custom_color_alpha_10")
|
||||
insert_after_color(
|
||||
"carmine", "custom_color", main_color[0] + "ff" + main_color[1:]
|
||||
)
|
||||
insert_after_color(
|
||||
"carmine_alpha_10",
|
||||
"custom_color_alpha_10",
|
||||
main_color[0] + "1a" + main_color[1:],
|
||||
)
|
||||
|
||||
return True
|
||||
# Замена цветов
|
||||
change_color("accent_alpha_10", main_color[0] + "1a" + main_color[1:])
|
||||
change_color("accent_alpha_20", main_color[0] + "33" + main_color[1:])
|
||||
change_color("accent_alpha_50", main_color[0] + "80" + main_color[1:])
|
||||
change_color("accent_alpha_70", main_color[0] + "b3" + main_color[1:])
|
||||
|
||||
change_color("colorAccent", main_color[0] + "ff" + main_color[1:])
|
||||
change_color("link_color", main_color[0] + "ff" + main_color[1:])
|
||||
change_color("link_color_alpha_70", main_color[0] + "b3" + main_color[1:])
|
||||
change_color("refresh_progress", main_color[0] + "ff" + main_color[1:])
|
||||
|
||||
change_color("ic_launcher_background", "#ff000000")
|
||||
change_color("bottom_nav_indicator_active", "#ffffffff")
|
||||
change_color(
|
||||
"bottom_nav_indicator_icon_checked", main_color[0] + "ff" + main_color[1:]
|
||||
)
|
||||
change_color(
|
||||
"bottom_nav_indicator_label_checked", main_color[0] + "ff" + main_color[1:]
|
||||
)
|
||||
|
||||
return True
|
||||
|
||||
Reference in New Issue
Block a user