@@ -24,6 +24,10 @@ def __init__(self, page: ft.Page):
2424 self .update_files = []
2525 self .logo_path = ""
2626 self .use_webview2 = True
27+ self .arch_group = ft .RadioGroup (content = ft .Row ([
28+ ft .Radio (value = "32" , label = "32-bit (Win32)" ),
29+ ft .Radio (value = "64" , label = "64-bit (Win64)" )
30+ ]), value = "64" )
2731
2832 self .current_step = 1
2933 self .content_area = ft .Container (expand = True )
@@ -34,9 +38,35 @@ def __init__(self, page: ft.Page):
3438 self ._build_nav_buttons ()
3539 ]
3640
37- self ._show_step (1 )
41+ from switchcraft .utils .shell_utils import ShellUtils
42+ self .is_admin = ShellUtils .is_admin ()
43+
44+ if not self .is_admin :
45+ self .content_area .content = self ._build_admin_warning ()
46+ # Hide nav buttons if not admin
47+ self .controls [- 1 ].visible = False
48+ else :
49+ self ._show_step (1 )
50+
51+ def _build_admin_warning (self ):
52+ from switchcraft .utils .shell_utils import ShellUtils
53+ return ft .Column ([
54+ ft .Icon (ft .Icons .SECURITY , size = 64 , color = "RED" ),
55+ ft .Text (i18n .get ("sap_admin_required_title" ) or "Administrator Privileges Required" , size = 20 , weight = ft .FontWeight .BOLD ),
56+ ft .Text (i18n .get ("sap_admin_required_desc" ) or "The SAP Installation Server Administration Tool (NwSapSetupAdmin.exe) requires administrative rights to merge updates and create packages." ),
57+ ft .Container (height = 20 ),
58+ ft .ElevatedButton (
59+ i18n .get ("btn_restart_admin" ) or "Restart SwitchCraft as Admin" ,
60+ icon = ft .Icons .SHIELD ,
61+ on_click = lambda _ : ShellUtils .restart_as_admin (),
62+ bgcolor = "RED" , color = "WHITE"
63+ )
64+ ], alignment = ft .MainAxisAlignment .CENTER , horizontal_alignment = ft .CrossAxisAlignment .CENTER , expand = True )
3865
3966 def _show_step (self , step_num ):
67+ if not self .is_admin :
68+ return
69+
4070 self .current_step = step_num
4171 if step_num == 1 :
4272 self .content_area .content = self ._build_step_1 ()
@@ -67,7 +97,10 @@ def on_pick_server(e: ft.FilePickerResultEvent):
6797 ft .Row ([
6898 ft .ElevatedButton (i18n .get ("btn_browse_folder" ) or "Browse Server Folder" , icon = ft .Icons .FOLDER_OPEN , on_click = lambda _ : fp .get_directory_path ()),
6999 path_text
70- ])
100+ ]),
101+ ft .Divider (height = 20 , color = "TRANSPARENT" ),
102+ ft .Text (i18n .get ("sap_arch_select" ) or "Architecture:" , weight = ft .FontWeight .BOLD ),
103+ self .arch_group
71104 ])
72105
73106 def _build_step_2 (self ):
@@ -92,12 +125,33 @@ def _build_step_3(self):
92125
93126 def _build_step_4 (self ):
94127 """Step 4: Summary & Packaging."""
128+ # Refresh packages list on entry
129+ packages = []
130+ try :
131+ packages = self .sap_service .list_packages (self .server_path )
132+ except :
133+ pass
134+
135+ opts = [ft .dropdown .Option (p ['name' ]) for p in packages ]
136+ # Default to first if available, else standard SAPGUI
137+ default_val = packages [0 ]['name' ] if packages else "SAPGUI"
138+
139+ self .package_dd = ft .Dropdown (
140+ label = i18n .get ("sap_package_select" ) or "Select Package to Build" ,
141+ options = opts ,
142+ value = default_val ,
143+ width = 400
144+ )
145+
95146 return ft .Column ([
96147 ft .Text (i18n .get ("sap_step4_title" ) or "4. Summary & Packaging" , size = 18 , weight = ft .FontWeight .BOLD ),
97148 ft .Text (f"{ i18n .get ('label_server' ) or 'Server' } : { self .server_path } " ),
149+ ft .Text (f"Architecture: { self .arch_group .value } -bit" ),
98150 ft .Text (f"{ i18n .get ('label_custom_logo' ) or 'Custom Logo' } : { 'Yes' if self .logo_path else 'No' } " ),
99151 ft .Text (f"{ i18n .get ('label_webview2' ) or 'Edge WebView2' } : { 'Enabled' if self .use_webview2 else 'Disabled' } " ),
100152 ft .Divider (),
153+ self .package_dd ,
154+ ft .Container (height = 10 ),
101155 ft .ElevatedButton (i18n .get ("btn_apply_build" ) or "Apply & Build Packaging" , icon = ft .Icons .BUILD_CIRCLE , bgcolor = "PRIMARY" , color = "WHITE" , on_click = self ._on_finalize )
102156 ])
103157
@@ -113,8 +167,42 @@ def _on_finalize(self, _):
113167 return
114168
115169 try :
116- self .sap_service .customize_server (self .server_path , self .logo_path , self .use_webview2 )
170+ target_path = self .server_path
171+ if self .arch_group .value == "64" :
172+ if "Win32" in target_path :
173+ target_path = target_path .replace ("Win32" , "Win64" )
174+ elif "Win64" not in target_path and (Path (target_path ) / "Win64" ).exists ():
175+ target_path = str (Path (target_path ) / "Win64" )
176+
177+ # 1. Customize
178+ self .sap_service .customize_server (target_path , self .logo_path , self .use_webview2 )
117179 self ._show_snack ("SAP Server customized successfully!" , color = "GREEN" )
118- # In a real app, we would now trigger the packaging process
180+
181+ # 2. Build
182+ pkg_name = self .package_dd .value
183+ if not pkg_name :
184+ self ._show_snack ("Please select a package to build." , color = "RED" )
185+ return
186+
187+ import tempfile
188+ # Use %TEMP%\SwitchCraft\Dist
189+ temp_dir = Path (tempfile .gettempdir ()) / "SwitchCraft" / "Dist"
190+ out_dir = str (temp_dir )
191+
192+ self ._show_snack (f"Building package '{ pkg_name } '... Please wait..." , color = "BLUE" )
193+ self .app_page .update ()
194+
195+ # Use threading to avoid UI freeze if desired, but for now simple blocking is safer for debugging logic
196+ out_file = self .sap_service .create_single_file_installer (target_path , pkg_name , out_dir )
197+
198+ self ._show_snack (f"Build Success! Installer at: { out_file } " , color = "GREEN" , duration = 5000 )
199+
200+ # Auto-open in Explorer
201+ try :
202+ os .startfile (out_dir )
203+ except Exception as e :
204+ logger .error (f"Failed to open explorer: { e } " )
205+
119206 except Exception as e :
207+ logger .error (f"SAP Finalize Error: { e } " )
120208 self ._show_snack (f"Error: { e } " , color = "RED" )
0 commit comments