Skip to content

Commit

Permalink
Add basic error reporting (#107)
Browse files Browse the repository at this point in the history
  • Loading branch information
defagos authored Oct 17, 2022
1 parent 69b93ea commit f366d3c
Show file tree
Hide file tree
Showing 42 changed files with 969 additions and 77 deletions.
3 changes: 2 additions & 1 deletion .swiftpm/xcode/xcshareddata/xcschemes/Analytics.xcscheme
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
shouldUseLaunchSchemeArgsEnv = "YES"
language = "en">
<Testables>
<TestableReference
skipped = "NO"
Expand Down
1 change: 1 addition & 0 deletions .swiftpm/xcode/xcshareddata/xcschemes/Circumspect.xcscheme
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES"
language = "en"
codeCoverageEnabled = "YES">
<Testables>
<TestableReference
Expand Down
1 change: 1 addition & 0 deletions .swiftpm/xcode/xcshareddata/xcschemes/Core.xcscheme
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES"
language = "en"
codeCoverageEnabled = "YES">
<Testables>
<TestableReference
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES"
language = "en"
codeCoverageEnabled = "YES">
<Testables>
<TestableReference
Expand Down
1 change: 1 addition & 0 deletions .swiftpm/xcode/xcshareddata/xcschemes/Diagnostics.xcscheme
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES"
language = "en"
codeCoverageEnabled = "YES">
<Testables>
<TestableReference
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,7 @@
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES"
language = "en"
codeCoverageEnabled = "YES">
<Testables>
<TestableReference
Expand Down
1 change: 1 addition & 0 deletions .swiftpm/xcode/xcshareddata/xcschemes/Player.xcscheme
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES"
language = "en"
codeCoverageEnabled = "YES">
<Testables>
<TestableReference
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES"
language = "en"
codeCoverageEnabled = "YES">
<Testables>
<TestableReference
Expand Down
11 changes: 8 additions & 3 deletions Demo/Sources/ExamplesView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -101,13 +101,18 @@ private struct Example: Identifiable {
media: MediaURL.appleAdvanced_16_9_HEVC_h264_HLS
),
Example(
title: "Unknown media",
description: "This media does not exist",
title: "Expired content",
description: "This content is not available anymore",
media: MediaURN.expired
),
Example(
title: "Unknown content",
description: "This content does not exist",
media: MediaURN.unknown
),
Example(
title: "Empty",
description: "No media is provided",
description: "No content is provided",
media: .empty
)
]
Expand Down
1 change: 1 addition & 0 deletions Demo/Sources/Media.swift
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ enum MediaURN {
static let dvrAudio = Media.urn("urn:rts:audio:3262363")
static let onDemandAudio = Media.urn("urn:rsi:audio:8833144")

static let expired = Media.urn("urn:rts:video:13382911")
static let unknown = Media.urn("urn:srf:video:unknown")
}

Expand Down
62 changes: 47 additions & 15 deletions Demo/Sources/PlayerView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,32 @@ import UserInterface

// MARK: View

private struct ContentView: View {
@ObservedObject var player: Player
@State private var isUserInterfaceHidden = false

var body: some View {
ZStack {
Group {
VideoView(player: player)
ControlsView(player: player, isUserInterfaceHidden: isUserInterfaceHidden)
}
.onTapGesture {
isUserInterfaceHidden.toggle()
}
.ignoresSafeArea()
#if os(iOS)
Slider(player: player)
.tint(.white)
.opacity(isUserInterfaceHidden ? 0 : 1)
.padding()
.frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .bottom)
#endif
}
.animation(.easeInOut(duration: 0.2), value: isUserInterfaceHidden)
}
}

private struct ControlsView: View {
@ObservedObject var player: Player
let isUserInterfaceHidden: Bool
Expand All @@ -34,6 +60,18 @@ private struct ControlsView: View {
}
}

private struct MessageView: View {
let message: String

var body: some View {
Text(message)
.multilineTextAlignment(.center)
.foregroundColor(.white)
.padding()
.frame(maxWidth: .infinity, maxHeight: .infinity)
}
}

private struct NextButton: View {
@ObservedObject var player: Player

Expand Down Expand Up @@ -98,28 +136,22 @@ struct PlayerView: View {
let medias: [Media]

@StateObject private var player = Player()
@State private var isUserInterfaceHidden = false

var body: some View {
ZStack {
Group {
VideoView(player: player)
ControlsView(player: player, isUserInterfaceHidden: isUserInterfaceHidden)
if !player.items.isEmpty {
switch player.playbackState {
case let .failed(error: error):
MessageView(message: error.localizedDescription)
default:
ContentView(player: player)
}
}
.onTapGesture {
isUserInterfaceHidden.toggle()
else {
MessageView(message: "No content")
}
.ignoresSafeArea()
#if os(iOS)
Slider(player: player)
.tint(.white)
.opacity(isUserInterfaceHidden ? 0 : 1)
.padding()
.frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .bottom)
#endif
}
.background(.black)
.animation(.easeInOut(duration: 0.2), value: isUserInterfaceHidden)
.onAppear {
play()
}
Expand Down
15 changes: 10 additions & 5 deletions Sources/Circumspect/Expectations.swift
Original file line number Diff line number Diff line change
Expand Up @@ -573,10 +573,11 @@ public extension XCTestCase {
let cancellable = publisher.sink { completion in
switch completion {
case .finished:
expectation.fulfill()
case .failure:
break
case .failure:
XCTFail("The publisher incorrectly failed", file: file, line: line)
}
expectation.fulfill()
} receiveValue: { _ in
}
defer {
Expand All @@ -592,6 +593,7 @@ public extension XCTestCase {

/// Expect a publisher to complete with a failure.
func expectFailure<P: Publisher>(
_ error: Error? = nil,
from publisher: P,
timeout: TimeInterval = 10,
file: StaticString = #file,
Expand All @@ -602,10 +604,13 @@ public extension XCTestCase {
let cancellable = publisher.sink { completion in
switch completion {
case .finished:
break
case .failure:
expectation.fulfill()
XCTFail("The publisher incorrectly succeeded", file: file, line: line)
case let .failure(actualError):
if let error {
XCTAssertEqual(error as NSError, actualError as NSError, file: file, line: line)
}
}
expectation.fulfill()
} receiveValue: { _ in
}
defer {
Expand Down
11 changes: 2 additions & 9 deletions Sources/CoreBusiness/AssetResourceLoaderDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -35,14 +35,7 @@ final class AssetResourceLoaderDelegate: NSObject, AVAssetResourceLoaderDelegate

private func processLoadingRequest(_ loadingRequest: AVAssetResourceLoadingRequest) -> Bool {
guard let url = loadingRequest.request.url, let urn = URLCoding.decodeUrn(from: url) else { return false }
cancellable = DataProvider(environment: environment).mediaComposition(forUrn: urn)
.map(\.mainChapter.recommendedResource)
.tryMap { resource in
guard let resource else {
throw ResourceLoadingError.notFound
}
return resource
}
cancellable = DataProvider(environment: environment).recommendedPlayableResource(forUrn: urn)
.sink(receiveCompletion: { completion in
switch completion {
case .finished:
Expand All @@ -62,6 +55,6 @@ private extension AVAssetResourceLoadingRequest {
var redirectRequest = request
redirectRequest.url = url
redirect = redirectRequest
response = HTTPURLResponse(url: url, statusCode: 303, httpVersion: nil, headerFields: nil)
response = HTTPURLResponse(url: url, statusCode: 302, httpVersion: nil, headerFields: nil)
}
}
63 changes: 63 additions & 0 deletions Sources/CoreBusiness/BlockingReason.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
//
// Copyright (c) SRG SSR. All rights reserved.
//
// License information is available from the LICENSE file.
//

import Foundation

enum BlockingReason: String, Decodable {
case ageRating12 = "AGERATING12"
case ageRating18 = "AGERATING18"
case commercial = "COMMERCIAL"
case endDate = "ENDDATE"
case geoblocked = "GEOBLOCK"
case legal = "LEGAL"
case startDate = "STARTDATE"
case unknown = "UNKNOWN"

public var description: String {
switch self {
case .ageRating12:
return NSLocalizedString(
"To protect children this content is only available between 8PM and 6AM.",
comment: "Blocking reason description message"
)
case .ageRating18:
return NSLocalizedString(
"To protect children this content is only available between 10PM and 5AM.",
comment: "Blocking reason description message"
)
case .commercial:
return NSLocalizedString(
"This commercial content is not available.",
comment: "Blocking reason description message"
)
case .endDate:
return NSLocalizedString(
"This content is not available anymore.",
comment: "Blocking reason description message"
)
case .geoblocked:
return NSLocalizedString(
"This content is not available outside Switzerland.",
comment: "Blocking reason description message"
)
case .legal:
return NSLocalizedString(
"This content is not available due to legal restrictions.",
comment: "Blocking reason description message"
)
case .startDate:
return NSLocalizedString(
"This content is not available yet. Please try again later.",
comment: "Blocking reason description message"
)
case .unknown:
return NSLocalizedString(
"This content is not available.",
comment: "Blocking reason description message"
)
}
}
}
27 changes: 25 additions & 2 deletions Sources/CoreBusiness/Chapter.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,37 @@ import Foundation

struct Chapter: Decodable {
enum CodingKeys: String, CodingKey {
case urn
case title
case blockingReason = "blockReason"
case endDate = "validTo"
case resources = "resourceList"
case startDate = "validFrom"
case title
case urn
}

private let blockingReason: BlockingReason?

let urn: String
let title: String
let resources: [Resource]

let startDate: Date?
let endDate: Date?

func blockingReason(at date: Date = Date()) -> BlockingReason? {
if blockingReason != .none {
return blockingReason
}
else if let startDate, date < startDate {
return .startDate
}
else if let endDate, date > endDate {
return .endDate
}
else {
return .none
}
}
}

extension Chapter {
Expand Down
9 changes: 0 additions & 9 deletions Sources/CoreBusiness/CoreBusiness.swift

This file was deleted.

Loading

0 comments on commit f366d3c

Please sign in to comment.