Progress view
This commit is contained in:
parent
ab2b7e15fa
commit
eddf11288c
@ -36,6 +36,9 @@
|
|||||||
7A68399A269612EA00B2188A /* Response.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A683998269612EA00B2188A /* Response.swift */; };
|
7A68399A269612EA00B2188A /* Response.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A683998269612EA00B2188A /* Response.swift */; };
|
||||||
7ACD05D72695C08A00557667 /* Constants.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7ACD05D62695C08A00557667 /* Constants.swift */; };
|
7ACD05D72695C08A00557667 /* Constants.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7ACD05D62695C08A00557667 /* Constants.swift */; };
|
||||||
7ACD05D82695C08A00557667 /* Constants.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7ACD05D62695C08A00557667 /* Constants.swift */; };
|
7ACD05D82695C08A00557667 /* Constants.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7ACD05D62695C08A00557667 /* Constants.swift */; };
|
||||||
|
7AEFAEED26985A3400ED2C85 /* ACProgressView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AEFAEEC26985A3400ED2C85 /* ACProgressView.swift */; };
|
||||||
|
7AEFAEEE26985A3400ED2C85 /* ACProgressView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AEFAEEC26985A3400ED2C85 /* ACProgressView.swift */; };
|
||||||
|
7AF552D92696E5C100578083 /* ApiTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AF552D82696E5C100578083 /* ApiTests.swift */; };
|
||||||
/* End PBXBuildFile section */
|
/* End PBXBuildFile section */
|
||||||
|
|
||||||
/* Begin PBXContainerItemProxy section */
|
/* Begin PBXContainerItemProxy section */
|
||||||
@ -107,6 +110,8 @@
|
|||||||
7A40D6012694FF5D009B0BC4 /* Api.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Api.swift; sourceTree = "<group>"; };
|
7A40D6012694FF5D009B0BC4 /* Api.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Api.swift; sourceTree = "<group>"; };
|
||||||
7A683998269612EA00B2188A /* Response.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Response.swift; sourceTree = "<group>"; };
|
7A683998269612EA00B2188A /* Response.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Response.swift; sourceTree = "<group>"; };
|
||||||
7ACD05D62695C08A00557667 /* Constants.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Constants.swift; sourceTree = "<group>"; };
|
7ACD05D62695C08A00557667 /* Constants.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Constants.swift; sourceTree = "<group>"; };
|
||||||
|
7AEFAEEC26985A3400ED2C85 /* ACProgressView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ACProgressView.swift; sourceTree = "<group>"; };
|
||||||
|
7AF552D82696E5C100578083 /* ApiTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ApiTests.swift; sourceTree = "<group>"; };
|
||||||
/* End PBXFileReference section */
|
/* End PBXFileReference section */
|
||||||
|
|
||||||
/* Begin PBXFrameworksBuildPhase section */
|
/* Begin PBXFrameworksBuildPhase section */
|
||||||
@ -234,6 +239,7 @@
|
|||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
7A40D5E826938BEC009B0BC4 /* AuthView.swift */,
|
7A40D5E826938BEC009B0BC4 /* AuthView.swift */,
|
||||||
|
7AEFAEEC26985A3400ED2C85 /* ACProgressView.swift */,
|
||||||
);
|
);
|
||||||
path = Views;
|
path = Views;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@ -250,6 +256,7 @@
|
|||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
7A40D5F52693A63A009B0BC4 /* SettingsTests.swift */,
|
7A40D5F52693A63A009B0BC4 /* SettingsTests.swift */,
|
||||||
|
7AF552D82696E5C100578083 /* ApiTests.swift */,
|
||||||
);
|
);
|
||||||
path = AutoCat2Tests;
|
path = AutoCat2Tests;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@ -464,6 +471,7 @@
|
|||||||
7A40D5E926938BEC009B0BC4 /* AuthView.swift in Sources */,
|
7A40D5E926938BEC009B0BC4 /* AuthView.swift in Sources */,
|
||||||
7ACD05D72695C08A00557667 /* Constants.swift in Sources */,
|
7ACD05D72695C08A00557667 /* Constants.swift in Sources */,
|
||||||
7A40D5E326924B09009B0BC4 /* Settings.swift in Sources */,
|
7A40D5E326924B09009B0BC4 /* Settings.swift in Sources */,
|
||||||
|
7AEFAEED26985A3400ED2C85 /* ACProgressView.swift in Sources */,
|
||||||
7A40D5A02691C6D8009B0BC4 /* AutoCat2App.swift in Sources */,
|
7A40D5A02691C6D8009B0BC4 /* AutoCat2App.swift in Sources */,
|
||||||
7A683999269612EA00B2188A /* Response.swift in Sources */,
|
7A683999269612EA00B2188A /* Response.swift in Sources */,
|
||||||
7A40D5A42691C6D8009B0BC4 /* Persistence.swift in Sources */,
|
7A40D5A42691C6D8009B0BC4 /* Persistence.swift in Sources */,
|
||||||
@ -483,6 +491,7 @@
|
|||||||
7A40D5EA26938BEC009B0BC4 /* AuthView.swift in Sources */,
|
7A40D5EA26938BEC009B0BC4 /* AuthView.swift in Sources */,
|
||||||
7ACD05D82695C08A00557667 /* Constants.swift in Sources */,
|
7ACD05D82695C08A00557667 /* Constants.swift in Sources */,
|
||||||
7A40D5A12691C6D8009B0BC4 /* AutoCat2App.swift in Sources */,
|
7A40D5A12691C6D8009B0BC4 /* AutoCat2App.swift in Sources */,
|
||||||
|
7AEFAEEE26985A3400ED2C85 /* ACProgressView.swift in Sources */,
|
||||||
7A40D5A52691C6D8009B0BC4 /* Persistence.swift in Sources */,
|
7A40D5A52691C6D8009B0BC4 /* Persistence.swift in Sources */,
|
||||||
7A68399A269612EA00B2188A /* Response.swift in Sources */,
|
7A68399A269612EA00B2188A /* Response.swift in Sources */,
|
||||||
7A40D5E526924B0C009B0BC4 /* User.swift in Sources */,
|
7A40D5E526924B0C009B0BC4 /* User.swift in Sources */,
|
||||||
@ -515,6 +524,7 @@
|
|||||||
isa = PBXSourcesBuildPhase;
|
isa = PBXSourcesBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
|
7AF552D92696E5C100578083 /* ApiTests.swift in Sources */,
|
||||||
7A40D5F62693A63A009B0BC4 /* SettingsTests.swift in Sources */,
|
7A40D5F62693A63A009B0BC4 /* SettingsTests.swift in Sources */,
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
|||||||
@ -7,12 +7,12 @@
|
|||||||
<key>AutoCat2 (iOS).xcscheme_^#shared#^_</key>
|
<key>AutoCat2 (iOS).xcscheme_^#shared#^_</key>
|
||||||
<dict>
|
<dict>
|
||||||
<key>orderHint</key>
|
<key>orderHint</key>
|
||||||
<integer>0</integer>
|
<integer>1</integer>
|
||||||
</dict>
|
</dict>
|
||||||
<key>AutoCat2 (macOS).xcscheme_^#shared#^_</key>
|
<key>AutoCat2 (macOS).xcscheme_^#shared#^_</key>
|
||||||
<dict>
|
<dict>
|
||||||
<key>orderHint</key>
|
<key>orderHint</key>
|
||||||
<integer>1</integer>
|
<integer>0</integer>
|
||||||
</dict>
|
</dict>
|
||||||
<key>AutoCatCore.xcscheme_^#shared#^_</key>
|
<key>AutoCatCore.xcscheme_^#shared#^_</key>
|
||||||
<dict>
|
<dict>
|
||||||
|
|||||||
29
AutoCat2Tests/ApiTests.swift
Normal file
29
AutoCat2Tests/ApiTests.swift
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
import XCTest
|
||||||
|
import AutoCat2
|
||||||
|
|
||||||
|
class ApiTests: XCTestCase {
|
||||||
|
|
||||||
|
private var api: Api!
|
||||||
|
|
||||||
|
override func setUpWithError() throws {
|
||||||
|
let sessionConfig = URLSessionConfiguration.default
|
||||||
|
let session = URLSession(configuration: sessionConfig)
|
||||||
|
self.api = Api(session: session)
|
||||||
|
}
|
||||||
|
|
||||||
|
override func tearDownWithError() throws {
|
||||||
|
// Put teardown code here. This method is called after the invocation of each test method in the class.
|
||||||
|
}
|
||||||
|
|
||||||
|
func testLogin() async throws {
|
||||||
|
let user = try await self.api.login()
|
||||||
|
}
|
||||||
|
|
||||||
|
// func testPerformanceExample() throws {
|
||||||
|
// // This is an example of a performance test case.
|
||||||
|
// self.measure {
|
||||||
|
// // Put the code you want to measure the time of here.
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
}
|
||||||
68
Shared/Views/ACProgressView.swift
Normal file
68
Shared/Views/ACProgressView.swift
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
import SwiftUI
|
||||||
|
|
||||||
|
struct ACProgressView: View {
|
||||||
|
@State var isDeterminate: Bool = false
|
||||||
|
@State var progress: CGFloat = 0
|
||||||
|
@State var text: String? = nil
|
||||||
|
@State var isAnimating: Bool = false
|
||||||
|
|
||||||
|
var body: some View {
|
||||||
|
ZStack(alignment: .center) {
|
||||||
|
Color.black.opacity(0.4)
|
||||||
|
VStack {
|
||||||
|
VStack(spacing: 24) {
|
||||||
|
if self.isDeterminate {
|
||||||
|
ZStack {
|
||||||
|
Circle()
|
||||||
|
.stroke(Color.secondary.opacity(0.2), style: StrokeStyle(lineWidth: 4))
|
||||||
|
.frame(width: 100, height: 100)
|
||||||
|
Circle()
|
||||||
|
.trim(from: 0, to: self.progress)
|
||||||
|
.stroke(Color.blue, style: StrokeStyle(lineWidth: 4))
|
||||||
|
.rotationEffect(.degrees(-90))
|
||||||
|
.frame(width: 100, height: 100)
|
||||||
|
Text("\(Int(self.progress*100)) %")
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
let gradient = AngularGradient(
|
||||||
|
gradient: Gradient(colors: [Color.blue, Color.blue.opacity(0.01)]),
|
||||||
|
center: .center,
|
||||||
|
startAngle: .degrees(360),
|
||||||
|
endAngle: .degrees(0))
|
||||||
|
Circle()
|
||||||
|
.stroke(gradient, style: StrokeStyle(lineWidth: 4))
|
||||||
|
.rotationEffect(Angle(degrees: self.isAnimating ? 360 : 0))
|
||||||
|
.onAppear {
|
||||||
|
withAnimation(.linear(duration: 1).repeatForever(autoreverses: false)) {
|
||||||
|
self.isAnimating = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.onDisappear(perform: {
|
||||||
|
self.isAnimating = false
|
||||||
|
})
|
||||||
|
.frame(width: 100, height: 100)
|
||||||
|
}
|
||||||
|
|
||||||
|
if let msg = self.text {
|
||||||
|
Text(msg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.padding(28)
|
||||||
|
}
|
||||||
|
//.frame(width: 160, height: 160)
|
||||||
|
.background(.regularMaterial)
|
||||||
|
.cornerRadius(20)
|
||||||
|
}
|
||||||
|
.edgesIgnoringSafeArea(.all)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ACProgressView_Previews: PreviewProvider {
|
||||||
|
static var previews: some View {
|
||||||
|
Group {
|
||||||
|
ACProgressView()
|
||||||
|
ACProgressView(isDeterminate: true, progress: 0.3, text: "Loading...")
|
||||||
|
.preferredColorScheme(.dark)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -5,13 +5,16 @@ struct AuthView: View {
|
|||||||
|
|
||||||
@State var login: String
|
@State var login: String
|
||||||
@State var password: String
|
@State var password: String
|
||||||
|
@State var showProgress: Bool = false
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
|
ZStack {
|
||||||
VStack(alignment: .center, spacing: 16) {
|
VStack(alignment: .center, spacing: 16) {
|
||||||
Spacer()
|
Spacer()
|
||||||
TextField("Login", text: $login)
|
TextField("Login", text: $login)
|
||||||
SecureField("Password", text: $password)
|
SecureField("Password", text: $password)
|
||||||
Button("Login") {
|
Button("Login") {
|
||||||
|
self.showProgress = true
|
||||||
async {
|
async {
|
||||||
try await self.viewModel.login(user: self.login, password: self.password)
|
try await self.viewModel.login(user: self.login, password: self.password)
|
||||||
}
|
}
|
||||||
@ -21,6 +24,11 @@ struct AuthView: View {
|
|||||||
.buttonStyle(.bordered)
|
.buttonStyle(.bordered)
|
||||||
.textFieldStyle(.roundedBorder)
|
.textFieldStyle(.roundedBorder)
|
||||||
.padding(20)
|
.padding(20)
|
||||||
|
|
||||||
|
if self.showProgress {
|
||||||
|
ACProgressView()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user