"""The plugin's settings screen. main page global ghost mode switch, the option switches, the accounts account page that account's choice per option (Global / On / Off) and its chat exceptions """ from ui.settings import Divider, Header, Selector, Switch, Text import features import peers from prefs import INHERIT, OFF, ON, account_key, chats_key, global_key GHOST_KEY = "g_ghost" GHOST_ICON = "ghost" def _state(value): return "On" if value else "Off" class SettingsPage: def __init__(self, plugin, prefs, menus): self.plugin = plugin self.prefs = prefs self.menus = menus # main page def build(self): prefs = self.prefs # The master switch shows whether every essential is on (AyuGram's # isGhostModeActive), whichever way they got there. self.plugin.set_setting(GHOST_KEY, prefs.ghost_active(0)) rows = [ Header(text="Ghost mode"), Switch( key=GHOST_KEY, text="Ghost mode", default=False, subtext="Turns all ghost essentials on or off", icon=GHOST_ICON, on_change=self._on_ghost_change, ), Header(text="Ghost essentials"), ] rows += [self._switch(f) for f in features.ESSENTIALS] rows.append(Header(text="Options")) rows += [self._switch(f) for f in features.EXTRAS] rows.append(Divider(text="These are the defaults. Each account can override them, and each chat can override its account: open the chat's ⋮ menu → Ghost mode.")) rows.append(Header(text="Accounts")) accounts = self._accounts() for slot, uid in accounts: rows.append( Text( text=peers.account_name(slot), subtext=self._account_summary(uid), icon="msg_contacts", create_sub_fragment=lambda slot=slot, uid=uid: self.build_account(slot, uid), ) ) if not accounts: rows.append(Text(text="No signed-in accounts", icon="msg_info")) rows.append(Divider(text="The side menu's Ghost mode item opens these options for the account in use.")) return rows def _switch(self, feature): return Switch( key=global_key(feature), text=feature.title, default=feature.default, subtext=feature.subtext, icon=feature.icon, on_change=self._on_essential_change if feature.essential else None, ) def _on_ghost_change(self, enabled): for feature in features.ESSENTIALS: self.prefs.set_global(feature, enabled) self.plugin.set_setting(GHOST_KEY, bool(enabled), True) def _on_essential_change(self, _value): active = self.prefs.ghost_active(0) if bool(self.plugin.get_setting(GHOST_KEY, False)) != active: self.plugin.set_setting(GHOST_KEY, active, True) def _accounts(self): try: return peers.signed_in() except Exception as exc: self.plugin.log(f"accounts: {exc}") return [] def _account_summary(self, uid): overridden = len(self.prefs.account_overrides(uid)) chats = len(self.prefs.chat_overrides(uid)) parts = [f"Ghost mode {_state(self.prefs.ghost_active(uid)).lower()}"] parts.append(f"{overridden} own option{'s' if overridden != 1 else ''}" if overridden else "global options") if chats: parts.append(f"{chats} chat exception{'s' if chats != 1 else ''}") return " · ".join(parts) # account page def build_account(self, slot, uid): prefs = self.prefs ghost_key = f"a_{uid}_ghost" self.plugin.set_setting(ghost_key, self._ghost_choice(uid)) rows = [ Header(text=peers.account_name(slot)), Selector( key=ghost_key, text="Ghost mode", default=INHERIT, items=["Global", "On", "Off"], icon=GHOST_ICON, on_change=lambda choice: self._on_account_ghost_change(uid, choice), ), Header(text="Options"), ] for feature in features.ALL: global_value = prefs.global_value(feature) rows.append( Selector( key=account_key(uid, feature), text=feature.title, default=INHERIT, items=[f"Global ({_state(global_value)})", "On", "Off"], icon=feature.icon, on_change=lambda _choice: self._refresh_account_ghost(uid), ) ) rows.append(Divider(text="Global follows the plugin's main switches.")) rows.append(Header(text="Chat exceptions")) chats = prefs.chat_overrides(uid) for dialog, values in sorted(chats.items(), key=lambda item: peers.dialog_title(slot, item[0]).lower()): rows.append( Text( text=peers.dialog_title(slot, dialog), subtext=" · ".join( f"{features.BY_KEY[k].title}: {_state(v)}" for k, v in values.items() ), icon="msg_discussion", on_click=lambda _view, dialog=dialog: self._edit_chat(slot, uid, dialog), ) ) if chats: rows.append( Text( text="Remove all chat exceptions", icon="msg_delete", red=True, on_click=lambda _view: prefs.clear_chats(uid, True), ) ) else: rows.append(Text(text="No chat exceptions", icon="msg_info")) rows.append(Divider(text="Add one from a chat's ⋮ menu → Ghost mode. Tap an exception to change it.")) return rows def _ghost_choice(self, uid): """What the account's Ghost mode selector shows.""" choices = {self.prefs.account_choice(uid, f) for f in features.ESSENTIALS} if choices == {INHERIT}: return INHERIT return ON if self.prefs.ghost_active(uid) else OFF def _on_account_ghost_change(self, uid, choice): for feature in features.ESSENTIALS: self.prefs.set_account_choice(uid, feature, choice) self.plugin.set_setting(f"a_{uid}_ghost", int(choice), True) def _refresh_account_ghost(self, uid): key = f"a_{uid}_ghost" choice = self._ghost_choice(uid) if self.plugin.get_setting(key, INHERIT) != choice: self.plugin.set_setting(key, choice, True) def _edit_chat(self, slot, uid, dialog): # Reload the page once the dialog closes, so the list shows the result. raw_key = chats_key(uid) def closed(): self.plugin.set_setting(raw_key, self.plugin.get_setting(raw_key, ""), True) self.menus.open_chat_dialog(slot, dialog, closed)