Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
2ef9032
Update project.pbxproj
panandafog Mar 21, 2025
0454f9a
New charts
panandafog Aug 31, 2025
5a181af
Edit mode in RecordingsView
panandafog Sep 1, 2025
7300152
Chart paddings update
panandafog Sep 1, 2025
a938235
Less chart values
panandafog Sep 16, 2025
b5f109a
Delete button with safe area insets
panandafog Sep 16, 2025
051626a
Tab bar delete button
panandafog Sep 16, 2025
62c0906
Remove old charts
panandafog Sep 17, 2025
6130211
Less chart values, new preview
panandafog Sep 17, 2025
a25db32
Now recording chart starts from first entry datetime
panandafog Sep 17, 2025
9ef071e
Refactor recordings processing and AxesSummaryViewExtended previews
panandafog Sep 19, 2025
1100380
Merge pull request #6 from panandafog/charts
panandafog Sep 19, 2025
27c258a
Remove delete confirmation
panandafog Sep 19, 2025
ee85647
Toggles accent color
panandafog Sep 19, 2025
b1a0f7a
Buttons styles
panandafog Sep 19, 2025
966eec5
NewRecordingView animations
panandafog Sep 19, 2025
ed5be58
Memory monitor created
panandafog Sep 21, 2025
f9ecd82
Active recording duplicate fix
panandafog Sep 21, 2025
20c0fe8
RecordingsView memory handling
panandafog Sep 22, 2025
719104d
Merge pull request #7 from panandafog/memory_management
panandafog Sep 22, 2025
45b2e59
New recording list style
panandafog Sep 22, 2025
38b5b07
MeasurementSummaryView memory handling, debug settings
panandafog Sep 22, 2025
c20cc92
Merge pull request #8 from panandafog/memory_management
panandafog Sep 22, 2025
f9ceed2
Recordings metadata
panandafog Sep 22, 2025
cca4e2d
Recordings cache
panandafog Sep 22, 2025
f25c838
ActiveRecordingManager created
panandafog Sep 28, 2025
bbe08d7
Debug rec info
panandafog Sep 28, 2025
e46c7ea
Revert "ActiveRecordingManager created"
panandafog Sep 29, 2025
85c12b3
Store active recording in deque
panandafog Sep 29, 2025
d843a46
Active recording timer
panandafog Sep 29, 2025
d99f80c
Refactor cache
panandafog Sep 29, 2025
55af45d
Merge pull request #9 from panandafog/optimization
panandafog Sep 29, 2025
bf7cae8
Recording export refactoring
panandafog Sep 29, 2025
3266611
Marks and icons for measurement types
panandafog Sep 29, 2025
b2e832f
Fullscreen charts
panandafog Oct 2, 2025
795a6d1
Fullscreen charts styling
panandafog Oct 3, 2025
baaa5c1
Fullscreen charts time format
panandafog Oct 3, 2025
7b7fddd
Debug samples, buttons improvements
panandafog Oct 3, 2025
90353fe
Recording preview timer fix
panandafog Oct 3, 2025
821018f
Chart leading delay fix
panandafog Oct 3, 2025
2cc555c
Recordings sort
panandafog Oct 3, 2025
7e2cf24
Merge pull request #10 from panandafog/big_charts
panandafog Oct 3, 2025
443bf42
Export modifier
panandafog Oct 3, 2025
2828e33
Description
panandafog Oct 3, 2025
61d4cf2
Version 0.2.0
panandafog Oct 3, 2025
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
106 changes: 82 additions & 24 deletions Accelerometer.xcodeproj/project.pbxproj

Large diffs are not rendered by default.

10 changes: 5 additions & 5 deletions Accelerometer.xcworkspace/xcshareddata/swiftpm/Package.resolved

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Accelerometer/AccelerometerApp.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ struct AccelerometerApp: App {

init() {
self.measurer = Measurer(settings: settings)
self.recorder = Recorder(measurer: measurer)
self.recorder = Recorder(measurer: measurer, settings: settings)
}

var body: some Scene {
Expand Down
22 changes: 14 additions & 8 deletions Accelerometer/ContentView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,44 +8,50 @@
import SwiftUI

struct ContentView: View {

@EnvironmentObject var recorder: Recorder
@State private var selectedTab = 0

var body: some View {
TabView {
TabView(selection: $selectedTab) {
NavigationView {
MeasurementsView()
.navigationTitle(Text("Measurements"))
.navigationTitle("Measurements")
}
.phoneOnlyStackNavigationView()
.tabItem {
Label("Measurements", systemImage: "list.bullet")
}

.tag(0)

NavigationView {
RecordingsView()
.navigationTitle(Text("Recordings"))
.navigationTitle("Recordings")
}
.phoneOnlyStackNavigationView()
.tabItem {
Label("Recordings", systemImage: "play")
}

.tag(1)

NavigationView {
SettingsView()
.navigationTitle(Text("Settings"))
.navigationTitle("Settings")
}
.navigationViewStyle(.stack)
.tabItem {
Label("Settings", systemImage: "gear")
}
.tag(2)
}
}
}


struct ContentView_Previews: PreviewProvider {

static let settings = Settings()
static let measurer = Measurer(settings: settings)
static let recorder = Recorder(measurer: measurer)
static let recorder = Recorder(measurer: measurer, settings: settings)

static var previews: some View {
ContentView()
Expand Down
22 changes: 21 additions & 1 deletion Accelerometer/Extensions/Bool.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,29 @@
//

import Foundation
import Charts

extension Bool: Comparable {
extension Bool: @retroactive Comparable {
public static func < (lhs: Bool, rhs: Bool) -> Bool {
(lhs == false) && (rhs == true)
}
}

extension Bool: @retroactive Plottable {
public typealias PrimitivePlottable = Double

public var primitivePlottable: Double {
self ? 1.0 : 0.0
}

public init?(primitivePlottable: Double) {
switch primitivePlottable {
case 0.0:
self = false
case 1.0:
self = true
default:
return nil
}
}
}
30 changes: 27 additions & 3 deletions Accelerometer/Extensions/View.swift
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,11 @@ extension View {
var statusBarOrientation: UIInterfaceOrientation? {
get {
guard let orientation = UIApplication.shared.windows.first?.windowScene?.interfaceOrientation else {
#if DEBUG
#if DEBUG
fatalError("Could not obtain UIInterfaceOrientation from a valid windowScene")
#else
#else
return nil
#endif
#endif
}
return orientation
}
Expand All @@ -40,6 +40,30 @@ extension View {
self
}
}

func exportable(
isPresented: Binding<Bool>,
url: Binding<URL?>,
filename: String
) -> some View {
modifier(ExportModifier(
isPresented: isPresented,
url: url,
filename: filename
))
}

func exportable(
isPresented: Binding<Bool>,
url: Binding<URL?>,
measurementType: MeasurementType
) -> some View {
modifier(ExportModifier(
isPresented: isPresented,
url: url,
measurementType: measurementType
))
}
}

struct RoundedCorner: Shape {
Expand Down
158 changes: 60 additions & 98 deletions Accelerometer/Measurements/Axes/AxesSummaryViewExtended.swift
Original file line number Diff line number Diff line change
Expand Up @@ -66,113 +66,75 @@ struct AxesSummaryViewExtended: View {
}
}

// MARK: - Previews

struct AxesSummaryViewExtended_Previews: PreviewProvider {

static let settings = Settings()
// MARK: Test Measurers

// TODO: refactor this
static let measurer1: Measurer = {
let measurer = Measurer(settings: settings)
var axes = TriangleAxes.zero
axes.displayableAbsMax = 1.0
measurer.saveData(
axesType: TriangleAxes.self,
measurementType: .userAcceleration,
values: [
.x: 0,
.y: 0,
.z: 0
]
)
measurer.saveData(
axesType: TriangleAxes.self,
measurementType: .magneticField,
values: [
.x: 0,
.y: 0,
.z: 0
]
)
return measurer
}()
struct MeasurerScenario {
let title: String
let measurer: Measurer
}

static let measurer2: Measurer = {
let measurer = Measurer(settings: settings)
var axes = TriangleAxes.zero
axes.displayableAbsMax = 1.0
measurer.saveData(
axesType: TriangleAxes.self,
measurementType: .userAcceleration,
values: [
.x: 0.5,
.y: 0.5,
.z: 0.5
]
)
measurer.saveData(
axesType: TriangleAxes.self,
measurementType: .magneticField,
values: [
.x: 100,
.y: 100,
.z: 100
]
)
return measurer
}()
private static let settings = Settings()

static let measurer3: Measurer = {
let measurer = Measurer(settings: settings)
var axes = TriangleAxes.zero
axes.displayableAbsMax = 1.0
measurer.saveData(
axesType: TriangleAxes.self,
measurementType: .userAcceleration,
values: [
.x: 1,
.y: 1,
.z: 1
]
)
measurer.saveData(
axesType: TriangleAxes.self,
measurementType: .magneticField,
values: [
.x: 200,
.y: 200,
.z: 200
]
)
return measurer
}()
private static func makeMeasurer(x: Double, y: Double, z: Double) -> Measurer {
let m = Measurer(settings: settings)
m.saveData(axesType: TriangleAxes.self, measurementType: .userAcceleration,
values: [.x: x, .y: y, .z: z])
m.saveData(axesType: TriangleAxes.self, measurementType: .magneticField,
values: [.x: x * 200, .y: y * 200, .z: z * 200])
return m
}

private static let scenarios: [MeasurerScenario] = [
MeasurerScenario(title: "Zero", measurer: makeMeasurer(x: 0, y: 0, z: 0)),
MeasurerScenario(title: "Half-Max",measurer: makeMeasurer(x: 0.5, y: 0.5, z: 0.5)),
MeasurerScenario(title: "Full-Max",measurer: makeMeasurer(x: 1, y: 1, z: 1))
]

// MARK: Preview

static var previews: some View {
Group {
AxesSummaryViewExtended(type: .userAcceleration)
.padding()
.previewLayout(.sizeThatFits)
.environmentObject(measurer1)
AxesSummaryViewExtended(type: .userAcceleration)
.padding()
.previewLayout(.sizeThatFits)
.environmentObject(measurer2)
AxesSummaryViewExtended(type: .userAcceleration)
.padding()
.previewLayout(.sizeThatFits)
.environmentObject(measurer3)
AxesSummaryViewExtended(type: .magneticField)
.padding()
.previewLayout(.sizeThatFits)
.environmentObject(measurer1)
AxesSummaryViewExtended(type: .magneticField)
.padding()
.previewLayout(.sizeThatFits)
.environmentObject(measurer2)
AxesSummaryViewExtended(type: .magneticField)
.padding()
.previewLayout(.sizeThatFits)
.environmentObject(measurer3)
ForEach([MeasurementType.userAcceleration, .magneticField], id: \.self) { type in
PreviewSection(type: type, scenarios: scenarios)
}
}
.environmentObject(settings)
}
}

// MARK: Helper Views

private struct PreviewSection: View {
let type: MeasurementType
let scenarios: [AxesSummaryViewExtended_Previews.MeasurerScenario]

var body: some View {
VStack(alignment: .leading, spacing: 10) {
Text(type.name.capitalizingFirstLetter())
.font(.title2)
.padding(.bottom)

VStack(spacing: 20) {
ForEach(scenarios, id: \.title) { scenario in
VStack(spacing: 8) {
Text(scenario.title)
.font(.caption)
AxesSummaryViewExtended(type: type)
.environmentObject(scenario.measurer)
.padding()
.background(Color(.systemBackground))
.cornerRadius(6)
.shadow(radius: 1)
}
}
}
}
.padding()
.previewDisplayName(type.name.capitalizingFirstLetter())
.previewLayout(.sizeThatFits)
}
}
20 changes: 13 additions & 7 deletions Accelerometer/Measurements/MeasurementSummaryView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,15 @@ struct MeasurementSummaryView: View {
}

var recordButton: some View {
let enabled = !recorder.recordingInProgress
let text = enabled ? "Start recording this value" : "Recording is already enabled"
let backgroundColor: Color = enabled ? .enabledButton : .disabledButton
let enabled = !recorder.recordingInProgress && recorder.hasEnoughMemory

let text = if !recorder.hasEnoughMemory {
"Not enough memory"
} else if recorder.recordingInProgress {
"Recording is already started"
} else {
"Start recording this value"
}

return Button(
action: {
Expand All @@ -35,10 +41,10 @@ struct MeasurementSummaryView: View {
.foregroundColor(.background)
}
)
.buttonStyle(.glassProminent)
.controlSize(.large)
.disabled(!enabled)
.padding(.defaultPadding)
.background(backgroundColor)
.cornerRadius(.defaultCornerRadius)
}

var body: some View {
Expand Down Expand Up @@ -99,12 +105,12 @@ struct MeasurementSummaryView_Previews: PreviewProvider {
}()

static let recorder1: Recorder = {
let recorder = Recorder(measurer: measurer)
let recorder = Recorder(measurer: measurer, settings: settings)
return recorder
}()

static let recorder2: Recorder = {
let recorder = Recorder(measurer: measurer)
let recorder = Recorder(measurer: measurer, settings: settings)
recorder.record(measurements: [.acceleration])
return recorder
}()
Expand Down
Loading
Loading