From 1f23a55b51b443fa2c73cfdec019af7e2621ae06 Mon Sep 17 00:00:00 2001 From: breadone Date: Wed, 26 Jun 2024 00:24:16 +1200 Subject: [PATCH] Added timers for the cue card view (can be controlled) minor other adjustments --- OnCue.xcodeproj/project.pbxproj | 6 ++++ OnCue/Model/TimerManager.swift | 42 +++++++++++++++++++++++++++ OnCue/View/CardsView.swift | 2 +- OnCue/View/ProjectSlideshowView.swift | 19 +++++++++--- OnCue/View/SettingsView.swift | 34 +++++++++++++--------- Shared/Preferences.swift | 2 ++ 6 files changed, 87 insertions(+), 18 deletions(-) create mode 100644 OnCue/Model/TimerManager.swift diff --git a/OnCue.xcodeproj/project.pbxproj b/OnCue.xcodeproj/project.pbxproj index 88dbbf9..1218aca 100644 --- a/OnCue.xcodeproj/project.pbxproj +++ b/OnCue.xcodeproj/project.pbxproj @@ -7,6 +7,8 @@ objects = { /* Begin PBXBuildFile section */ + 460D7DF62C2AE788002B623C /* TimerManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 460D7DF52C2AE788002B623C /* TimerManager.swift */; }; + 460D7DF72C2AE788002B623C /* TimerManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 460D7DF52C2AE788002B623C /* TimerManager.swift */; }; 464787CB2C269CAF00A9C462 /* TeleprompterView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 464787CA2C269CAF00A9C462 /* TeleprompterView.swift */; }; 464787CC2C26A2E100A9C462 /* ColorModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 46AD30F12C2672BD00486C25 /* ColorModel.swift */; }; 464787CD2C26A2E500A9C462 /* PreviewData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 46AD30F32C267D6400486C25 /* PreviewData.swift */; }; @@ -63,6 +65,7 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ + 460D7DF52C2AE788002B623C /* TimerManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimerManager.swift; sourceTree = ""; }; 464787CA2C269CAF00A9C462 /* TeleprompterView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TeleprompterView.swift; sourceTree = ""; }; 46AD30B72C26557500486C25 /* OnCue.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = OnCue.app; sourceTree = BUILT_PRODUCTS_DIR; }; 46AD30BA2C26557500486C25 /* OnCueApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnCueApp.swift; sourceTree = ""; }; @@ -175,6 +178,7 @@ 46AD30BE2C26557500486C25 /* Item.swift */, 46AD30E12C2656CB00486C25 /* OCCard.swift */, 46AD30E42C2656D100486C25 /* OCProject.swift */, + 460D7DF52C2AE788002B623C /* TimerManager.swift */, ); path = Model; sourceTree = ""; @@ -339,6 +343,7 @@ 46AD30BB2C26557500486C25 /* OnCueApp.swift in Sources */, 46AD30E52C2656D100486C25 /* OCProject.swift in Sources */, 46AD30E22C2656CB00486C25 /* OCCard.swift in Sources */, + 460D7DF62C2AE788002B623C /* TimerManager.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -352,6 +357,7 @@ 464787CD2C26A2E500A9C462 /* PreviewData.swift in Sources */, 46AD30D12C26559B00486C25 /* OnCuePresenterApp.swift in Sources */, 46AD30E62C2656D100486C25 /* OCProject.swift in Sources */, + 460D7DF72C2AE788002B623C /* TimerManager.swift in Sources */, 464787CC2C26A2E100A9C462 /* ColorModel.swift in Sources */, 46D3E1402C26D6430060722E /* Constants.swift in Sources */, ); diff --git a/OnCue/Model/TimerManager.swift b/OnCue/Model/TimerManager.swift new file mode 100644 index 0000000..017b8d1 --- /dev/null +++ b/OnCue/Model/TimerManager.swift @@ -0,0 +1,42 @@ +// +// TimerManager.swift +// OnCue +// +// Created by Pradyun Setti on 25/06/2024. +// + +import Foundation + +public class TimerManager: ObservableObject { + @Published public var secondsElapsed: Int = 0 + @Published public var formattedTime: String = "00:00" + + private var timer: Timer? = nil + + public func startTimer() { + self.timer?.invalidate() + self.timer = Timer.scheduledTimer(timeInterval: 1, + target: self, + selector: #selector(update), + userInfo: nil, + repeats: true) + } + + public func stopTimer() { + self.timer?.invalidate() + self.timer = nil + } + + @objc public func update() { + secondsElapsed += 1 + + formattedTime = formatSeconds(secondsElapsed) + } + + private func formatSeconds(_ seconds: Int) -> String { + let minutes = floor(Double(seconds) / 60) + let rSeconds = Double(seconds) - (minutes * 60) + + return String(format: "%02.0f:%02.0f", minutes, rSeconds) + } +} diff --git a/OnCue/View/CardsView.swift b/OnCue/View/CardsView.swift index 4bf500d..7c5b69d 100644 --- a/OnCue/View/CardsView.swift +++ b/OnCue/View/CardsView.swift @@ -32,7 +32,7 @@ struct CardsView: View { .swipeActions { Button(role: .destructive) { } label: { Image(systemName: "trash.fill") } .background(Color.red) - Button { editCardText = card.content; editCard.toggle() } label: { Image(systemName: "pencil") } + Button { editCardText = card.content; editCard.toggle() } label: { Image(systemName: "pencil") }.tint(.blue) } } } header: { diff --git a/OnCue/View/ProjectSlideshowView.swift b/OnCue/View/ProjectSlideshowView.swift index 6f5faac..0c9672e 100644 --- a/OnCue/View/ProjectSlideshowView.swift +++ b/OnCue/View/ProjectSlideshowView.swift @@ -9,9 +9,21 @@ import SwiftUI struct ProjectSlideshowView: View { let project: OCProject - @State private var textSize = 25.0 + @AppStorage(Preferences.cueDefaultSize) private var textSize = 25.0 + @AppStorage(Preferences.showTimers) var showTimers = true + @StateObject private var timer = TimerManager() var body: some View { + if showTimers { + mainView + .navigationTitle(timer.formattedTime) + .onAppear { timer.startTimer() } + } else { + mainView + } + } + + var mainView: some View { TabView() { ForEach(project.sortedCards) { card in VStack(alignment: .leading) { @@ -22,8 +34,7 @@ struct ProjectSlideshowView: View { .frame(height: 550) Spacer() } - .navigationTitle("\(card.index+1)") - .navigationBarTitleDisplayMode(.inline) + .navigationBarTitleDisplayMode(.inline) } } .tabViewStyle(PageTabViewStyle(indexDisplayMode: .always)) @@ -35,7 +46,7 @@ struct ProjectSlideshowView: View { } label: { Image(systemName: "ellipsis.circle") } - + } ToolbarItem(placement: .topBarTrailing) { NavigationLink(destination: { CardsView(project: project) }) { diff --git a/OnCue/View/SettingsView.swift b/OnCue/View/SettingsView.swift index 0e455cb..ead28e8 100644 --- a/OnCue/View/SettingsView.swift +++ b/OnCue/View/SettingsView.swift @@ -23,6 +23,7 @@ struct SettingsView: View { // @State private var themesColor: Color = .blue @AppStorage(Preferences.themeColour) var themesColor = Color.blue.toHex()! + @AppStorage(Preferences.showTimers) var showTimers = true var body: some View { NavigationView { @@ -45,24 +46,31 @@ struct SettingsView: View { var generalSettings: some View { Section { - Text("Theme Color") + HStack { - ForEach(Constants.colors, id: \.self) { color in - if themesColor == color.toHex()! { - ZStack { - Circle() - .foregroundStyle(color) -// .strokeBorder(Color.white,lineWidth: 4) -// .background(Circle().foregroundStyle(color)) - Image(systemName: "checkmark") + Text("Theme Color") + // TODO: redo this as a grid + ScrollView(.horizontal) { + HStack { + ForEach(Constants.colors, id: \.self) { color in + if themesColor == color.toHex()! { + ZStack { + Circle() + .foregroundStyle(color) +// .strokeBorder(Color.white,lineWidth: 4) +// .background(Circle().foregroundStyle(color)) + Image(systemName: "checkmark") + } + } else { + Circle() + .foregroundStyle(color) + .onTapGesture { themesColor = color.toHex()! } + } } - } else { - Circle() - .foregroundStyle(color) - .onTapGesture { themesColor = color.toHex()! } } } } + Toggle("Show Timers", isOn: $showTimers) } header: { Text("General") } } diff --git a/Shared/Preferences.swift b/Shared/Preferences.swift index d546415..7de4e28 100644 --- a/Shared/Preferences.swift +++ b/Shared/Preferences.swift @@ -18,4 +18,6 @@ public struct Preferences { static let cueDefaultSize = "cueDefaultSize" static let themeColour = "themeColour" + + static let showTimers = "showTimers" }