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
23 changes: 0 additions & 23 deletions SPAR/SPAR/SPARApp.swift

This file was deleted.

70 changes: 0 additions & 70 deletions SPAR/SPAR/ViewModel/LoginViewModel.swift

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@
3D98C7F92D4FE04700462EF4 /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 3D98C7F82D4FE04700462EF4 /* Preview Assets.xcassets */; };
3DA1AA442DBDB01300678160 /* DiskIOModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3D505B6E2DBACDCA00510486 /* DiskIOModel.swift */; };
3DA1AA452DBDB08700678160 /* AppSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3D505B5C2DBA657B00510486 /* AppSettings.swift */; };
3DA1AA472DBF034200678160 /* KeychainHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DA1AA462DBF034200678160 /* KeychainHelper.swift */; };
3DCE45892D68C19200FACBB8 /* Constant.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DCE45882D68C19200FACBB8 /* Constant.swift */; };
3DCE458B2D68C19F00FACBB8 /* SplashScreenView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DCE458A2D68C19F00FACBB8 /* SplashScreenView.swift */; };
3DCE458D2D68C1A900FACBB8 /* Logger+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DCE458C2D68C1A900FACBB8 /* Logger+Extension.swift */; };
Expand Down Expand Up @@ -141,6 +142,7 @@
3D98C7F32D4FE04500462EF4 /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = "<group>"; };
3D98C7F52D4FE04700462EF4 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
3D98C7F82D4FE04700462EF4 /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = "<group>"; };
3DA1AA462DBF034200678160 /* KeychainHelper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeychainHelper.swift; sourceTree = "<group>"; };
3DCE45882D68C19200FACBB8 /* Constant.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Constant.swift; sourceTree = "<group>"; };
3DCE458A2D68C19F00FACBB8 /* SplashScreenView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SplashScreenView.swift; sourceTree = "<group>"; };
3DCE458C2D68C1A900FACBB8 /* Logger+Extension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Logger+Extension.swift"; sourceTree = "<group>"; };
Expand Down Expand Up @@ -219,6 +221,7 @@
3D505B642DBAAE4D00510486 /* DiskUsageViewModel.swift */,
3D505B6A2DBAC5EC00510486 /* CpuUsageViewModel.swift */,
3D505B702DBACDE500510486 /* DiskIOViewModel.swift */,
3DA1AA462DBF034200678160 /* KeychainHelper.swift */,
);
path = ViewModel;
sourceTree = "<group>";
Expand Down Expand Up @@ -473,6 +476,7 @@
3D5994FA2DB307B400E9215B /* HomeViewModel.swift in Sources */,
3DCE458B2D68C19F00FACBB8 /* SplashScreenView.swift in Sources */,
3DCE458D2D68C1A900FACBB8 /* Logger+Extension.swift in Sources */,
3DA1AA472DBF034200678160 /* KeychainHelper.swift in Sources */,
3D505B4D2DB9C1BE00510486 /* DeviceOptions.swift in Sources */,
3D505B5B2DB9E3F700510486 /* ProcessViewModel.swift in Sources */,
3D505B632DBAAE2C00510486 /* DiskUsage.swift in Sources */,
Expand Down Expand Up @@ -697,6 +701,7 @@
DEVELOPMENT_TEAM = 2WRH48XVUZ;
ENABLE_PREVIEWS = YES;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_KEY_NSFaceIDUsageDescription = "We use it to unlock the phone";
INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES;
INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
INFOPLIST_KEY_UILaunchScreen_Generation = YES;
Expand Down Expand Up @@ -732,6 +737,7 @@
DEVELOPMENT_TEAM = 2WRH48XVUZ;
ENABLE_PREVIEWS = YES;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_KEY_NSFaceIDUsageDescription = "We use it to unlock the phone";
INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES;
INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
INFOPLIST_KEY_UILaunchScreen_Generation = YES;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,48 +39,48 @@
<BreakpointProxy
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
<BreakpointContent
uuid = "04D26233-6466-4FCF-87B6-2158621E72B8"
uuid = "9F496AF5-2BA7-4384-BB8C-F0B60E13AE01"
shouldBeEnabled = "No"
ignoreCount = "0"
continueAfterRunningActions = "No"
filePath = "SPAR/ViewModel/HomeViewModel.swift"
filePath = "SPAR/ViewModel/ProcessViewModel.swift"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "37"
endingLineNumber = "37"
landmarkName = "getDeviceData()"
startingLineNumber = "21"
endingLineNumber = "21"
landmarkName = "fetchProcessInfo(device:)"
landmarkType = "7">
</BreakpointContent>
</BreakpointProxy>
<BreakpointProxy
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
<BreakpointContent
uuid = "9F496AF5-2BA7-4384-BB8C-F0B60E13AE01"
uuid = "84940FE7-5CAE-4A83-A81B-9ADF5CBFD006"
shouldBeEnabled = "No"
ignoreCount = "0"
continueAfterRunningActions = "No"
filePath = "SPAR/ViewModel/ProcessViewModel.swift"
filePath = "SPAR/NetworkService/NetworkManager.swift"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "21"
endingLineNumber = "21"
landmarkName = "fetchProcessInfo(device:)"
startingLineNumber = "29"
endingLineNumber = "29"
landmarkName = "fetchCPUUsageInfo(for:deviceId:)"
landmarkType = "7">
</BreakpointContent>
</BreakpointProxy>
<BreakpointProxy
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
<BreakpointContent
uuid = "84940FE7-5CAE-4A83-A81B-9ADF5CBFD006"
uuid = "951A46B2-807E-40DA-AAF7-ECB1AB5BD7B9"
shouldBeEnabled = "No"
ignoreCount = "0"
continueAfterRunningActions = "No"
filePath = "SPAR/NetworkService/NetworkManager.swift"
filePath = "SPAR/ViewModel/HomeViewModel.swift"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "29"
endingLineNumber = "29"
landmarkName = "fetchCPUUsageInfo(for:deviceId:)"
startingLineNumber = "44"
endingLineNumber = "44"
landmarkName = "getDeviceData()"
landmarkType = "7">
</BreakpointContent>
</BreakpointProxy>
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
45 changes: 42 additions & 3 deletions SPAR/SPAR/HomeView.swift → SPAR_iOS/SPAR/SPAR/HomeView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@

import SwiftUI


struct HomeView: View {
@Binding var currentView: AppView
@StateObject private var viewModel = HomeViewModel()
Expand All @@ -19,7 +18,6 @@ struct HomeView: View {
BackgroundAnimationView(animate: $viewModel.animate)

VStack(spacing: 20) {

// SPAR title
HStack {
Text(StringConstant.appName)
Expand Down Expand Up @@ -93,7 +91,48 @@ struct HomeView: View {
.navigationBarHidden(true)
.onAppear {
self.logPageVisit()
}
}

// Show download popup when no devices are available
if viewModel.showDownloadPopup {
VStack {
Spacer(minLength: 200)

// Cool empty state
VStack {
Image(systemName: "desktopcomputer")
.font(.system(size: 70))
.foregroundColor(.blue)
.scaleEffect(1.2)
.opacity(0.8)
.animation(.easeInOut(duration: 1).repeatForever(autoreverses: true), value: viewModel.showDownloadPopup)

Text("You need to have at least one Desktop APP.")
.font(.system(size: 28, weight: .bold))
.foregroundColor(.primary)
.multilineTextAlignment(.center)
.padding(.top, 20)
.opacity(0.9)
.scaleEffect(viewModel.showDownloadPopup ? 1 : 1.05)
.animation(.easeInOut(duration: 0.6).repeatForever(autoreverses: true), value: viewModel.showDownloadPopup)

Text("Download SPAR Desktop")
.font(.system(size: 20, weight: .semibold))
.foregroundColor(.blue)
.underline()
.onTapGesture {
// Action to download SPAR Desktop
// You can trigger URL to download or show info here
}
.padding(.top, 10)

Spacer()
}
.frame(maxWidth: .infinity, maxHeight: .infinity)
.padding(40)
.transition(.opacity)
}
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ struct LoginView: View {
Button(action: {
viewModel.submit()
viewModel.logger.info("\(LoggerConstant.LoginSubmitTapped)")
AppSettings.shared.hasLoggedInOnce = true // Save after first login
}) {
Text(StringConstant.submit)
.frame(maxWidth: .infinity)
Expand All @@ -105,15 +106,40 @@ struct LoginView: View {
.minimumScaleFactor(sizeCategory.customMinScaleFactor)
.shadow(radius: 10)
}
.accessibilityElement(children: .ignore) // Ensures only the button's main label is read by screen readers
.accessibilityAddTraits(.isButton)
.accessibilityElement(children: .ignore)
.accessibilityAddTraits(.isButton)

// Face ID Button
if AppSettings.shared.hasLoggedInOnce {
Button(action: {
viewModel.loginWithFaceID()
}) {
Image(systemName: "faceid")
.resizable()
.scaledToFit()
.frame(width: 50, height: 50)
.padding()
.background(Color.blue.opacity(0.5))
.foregroundColor(.white)
.clipShape(Circle())
}
.padding(.top, 10)
.shadow(radius: 10)
}
}
.padding(40)
}
.onAppear {
viewModel.delegate = coordinator
viewModel.animate = true
self.logPageVisit()

// If already logged in once, automatically trigger FaceID
if AppSettings.shared.hasLoggedInOnce {
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
viewModel.loginWithFaceID()
}
}
}
}

Expand All @@ -130,10 +156,8 @@ struct LoginView: View {
}
}


struct LoginView_Previews: PreviewProvider {
static var previews: some View {
LoginView(currentView: .constant(.login))
}
}

33 changes: 33 additions & 0 deletions SPAR_iOS/SPAR/SPAR/SPARApp.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
//
// SPARApp.swift
// SPAR
//
// Created by Abhijeet Cherungottil on 2/2/25.
//

import SwiftUI
import OSLog

@main
struct SPARApp: App {
init() {
// Check if we're running in UI Test mode
if ProcessInfo.processInfo.arguments.contains("-resetDefaults") {
let domain = Bundle.main.bundleIdentifier!
UserDefaults.standard.removePersistentDomain(forName: domain)
UserDefaults.standard.synchronize()
print("UserDefaults reset for UI Test")
}
}

let logger = Logger.fileLocation

var body: some Scene {
WindowGroup {
ContentView()
.onAppear{
logger.info("\(URL.documentsDirectory.path())")
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,12 @@ final class AppSettings {
private let onboardingKey = "hasCompletedOnboarding"
private let tokenKey = "authToken"
private let userIdKey = "userId"
private let hasLoggedInOnceKey = "hasLoggedInOnce"

var hasLoggedInOnce: Bool {
get { UserDefaults.standard.bool(forKey: hasLoggedInOnceKey) }
set { UserDefaults.standard.set(newValue, forKey: hasLoggedInOnceKey) }
}

var hasCompletedOnboarding: Bool {
get { UserDefaults.standard.bool(forKey: onboardingKey) }
Expand Down
Loading
Loading