Visual changes

main
Laurent 3 years ago
parent 1d9d2e5ce1
commit d0b31d2c3e
  1. 4
      LeCountdown.xcodeproj/project.pbxproj
  2. 7
      LeCountdown/Intent/TimerShortcuts.swift
  3. 11
      LeCountdown/Views/ContentView.swift
  4. 181
      LeCountdown/Views/LiveTimerListView.swift
  5. 13
      LeCountdown/Views/PresetsView.swift
  6. 25
      LeCountdown/Views/Reusable/SeparatorView.swift

@ -167,6 +167,7 @@
C4E5D67C29B8D4A5008E7465 /* Low_Tom_Disto_Earth.wav in Resources */ = {isa = PBXBuildFile; fileRef = C4E5D67B29B8D4A5008E7465 /* Low_Tom_Disto_Earth.wav */; };
C4E5D68029B8FD93008E7465 /* Store.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4E5D67F29B8FD93008E7465 /* Store.swift */; };
C4E5D68229B93583008E7465 /* PVP_Stab_Oneshot_Bleep_Em.wav in Resources */ = {isa = PBXBuildFile; fileRef = C4E5D68129B93583008E7465 /* PVP_Stab_Oneshot_Bleep_Em.wav */; };
C4E5D68429BB2425008E7465 /* SeparatorView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4E5D68329BB2425008E7465 /* SeparatorView.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 */; };
@ -383,6 +384,7 @@
C4E5D67B29B8D4A5008E7465 /* Low_Tom_Disto_Earth.wav */ = {isa = PBXFileReference; lastKnownFileType = audio.wav; path = Low_Tom_Disto_Earth.wav; sourceTree = "<group>"; };
C4E5D67F29B8FD93008E7465 /* Store.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Store.swift; sourceTree = "<group>"; };
C4E5D68129B93583008E7465 /* PVP_Stab_Oneshot_Bleep_Em.wav */ = {isa = PBXFileReference; lastKnownFileType = audio.wav; path = PVP_Stab_Oneshot_Bleep_Em.wav; sourceTree = "<group>"; };
C4E5D68329BB2425008E7465 /* SeparatorView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SeparatorView.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>"; };
@ -774,6 +776,7 @@
C4742B5A298414B000D5D950 /* ImageSelectionView.swift */,
C4F8B1D1298BF646005C86A5 /* PermissionAlertView.swift */,
C4F8B15E298961A7005C86A5 /* ReorderableForEach.swift */,
C4E5D68329BB2425008E7465 /* SeparatorView.swift */,
C4F8B165298A9ABB005C86A5 /* SoundImageFormView.swift */,
C4BA2AD52993F62700CB4FBA /* SoundSelectionView.swift */,
C4BA2ADA299549BC00CB4FBA /* TimerModel.swift */,
@ -1023,6 +1026,7 @@
C4E5D67A29B8C5A1008E7465 /* VolumeView.swift in Sources */,
C4BA2B04299A42EF00CB4FBA /* NewDataView.swift in Sources */,
C4BA2B4C299FCE0C00CB4FBA /* Stopwatch+CoreDataProperties.swift in Sources */,
C4E5D68429BB2425008E7465 /* SeparatorView.swift in Sources */,
C4E5D67429B88734008E7465 /* DelaySoundPlayer.swift in Sources */,
C438C7FF2981300500BF3EF9 /* IntentDataProvider.swift in Sources */,
C4E5D66629B73AED008E7465 /* StartTimerIntent.swift in Sources */,

@ -11,11 +11,12 @@ struct TimerShortcuts: AppShortcutsProvider {
static var appShortcuts: [AppShortcut] {
AppShortcut(intent: StartTimerIntent(), phrases: [
"Start \(.applicationName)",
"Launch \(.applicationName)",
"\(.applicationName) \(\.$timer)",
"Start \(\.$timer) with \(.applicationName)",
"Launch \(\.$timer) with \(.applicationName)",
"\(.applicationName) \(\.$timer)"])
"Start \(.applicationName)",
"Launch \(.applicationName)"
])
}
}

@ -119,6 +119,7 @@ struct ContentView<T : AbstractTimer>: View {
LiveTimerListView()
.environment(\.managedObjectContext, viewContext)
.environmentObject(conductor)
.padding(.horizontal, 12.0)
.foregroundColor(.white)
.background(Color(white: 0.1))
.cornerRadius(32.0, corners: [.topRight, .topLeft])
@ -137,8 +138,6 @@ struct ContentView<T : AbstractTimer>: View {
PermissionAlertView()
}
.sheet(isPresented: $boringContext.isShowingNewData, content: {
// self._newView(isPresented: $boringContext.isShowingNewData)
// .environment(\.managedObjectContext, viewContext)
})
.toolbar {
ToolbarItem(placement: .navigationBarTrailing) {
@ -293,14 +292,6 @@ fileprivate extension Countdown {
return endDate != nil
}
// var colorForStatus: Color {
// if isLive {
// return Color(red: 0.9, green: 1.0, blue: 0.95)
// } else {
// return Color(red: 0.9, green: 0.95, blue: 1.0)
// }
// }
}
struct ContentView_Previews: PreviewProvider {

@ -21,19 +21,9 @@ class LiveStopwatchModel: ObservableObject {
}
}
struct SeparatorView: View {
var body: some View {
Spacer()
.frame(minWidth: 0.0, maxWidth: .infinity, minHeight: 1.0, maxHeight: 1.0)
.background(Color(white: 0.85))
.padding(.vertical, 8.0)
}
}
fileprivate let liveViewSize: CGFloat = 70.0
fileprivate let timerFontSize: CGFloat = 32.0
fileprivate let actionButtonFontSize: CGFloat = 36.0
struct TimeView: View {
@ -61,58 +51,51 @@ struct LiveStopwatchView: View {
let running = (self.model.endDate == nil)
VStack(alignment: .trailing) {
HStack {
if running {
TimelineView(.periodic(from: self.date, by: 0.01)) { context in
TimeView(text: self._formattedDuration(date: context.date))
VStack(alignment: .leading) {
if running {
TimelineView(.periodic(from: self.date, by: 0.01)) { context in
TimeView(text: self._formattedDuration(date: context.date))
}
} else {
let duration = self.model.endDate?.timeIntervalSince(self.date) ?? 0.0
TimeView(text: duration.hourMinuteSecondHS)
}
} else {
let duration = self.model.endDate?.timeIntervalSince(self.date) ?? 0.0
TimeView(text: duration.hourMinuteSecondHS)
Text(stopwatch.displayName.uppercased())
}
Spacer()
// if running {
//
//// Button {
//// self.model.stop(stopwatch)
//// } label: {
////
//// Image(systemName: "stop.circle.fill")
//// .font(.title)
//// .foregroundColor(.white)
//// .cornerRadius(8.0)
//// .frame(minWidth: 0.0, maxWidth: 60.0, minHeight: 0.0, maxHeight: .infinity)
//// }.background(.red)
//
// } else {
// GreenCheckmarkView()
// }
// SeparatorView()
HStack {
Group {
if !running {
GreenCheckmarkView()
}
Text(stopwatch.displayName.uppercased())
}
}.onTapGesture {
withAnimation {
if self.model.endDate == nil {
self.model.stop(stopwatch)
} else {
self._dismiss()
Image(systemName: "stop.circle.fill")
.foregroundColor(.accentColor)
}
}
}.font(.system(size: actionButtonFontSize))
}
.frame(height: liveViewSize)
// .foregroundColor(.white)
.monospaced()
// .background(Color(white: 0.2))
// .cornerRadius(16.0)
.frame(height: liveViewSize)
.contentShape(Rectangle())
.onTapGesture {
self._actionHandler()
}
}
fileprivate func _actionHandler() {
withAnimation {
if self.model.endDate == nil {
self.model.stop(stopwatch)
} else {
self._dismiss()
}
}
}
fileprivate func _dismiss() {
conductor.removeLiveTimer(id: self.stopwatch.stringId)
}
@ -134,50 +117,58 @@ struct LiveCountdownView: View {
var body: some View {
TimelineView(.periodic(from: self.date, by: 0.01)) { context in
VStack(alignment: .trailing) {
HStack {
let running = self.date > context.date
let cancelled = conductor.cancelledCountdowns.contains(where: { $0 == self.countdown.stringId })
if cancelled {
TimeView(text: NSLocalizedString("Cancelled", comment: ""))
} else if running {
TimeView(text: self._formattedDuration(date: context.date))
} else {
TimeView(text: self.date.formatted(date: .omitted, time: .shortened))
VStack(alignment: .leading) {
if cancelled {
TimeView(text: NSLocalizedString("Cancelled", comment: ""))
} else if running {
TimeView(text: self._formattedDuration(date: context.date))
} else {
TimeView(text: self.date.formatted(date: .omitted, time: .shortened))
}
Text(self.countdown.displayName.uppercased())
}
// SeparatorView()
HStack {
Spacer()
Group {
if cancelled {
XMarkView()
Image(systemName: "xmark.circle").foregroundColor(.accentColor)
} else if !running {
GreenCheckmarkView()
} else {
Image(systemName: "xmark.circle.fill").foregroundColor(.accentColor)
}
Text(self.countdown.displayName.uppercased())
// .padding(.top, 2.0)
}
}.font(.system(size: actionButtonFontSize))
}
}
.contentShape(Rectangle()) // make the onTap react everywhere
.contentShape(Rectangle())
.onTapGesture {
withAnimation {
if conductor.currentCountdowns[self.countdown.stringId] != nil {
self._cancelCountdown()
} else {
self._dismiss()
}
}
self._actionHandler()
}
.frame(height: liveViewSize)
// .foregroundColor(.white)
.monospaced()
// .background(Color(white: 0.2))
// .cornerRadius(16.0)
}
fileprivate func _actionHandler() {
withAnimation {
if conductor.currentCountdowns[self.countdown.stringId] != nil {
self._cancelCountdown()
} else {
self._dismiss()
}
}
}
fileprivate func _dismiss() {
// conductor.cancelCountdown(id: self.countdown.stringId)
conductor.removeLiveTimer(id: self.countdown.stringId)
}
@ -199,31 +190,27 @@ struct LiveTimerListView: View {
var body: some View {
// ScrollView {
// ScrollView {
VStack {
LazyVGrid(
columns: self._columns(),
alignment: .trailing,
spacing: 0.0
) {
ForEach(conductor.liveTimers) { liveTimer in
ForEach(conductor.liveTimers) { liveTimer in
if let timer: AbstractTimer = liveTimer.timer(context: self.viewContext) {
if let timer: AbstractTimer = liveTimer.timer(context: self.viewContext) {
switch timer {
case let cd as Countdown:
LiveCountdownView(countdown: cd, date: liveTimer.date)
case let sw as Stopwatch:
LiveStopwatchView(stopwatch: sw, date: liveTimer.date)
default:
Text("unmanaged timer: \(timer)")
}
switch timer {
case let cd as Countdown:
LiveCountdownView(countdown: cd, date: liveTimer.date)
case let sw as Stopwatch:
LiveStopwatchView(stopwatch: sw, date: liveTimer.date)
default:
Text("unmanaged timer: \(timer)")
}
}
// }
}
}.padding()
}
@ -231,7 +218,7 @@ struct LiveTimerListView: View {
fileprivate func _columnCount() -> Int {
#if os(iOS)
if UIDevice.isPhoneIdiom {
return 2
return 18
} else {
return 3
}

@ -55,19 +55,15 @@ struct PresetsView: View {
Text("Create countdown".uppercased())
.frame(maxWidth: .infinity)
.frame(height: 40.0)
}
}.monospaced().buttonStyle(.bordered)
Button {
self.isShowingNewStopwatch = true
} label: {
Text("Create stopwatch".uppercased())
.frame(maxWidth: .infinity)
.frame(height: 40.0)
}
}.padding(.horizontal).monospaced().buttonStyle(.bordered)
VStack(alignment: .leading) {
SeparatorView()
}.monospaced().buttonStyle(.bordered)
Text("Presets")
.font(.system(.title, weight: .heavy))
@ -77,7 +73,8 @@ struct PresetsView: View {
.font(.callout)
}.padding(.horizontal)
.padding(.bottom)
LazyVGrid(
columns: self._columns(),
alignment: .leading,

@ -0,0 +1,25 @@
//
// SeparatorView.swift
// LeCountdown
//
// Created by Laurent Morvillier on 10/03/2023.
//
import SwiftUI
struct SeparatorView: View {
var body: some View {
Spacer()
.frame(minWidth: 0.0, maxWidth: .infinity, minHeight: 1.0, maxHeight: 1.0)
.background(Color(white: 0.85))
.padding(.vertical, 8.0)
}
}
struct SeparatorView_Previews: PreviewProvider {
static var previews: some View {
SeparatorView()
}
}
Loading…
Cancel
Save