fix: replace generic icon with beacon-specific icon and match Android color scheme
- App icon now uses white bg + PAYFRIT text + bluetooth beacon icon (matches Android) - AccentColor set to Payfrit Green (#22B24B) - Added BrandColors.swift with full Android color palette parity - All views updated: payfritGreen replaces .blue, proper status colors throughout - Signal strength, beacon type badges, QR scanner corners all use brand colors - DevBanner uses warningOrange matching Android's #FF9800 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
2496cab7f3
commit
8ecd533429
11 changed files with 105 additions and 22 deletions
|
|
@ -27,6 +27,7 @@
|
||||||
A01000000040 /* BeaconBanList.swift in Sources */ = {isa = PBXBuildFile; fileRef = A02000000040 /* BeaconBanList.swift */; };
|
A01000000040 /* BeaconBanList.swift in Sources */ = {isa = PBXBuildFile; fileRef = A02000000040 /* BeaconBanList.swift */; };
|
||||||
A01000000041 /* BeaconShardPool.swift in Sources */ = {isa = PBXBuildFile; fileRef = A02000000041 /* BeaconShardPool.swift */; };
|
A01000000041 /* BeaconShardPool.swift in Sources */ = {isa = PBXBuildFile; fileRef = A02000000041 /* BeaconShardPool.swift */; };
|
||||||
A01000000042 /* UUIDFormatting.swift in Sources */ = {isa = PBXBuildFile; fileRef = A02000000042 /* UUIDFormatting.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 */; };
|
A01000000050 /* BusinessListView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A02000000050 /* BusinessListView.swift */; };
|
||||||
A01000000051 /* DevBanner.swift in Sources */ = {isa = PBXBuildFile; fileRef = A02000000051 /* DevBanner.swift */; };
|
A01000000051 /* DevBanner.swift in Sources */ = {isa = PBXBuildFile; fileRef = A02000000051 /* DevBanner.swift */; };
|
||||||
A01000000052 /* LoginView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A02000000052 /* LoginView.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 = "<group>"; };
|
A02000000032 /* BLEManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BLEManager.swift; sourceTree = "<group>"; };
|
||||||
A02000000033 /* SecureStorage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecureStorage.swift; sourceTree = "<group>"; };
|
A02000000033 /* SecureStorage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecureStorage.swift; sourceTree = "<group>"; };
|
||||||
A02000000040 /* BeaconBanList.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BeaconBanList.swift; sourceTree = "<group>"; };
|
A02000000040 /* BeaconBanList.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BeaconBanList.swift; sourceTree = "<group>"; };
|
||||||
|
A02000000043 /* BrandColors.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BrandColors.swift; sourceTree = "<group>"; };
|
||||||
A02000000041 /* BeaconShardPool.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BeaconShardPool.swift; sourceTree = "<group>"; };
|
A02000000041 /* BeaconShardPool.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BeaconShardPool.swift; sourceTree = "<group>"; };
|
||||||
A02000000042 /* UUIDFormatting.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UUIDFormatting.swift; sourceTree = "<group>"; };
|
A02000000042 /* UUIDFormatting.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UUIDFormatting.swift; sourceTree = "<group>"; };
|
||||||
A02000000050 /* BusinessListView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BusinessListView.swift; sourceTree = "<group>"; };
|
A02000000050 /* BusinessListView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BusinessListView.swift; sourceTree = "<group>"; };
|
||||||
|
|
@ -167,6 +169,7 @@
|
||||||
A02000000040 /* BeaconBanList.swift */,
|
A02000000040 /* BeaconBanList.swift */,
|
||||||
A02000000041 /* BeaconShardPool.swift */,
|
A02000000041 /* BeaconShardPool.swift */,
|
||||||
A02000000042 /* UUIDFormatting.swift */,
|
A02000000042 /* UUIDFormatting.swift */,
|
||||||
|
A02000000043 /* BrandColors.swift */,
|
||||||
);
|
);
|
||||||
path = Utils;
|
path = Utils;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
|
|
@ -276,6 +279,7 @@
|
||||||
A01000000040 /* BeaconBanList.swift in Sources */,
|
A01000000040 /* BeaconBanList.swift in Sources */,
|
||||||
A01000000041 /* BeaconShardPool.swift in Sources */,
|
A01000000041 /* BeaconShardPool.swift in Sources */,
|
||||||
A01000000042 /* UUIDFormatting.swift in Sources */,
|
A01000000042 /* UUIDFormatting.swift in Sources */,
|
||||||
|
A01000000043 /* BrandColors.swift in Sources */,
|
||||||
A01000000050 /* BusinessListView.swift in Sources */,
|
A01000000050 /* BusinessListView.swift in Sources */,
|
||||||
A01000000051 /* DevBanner.swift in Sources */,
|
A01000000051 /* DevBanner.swift in Sources */,
|
||||||
A01000000052 /* LoginView.swift in Sources */,
|
A01000000052 /* LoginView.swift in Sources */,
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,15 @@
|
||||||
{
|
{
|
||||||
"colors" : [
|
"colors" : [
|
||||||
{
|
{
|
||||||
|
"color" : {
|
||||||
|
"color-space" : "srgb",
|
||||||
|
"components" : {
|
||||||
|
"alpha" : "1.000",
|
||||||
|
"blue" : "0.294",
|
||||||
|
"green" : "0.698",
|
||||||
|
"red" : "0.133"
|
||||||
|
}
|
||||||
|
},
|
||||||
"idiom" : "universal"
|
"idiom" : "universal"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
|
|
||||||
Binary file not shown.
|
Before Width: | Height: | Size: 26 KiB After Width: | Height: | Size: 113 KiB |
|
|
@ -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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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
|
||||||
|
}
|
||||||
|
}
|
||||||
30
PayfritBeacon/Utils/BrandColors.swift
Normal file
30
PayfritBeacon/Utils/BrandColors.swift
Normal file
|
|
@ -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)
|
||||||
|
}
|
||||||
|
|
@ -26,7 +26,7 @@ struct BusinessListView: View {
|
||||||
VStack(spacing: 12) {
|
VStack(spacing: 12) {
|
||||||
Image(systemName: "exclamationmark.triangle")
|
Image(systemName: "exclamationmark.triangle")
|
||||||
.font(.system(size: 48))
|
.font(.system(size: 48))
|
||||||
.foregroundStyle(.orange)
|
.foregroundStyle(.warningOrange)
|
||||||
Text("Error")
|
Text("Error")
|
||||||
.font(.headline)
|
.font(.headline)
|
||||||
Text(error)
|
Text(error)
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ struct DevBanner: View {
|
||||||
.foregroundStyle(.white)
|
.foregroundStyle(.white)
|
||||||
.padding(.horizontal, 12)
|
.padding(.horizontal, 12)
|
||||||
.padding(.vertical, 4)
|
.padding(.vertical, 4)
|
||||||
.background(.orange, in: Capsule())
|
.background(.warningOrange, in: Capsule())
|
||||||
.padding(.top, 4)
|
.padding(.top, 4)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@ struct LoginView: View {
|
||||||
// Logo
|
// Logo
|
||||||
Image(systemName: "antenna.radiowaves.left.and.right")
|
Image(systemName: "antenna.radiowaves.left.and.right")
|
||||||
.font(.system(size: 64))
|
.font(.system(size: 64))
|
||||||
.foregroundStyle(.blue)
|
.foregroundStyle(.payfritGreen)
|
||||||
|
|
||||||
Text("Payfrit Beacon")
|
Text("Payfrit Beacon")
|
||||||
.font(.title.bold())
|
.font(.title.bold())
|
||||||
|
|
@ -49,7 +49,7 @@ struct LoginView: View {
|
||||||
if let error = errorMessage {
|
if let error = errorMessage {
|
||||||
Text(error)
|
Text(error)
|
||||||
.font(.caption)
|
.font(.caption)
|
||||||
.foregroundStyle(.red)
|
.foregroundStyle(.errorRed)
|
||||||
}
|
}
|
||||||
|
|
||||||
Button(action: handleAction) {
|
Button(action: handleAction) {
|
||||||
|
|
|
||||||
|
|
@ -101,7 +101,7 @@ struct QRScannerView: View {
|
||||||
p.addLine(to: CGPoint(x: 0, y: 0))
|
p.addLine(to: CGPoint(x: 0, y: 0))
|
||||||
p.addLine(to: CGPoint(x: corner, y: 0))
|
p.addLine(to: CGPoint(x: corner, y: 0))
|
||||||
}
|
}
|
||||||
.stroke(.blue, lineWidth: thickness)
|
.stroke(.payfritGreen, lineWidth: thickness)
|
||||||
|
|
||||||
// Top-right
|
// Top-right
|
||||||
Path { p in
|
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: 0))
|
||||||
p.addLine(to: CGPoint(x: w, y: corner))
|
p.addLine(to: CGPoint(x: w, y: corner))
|
||||||
}
|
}
|
||||||
.stroke(.blue, lineWidth: thickness)
|
.stroke(.payfritGreen, lineWidth: thickness)
|
||||||
|
|
||||||
// Bottom-left
|
// Bottom-left
|
||||||
Path { p in
|
Path { p in
|
||||||
|
|
@ -117,7 +117,7 @@ struct QRScannerView: View {
|
||||||
p.addLine(to: CGPoint(x: 0, y: h))
|
p.addLine(to: CGPoint(x: 0, y: h))
|
||||||
p.addLine(to: CGPoint(x: corner, y: h))
|
p.addLine(to: CGPoint(x: corner, y: h))
|
||||||
}
|
}
|
||||||
.stroke(.blue, lineWidth: thickness)
|
.stroke(.payfritGreen, lineWidth: thickness)
|
||||||
|
|
||||||
// Bottom-right
|
// Bottom-right
|
||||||
Path { p in
|
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))
|
||||||
p.addLine(to: CGPoint(x: w, y: h - corner))
|
p.addLine(to: CGPoint(x: w, y: h - corner))
|
||||||
}
|
}
|
||||||
.stroke(.blue, lineWidth: thickness)
|
.stroke(.payfritGreen, lineWidth: thickness)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -116,7 +116,7 @@ struct ScanView: View {
|
||||||
.padding(.horizontal, 14)
|
.padding(.horizontal, 14)
|
||||||
.padding(.vertical, 8)
|
.padding(.vertical, 8)
|
||||||
.background(
|
.background(
|
||||||
selectedServicePoint?.id == sp.id ? Color.blue : Color(.systemGray5),
|
selectedServicePoint?.id == sp.id ? Color.payfritGreen : Color(.systemGray5),
|
||||||
in: Capsule()
|
in: Capsule()
|
||||||
)
|
)
|
||||||
.foregroundStyle(selectedServicePoint?.id == sp.id ? .white : .primary)
|
.foregroundStyle(selectedServicePoint?.id == sp.id ? .white : .primary)
|
||||||
|
|
@ -174,7 +174,7 @@ struct ScanView: View {
|
||||||
VStack(spacing: 12) {
|
VStack(spacing: 12) {
|
||||||
Image(systemName: "exclamationmark.triangle")
|
Image(systemName: "exclamationmark.triangle")
|
||||||
.font(.system(size: 48))
|
.font(.system(size: 48))
|
||||||
.foregroundStyle(.orange)
|
.foregroundStyle(.warningOrange)
|
||||||
Text("Namespace Error")
|
Text("Namespace Error")
|
||||||
.font(.headline)
|
.font(.headline)
|
||||||
Text(errorMessage ?? "Failed to allocate beacon namespace")
|
Text(errorMessage ?? "Failed to allocate beacon namespace")
|
||||||
|
|
@ -240,7 +240,7 @@ struct ScanView: View {
|
||||||
if bleManager.bluetoothState != .poweredOn {
|
if bleManager.bluetoothState != .poweredOn {
|
||||||
Label("Bluetooth Off", systemImage: "bluetooth.slash")
|
Label("Bluetooth Off", systemImage: "bluetooth.slash")
|
||||||
.font(.caption)
|
.font(.caption)
|
||||||
.foregroundStyle(.red)
|
.foregroundStyle(.errorRed)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.padding(.horizontal)
|
.padding(.horizontal)
|
||||||
|
|
@ -323,7 +323,7 @@ struct ScanView: View {
|
||||||
|
|
||||||
Image(systemName: "light.beacon.max")
|
Image(systemName: "light.beacon.max")
|
||||||
.font(.system(size: 64))
|
.font(.system(size: 64))
|
||||||
.foregroundStyle(.orange)
|
.foregroundStyle(.payfritGreen)
|
||||||
.modifier(PulseEffectModifier())
|
.modifier(PulseEffectModifier())
|
||||||
|
|
||||||
Text("Beacon is Flashing")
|
Text("Beacon is Flashing")
|
||||||
|
|
@ -345,7 +345,7 @@ struct ScanView: View {
|
||||||
.frame(maxWidth: .infinity)
|
.frame(maxWidth: .infinity)
|
||||||
}
|
}
|
||||||
.buttonStyle(.borderedProminent)
|
.buttonStyle(.borderedProminent)
|
||||||
.tint(.orange)
|
.tint(.payfritGreen)
|
||||||
.controlSize(.large)
|
.controlSize(.large)
|
||||||
.padding(.horizontal, 32)
|
.padding(.horizontal, 32)
|
||||||
|
|
||||||
|
|
@ -379,7 +379,7 @@ struct ScanView: View {
|
||||||
Spacer()
|
Spacer()
|
||||||
Image(systemName: "checkmark.circle.fill")
|
Image(systemName: "checkmark.circle.fill")
|
||||||
.font(.system(size: 64))
|
.font(.system(size: 64))
|
||||||
.foregroundStyle(.green)
|
.foregroundStyle(.successGreen)
|
||||||
Text("Beacon Provisioned!")
|
Text("Beacon Provisioned!")
|
||||||
.font(.title2.bold())
|
.font(.title2.bold())
|
||||||
Text(statusMessage)
|
Text(statusMessage)
|
||||||
|
|
@ -400,7 +400,7 @@ struct ScanView: View {
|
||||||
Spacer()
|
Spacer()
|
||||||
Image(systemName: "xmark.circle.fill")
|
Image(systemName: "xmark.circle.fill")
|
||||||
.font(.system(size: 64))
|
.font(.system(size: 64))
|
||||||
.foregroundStyle(.red)
|
.foregroundStyle(.errorRed)
|
||||||
Text("Provisioning Failed")
|
Text("Provisioning Failed")
|
||||||
.font(.title2.bold())
|
.font(.title2.bold())
|
||||||
Text(errorMessage ?? "Unknown error")
|
Text(errorMessage ?? "Unknown error")
|
||||||
|
|
@ -801,18 +801,18 @@ struct BeaconRow: View {
|
||||||
|
|
||||||
private var signalColor: Color {
|
private var signalColor: Color {
|
||||||
switch beacon.rssi {
|
switch beacon.rssi {
|
||||||
case -50...0: return .green
|
case -50...0: return .signalStrong
|
||||||
case -65 ... -51: return .blue
|
case -65 ... -51: return .payfritGreen
|
||||||
case -80 ... -66: return .orange
|
case -80 ... -66: return .signalMedium
|
||||||
default: return .red
|
default: return .signalWeak
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private var typeColor: Color {
|
private var typeColor: Color {
|
||||||
switch beacon.type {
|
switch beacon.type {
|
||||||
case .kbeacon: return .blue
|
case .kbeacon: return .payfritGreen
|
||||||
case .dxsmart: return .orange
|
case .dxsmart: return .warningOrange
|
||||||
case .bluecharm: return .purple
|
case .bluecharm: return .infoBlue
|
||||||
case .unknown: return .gray
|
case .unknown: return .gray
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue