diff --git a/PayfritBeacon.xcodeproj/project.pbxproj b/PayfritBeacon.xcodeproj/project.pbxproj index eb179de..1600d9b 100644 --- a/PayfritBeacon.xcodeproj/project.pbxproj +++ b/PayfritBeacon.xcodeproj/project.pbxproj @@ -27,6 +27,7 @@ A01000000040 /* BeaconBanList.swift in Sources */ = {isa = PBXBuildFile; fileRef = A02000000040 /* BeaconBanList.swift */; }; A01000000041 /* BeaconShardPool.swift in Sources */ = {isa = PBXBuildFile; fileRef = A02000000041 /* BeaconShardPool.swift */; }; A01000000042 /* UUIDFormatting.swift in Sources */ = {isa = PBXBuildFile; fileRef = A02000000042 /* UUIDFormatting.swift */; }; + A01000000043 /* BrandColors.swift in Sources */ = {isa = PBXBuildFile; fileRef = A02000000043 /* BrandColors.swift */; }; A01000000050 /* BusinessListView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A02000000050 /* BusinessListView.swift */; }; A01000000051 /* DevBanner.swift in Sources */ = {isa = PBXBuildFile; fileRef = A02000000051 /* DevBanner.swift */; }; A01000000052 /* LoginView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A02000000052 /* LoginView.swift */; }; @@ -57,6 +58,7 @@ A02000000032 /* BLEManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BLEManager.swift; sourceTree = ""; }; A02000000033 /* SecureStorage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecureStorage.swift; sourceTree = ""; }; A02000000040 /* BeaconBanList.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BeaconBanList.swift; sourceTree = ""; }; + A02000000043 /* BrandColors.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BrandColors.swift; sourceTree = ""; }; A02000000041 /* BeaconShardPool.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BeaconShardPool.swift; sourceTree = ""; }; A02000000042 /* UUIDFormatting.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UUIDFormatting.swift; sourceTree = ""; }; A02000000050 /* BusinessListView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BusinessListView.swift; sourceTree = ""; }; @@ -167,6 +169,7 @@ A02000000040 /* BeaconBanList.swift */, A02000000041 /* BeaconShardPool.swift */, A02000000042 /* UUIDFormatting.swift */, + A02000000043 /* BrandColors.swift */, ); path = Utils; sourceTree = ""; @@ -276,6 +279,7 @@ A01000000040 /* BeaconBanList.swift in Sources */, A01000000041 /* BeaconShardPool.swift in Sources */, A01000000042 /* UUIDFormatting.swift in Sources */, + A01000000043 /* BrandColors.swift in Sources */, A01000000050 /* BusinessListView.swift in Sources */, A01000000051 /* DevBanner.swift in Sources */, A01000000052 /* LoginView.swift in Sources */, diff --git a/PayfritBeacon/Assets.xcassets/AccentColor.colorset/Contents.json b/PayfritBeacon/Assets.xcassets/AccentColor.colorset/Contents.json index eb87897..650bdd4 100644 --- a/PayfritBeacon/Assets.xcassets/AccentColor.colorset/Contents.json +++ b/PayfritBeacon/Assets.xcassets/AccentColor.colorset/Contents.json @@ -1,6 +1,15 @@ { "colors" : [ { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0.294", + "green" : "0.698", + "red" : "0.133" + } + }, "idiom" : "universal" } ], diff --git a/PayfritBeacon/Assets.xcassets/AppIcon.appiconset/AppIcon.png b/PayfritBeacon/Assets.xcassets/AppIcon.appiconset/AppIcon.png index 9d45a48..23a0f4f 100644 Binary files a/PayfritBeacon/Assets.xcassets/AppIcon.appiconset/AppIcon.png and b/PayfritBeacon/Assets.xcassets/AppIcon.appiconset/AppIcon.png differ diff --git a/PayfritBeacon/Assets.xcassets/PayfritGreen.colorset/Contents.json b/PayfritBeacon/Assets.xcassets/PayfritGreen.colorset/Contents.json new file mode 100644 index 0000000..3e87133 --- /dev/null +++ b/PayfritBeacon/Assets.xcassets/PayfritGreen.colorset/Contents.json @@ -0,0 +1,20 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0x4B", + "green" : "0xB2", + "red" : "0x22" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/PayfritBeacon/Assets.xcassets/PayfritGreenDark.colorset/Contents.json b/PayfritBeacon/Assets.xcassets/PayfritGreenDark.colorset/Contents.json new file mode 100644 index 0000000..feee4c1 --- /dev/null +++ b/PayfritBeacon/Assets.xcassets/PayfritGreenDark.colorset/Contents.json @@ -0,0 +1,20 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0x3A", + "green" : "0x8A", + "red" : "0x1A" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/PayfritBeacon/Utils/BrandColors.swift b/PayfritBeacon/Utils/BrandColors.swift new file mode 100644 index 0000000..35067bf --- /dev/null +++ b/PayfritBeacon/Utils/BrandColors.swift @@ -0,0 +1,30 @@ +import SwiftUI + +/// Payfrit brand colors — matches Android colors.xml exactly +/// Primary: #22B24B (Payfrit Green) +/// Dark: #1A8A3A +extension Color { + // MARK: - Brand + static let payfritGreen = Color(red: 0x22/255.0, green: 0xB2/255.0, blue: 0x4B/255.0) + static let payfritGreenDark = Color(red: 0x1A/255.0, green: 0x8A/255.0, blue: 0x3A/255.0) + + // MARK: - Status (matching Android) + static let successGreen = Color(red: 0x4C/255.0, green: 0xAF/255.0, blue: 0x50/255.0) + static let errorRed = Color(red: 0xBA/255.0, green: 0x1A/255.0, blue: 0x1A/255.0) + static let warningOrange = Color(red: 0xFF/255.0, green: 0x98/255.0, blue: 0x00/255.0) + static let infoBlue = Color(red: 0x21/255.0, green: 0x96/255.0, blue: 0xF3/255.0) + + // MARK: - Signal Strength (matching Android) + static let signalStrong = Color(red: 0x4C/255.0, green: 0xAF/255.0, blue: 0x50/255.0) + static let signalMedium = Color(red: 0xF9/255.0, green: 0xA8/255.0, blue: 0x25/255.0) + static let signalWeak = Color(red: 0xBA/255.0, green: 0x1A/255.0, blue: 0x1A/255.0) + + // MARK: - Surfaces (matching Android) + static let surfaceBg = Color(red: 0xFC/255.0, green: 0xFD/255.0, blue: 0xF7/255.0) + static let surfaceCard = Color(red: 0xF0/255.0, green: 0xF1/255.0, blue: 0xEB/255.0) + + // MARK: - Text (matching Android) + static let textPrimary = Color(red: 0x1A/255.0, green: 0x1C/255.0, blue: 0x19/255.0) + static let textSecondary = Color(red: 0x42/255.0, green: 0x49/255.0, blue: 0x40/255.0) + static let textHint = Color(red: 0x72/255.0, green: 0x79/255.0, blue: 0x70/255.0) +} diff --git a/PayfritBeacon/Views/BusinessListView.swift b/PayfritBeacon/Views/BusinessListView.swift index 0d4370a..fab8cda 100644 --- a/PayfritBeacon/Views/BusinessListView.swift +++ b/PayfritBeacon/Views/BusinessListView.swift @@ -26,7 +26,7 @@ struct BusinessListView: View { VStack(spacing: 12) { Image(systemName: "exclamationmark.triangle") .font(.system(size: 48)) - .foregroundStyle(.orange) + .foregroundStyle(.warningOrange) Text("Error") .font(.headline) Text(error) diff --git a/PayfritBeacon/Views/DevBanner.swift b/PayfritBeacon/Views/DevBanner.swift index 41f970f..2634a09 100644 --- a/PayfritBeacon/Views/DevBanner.swift +++ b/PayfritBeacon/Views/DevBanner.swift @@ -8,7 +8,7 @@ struct DevBanner: View { .foregroundStyle(.white) .padding(.horizontal, 12) .padding(.vertical, 4) - .background(.orange, in: Capsule()) + .background(.warningOrange, in: Capsule()) .padding(.top, 4) } } diff --git a/PayfritBeacon/Views/LoginView.swift b/PayfritBeacon/Views/LoginView.swift index c24f5f9..b254f83 100644 --- a/PayfritBeacon/Views/LoginView.swift +++ b/PayfritBeacon/Views/LoginView.swift @@ -20,7 +20,7 @@ struct LoginView: View { // Logo Image(systemName: "antenna.radiowaves.left.and.right") .font(.system(size: 64)) - .foregroundStyle(.blue) + .foregroundStyle(.payfritGreen) Text("Payfrit Beacon") .font(.title.bold()) @@ -49,7 +49,7 @@ struct LoginView: View { if let error = errorMessage { Text(error) .font(.caption) - .foregroundStyle(.red) + .foregroundStyle(.errorRed) } Button(action: handleAction) { diff --git a/PayfritBeacon/Views/QRScannerView.swift b/PayfritBeacon/Views/QRScannerView.swift index e33158e..8c6434b 100644 --- a/PayfritBeacon/Views/QRScannerView.swift +++ b/PayfritBeacon/Views/QRScannerView.swift @@ -101,7 +101,7 @@ struct QRScannerView: View { p.addLine(to: CGPoint(x: 0, y: 0)) p.addLine(to: CGPoint(x: corner, y: 0)) } - .stroke(.blue, lineWidth: thickness) + .stroke(.payfritGreen, lineWidth: thickness) // Top-right Path { p in @@ -109,7 +109,7 @@ struct QRScannerView: View { p.addLine(to: CGPoint(x: w, y: 0)) p.addLine(to: CGPoint(x: w, y: corner)) } - .stroke(.blue, lineWidth: thickness) + .stroke(.payfritGreen, lineWidth: thickness) // Bottom-left Path { p in @@ -117,7 +117,7 @@ struct QRScannerView: View { p.addLine(to: CGPoint(x: 0, y: h)) p.addLine(to: CGPoint(x: corner, y: h)) } - .stroke(.blue, lineWidth: thickness) + .stroke(.payfritGreen, lineWidth: thickness) // Bottom-right Path { p in @@ -125,7 +125,7 @@ struct QRScannerView: View { p.addLine(to: CGPoint(x: w, y: h)) p.addLine(to: CGPoint(x: w, y: h - corner)) } - .stroke(.blue, lineWidth: thickness) + .stroke(.payfritGreen, lineWidth: thickness) } } diff --git a/PayfritBeacon/Views/ScanView.swift b/PayfritBeacon/Views/ScanView.swift index 61b9062..94d77af 100644 --- a/PayfritBeacon/Views/ScanView.swift +++ b/PayfritBeacon/Views/ScanView.swift @@ -116,7 +116,7 @@ struct ScanView: View { .padding(.horizontal, 14) .padding(.vertical, 8) .background( - selectedServicePoint?.id == sp.id ? Color.blue : Color(.systemGray5), + selectedServicePoint?.id == sp.id ? Color.payfritGreen : Color(.systemGray5), in: Capsule() ) .foregroundStyle(selectedServicePoint?.id == sp.id ? .white : .primary) @@ -174,7 +174,7 @@ struct ScanView: View { VStack(spacing: 12) { Image(systemName: "exclamationmark.triangle") .font(.system(size: 48)) - .foregroundStyle(.orange) + .foregroundStyle(.warningOrange) Text("Namespace Error") .font(.headline) Text(errorMessage ?? "Failed to allocate beacon namespace") @@ -240,7 +240,7 @@ struct ScanView: View { if bleManager.bluetoothState != .poweredOn { Label("Bluetooth Off", systemImage: "bluetooth.slash") .font(.caption) - .foregroundStyle(.red) + .foregroundStyle(.errorRed) } } .padding(.horizontal) @@ -323,7 +323,7 @@ struct ScanView: View { Image(systemName: "light.beacon.max") .font(.system(size: 64)) - .foregroundStyle(.orange) + .foregroundStyle(.payfritGreen) .modifier(PulseEffectModifier()) Text("Beacon is Flashing") @@ -345,7 +345,7 @@ struct ScanView: View { .frame(maxWidth: .infinity) } .buttonStyle(.borderedProminent) - .tint(.orange) + .tint(.payfritGreen) .controlSize(.large) .padding(.horizontal, 32) @@ -379,7 +379,7 @@ struct ScanView: View { Spacer() Image(systemName: "checkmark.circle.fill") .font(.system(size: 64)) - .foregroundStyle(.green) + .foregroundStyle(.successGreen) Text("Beacon Provisioned!") .font(.title2.bold()) Text(statusMessage) @@ -400,7 +400,7 @@ struct ScanView: View { Spacer() Image(systemName: "xmark.circle.fill") .font(.system(size: 64)) - .foregroundStyle(.red) + .foregroundStyle(.errorRed) Text("Provisioning Failed") .font(.title2.bold()) Text(errorMessage ?? "Unknown error") @@ -801,18 +801,18 @@ struct BeaconRow: View { private var signalColor: Color { switch beacon.rssi { - case -50...0: return .green - case -65 ... -51: return .blue - case -80 ... -66: return .orange - default: return .red + case -50...0: return .signalStrong + case -65 ... -51: return .payfritGreen + case -80 ... -66: return .signalMedium + default: return .signalWeak } } private var typeColor: Color { switch beacon.type { - case .kbeacon: return .blue - case .dxsmart: return .orange - case .bluecharm: return .purple + case .kbeacon: return .payfritGreen + case .dxsmart: return .warningOrange + case .bluecharm: return .infoBlue case .unknown: return .gray } }