Skip to content
Open
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
8 changes: 8 additions & 0 deletions LoopFollow.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -808,6 +808,8 @@
/* End PBXFileReference section */

/* Begin PBXFileSystemSynchronizedRootGroup section */
65AC25F52ECFD5E800421360 /* Stats */ = {isa = PBXFileSystemSynchronizedRootGroup; explicitFileTypes = {}; explicitFolders = (); path = Stats; sourceTree = "<group>"; };
65AC26702ED245DF00421360 /* Treatments */ = {isa = PBXFileSystemSynchronizedRootGroup; explicitFileTypes = {}; explicitFolders = (); path = Treatments; sourceTree = "<group>"; };
DDCC3AD72DDE1790006F1C10 /* Tests */ = {isa = PBXFileSystemSynchronizedRootGroup; explicitFileTypes = {}; explicitFolders = (); path = Tests; sourceTree = "<group>"; };
/* End PBXFileSystemSynchronizedRootGroup section */

Expand Down Expand Up @@ -1473,6 +1475,8 @@
FC8DEEE32485D1680075863F /* LoopFollow */ = {
isa = PBXGroup;
children = (
65AC26702ED245DF00421360 /* Treatments */,
65AC25F52ECFD5E800421360 /* Stats */,
6589CC612E9E7D1600BB18FE /* Settings */,
DDCF9A7E2D85FCE6004DF4DD /* Alarm */,
FC16A97624995FEE003D6245 /* Application */,
Expand Down Expand Up @@ -1630,6 +1634,10 @@
);
dependencies = (
);
fileSystemSynchronizedGroups = (
65AC25F52ECFD5E800421360 /* Stats */,
65AC26702ED245DF00421360 /* Treatments */,
);
name = LoopFollow;
packageProductDependencies = (
DD48781B2C7DAF140048F05C /* SwiftJWT */,
Expand Down
4 changes: 2 additions & 2 deletions LoopFollow/Alarm/AddAlarm/AddAlarmSheet.swift
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ struct AddAlarmSheet: View {
Section(header: Text(group.rawValue)
.font(.headline)
.frame(maxWidth: .infinity, alignment: .leading)
.padding(.horizontal, 4)
) {
.padding(.horizontal, 4))
{
ForEach(AlarmType.allCases.filter { $0.group == group }, id: \.self) { type in
AlarmTile(type: type) {
onSelect(type)
Expand Down
8 changes: 4 additions & 4 deletions LoopFollow/Alarm/Alarm.swift
Original file line number Diff line number Diff line change
Expand Up @@ -183,9 +183,9 @@ struct Alarm: Identifiable, Codable, Equatable {
/// “Ignore Under BG” (if current BG is below this, skip the alert)
var missedBolusIgnoreUnderBG: Double?

// ─────────────────────────────────────────────────────────────
// Bolus‑Count fields ─
// ─────────────────────────────────────────────────────────────
/// ─────────────────────────────────────────────────────────────
/// Bolus‑Count fields ─
/// ─────────────────────────────────────────────────────────────
/// trigger when N or more of those boluses occur...
var bolusCountThreshold: Int?
/// ...within this many minutes
Expand Down Expand Up @@ -266,7 +266,7 @@ struct Alarm: Identifiable, Codable, Equatable {

switch type {
case .buildExpire:
/// Alert 7 days before the build expires
// Alert 7 days before the build expires
threshold = 7
soundFile = .wrongAnswer
snoozeDuration = 1
Expand Down
2 changes: 0 additions & 2 deletions LoopFollow/Alarm/AlarmCondition/PumpChangeCondition.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,6 @@ import Foundation
/// cannula 3-day hard-stop. Automatically disables itself after firing.
struct PumpChangeCondition: AlarmCondition {
static let type: AlarmType = .pumpChange
init() {}

/// Pod lifetime = 3 days = 72 h
private let lifetime: TimeInterval = 3 * 24 * 60 * 60

Expand Down
2 changes: 0 additions & 2 deletions LoopFollow/Alarm/AlarmCondition/SensorAgeCondition.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,6 @@ import Foundation
/// Dexcom 10-day hard-stop. No repeats once triggered.
struct SensorAgeCondition: AlarmCondition {
static let type: AlarmType = .sensorChange
init() {}

/// Dexcom hard-stop = 10 days = 240 h
private let lifetime: TimeInterval = 10 * 24 * 60 * 60

Expand Down
1 change: 0 additions & 1 deletion LoopFollow/Alarm/AlarmEditing/AlarmEditor.swift
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,6 @@ struct AlarmEditor: View {
.preferredColorScheme(Storage.shared.appearanceMode.value.colorScheme)
}

@ViewBuilder
private func innerEditor() -> some View {
Form {
innerEditorBody()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@ import SwiftUI
struct AlarmSnoozeSection: View {
@Binding var alarm: Alarm

private var unitLabel: String { alarm.type.snoozeTimeUnit.label }
private var unitLabel: String {
alarm.type.snoozeTimeUnit.label
}

private var defaultSnoozeBinding: Binding<Int> {
Binding(
Expand Down
2 changes: 1 addition & 1 deletion LoopFollow/Alarm/AlarmEditing/Components/InfoBanner.swift
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ struct InfoBanner: View {
var tint: Color = Color.blue.opacity(0.20)
var border: Color = Color.blue.opacity(0.40)

// ────────── View ──────────
/// ────────── View ──────────
var body: some View {
HStack(alignment: .top, spacing: 12) {
Image(systemName: alarmType?.icon ?? "info.circle.fill")
Expand Down
6 changes: 4 additions & 2 deletions LoopFollow/Alarm/AlarmEditing/Components/SoundFile.swift
Original file line number Diff line number Diff line change
Expand Up @@ -112,8 +112,10 @@ enum SoundFile: String, CaseIterable, Identifiable, Codable {
case winGain = "Win_Gain"
case wrongAnswer = "Wrong_Answer"

// Identifiable conformance
var id: SoundFile { self }
/// Identifiable conformance
var id: SoundFile {
self
}

/// Human-friendly name (spaces instead of underscores)
var displayName: String {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import SwiftUI
struct TemporaryAlarmEditor: View {
@Binding var alarm: Alarm

// Shared BG range
/// Shared BG range
private let bgRange: ClosedRange<Double> = 40 ... 300

var body: some View {
Expand Down
1 change: 0 additions & 1 deletion LoopFollow/Alarm/AlarmListView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,6 @@ struct AlarmListView: View {

// MARK: - Views

@ViewBuilder
private func alarmRow(for alarm: Alarm) -> some View {
Button {
selectedAlarm = alarm
Expand Down
2 changes: 1 addition & 1 deletion LoopFollow/Alarm/DataStructs/GlucoseValue.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

import Foundation

// Make use of this more clean glucose struct in more places
/// Make use of this more clean glucose struct in more places
struct GlucoseValue: Codable {
let sgv: Int
let date: Date
Expand Down
6 changes: 3 additions & 3 deletions LoopFollow/Application/AppDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate {

// MARK: - Remote Notifications

// Called when successfully registered for remote notifications
/// Called when successfully registered for remote notifications
func application(_: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
let tokenString = deviceToken.map { String(format: "%02.2hhx", $0) }.joined()

Expand All @@ -61,12 +61,12 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
LogManager.shared.log(category: .general, message: "Successfully registered for remote notifications with token: \(tokenString)")
}

// Called when failed to register for remote notifications
/// Called when failed to register for remote notifications
func application(_: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) {
LogManager.shared.log(category: .general, message: "Failed to register for remote notifications: \(error.localizedDescription)")
}

// Called when a remote notification is received
/// Called when a remote notification is received
func application(_: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
LogManager.shared.log(category: .general, message: "Received remote notification: \(userInfo)")

Expand Down
4 changes: 2 additions & 2 deletions LoopFollow/Application/SceneDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate {
(UIApplication.shared.delegate as? AppDelegate)?.saveContext()
}

// Handle the UIApplicationShortcutItem when the user taps on the Home Screen Quick Action. This function toggles the "Speak BG" setting in UserDefaultsRepository, speaks the current state (on/off) using AVSpeechSynthesizer, and updates the Quick Action appearance.
/// Handle the UIApplicationShortcutItem when the user taps on the Home Screen Quick Action. This function toggles the "Speak BG" setting in UserDefaultsRepository, speaks the current state (on/off) using AVSpeechSynthesizer, and updates the Quick Action appearance.
func handleShortcutItem(_ shortcutItem: UIApplicationShortcutItem) {
if let bundleIdentifier = Bundle.main.bundleIdentifier {
let expectedType = bundleIdentifier + ".toggleSpeakBG"
Expand All @@ -66,7 +66,7 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate {
}
}

// The following method is called when the user taps on the Home Screen Quick Action
/// The following method is called when the user taps on the Home Screen Quick Action
func windowScene(_: UIWindowScene, performActionFor shortcutItem: UIApplicationShortcutItem, completionHandler _: @escaping (Bool) -> Void) {
handleShortcutItem(shortcutItem)
}
Expand Down
12 changes: 6 additions & 6 deletions LoopFollow/Controllers/AlarmSound.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import Foundation
import MediaPlayer
import UIKit

/*
/**
* Class that handles the playing and the volume of the alarm sound.
*/
class AlarmSound {
Expand Down Expand Up @@ -48,7 +48,7 @@ class AlarmSound {
AlarmSound.stop()
}

/*
/**
* Sets the audio volume to 0.
*/
static func muteVolume() {
Expand All @@ -61,7 +61,7 @@ class AlarmSound {
soundURL = Bundle.main.url(forResource: str, withExtension: "caf")!
}

/*
/**
* Sets the volume of the alarm back to the volume before it has been muted.
*/
static func unmuteVolume() {
Expand Down Expand Up @@ -284,7 +284,7 @@ class AudioPlayerDelegate: NSObject, AVAudioPlayerDelegate {
}
}

/* if an error occurs while decoding it will be reported to the delegate. */
/** if an error occurs while decoding it will be reported to the delegate. */
func audioPlayerDecodeErrorDidOccur(_: AVAudioPlayer, error: Error?) {
if let error = error {
LogManager.shared.log(category: .alarm, message: "AlarmRule - audioPlayerDecodeErrorDidOccur: \(error)")
Expand All @@ -302,14 +302,14 @@ class AudioPlayerDelegate: NSObject, AVAudioPlayerDelegate {
}

/* audioPlayerEndInterruption:withOptions: is called when the audio session interruption has ended and this player had been interrupted while playing. */
/* Currently the only flag is AVAudioSessionInterruptionFlags_ShouldResume. */
/** Currently the only flag is AVAudioSessionInterruptionFlags_ShouldResume. */
func audioPlayerEndInterruption(_: AVAudioPlayer, withOptions flags: Int) {
LogManager.shared.log(category: .alarm, message: "AlarmRule - audioPlayerEndInterruption withOptions: \(flags)")
Observable.shared.alarmSoundPlaying.value = false
}
}

// Helper function inserted by Swift 4.2 migrator.
/// Helper function inserted by Swift 4.2 migrator.
private func convertFromAVAudioSessionCategory(_ input: AVAudioSession.Category) -> String {
return input.rawValue
}
Expand Down
5 changes: 1 addition & 4 deletions LoopFollow/Controllers/Graphs.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@ import Charts
import Foundation
import UIKit

import Charts

enum GraphDataIndex: Int {
case bg = 0
case prediction = 1
Expand Down Expand Up @@ -139,14 +137,13 @@ class TempTargetChartDataEntry: ChartDataEntry {
}

override func copy(with _: NSZone? = nil) -> Any {
let copy = TempTargetChartDataEntry(
return TempTargetChartDataEntry(
xStart: xStart,
xEnd: xEnd,
yTop: yTop,
yBottom: yBottom,
data: data
)
return copy
}
}

Expand Down
14 changes: 7 additions & 7 deletions LoopFollow/Controllers/MainViewController+updateStats.swift
Original file line number Diff line number Diff line change
Expand Up @@ -22,16 +22,16 @@ extension MainViewController {

let stats = StatsData(bgData: lastDayOfData)

statsLowPercent.text = String(format: "%.1f%", stats.percentLow) + "%"
statsInRangePercent.text = String(format: "%.1f%", stats.percentRange) + "%"
statsHighPercent.text = String(format: "%.1f%", stats.percentHigh) + "%"
statsAvgBG.text = Localizer.toDisplayUnits(String(format: "%.0f%", stats.avgBG))
statsLowPercent.text = String(format: "%.1f%%", stats.percentLow)
statsInRangePercent.text = String(format: "%.1f%%", stats.percentRange)
statsHighPercent.text = String(format: "%.1f%%", stats.percentHigh)
statsAvgBG.text = Localizer.toDisplayUnits(String(format: "%.0f", stats.avgBG))
if Storage.shared.useIFCC.value {
statsEstA1C.text = String(format: "%.0f%", stats.a1C)
statsEstA1C.text = String(format: "%.0f", stats.a1C)
} else {
statsEstA1C.text = String(format: "%.1f%", stats.a1C)
statsEstA1C.text = String(format: "%.1f", stats.a1C)
}
statsStdDev.text = String(format: "%.2f%", stats.stdDev)
statsStdDev.text = String(format: "%.2f", stats.stdDev)

createStatsPie(pieData: stats.pie)
}
Expand Down
10 changes: 5 additions & 5 deletions LoopFollow/Controllers/NightScout.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import Foundation
import UIKit

extension MainViewController {
// NS Cage Struct
/// NS Cage Struct
struct cageData: Codable {
var created_at: String
}
Expand All @@ -18,27 +18,27 @@ extension MainViewController {
var created_at: String
}

// NS Basal Profile Struct
/// NS Basal Profile Struct
struct basalProfileStruct: Codable {
var value: Double
var time: String
var timeAsSeconds: Double
}

// NS Basal Data Struct
/// NS Basal Data Struct
struct basalGraphStruct: Codable {
var basalRate: Double
var date: TimeInterval
}

// NS Bolus Data Struct
/// NS Bolus Data Struct
struct bolusGraphStruct: Codable {
var value: Double
var date: TimeInterval
var sgv: Int
}

// NS Bolus Data Struct
/// NS Bolus Data Struct
struct carbGraphStruct: Codable {
var value: Double
var date: TimeInterval
Expand Down
6 changes: 3 additions & 3 deletions LoopFollow/Controllers/Nightscout/BGData.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import Foundation
import UIKit

extension MainViewController {
// Dex Share Web Call
/// Dex Share Web Call
func webLoadDexShare() {
// Dexcom Share only returns 24 hrs of data as of now
// Requesting more just for consistency with NS
Expand Down Expand Up @@ -42,7 +42,7 @@ extension MainViewController {
}
}

// NS BG Data Web call
/// NS BG Data Web call
func webLoadNSBGData(dexData: [ShareGlucoseData] = []) {
// This kicks it out in the instance where dexcom fails but they aren't using NS &&
if !IsNightscoutEnabled() {
Expand Down Expand Up @@ -218,7 +218,7 @@ extension MainViewController {
}
}

// NS BG Data Front end updater
/// NS BG Data Front end updater
func viewUpdateNSBG(sourceName: String) {
DispatchQueue.main.async {
TaskScheduler.shared.rescheduleTask(id: .minAgoUpdate, to: Date())
Expand Down
4 changes: 2 additions & 2 deletions LoopFollow/Controllers/Nightscout/CAge.swift
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import Foundation

extension MainViewController {
// NS Cage Web Call
/// NS Cage Web Call
func webLoadNSCage() {
let currentTimeString = dateTimeUtils.getDateTimeString()

Expand All @@ -24,7 +24,7 @@ extension MainViewController {
}
}

// NS Cage Response Processor
/// NS Cage Response Processor
func updateCage(data: [cageData]) {
infoManager.clearInfoData(type: .cage)
if data.count == 0 {
Expand Down
2 changes: 1 addition & 1 deletion LoopFollow/Controllers/Nightscout/DeviceStatus.swift
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ extension MainViewController {
}
}

// NS Device Status Response Processor
/// NS Device Status Response Processor
func updateDeviceStatusDisplay(jsonDeviceStatus: [[String: AnyObject]]) {
infoManager.clearInfoData(types: [.iob, .cob, .battery, .pump, .pumpBattery, .target, .isf, .carbRatio, .updated, .recBolus, .tdd])

Expand Down
Loading