Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/FALAK097/typesteps/llms.txt

Use this file to discover all available pages before exploring further.

TypeSteps is built using modern SwiftUI patterns with a clear separation between UI, business logic, and data management.

App Structure

The application follows SwiftUI’s declarative architecture with three core managers:
@main
struct TypeStepsApp: App {
    @NSApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
    @StateObject private var storage = StorageManager.shared
    @StateObject private var listener = KeystrokeListener.shared
    @State private var showOnboarding = false
    // ...
}
The main app structure uses:
  • MenuBarExtra for lightweight menu bar presence
  • Window for the dashboard interface
  • @StateObject to manage singleton instances

StateObject Pattern

TypeSteps uses the StateObject pattern to manage app-wide state through singleton managers:

StorageManager.shared

Manages all data persistence and statistics:
class StorageManager: ObservableObject {
    static let shared = StorageManager()
    
    @Published var dailyStats: [String: Int] = [:]
    @Published var hourlyStats: [String: Int] = [:]
    @Published var minuteStats: [String: Int] = [:]
    @Published var appStats: [String: Int] = [:]
    @Published var projectStats: [String: Int] = [:]
    @Published var appBundleMapping: [String: String] = [:]
    // ...
}
See StorageManager.swift:5-392

KeystrokeListener.shared

Handles global event monitoring:
class KeystrokeListener: ObservableObject {
    static let shared = KeystrokeListener()
    
    @Published var isAuthorized: Bool = false
    @Published var isPaused: Bool = false
    private var eventMonitor: Any?
    // ...
}
See KeystrokeListener.swift:5-91

WakaTimeManager.shared

Integrates with WakaTime API:
class WakaTimeManager: ObservableObject {
    static let shared = WakaTimeManager()
    
    @Published var totalMinutesToday: Double = 0
    @Published var isFetching: Bool = false
    @Published var lastError: String?
    // ...
}
See WakaTimeManager.swift:4-62

App Lifecycle

AppDelegate

The AppDelegate handles initialization and onboarding flow:
class AppDelegate: NSObject, NSApplicationDelegate {
    func applicationDidFinishLaunching(_ notification: Notification) {
        NSApp.setActivationPolicy(.regular)
        UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .sound]) { _, _ in }
        
        DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
            self.checkAndStartTracking()
        }
    }
    
    private func checkAndStartTracking() {
        let hasCompletedOnboarding = UserDefaults.standard.bool(forKey: "has_completed_onboarding")
        
        if hasCompletedOnboarding {
            if KeystrokeListener.shared.checkPermissionsSilently() {
                KeystrokeListener.shared.startListening()
            }
        } else {
            NotificationCenter.default.post(name: .showOnboarding, object: nil)
        }
    }
}
See TypeStepsApp.swift:5-29

Notification System

TypeSteps uses NotificationCenter for app-wide events:
extension Notification.Name {
    static let showOnboarding = Notification.Name("showOnboarding")
    static let onboardingCompleted = Notification.Name("onboardingCompleted")
    static let accessibilityGranted = Notification.Name("accessibilityGranted")
}
See TypeStepsApp.swift:31-35

UI Architecture

The menu bar provides quick stats and controls:
MenuBarExtra {
    Text("Today: \(storage.getCount())")
    Text("This Week: \(storage.getWeeklyTotal())")
    Text("This Month: \(storage.getMonthlyTotal())")
    
    Divider()
    
    Button(listener.isPaused ? "Resume Tracking" : "Pause Tracking") {
        listener.isPaused.toggle()
    }
    // ...
} label: {
    HStack {
        Image(systemName: listener.isPaused ? "keyboard.badge.ellipsis" : "keyboard")
        Text("\(storage.getCount())")
    }
}
See TypeStepsApp.swift:55-98

Dashboard Window

The main dashboard uses a tabbed interface showing:
  • Day view with hourly activity chart
  • Week view with daily breakdowns
  • Month view with historical data
Window("TypeSteps", id: "dashboard") {
    ZStack {
        DashboardView()
            .preferredColorScheme(appTheme == 0 ? nil : (appTheme == 1 ? .light : .dark))
        
        if showOnboarding {
            // Onboarding overlay
        }
    }
}
.windowStyle(.hiddenTitleBar)
.defaultSize(width: 1200, height: 850)
See TypeStepsApp.swift:113-150

Theme System

TypeSteps includes 24 built-in themes (12 light, 12 dark):
struct AppTheme: Identifiable, Equatable {
    let id: Int
    let name: String
    let mainBg: Color
    let secondaryBg: Color
    let border: Color
    let text: Color
    let secondaryText: Color
    let accent: Color
}
Themes are stored using @AppStorage:
@AppStorage("app_theme") private var appTheme = 0
See Theme.swift:3-258

Data Models

ActivityPoint

Used for chart rendering:
struct ActivityPoint: Identifiable, Equatable {
    let id = UUID()
    let label: String
    let count: Int
}

AppCategory

Categorizes applications:
enum AppCategory: String, CaseIterable {
    case code = "Code"
    case communicate = "Communicate"
    case create = "Create"
    case browsing = "Browsing"
    case utility = "Utility"
    case other = "Other"
}
See Models.swift:1-28

Service Management

TypeSteps uses ServiceManagement for login item registration:
private func updateLoginItem(enabled: Bool) {
    do {
        if enabled {
            try SMAppService.mainApp.register()
        } else {
            try SMAppService.mainApp.unregister()
        }
    } catch {
        print("Failed to toggle login item: \(error)")
    }
}
See TypeStepsApp.swift:164-176

Build docs developers (and LLMs) love