Add Discord Rich Presence detail controls
This commit is contained in:
@@ -18,6 +18,22 @@ class ModernWowSetupTool(WowSetupTool):
|
||||
self.auction_throttle_enabled = tk.BooleanVar(master=root, value=True)
|
||||
self.vmmfix_enabled = tk.BooleanVar(master=root, value=False)
|
||||
self.interact_enabled = tk.BooleanVar(master=root, value=False)
|
||||
|
||||
# Discord Rich Presence detail choices are kept independently from the
|
||||
# main WowPresence checkbox so hiding/disabling the integration never
|
||||
# destroys the user's selected disclosure preferences.
|
||||
self.discord_show_character_details = tk.BooleanVar(master=root, value=True)
|
||||
self.discord_detail_vars = {
|
||||
"name": tk.BooleanVar(master=root, value=True),
|
||||
"guild": tk.BooleanVar(master=root, value=True),
|
||||
"race": tk.BooleanVar(master=root, value=True),
|
||||
"faction": tk.BooleanVar(master=root, value=True),
|
||||
"class": tk.BooleanVar(master=root, value=True),
|
||||
"level": tk.BooleanVar(master=root, value=True),
|
||||
"zone": tk.BooleanVar(master=root, value=True),
|
||||
}
|
||||
self.discord_presence_details_frame = None
|
||||
|
||||
self._download_window = None
|
||||
self._download_label = None
|
||||
self._download_detail = None
|
||||
@@ -26,6 +42,167 @@ class ModernWowSetupTool(WowSetupTool):
|
||||
self._download_indeterminate = False
|
||||
super().__init__(root)
|
||||
|
||||
def _collect_settings(self):
|
||||
settings = super()._collect_settings()
|
||||
settings["discord_presence"] = {
|
||||
"show_character_details": bool(self.discord_show_character_details.get()),
|
||||
"details": {
|
||||
name: bool(var.get())
|
||||
for name, var in self.discord_detail_vars.items()
|
||||
},
|
||||
}
|
||||
return settings
|
||||
|
||||
def _apply_settings_dict(self, saved):
|
||||
super()._apply_settings_dict(saved)
|
||||
|
||||
discord = saved.get("discord_presence") if isinstance(saved, dict) else None
|
||||
if not isinstance(discord, dict):
|
||||
return
|
||||
|
||||
show_details = discord.get("show_character_details")
|
||||
if isinstance(show_details, bool):
|
||||
self.discord_show_character_details.set(show_details)
|
||||
|
||||
details = discord.get("details")
|
||||
if isinstance(details, dict):
|
||||
for name, value in details.items():
|
||||
var = self.discord_detail_vars.get(name)
|
||||
if var is not None and isinstance(value, bool):
|
||||
var.set(value)
|
||||
|
||||
def _load_wowpresence_broadcast_preferences(self, target_dir):
|
||||
"""Migrate the old six-bit mask into the new seven-choice UI."""
|
||||
mask = remote_packages.read_wowpresence_broadcast_flags(target_dir)
|
||||
if mask is None:
|
||||
return
|
||||
|
||||
bits = {
|
||||
"name": remote_packages.WOWPRESENCE_SHARE_NAME,
|
||||
"guild": remote_packages.WOWPRESENCE_SHARE_GUILD,
|
||||
"faction": remote_packages.WOWPRESENCE_SHARE_FACTION,
|
||||
"class": remote_packages.WOWPRESENCE_SHARE_CLASS,
|
||||
"level": remote_packages.WOWPRESENCE_SHARE_LEVEL,
|
||||
"zone": remote_packages.WOWPRESENCE_SHARE_ZONE,
|
||||
}
|
||||
for name, bit in bits.items():
|
||||
self.discord_detail_vars[name].set(bool(mask & bit))
|
||||
|
||||
# WowPresence versions before the dedicated Race flag always exposed
|
||||
# race information regardless of the six-bit mask. Treat masks <= 63
|
||||
# as legacy so the migration preserves exactly that visible behavior.
|
||||
if mask <= 63:
|
||||
self.discord_detail_vars["race"].set(True)
|
||||
else:
|
||||
self.discord_detail_vars["race"].set(
|
||||
bool(mask & remote_packages.WOWPRESENCE_SHARE_RACE)
|
||||
)
|
||||
|
||||
# A legacy mask never had a separate master switch. Keeping this on
|
||||
# preserves the previous display while still allowing all individual
|
||||
# choices to be edited.
|
||||
self.discord_show_character_details.set(True)
|
||||
|
||||
def _load_legacy_install_state(self, target_dir):
|
||||
super()._load_legacy_install_state(target_dir)
|
||||
self._load_wowpresence_broadcast_preferences(target_dir)
|
||||
|
||||
def load_settings(self, target_dir):
|
||||
settings_path = self._settings_path(target_dir)
|
||||
has_saved_discord_preferences = False
|
||||
try:
|
||||
with open(settings_path, "r", encoding="utf-8") as handle:
|
||||
saved = json.load(handle)
|
||||
has_saved_discord_preferences = isinstance(
|
||||
saved.get("discord_presence") if isinstance(saved, dict) else None,
|
||||
dict,
|
||||
)
|
||||
except (OSError, json.JSONDecodeError, ValueError, TypeError):
|
||||
pass
|
||||
|
||||
loaded = super().load_settings(target_dir)
|
||||
|
||||
# Existing v2.1 settings.json files predate the detailed controls. Read
|
||||
# their actual WowPresence mask once so manual choices are not lost.
|
||||
if os.path.isfile(settings_path) and not has_saved_discord_preferences:
|
||||
self._load_wowpresence_broadcast_preferences(target_dir)
|
||||
|
||||
self.update_discord_presence_controls()
|
||||
return loaded
|
||||
|
||||
def _discord_broadcast_mask(self):
|
||||
if not self.discord_show_character_details.get():
|
||||
return 0
|
||||
|
||||
bits = {
|
||||
"name": remote_packages.WOWPRESENCE_SHARE_NAME,
|
||||
"guild": remote_packages.WOWPRESENCE_SHARE_GUILD,
|
||||
"race": remote_packages.WOWPRESENCE_SHARE_RACE,
|
||||
"faction": remote_packages.WOWPRESENCE_SHARE_FACTION,
|
||||
"class": remote_packages.WOWPRESENCE_SHARE_CLASS,
|
||||
"level": remote_packages.WOWPRESENCE_SHARE_LEVEL,
|
||||
"zone": remote_packages.WOWPRESENCE_SHARE_ZONE,
|
||||
}
|
||||
mask = 0
|
||||
for name, bit in bits.items():
|
||||
var = self.discord_detail_vars.get(name)
|
||||
if var is not None and var.get():
|
||||
mask |= bit
|
||||
return mask
|
||||
|
||||
def update_discord_presence_controls(self):
|
||||
frame = getattr(self, "discord_presence_details_frame", None)
|
||||
if frame is None:
|
||||
return
|
||||
|
||||
var = self.optional_plugins.get("WowPresence.dll")
|
||||
visible = bool(var is not None and var.get())
|
||||
manager = frame.winfo_manager()
|
||||
|
||||
if visible and not manager:
|
||||
frame.pack(fill="x", padx=(22, 8), pady=(0, 4))
|
||||
elif not visible and manager:
|
||||
frame.pack_forget()
|
||||
|
||||
def _build_discord_presence_details(self, parent):
|
||||
frame = ttk.Frame(parent)
|
||||
self.discord_presence_details_frame = frame
|
||||
|
||||
show_cb = ttk.Checkbutton(
|
||||
frame,
|
||||
text="Show character details",
|
||||
variable=self.discord_show_character_details,
|
||||
)
|
||||
show_cb.pack(anchor="w", padx=6, pady=(1, 2))
|
||||
ToolTip(
|
||||
show_cb,
|
||||
"Controls whether the selected character details are published to Discord. "
|
||||
"The choices below stay available even when this is unchecked.",
|
||||
)
|
||||
|
||||
labels = {
|
||||
"name": "Character Name",
|
||||
"guild": "Guild",
|
||||
"race": "Race",
|
||||
"faction": "Faction",
|
||||
"class": "Class",
|
||||
"level": "Level",
|
||||
"zone": "Zone",
|
||||
}
|
||||
for name, label in labels.items():
|
||||
cb = ttk.Checkbutton(
|
||||
frame,
|
||||
text=label,
|
||||
variable=self.discord_detail_vars[name],
|
||||
)
|
||||
cb.pack(anchor="w", padx=24, pady=1)
|
||||
ToolTip(
|
||||
cb,
|
||||
f"Choose whether WowPresence may publish your {label.lower()} on Discord.",
|
||||
)
|
||||
|
||||
self.update_discord_presence_controls()
|
||||
|
||||
def _show_download_progress(self):
|
||||
if self._download_window is not None and self._download_window.winfo_exists():
|
||||
return
|
||||
@@ -303,14 +480,24 @@ class ModernWowSetupTool(WowSetupTool):
|
||||
for dll, var in self.optional_plugins.items():
|
||||
if dll == "no1600x1200.dll":
|
||||
continue
|
||||
|
||||
command = (
|
||||
self.update_discord_presence_controls
|
||||
if dll == "WowPresence.dll"
|
||||
else None
|
||||
)
|
||||
self._plugin_row(
|
||||
right_frame,
|
||||
optional_display.get(dll, os.path.splitext(dll)[0]),
|
||||
var,
|
||||
optional_attribution.get(dll, "by MarcelineVQ"),
|
||||
self.descriptions.get(dll, ""),
|
||||
command=command,
|
||||
)
|
||||
|
||||
if dll == "WowPresence.dll":
|
||||
self._build_discord_presence_details(right_frame)
|
||||
|
||||
def clean_unselected_files(self, target):
|
||||
super().clean_unselected_files(target)
|
||||
|
||||
@@ -867,6 +1054,11 @@ class ModernWowSetupTool(WowSetupTool):
|
||||
os.remove(legacy_path)
|
||||
except OSError:
|
||||
pass
|
||||
|
||||
remote_packages.write_wowpresence_broadcast_flags(
|
||||
target,
|
||||
self._discord_broadcast_mask(),
|
||||
)
|
||||
else:
|
||||
source_dll = os.path.join(payload_weirdu, dll_name)
|
||||
if os.path.exists(source_dll):
|
||||
|
||||
Reference in New Issue
Block a user