From df2bb763907faf1748f5a310ac8c51bc86bce9c9 Mon Sep 17 00:00:00 2001 From: Nose Date: Sun, 11 Jan 2026 03:34:35 -0800 Subject: [PATCH] f --- TUI/modalscreen/config_modal.py | 102 +++++++++++++++++++---------- TUI/modalscreen/selection_modal.py | 12 ++-- 2 files changed, 74 insertions(+), 40 deletions(-) diff --git a/TUI/modalscreen/config_modal.py b/TUI/modalscreen/config_modal.py index b4981e3..8191e01 100644 --- a/TUI/modalscreen/config_modal.py +++ b/TUI/modalscreen/config_modal.py @@ -98,6 +98,8 @@ class ConfigModal(ModalScreen): self.editing_item_type = None # 'store' or 'provider' self.editing_item_name = None self.workspace_root = workspace_root + self._button_id_map = {} + self._input_id_map = {} def compose(self) -> ComposeResult: with Container(id="config-container"): @@ -127,6 +129,8 @@ class ConfigModal(ModalScreen): def refresh_view(self) -> None: container = self.query_one("#fields-container", ScrollableContainer) + self._button_id_map.clear() + self._input_id_map.clear() # Clear existing synchronously for child in list(container.children): @@ -157,10 +161,14 @@ class ConfigModal(ModalScreen): def render_globals(self, container: ScrollableContainer) -> None: container.mount(Label("General Configuration", classes="config-label")) + idx = 0 for k, v in self.config_data.items(): if not isinstance(v, dict) and not k.startswith("_"): + inp_id = f"global-{idx}" + self._input_id_map[inp_id] = k container.mount(Label(k)) - container.mount(Input(value=str(v), id=f"global-{k}", classes="config-input")) + container.mount(Input(value=str(v), id=inp_id, classes="config-input")) + idx += 1 def render_stores(self, container: ScrollableContainer) -> None: container.mount(Label("Configured Stores", classes="config-label")) @@ -169,6 +177,7 @@ class ConfigModal(ModalScreen): container.mount(Static("No stores configured.")) else: # stores is structured as: {type: {name_key: config}} + idx = 0 for stype, instances in stores.items(): if isinstance(instances, dict): for name_key, conf in instances.items(): @@ -182,10 +191,16 @@ class ConfigModal(ModalScreen): or name_key ) + edit_id = f"edit-store-{idx}" + del_id = f"del-store-{idx}" + self._button_id_map[edit_id] = ("edit", f"store-{stype}", name_key) + self._button_id_map[del_id] = ("del", f"store-{stype}", name_key) + idx += 1 + row = Horizontal( Static(f"{display_name} ({stype})", classes="item-label"), - Button("Edit", id=f"edit-store-{stype}-{name_key}"), - Button("Delete", variant="error", id=f"del-store-{stype}-{name_key}"), + Button("Edit", id=edit_id), + Button("Delete", variant="error", id=del_id), classes="item-row" ) container.mount(row) @@ -196,11 +211,16 @@ class ConfigModal(ModalScreen): if not providers: container.mount(Static("No providers configured.")) else: - for name, _ in providers.items(): + for i, (name, _) in enumerate(providers.items()): + edit_id = f"edit-provider-{i}" + del_id = f"del-provider-{i}" + self._button_id_map[edit_id] = ("edit", "provider", name) + self._button_id_map[del_id] = ("del", "provider", name) + row = Horizontal( Static(name, classes="item-label"), - Button("Edit", id=f"edit-provider-{name}"), - Button("Delete", variant="error", id=f"del-provider-{name}"), + Button("Edit", id=edit_id), + Button("Delete", variant="error", id=del_id), classes="item-row" ) container.mount(row) @@ -246,6 +266,7 @@ class ConfigModal(ModalScreen): # Show all existing keys existing_keys_upper = set() + idx = 0 for k, v in section.items(): if k.startswith("_"): continue @@ -267,10 +288,13 @@ class ConfigModal(ModalScreen): is_secret = True container.mount(Label(label_text)) - inp = Input(value=str(v), id=f"item-{k}", classes="config-input") + inp_id = f"item-{idx}" + self._input_id_map[inp_id] = k + inp = Input(value=str(v), id=inp_id, classes="config-input") if is_secret: inp.password = True container.mount(inp) + idx += 1 # Add required/optional fields from schema that are missing for k_upper, field_def in provider_schema_map.items(): @@ -282,7 +306,10 @@ class ConfigModal(ModalScreen): label_text += " *" default_val = str(field_def.get("default") or "") - inp = Input(value=default_val, id=f"item-{key}", classes="config-input") + inp_id = f"item-{idx}" + self._input_id_map[inp_id] = key + inp = Input(value=default_val, id=inp_id, classes="config-input") + idx += 1 if field_def.get("secret"): inp.password = True if field_def.get("placeholder"): @@ -301,7 +328,10 @@ class ConfigModal(ModalScreen): # Case-insensitive deduplication (fix path vs PATH) if rk.upper() not in existing_keys_upper: container.mount(Label(rk)) - container.mount(Input(value="", id=f"item-{rk}", classes="config-input")) + inp_id = f"item-{idx}" + self._input_id_map[inp_id] = rk + container.mount(Input(value="", id=inp_id, classes="config-input")) + idx += 1 # If it's a provider, we might have required keys (legacy check fallback) if item_type == "provider": @@ -314,7 +344,10 @@ class ConfigModal(ModalScreen): for rk in required_keys: if rk.upper() not in existing_keys_upper: container.mount(Label(rk)) - container.mount(Input(value="", id=f"item-{rk}", classes="config-input")) + inp_id = f"item-{idx}" + self._input_id_map[inp_id] = rk + container.mount(Input(value="", id=inp_id, classes="config-input")) + idx += 1 except Exception: pass @@ -355,17 +388,22 @@ class ConfigModal(ModalScreen): self.editing_item_name = None self.editing_item_type = None self.refresh_view() - elif bid.startswith("edit-store-"): - parts = bid.replace("edit-store-", "").split("-", 1) - if len(parts) == 2: - stype, name = parts - self.editing_item_type = f"store-{stype}" + elif bid in self._button_id_map: + action, itype, name = self._button_id_map[bid] + if action == "edit": + self.editing_item_type = itype self.editing_item_name = name self.refresh_view() - elif bid.startswith("edit-provider-"): - self.editing_item_name = bid.replace("edit-provider-", "") - self.editing_item_type = "provider" - self.refresh_view() + elif action == "del": + if itype.startswith("store-"): + stype = itype.replace("store-", "") + if "store" in self.config_data and stype in self.config_data["store"]: + if name in self.config_data["store"][stype]: + del self.config_data["store"][stype][name] + elif itype == "provider": + if "provider" in self.config_data and name in self.config_data["provider"]: + del self.config_data["provider"][name] + self.refresh_view() elif bid == "add-store-btn": all_classes = _discover_store_classes() options = [] @@ -390,19 +428,6 @@ class ConfigModal(ModalScreen): except Exception: pass self.app.push_screen(SelectionModal("Select Provider Type", options), callback=self.on_provider_type_selected) - elif bid.startswith("del-store-"): - parts = bid.replace("del-store-", "").split("-", 1) - if len(parts) == 2: - stype, name = parts - if "store" in self.config_data and stype in self.config_data["store"]: - if name in self.config_data["store"][stype]: - del self.config_data["store"][stype][name] - self.refresh_view() - elif bid.startswith("del-provider-"): - name = bid.replace("del-provider-", "") - if "provider" in self.config_data and name in self.config_data["provider"]: - del self.config_data["provider"][name] - self.refresh_view() def on_store_type_selected(self, stype: str) -> None: if not stype: return @@ -474,11 +499,16 @@ class ConfigModal(ModalScreen): def on_input_changed(self, event: Input.Changed) -> None: if not event.input.id: return - if event.input.id.startswith("global-"): - key = event.input.id.replace("global-", "") + + bid = event.input.id + if bid not in self._input_id_map: + return + + key = self._input_id_map[bid] + + if bid.startswith("global-"): self.config_data[key] = event.value - elif event.input.id.startswith("item-") and self.editing_item_name: - key = event.input.id.replace("item-", "") + elif bid.startswith("item-") and self.editing_item_name: it = str(self.editing_item_type or "") inm = str(self.editing_item_name or "") diff --git a/TUI/modalscreen/selection_modal.py b/TUI/modalscreen/selection_modal.py index f982b1d..c1ed3ea 100644 --- a/TUI/modalscreen/selection_modal.py +++ b/TUI/modalscreen/selection_modal.py @@ -53,13 +53,17 @@ class SelectionModal(ModalScreen[str]): with Container(id="selection-container"): yield Static(self.selection_title, classes="selection-title") with ScrollableContainer(): - for opt in self.options: - yield Button(opt, id=f"opt-{opt}", classes="selection-button") + for i, opt in enumerate(self.options): + yield Button(opt, id=f"opt-{i}", classes="selection-button") yield Button("Cancel", id="selection-cancel") def on_button_pressed(self, event: Button.Pressed) -> None: if event.button.id == "selection-cancel": self.dismiss("") elif event.button.id and event.button.id.startswith("opt-"): - selection = event.button.id.replace("opt-", "") - self.dismiss(selection) + try: + idx = int(event.button.id.replace("opt-", "")) + selection = self.options[idx] + self.dismiss(selection) + except (ValueError, IndexError): + pass