Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions docs/.vitepress/config.mts
Original file line number Diff line number Diff line change
Expand Up @@ -85,9 +85,17 @@ export default defineConfig({
{ text: 'Script Manager', link: '/views/scripts' },
{ text: 'Detection Tester', link: '/views/tester' },
{ text: 'AI Helper', link: '/views/helper' },
{ text: 'SAP Management', link: '/views/sap_wizard' },
{ text: 'Settings', link: '/views/settings' }
]
},
{
text: 'Specialized Tools',
collapsed: false,
items: [
{ text: 'SAP Installation Server', link: '/SAP' }
]
},
{
text: 'Enterprise & IT Pro',
collapsed: false,
Expand Down
31 changes: 31 additions & 0 deletions docs/SAP.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# SAP Management

SwitchCraft provides specialized tools for managing SAP Installation Servers (`nwsetupadmin`). This tool automates common administrative tasks like merging updates, customizing the GUI appearance, and forcing browser preferences.

## Key Features

- **Automated Update Merging**: Easily integrate SAP GUI patches and add-ons using the `/UpdateServer` command-line interface.
- **Logo Customization**: Automatically distribute custom company logos to all clients by integrated them into the installation server.
- **Edge WebView2 Enforcement**: Force the use of Edge WebView2 as the default browser engine for SAP GUI transactions by patching the `SapGuiSetup.xml` configuration.
Comment on lines +7 to +9
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Minor grammar fix in Logo Customization bullet.
“by integrated them” → “by integrating them”.

✏️ Suggested edit
-- **Logo Customization**: Automatically distribute custom company logos to all clients by integrated them into the installation server.
+- **Logo Customization**: Automatically distribute custom company logos to all clients by integrating them into the installation server.
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
- **Automated Update Merging**: Easily integrate SAP GUI patches and add-ons using the `/UpdateServer` command-line interface.
- **Logo Customization**: Automatically distribute custom company logos to all clients by integrated them into the installation server.
- **Edge WebView2 Enforcement**: Force the use of Edge WebView2 as the default browser engine for SAP GUI transactions by patching the `SapGuiSetup.xml` configuration.
- **Automated Update Merging**: Easily integrate SAP GUI patches and add-ons using the `/UpdateServer` command-line interface.
- **Logo Customization**: Automatically distribute custom company logos to all clients by integrating them into the installation server.
- **Edge WebView2 Enforcement**: Force the use of Edge WebView2 as the default browser engine for SAP GUI transactions by patching the `SapGuiSetup.xml` configuration.
🤖 Prompt for AI Agents
In `@docs/SAP.md` around lines 7 - 9, Fix the grammar in the "Logo Customization"
bullet: replace the phrase "by integrated them into the installation server"
with "by integrating them into the installation server" in the Logo
Customization bullet text so it reads correctly; locate and update the line that
currently starts "**Logo Customization**: Automatically distribute custom
company logos..." and apply the single-word change.

- **Guided Multi-Step Wizard**: A specialized UI that walks you through the entire process from server selection to finalized packaging.

## Usage Guide

### 1. Select Installation Server
Point SwitchCraft to the root directory of your SAP Installation Server. The tool will look for `NwSapSetupAdmin.exe` in the `Setup` subfolder.

### 2. Merge Updates
Select one or more SAP update executables. SwitchCraft will execute the merge process in the background, ensuring your server is up to date with the latest patches.

### 3. Customization
- **Edge WebView2**: Check this option to ensure all clients use the modern WebView2 engine.
- **Custom Logo**: Select a `.png` file to be used as the branding logo in the SAP GUI.

### 4. Finalize & Package
Once customized, you can trigger the creation of a **Single-File Installer (SFU)**. This creates a self-extracting executable that contains only the necessary components for a silent, standalone deployment.

## Technical Details

The tool interacts with the SAP Setup infrastructure via:
- **CLI**: `NwSapSetupAdmin.exe` for server updates and SFU compression.
- **XML Patching**: Direct manipulation of `Setup\SapGuiSetup.xml` for specific preference overrides that are not exposed via standard CLI arguments.
23 changes: 23 additions & 0 deletions docs/views/sap_wizard.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# SAP Management Wizard

The **SAP Management Wizard** is a guided tool designed to simplify the lifecycle management of SAP Installation Servers.

![SAP Wizard Screenshot](/docs/public/img/sap_wizard.png)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Check if the image file exists
find docs -name "sap_wizard.png" -type f 2>/dev/null
echo "---"
# List the structure of docs/public if it exists
if [ -d "docs/public" ]; then
  echo "docs/public directory structure:"
  find docs/public -type f 2>/dev/null | head -20
else
  echo "docs/public directory does not exist"
fi
echo "---"
# List the docs/views directory to confirm the file exists
echo "docs/views directory contents:"
ls -la docs/views/ 2>/dev/null || echo "docs/views not accessible"

Repository: FaserF/SwitchCraft

Length of output: 1830


🏁 Script executed:

#!/bin/bash
# Check for VitePress config to understand path conventions
find . -maxdepth 2 -name "*vitepress*" -o -name "*.config.*" | grep -E "(vitepress|config)" | head -10
echo "---"
# Look for other image references in docs to see the pattern
rg "!\[.*\]\(/.*\.png" docs/ --type md | head -10

Repository: FaserF/SwitchCraft

Length of output: 166


🏁 Script executed:

#!/bin/bash
# Check the exact content of the sap_wizard.md file
cat -n docs/views/sap_wizard.md 2>/dev/null || echo "File not found"

Repository: FaserF/SwitchCraft

Length of output: 1211


The image file is missing from the repository and the path format is incorrect.

The sap_wizard.png file does not exist in docs/public/ or anywhere else in the codebase. Additionally, the path format is incorrect for VitePress—docs/public/ assets are served from the root, not as absolute paths including /docs/public/.

To resolve this:

  1. Add the sap_wizard.png image file to docs/public/img/ (or adjust the path if using a different location)
  2. Update the markdown reference to /img/sap_wizard.png
Proposed fix
-![SAP Wizard Screenshot](/docs/public/img/sap_wizard.png)
+![SAP Wizard Screenshot](/img/sap_wizard.png)
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
![SAP Wizard Screenshot](/docs/public/img/sap_wizard.png)
![SAP Wizard Screenshot](/img/sap_wizard.png)
🤖 Prompt for AI Agents
In `@docs/views/sap_wizard.md` at line 5, The markdown references a missing image
and uses the wrong VitePress path: replace the existing reference string "! [SAP
Wizard Screenshot](/docs/public/img/sap_wizard.png)" by adding the actual
sap_wizard.png into docs/public/img/ (or your chosen docs public asset folder)
and update the markdown to use the VitePress-served path "/img/sap_wizard.png"
(i.e., change the image link to "![SAP Wizard
Screenshot](/img/sap_wizard.png)"); ensure the file name matches exactly
(sap_wizard.png) and commit both the image and the updated
docs/views/sap_wizard.md line.

*Note: Screenshot represents the modern UI layout.*

## View Components

### Server Selection
The first step requires the path to a network share or local folder containing the SAP nwsetupadmin server.

### Update Manager
Allows queuing multiple `.exe` patches for sequential merging.

### Customization Options
- **WebView2 Toggle**: Corresponds to the `UseWebView2` parameter in the SAP configuration.
- **Branding**: Automatically handles the copying and registration of custom logos.

## Best Practices
- Always create a backup of your `Setup` directory before applying customizations.
- Ensure you have administrative privileges on the folder where the installation server is hosted.
- Test the resulting Single-File Installer on a clean machine before wide-scale distribution.
21 changes: 20 additions & 1 deletion src/switchcraft/assets/lang/de.json
Original file line number Diff line number Diff line change
Expand Up @@ -1095,5 +1095,24 @@
"error_feature_demo_restricted": "Das Paketieren ist in der Web-Demo nicht verfügbar.",
"error_wine_missing": "Wine wird benötigt, um das Paketierungs-Werkzeug unter Linux auszuführen. Bitte installiere Wine.",
"demo_restriction_hint": "Die Funktion {feature}ist in der Web-Demo eingeschränkt. Für den vollen Funktionsumfang nutze bitte die Desktop-Version.",
"wine_missing_hint": "Diese Funktion erfordert eine Wine-Installation auf deinem Linux-System."
"wine_missing_hint": "Diese Funktion erfordert eine Wine-Installation auf deinem Linux-System.",
"sap_wizard_title": "SAP Management Wizard",
"sap_card_title": "SAP Management",
"sap_card_desc": "SAP Install Server Werkzeug",
"sap_step1_title": "1. SAP Installations-Server wählen",
"sap_step1_desc": "Wähle den Stammordner deines SAP nwsetupadmin Servers aus.",
"sap_step2_title": "2. Updates & Add-ons hinzufügen (Optional)",
"sap_step2_desc": "Wähle .exe Dateien aus, die in den Installations-Server integriert werden sollen.",
"sap_step3_title": "3. Anpassung",
"sap_step3_desc": "Konfiguriere Logo und Browser-Einstellungen.",
"sap_step4_title": "4. Zusammenfassung & Paketierung",
"sap_use_webview2": "Edge WebView2 als Standard (Empfohlen)",
"no_logo_selected": "Kein Logo ausgewählt",
"label_server": "Server",
"label_custom_logo": "Benutzerdefiniertes Logo",
"label_webview2": "Edge WebView2",
"btn_browse_folder": "Serverordner durchsuchen",
"btn_add_update": "Update EXE hinzufügen",
"btn_select_logo": "Custom Logo wählen",
"btn_apply_build": "Anwenden & Paketierung erstellen"
Comment on lines +1098 to +1117
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Consider fully localizing the new SAP strings.
Several new values are English or mixed (e.g., “SAP Management Wizard”, “Custom Logo wählen”). If this is intentional, ignore; otherwise, a consistent German localization would improve UX.

💬 Optional wording adjustments
-    "sap_wizard_title": "SAP Management Wizard",
+    "sap_wizard_title": "SAP-Verwaltungsassistent",
...
-    "btn_select_logo": "Custom Logo wählen",
+    "btn_select_logo": "Benutzerdefiniertes Logo wählen",
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
"wine_missing_hint": "Diese Funktion erfordert eine Wine-Installation auf deinem Linux-System.",
"sap_wizard_title": "SAP Management Wizard",
"sap_card_title": "SAP Management",
"sap_card_desc": "SAP Install Server Werkzeug",
"sap_step1_title": "1. SAP Installations-Server wählen",
"sap_step1_desc": "Wähle den Stammordner deines SAP nwsetupadmin Servers aus.",
"sap_step2_title": "2. Updates & Add-ons hinzufügen (Optional)",
"sap_step2_desc": "Wähle .exe Dateien aus, die in den Installations-Server integriert werden sollen.",
"sap_step3_title": "3. Anpassung",
"sap_step3_desc": "Konfiguriere Logo und Browser-Einstellungen.",
"sap_step4_title": "4. Zusammenfassung & Paketierung",
"sap_use_webview2": "Edge WebView2 als Standard (Empfohlen)",
"no_logo_selected": "Kein Logo ausgewählt",
"label_server": "Server",
"label_custom_logo": "Benutzerdefiniertes Logo",
"label_webview2": "Edge WebView2",
"btn_browse_folder": "Serverordner durchsuchen",
"btn_add_update": "Update EXE hinzufügen",
"btn_select_logo": "Custom Logo wählen",
"btn_apply_build": "Anwenden & Paketierung erstellen"
"wine_missing_hint": "Diese Funktion erfordert eine Wine-Installation auf deinem Linux-System.",
"sap_wizard_title": "SAP-Verwaltungsassistent",
"sap_card_title": "SAP Management",
"sap_card_desc": "SAP Install Server Werkzeug",
"sap_step1_title": "1. SAP Installations-Server wählen",
"sap_step1_desc": "Wähle den Stammordner deines SAP nwsetupadmin Servers aus.",
"sap_step2_title": "2. Updates & Add-ons hinzufügen (Optional)",
"sap_step2_desc": "Wähle .exe Dateien aus, die in den Installations-Server integriert werden sollen.",
"sap_step3_title": "3. Anpassung",
"sap_step3_desc": "Konfiguriere Logo und Browser-Einstellungen.",
"sap_step4_title": "4. Zusammenfassung & Paketierung",
"sap_use_webview2": "Edge WebView2 als Standard (Empfohlen)",
"no_logo_selected": "Kein Logo ausgewählt",
"label_server": "Server",
"label_custom_logo": "Benutzerdefiniertes Logo",
"label_webview2": "Edge WebView2",
"btn_browse_folder": "Serverordner durchsuchen",
"btn_add_update": "Update EXE hinzufügen",
"btn_select_logo": "Benutzerdefiniertes Logo wählen",
"btn_apply_build": "Anwenden & Paketierung erstellen"
🤖 Prompt for AI Agents
In `@src/switchcraft/assets/lang/de.json` around lines 1098 - 1117, Several newly
added localization keys (e.g., "sap_wizard_title", "sap_card_title",
"sap_card_desc", "sap_step1_title"… "btn_select_logo", "btn_apply_build")
contain English or mixed-language strings; replace them with fully German
translations to ensure a consistent localized UX—for example translate "SAP
Management Wizard" and "Custom Logo wählen" into proper German, and update all
"sap_stepX_*", "sap_use_webview2", "no_logo_selected", "label_*", and "btn_*"
values to idiomatic German while keeping the key names unchanged so callers
continue to work.

}
21 changes: 20 additions & 1 deletion src/switchcraft/assets/lang/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -1095,5 +1095,24 @@
"error_feature_demo_restricted": "Packaging is not available in the Web Demo.",
"error_wine_missing": "Wine is required to run the Packaging Tool on Linux. Please install Wine.",
"demo_restriction_hint": "The feature {feature}is restricted in the Web Demo. For full functionality, please use the Desktop version.",
"wine_missing_hint": "This feature requires Wine to be installed on your Linux system."
"wine_missing_hint": "This feature requires Wine to be installed on your Linux system.",
"sap_wizard_title": "SAP Management Wizard",
"sap_card_title": "SAP Management",
"sap_card_desc": "SAP Install Server tool",
"sap_step1_title": "1. Select SAP Installation Server",
"sap_step1_desc": "Point to the root folder of your SAP nwsetupadmin server.",
"sap_step2_title": "2. Add Updates & Add-ons (Optional)",
"sap_step2_desc": "Select .exe files to merge into the installation server.",
"sap_step3_title": "3. Customization",
"sap_step3_desc": "Configure logo and browser preferences.",
"sap_step4_title": "4. Summary & Packaging",
"sap_use_webview2": "Default to Edge WebView2 (Recommended)",
"no_logo_selected": "No logo selected",
"label_server": "Server",
"label_custom_logo": "Custom Logo",
"label_webview2": "Edge WebView2",
"btn_browse_folder": "Browse Server Folder",
"btn_add_update": "Add Update EXE",
"btn_select_logo": "Select Custom Logo",
"btn_apply_build": "Apply & Build Packaging"
}
9 changes: 9 additions & 0 deletions src/switchcraft/gui_modern/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -1076,6 +1076,9 @@ def build_ui(self):
ft.NavigationRailDestination(
icon=ft.Icons.POLICY_OUTLINED, selected_icon=ft.Icons.POLICY, label=i18n.get("settings_policies") or "Policies"
), # 21 Policies
ft.NavigationRailDestination(
icon=ft.Icons.BUSINESS, selected_icon=ft.Icons.BUSINESS, label=i18n.get("sap_card_title") or "SAP Management"
), # 22 SAP Magic
]


Expand Down Expand Up @@ -1779,6 +1782,12 @@ def _f():
from switchcraft.gui_modern.views.wingetcreate_view import WingetCreateView
return WingetCreateView(self.page)
load_view(_f)
elif idx == NavIndex.SAP_WIZARD:
# SAP Management
def _f():
from switchcraft.gui_modern.views.sap_wizard_view import SapWizardView
return SapWizardView(self.page)
load_view(_f)

else:
# Dynamic Addons
Expand Down
3 changes: 2 additions & 1 deletion src/switchcraft/gui_modern/nav_constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ class NavIndex:
EXCHANGE = 20 # Exchange Online View

SETTINGS_POLICIES = 21 # Settings tab index 3 (Policies)
SAP_WIZARD = 22 # SAP Management Wizard


# Mapping from NavIndex to sidebar category for reference
Expand All @@ -58,7 +59,7 @@ class NavIndex:
"Tools": [
NavIndex.ANALYZER, NavIndex.HELPER, NavIndex.SCRIPTS,
NavIndex.MACOS, NavIndex.PACKAGING_WIZARD, NavIndex.DETECTION_TESTER,
NavIndex.WINGET_CREATE
NavIndex.WINGET_CREATE, NavIndex.SAP_WIZARD
],
"System": [
NavIndex.SETTINGS, NavIndex.SETTINGS_UPDATES,
Expand Down
4 changes: 3 additions & 1 deletion src/switchcraft/gui_modern/views/category_view.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,9 @@
"Help & Resources": "desc_help",
"Hilfe & Ressourcen": "desc_help",
"Policies": "desc_policies",
"Richtlinien": "desc_policies"
"Richtlinien": "desc_policies",
"SAP Management": "sap_card_desc",
"SAP-Management": "sap_card_desc"
}

class CategoryView(ft.Container):
Expand Down
1 change: 1 addition & 0 deletions src/switchcraft/gui_modern/views/home_view.py
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,7 @@ def _build_content(self):
ft.Row([
self._create_action_card(i18n.get("home_card_analyzer_title") or "Analyzer", i18n.get("home_card_analyzer_desc") or "Deep Scan Installers", ft.Icons.SEARCH, NavIndex.ANALYZER, "CYAN"),
self._create_action_card(i18n.get("home_card_wizard_title") or "Wizard", i18n.get("home_card_wizard_desc") or "Packaging Wizard", ft.Icons.AUTO_FIX_HIGH, NavIndex.PACKAGING_WIZARD, "PURPLE"),
self._create_action_card(i18n.get("sap_card_title") or "SAP Management", i18n.get("sap_card_desc") or "SAP Install Server tool", ft.Icons.BUSINESS, NavIndex.SAP_WIZARD, "BLUE"),
self._create_action_card(i18n.get("home_card_winget_title") or "Winget", i18n.get("home_card_winget_desc") or "Browse Store", ft.Icons.SHOP_TWO, NavIndex.WINGET, "BLUE"),
], wrap=True, spacing=15),

Expand Down
119 changes: 119 additions & 0 deletions src/switchcraft/gui_modern/views/sap_wizard_view.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
import flet as ft
import logging
import os
from pathlib import Path
from switchcraft.gui_modern.utils.view_utils import ViewMixin
from switchcraft.utils.i18n import i18n
from switchcraft.services.sap_service import SapService

logger = logging.getLogger(__name__)

class SapWizardView(ft.Column, ViewMixin):
"""
Wizard-style UI for SAP Installation Server management.
Handles merging updates, customization, and packaging.
"""

def __init__(self, page: ft.Page):
super().__init__(expand=True, scroll=ft.ScrollMode.AUTO)
self.app_page = page
self.sap_service = SapService()

# State
self.server_path = ""
self.update_files = []
self.logo_path = ""
self.use_webview2 = True

self.current_step = 1
self.content_area = ft.Container(expand=True)
self.controls = [
ft.Text(i18n.get("sap_wizard_title") or "SAP Management Wizard", size=24, weight=ft.FontWeight.BOLD),
ft.Divider(),
self.content_area,
self._build_nav_buttons()
]

self._show_step(1)

def _show_step(self, step_num):
self.current_step = step_num
if step_num == 1:
self.content_area.content = self._build_step_1()
elif step_num == 2:
self.content_area.content = self._build_step_2()
elif step_num == 3:
self.content_area.content = self._build_step_3()
elif step_num == 4:
self.content_area.content = self._build_step_4()
self.update()

def _build_step_1(self):
"""Step 1: Select SAP Installation Server path."""
def on_pick_server(e: ft.FilePickerResultEvent):
if e.path:
self.server_path = e.path
path_text.value = e.path
self.update()

path_text = ft.Text(self.server_path or "No path selected", italic=True)
fp = ft.FilePicker(on_result=on_pick_server)
self.app_page.overlay.append(fp)

return ft.Column([
ft.Text(i18n.get("sap_step1_title") or "1. Select SAP Installation Server", size=18, weight=ft.FontWeight.BOLD),
ft.Text(i18n.get("sap_step1_desc") or "Point to the root folder of your SAP nwsetupadmin server."),
ft.Row([
ft.ElevatedButton(i18n.get("btn_browse_folder") or "Browse Server Folder", icon=ft.Icons.FOLDER_OPEN, on_click=lambda _: fp.get_directory_path()),
path_text
])
])
Comment on lines +51 to +71
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

FilePicker accumulates in overlay on repeated navigation.

Each call to _build_step_1 appends a new FilePicker to self.app_page.overlay. When users navigate back to step 1, this creates duplicate pickers. Consider initializing the FilePicker once in __init__ or clearing the previous one before adding.

Proposed fix - initialize FilePicker in __init__
 def __init__(self, page: ft.Page):
     super().__init__(expand=True, scroll=ft.ScrollMode.AUTO)
     self.app_page = page
     self.sap_service = SapService()

     # State
     self.server_path = ""
     self.update_files = []
     self.logo_path = ""
     self.use_webview2 = True

+    # FilePicker for server selection
+    self.server_picker = ft.FilePicker(on_result=self._on_pick_server)
+    self.app_page.overlay.append(self.server_picker)
+
     self.current_step = 1

Then update _build_step_1 to use self.server_picker instead of creating a new one.

🤖 Prompt for AI Agents
In `@src/switchcraft/gui_modern/views/sap_wizard_view.py` around lines 51 - 70,
The FilePicker is being appended to self.app_page.overlay each time
_build_step_1 runs, causing duplicates; fix by creating a single FilePicker once
(e.g., initialize self.server_picker = ft.FilePicker(on_result=...) in __init__)
and replace local fp usage in _build_step_1 with self.server_picker (append it
to self.app_page.overlay only once or ensure you remove any existing picker
before appending). Ensure the on_result handler updates self.server_path and
path_text the same way and that _build_step_1 references
self.server_picker.get_directory_path() in the ElevatedButton callback.


def _build_step_2(self):
"""Step 2: Add Updates/Add-ons."""
return ft.Column([
ft.Text(i18n.get("sap_step2_title") or "2. Add Updates & Add-ons (Optional)", size=18, weight=ft.FontWeight.BOLD),
ft.Text(i18n.get("sap_step2_desc") or "Select .exe files to merge into the installation server."),
ft.ElevatedButton(i18n.get("btn_add_update") or "Add Update EXE", icon=ft.Icons.ADD, on_click=lambda _: self._show_snack("Not implemented in stub")),
ft.ListView(expand=True, height=100) # Placeholder for file list
])

def _build_step_3(self):
"""Step 3: Customization."""
return ft.Column([
ft.Text(i18n.get("sap_step3_title") or "3. Customization", size=18, weight=ft.FontWeight.BOLD),
ft.Checkbox(label=i18n.get("sap_use_webview2") or "Default to Edge WebView2 (Recommended)", value=self.use_webview2, on_change=lambda e: setattr(self, 'use_webview2', e.control.value)),
ft.Row([
ft.ElevatedButton(i18n.get("btn_select_logo") or "Select Custom Logo", icon=ft.Icons.IMAGE),
ft.Text(i18n.get("no_logo_selected") or "No logo selected", italic=True)
])
])

def _build_step_4(self):
"""Step 4: Summary & Packaging."""
return ft.Column([
ft.Text(i18n.get("sap_step4_title") or "4. Summary & Packaging", size=18, weight=ft.FontWeight.BOLD),
ft.Text(f"{i18n.get('label_server') or 'Server'}: {self.server_path}"),
ft.Text(f"{i18n.get('label_custom_logo') or 'Custom Logo'}: {'Yes' if self.logo_path else 'No'}"),
ft.Text(f"{i18n.get('label_webview2') or 'Edge WebView2'}: {'Enabled' if self.use_webview2 else 'Disabled'}"),
ft.Divider(),
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)
])

def _build_nav_buttons(self):
return ft.Row([
ft.TextButton(i18n.get("btn_back") or "Back", on_click=lambda _: self._show_step(self.current_step - 1) if self.current_step > 1 else None),
ft.ElevatedButton(i18n.get("btn_next") or "Next", on_click=lambda _: self._show_step(self.current_step + 1) if self.current_step < 4 else None)
], alignment=ft.MainAxisAlignment.END)

def _on_finalize(self, _):
if not self.server_path:
self._show_snack("Please select a server path first.", color="RED")
return

try:
self.sap_service.customize_server(self.server_path, self.logo_path, self.use_webview2)
self._show_snack("SAP Server customized successfully!", color="GREEN")
# In a real app, we would now trigger the packaging process
except Exception as e:
self._show_snack(f"Error: {e}", color="RED")
Loading
Loading