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
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"images" : [
{
"filename" : "app-icon.png",
"filename" : "app-icon-black.png",
"idiom" : "universal",
"scale" : "1x"
},
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
"images" : [
{
"filename" : "app-icon-orange.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"idiom" : "universal",
"scale" : "2x"
},
{
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file not shown.
Binary file modified Bitkit/Assets.xcassets/icons/bolt.imageset/bolt.pdf
Binary file not shown.
12 changes: 10 additions & 2 deletions Bitkit/Components/Button/Button.swift
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ struct CustomButton: View {
let isDisabled: Bool
let isLoading: Bool
let shouldExpand: Bool
let background: AnyView?
let action: (() async -> Void)?
let destination: AnyView?

Expand All @@ -77,7 +78,8 @@ struct CustomButton: View {
icon: (any View)? = nil,
isDisabled: Bool = false,
isLoading: Bool = false,
shouldExpand: Bool = false
shouldExpand: Bool = false,
background: (any View)? = nil
) {
self.title = title
self.variant = variant
Expand All @@ -86,6 +88,7 @@ struct CustomButton: View {
self.isDisabled = isDisabled
self.isLoading = isLoading
self.shouldExpand = shouldExpand
self.background = background.map { AnyView($0) }
action = nil
destination = nil
}
Expand All @@ -99,6 +102,7 @@ struct CustomButton: View {
isDisabled: Bool = false,
isLoading: Bool = false,
shouldExpand: Bool = false,
background: (any View)? = nil,
action: @escaping () async -> Void
) {
self.title = title
Expand All @@ -108,6 +112,7 @@ struct CustomButton: View {
self.isDisabled = isDisabled
self.isLoading = isLoading
self.shouldExpand = shouldExpand
self.background = background.map { AnyView($0) }
self.action = action
destination = nil
}
Expand All @@ -121,6 +126,7 @@ struct CustomButton: View {
isDisabled: Bool = false,
isLoading: Bool = false,
shouldExpand: Bool = false,
background: (any View)? = nil,
destination: some View
) {
self.title = title
Expand All @@ -130,6 +136,7 @@ struct CustomButton: View {
self.isDisabled = isDisabled
self.isLoading = isLoading
self.shouldExpand = shouldExpand
self.background = background.map { AnyView($0) }
action = nil
self.destination = AnyView(destination)
}
Expand All @@ -144,7 +151,8 @@ struct CustomButton: View {
isDisabled: isDisabled,
isLoading: isLoading,
isPressed: isPressed,
shouldExpand: shouldExpand
shouldExpand: shouldExpand,
background: background
))
case .secondary:
AnyView(SecondaryButtonView(
Expand Down
6 changes: 6 additions & 0 deletions 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 background: AnyView?

var body: some View {
HStack(spacing: 8) {
Expand Down Expand Up @@ -38,9 +39,14 @@ struct PrimaryButtonView: View {
}

private var backgroundGradient: some View {
if let background {
return background
}

if isLoading {
return AnyView(Color.gray6)
}

if isDisabled {
return AnyView(Color.clear)
}
Expand Down
8 changes: 6 additions & 2 deletions Bitkit/Components/CopyAddressCard.swift
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,10 @@ struct CopyAddressCard: View {
onCopy(address: pair.address, index: index)
}

ShareLink(item: URL(string: pair.address)!) {
ShareLink(
item: pair.address,
preview: SharePreview(pair.address, image: Image("app-icon-orange"))
) {
CustomButton(
title: t("common__share"),
size: .small,
Expand Down Expand Up @@ -77,7 +80,8 @@ struct CopyAddressCard: View {
Spacer()
}
.frame(maxWidth: .infinity, alignment: .leading)
.padding(32)
.padding(.vertical, 32)
.padding(.horizontal, UIScreen.main.isSmall ? 16 : 32)
.background(Color.black)
.cornerRadius(8)
.aspectRatio(1, contentMode: .fit)
Expand Down
17 changes: 13 additions & 4 deletions Bitkit/Components/MoneyStack.swift
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ struct MoneyStack: View {
symbol: true,
color: .textSecondary
)
.contentTransition(.numericText())
.transition(
.move(edge: .bottom)
.combined(with: .opacity)
Expand All @@ -40,6 +41,7 @@ struct MoneyStack: View {
prefix: prefix,
color: .textPrimary
)
.contentTransition(.numericText())

Spacer()

Expand All @@ -60,6 +62,7 @@ struct MoneyStack: View {
symbol: true,
color: .textSecondary
)
.contentTransition(.numericText())
.transition(
.move(edge: .bottom)
.combined(with: .opacity)
Expand All @@ -75,6 +78,7 @@ struct MoneyStack: View {
prefix: prefix,
color: .textPrimary
)
.contentTransition(.numericText())

Spacer()

Expand Down Expand Up @@ -179,15 +183,20 @@ private extension MoneyStack {
#Preview {
ScrollView {
VStack(alignment: .leading, spacing: 32) {
// With toggle enabled
MoneyStack(sats: 123_456, prefix: "+", showSymbol: false)
// Large amounts to show dramatic transitions
MoneyStack(sats: 1_234_567_890, prefix: "+", showSymbol: false)
.environmentObject(MoneyStack.previewCurrencyVM(primaryDisplay: .bitcoin, currency: "USD"))
.environmentObject(MoneyStack.previewSettingsVM())

// With symbol
MoneyStack(sats: 123_456, prefix: "-", showSymbol: true)
// With symbol and different amount
MoneyStack(sats: 987_654_321, prefix: "-", showSymbol: true)
.environmentObject(MoneyStack.previewCurrencyVM(primaryDisplay: .fiat, currency: "EUR"))
.environmentObject(MoneyStack.previewSettingsVM())

// Medium amount with eye icon
MoneyStack(sats: 456_789_123, showEyeIcon: true)
.environmentObject(MoneyStack.previewCurrencyVM(primaryDisplay: .bitcoin, currency: "USD", displayUnit: .classic))
.environmentObject(MoneyStack.previewSettingsVM(hideBalance: true))
}
.frame(maxWidth: .infinity, alignment: .leading)
.padding()
Expand Down
3 changes: 2 additions & 1 deletion Bitkit/Components/NotificationPreview.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,10 @@ struct NotificationPreview: View {

var body: some View {
HStack(alignment: .top, spacing: 8) {
Image("app-icon")
Image("app-icon-black")
.resizable()
.frame(width: 38, height: 38)
.cornerRadius(9)

VStack(alignment: .leading, spacing: 2) {
HStack {
Expand Down
2 changes: 1 addition & 1 deletion Bitkit/Components/NumberPad.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ struct NumberPad: View {
self.onPress = onPress
}

private let buttonHeight: CGFloat = 44 + 34
private let buttonHeight: CGFloat = UIScreen.main.isSmall ? 65 : 44 + 34
private let gridItems = Array(repeating: GridItem(.flexible(), spacing: 0), count: 3)
private let numbers = ["1", "2", "3", "4", "5", "6", "7", "8", "9"]

Expand Down
33 changes: 6 additions & 27 deletions Bitkit/Views/Backup/BackupConfirmMnemonic.swift
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,12 @@ struct BackupConfirmMnemonic: View {

WrappingHStack(spacing: 5) {
ForEach(0 ..< shuffledWords.count, id: \.self) { index in
WordButton(
word: shuffledWords[index],
isPressed: pressedIndices.contains(index),
onTap: {
handleWordPress(word: shuffledWords[index], index: index)
}
)
let word = shuffledWords[index]
let isPressed = pressedIndices.contains(index)

CustomButton(title: word, size: .small, background: isPressed ? Color.white32 : nil) {
handleWordPress(word: word, index: index)
}
}
}

Expand Down Expand Up @@ -118,26 +117,6 @@ struct BackupConfirmMnemonic: View {
}
}

struct WordButton: View {
let word: String
let isPressed: Bool
let onTap: () -> Void

var body: some View {
Button(action: onTap) {
Text(word)
.font(.system(size: 15, weight: .semibold))
.foregroundColor(.textPrimary)
.padding(.horizontal, 12)
.padding(.vertical, 12)
.frame(minWidth: 50)
.background(isPressed ? Color.white32 : Color.white16)
.cornerRadius(54)
}
.buttonStyle(PlainButtonStyle())
}
}

struct ConfirmWordView: View {
let number: Int
let word: String
Expand Down
9 changes: 7 additions & 2 deletions Bitkit/Views/Backup/BackupMetadata.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,13 @@ struct BackupMetadata: View {
Spacer()

// TODO: Add actual last backup time
BodySText(t("security__mnemonic_latest_backup", variables: ["time": "12/06/2025 12:00"]))
.padding(.bottom, 16)
BodySText(
tTodo("<accent>Latest full backup:</accent> {time}", variables: ["time": "12/06/2025 12:00"]),
textColor: .textPrimary,
accentColor: .textPrimary,
accentFont: Fonts.bold
)
.padding(.bottom, 16)

CustomButton(title: t("common__ok")) {
sheets.hideSheet()
Expand Down
41 changes: 21 additions & 20 deletions Bitkit/Views/Backup/BackupMnemonic.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,24 @@ struct BackupMnemonicView: View {
@State private var passphrase: String = ""
@State private var showMnemonic: Bool = false

private var text: String {
showMnemonic
? t("security__mnemonic_write", variables: ["length": "\(mnemonic.count)"])
: t("security__mnemonic_use")
}

private var note: String {
showMnemonic
? "<accent>Bitkit cannot access your funds and cannot help recover them</accent> if you lose your recovery phrase. Keep it safe!"
: "Make sure no one can see your screen. <accent>Never share your recovery phrase</accent> with anyone, as it may result in loss of funds."
}

var body: some View {
VStack(alignment: .leading, spacing: 0) {
SheetHeader(title: t("security__mnemonic_your"))

VStack(spacing: 0) {
BodyMText(t("security__mnemonic_write", variables: ["length": "\(mnemonic.count)"]))
BodyMText(text)
.frame(maxWidth: .infinity, alignment: .leading)
.padding(.bottom, 16)

Expand All @@ -35,25 +47,18 @@ struct BackupMnemonicView: View {
.frame(maxWidth: .infinity, alignment: .leading)
}
.padding(32)
.background(Color.white10)
.background(Color.gray6)
.blur(radius: showMnemonic ? 0 : 5)
.privacySensitive()

if !showMnemonic {
Button(action: {
CustomButton(
title: t("security__mnemonic_reveal"),
icon: Image("eye").resizable().frame(width: 16, height: 16)
) {
showMnemonic = true
}) {
BodySSBText(t("security__mnemonic_reveal"))
.frame(width: 154, height: 56)
.background(Color.black50)
.cornerRadius(64)
}
.shadow(
color: Color.black.opacity(0.25),
radius: 50,
x: 0,
y: 25
)
.frame(maxWidth: 180)
}
}
.cornerRadius(16)
Expand All @@ -67,23 +72,19 @@ struct BackupMnemonicView: View {
}
}

BodySText(t("security__mnemonic_never_share"), accentColor: .brandAccent)
BodySText(tTodo(note), textColor: .brandAccent, accentFont: Fonts.bold)

Spacer()

HStack(alignment: .center, spacing: 16) {
CustomButton(
title: t("common__continue"),
isDisabled: !showMnemonic
) {
CustomButton(title: t("common__continue"), isDisabled: !showMnemonic) {
let route =
passphrase.isEmpty
? BackupRoute.confirmMnemonic(mnemonic: mnemonic, passphrase: passphrase)
: BackupRoute.passphrase(mnemonic: mnemonic, passphrase: passphrase)
navigationPath.append(route)
}
}
.padding(.top, 32)
}
.padding(.horizontal, 16)
}
Expand Down
12 changes: 7 additions & 5 deletions Bitkit/Views/Backup/BackupPassphrase.swift
Original file line number Diff line number Diff line change
Expand Up @@ -25,21 +25,23 @@ struct BackupPassphrase: View {
}
.padding(32)
.frame(maxHeight: .infinity)
.background(Color.white10)
.background(Color.gray6)
.cornerRadius(16)
.padding(.top, 16)
.padding(.bottom, 32)
.privacySensitive()
.frame(maxWidth: .infinity)

BodySText(t("security__pass_never_share"), accentColor: .brandAccent)
BodySText(
tTodo("<accent>Never share your passphrase</accent> with anyone, as it may result in loss of funds. Keep it secret!"),
accentColor: .brandAccent,
accentFont: Fonts.bold
)

Spacer()

HStack(alignment: .center, spacing: 16) {
CustomButton(
title: t("common__continue")
) {
CustomButton(title: t("common__continue")) {
navigationPath.append(.confirmMnemonic(mnemonic: mnemonic, passphrase: passphrase))
}
}
Expand Down
Loading
Loading