Merge branch 'video' into carplay

This commit is contained in:
leminlimez committed 2025-06-21 13:47:17 -04:00
commit 759597dfb2
11 files changed
+6251 -102

No files matched your search

@@ -11,14 +11,33 @@ import AVKit
struct VideoView: View {
@ObservedObject var pbManager = PosterBoardManager.shared
@AppStorage("ignoreDurationLimit") var ignoreDurationLimit: Bool = false
@State var selectedVideo: PhotosPickerItem?
@State private var currentPage: Int = 0
@State private var currentDate = Date()
private let timer = Timer.publish(every: 1, on: .main, in: .common).autoconnect() // update every second
private var dateFormatter: DateFormatter {
let formatter = DateFormatter()
formatter.dateFormat = "EEEE, MMMM d"
return formatter
}
private var timeFormatter: DateFormatter {
let formatter = DateFormatter()
if Locale.current.hourCycle == .zeroToEleven || Locale.current.hourCycle == .oneToTwelve {
formatter.dateFormat = "h:mm"
} else {
formatter.dateFormat = "HH:mm"
}
return formatter
}
var body: some View {
VStack {
GeometryReader { geom in
TabView {
ForEach(pbManager.videos) { vid in
TabView(selection: $currentPage) {
ForEach(Array(pbManager.videos.enumerated()), id: \.offset) { idx, vid in
ZStack {
switch vid.loadState {
case .unknown:
@@ -30,6 +49,17 @@ struct VideoView: View {
.scaledToFill()
.frame(width: geom.size.width * 0.7, height: geom.size.height * 0.8)
.clipped()
VStack {
Text(dateFormatter.string(from: currentDate))
.shadow(radius: 10)
Text(timeFormatter.string(from: currentDate))
.font(.system(size: 75, weight: .semibold, design: .rounded))
.shadow(radius: 10)
Spacer()
}
.padding(.top, 45)
.foregroundStyle(.white)
case .failed:
Text("Failed")
}
@@ -38,6 +68,7 @@ struct VideoView: View {
.shadow(radius: 5)
.background(Color.black.opacity(0.6))
.cornerRadius(24)
.tag(idx)
.overlay {
RoundedRectangle(cornerRadius: 24)
.stroke(.gray, lineWidth: 4)
@@ -50,22 +81,30 @@ struct VideoView: View {
.overlay(
// Loops Button
Button(action: {
if let index = pbManager.videos.firstIndex(of: vid) {
pbManager.videos[index].autoReverses = !vid.autoReverses
}
pbManager.videos[idx].autoReverses = !vid.autoReverses
}) {
Image(systemName: "arrow.left.arrow.right.circle")
.font(.title)
.foregroundStyle(.black)
.foregroundStyle(Color(uiColor: .label))
.background {
Circle()
.foregroundStyle(vid.autoReverses ? .blue : .white)
if vid.autoReverses {
Circle()
.foregroundStyle(.blue.opacity(0.8))
.shadow(radius: 5)
} else {
Circle()
.foregroundStyle(.regularMaterial)
.shadow(radius: 5)
}
}
}.offset(x: 8, y: -8),
alignment: .topTrailing
)
}
.onDelete(perform: removeVideo)
.onReceive(timer) { input in
currentDate = input
}
// MARK: Select Photo Option
if selectedVideo == nil && pbManager.videos.count < 5 {
@@ -89,6 +128,7 @@ struct VideoView: View {
.shadow(radius: 5)
.background(Color.black.opacity(0.6))
.cornerRadius(24)
.tag(pbManager.videos.count)
.overlay {
RoundedRectangle(cornerRadius: 24)
.stroke(.gray, lineWidth: 4)
@@ -103,7 +143,13 @@ struct VideoView: View {
do {
if let movie = try await selectedVideo?.loadTransferable(type: Movie.self) {
await MainActor.run {
pbManager.videos[id].loadState = .loaded(movie)
if !ignoreDurationLimit && VideoHandler.isVideoTooLong(at: movie.url) {
pbManager.videos.remove(at: id)
UIApplication.shared.alert(title: NSLocalizedString("Failed to Import Video", comment: ""), body: String(format: NSLocalizedString("The video you imported is too long! Your video must be %@ seconds or less.", comment: ""), "\(Int(VideoHandler.MaxDurationSecs))"))
} else {
pbManager.videos[id].loadState = .loaded(movie)
currentPage = id
}
}
} else {
await MainActor.run {
@@ -118,7 +164,7 @@ struct VideoView: View {
selectedVideo = nil
}
}
.tabViewStyle(.page)
.tabViewStyle(PageTabViewStyle(indexDisplayMode: .always))
}
}
}
@@ -149,7 +195,8 @@ struct DeleteButton: View {
.font(.title)
.background {
Circle()
.foregroundStyle(.white)
.foregroundStyle(.regularMaterial)
.shadow(radius: 5)
}
}
.offset(x: -8, y: -8)
@@ -29,30 +29,30 @@ struct OnBoardingPage: Identifiable {
let onBoardingCards: [OnBoardingPage] = [
.init(
title: "Welcome to Pocket Poster!",
description: "Here is a tutorial to help you get started with the app.",
title: NSLocalizedString("Welcome to Pocket Poster!", comment: ""),
description: NSLocalizedString("Here is a tutorial to help you get started with the app.", comment: ""),
image: "Logo"
),
.init(
title: "Install the Fallback Shortcut (Optional)",
description: "To apply, PosterBoard will need to open.\n\nYou can install an optional shortcut if the original method fails.",
title: NSLocalizedString("Install the Fallback Shortcut (Optional)", comment: ""),
description: NSLocalizedString("To apply, PosterBoard will need to open.", comment: "") + "\n\n" + NSLocalizedString("You can install an optional shortcut if the original method fails.", comment: ""),
image: "Shortcuts",
link: URL(string: PosterBoardManager.ShortcutURL),
linkName: "Get Shortcut"
linkName: NSLocalizedString("Get Shortcut", comment: "")
),
.init(
title: "Install Nugget",
description: "To get the app bundle id, Nugget is required.\n\nOn your computer, download Nugget from the GitHub.",
title: NSLocalizedString("Install Nugget", comment: ""),
description: NSLocalizedString("To get the app bundle id, Nugget is required.", comment: "") + "\n\n" + NSLocalizedString("On your computer, download Nugget from the GitHub.", comment: ""),
image: "Nugget",
link: URL(string: "https://github.com/leminlimez/Nugget/releases/latest"),
linkName: "Open GitHub"
linkName: NSLocalizedString("Open GitHub", comment: "")
),
.init(
title: "Enjoy!",
description: "You can find wallpapers on the official Cowabun.ga website.",
title: NSLocalizedString("Enjoy!", comment: ""),
description: NSLocalizedString("You can find wallpapers on the official Cowabun.ga website.", comment: ""),
image: "Cowabunga",
link: URL(string: PosterBoardManager.WallpapersURL),
linkName: "Find Wallpapers"
linkName: NSLocalizedString("Find Wallpapers", comment: "")
)
]
+12 -2
View File
@@ -9,8 +9,9 @@ import SwiftUI
struct SettingsView: View {
// Prefs
@AppStorage("pbHash") var pbHash: String = ""
@AppStorage("cpHash") var cpHash: String = ""
@AppStorage("pbHash") var pbHash: String = "" // PosterBoard hash
@AppStorage("cpHash") var cpHash: String = "" // CarPlay hash
@AppStorage("ignoreDurationLimit") var ignoreDurationLimit: Bool = false
@State var checkingForHash: Bool = false
@State var hashCheckTask: Task<Void, any Error>? = nil
@@ -49,6 +50,14 @@ struct SettingsView: View {
Label("App Hash", systemImage: "lock.app.dashed")
}
Section {
Toggle(isOn: $ignoreDurationLimit, label: {
Label("Disable Video Duration Limit", systemImage: "ruler")
})
} header: {
Label("Preferences", systemImage: "gear")
}
Section {
Button(action: {
UIImpactFeedbackGenerator(style: .soft).impactOccurred()
@@ -128,6 +137,7 @@ struct SettingsView: View {
LinkCell(imageName: "Nathan", url: "https://github.com/verygenericname", title: "Nathan", contribution: NSLocalizedString("Exploit", comment: ""), circle: true)
LinkCell(imageName: "duy", url: "https://github.com/khanhduytran0", title: "DuyKhanhTran", contribution: NSLocalizedString("Exploit", comment: ""), circle: true)
LinkCell(imageName: "sky", url: "https://bsky.app/profile/did:plc:xykfeb7ieeo335g3aly6vev4", title: "dootskyre", contribution: NSLocalizedString("Fallback Shortcut Creator", comment: ""), circle: true)
LinkCell(imageName: "POEditor", url: "https://poeditor.com/join/project/MPZOsunwVj", title: NSLocalizedString("Community Translators", comment: ""), contribution: "POEditor")
} header: {
Label("Credits", systemImage: "wrench.and.screwdriver")
}