size classes

release
Laurent 3 years ago
parent 152e88138b
commit 2f19388cbf
  1. 4
      LeCountdown.xcodeproj/project.pbxproj
  2. 1
      LeCountdown/CountdownScheduler.swift
  3. 63
      LeCountdown/LeCountdownApp.swift
  4. 86
      LeCountdown/Views/HomeView.swift
  5. 21
      LeCountdown/Views/PresetsView.swift

@ -107,6 +107,7 @@
C4BA2B1F299BE6A100CB4FBA /* Countdown+CoreDataProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4BA2B0E299BE61E00CB4FBA /* Countdown+CoreDataProperties.swift */; };
C4BA2B22299BE82E00CB4FBA /* AbstractSoundTimer+CoreDataProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4BA2AEF2996A11900CB4FBA /* AbstractSoundTimer+CoreDataProperties.swift */; };
C4BA2B23299BE82E00CB4FBA /* AbstractSoundTimer+CoreDataProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4BA2AEF2996A11900CB4FBA /* AbstractSoundTimer+CoreDataProperties.swift */; };
C4BA2B25299D35C100CB4FBA /* HomeView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4BA2B24299D35C100CB4FBA /* HomeView.swift */; };
C4F8B1532987FE6F005C86A5 /* LaunchWidgetLiveActivity.swift in Sources */ = {isa = PBXBuildFile; fileRef = C438C7D72981216200BF3EF9 /* LaunchWidgetLiveActivity.swift */; };
C4F8B15729891271005C86A5 /* Conductor.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4F8B15629891271005C86A5 /* Conductor.swift */; };
C4F8B15929891528005C86A5 /* forest_stream.mp3 in Resources */ = {isa = PBXBuildFile; fileRef = C4F8B15829891528005C86A5 /* forest_stream.mp3 */; };
@ -287,6 +288,7 @@
C4BA2B0C299BE61E00CB4FBA /* IntervalGroup+CoreDataClass.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "IntervalGroup+CoreDataClass.swift"; sourceTree = "<group>"; };
C4BA2B0D299BE61E00CB4FBA /* IntervalGroup+CoreDataProperties.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "IntervalGroup+CoreDataProperties.swift"; sourceTree = "<group>"; };
C4BA2B0E299BE61E00CB4FBA /* Countdown+CoreDataProperties.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Countdown+CoreDataProperties.swift"; sourceTree = "<group>"; };
C4BA2B24299D35C100CB4FBA /* HomeView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeView.swift; sourceTree = "<group>"; };
C4F8B15629891271005C86A5 /* Conductor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Conductor.swift; sourceTree = "<group>"; };
C4F8B15829891528005C86A5 /* forest_stream.mp3 */ = {isa = PBXFileReference; lastKnownFileType = audio.mp3; path = forest_stream.mp3; sourceTree = "<group>"; };
C4F8B15E298961A7005C86A5 /* ReorderableForEach.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReorderableForEach.swift; sourceTree = "<group>"; };
@ -508,6 +510,7 @@
C4F8B1D3298BF686005C86A5 /* Components */,
C4060DC1297AE73B003FAB80 /* ContentView.swift */,
C4F8B1CF298BF2E2005C86A5 /* DialView.swift */,
C4BA2B24299D35C100CB4FBA /* HomeView.swift */,
C498E59E298D4DEA00E90DE0 /* LiveTimerListView.swift */,
C4BA2B03299A42EF00CB4FBA /* NewDataView.swift */,
C4BA2B05299A8F8D00CB4FBA /* PresetsView.swift */,
@ -848,6 +851,7 @@
C4BA2B12299BE61E00CB4FBA /* IntervalGroup+CoreDataProperties.swift in Sources */,
C4BA2AF32996A11900CB4FBA /* AbstractSoundTimer+CoreDataProperties.swift in Sources */,
C4742B59298411E800D5D950 /* CountdownFormView.swift in Sources */,
C4BA2B25299D35C100CB4FBA /* HomeView.swift in Sources */,
C4BA2AF12996A11900CB4FBA /* CustomSound+CoreDataClass.swift in Sources */,
C4060DC2297AE73B003FAB80 /* ContentView.swift in Sources */,
C438C7C12980228B00BF3EF9 /* CountdownScheduler.swift in Sources */,

@ -48,7 +48,6 @@ class CountdownScheduler {
// content.sound = UNNotificationSound(named: UNNotificationSoundName(rawValue: sound))
content.sound = UNNotificationSound.criticalSoundNamed(UNNotificationSoundName(rawValue: sound), withAudioVolume: 1.0)
content.interruptionLevel = .critical
content.relevanceScore = 1.0

@ -18,8 +18,6 @@ enum BGTaskIdentifier : String {
struct LeCountdownApp: App {
let persistenceController = PersistenceController.shared
@State private var tabSelection: Int = 1
@UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
@ -32,37 +30,35 @@ struct LeCountdownApp: App {
self._registerBackgroundRefreshes()
}
#if os(iOS)
@Environment(\.horizontalSizeClass) private var horizontalSizeClass
#endif
var body: some Scene {
WindowGroup {
NavigationStack {
TabView(selection: $tabSelection) {
PresetsView(tabSelection: $tabSelection)
Group {
#if os(iOS)
if horizontalSizeClass == .compact {
CompactHomeView()
.environment(\.managedObjectContext, persistenceController.container.viewContext)
.tabItem { Label("Presets", systemImage: "globe") }
.tag(0)
ContentView<AbstractTimer>()
} else {
RegularHomeView()
.environment(\.managedObjectContext, persistenceController.container.viewContext)
.environmentObject(Conductor.maestro)
.tabItem { Label("Home", systemImage: "clock.fill") }
.tag(1)
RecordsView().environment(\.managedObjectContext, persistenceController.container.viewContext)
.tabItem { Label("Stats", systemImage: "chart.bar.fill") }
.tag(2)
}
}.tabViewStyle(.page)
#else
RegularHomeView()
.environment(\.managedObjectContext, persistenceController.container.viewContext)
#endif
}
.onReceive(NotificationCenter.default.publisher(for: UIApplication.willEnterForegroundNotification)) { _ in
self._willEnterForegroundNotification()
}
.onAppear {
self._onAppear()
}
.onOpenURL { url in
print("open URL = \(url)")
self._performActionIfPossible(url: url)
}
}
}
fileprivate func _willEnterForegroundNotification() {
@ -106,29 +102,4 @@ struct LeCountdownApp: App {
}
/// Show the appropriate tab
/// Actions are launched from the ContentView
fileprivate func _performActionIfPossible(url: URL) {
let context = persistenceController.container.viewContext
let urlString = url.absoluteString
if let timer = context.object(stringId: urlString) as? AbstractTimer {
switch timer {
case is Countdown:
self.tabSelection = 1
case is Stopwatch:
self.tabSelection = 2
case is Alarm:
self.tabSelection = 3
default:
print("url not managed, object is \(timer)")
break
}
} else {
print("url not managed: \(url)")
}
}
}

@ -0,0 +1,86 @@
//
// HomeView.swift
// LeCountdown
//
// Created by Laurent Morvillier on 15/02/2023.
//
import SwiftUI
struct CompactHomeView: View {
@Environment(\.managedObjectContext) private var viewContext
@State private var tabSelection: Int = 1
var body: some View {
NavigationStack {
TabView(selection: $tabSelection) {
PresetsView(tabSelection: $tabSelection)
.environment(\.managedObjectContext, viewContext)
.tabItem { Label("Presets", systemImage: "globe") }
.tag(0)
ContentView<AbstractTimer>()
.environment(\.managedObjectContext, viewContext)
.environmentObject(Conductor.maestro)
.tabItem { Label("Home", systemImage: "clock.fill") }
.tag(1)
RecordsView()
.environment(\.managedObjectContext, viewContext)
.tabItem { Label("Stats", systemImage: "chart.bar.fill") }
.tag(2)
}
.tabViewStyle(.page)
.onOpenURL { _ in
self.tabSelection = 1
}
}
}
}
struct RegularHomeView: View {
@Environment(\.managedObjectContext) private var viewContext
@State private var tabSelection: Int = 1
var body: some View {
NavigationStack {
TabView(selection: $tabSelection) {
PresetsView(tabSelection: $tabSelection)
.environment(\.managedObjectContext, viewContext)
.tabItem { Label("Presets", systemImage: "globe") }
.tag(0)
ContentView<AbstractTimer>()
.environment(\.managedObjectContext, viewContext)
.environmentObject(Conductor.maestro)
.tabItem { Label("Home", systemImage: "clock.fill") }
.tag(1)
RecordsView()
.environment(\.managedObjectContext, viewContext)
.tabItem { Label("Stats", systemImage: "chart.bar.fill") }
.tag(2)
}
}
.tabViewStyle(.page)
.onOpenURL { _ in
self.tabSelection = 1
}
}
}
struct CompactHomeView_Previews: PreviewProvider {
static var previews: some View {
CompactHomeView().previewDevice(PreviewDevice(rawValue: "iPhone 12 Pro"))
}
}
struct RegularHomeView_Previews: PreviewProvider {
static var previews: some View {
RegularHomeView().previewDevice(PreviewDevice(rawValue: "iPad Pro (11-inch)"))
}
}

@ -144,6 +144,9 @@ class PresetModel : ObservableObject {
struct PresetsView: View {
@Environment(\.managedObjectContext) private var viewContext
#if os(iOS)
@Environment(\.horizontalSizeClass) private var horizontalSizeClass
#endif
@StateObject var model: PresetModel = PresetModel()
@ -156,6 +159,22 @@ struct PresetsView: View {
GridItem(spacing: 10.0),
]
fileprivate func _columnCount() -> Int {
#if os(iOS)
if horizontalSizeClass == .compact {
return 2
} else {
return 3
}
#else
return 3
#endif
}
fileprivate func _columns() -> [GridItem] {
return (0..<self._columnCount()).map { _ in GridItem(spacing: 10.0) }
}
var body: some View {
ScrollView {
@ -165,7 +184,7 @@ struct PresetsView: View {
.font(.callout)
LazyVGrid(
columns: columns,
columns: self._columns(),
spacing: 10.0
) {

Loading…
Cancel
Save