Skip to content

Commit bade351

Browse files
committed
chore: merge master into release
2 parents a7c4629 + e511a0d commit bade351

72 files changed

Lines changed: 3194 additions & 362 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

AGENTS.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -279,6 +279,7 @@ Ensure accessibility modifiers and labels are added to custom components.
279279
- Swift version: 5.10
280280
- Use descriptive names: `isLoadingUsers` not `loading`
281281
- Follow Apple's SwiftUI best practices
282+
- AVOID code comments on private functions, types, etc — PREFER self-documenting names that make intent obvious without explanation; only add a comment when the rationale is genuinely non-obvious (e.g. a workaround, an edge case, or a "why" the code itself can't convey)
282283

283284
### Changelog
284285

Bitkit.xcodeproj/xcshareddata/xcschemes/BitkitAITests.xcscheme

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,7 @@
3131
shouldAutocreateTestPlan = "YES">
3232
<Testables>
3333
<TestableReference
34-
skipped = "NO"
35-
parallelizable = "NO">
34+
skipped = "NO">
3635
<BuildableReference
3736
BuildableIdentifier = "primary"
3837
BlueprintIdentifier = "96FE1F7B2C2DE6AC006D0C8B"

Bitkit/Components/Button/Button.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,8 @@ struct CustomButton: View {
166166
size: size,
167167
icon: icon,
168168
isDisabled: effectiveIsDisabled,
169-
isPressed: isPressed
169+
isPressed: isPressed,
170+
isLoading: isLoading
170171
))
171172
case .tertiary:
172173
AnyView(TertiaryButtonView(

Bitkit/Components/Button/SecondaryButtonView.swift

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,19 @@ struct SecondaryButtonView: View {
66
let icon: AnyView?
77
let isDisabled: Bool
88
let isPressed: Bool
9+
var isLoading: Bool = false
910

1011
var body: some View {
1112
HStack(spacing: 8) {
12-
if let icon {
13+
if let icon, !isLoading {
1314
icon
1415
}
1516

16-
if size == .small {
17+
if isLoading {
18+
ProgressView()
19+
.progressViewStyle(CircularProgressViewStyle(tint: textColor))
20+
.frame(width: 20, height: 20)
21+
} else if size == .small {
1722
CaptionBText(title, textColor: textColor)
1823
} else {
1924
BodySSBText(title, textColor: textColor)

Bitkit/Components/NumberPad.swift

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ struct NumberPad: View {
1010
let type: NumberPadType
1111
let decimalSeparator: String
1212
let errorKey: String?
13+
let isDisabled: Bool
1314
let onDeleteLongPress: (() -> Void)?
1415
let onPress: (String) -> Void
1516

@@ -25,12 +26,14 @@ struct NumberPad: View {
2526
type: NumberPadType = .simple,
2627
decimalSeparator: String = ".",
2728
errorKey: String? = nil,
29+
isDisabled: Bool = false,
2830
onDeleteLongPress: (() -> Void)? = nil,
2931
onPress: @escaping (String) -> Void
3032
) {
3133
self.type = type
3234
self.decimalSeparator = decimalSeparator
3335
self.errorKey = errorKey
36+
self.isDisabled = isDisabled
3437
self.onDeleteLongPress = onDeleteLongPress
3538
self.onPress = onPress
3639
}
@@ -127,6 +130,8 @@ struct NumberPad: View {
127130
)
128131
}
129132
}
133+
.opacity(isDisabled ? 0.5 : 1)
134+
.disabled(isDisabled)
130135
}
131136
}
132137

Bitkit/Components/NumberPadTextField.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import SwiftUI
33
/// NumberPadTextField - Amount view to be used with number pad
44
struct NumberPadTextField: View {
55
@EnvironmentObject var currency: CurrencyViewModel
6-
@ObservedObject var viewModel: AmountInputViewModel
6+
var viewModel: AmountInputViewModel
77

88
var showConversion: Bool = true
99
var showEditButton: Bool = false

Bitkit/Components/ToastView.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ struct ToastView: View {
2121
.frame(maxWidth: .infinity, alignment: .leading)
2222
.padding(16)
2323
.background(accentColor.opacity(0.32))
24-
.background(.ultraThinMaterial)
24+
.background(BlurView())
2525
.cornerRadius(16)
2626
.shadow(color: .black.opacity(0.4), radius: 10, x: 0, y: 25)
2727
.accessibilityIdentifierIfPresent(toast.accessibilityIdentifier)
@@ -78,7 +78,7 @@ struct ToastView: View {
7878
}
7979
} else {
8080
// Snap back to original position
81-
withAnimation(.spring(response: 0.3, dampingFraction: 0.7)) {
81+
withAnimation(ToastMotion.entrance) {
8282
dragOffset = 0
8383
}
8484
}
@@ -92,7 +92,7 @@ struct ToastView: View {
9292
case .info: return .blueAccent
9393
case .lightning: return .purpleAccent
9494
case .warning: return .brandAccent
95-
case .error: return .redAccent
95+
case .error: return .brandAccent
9696
}
9797
}
9898
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import SwiftUI
2+
3+
struct TrezorAccountTypeSelector: View {
4+
@Binding var selection: TrezorAccountTypeSelection
5+
var title: String = "Account Type"
6+
7+
var body: some View {
8+
VStack(alignment: .leading, spacing: 8) {
9+
CaptionMText(title)
10+
11+
SegmentedControl(selectedTab: $selection, tabs: TrezorAccountTypeSelection.allCases)
12+
13+
FootnoteText(selection.subtitle)
14+
}
15+
.frame(maxWidth: .infinity, alignment: .leading)
16+
.accessibilityIdentifier("TrezorAccountTypeSelector")
17+
}
18+
}

Bitkit/Components/Trezor/TrezorPinPad.swift

Lines changed: 29 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,11 @@ struct TrezorPinPad: View {
66
/// Current PIN being entered
77
@Binding var pin: String
88

9-
/// Maximum PIN length
10-
var maxLength: Int = 9
9+
/// Maximum PIN length. Trezor PINs can be up to 50 digits.
10+
var maxLength: Int = 50
11+
12+
/// Number of entered-digit dots to render per row before wrapping.
13+
private let dotsPerRow = 9
1114

1215
/// PIN pad layout (positions map to device keypad)
1316
/// The Trezor shows scrambled numbers, we show only position dots
@@ -19,12 +22,30 @@ struct TrezorPinPad: View {
1922

2023
var body: some View {
2124
VStack(spacing: 16) {
22-
// PIN display
23-
HStack(spacing: 12) {
24-
ForEach(0 ..< maxLength, id: \.self) { index in
25-
Circle()
26-
.fill(index < pin.count ? Color.white : Color.white.opacity(0.3))
27-
.frame(width: 12, height: 12)
25+
// PIN display — one dot per entered digit, wrapping across rows so long
26+
// PINs (Trezor allows up to 50 digits) don't overflow a single line.
27+
VStack(spacing: 8) {
28+
if pin.isEmpty {
29+
// Placeholder row so the layout doesn't collapse before entry.
30+
HStack(spacing: 12) {
31+
ForEach(0 ..< dotsPerRow, id: \.self) { _ in
32+
Circle()
33+
.fill(Color.white.opacity(0.3))
34+
.frame(width: 12, height: 12)
35+
}
36+
}
37+
} else {
38+
let rowCount = (pin.count + dotsPerRow - 1) / dotsPerRow
39+
ForEach(0 ..< rowCount, id: \.self) { row in
40+
let dotsInRow = min(dotsPerRow, pin.count - row * dotsPerRow)
41+
HStack(spacing: 12) {
42+
ForEach(0 ..< dotsInRow, id: \.self) { _ in
43+
Circle()
44+
.fill(Color.white)
45+
.frame(width: 12, height: 12)
46+
}
47+
}
48+
}
2849
}
2950
}
3051
.padding(.bottom, 24)

Bitkit/Components/Widgets/Suggestions.swift

Lines changed: 31 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,10 @@ struct Suggestions: View {
164164
/// When true, show a fixed set of static cards and ignore taps (e.g. widget preview).
165165
var isPreview: Bool = false
166166

167+
/// When editing the home grid, keep the widget visible (and reorderable/removable) by falling
168+
/// back to the static preview set when there are no live cards to show.
169+
var isEditing: Bool = false
170+
167171
var previewCardIds: [String]?
168172

169173
static let previewSheetCardIds = ["backupSeedPhrase", "pin", "transferToSpending", "support"]
@@ -250,8 +254,30 @@ struct Suggestions: View {
250254
)
251255
}
252256

257+
private var isEditingFallback: Bool {
258+
isEditing && !isPreview && visibleCards.isEmpty
259+
}
260+
261+
private var cardsToShow: [SuggestionCardData] {
262+
guard isEditingFallback else { return visibleCards }
263+
return Self.visibleCards(
264+
wallet: wallet,
265+
app: app,
266+
settings: settings,
267+
suggestionsManager: suggestionsManager,
268+
pubkyProfile: pubkyProfile,
269+
isPaykitUIEnabled: isPaykitUIActive,
270+
isPreview: true,
271+
previewCardIds: Self.previewSheetCardIds
272+
)
273+
}
274+
275+
private var renderStatic: Bool {
276+
isPreview || isEditingFallback
277+
}
278+
253279
var body: some View {
254-
if visibleCards.isEmpty {
280+
if cardsToShow.isEmpty {
255281
EmptyView()
256282
} else {
257283
LazyVGrid(
@@ -261,25 +287,25 @@ struct Suggestions: View {
261287
],
262288
spacing: 16
263289
) {
264-
ForEach(visibleCards) { card in
290+
ForEach(cardsToShow) { card in
265291
SuggestionCard(
266292
title: card.title,
267293
description: card.description,
268294
imageName: card.imageName,
269295
accentColor: card.color,
270-
onTap: { if !isPreview { onItemTap(card) } },
296+
onTap: { if !renderStatic { onItemTap(card) } },
271297
onDismiss: { dismissCard(card) }
272298
)
273299
.background {
274-
if isPreview {
300+
if renderStatic {
275301
RoundedRectangle(cornerRadius: 16).fill(Color.black)
276302
}
277303
}
278304
.accessibilityElement(children: .contain)
279305
.accessibilityIdentifier("Suggestion-\(card.accessibilityId)")
280306
}
281307
}
282-
.allowsHitTesting(!isPreview)
308+
.allowsHitTesting(!renderStatic)
283309
.sheet(isPresented: $showShareSheet) {
284310
ShareSheet(activityItems: [
285311
t(

0 commit comments

Comments
 (0)