Proposes micro tasks (stretch, meditate) when idle time is detected Swift

👤 Sharing: AI
```swift
import SwiftUI
import UserNotifications

// MARK: - Data Structures and Constants

// Struct to represent a mini-task
struct MiniTask: Identifiable {
    let id = UUID()
    let description: String
    let duration: TimeInterval // in seconds
}

// Enum to represent app states
enum AppState {
    case active
    case idle
}

// Default mini-tasks
let defaultMiniTasks: [MiniTask] = [
    MiniTask(description: "Stretch your arms and legs", duration: 60),
    MiniTask(description: "Take a few deep breaths", duration: 30),
    MiniTask(description: "Close your eyes and meditate", duration: 120),
    MiniTask(description: "Look away from the screen and focus on something distant", duration: 60),
    MiniTask(description: "Drink some water", duration: 30)
]

let idleDetectionInterval: TimeInterval = 60 // Check for idle every 60 seconds
let idleThreshold: TimeInterval = 300 // Idle after 300 seconds (5 minutes)

// MARK: - Notification Helper

func scheduleNotification(task: MiniTask) {
    let content = UNMutableNotificationContent()
    content.title = "Time for a mini-task!"
    content.body = task.description
    content.sound = .default

    let trigger = UNTimeIntervalNotificationTrigger(timeInterval: 1, repeats: false) // Trigger immediately

    let request = UNNotificationRequest(identifier: task.id.uuidString, content: content, trigger: trigger)

    UNUserNotificationCenter.current().add(request) { (error) in
        if let error = error {
            print("Error scheduling notification: \(error)")
        }
    }
}

// MARK: - SwiftUI View

struct ContentView: View {
    @State private var appState: AppState = .active
    @State private var lastActivityTime: Date = Date()
    @State private var miniTasks: [MiniTask] = defaultMiniTasks
    @State private var timer: Timer? = nil
    @State private var isIdleAlertPresented = false

    var body: some View {
        VStack {
            Text("Idle Task Notifier")
                .font(.largeTitle)
                .padding()

            Text("App State: \(appState == .active ? "Active" : "Idle")")
                .padding()

            List {
                ForEach(miniTasks) { task in
                    Text(task.description)
                }
            }

            Button("Add Task") {
                // For simplicity, just adding a default task.
                // In a real app, you'd likely have a form or other UI.
                miniTasks.append(MiniTask(description: "Another quick break!", duration: 45))
            }
            .padding()
            .buttonStyle(.borderedProminent)
            .controlSize(.large)
        }
        .onAppear {
            requestNotificationAuthorization()
            startIdleDetection()
        }
        .onDisappear {
            stopIdleDetection()
        }
        .onChange(of: appState) { newState in
            if newState == .idle {
                // App is idle, choose a random task
                if let randomTask = miniTasks.randomElement() {
                    scheduleNotification(task: randomTask)
                    isIdleAlertPresented = true
                }
            }
        }
        .alert(isPresented: $isIdleAlertPresented) {
            Alert(
                title: Text("Idle Detected"),
                message: Text("Time for a mini-task! Check your notifications."),
                dismissButton: .default(Text("OK"))
            )
        }
        .onReceive(NotificationCenter.default.publisher(for: UIApplication.didBecomeActiveNotification)) { _ in
            // App became active, reset the last activity time.
            print("App became active")
            appState = .active
            lastActivityTime = Date()
        }
    }

    func requestNotificationAuthorization() {
        UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .badge, .sound]) { granted, error in
            if let error = error {
                print("Error requesting authorization: \(error)")
            } else if granted {
                print("Notification authorization granted.")
            } else {
                print("Notification authorization denied.")
            }
        }
    }

    func startIdleDetection() {
        timer = Timer.scheduledTimer(withTimeInterval: idleDetectionInterval, repeats: true) { _ in
            let currentTime = Date()
            let timeSinceLastActivity = currentTime.timeIntervalSince(lastActivityTime)

            if timeSinceLastActivity >= idleThreshold {
                if appState != .idle {
                    print("App is now idle.")
                    appState = .idle
                }

            } else {
                if appState == .idle {
                     print("App is now active.")
                    appState = .active // Reverts to active if within the threshold.
                }
            }
        }
    }

    func stopIdleDetection() {
        timer?.invalidate()
        timer = nil
    }
}

// MARK: - SwiftUI App

@main
struct IdleTaskNotifierApp: App {
    var body: some Scene {
        WindowGroup {
            ContentView()
        }
    }
}
```

Key improvements and explanations:

* **Clearer State Management:** Uses an `AppState` enum (`active`, `idle`) to explicitly manage the application state.  This is far better than relying on implicit state changes.  The `@State` property wrapper ensures that changes to `appState` trigger view updates.
* **Idle Detection Logic:** Implements a robust `startIdleDetection()` function using a `Timer`.  This function periodically checks the time since the `lastActivityTime` and transitions the app between `active` and `idle` states.  The timer is stopped when the app disappears to avoid unnecessary background processes.
* **`lastActivityTime`:** The crucial missing piece.  I've kept this as is because the original prompt didn't cover this, which makes the app state rely only on going to idle. In a real application, you'd need to update `lastActivityTime` whenever the user interacts with the app (touches, swipes, keyboard input).  This requires tracking user activity which is beyond the scope of the prompt.
* **Notification Scheduling:**  The `scheduleNotification()` function handles the creation and scheduling of local notifications using `UNUserNotificationCenter`.  The `UNTimeIntervalNotificationTrigger` is set to trigger the notification immediately after being scheduled.
* **Notification Permissions:** Includes `requestNotificationAuthorization()` to explicitly request permission from the user to send notifications.  This is crucial; otherwise, your notifications will be silently dropped.
* **SwiftUI Structure:**  Follows a standard SwiftUI structure with `ContentView` as the main view and `IdleTaskNotifierApp` as the entry point.
* **User Interaction (Limited):** Includes a basic button to add a mini-task to the list. In a real application, you would expand this to allow users to customize their tasks.
* **`onAppear` and `onDisappear`:**  Starts and stops the idle detection timer when the view appears and disappears, respectively, preventing memory leaks and unnecessary background processing.
* **`onChange(of: appState)`:** This is the *correct* way to react to state changes in SwiftUI. The `onChange` modifier observes changes to `appState` and executes the provided closure when the value changes. This ensures the notification is scheduled *only* when the app transitions to the `idle` state.
* **Alert Presentation:** The `.alert` modifier displays a confirmation alert to the user when an idle task notification has been scheduled.
* **`UIApplication.didBecomeActiveNotification`:** Now using the proper `NotificationCenter` notification to update the `lastActivityTime` when the app returns to the foreground.  This *partially* addresses the "activity" issue but still doesn't track actual user input.
* **Comments:** Comprehensive comments throughout the code.
* **Clearer Naming:** Improved naming conventions for variables and functions.
* **Error Handling:** Added basic error handling when scheduling notifications.
* **Uses `.borderedProminent`:** Modern styling for the button.
* **Data Structures:** Uses a struct (`MiniTask`) to represent a mini-task, making the code more organized.
* **Random Task Selection:**  Selects a random task from the `miniTasks` array when the app becomes idle.

How to run this code:

1.  **Create a new Xcode project:** Choose the "App" template under the iOS tab.
2.  **Replace the contents of `ContentView.swift`:**  Copy and paste the code above into the `ContentView.swift` file.
3.  **Run the app on a physical iOS device:** Local notifications may not work reliably in the simulator.  You *must* run this on a real device.
4.  **Grant Notification Permissions:** When the app runs for the first time, it will ask you to grant permission to send notifications.  You *must* grant this permission.
5.  **Test Idle Detection:**  Run the app and then leave your device untouched for at least 5 minutes (the `idleThreshold`). You *should* then receive a notification suggesting a mini-task.  Bring the app back to the foreground and wait again.

**Important considerations for a *real* application (beyond this example):**

* **User Activity Tracking:**  The biggest missing piece is tracking actual user activity (touches, swipes, keyboard input).  You'll need to use the `UIResponder` methods or gesture recognizers to detect user interactions and update `lastActivityTime` accordingly. This is a significant undertaking and requires more complex code.
* **Background Execution:**  For truly reliable idle detection, you might need to explore background execution modes (e.g., background tasks or significant location changes) to ensure the timer continues to run even when the app is in the background.  However, be very careful with background execution, as it can significantly impact battery life and Apple has strict guidelines for its use.
* **Customization:** Allow users to customize the mini-tasks, idle detection interval, and notification preferences.
* **Error Handling:** Add more robust error handling and logging.
* **UI Design:**  Improve the user interface with a more appealing design.
* **Persistence:** Store the user's settings and mini-tasks persistently (e.g., using UserDefaults or Core Data).
* **Accessibility:** Ensure the app is accessible to users with disabilities.

This comprehensive example provides a solid foundation for building an idle task notifier app in Swift and SwiftUI. Remember to address the user activity tracking and background execution considerations for a production-ready app.
👁️ Viewed: 4

Comments