mirror of
https://github.com/Omni-guides/Jackify.git
synced 2026-01-17 19:47:00 +01:00
Sync from development - prepare for v0.2.0.7
This commit is contained in:
15
CHANGELOG.md
15
CHANGELOG.md
@@ -1,16 +1,31 @@
|
|||||||
# Jackify Changelog
|
# Jackify Changelog
|
||||||
|
|
||||||
|
## v0.2.0.7 - Critical Auth Fix
|
||||||
|
**Release Date:** 2025-12-28
|
||||||
|
|
||||||
|
### Critical Bug Fixes
|
||||||
|
- **OAuth Token Loss**: Fixed version comparison bug that was deleting OAuth tokens every time settings were saved (affects users on v0.2.0.4+)
|
||||||
|
- Fixed internal import paths for improved stability
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## v0.2.0.6 - Premium Detection and Engine Update
|
## v0.2.0.6 - Premium Detection and Engine Update
|
||||||
**Release Date:** 2025-12-28
|
**Release Date:** 2025-12-28
|
||||||
|
|
||||||
|
**IMPORTANT:** If you are on v0.2.0.5, automatic updates will not work. You must manually download and install v0.2.0.6.
|
||||||
|
|
||||||
### Engine Updates
|
### Engine Updates
|
||||||
- **jackify-engine 0.4.4**: Latest engine version with improvements
|
- **jackify-engine 0.4.4**: Latest engine version with improvements
|
||||||
|
|
||||||
### Critical Bug Fixes
|
### Critical Bug Fixes
|
||||||
|
- **Auto-Update System**: Fixed broken update dialog import that prevented automatic updates
|
||||||
- **Premium Detection**: Fixed false Premium errors caused by overly-broad detection pattern triggering on jackify-engine 0.4.3's userinfo JSON output
|
- **Premium Detection**: Fixed false Premium errors caused by overly-broad detection pattern triggering on jackify-engine 0.4.3's userinfo JSON output
|
||||||
- **Custom Data Directory**: Fixed AppImage always creating ~/Jackify on startup, even when user configured a custom jackify_data_dir
|
- **Custom Data Directory**: Fixed AppImage always creating ~/Jackify on startup, even when user configured a custom jackify_data_dir
|
||||||
- **Proton Auto-Selection**: Fixed auto-selection writing invalid "auto" string to config on detection failure
|
- **Proton Auto-Selection**: Fixed auto-selection writing invalid "auto" string to config on detection failure
|
||||||
|
|
||||||
|
### Quality Improvements
|
||||||
|
- Added pre-build import validator to prevent broken imports from reaching production
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## v0.2.0.5 - Emergency OAuth Fix
|
## v0.2.0.5 - Emergency OAuth Fix
|
||||||
|
|||||||
@@ -5,4 +5,4 @@ This package provides both CLI and GUI interfaces for managing
|
|||||||
Wabbajack modlists natively on Linux systems.
|
Wabbajack modlists natively on Linux systems.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
__version__ = "0.2.0.6"
|
__version__ = "0.2.0.7"
|
||||||
|
|||||||
@@ -157,7 +157,8 @@ class ConfigHandler:
|
|||||||
# Migration: v0.0.x -> v0.2.0
|
# Migration: v0.0.x -> v0.2.0
|
||||||
# Encryption changed from cryptography (Fernet) to pycryptodome (AES-GCM)
|
# Encryption changed from cryptography (Fernet) to pycryptodome (AES-GCM)
|
||||||
# Old encrypted API keys cannot be decrypted, must be re-entered
|
# Old encrypted API keys cannot be decrypted, must be re-entered
|
||||||
if current_version < "0.2.0":
|
from packaging import version
|
||||||
|
if version.parse(current_version) < version.parse("0.2.0"):
|
||||||
# Clear old encrypted credentials
|
# Clear old encrypted credentials
|
||||||
if self.settings.get("nexus_api_key"):
|
if self.settings.get("nexus_api_key"):
|
||||||
logger.warning("Clearing saved API key due to encryption format change")
|
logger.warning("Clearing saved API key due to encryption format change")
|
||||||
|
|||||||
@@ -205,7 +205,7 @@ class ShortcutHandler:
|
|||||||
time.sleep(1) # Give some time for the install to complete
|
time.sleep(1) # Give some time for the install to complete
|
||||||
|
|
||||||
# Now import it
|
# Now import it
|
||||||
import steam_vdf
|
import vdf as steam_vdf
|
||||||
|
|
||||||
with open(shortcuts_file, 'rb') as f:
|
with open(shortcuts_file, 'rb') as f:
|
||||||
shortcuts_data = steam_vdf.load(f)
|
shortcuts_data = steam_vdf.load(f)
|
||||||
|
|||||||
@@ -1562,7 +1562,7 @@ class JackifyMainWindow(QMainWindow):
|
|||||||
|
|
||||||
# Show update dialog after a short delay to ensure GUI is fully loaded
|
# Show update dialog after a short delay to ensure GUI is fully loaded
|
||||||
def show_update_dialog():
|
def show_update_dialog():
|
||||||
from ..dialogs.update_dialog import UpdateDialog
|
from .dialogs.update_dialog import UpdateDialog
|
||||||
dialog = UpdateDialog(update_info, self.update_service, self)
|
dialog = UpdateDialog(update_info, self.update_service, self)
|
||||||
dialog.exec()
|
dialog.exec()
|
||||||
|
|
||||||
|
|||||||
@@ -4358,7 +4358,7 @@ class InstallModlistScreen(QWidget):
|
|||||||
|
|
||||||
def _show_somnium_post_install_guidance(self):
|
def _show_somnium_post_install_guidance(self):
|
||||||
"""Show guidance popup for Somnium post-installation steps"""
|
"""Show guidance popup for Somnium post-installation steps"""
|
||||||
from ..widgets.message_service import MessageService
|
from ..services.message_service import MessageService
|
||||||
|
|
||||||
guidance_text = f"""<b>Somnium Post-Installation Required</b><br><br>
|
guidance_text = f"""<b>Somnium Post-Installation Required</b><br><br>
|
||||||
Due to Somnium's non-standard folder structure, you need to manually update the binary paths in ModOrganizer:<br><br>
|
Due to Somnium's non-standard folder structure, you need to manually update the binary paths in ModOrganizer:<br><br>
|
||||||
|
|||||||
@@ -3494,7 +3494,7 @@ class InstallTTWScreen(QWidget):
|
|||||||
|
|
||||||
def _show_somnium_post_install_guidance(self):
|
def _show_somnium_post_install_guidance(self):
|
||||||
"""Show guidance popup for Somnium post-installation steps"""
|
"""Show guidance popup for Somnium post-installation steps"""
|
||||||
from ..widgets.message_service import MessageService
|
from ..services.message_service import MessageService
|
||||||
|
|
||||||
guidance_text = f"""<b>Somnium Post-Installation Required</b><br><br>
|
guidance_text = f"""<b>Somnium Post-Installation Required</b><br><br>
|
||||||
Due to Somnium's non-standard folder structure, you need to manually update the binary paths in ModOrganizer:<br><br>
|
Due to Somnium's non-standard folder structure, you need to manually update the binary paths in ModOrganizer:<br><br>
|
||||||
|
|||||||
@@ -1509,18 +1509,19 @@ class ModlistGalleryDialog(QDialog):
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
# Remove all cards from layout
|
# Remove all cards from layout
|
||||||
# CRITICAL FIX: Properly remove widgets to prevent overlapping and orphaned windows
|
# CRITICAL FIX: Properly remove all widgets to prevent overlapping
|
||||||
# We need to explicitly remove widgets from the layout before taking items
|
# Iterate backwards to avoid index shifting issues
|
||||||
# to ensure they're fully cleaned up, but we don't setParent(None) because
|
for i in range(self.grid_layout.count() - 1, -1, -1):
|
||||||
# widgets are immediately re-added to the grid (Qt will reparent them).
|
item = self.grid_layout.takeAt(i)
|
||||||
while self.grid_layout.count():
|
|
||||||
item = self.grid_layout.takeAt(0)
|
|
||||||
widget = item.widget() if item else None
|
widget = item.widget() if item else None
|
||||||
if widget:
|
if widget:
|
||||||
# Explicitly remove widget from layout to prevent overlapping
|
# Hide widget during removal to prevent visual artifacts
|
||||||
self.grid_layout.removeWidget(widget)
|
widget.hide()
|
||||||
del item
|
del item
|
||||||
|
|
||||||
|
# Force layout update to ensure all widgets are removed
|
||||||
|
self.grid_layout.update()
|
||||||
|
|
||||||
# Calculate number of columns based on available width
|
# Calculate number of columns based on available width
|
||||||
# Get the scroll area width (accounting for filter panel ~280px + margins)
|
# Get the scroll area width (accounting for filter panel ~280px + margins)
|
||||||
scroll_area = self.grid_widget.parent()
|
scroll_area = self.grid_widget.parent()
|
||||||
@@ -1558,16 +1559,20 @@ class ModlistGalleryDialog(QDialog):
|
|||||||
|
|
||||||
card = self.all_cards.get(modlist.machineURL)
|
card = self.all_cards.get(modlist.machineURL)
|
||||||
if card:
|
if card:
|
||||||
# Ensure widget is not already in the layout (prevent overlapping)
|
# Safety check: ensure widget is not already in the layout
|
||||||
# If it is, remove it first (shouldn't happen after takeAt, but safety check)
|
# (shouldn't happen after proper removal above, but defensive programming)
|
||||||
if card.parent() == self.grid_widget:
|
already_in_layout = False
|
||||||
# Widget is already a child of grid_widget, check if it's in layout
|
for i in range(self.grid_layout.count()):
|
||||||
for i in range(self.grid_layout.count()):
|
item = self.grid_layout.itemAt(i)
|
||||||
item = self.grid_layout.itemAt(i)
|
if item and item.widget() == card:
|
||||||
if item and item.widget() == card:
|
# Widget is already in layout - this shouldn't happen, but handle it
|
||||||
# Already in layout, remove it first
|
already_in_layout = True
|
||||||
self.grid_layout.removeWidget(card)
|
self.grid_layout.removeWidget(card)
|
||||||
break
|
break
|
||||||
|
|
||||||
|
# Ensure widget is visible and add to grid
|
||||||
|
if not already_in_layout or card.isHidden():
|
||||||
|
card.show()
|
||||||
self.grid_layout.addWidget(card, row, col)
|
self.grid_layout.addWidget(card, row, col)
|
||||||
|
|
||||||
# Set column stretch - don't stretch card columns, but add a spacer column
|
# Set column stretch - don't stretch card columns, but add a spacer column
|
||||||
|
|||||||
Reference in New Issue
Block a user