Skip to content

Commit cc96d0a

Browse files
committed
Version & FIlePicker bug fixes
1 parent 638f27d commit cc96d0a

9 files changed

Lines changed: 99 additions & 86 deletions

File tree

.github/scripts/update_version_info.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,11 +35,12 @@ def update_version_info(version_str, file_path='file_version_info.txt'):
3535
content = re.sub(r'filevers=\(\d+, \d+, \d+, \d+\)', f'filevers={tuple_str}', content)
3636
content = re.sub(r'prodvers=\(\d+, \d+, \d+, \d+\)', f'prodvers={tuple_str}', content)
3737

38+
# Update StringStructs
3839
# Update StringStructs
3940
# FileVersion should be numeric only
40-
content = re.sub(r"StringStruct\(u'FileVersion', u'[^']+'\)", f"StringStruct(u'FileVersion', u'{full_version_str}')", content)
41+
content = re.sub(r"StringStruct\(u?'FileVersion', u?'[^']+'\)", f"StringStruct(u'FileVersion', u'{full_version_str}')", content)
4142
# ProductVersion can include suffix for display
42-
content = re.sub(r"StringStruct\(u'ProductVersion', u'[^']+'\)", f"StringStruct(u'ProductVersion', u'{display_version_str}')", content)
43+
content = re.sub(r"StringStruct\(u?'ProductVersion', u?'[^']+'\)", f"StringStruct(u'ProductVersion', u'{display_version_str}')", content)
4344

4445
with open(file_path, 'w', encoding='utf-8') as f:
4546
f.write(content)

.github/workflows/review-auto-merge.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,8 @@ jobs:
6161
6262
# 2. Check PR Author Permissions
6363
PR_AUTHOR=$(gh pr view "$PR_NUMBER" --json author --jq '.author.login')
64-
if [[ "$PR_AUTHOR" == *"[bot]" ]]; then
64+
echo "PR Author: $PR_AUTHOR"
65+
if [[ "$PR_AUTHOR" == *"[bot]" || "$PR_AUTHOR" == "app/renovate" ]]; then
6566
echo "PR Author is a Bot. Allowed."
6667
else
6768
PERM=$(gh api "repos/$REPO/collaborators/$PR_AUTHOR/permission" --jq '.permission')

file_version_info.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,12 +31,12 @@ VSVersionInfo(
3131
'040904B0',
3232
[StringStruct('CompanyName', 'FaserF'),
3333
StringStruct('FileDescription', 'SwitchCraft - Advanced Silent Switch & Packaging Tool'),
34-
StringStruct('FileVersion', '2026.1.4.0'),
34+
StringStruct('FileVersion', '2026.1.5.0'),
3535
StringStruct('InternalName', 'SwitchCraft'),
3636
StringStruct('LegalCopyright', 'Copyright (c) 2026 FaserF'),
3737
StringStruct('OriginalFilename', 'SwitchCraft.exe'),
3838
StringStruct('ProductName', 'SwitchCraft'),
39-
StringStruct('ProductVersion', '2026.1.4.0')])
39+
StringStruct('ProductVersion', '2026.1.5.0')])
4040
]),
4141
VarFileInfo([VarStruct('Translation', [1033, 1200])])
4242
]

scripts/build_release.ps1

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -226,10 +226,26 @@ if (-not $IsCI -and (Test-Path (Join-Path $RepoRoot ".git"))) {
226226
try {
227227
$GitCommit = (git rev-parse --short HEAD).Trim()
228228
if ($GitCommit) {
229-
# Append local dev suffix
230-
$AppVersion = "$AppVersion.dev0+$GitCommit"
231-
Write-Host "Local Dev Build Detected: Appending commit hash $GitCommit" -ForegroundColor Cyan
232-
Write-Host "New Version: $AppVersion" -ForegroundColor Cyan
229+
# Append local dev suffix only if not already present
230+
if (-not ($AppVersion -like "*$GitCommit*")) {
231+
# If version is already a dev version (has .dev), just append +commit if missing?
232+
# Or typically we want "X.Y.Z.dev0+commit"
233+
# If AppVersion is "2026.1.5", we make "2026.1.5.dev0+commit"
234+
# If AppVersion is "2026.1.5.dev0+oldcommit", we might be in trouble, but assuming standard flow:
235+
236+
if ($AppVersion -match "dev\d+") {
237+
# Already has dev tag, maybe just missing commit or has different one?
238+
# Ideally we replace the existing build metadata?
239+
# For safety/simplicity in this script: Don't append .dev0 again if it has dev match
240+
$AppVersion = "$AppVersion+$GitCommit"
241+
} else {
242+
$AppVersion = "$AppVersion.dev0+$GitCommit"
243+
}
244+
Write-Host "Local Dev Build Detected: Appending commit hash $GitCommit" -ForegroundColor Cyan
245+
Write-Host "New Version: $AppVersion" -ForegroundColor Cyan
246+
} else {
247+
Write-Host "Local Dev Build: Version already contains current commit hash ($GitCommit). Skipping append." -ForegroundColor Gray
248+
}
233249
}
234250
} catch {
235251
Write-Warning "Failed to get git commit hash: $_"

src/switchcraft/gui_modern/views/intune_store_view.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -361,6 +361,15 @@ def _load_image_async():
361361
)
362362
detail_controls.append(self.title_field)
363363

364+
365+
# Editable Version Field
366+
self.version_field = ft.TextField(
367+
label=i18n.get("field_version") or "Version",
368+
value=app.get("displayVersion", ""),
369+
expand=True
370+
)
371+
detail_controls.append(self.version_field)
372+
364373
# Metadata (read-only)
365374
meta_rows = [
366375
(i18n.get("field_id", default="ID"), app.get("id")),
@@ -561,6 +570,9 @@ def _save_changes(self, app):
561570
if hasattr(self, 'title_field') and self.title_field.value != app.get('displayName'):
562571
update_data['displayName'] = self.title_field.value
563572

573+
if hasattr(self, 'version_field') and self.version_field.value != app.get('displayVersion'):
574+
update_data['displayVersion'] = self.version_field.value
575+
564576
if hasattr(self, 'description_field') and self.description_field.value != app.get('description'):
565577
update_data['description'] = self.description_field.value
566578

src/switchcraft/gui_modern/views/settings_view.py

Lines changed: 51 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,9 @@ def __init__(self, page: ft.Page, initial_tab_index=0):
2727
self.latest_version_text = ft.Text("")
2828

2929
# Shared FilePicker for various actions
30-
self.file_picker = ft.FilePicker()
31-
self.file_picker.on_result = self._on_file_picker_result
30+
# self.file_picker removed in favor of FilePickerHelper (Tkinter) logic
31+
# self.file_picker = ft.FilePicker()
32+
# self.file_picker.on_result = self._on_file_picker_result
3233

3334
# Custom Tab Navigation
3435
self.current_content = ft.Container(expand=True, padding=10)
@@ -57,8 +58,7 @@ def __init__(self, page: ft.Page, initial_tab_index=0):
5758
self.controls = [
5859
ft.Container(content=self.nav_row, height=60, padding=5, bgcolor="SURFACE_CONTAINER"),
5960
ft.Divider(height=1, thickness=1),
60-
self.current_content,
61-
self.file_picker
61+
self.current_content
6262
]
6363

6464
# Load initial content
@@ -93,6 +93,8 @@ def did_mount(self):
9393
# Check for policy-managed settings
9494
self._check_managed_settings()
9595

96+
97+
9698
def _switch_tab(self, builder_func):
9799
try:
98100
if builder_func:
@@ -1127,6 +1129,7 @@ async def _export_settings(self, e):
11271129
"""
11281130
from switchcraft import IS_WEB
11291131
import base64
1132+
import json
11301133

11311134
prefs = SwitchCraftConfig.export_preferences()
11321135
json_str = json.dumps(prefs, indent=4)
@@ -1140,89 +1143,55 @@ async def _export_settings(self, e):
11401143
self._launch_url(data_uri)
11411144
self._show_snack("Export started (Check downloads)", "GREEN")
11421145
else:
1143-
# Desktop: Use Save File Dialog
1144-
self._picker_context = "export_settings"
1145-
await self.file_picker.save_file(
1146+
# Desktop: Use Save File Dialog via Helper
1147+
from switchcraft.gui_modern.utils.file_picker_helper import FilePickerHelper
1148+
path = FilePickerHelper.save_file(
11461149
dialog_title=i18n.get("btn_export_settings") or "Export Settings",
11471150
file_name="settings.json",
11481151
allowed_extensions=["json"]
11491152
)
11501153

1154+
if path:
1155+
try:
1156+
with open(path, "w") as f:
1157+
f.write(json_str)
1158+
self._show_snack(f"{i18n.get('export_success') or 'Exported to'} {path}", "GREEN")
1159+
except Exception as ex:
1160+
logger.error(f"Failed to export settings: {ex}")
1161+
self._show_snack(f"Export Failed: {ex}", "RED")
1162+
11511163
async def _import_settings(self, e):
11521164
"""
11531165
Import settings via FilePicker.
11541166
"""
1155-
self._picker_context = "import_settings"
1156-
await self.file_picker.pick_files(
1157-
allow_multiple=False,
1158-
allowed_extensions=["json"],
1159-
dialog_title=i18n.get("btn_import_settings") or "Import Settings"
1160-
)
1167+
from switchcraft import IS_WEB
1168+
import json
11611169

1162-
def _on_file_picker_result(self, e):
1163-
"""Handle results from the shared FilePicker."""
1164-
context = getattr(self, "_picker_context", None)
1165-
if not context:
1166-
return
1170+
if IS_WEB:
1171+
self._show_snack("Settings import not supported in web version yet", "ORANGE")
1172+
return
11671173

1168-
if context == "export_settings":
1169-
if e.path:
1170-
try:
1171-
prefs = SwitchCraftConfig.export_preferences()
1172-
with open(e.path, "w") as f:
1173-
json.dump(prefs, f, indent=4)
1174-
self._show_snack(f"{i18n.get('export_success') or 'Exported to'} {e.path}")
1175-
except Exception as ex:
1176-
logger.error(f"Failed to export settings: {ex}")
1177-
self._show_snack(f"Export Failed: {ex}", "RED")
1174+
from switchcraft.gui_modern.utils.file_picker_helper import FilePickerHelper
1175+
path = FilePickerHelper.pick_file(
1176+
allowed_extensions=["json"],
1177+
allow_multiple=False
1178+
)
11781179

1179-
elif context == "import_settings":
1180-
if e.files and len(e.files) > 0:
1181-
fpath = e.files[0].path
1182-
content = getattr(e.files[0], "content", None)
1180+
if path:
1181+
# pick_file returns string if allow_multiple=False is intended or just first item
1182+
fpath = path[0] if isinstance(path, list) else path
11831183

1184-
try:
1185-
if fpath:
1186-
# Desktop Flow
1187-
with open(fpath, "r", encoding="utf-8") as f:
1188-
data = json.load(f)
1189-
elif content:
1190-
# Web Flow (Simulated/Future-Proofing for Flet Web Byte Access)
1191-
# content is usually bytes in Flet Web
1192-
data = json.loads(content.decode("utf-8"))
1193-
else:
1194-
# Fallback for Web where path is None and content not provided directly
1195-
# Or restricted environment
1196-
from switchcraft import IS_WEB
1197-
if IS_WEB:
1198-
self._show_snack("Settings import not supported in web version yet (Sandbox restriction)", "ORANGE")
1199-
else:
1200-
self._show_snack("Import failed: No file path or content received", "RED")
1201-
return
1184+
try:
1185+
with open(fpath, "r", encoding="utf-8") as f:
1186+
data = json.load(f)
12021187

1203-
SwitchCraftConfig.import_preferences(data)
1204-
self._show_snack(i18n.get("import_success") or "Settings Imported. Please Restart.", "GREEN")
1205-
except Exception as ex:
1206-
logger.error(f"Error importing settings: {ex}")
1207-
self._show_snack(f"Import Failed: {ex}", "RED")
1188+
SwitchCraftConfig.import_preferences(data)
1189+
self._show_snack(i18n.get("import_success") or "Settings Imported. Please Restart.", "GREEN")
1190+
except Exception as ex:
1191+
logger.error(f"Error importing settings: {ex}")
1192+
self._show_snack(f"Import Failed: {ex}", "RED")
12081193

1209-
elif context == "export_logs":
1210-
if e.path:
1211-
try:
1212-
# e.path is the destination
1213-
# We need to copy from self._log_source_path (set in _export_logs)
1214-
src = getattr(self, "_log_source_path", None)
1215-
if src:
1216-
import shutil
1217-
shutil.copy2(src, e.path)
1218-
self._show_snack(f"Logs exported to {e.path}", "GREEN")
1219-
else:
1220-
self._show_snack("Log copy failed: Source lost", "RED")
1221-
except Exception as ex:
1222-
self._show_snack(f"Log export failed: {ex}", "RED")
12231194

1224-
# Reset context
1225-
self._picker_context = None
12261195

12271196
async def _export_logs(self, e):
12281197
"""Export logs to a file. Includes current session log and recent log files."""
@@ -1275,14 +1244,22 @@ async def _export_logs(self, e):
12751244
self._show_snack(f"Web Export Failed: {ex}", "RED")
12761245
else:
12771246
# Desktop: Save Dialog
1278-
self._log_source_path = source_path
1279-
self._picker_context = "export_logs"
1280-
await self.file_picker.save_file(
1247+
from switchcraft.gui_modern.utils.file_picker_helper import FilePickerHelper
1248+
1249+
path = FilePickerHelper.save_file(
12811250
dialog_title=i18n.get("help_export_logs") or "Export Logs",
12821251
file_name=filename,
12831252
allowed_extensions=["log", "txt"]
12841253
)
12851254

1255+
if path:
1256+
try:
1257+
import shutil
1258+
shutil.copy2(source_path, path)
1259+
self._show_snack(f"Logs exported to {path}", "GREEN")
1260+
except Exception as ex:
1261+
self._show_snack(f"Log export failed: {ex}", "RED")
1262+
12861263

12871264

12881265

src/switchcraft/services/intune_service.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -581,7 +581,7 @@ def list_apps(self, token, filter_query=None):
581581
else:
582582
# Default limits and select to improve performance
583583
params["$top"] = "100"
584-
params["$select"] = "id,displayName,publisher,appType,largeIcon,iconUrl,logoUrl"
584+
params["$select"] = "id,displayName,publisher,appType,largeIcon,iconUrl,logoUrl,displayVersion"
585585

586586
try:
587587
resp = requests.get(url, headers=headers, params=params, timeout=30, stream=False)

switchcraft.iss

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@
1717
#define MyAppPublisher "FaserF"
1818
#define MyAppURL "https://github.com/FaserF/SwitchCraft"
1919
#define MyAppExeName "SwitchCraft.exe"
20-
#define MyAppDescription "Silent Install Switch Finder"
20+
#define MyAppDescription "SwitchCraft - Advanced Silent Switch & Packaging Tool"
21+
#define MyAppCopyright "Copyright (c) 2026 FaserF"
2122

2223
[Setup]
2324
; Basic Info
@@ -33,6 +34,8 @@ VersionInfoVersion={#MyAppVersionInfo}
3334
VersionInfoCompany={#MyAppPublisher}
3435
VersionInfoDescription={#MyAppDescription}
3536
VersionInfoProductName={#MyAppName}
37+
VersionInfoCopyright={#MyAppCopyright}
38+
VersionInfoProductVersion={#MyAppVersionInfo}
3639

3740
; Default directory (changes based on admin/user mode)
3841
DefaultDirName={autopf}\{#MyAppPublisher}\{#MyAppName}

switchcraft_legacy.iss

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@
1717
#define MyAppPublisher "FaserF"
1818
#define MyAppURL "https://github.com/FaserF/SwitchCraft"
1919
#define MyAppExeName "SwitchCraft-Legacy.exe"
20-
#define MyAppDescription "Silent Install Switch Finder (Legacy)"
20+
#define MyAppDescription "SwitchCraft - Advanced Silent Switch & Packaging Tool (Legacy)"
21+
#define MyAppCopyright "Copyright (c) 2026 FaserF"
2122

2223
[Setup]
2324
; Basic Info
@@ -33,6 +34,8 @@ VersionInfoVersion={#MyAppVersionInfo}
3334
VersionInfoCompany={#MyAppPublisher}
3435
VersionInfoDescription={#MyAppDescription}
3536
VersionInfoProductName={#MyAppName}
37+
VersionInfoCopyright={#MyAppCopyright}
38+
VersionInfoProductVersion={#MyAppVersionInfo}
3639

3740
; Default directory (changes based on admin/user mode)
3841
DefaultDirName={autopf}\{#MyAppPublisher}\{#MyAppName}

0 commit comments

Comments
 (0)