Skip to content
This repository was archived by the owner on Mar 7, 2026. It is now read-only.

Commit f82a032

Browse files
authored
UI improvements
1 parent 7d3c8a4 commit f82a032

3 files changed

Lines changed: 276 additions & 101 deletions

File tree

Sources/prostore/views/AboutView.swift

Lines changed: 84 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -39,56 +39,74 @@ struct AboutView: View {
3939
}
4040

4141
var body: some View {
42-
List {
43-
VStack(spacing: 8) {
44-
if let url = appIconURL {
45-
AsyncImage(url: url) { phase in
46-
if let img = phase.image {
47-
img
48-
.resizable()
49-
.scaledToFit()
50-
.frame(width: 120, height: 120)
51-
.clipShape(RoundedRectangle(cornerRadius: 20, style: .continuous))
52-
.shadow(radius: 6)
53-
} else if phase.error != nil {
54-
Image(systemName: "app.fill")
55-
.resizable()
56-
.scaledToFit()
57-
.frame(width: 80, height: 80)
58-
.foregroundColor(.secondary)
59-
} else {
60-
ProgressView()
61-
.frame(width: 80, height: 80)
42+
NavigationView {
43+
List {
44+
VStack(spacing: 12) {
45+
if let url = appIconURL {
46+
AsyncImage(url: url) { phase in
47+
if let img = phase.image {
48+
img
49+
.resizable()
50+
.scaledToFit()
51+
.frame(width: 120, height: 120)
52+
.clipShape(RoundedRectangle(cornerRadius: 24, style: .continuous))
53+
.shadow(color: Color.black.opacity(0.2), radius: 6, x: 0, y: 2)
54+
.background(
55+
RoundedRectangle(cornerRadius: 24, style: .continuous)
56+
.fill(Color.blue.opacity(0.1)) // Subtle background
57+
)
58+
.padding(4)
59+
} else if phase.error != nil {
60+
Image(systemName: "app.fill")
61+
.resizable()
62+
.scaledToFit()
63+
.frame(width: 80, height: 80)
64+
.foregroundColor(.blue.opacity(0.6)) // Tinted fallback
65+
} else {
66+
ProgressView()
67+
.tint(.blue) // Tinted spinner
68+
.frame(width: 80, height: 80)
69+
}
6270
}
71+
.animation(.easeIn(duration: 0.3), value: url) // Fade-in animation
6372
}
64-
}
6573

66-
Text("ProStore")
67-
.font(.title2)
68-
.fontWeight(.semibold)
74+
Text("ProStore")
75+
.font(.title2)
76+
.fontWeight(.bold) // Bolder for emphasis
77+
.foregroundColor(.primary)
6978

70-
Text("Version \(versionString)")
71-
.font(.footnote)
72-
.foregroundColor(.secondary)
73-
}
74-
.frame(maxWidth: .infinity)
75-
.padding(.vertical, 20)
76-
.listRowInsets(EdgeInsets())
79+
Text("Version \(versionString)")
80+
.font(.footnote)
81+
.foregroundColor(.secondary)
82+
}
83+
.frame(maxWidth: .infinity)
84+
.padding(.vertical, 24) // More spacing
85+
.listRowInsets(EdgeInsets())
86+
.background(Color.blue.opacity(0.05)) // Subtle list row background
7787

78-
Section(header: Text("Credits")) {
79-
ForEach(credits) { c in
80-
CreditRow(credit: c)
88+
Section(header: Text("Credits")
89+
.font(.headline)
90+
.foregroundColor(.primary)
91+
.padding(.top, 8)) {
92+
ForEach(credits) { c in
93+
CreditRow(credit: c)
94+
}
8195
}
8296
}
97+
.listStyle(.insetGrouped)
98+
.background(Color(UIColor.systemBackground)) // Clean background
99+
.navigationTitle("About ProStore")
100+
.navigationBarTitleDisplayMode(.inline)
101+
.accentColor(.blue) // Consistent blue accent
83102
}
84-
.listStyle(InsetGroupedListStyle())
85-
.navigationTitle("About")
86103
}
87104
}
88105

89106
struct CreditRow: View {
90107
let credit: Credit
91108
@Environment(\.openURL) var openURL
109+
@State private var isTapped = false // For button animation
92110

93111
var body: some View {
94112
HStack(spacing: 12) {
@@ -97,21 +115,31 @@ struct CreditRow: View {
97115
img
98116
.resizable()
99117
.scaledToFill()
118+
.frame(width: 48, height: 48)
119+
.clipShape(Circle())
120+
.overlay(
121+
Circle()
122+
.stroke(Color.blue.opacity(0.3), lineWidth: 1) // Modern border
123+
)
100124
} else if phase.error != nil {
101125
Image(systemName: "person.crop.circle.fill")
102126
.resizable()
103127
.scaledToFill()
128+
.frame(width: 48, height: 48)
129+
.foregroundColor(.blue.opacity(0.6)) // Tinted fallback
104130
} else {
105131
ProgressView()
132+
.tint(.blue) // Tinted spinner
133+
.frame(width: 48, height: 48)
106134
}
107135
}
108-
.frame(width: 44, height: 44)
109-
.clipShape(Circle())
110-
.overlay(Circle().stroke(Color(UIColor.separator), lineWidth: 0.5))
136+
.animation(.easeIn(duration: 0.3), value: credit.avatarURL) // Fade-in animation
111137

112-
VStack(alignment: .leading, spacing: 2) {
138+
VStack(alignment: .leading, spacing: 4) {
113139
Text(credit.name)
114140
.font(.body)
141+
.fontWeight(.medium)
142+
.foregroundColor(.primary)
115143
Text(credit.role)
116144
.font(.subheadline)
117145
.foregroundColor(.secondary)
@@ -120,14 +148,29 @@ struct CreditRow: View {
120148
Spacer()
121149

122150
Button {
151+
isTapped = true
123152
openURL(credit.profileURL)
153+
DispatchQueue.main.asyncAfter(deadline: .now() + 0.2) {
154+
isTapped = false
155+
}
124156
} label: {
125157
Image(systemName: "arrow.up.right.square")
126158
.imageScale(.large)
127-
.foregroundColor(.accentColor)
159+
.foregroundColor(.blue)
160+
.padding(8)
161+
.background(Color.blue.opacity(0.1)) // Subtle button background
162+
.clipShape(Circle())
163+
.scaleEffect(isTapped ? 0.9 : 1.0) // Tap animation
128164
}
129165
.buttonStyle(BorderlessButtonStyle())
166+
.animation(.easeInOut(duration: 0.2), value: isTapped) // Smooth tap animation
130167
}
131168
.padding(.vertical, 8)
169+
.padding(.horizontal, 8)
170+
.background(
171+
RoundedRectangle(cornerRadius: 12)
172+
.fill(Color.blue.opacity(0.05)) // Subtle row background
173+
)
174+
.padding(.horizontal, 4)
132175
}
133176
}

Sources/prostore/views/CertificateView.swift

Lines changed: 85 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,3 @@
1-
// views/CertificateView.swift
2-
// Put this file under views/ in your project
3-
41
import SwiftUI
52
import UniformTypeIdentifiers
63

@@ -13,43 +10,101 @@ struct CertificateView: View {
1310
@State private var showPickerFor: PickerKind? = nil
1411

1512
var body: some View {
16-
Form {
17-
Section(header: Text("Inputs")) {
18-
HStack {
19-
Text("P12:")
20-
Spacer()
21-
Text(p12.name.isEmpty ? "" : p12.name).foregroundColor(.secondary)
22-
Button("Pick") {
23-
showPickerFor = .p12
13+
NavigationView {
14+
Form {
15+
Section(header: Text("Inputs")
16+
.font(.headline) // Bolder, larger header
17+
.foregroundColor(.primary)
18+
.padding(.top, 8)) {
19+
// P12 picker with icon and truncated file name
20+
HStack {
21+
Image(systemName: "lock.doc.fill") // Added SF Symbol
22+
.foregroundColor(.blue)
23+
Text("P12")
24+
Spacer()
25+
Text(p12.name.isEmpty ? "No file selected" : p12.name)
26+
.font(.caption) // Smaller font for file name
27+
.lineLimit(1) // Truncate long names
28+
.foregroundColor(.secondary)
29+
Button(action: { showPickerFor = .p12 }) {
30+
Text("Pick")
31+
.padding(.horizontal, 8)
32+
.padding(.vertical, 4)
33+
.background(Color.blue.opacity(0.1)) // Subtle button background
34+
.cornerRadius(8)
35+
}
36+
}
37+
.padding(.vertical, 4) // More spacing
38+
39+
// MobileProvision picker with icon
40+
HStack {
41+
Image(systemName: "gearshape.fill")
42+
.foregroundColor(.blue)
43+
Text("MobileProvision")
44+
Spacer()
45+
Text(prov.name.isEmpty ? "No file selected" : prov.name)
46+
.font(.caption)
47+
.lineLimit(1)
48+
.foregroundColor(.secondary)
49+
Button(action: { showPickerFor = .prov }) {
50+
Text("Pick")
51+
.padding(.horizontal, 8)
52+
.padding(.vertical, 4)
53+
.background(Color.blue.opacity(0.1))
54+
.cornerRadius(8)
55+
}
56+
}
57+
.padding(.vertical, 4)
58+
59+
// Password field with secure icon
60+
HStack {
61+
Image(systemName: "lock.fill")
62+
.foregroundColor(.blue)
63+
SecureField("P12 Password", text: $p12Password)
2464
}
65+
.padding(.vertical, 4)
2566
}
26-
HStack {
27-
Text("Mobileprovison:")
28-
Spacer()
29-
Text(prov.name.isEmpty ? "" : prov.name).foregroundColor(.secondary)
30-
Button("Pick") {
31-
showPickerFor = .prov
67+
68+
Section {
69+
Button(action: checkStatus) {
70+
HStack {
71+
Spacer()
72+
Text("Check Status")
73+
.font(.headline) // Bolder text
74+
.foregroundColor(.white)
75+
.padding()
76+
.frame(maxWidth: .infinity)
77+
.background(isProcessing || p12.url == nil || prov.url == nil ? Color.gray : Color.blue) // Dynamic color
78+
.cornerRadius(10)
79+
.shadow(radius: 2) // Subtle shadow
80+
Spacer()
81+
}
3282
}
83+
.disabled(isProcessing || p12.url == nil || prov.url == nil)
84+
.scaleEffect(isProcessing ? 0.95 : 1.0) // Subtle animation when processing
85+
.animation(.easeInOut(duration: 0.2), value: isProcessing) // Smooth animation
3386
}
34-
SecureField("P12 Password", text: $p12Password)
35-
}
87+
.padding(.vertical, 8)
3688

37-
Section {
38-
Button(action: checkStatus) {
89+
Section(header: Text("Result")
90+
.font(.headline)
91+
.foregroundColor(.primary)
92+
.padding(.top, 8)) {
3993
HStack {
40-
Spacer()
41-
Text("Check Status").bold()
42-
Spacer()
94+
if isProcessing {
95+
ProgressView() // Spinner for processing
96+
.padding(.trailing, 8)
97+
}
98+
Text(statusMessage)
99+
.foregroundColor(statusMessage == "Success!" ? .green : statusMessage.isEmpty ? .primary : .red) // Green for success, red for errors
100+
.animation(.easeIn, value: statusMessage) // Fade animation for status changes
43101
}
44102
}
45-
.disabled(isProcessing || p12.url == nil || prov.url == nil)
46-
}
47-
48-
Section(header: Text("Result")) {
49-
Text(statusMessage).foregroundColor(.primary)
50103
}
104+
.navigationTitle("Certificate Checker")
105+
.navigationBarTitleDisplayMode(.inline)
106+
.accentColor(.blue) // Custom accent color
51107
}
52-
.navigationTitle("Certificates")
53108
.sheet(item: $showPickerFor, onDismiss: nil) { kind in
54109
DocumentPicker(kind: kind, onPick: { url in
55110
switch kind {

0 commit comments

Comments
 (0)