Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
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
36 changes: 24 additions & 12 deletions xcode/Catnip.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -423,9 +423,10 @@
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
ASSETCATALOG_COMPILER_WIDGET_BACKGROUND_COLOR_NAME = WidgetBackground;
CODE_SIGN_ENTITLEMENTS = CatnipWidgetsExtension.entitlements;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_TEAM = QCUUU7QVF7;
DEVELOPMENT_TEAM = 5DTHBP38WM;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = CatnipWidgets/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = CatnipWidgets;
Expand All @@ -437,8 +438,9 @@
"@executable_path/../../Frameworks",
);
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = wandb.catnip.CatnipWidgets;
PRODUCT_BUNDLE_IDENTIFIER = com.wandb.catnip.CatnipWidgets;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
SKIP_INSTALL = YES;
STRING_CATALOG_GENERATE_SYMBOLS = YES;
"SWIFT_ACTIVE_COMPILATION_CONDITIONS[arch=*]" = WIDGET_EXTENSION;
Expand All @@ -456,9 +458,10 @@
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
ASSETCATALOG_COMPILER_WIDGET_BACKGROUND_COLOR_NAME = WidgetBackground;
CODE_SIGN_ENTITLEMENTS = CatnipWidgetsExtension.entitlements;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_TEAM = QCUUU7QVF7;
DEVELOPMENT_TEAM = 5DTHBP38WM;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = CatnipWidgets/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = CatnipWidgets;
Expand All @@ -470,8 +473,9 @@
"@executable_path/../../Frameworks",
);
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = wandb.catnip.CatnipWidgets;
PRODUCT_BUNDLE_IDENTIFIER = com.wandb.catnip.CatnipWidgets;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
SKIP_INSTALL = YES;
STRING_CATALOG_GENERATE_SYMBOLS = YES;
"SWIFT_ACTIVE_COMPILATION_CONDITIONS[arch=*]" = WIDGET_EXTENSION;
Expand All @@ -490,12 +494,15 @@
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
ASSETCATALOG_COMPILER_INCLUDE_ALL_APPICON_ASSETS = YES;
CODE_SIGN_ENTITLEMENTS = catnip/catnip.entitlements;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 2;
DEVELOPMENT_TEAM = QCUUU7QVF7;
DEVELOPMENT_TEAM = 5DTHBP38WM;
ENABLE_PREVIEWS = YES;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = catnip/Info.plist;
INFOPLIST_KEY_ITSAppUsesNonExemptEncryption = NO;
INFOPLIST_KEY_NSSupportsLiveActivities = YES;
INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES;
INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
INFOPLIST_KEY_UILaunchScreen_Generation = YES;
Expand All @@ -506,8 +513,9 @@
"@executable_path/Frameworks",
);
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = wandb.catnip;
PRODUCT_BUNDLE_IDENTIFIER = com.wandb.catnip;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
STRING_CATALOG_GENERATE_SYMBOLS = YES;
SWIFT_DEFAULT_ACTOR_ISOLATION = MainActor;
SWIFT_EMIT_LOC_STRINGS = YES;
Expand All @@ -524,12 +532,15 @@
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
ASSETCATALOG_COMPILER_INCLUDE_ALL_APPICON_ASSETS = YES;
CODE_SIGN_ENTITLEMENTS = catnip/catnip.entitlements;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 2;
DEVELOPMENT_TEAM = QCUUU7QVF7;
DEVELOPMENT_TEAM = 5DTHBP38WM;
ENABLE_PREVIEWS = YES;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = catnip/Info.plist;
INFOPLIST_KEY_ITSAppUsesNonExemptEncryption = NO;
INFOPLIST_KEY_NSSupportsLiveActivities = YES;
INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES;
INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
INFOPLIST_KEY_UILaunchScreen_Generation = YES;
Expand All @@ -540,8 +551,9 @@
"@executable_path/Frameworks",
);
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = wandb.catnip;
PRODUCT_BUNDLE_IDENTIFIER = com.wandb.catnip;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
STRING_CATALOG_GENERATE_SYMBOLS = YES;
SWIFT_DEFAULT_ACTOR_ISOLATION = MainActor;
SWIFT_EMIT_LOC_STRINGS = YES;
Expand Down Expand Up @@ -678,7 +690,7 @@
BUNDLE_LOADER = "$(TEST_HOST)";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_TEAM = QCUUU7QVF7;
DEVELOPMENT_TEAM = 5DTHBP38WM;
GENERATE_INFOPLIST_FILE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 17.0;
MARKETING_VERSION = 1.0;
Expand All @@ -699,7 +711,7 @@
BUNDLE_LOADER = "$(TEST_HOST)";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_TEAM = QCUUU7QVF7;
DEVELOPMENT_TEAM = 5DTHBP38WM;
GENERATE_INFOPLIST_FILE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 17.0;
MARKETING_VERSION = 1.0;
Expand All @@ -719,7 +731,7 @@
buildSettings = {
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_TEAM = QCUUU7QVF7;
DEVELOPMENT_TEAM = 5DTHBP38WM;
GENERATE_INFOPLIST_FILE = YES;
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = wandb.catnipUITests;
Expand All @@ -738,7 +750,7 @@
buildSettings = {
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_TEAM = QCUUU7QVF7;
DEVELOPMENT_TEAM = 5DTHBP38WM;
GENERATE_INFOPLIST_FILE = YES;
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = wandb.catnipUITests;
Expand Down
2 changes: 1 addition & 1 deletion xcode/CatnipWidgetsExtension.entitlements
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<dict>
<key>com.apple.security.application-groups</key>
<array>
<string>group.com.wandb.catnip</string>
<string>group.com.wandb.catnip.widgets</string>
</array>
</dict>
</plist>
18 changes: 9 additions & 9 deletions xcode/catnip/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,6 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>ITSAppUsesNonExemptEncryption</key>
<false/>
<key>NSSupportsLiveActivities</key>
<true/>
<key>UIBackgroundModes</key>
<array>
<string>remote-notification</string>
<string>fetch</string>
</array>
<key>CFBundleURLTypes</key>
<array>
<dict>
Expand All @@ -24,5 +15,14 @@
</array>
<key>NSUserNotificationsUsageDescription</key>
<string>Catnip sends notifications when your codespace is ready. Creating a codespace can take up to 10 minutes.</string>
<key>ITSAppUsesNonExemptEncryption</key>
<false/>
<key>NSSupportsLiveActivities</key>
<true/>
<key>UIBackgroundModes</key>
<array>
<string>remote-notification</string>
<string>fetch</string>
</array>
</dict>
</plist>
35 changes: 35 additions & 0 deletions xcode/catnip/Views/CodespaceView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ enum RepositoryListMode {
}

struct CodespaceView: View {
@Environment(\.scenePhase) private var scenePhase
@EnvironmentObject var authManager: AuthManager
@StateObject private var installer = CatnipInstaller.shared
@StateObject private var tracker = CodespaceCreationTracker.shared
Expand All @@ -40,6 +41,8 @@ struct CodespaceView: View {
@State private var createdCodespace: CodespaceCreationResult.CodespaceInfo?
@State private var repositoryListMode: RepositoryListMode = .installation
@State private var pendingRepository: String?
@State private var pendingCodespaceName: String?
@State private var wasConnectingBeforeBackground = false

private let catFacts = [
"Cats can rotate their ears 180 degrees.",
Expand Down Expand Up @@ -227,6 +230,10 @@ struct CodespaceView: View {
NSLog("🐱 [CodespaceView] Failed to preload repositories: \(error)")
}
}

}
.onChange(of: scenePhase) { oldPhase, newPhase in
handleScenePhaseChange(oldPhase: oldPhase, newPhase: newPhase)
}
}

Expand Down Expand Up @@ -510,6 +517,9 @@ struct CodespaceView: View {
statusMessage = ""
statusMessage = "Finding your codespace..."

// Store codespace name for potential reconnection after backgrounding
pendingCodespaceName = codespaceName

// Mock connection for UI tests
if UITestingHelper.isUITesting {
UserDefaults.standard.set("mock-codespace", forKey: "codespace_name")
Expand Down Expand Up @@ -1115,6 +1125,31 @@ struct CodespaceView: View {
.background(Color(uiColor: .systemGroupedBackground))
}

// MARK: - App Lifecycle Handling

private func handleScenePhaseChange(oldPhase: ScenePhase, newPhase: ScenePhase) {
// Track when app goes to background during SSE connection
if newPhase == .background && phase == .connecting {
wasConnectingBeforeBackground = true
NSLog("🐱 [CodespaceView] App backgrounded during SSE connection, will reconnect on foreground")
}

// Reconnect when app returns to foreground if we were connecting
if newPhase == .active && oldPhase == .background && wasConnectingBeforeBackground && phase == .connecting {
NSLog("🐱 [CodespaceView] App foregrounded, reconnecting SSE...")

// Disconnect the old stale connection
sseService?.disconnect()
sseService = nil

// Restart the connection with the same codespace name
handleConnect(codespaceName: pendingCodespaceName)

// Reset the flag
wasConnectingBeforeBackground = false
}
}

private var createRepositoryView: some View {
ScrollView {
VStack(spacing: 24) {
Expand Down
2 changes: 1 addition & 1 deletion xcode/catnip/catnip.entitlements
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<string>development</string>
<key>com.apple.security.application-groups</key>
<array>
<string>group.com.wandb.catnip</string>
<string>group.com.wandb.catnip.widgets</string>
</array>
</dict>
</plist>