diff --git a/CHANGELOG.md b/CHANGELOG.md index f0a78c6..636248a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,18 @@ ## CHANGELOG +## [0.18.0] + +### Added + +- Story block UI component +- RTL support +- Arabic translations + +### Changed + +- Product unit option names are now used when hydration occurs +- Fix for video event callback + ## [0.17.0] ### Added diff --git a/FireworkVideo.podspec b/FireworkVideo.podspec index 9247048..1c2e201 100644 --- a/FireworkVideo.podspec +++ b/FireworkVideo.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |spec| spec.name = "FireworkVideo" - spec.version = "0.17.0" + spec.version = "0.18.0" spec.summary = "FireworkVideoSDK" spec.homepage = "https://github.com/loopsocial/firework_ios_sdk" spec.license = { :text => "Copyright 2021 Loop Now Technologies, Inc.", :type => "Copyright" } diff --git a/FireworkVideoSample/FireworkVideoSample.xcodeproj/project.pbxproj b/FireworkVideoSample/FireworkVideoSample.xcodeproj/project.pbxproj index 9786d70..a183a2e 100644 --- a/FireworkVideoSample/FireworkVideoSample.xcodeproj/project.pbxproj +++ b/FireworkVideoSample/FireworkVideoSample.xcodeproj/project.pbxproj @@ -41,6 +41,7 @@ 8432FD33273E1A78000A0125 /* StorefrontRepository.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8432FD32273E1A78000A0125 /* StorefrontRepository.swift */; }; 8432FD35273E22F5000A0125 /* CartViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8432FD34273E22F5000A0125 /* CartViewController.swift */; }; 84E478AB2622C888007CC9AE /* ShareVideoExamplesViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84E478AA2622C888007CC9AE /* ShareVideoExamplesViewController.swift */; }; + C9ED838C286E00180033072B /* StoryBlockExampleViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = C9ED838B286E00180033072B /* StoryBlockExampleViewController.swift */; }; /* End PBXBuildFile section */ /* Begin PBXCopyFilesBuildPhase section */ @@ -92,6 +93,7 @@ 8432FD32273E1A78000A0125 /* StorefrontRepository.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StorefrontRepository.swift; sourceTree = ""; }; 8432FD34273E22F5000A0125 /* CartViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CartViewController.swift; sourceTree = ""; }; 84E478AA2622C888007CC9AE /* ShareVideoExamplesViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShareVideoExamplesViewController.swift; sourceTree = ""; }; + C9ED838B286E00180033072B /* StoryBlockExampleViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StoryBlockExampleViewController.swift; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -155,6 +157,7 @@ 7BA940C025B979D000CF58D5 /* TableViewEmbeddedVideoFeedViewController.swift */, 7B1A7B9725DB305E0097079C /* VideoFeedChannelSourceViewController.swift */, 7BA940C525B979D900CF58D5 /* StoryboardVideoFeedViewController.swift */, + C9ED838B286E00180033072B /* StoryBlockExampleViewController.swift */, 7B8BD69E25BD85C400BFFFB5 /* ColorPickers.swift */, 7B8BD6A025BD973900BFFFB5 /* Helpers.swift */, 7BA940AE25B9765300CF58D5 /* Main.storyboard */, @@ -365,6 +368,7 @@ 7BA940AB25B9765300CF58D5 /* SceneDelegate.swift in Sources */, 7B1A7B9625DB2E640097079C /* VideoPlaybackLogger.swift in Sources */, 7B052ACB2613EA0700B96C2F /* DiscoverVideoFeedViewController.swift in Sources */, + C9ED838C286E00180033072B /* StoryBlockExampleViewController.swift in Sources */, 7B8BD6A125BD973900BFFFB5 /* Helpers.swift in Sources */, 7BA940C625B979D900CF58D5 /* StoryboardVideoFeedViewController.swift in Sources */, 7B8BD69F25BD85C400BFFFB5 /* ColorPickers.swift in Sources */, diff --git a/FireworkVideoSample/FireworkVideoSample/Base.lproj/Main.storyboard b/FireworkVideoSample/FireworkVideoSample/Base.lproj/Main.storyboard index 11bf383..47067f3 100644 --- a/FireworkVideoSample/FireworkVideoSample/Base.lproj/Main.storyboard +++ b/FireworkVideoSample/FireworkVideoSample/Base.lproj/Main.storyboard @@ -235,12 +235,36 @@ + + + + + + + + + + + + - + @@ -278,7 +302,7 @@ - + @@ -322,7 +346,7 @@ - + diff --git a/FireworkVideoSample/FireworkVideoSample/StoryBlockExampleViewController.swift b/FireworkVideoSample/FireworkVideoSample/StoryBlockExampleViewController.swift new file mode 100644 index 0000000..38eeb46 --- /dev/null +++ b/FireworkVideoSample/FireworkVideoSample/StoryBlockExampleViewController.swift @@ -0,0 +1,57 @@ +// +// StoryBlockLayoutViewController.swift +// FireworkVideoDebug +// +// Created by Luke Davis on 6/3/22. +// + +import UIKit +import FireworkVideo + +class StoryBlockExampleViewController: UIViewController { + private lazy var storyBlock: StoryBlockViewController = { + let storyBlock = StoryBlockViewController( + source: StoryBlockContentSource.discover + ) + storyBlock.delegate = self + return storyBlock + }() + + override func viewDidLoad() { + super.viewDidLoad() + setupStoryBlock() + } + + private func setupStoryBlock() { + view.backgroundColor = .systemBackground + self.addChild(storyBlock) + view.addSubview(storyBlock.view) + storyBlock.view.translatesAutoresizingMaskIntoConstraints = false + let aspect: CGFloat = 16 / 9 + NSLayoutConstraint.activate([ + storyBlock.view.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 50), + storyBlock.view.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor, constant: 50), + view.safeAreaLayoutGuide.trailingAnchor.constraint(equalTo: storyBlock.view.trailingAnchor, constant: 50), + storyBlock.view.heightAnchor.constraint(equalTo: storyBlock.view.widthAnchor, multiplier: aspect) + ]) + storyBlock.didMove(toParent: self) + } +} + +extension StoryBlockExampleViewController: StoryBlockViewControllerDelegate { + func storyBlockDidLoadFeed(_ viewController: StoryBlockViewController) { + } + + func storyBlock(_ viewController: StoryBlockViewController, didFailToLoadFeed error: StoryBlockError) { + let alert = UIAlertController(title: "Failed to load feed", message: "Unable to load feed. Failed with error: \(error)", preferredStyle: .alert) + let copyError = UIAlertAction(title: "Copy Error", style: .default) { _ in + UIPasteboard.general.string = "\(error)" + } + alert.addAction(copyError) + let ok = UIAlertAction(title: "OK", style: .default) { _ in + // Pop back? + } + alert.addAction(ok) + present(alert, animated: true) + } +} diff --git a/FireworkVideoSample/FireworkVideoSample/VideoFeedExamplesViewController.swift b/FireworkVideoSample/FireworkVideoSample/VideoFeedExamplesViewController.swift index ae60113..8b973ad 100644 --- a/FireworkVideoSample/FireworkVideoSample/VideoFeedExamplesViewController.swift +++ b/FireworkVideoSample/FireworkVideoSample/VideoFeedExamplesViewController.swift @@ -49,6 +49,8 @@ class VideoFeedExamplesViewController: UITableViewController { channelID: "23LBMWN", parameters: ["category": ["dessert"]]) return VideoFeedChannelSourceViewController(contentSource: contentSource) + } else if selectedIndexPath.section == 0 && selectedIndexPath.row == 9 { + return StoryBlockExampleViewController() } return nil diff --git a/Package.swift b/Package.swift index d6cf929..f99fefd 100644 --- a/Package.swift +++ b/Package.swift @@ -15,8 +15,8 @@ let package = Package( ], targets: [ .binaryTarget(name: "FireworkVideo", - url: "https://github.com/loopsocial/firework_ios_sdk/releases/download/v0.17.0/FireworkVideo-v0.17.0.xcframework.zip", - checksum: "ba314e51703a9a0c69e4578f1753a5fc25e79388ad5969e90f27f58ce3259a2c"), + url: "https://github.com/loopsocial/firework_ios_sdk/releases/download/v0.18.0/FireworkVideo-v0.18.0.xcframework.zip", + checksum: "f1d4ce87bc53220623fb6acc7ba5f1f1f002bfa7a9c87791242a01bae4d78a29"), ] ) diff --git a/README.md b/README.md index e55d37a..759f431 100644 --- a/README.md +++ b/README.md @@ -296,9 +296,9 @@ func handleCustomCTAClick(_ viewController: PlayerViewController, url: URL) -> B } ``` -### Content Sources +### Feed Content Sources -The enum VideoFeedContentSource defines the different sources that can be used to populate the video feed. The content source must be specified when the VideoFeedViewController is instantiated; `VideoFeedViewController(source: .discover)`. By default the feed will use the `.discover` content source. +The enum `VideoFeedContentSource` defines the different sources that can be used to populate the video feed. The content source must be specified when the VideoFeedViewController is instantiated; `VideoFeedViewController(source: .discover)`. By default the feed will use the `.discover` content source. Other content sources include @@ -344,6 +344,71 @@ let parameters: DynamicContentParameters = ["": ["", let feedVC = VideoFeedViewController(source: .dynamicContent(channelID: channelID, parameters: parameters)) ``` +### Story Block + +Displaying a Story Block can be done by using a `StoryBlockViewController` either programmatically or in a storyboard. + +#### Programmatic + + 1. Import FireworkVideo + 2. Create a new `StoryBlockViewController` + 3. Embed the instantiated `StoryBlockViewController` + +```swift +import FireworkVideo + +class ViewController: UIViewController { + + func embedFeedInViewController() { + let storyBlockVC = StoryBlockViewController() + self.addChild(storyBlockVC) + self.view.addSubview(storyBlockVC.view) + storyBlockVC.view.frame = self.view.bounds + storyBlockVC.willMove(toParent: self) + } + +} +``` + +#### Story Block Content Source + +The enum `StoryBlockContentSource` defines the different sources that can be used to populate the story block. The content source must be specified when the `StoryBlockViewController` is instantiated; `StoryBlockViewController(source: .discover)`. By default, the feed will use the `.discover` content source. + +Other content sources include + +#### Channel + +Displays content from the specified channel id. + +> Note: The user will only see videos they have not viewed before. If the user has viewed all the videos for a channel similar videos will automatically be provided. + +```swift +let channelID = "" +let feedVC = StoryBlockViewController(source: .channel(channelID: channelID)) +``` + +#### Channel Playlist + +Displays content from the specified playlist id. + +> Note: Unlike the [channel content source](#channel), only content in the playlist will be shown to the user. + +```swift +let channelID = "" +let playlistID = "" +let feedVC = StoryBlockViewController(source: .channelPlaylist(channelID: channelID, playlistID: playlistID)) +``` + +#### Dynamic Content + +Displays dynamic content based on the provided channel id and content parameters. + +```swift +let channelID = "" +let parameters: DynamicContentParameters = ["": ["", ""]] +let feedVC = StoryBlockViewController(source: .dynamicContent(channelID: channelID, parameters: parameters)) +``` + ### Shopping FireworkVideoSDK contains a `shopping` property that enables video shopping integration. There are two main points of integration both located on the `FireworkVideoShopping` type.