Skip to content

Commit 1bfe6fb

Browse files
committed
filepicker fixes
1 parent f487e59 commit 1bfe6fb

File tree

7 files changed

+56
-89
lines changed

7 files changed

+56
-89
lines changed
Lines changed: 20 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,22 @@
11
{
2-
"name": "SwitchCraft",
3-
"short_name": "SwitchCraft",
4-
"start_url": ".",
5-
"display": "standalone",
6-
"background_color": "#202020",
7-
"theme_color": "#202020",
8-
"description": "SwitchCraft - Enterprise Application Management",
9-
"icons": [
10-
{
11-
"src": "icon-192.png",
12-
"sizes": "192x192",
13-
"type": "image/png"
14-
},
15-
{
16-
"src": "icon-512.png",
17-
"sizes": "512x512",
18-
"type": "image/png"
19-
},
20-
{
21-
"src": "switchcraft_logo.png",
22-
"sizes": "any",
23-
"type": "image/png"
24-
},
25-
{
26-
"src": "apple-touch-icon.png",
27-
"sizes": "180x180",
28-
"type": "image/png"
29-
}
30-
],
31-
"version": "2026.1.5b3"
2+
"name": "SwitchCraft",
3+
"short_name": "SwitchCraft",
4+
"id": "/",
5+
"start_url": "./?pwa=1",
6+
"display": "standalone",
7+
"background_color": "#111315",
8+
"theme_color": "#0066cc",
9+
"description": "SwitchCraft Modern Software Management (v2026.1.5b3.dev0+f487e59)",
10+
"icons": [
11+
{
12+
"src": "icon-192.png",
13+
"sizes": "192x192",
14+
"type": "image/png"
15+
},
16+
{
17+
"src": "icon-512.png",
18+
"sizes": "512x512",
19+
"type": "image/png"
20+
}
21+
]
3222
}

src/switchcraft/gui_modern/utils/view_utils.py

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -401,16 +401,16 @@ def _open_dialog_safe(self, dlg):
401401
return False
402402

403403
try:
404-
# Method 1: Modern API (Preferred) - DISABLED due to visibility issues on Windows Desktop
405-
# if hasattr(page, 'open'):
406-
# try:
407-
# logger.debug("Attempting to open dialog using page.open()...")
408-
# page.open(dlg)
409-
# page.update()
410-
# logger.info("Dialog opened successfully using page.open()")
411-
# return True
412-
# except Exception as e:
413-
# logger.warning(f"page.open(dlg) failed: {e}. Falling back to legacy mode.")
404+
# Method 1: Modern API (Preferred)
405+
if hasattr(page, 'open'):
406+
try:
407+
logger.debug("Attempting to open dialog using page.open()...")
408+
page.open(dlg)
409+
page.update()
410+
logger.info("Dialog opened successfully using page.open()")
411+
return True
412+
except Exception as e:
413+
logger.warning(f"page.open(dlg) failed: {e}. Falling back to legacy mode.")
414414

415415
# Method 2: Legacy API (Fallback)
416416
logger.debug("Attempting to open dialog using legacy page.dialog...")

src/switchcraft/gui_modern/views/analyzer_view.py

Lines changed: 12 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -50,17 +50,13 @@ def __init__(self, page: ft.Page):
5050
self.progress_bar = ft.ProgressBar(width=400, visible=False)
5151
self.addon_warning = ft.Container(visible=False)
5252

53-
# File Picker for Native/Web Support
54-
self.file_picker = ft.FilePicker()
55-
self.file_picker.on_result = self._on_file_picker_result
56-
self.file_picker.on_upload = self._on_file_upload
57-
5853
async def on_drop_click(e):
59-
# Use Flet's FilePicker instead of blocking helper
60-
await self.file_picker.pick_files(
61-
allow_multiple=False,
54+
# Use FilePickerHelper (Tkinter) instead of Flet's potentially buggy FilePicker
55+
path = FilePickerHelper.pick_file(
6256
allowed_extensions=["exe", "msi", "ps1", "bat", "cmd", "vbs", "msp"]
6357
)
58+
if path:
59+
self.start_analysis(path)
6460

6561
def on_drag_enter(e):
6662
self.drop_zone.border = ft.Border.all(4, "BLUE_400")
@@ -224,8 +220,7 @@ def on_source_tab_change(e):
224220

225221
]
226222

227-
# Add FilePicker to controls (it's invisible but needs to be in the tree)
228-
self.controls.append(self.file_picker)
223+
# Add FilePicker removed in favor of FilePickerHelper (Tkinter) logic
229224

230225
self._check_addon()
231226

@@ -651,9 +646,9 @@ def _show_results(self, result: AnalysisResult):
651646
)
652647

653648
action_buttons = ft.Row([
654-
ft.FilledButton(content=ft.Row([ft.Icon(ft.Icons.AUTO_FIX_HIGH), ft.Text(i18n.get("btn_auto_deploy") or "Auto Deploy (All-in-One)")], alignment=ft.MainAxisAlignment.CENTER), style=ft.ButtonStyle(bgcolor="RED_700", color="WHITE"), on_click=lambda _: self._run_all_in_one_flow(result)),
655-
ft.FilledButton(content=ft.Row([ft.Icon(ft.Icons.PLAY_ARROW), ft.Text(i18n.get("btn_test_locally") or "Test Locally (Admin)")], alignment=ft.MainAxisAlignment.CENTER), style=ft.ButtonStyle(bgcolor="GREEN_700", color="WHITE"), on_click=lambda _: self._run_local_test_action(info.file_path, info.install_switches)),
656-
ft.FilledButton(content=ft.Row([ft.Icon(ft.Icons.DESCRIPTION), ft.Text(i18n.get("btn_winget_manifest") or "Winget Manifest")], alignment=ft.MainAxisAlignment.CENTER), on_click=lambda _: self._open_manifest_dialog(info)),
649+
ft.FilledButton(content=ft.Row([ft.Icon(ft.Icons.AUTO_FIX_HIGH), ft.Text(i18n.get("btn_auto_deploy") or "Auto Deploy (All-in-One)")], alignment=ft.MainAxisAlignment.CENTER), style=ft.ButtonStyle(bgcolor="RED_700", color="WHITE"), on_click=self._safe_event_handler(lambda _: self._run_all_in_one_flow(result), "Auto Deploy")),
650+
ft.FilledButton(content=ft.Row([ft.Icon(ft.Icons.PLAY_ARROW), ft.Text(i18n.get("btn_test_locally") or "Test Locally (Admin)")], alignment=ft.MainAxisAlignment.CENTER), style=ft.ButtonStyle(bgcolor="GREEN_700", color="WHITE"), on_click=self._safe_event_handler(lambda _: self._run_local_test_action(info.file_path, info.install_switches), "Test Locally")),
651+
ft.FilledButton(content=ft.Row([ft.Icon(ft.Icons.DESCRIPTION), ft.Text(i18n.get("btn_winget_manifest") or "Winget Manifest")], alignment=ft.MainAxisAlignment.CENTER), on_click=self._safe_event_handler(lambda _: self._open_manifest_dialog(info), "Winget Manifest")),
657652
], wrap=True)
658653
self.results_column.controls.append(action_buttons)
659654

@@ -687,9 +682,9 @@ def _show_results(self, result: AnalysisResult):
687682
# 7. Deployment Actions (Intune, IntuneWin)
688683
self.results_column.controls.append(
689684
ft.Row([
690-
ft.FilledButton(content=ft.Row([ft.Icon(ft.Icons.CODE), ft.Text(i18n.get("generate_intune_script") or "Generate Intune Script")], alignment=ft.MainAxisAlignment.CENTER), on_click=self._on_click_create_script),
691-
ft.FilledButton(content=ft.Row([ft.Icon(ft.Icons.INVENTORY), ft.Text(i18n.get("btn_create_intunewin") or "Create .intunewin")], alignment=ft.MainAxisAlignment.CENTER), on_click=self._on_click_create_intunewin),
692-
ft.FilledButton(content=ft.Row([ft.Icon(ft.Icons.TERMINAL), ft.Text(i18n.get("btn_manual_cmds") or "Manual Commands")], alignment=ft.MainAxisAlignment.CENTER), on_click=self._show_manual_cmds),
685+
ft.FilledButton(content=ft.Row([ft.Icon(ft.Icons.CODE), ft.Text(i18n.get("generate_intune_script") or "Generate Intune Script")], alignment=ft.MainAxisAlignment.CENTER), on_click=self._safe_event_handler(self._on_click_create_script, "Generate Script")),
686+
ft.FilledButton(content=ft.Row([ft.Icon(ft.Icons.INVENTORY), ft.Text(i18n.get("btn_create_intunewin") or "Create .intunewin")], alignment=ft.MainAxisAlignment.CENTER), on_click=self._safe_event_handler(self._on_click_create_intunewin, "Create Intunewin")),
687+
ft.FilledButton(content=ft.Row([ft.Icon(ft.Icons.TERMINAL), ft.Text(i18n.get("btn_manual_cmds") or "Manual Commands")], alignment=ft.MainAxisAlignment.CENTER), on_click=self._safe_event_handler(self._show_manual_cmds, "Manual Commands")),
693688
], wrap=True)
694689
)
695690

@@ -761,7 +756,7 @@ def _show_results(self, result: AnalysisResult):
761756

762757
# 12. View Detailed Button
763758
self.results_column.controls.append(
764-
ft.FilledButton(content=ft.Row([ft.Icon(ft.Icons.ZOOM_IN), ft.Text(i18n.get("view_full_params") or "View Detailed Analysis Data")], alignment=ft.MainAxisAlignment.CENTER), on_click=lambda _: self._show_detailed_parameters(result))
759+
ft.FilledButton(content=ft.Row([ft.Icon(ft.Icons.ZOOM_IN), ft.Text(i18n.get("view_full_params") or "View Detailed Analysis Data")], alignment=ft.MainAxisAlignment.CENTER), on_click=self._safe_event_handler(lambda _: self._show_detailed_parameters(result), "View Details"))
765760
)
766761

767762
self.update()

src/switchcraft/gui_modern/views/sap_wizard_view.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -87,15 +87,14 @@ def on_pick_server(e: ft.FilePickerResultEvent):
8787
self.update()
8888

8989
path_text = ft.Text(self.server_path or "No path selected", italic=True)
90-
fp = ft.FilePicker()
91-
fp.on_result = on_pick_server
92-
self.app_page.overlay.append(fp)
90+
91+
# Use FilePickerHelper (Tkinter) instead of Flet's FilePicker
9392

9493
return ft.Column([
9594
ft.Text(i18n.get("sap_step1_title") or "1. Select SAP Installation Server", size=18, weight=ft.FontWeight.BOLD),
9695
ft.Text(i18n.get("sap_step1_desc") or "Point to the root folder of your SAP nwsetupadmin server."),
9796
ft.Row([
98-
ft.FilledButton(i18n.get("btn_browse_folder") or "Browse Server Folder", icon=ft.Icons.FOLDER_OPEN, on_click=lambda _: fp.get_directory_path()),
97+
ft.FilledButton(i18n.get("btn_browse_folder") or "Browse Server Folder", icon=ft.Icons.FOLDER_OPEN, on_click=lambda _: on_pick_server(ft.FilePickerResultEvent(path=FilePickerHelper.pick_directory(), files=None))),
9998
path_text
10099
]),
101100
ft.Divider(height=20, color="TRANSPARENT"),

src/switchcraft/main.py

Lines changed: 2 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -95,28 +95,7 @@ def start_splash():
9595
# Now do heavy imports
9696
import flet as ft # noqa: E402
9797

98-
# --- MONKEY PATCH: Fix web_entry.py legacy ft.run call ---
99-
# web_entry.py (generated) calls ft.run(target=...) but Pyodide flet might expect ft.app or different sig.
100-
def flexible_run(*args, **kwargs):
101-
# Extract target from kwargs or args
102-
target = kwargs.get("target")
103-
if not target and args:
104-
target = args[0]
105-
106-
# Use run() if available (Flet 0.80.0+), else app()
107-
clean_kwargs = {k: v for k, v in kwargs.items() if k != "target"}
108-
if hasattr(ft, "_original_run") and ft._original_run:
109-
return ft._original_run(target, **clean_kwargs)
110-
elif hasattr(ft, "run") and ft.run != flexible_run:
111-
return ft.run(target, **clean_kwargs)
112-
113-
return ft.app(target=target, **clean_kwargs)
114-
115-
# Save original run and override
116-
if not hasattr(ft, "_original_run"):
117-
ft._original_run = getattr(ft, "run", None)
118-
ft.run = flexible_run
119-
# ---------------------------------------------------------
98+
# Monkey patch removed - using standard methods
12099

121100
# Flet Universal Compatibility Patch
122101
def patch_flet():
@@ -839,10 +818,7 @@ def _ensure_pwa_manifest():
839818
pass
840819

841820
try:
842-
if hasattr(ft, "run"):
843-
ft.run(main)
844-
else:
845-
ft.app(target=main, assets_dir="assets")
821+
ft.run(main, assets_dir="assets")
846822
except Exception as e:
847823
# Fallback for early failures (before main() handles it)
848824
try:

tests/test_i18n_integrity.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,8 @@ def test_codebase_keys_exist(self):
128128
'rule_type', 'output_json', 'target_version', 'search_query',
129129
'error_description', 'import_settings', 'created_at', 'export_settings', 'export_logs',
130130
'admin_password', 'config_path', 'admin_password_hash', 'first_run', 'demo_mode',
131-
'current_password', 'new_password', 'confirm_password', 'update_exe', 'banner_container'
131+
'current_password', 'new_password', 'confirm_password', 'update_exe', 'banner_container',
132+
'file_picker'
132133
}
133134

134135
for k in found_keys:

tests/test_smoke.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,14 @@ def test_import_gui(self):
2929

3030
def test_cli_version(self):
3131
"""Verify CLI --version runs without error."""
32+
import os
33+
env = os.environ.copy()
34+
# Add src to PYTHONPATH so it finds switchcraft module without installation
35+
src_path = os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "src"))
36+
env["PYTHONPATH"] = src_path + os.pathsep + env.get("PYTHONPATH", "")
37+
3238
cmd = [sys.executable, "-m", "switchcraft.main", "--version"]
33-
result = subprocess.run(cmd, capture_output=True, text=True)
39+
result = subprocess.run(cmd, capture_output=True, text=True, env=env)
3440
self.assertEqual(result.returncode, 0)
3541
self.assertIn("SwitchCraft", result.stdout)
3642

0 commit comments

Comments
 (0)