Skip to content

Commit b3fb189

Browse files
committed
v0.6.14: fix Save All — use on_change to sync TextField values to Python
Without on_change, Flet never sends the user's typed text back to the Python process; tf.value stays at the initial value. Fix: - All connection/API key fields use _v dict updated by on_change lambdas; _save_all reads from _v instead of tf.value - Const TextFields get on_change=lambda e: None so Flet syncs ctrl.value - Fully tested: config.json, key files, and _write_constant round-trip
1 parent 913bd14 commit b3fb189

1 file changed

Lines changed: 48 additions & 52 deletions

File tree

gui.py

Lines changed: 48 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -1070,59 +1070,52 @@ def _save_config_all(data: dict) -> None:
10701070
with open(config_file, "w") as f:
10711071
json.dump(cfg, f, indent=2)
10721072

1073+
# _v holds the live text for every field; on_change keeps it in sync.
1074+
# Reading tf.value without on_change returns the *initial* value only.
10731075
_cfg = _load_config()
1074-
tf_canvas_url = ft.TextField(
1075-
value=_cfg.get("CANVAS_URL", ""),
1076-
hint_text="canvas.yourschool.edu (https:// added automatically)", expand=True, dense=True,
1077-
bgcolor=C_OUTPUT_BG, border_color=C_PRIMARY, text_size=12,
1078-
)
1079-
tf_panopto = ft.TextField(
1080-
value=_cfg.get("PANOPTO_HOST", ""),
1081-
hint_text="mediaweb.ap.panopto.com", expand=True, dense=True,
1082-
bgcolor=C_OUTPUT_BG, border_color=C_PRIMARY, text_size=12,
1083-
)
1084-
1085-
conn_card = _card(ft.Column(controls=[
1086-
ft.Text("Connection", size=13,
1087-
weight=ft.FontWeight.BOLD, color=ft.Colors.WHITE),
1088-
ft.Text("Saved to config.json in the project directory.",
1089-
size=11, color=ft.Colors.with_opacity(0.5, ft.Colors.WHITE)),
1090-
ft.Container(height=4),
1091-
_field_row("Canvas URL", tf_canvas_url),
1092-
_field_row("Panopto Host", tf_panopto),
1093-
], spacing=10))
1094-
1095-
# ── API Keys ──────────────────────────────────────────────────────────────
1096-
10971076
canvas_file = PROJECT_DIR / "canvas_token.txt"
10981077
openai_file = PROJECT_DIR / "openai_api.txt"
10991078
anthropic_file = PROJECT_DIR / "anthropic_key.txt"
11001079
gemini_file = PROJECT_DIR / "gemini_api.txt"
11011080

1102-
tf_canvas = ft.TextField(
1103-
value=canvas_file.read_text().strip() if canvas_file.exists() else "",
1081+
_v = {
1082+
"canvas_url": _cfg.get("CANVAS_URL", ""),
1083+
"panopto": _cfg.get("PANOPTO_HOST", ""),
1084+
"canvas": canvas_file.read_text().strip() if canvas_file.exists() else "",
1085+
"openai": openai_file.read_text().strip() if openai_file.exists() else "",
1086+
"anthropic": anthropic_file.read_text().strip() if anthropic_file.exists() else "",
1087+
"gemini": gemini_file.read_text().strip() if gemini_file.exists() else "",
1088+
}
1089+
1090+
def _mk_tf(key: str, **kwargs) -> ft.TextField:
1091+
return ft.TextField(
1092+
value=_v[key],
1093+
on_change=lambda e, k=key: _v.update({k: e.control.value}),
1094+
**kwargs,
1095+
)
1096+
1097+
tf_canvas_url = _mk_tf("canvas_url",
1098+
hint_text="canvas.yourschool.edu (https:// added automatically)",
1099+
expand=True, dense=True, bgcolor=C_OUTPUT_BG, border_color=C_PRIMARY, text_size=12)
1100+
tf_panopto = _mk_tf("panopto",
1101+
hint_text="mediaweb.ap.panopto.com",
1102+
expand=True, dense=True, bgcolor=C_OUTPUT_BG, border_color=C_PRIMARY, text_size=12)
1103+
tf_canvas = _mk_tf("canvas",
11041104
password=True, can_reveal_password=True,
1105-
hint_text="Canvas API token", expand=True, dense=True,
1106-
bgcolor=C_OUTPUT_BG, border_color=C_PRIMARY, text_size=12,
1107-
)
1108-
tf_openai = ft.TextField(
1109-
value=openai_file.read_text().strip() if openai_file.exists() else "",
1105+
hint_text="Canvas API token",
1106+
expand=True, dense=True, bgcolor=C_OUTPUT_BG, border_color=C_PRIMARY, text_size=12)
1107+
tf_openai = _mk_tf("openai",
11101108
password=True, can_reveal_password=True,
1111-
hint_text="sk-… (no default)", expand=True, dense=True,
1112-
bgcolor=C_OUTPUT_BG, border_color=C_PRIMARY, text_size=12,
1113-
)
1114-
tf_anthropic = ft.TextField(
1115-
value=anthropic_file.read_text().strip() if anthropic_file.exists() else "",
1109+
hint_text="sk-… (no default)",
1110+
expand=True, dense=True, bgcolor=C_OUTPUT_BG, border_color=C_PRIMARY, text_size=12)
1111+
tf_anthropic = _mk_tf("anthropic",
11161112
password=True, can_reveal_password=True,
1117-
hint_text="sk-ant-… (no default)", expand=True, dense=True,
1118-
bgcolor=C_OUTPUT_BG, border_color=C_PRIMARY, text_size=12,
1119-
)
1120-
tf_gemini = ft.TextField(
1121-
value=gemini_file.read_text().strip() if gemini_file.exists() else "",
1113+
hint_text="sk-ant-… (no default)",
1114+
expand=True, dense=True, bgcolor=C_OUTPUT_BG, border_color=C_PRIMARY, text_size=12)
1115+
tf_gemini = _mk_tf("gemini",
11221116
password=True, can_reveal_password=True,
1123-
hint_text="AIza… (Google AI Studio key, no default)", expand=True, dense=True,
1124-
bgcolor=C_OUTPUT_BG, border_color=C_PRIMARY, text_size=12,
1125-
)
1117+
hint_text="AIza… (Google AI Studio key, no default)",
1118+
expand=True, dense=True, bgcolor=C_OUTPUT_BG, border_color=C_PRIMARY, text_size=12)
11261119

11271120
refresh_status = ft.Text("", size=11,
11281121
color=ft.Colors.with_opacity(0.6, ft.Colors.WHITE))
@@ -1270,6 +1263,7 @@ def _const_row(script: str, name: str, desc: str, default: str,
12701263
value=cur, expand=True, dense=True,
12711264
bgcolor=C_OUTPUT_BG, border_color=accent,
12721265
text_size=12, content_padding=ft.padding.symmetric(horizontal=8, vertical=6),
1266+
on_change=lambda e: None, # ensures Flet syncs typed value to ctrl.value
12731267
)
12741268

12751269
_const_ctrls.append((ctrl, script, name, default))
@@ -1318,23 +1312,25 @@ def _save_all(_):
13181312
errors: list[str] = []
13191313
try:
13201314
_save_config_all({
1321-
"CANVAS_URL": tf_canvas_url.value.strip(),
1322-
"PANOPTO_HOST": tf_panopto.value.strip(),
1315+
"CANVAS_URL": _v["canvas_url"].strip(),
1316+
"PANOPTO_HOST": _v["panopto"].strip(),
13231317
})
13241318
except Exception as e:
13251319
errors.append(f"Connection: {e}")
1326-
for path, tf in [
1327-
(canvas_file, tf_canvas),
1328-
(openai_file, tf_openai),
1329-
(anthropic_file, tf_anthropic),
1330-
(gemini_file, tf_gemini),
1320+
for path, key in [
1321+
(canvas_file, "canvas"),
1322+
(openai_file, "openai"),
1323+
(anthropic_file, "anthropic"),
1324+
(gemini_file, "gemini"),
13311325
]:
13321326
try:
1333-
if tf.value.strip():
1334-
path.write_text(tf.value.strip())
1327+
val = _v[key].strip()
1328+
if val:
1329+
path.write_text(val)
13351330
except Exception as e:
13361331
errors.append(str(e))
13371332
for ctrl, script, name, default in _const_ctrls:
1333+
# Dropdowns sync via on_select; TextFields sync via on_change
13381334
val = (ctrl.value or default) if isinstance(ctrl, ft.Dropdown) \
13391335
else ctrl.value.strip()
13401336
if not _write_constant(script, name, val):

0 commit comments

Comments
 (0)