Skip to content

Commit 8d6c1dc

Browse files
committed
6-16-25-fix
1 parent 9e0341b commit 8d6c1dc

2 files changed

Lines changed: 63 additions & 122 deletions

File tree

config_handler.py

Lines changed: 1 addition & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -149,72 +149,4 @@ def get_all_instance_root_statuses(config_path: str) -> Dict[str, bool]:
149149
if not statuses:
150150
logger.info(f"No instance root status settings found in {config_path}.")
151151

152-
return statuses
153-
154-
155-
def is_root_enabled(config_path: str, instance_name: str) -> Optional[bool]:
156-
"""
157-
Checks if root access is enabled for a *single* given instance.
158-
159-
Less efficient than get_all_instance_root_statuses if checking multiple instances.
160-
161-
Args:
162-
config_path: Path to the configuration file.
163-
instance_name: The name of the instance.
164-
165-
Returns:
166-
True if root is enabled ('="1"'), False if disabled ('="0"' or setting not found),
167-
None if the file cannot be read or another error occurs.
168-
"""
169-
if not os.path.isfile(config_path):
170-
logger.warning(f"Config file not found for checking root status: {config_path}")
171-
return None
172-
173-
setting_key = (
174-
f"{constants.INSTANCE_PREFIX}{instance_name}{constants.ENABLE_ROOT_KEY}"
175-
)
176-
177-
enabled_pattern = re.compile(
178-
r"^" + re.escape(setting_key) + r'\s*=\s*"1"\s*$', re.IGNORECASE
179-
)
180-
181-
setting_exists_pattern = re.compile(
182-
r"^" + re.escape(setting_key) + r'\s*=\s*"[^"]*"\s*$', re.IGNORECASE
183-
)
184-
185-
setting_found = False
186-
try:
187-
with open(config_path, "r", encoding="utf-8") as file:
188-
for line in file:
189-
stripped_line = line.strip()
190-
if enabled_pattern.match(stripped_line):
191-
logger.debug(
192-
f"Root access for instance '{instance_name}' is explicitly enabled ('= \"1\"')."
193-
)
194-
return True
195-
if setting_exists_pattern.match(stripped_line):
196-
197-
setting_found = True
198-
199-
logger.debug(
200-
f"Found root access setting for '{instance_name}', but value is not '1'."
201-
)
202-
break
203-
204-
if setting_found:
205-
logger.debug(
206-
f"Root access for instance '{instance_name}' is disabled (setting found but not '= \"1\"')."
207-
)
208-
return False
209-
else:
210-
211-
logger.debug(
212-
f"Root access setting key '{setting_key}' not found in {config_path}."
213-
)
214-
return False
215-
216-
except Exception:
217-
logger.exception(
218-
f"Error reading config file {config_path} while checking root for {instance_name}."
219-
)
220-
return None
152+
return statuses

main.py

Lines changed: 62 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -756,41 +756,6 @@ def _check_and_kill_bluestacks_worker(self) -> None:
756756
logger.exception(error_message)
757757
raise Exception(error_message) from e
758758

759-
def _toggle_single_instance_root(self, unique_id: str) -> None:
760-
"""Toggles root for a single, uniquely identified instance."""
761-
if not self.worker:
762-
raise Exception("Worker not available.")
763-
764-
instance = self.instance_data.get(unique_id)
765-
if not instance:
766-
raise Exception(f"Instance data missing for {unique_id}.")
767-
768-
config_path = instance["config_path"]
769-
original_name = instance["original_name"]
770-
if not os.path.isfile(config_path):
771-
raise FileNotFoundError(f"Config file not found: {config_path}")
772-
773-
current_state = instance.get("root_enabled", False)
774-
new_state_val = "0" if current_state else "1"
775-
new_state_bool = not current_state
776-
on_off_text = (
777-
self.translation_manager.get_translation("On")
778-
if new_state_bool
779-
else self.translation_manager.get_translation("Off")
780-
)
781-
782-
try:
783-
setting_key = f"{constants.INSTANCE_PREFIX}{original_name}{constants.ENABLE_ROOT_KEY}"
784-
config_handler.modify_config_file(config_path, setting_key, new_state_val)
785-
config_handler.modify_config_file(config_path, constants.FEATURE_ROOTING_KEY, new_state_val)
786-
787-
self.instance_data[unique_id]["root_enabled"] = new_state_bool
788-
self.worker.instance_status_updated.emit(unique_id, "root", on_off_text)
789-
logger.info(f"Root toggled for instance: {unique_id} to {on_off_text}")
790-
except Exception as e:
791-
logger.exception(f"Failed to toggle root for instance {unique_id}")
792-
raise Exception(f"Failed to modify config for {unique_id}: {e}") from e
793-
794759
def _toggle_single_instance_rw(self, unique_id: str) -> None:
795760
"""Toggles R/W for a single, uniquely identified instance."""
796761
if not self.worker:
@@ -836,41 +801,85 @@ def _toggle_single_instance_rw(self, unique_id: str) -> None:
836801
raise Exception(f"Failed to modify instance files for {unique_id}: {e}") from e
837802

838803
def _perform_root_toggle_operation(self) -> None:
804+
"""
805+
FIXED: This operation toggles root for selected instances and then sets the
806+
global root flag based on the final state of ALL instances per config file.
807+
This prevents toggling one instance from breaking others.
808+
"""
839809
if not self.worker:
840810
return
841811
try:
842812
self._check_and_kill_bluestacks_worker()
843813
except Exception as e:
844814
self.worker.error.emit(str(e))
845815
return
846-
847-
selected_ids = [
848-
uid for uid, w in self.instance_checkboxes.items() if w["checkbox"].isChecked()
849-
]
850-
816+
817+
selected_ids = {uid for uid, w in self.instance_checkboxes.items() if w["checkbox"].isChecked()}
818+
if not selected_ids:
819+
return
820+
821+
# Show reminder if the user is turning root ON for any instance
851822
show_reminder = any(
852823
not self.instance_data.get(uid, {}).get("root_enabled", False)
853824
for uid in selected_ids
854825
)
855826
if show_reminder:
856827
self.worker.operation_message.emit("reminder", "show_magisk_reminder")
857-
858-
for unique_id in selected_ids:
859-
self.worker.operation_message.emit(
860-
"info",
861-
self.translation_manager.get_translation(
862-
"Toggling Root for {}..."
863-
).format(unique_id),
864-
)
828+
829+
# Group all instances by their config file path to process them in batches
830+
configs_map: Dict[str, List[Dict[str, Any]]] = {}
831+
for instance in self.instance_data.values():
832+
path = instance["config_path"]
833+
if path not in configs_map:
834+
configs_map[path] = []
835+
configs_map[path].append(instance)
836+
837+
# --- Main Logic ---
838+
for config_path, instances_in_config in configs_map.items():
839+
# Check if this config file is affected by the user's selection
840+
if not any(inst["unique_id"] in selected_ids for inst in instances_in_config):
841+
continue # Skip this config file if no instances in it were selected
842+
865843
try:
866-
self._toggle_single_instance_root(unique_id)
844+
# 1. Toggle the individual root flags for selected instances
845+
for instance in instances_in_config:
846+
unique_id = instance["unique_id"]
847+
if unique_id not in selected_ids:
848+
continue # Only toggle selected instances
849+
850+
self.worker.operation_message.emit(
851+
"info",
852+
self.translation_manager.get_translation("Toggling Root for {}...").format(unique_id)
853+
)
854+
855+
original_name = instance["original_name"]
856+
current_state = instance.get("root_enabled", False)
857+
new_state_bool = not current_state
858+
new_state_val = "1" if new_state_bool else "0"
859+
860+
setting_key = f"{constants.INSTANCE_PREFIX}{original_name}{constants.ENABLE_ROOT_KEY}"
861+
config_handler.modify_config_file(config_path, setting_key, new_state_val)
862+
863+
# Update internal state so the next step is accurate
864+
instance["root_enabled"] = new_state_bool
865+
866+
# Emit UI update signal
867+
on_off_text = self.translation_manager.get_translation("On") if new_state_bool else self.translation_manager.get_translation("Off")
868+
self.worker.instance_status_updated.emit(unique_id, "root", on_off_text)
869+
870+
# 2. Determine the new state for the global root flag
871+
is_any_root_on = any(inst.get("root_enabled", False) for inst in instances_in_config)
872+
new_global_value = "1" if is_any_root_on else "0"
873+
874+
logger.info(f"Setting global '{constants.FEATURE_ROOTING_KEY}' to '{new_global_value}' in {config_path}")
875+
config_handler.modify_config_file(config_path, constants.FEATURE_ROOTING_KEY, new_global_value)
876+
867877
except Exception as e:
868-
error_msg = self.translation_manager.get_translation(
869-
"Error toggling root for {}: {}"
870-
).format(unique_id, e)
878+
# Report a general error for this config file
879+
error_msg = f"Error processing {os.path.basename(config_path)}: {e}"
871880
self.worker.operation_message.emit("error", error_msg)
872881
self.operation_had_errors = True
873-
882+
874883
def _perform_rw_toggle_operation(self) -> None:
875884
if not self.worker:
876885
return

0 commit comments

Comments
 (0)