Skip to content
Draft
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
54 changes: 42 additions & 12 deletions Bitkit/AppScene.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,29 @@ import LDKNode
import SwiftUI
import UserNotifications

enum OrphanedKeychainCleanup {
static func perform(
hasNativeKeychain: Bool,
hasOrphanedRNKeychain: Bool,
deleteBitkitSharedIdentities: () throws -> Void,
wipePrivateKeychain: () throws -> Void,
cleanupRNKeychain: () -> Void
) throws {
guard hasNativeKeychain || hasOrphanedRNKeychain else {
return
}

// A reinstall must never orphan a shared Bitkit credential. Ring-owned
// accounts are outside this deletion's scope.
try deleteBitkitSharedIdentities()
try wipePrivateKeychain()

if hasOrphanedRNKeychain {
cleanupRNKeychain()
}
}
}

struct AppScene: View {
@Environment(\.scenePhase) var scenePhase
@EnvironmentObject private var session: SessionManager
Expand Down Expand Up @@ -485,7 +508,7 @@ struct AppScene: View {
/// Handle orphaned keychain entries from previous app installs.
/// If the installation marker doesn't exist but keychain has data, the app was reinstalled
/// and the keychain data is orphaned (corresponding wallet data was deleted with the app).
private func handleOrphanedKeychain() {
private func handleOrphanedKeychain() throws {
// If marker exists, app was installed before - keychain is valid
if InstallationMarker.exists() {
Logger.debug("Installation marker exists, skipping orphaned keychain check", context: "AppScene")
Expand All @@ -500,26 +523,30 @@ struct AppScene: View {

if hasNativeKeychain || hasOrphanedRNKeychain {
Logger.warn("Orphaned keychain detected, wiping", context: "AppScene")
try? Keychain.wipeEntireKeychain()

if hasOrphanedRNKeychain {
MigrationsService.shared.cleanupRNKeychain()
}
try OrphanedKeychainCleanup.perform(
hasNativeKeychain: hasNativeKeychain,
hasOrphanedRNKeychain: hasOrphanedRNKeychain,
deleteBitkitSharedIdentities: {
try SharedPubkyIdentityVault.deleteAllBitkitIdentities()
},
wipePrivateKeychain: {
try Keychain.wipeEntireKeychain()
},
cleanupRNKeychain: {
MigrationsService.shared.cleanupRNKeychain()
}
)
}

// Create marker for this installation
do {
try InstallationMarker.create()
} catch {
Logger.error("Failed to create installation marker: \(error)", context: "AppScene")
}
try InstallationMarker.create()
}

@Sendable
private func setupTask() async {
do {
// Handle orphaned keychain before anything else
handleOrphanedKeychain()
try handleOrphanedKeychain()

await checkAndPerformRNMigration()
try wallet.setWalletExistsState()
Expand Down Expand Up @@ -662,6 +689,9 @@ struct AppScene: View {
}

if newPhase == .active {
Task {
await pubkyProfile.validateSharedIdentitySourceIfNeeded()
}
// Reconnect a known hardware device so its connection indicator turns green again;
if isPinVerified || !settings.pinEnabled {
Task { await trezorManager.autoReconnect() }
Expand Down
16 changes: 16 additions & 0 deletions Bitkit/Assets.xcassets/icons/key.imageset/Contents.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"images" : [
{
"filename" : "key.svg",
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
},
"properties" : {
"preserves-vector-representation" : true,
"template-rendering-intent" : "template"
}
}
5 changes: 5 additions & 0 deletions Bitkit/Assets.xcassets/icons/key.imageset/key.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions Bitkit/Bitkit.entitlements
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
<string>$(AppIdentifierPrefix)to.bitkit.signet</string>
<string>$(AppIdentifierPrefix)to.bitkit.testnet</string>
<string>$(AppIdentifierPrefix)to.bitkit.regtest</string>
<string>$(AppIdentifierPrefix)pubky.shared</string>
</array>
</dict>
</plist>
14 changes: 12 additions & 2 deletions Bitkit/Components/Button/Button.swift
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ struct CustomButton: View {
let isDisabled: Bool
let isLoading: Bool
let shouldExpand: Bool
let labelKerning: CGFloat
let background: AnyView?
let action: (() async -> Void)?
let destination: AnyView?
Expand All @@ -85,6 +86,7 @@ struct CustomButton: View {
isDisabled: Bool = false,
isLoading: Bool = false,
shouldExpand: Bool = false,
labelKerning: CGFloat = 0.4,
background: (any View)? = nil
) {
self.title = title
Expand All @@ -94,6 +96,7 @@ struct CustomButton: View {
self.isDisabled = isDisabled
self.isLoading = isLoading
self.shouldExpand = shouldExpand
self.labelKerning = labelKerning
self.background = background.map { AnyView($0) }
action = nil
destination = nil
Expand All @@ -108,6 +111,7 @@ struct CustomButton: View {
isDisabled: Bool = false,
isLoading: Bool = false,
shouldExpand: Bool = false,
labelKerning: CGFloat = 0.4,
background: (any View)? = nil,
action: @escaping () async -> Void
) {
Expand All @@ -118,6 +122,7 @@ struct CustomButton: View {
self.isDisabled = isDisabled
self.isLoading = isLoading
self.shouldExpand = shouldExpand
self.labelKerning = labelKerning
self.background = background.map { AnyView($0) }
self.action = action
destination = nil
Expand All @@ -132,6 +137,7 @@ struct CustomButton: View {
isDisabled: Bool = false,
isLoading: Bool = false,
shouldExpand: Bool = false,
labelKerning: CGFloat = 0.4,
background: (any View)? = nil,
destination: some View
) {
Expand All @@ -142,6 +148,7 @@ struct CustomButton: View {
self.isDisabled = isDisabled
self.isLoading = isLoading
self.shouldExpand = shouldExpand
self.labelKerning = labelKerning
self.background = background.map { AnyView($0) }
action = nil
self.destination = AnyView(destination)
Expand All @@ -158,6 +165,7 @@ struct CustomButton: View {
isLoading: isLoading,
isPressed: isPressed,
shouldExpand: shouldExpand,
labelKerning: labelKerning,
background: background
))
case .secondary:
Expand All @@ -167,13 +175,15 @@ struct CustomButton: View {
icon: icon,
isDisabled: effectiveIsDisabled,
isPressed: isPressed,
isLoading: isLoading
isLoading: isLoading,
labelKerning: labelKerning
))
case .tertiary:
AnyView(TertiaryButtonView(
title: title,
icon: icon,
isPressed: isPressed
isPressed: isPressed,
labelKerning: labelKerning
))
}
}
Expand Down
3 changes: 2 additions & 1 deletion Bitkit/Components/Button/PrimaryButtonView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ struct PrimaryButtonView: View {
let isLoading: Bool
let isPressed: Bool
let shouldExpand: Bool
let labelKerning: CGFloat
let background: AnyView?

var body: some View {
Expand All @@ -24,7 +25,7 @@ struct PrimaryButtonView: View {
if size == .small {
CaptionBText(title, textColor: .textPrimary)
} else {
BodySSBText(title, textColor: .textPrimary)
BodySSBText(title, textColor: .textPrimary, kerning: labelKerning)
}
}
}
Expand Down
3 changes: 2 additions & 1 deletion Bitkit/Components/Button/SecondaryButtonView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ struct SecondaryButtonView: View {
let isDisabled: Bool
let isPressed: Bool
var isLoading: Bool = false
let labelKerning: CGFloat

var body: some View {
HStack(spacing: 8) {
Expand All @@ -21,7 +22,7 @@ struct SecondaryButtonView: View {
} else if size == .small {
CaptionBText(title, textColor: textColor)
} else {
BodySSBText(title, textColor: textColor)
BodySSBText(title, textColor: textColor, kerning: labelKerning)
}
}
.frame(maxWidth: size == .large ? .infinity : nil)
Expand Down
3 changes: 2 additions & 1 deletion Bitkit/Components/Button/TertiaryButtonView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,15 @@ struct TertiaryButtonView: View {
let title: String
let icon: AnyView?
let isPressed: Bool
let labelKerning: CGFloat

var body: some View {
HStack(spacing: 8) {
if let icon {
icon
}

BodySSBText(title, textColor: textColor)
BodySSBText(title, textColor: textColor, kerning: labelKerning)
}
.frame(maxWidth: .infinity)
.frame(height: CustomButton.Size.large.height)
Expand Down
5 changes: 1 addition & 4 deletions Bitkit/Components/NavigationBar.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,13 @@ struct NavigationBar: View {
let action: AnyView?
let icon: String?
let onBack: (() -> Void)?
let backAccessibilityIdentifier: String

init(
title: String,
showBackButton: Bool = true,
showMenuButton: Bool = true,
action: AnyView? = nil,
icon: String? = nil,
backAccessibilityIdentifier: String = "NavigationBack",
onBack: (() -> Void)? = nil
) {
self.title = title
Expand All @@ -27,7 +25,6 @@ struct NavigationBar: View {
self.action = action
self.icon = icon
self.onBack = onBack
self.backAccessibilityIdentifier = backAccessibilityIdentifier
}

var body: some View {
Expand All @@ -51,7 +48,7 @@ struct NavigationBar: View {
.foregroundColor(.textPrimary)
.frame(width: 24, height: 24)
}
.accessibilityIdentifier(backAccessibilityIdentifier)
.accessibilityIdentifier("NavigationBack")
} else {
Spacer()
.frame(width: 24, height: 24)
Expand Down
2 changes: 2 additions & 0 deletions Bitkit/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>SharedPubkyKeychainAccessGroup</key>
<string>$(AppIdentifierPrefix)pubky.shared</string>
<key>CFBundleURLTypes</key>
<array>
<dict>
Expand Down
Loading