Skip to content

Conversation

@graycreate
Copy link
Member

Summary

  • Fixed theme switching to apply immediately without requiring app restart
  • Theme changes now take effect in real-time when selecting Light/Dark/System modes

Changes

  • Added notification observer in RootHostingController to listen for theme changes
  • Moved preferredColorScheme modifier to the correct view hierarchy level
  • Removed duplicate notification handling in V2erApp
  • Added force redraw on theme change to ensure immediate UI update
  • Cleaned up redundant theme update calls in AppearanceSettingView

Test Plan

  • Build and run the app
  • Navigate to Settings > Appearance Settings
  • Switch between Light, Dark, and System modes
  • Verify theme changes apply immediately without app restart
  • Verify navigation bar and status bar colors update correctly
  • Verify all UI elements reflect the new theme

🤖 Generated with Claude Code

graycreate and others added 7 commits September 13, 2025 23:31
- Changed onChange to onReceive with proper publisher for reactive theme updates
- Added immediate window interface style updates when theme is changed
- Wrapped UIKit updates in DispatchQueue.main.async for thread safety
- Force window tint color refresh for navigation bar appearance
- Added direct updateAppearance call in settings for instant feedback

🤖 Generated with Claude Code (https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
- Added notification-based immediate UI updates for theme changes
- Modified WindowGroup to properly apply preferredColorScheme at root level
- Added ZStack with ID to force view redraw on theme change
- Implemented applyAppearance method in RootHostingController
- Added debug logging to track theme changes
- Synchronized UserDefaults to ensure persistence
- Updated both window and hosting controller interface styles
- Added notification observer for cross-component communication

🤖 Generated with Claude Code (https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
- Removed AppearanceMode type dependency in RootHostingController
- Simplified WindowGroup structure removing ZStack wrapper
- Use string-based appearance handling to avoid type issues
- Restored stable app launch while keeping theme functionality

🤖 Generated with Claude Code (https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
- Fixed settings UI to use store state directly instead of local @State
- Added comprehensive debug logging throughout theme change flow
- Enhanced window interface style updates to cover all scenes and windows
- Added startup theme application with slight delay for proper initialization
- Improved UserDefaults loading with debug output
- Force window redraw after theme changes
- Ensure all UI elements properly reflect saved theme preference

🤖 Generated with Claude Code (https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
- Created static methods for appearance updates to avoid self capture in init
- Replaced instance method calls with static versions in closures
- Simplified updateAppearance in AppearanceSettingView to use static method
- Maintains all functionality while fixing Swift compilation issue

🤖 Generated with Claude Code (https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
- Added notification observer in RootHostingController to listen for theme changes
- Moved preferredColorScheme modifier to the correct view hierarchy level
- Removed duplicate notification handling in V2erApp
- Added force redraw on theme change to ensure immediate UI update
- Cleaned up redundant theme update calls in AppearanceSettingView

The app now switches themes immediately when selecting Light/Dark/System modes
in settings without requiring an app restart.
Copilot AI review requested due to automatic review settings September 14, 2025 01:10
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

This PR fixes theme switching functionality to apply immediately without requiring an app restart. The implementation adds real-time theme change support through notification-based architecture and proper view hierarchy modifications.

  • Added notification observer in RootHostingController to listen for theme changes and apply them immediately
  • Simplified theme state management by removing local state variables and using the global store directly
  • Enhanced UI update mechanisms with forced redraws and proper interface style propagation

Reviewed Changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 17 comments.

Show a summary per file
File Description
AppearanceSettingView.swift Removed local state and simplified UI to use store state directly
SettingState.swift Added debug logging for appearance loading and initialization
SettingReducer.swift Added notification posting and debug logging for theme changes
V2erApp.swift Enhanced appearance update methods with static variants and improved UI refresh logic
RootView.swift Added notification observer and appearance handling in RootHostingController

Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.

ForEach(AppearanceMode.allCases, id: \.self) { mode in
Button(action: {
selectedAppearance = mode
print("🎨 User selected: \(mode.rawValue)")
Copy link

Copilot AI Sep 14, 2025

Choose a reason for hiding this comment

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

Debug print statements should be removed from production code. Consider using a proper logging framework or removing this before merging to production.

Suggested change
print("🎨 User selected: \(mode.rawValue)")

Copilot uses AI. Check for mistakes.
Comment on lines 20 to 22
print("📱 Loaded saved appearance: \(mode.rawValue)")
} else {
print("📱 No saved appearance, using default: system")
Copy link

Copilot AI Sep 14, 2025

Choose a reason for hiding this comment

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

Debug print statements should be removed from production code. Consider using a proper logging framework or removing these before merging to production.

Suggested change
print("📱 Loaded saved appearance: \(mode.rawValue)")
} else {
print("📱 No saved appearance, using default: system")
} else {

Copilot uses AI. Check for mistakes.

switch action {
case let action as SettingActions.ChangeAppearanceAction:
print("🎨 Changing appearance to: \(action.appearance.rawValue)")
Copy link

Copilot AI Sep 14, 2025

Choose a reason for hiding this comment

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

Debug print statements should be removed from production code. Consider using a proper logging framework or removing this before merging to production.

Copilot uses AI. Check for mistakes.
setupNotifications()
// Apply saved theme on app launch
let savedAppearance = Store.shared.appState.settingState.appearance
print("🚀 Saved appearance on launch: \(savedAppearance.rawValue)")
Copy link

Copilot AI Sep 14, 2025

Choose a reason for hiding this comment

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

Debug print statements should be removed from production code. Consider using a proper logging framework or removing this before merging to production.

Suggested change
print("🚀 Saved appearance on launch: \(savedAppearance.rawValue)")
// Debug print removed for production

Copilot uses AI. Check for mistakes.
}

private func updateAppearance(_ appearance: AppearanceMode) {
print("🔄 Updating appearance to: \(appearance.rawValue)")
Copy link

Copilot AI Sep 14, 2025

Choose a reason for hiding this comment

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

Multiple debug print statements should be removed from production code. Consider using a proper logging framework or removing these before merging to production.

Copilot uses AI. Check for mistakes.
// Also update the stored window if available
if let window = V2erApp.window {
window.overrideUserInterfaceStyle = style
print(" ✓ Updated stored window")
Copy link

Copilot AI Sep 14, 2025

Choose a reason for hiding this comment

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

Multiple debug print statements should be removed from production code. Consider using a proper logging framework or removing these before merging to production.

Copilot uses AI. Check for mistakes.
// Update the root hosting controller
if let rootHostingController = V2erApp.rootViewController as? RootHostingController<RootHostView> {
rootHostingController.applyAppearanceFromString(appearance.rawValue)
print(" ✓ Updated root hosting controller")
Copy link

Copilot AI Sep 14, 2025

Choose a reason for hiding this comment

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

Multiple debug print statements should be removed from production code. Consider using a proper logging framework or removing these before merging to production.

Copilot uses AI. Check for mistakes.
Comment on lines 22 to 31
setupNotifications()
// Apply saved theme on app launch
let savedAppearance = Store.shared.appState.settingState.appearance
print("🚀 Saved appearance on launch: \(savedAppearance.rawValue)")
}

private func setupNotifications() {
// Notifications are now handled in RootHostingController
}

Copy link

Copilot AI Sep 14, 2025

Choose a reason for hiding this comment

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

Empty method with only a comment should be removed entirely since it serves no purpose. If this is a placeholder for future functionality, consider adding a TODO comment or removing it completely.

Suggested change
setupNotifications()
// Apply saved theme on app launch
let savedAppearance = Store.shared.appState.settingState.appearance
print("🚀 Saved appearance on launch: \(savedAppearance.rawValue)")
}
private func setupNotifications() {
// Notifications are now handled in RootHostingController
}
// Apply saved theme on app launch
let savedAppearance = Store.shared.appState.settingState.appearance
print("🚀 Saved appearance on launch: \(savedAppearance.rawValue)")
}

Copilot uses AI. Check for mistakes.
}

// Force a redraw
UIApplication.shared.windows.forEach { $0.setNeedsDisplay() }
Copy link

Copilot AI Sep 14, 2025

Choose a reason for hiding this comment

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

UIApplication.shared.windows is deprecated in iOS 15+. Consider using UIApplication.shared.connectedScenes approach consistently as done elsewhere in the same methods.

Copilot uses AI. Check for mistakes.
}

// Force a redraw
UIApplication.shared.windows.forEach { $0.setNeedsDisplay() }
Copy link

Copilot AI Sep 14, 2025

Choose a reason for hiding this comment

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

UIApplication.shared.windows is deprecated in iOS 15+. Consider using UIApplication.shared.connectedScenes approach consistently as done elsewhere in the same methods.

Suggested change
UIApplication.shared.windows.forEach { $0.setNeedsDisplay() }
UIApplication.shared.connectedScenes.forEach { scene in
if let windowScene = scene as? UIWindowScene {
windowScene.windows.forEach { $0.setNeedsDisplay() }
}
}

Copilot uses AI. Check for mistakes.
- Removed all debug print statements from production code
- Fixed deprecated UIApplication.shared.windows usage
- Removed empty setupNotifications method
- Cleaned up code formatting and unnecessary blank lines

All CI checks should now pass.
@github-actions github-actions bot added size/L and removed size/L labels Sep 14, 2025
@graycreate graycreate merged commit 87f1c0e into main Sep 14, 2025
4 of 6 checks passed
@graycreate graycreate deleted the bugfix/theme-switching branch September 14, 2025 11:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants