mirror of
https://github.com/Omni-guides/Jackify.git
synced 2026-01-17 11:37:01 +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
|
||||
|
||||
## 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
|
||||
**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
|
||||
- **jackify-engine 0.4.4**: Latest engine version with improvements
|
||||
|
||||
### 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
|
||||
- **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
|
||||
|
||||
### Quality Improvements
|
||||
- Added pre-build import validator to prevent broken imports from reaching production
|
||||
|
||||
---
|
||||
|
||||
## 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.
|
||||
"""
|
||||
|
||||
__version__ = "0.2.0.6"
|
||||
__version__ = "0.2.0.7"
|
||||
|
||||
@@ -157,7 +157,8 @@ class ConfigHandler:
|
||||
# Migration: v0.0.x -> v0.2.0
|
||||
# Encryption changed from cryptography (Fernet) to pycryptodome (AES-GCM)
|
||||
# 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
|
||||
if self.settings.get("nexus_api_key"):
|
||||
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
|
||||
|
||||
# Now import it
|
||||
import steam_vdf
|
||||
import vdf as steam_vdf
|
||||
|
||||
with open(shortcuts_file, 'rb') as 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
|
||||
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.exec()
|
||||
|
||||
|
||||
@@ -4358,7 +4358,7 @@ class InstallModlistScreen(QWidget):
|
||||
|
||||
def _show_somnium_post_install_guidance(self):
|
||||
"""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>
|
||||
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):
|
||||
"""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>
|
||||
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:
|
||||
# Remove all cards from layout
|
||||
# CRITICAL FIX: Properly remove widgets to prevent overlapping and orphaned windows
|
||||
# We need to explicitly remove widgets from the layout before taking items
|
||||
# to ensure they're fully cleaned up, but we don't setParent(None) because
|
||||
# widgets are immediately re-added to the grid (Qt will reparent them).
|
||||
while self.grid_layout.count():
|
||||
item = self.grid_layout.takeAt(0)
|
||||
# CRITICAL FIX: Properly remove all widgets to prevent overlapping
|
||||
# Iterate backwards to avoid index shifting issues
|
||||
for i in range(self.grid_layout.count() - 1, -1, -1):
|
||||
item = self.grid_layout.takeAt(i)
|
||||
widget = item.widget() if item else None
|
||||
if widget:
|
||||
# Explicitly remove widget from layout to prevent overlapping
|
||||
self.grid_layout.removeWidget(widget)
|
||||
# Hide widget during removal to prevent visual artifacts
|
||||
widget.hide()
|
||||
del item
|
||||
|
||||
# Force layout update to ensure all widgets are removed
|
||||
self.grid_layout.update()
|
||||
|
||||
# Calculate number of columns based on available width
|
||||
# Get the scroll area width (accounting for filter panel ~280px + margins)
|
||||
scroll_area = self.grid_widget.parent()
|
||||
@@ -1558,16 +1559,20 @@ class ModlistGalleryDialog(QDialog):
|
||||
|
||||
card = self.all_cards.get(modlist.machineURL)
|
||||
if card:
|
||||
# Ensure widget is not already in the layout (prevent overlapping)
|
||||
# If it is, remove it first (shouldn't happen after takeAt, but safety check)
|
||||
if card.parent() == self.grid_widget:
|
||||
# Widget is already a child of grid_widget, check if it's in layout
|
||||
for i in range(self.grid_layout.count()):
|
||||
item = self.grid_layout.itemAt(i)
|
||||
if item and item.widget() == card:
|
||||
# Already in layout, remove it first
|
||||
self.grid_layout.removeWidget(card)
|
||||
break
|
||||
# Safety check: ensure widget is not already in the layout
|
||||
# (shouldn't happen after proper removal above, but defensive programming)
|
||||
already_in_layout = False
|
||||
for i in range(self.grid_layout.count()):
|
||||
item = self.grid_layout.itemAt(i)
|
||||
if item and item.widget() == card:
|
||||
# Widget is already in layout - this shouldn't happen, but handle it
|
||||
already_in_layout = True
|
||||
self.grid_layout.removeWidget(card)
|
||||
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)
|
||||
|
||||
# Set column stretch - don't stretch card columns, but add a spacer column
|
||||
|
||||
Reference in New Issue
Block a user