Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Tenor integration #13949

Merged
merged 105 commits into from
May 12, 2020
Merged
Show file tree
Hide file tree
Changes from 91 commits
Commits
Show all changes
105 commits
Select commit Hold shift + click to select a range
e857e35
Added Tenor feature flag
ngoctr Apr 6, 2020
4a33eb3
Merge branch 'feature/13803-tenor_integration' into feature/tenor-fea…
ngoctr Apr 6, 2020
7bae58f
Merge pull request #13829 from ngoctr/feature/tenor-feature-flag
ScoutHarris Apr 7, 2020
8ec416b
Merge branch 'develop' into feature/13803-tenor_integration
ScoutHarris Apr 7, 2020
6b19638
Added Tenor API Key support in gencredentials.rb
ngoctr Apr 3, 2020
30a06f9
Added Tenor Client API
ngoctr Apr 6, 2020
37ca6ba
Added more unit tests for Tenor API response
ngoctr Apr 6, 2020
b0e7160
Added nanoGIF into TenorGIFCollection to use as thumbnail
ngoctr Apr 7, 2020
bb32ab4
Removed file header generated by Xcode
ngoctr Apr 8, 2020
aa199f2
Merge branch 'develop' into feature/13803-tenor_integration
ScoutHarris Apr 8, 2020
5f50901
Print error if Tenor key not being configure
ngoctr Apr 8, 2020
1e56339
Fixed a typo in code comment
ngoctr Apr 8, 2020
f0fbfd1
Removed unnecessary properties that we don't need them
ngoctr Apr 8, 2020
f5dbe08
Use DDLogError instead of assertionFailture
ngoctr Apr 8, 2020
b46ccde
Added comment and explicitly add `public` modifier for search method
ngoctr Apr 8, 2020
53fd5fa
Merge pull request #13842 from ngoctr/13803/tenor-api-credentials
ScoutHarris Apr 8, 2020
ae01693
Merge pull request #13843 from ngoctr/13803/tenor-client-api
ScoutHarris Apr 8, 2020
29a5a23
Merge branch 'develop' into feature/13803-tenor_integration
ScoutHarris Apr 9, 2020
8dbadf5
Merge branch 'develop' into feature/13803-tenor_integration
ScoutHarris Apr 9, 2020
0773f8d
Implement Tenor media picker
ngoctr Apr 7, 2020
8e47b28
Added tenor-attribution image
ngoctr Apr 7, 2020
579fa89
Added unit tests for TenorPageable
ngoctr Apr 7, 2020
95c6f4f
Fixed a typo on variable name
ngoctr Apr 7, 2020
b9c58d2
Used nano GIF size from Tenor for a faster thumbnail loading in the P…
ngoctr Apr 7, 2020
e2b30ea
Used largest GIF image size from Tenor for user's media library and p…
ngoctr Apr 7, 2020
5a243d2
Removed commented code
ngoctr Apr 9, 2020
c4b336c
Fixed a build issue
ngoctr Apr 9, 2020
eecacb8
Moved mock data into json resource files
ngoctr Apr 9, 2020
fe9884b
Added TenorResultsPage tests
ngoctr Apr 9, 2020
d81e424
Added Tenor media exporter
ngoctr Apr 9, 2020
56b7b44
Added Tenor media source
ngoctr Apr 9, 2020
859f457
Added Tenor media source
ngoctr Apr 9, 2020
5d021d4
Added Tenor media source
ngoctr Apr 9, 2020
40bab0c
Added Tenor support for media library
ngoctr Apr 10, 2020
731dfa5
Added Tenor support for Aztec Editor
ngoctr Apr 10, 2020
da261a0
Implement Tenor support for Block editor
ngoctr Apr 10, 2020
1961c99
Changed TenorService to class so we can mock it
ngoctr Apr 10, 2020
eb59a69
Made TenorMedia immutable
ngoctr Apr 10, 2020
9c7f00c
Added unit tests for TenorDataSource
ngoctr Apr 10, 2020
97ec082
Implemented trailing_newline policy
ngoctr Apr 10, 2020
d230006
Merge branch '13803/tenor-picker' into 13803/tenor-for-media-library
ngoctr Apr 10, 2020
bd99c14
Merge branch '13803/tenor-picker' into 13803/tenor-for-aztec-editor
ngoctr Apr 10, 2020
f55adae
Merge branch '13803/tenor-picker' into 13803/tenor-for-gutenberg-editor
ngoctr Apr 10, 2020
0425612
Merge branch 'develop' into feature/13803-tenor_integration
ScoutHarris Apr 14, 2020
dc81e1c
Removed caption property from TenorMedia
ngoctr Apr 14, 2020
422f53c
Removed force unwrap
ngoctr Apr 14, 2020
f884b0b
Removed force unwrap
ngoctr Apr 14, 2020
1adbdab
Removed force unwrap.
ngoctr Apr 14, 2020
2230ba5
Clean up unnecessary code
ngoctr Apr 15, 2020
a9249b8
Changed the Tenor page size to 40 to make it consistent with StockPhotos
ngoctr Apr 15, 2020
b30652e
Merge branch '13803-tenor-master-branch' into 13803/tenor-picker
ngoctr Apr 15, 2020
dc5bdf2
Merge branch '13803/tenor-picker' into 13803/tenor-for-media-library
ngoctr Apr 15, 2020
90e2260
Merge branch '13803/tenor-picker' into 13803/tenor-for-gutenberg-editor
ngoctr Apr 15, 2020
38dd814
Merge branch '13803/tenor-picker' into 13803/tenor-for-aztec-editor
ngoctr Apr 15, 2020
9fad122
Merge branch 'develop' into feature/13803-tenor_integration
ScoutHarris Apr 15, 2020
e3c965f
Merge pull request #13861 from ngoctr/13803/tenor-picker
ScoutHarris Apr 15, 2020
82f7a7d
Merge branch 'develop' into feature/13803-tenor_integration
ScoutHarris Apr 15, 2020
b063dc7
Merge branch '13803-tenor-master-branch' into 13803/tenor-for-media-l…
ngoctr Apr 15, 2020
441db93
Merge branch '13803-tenor-master-branch' into 13803/tenor-for-gutenbe…
ngoctr Apr 15, 2020
647d61a
Merge branch '13803-tenor-master-branch' into 13803/tenor-for-aztec-e…
ngoctr Apr 15, 2020
6cd90d3
Changed *Tenor* to *Free GIF Library* to make it more understandable …
ngoctr Apr 15, 2020
ea3af7f
Changed *Tenor* to *Free GIF Library* to make it more understandable …
ngoctr Apr 15, 2020
7a92257
Changed *Tenor* to *Free GIF Library* to make it more understandable …
ngoctr Apr 15, 2020
dfa77e4
Merge pull request #13907 from ngoctr/13803/tenor-for-media-library
ScoutHarris Apr 16, 2020
12c5b9e
Merge branch '13803-tenor-master-branch' into 13803/tenor-for-aztec-e…
ngoctr Apr 16, 2020
6ae0331
Merge branch '13803-tenor-master-branch' into 13803/tenor-for-gutenbe…
ngoctr Apr 16, 2020
5fa137d
Merge pull request #13910 from ngoctr/13803/tenor-for-gutenberg-editor
ScoutHarris Apr 16, 2020
249c2da
Merge pull request #13908 from ngoctr/13803/tenor-for-aztec-editor
ScoutHarris Apr 16, 2020
6db76db
Merge branch 'develop' into feature/13803-tenor_integration
ScoutHarris Apr 16, 2020
c65a385
Merge branch 'develop' into feature/13803-tenor_integration
ScoutHarris Apr 16, 2020
9eeb0f3
Correct datetime decoding from Tenor response
ngoctr Apr 16, 2020
7c701e7
Added unit test for TenorMedia.created date
ngoctr Apr 17, 2020
964aae4
Added analytics events for Tenor
ngoctr Apr 17, 2020
d052c5a
Tracked accessed, searched & uploaded events for Tenor
ngoctr Apr 17, 2020
2b13e0f
Correct media and editor events
ngoctr Apr 17, 2020
f8671c8
Added events tracking for Tenor media
ngoctr Apr 17, 2020
df4a5de
Merge branch 'develop' into feature/13803-tenor_integration
ScoutHarris Apr 17, 2020
6490dd6
Merge branch 'develop' into feature/13803-tenor_integration
ScoutHarris Apr 17, 2020
1a1484d
Merge branch 'develop' into feature/13803-tenor_integration
ScoutHarris Apr 17, 2020
3a0e107
Clean up code in track function associated with a blog
ngoctr Apr 17, 2020
30c286d
Correct media source in StockPhotos & TenorPhotos sources for Gutenbe…
ngoctr Apr 17, 2020
cc29595
Merge pull request #13919 from ngoctr/13803/tenor-accesibility-support
ScoutHarris Apr 18, 2020
61d1c39
Added support animating GIFs in Tenor Picker
ngoctr Apr 18, 2020
a848a0e
Added a tiny GIF play strategy to reduce memory usage in a collection…
ngoctr Apr 18, 2020
1db8728
Merge branch 'develop' into feature/13803-tenor_integration
ScoutHarris Apr 20, 2020
6a1b672
Made function names more Swifty
ngoctr Apr 20, 2020
1deccc8
Undoed changes in StockPhotos tracking sources
ngoctr Apr 20, 2020
f0f11a5
Merge branch 'feature/13803-tenor_integration' of https://github.com/…
ngoctr Apr 20, 2020
7abe7db
Merge pull request #13923 from ngoctr/13803/tenor-analytics-support
ScoutHarris Apr 21, 2020
69aecc1
Merge pull request #13941 from ngoctr/13803/animated-gifs
ScoutHarris Apr 21, 2020
6e31736
Merge branch 'develop' into feature/13803-tenor_integration
ScoutHarris Apr 22, 2020
125be33
Removed reference to P2
ngoctr Apr 25, 2020
5258dec
Added contentFilter param to Tenor Client API
ngoctr Apr 25, 2020
2e90a13
Made subtitle image name a constant
ngoctr Apr 25, 2020
1a96c43
Created a new Tenor picker each time being invoked in Aztec Editor
ngoctr Apr 25, 2020
ae4e567
Correctly releasing the Tenor picker instance
ngoctr Apr 25, 2020
1d9fdf6
Removed unnecessary guards
ngoctr Apr 25, 2020
65e3a9b
Merge branch 'develop' into feature/13803-tenor_integration
ScoutHarris Apr 27, 2020
73494fd
Merge branch 'develop' into feature/13803-tenor_integration
ScoutHarris Apr 29, 2020
1bcf08a
Merge branch 'develop' into feature/13803-tenor_integration
ScoutHarris May 4, 2020
71573b7
Merge branch 'develop' into feature/13803-tenor_integration
ScoutHarris May 4, 2020
e4139be
Merge pull request #14001 from ngoctr/13803-tenor-master-branch
ScoutHarris May 5, 2020
25c6d0a
TenorClient: Added comment to clarify content filter ratings.
frosty May 6, 2020
a8aab30
Merge branch 'develop' into feature/13803-tenor_integration
ScoutHarris May 8, 2020
d35ce72
Merge branch 'develop' into feature/13803-tenor_integration
ScoutHarris May 12, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 16 additions & 1 deletion WordPress/Classes/Services/MediaCoordinator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -320,8 +320,23 @@ class MediaCoordinator: NSObject {
}

private func trackUploadOf(_ media: Media, analyticsInfo: MediaAnalyticsInfo?) {
guard let info = analyticsInfo else {
return
}

guard let event = info.eventForMediaType(media.mediaType) else {
// Fall back to the WPShared event tracking
trackUploadViaWPSharedOf(media, analyticsInfo: analyticsInfo)
return
}

let properties = info.properties(for: media)
WPAnalytics.track(event, properties: properties, blog: media.blog)
}

private func trackUploadViaWPSharedOf(_ media: Media, analyticsInfo: MediaAnalyticsInfo?) {
guard let info = analyticsInfo,
let event = info.eventForMediaType(media.mediaType) else {
let event = info.wpsharedEventForMediaType(media.mediaType) else {
return
}

Expand Down
3 changes: 3 additions & 0 deletions WordPress/Classes/Services/MediaImportService.swift
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,9 @@ open class MediaImportService: LocalCoreDataService {
case let stockPhotosMedia as StockPhotosMedia:
let exporter = MediaExternalExporter(externalAsset: stockPhotosMedia)
return exporter
case let tenorMedia as TenorMedia:
let exporter = MediaExternalExporter(externalAsset: tenorMedia)
return exporter
default:
return nil
}
Expand Down
42 changes: 39 additions & 3 deletions WordPress/Classes/Utility/Analytics/WPAnalyticsEvent.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,17 @@ import Foundation

// WPiOS-only events
@objc enum WPAnalyticsEvent: Int {
// Media Editor
case mediaEditorShown
case mediaEditorUsed
case editorCreatedPage
case createSheetShown
// Tenor
case tenorAccessed
case tenorSearched
case tenorUploaded
case mediaLibraryAddedPhotoViaTenor
case editorAddedPhotoViaTenor

// Prepublishing Nudges
case editorPostPublishTap
Expand All @@ -17,6 +24,7 @@ import Foundation
/// A String that represents the event
var value: String {
switch self {
// Media Editor
case .mediaEditorShown:
return "media_editor_shown"
case .mediaEditorUsed:
Expand All @@ -25,6 +33,18 @@ import Foundation
return "editor_page_created"
case .createSheetShown:
return "create_sheet_shown"
// Tenor
case .tenorAccessed:
return "tenor_accessed"
case .tenorSearched:
return "tenor_searched"
case .tenorUploaded:
return "tenor_uploaded"
case .mediaLibraryAddedPhotoViaTenor:
return "media_library_photo_added"
case .editorAddedPhotoViaTenor:
return "editor_photo_added"
// Editor
case .editorPostPublishTap:
return "editor_post_publish_tapped"
case .editorPostScheduled:
Expand All @@ -49,6 +69,10 @@ import Foundation
*/
var defaultProperties: [AnyHashable: Any]? {
switch self {
case .mediaLibraryAddedPhotoViaTenor:
return ["via": "tenor"]
case .editorAddedPhotoViaTenor:
return ["via": "tenor"]
default:
return nil
}
Expand All @@ -59,11 +83,11 @@ extension WPAnalytics {

/// Track a event
///
/// This will call each registered tracker and fire the given event
/// This will call each registered tracker and fire the given event.
/// - Parameter event: a `String` that represents the event name
///
/// - Note: If an event has its default properties, it will be passed through
static func track(_ event: WPAnalyticsEvent) {
WPAnalytics.trackString(event.value)
WPAnalytics.trackString(event.value, withProperties: event.defaultProperties ?? [:])
}

/// Track a event
Expand All @@ -79,6 +103,18 @@ extension WPAnalytics {
WPAnalytics.trackString(event.value, withProperties: mergedProperties)
}


/// This will call each registered tracker and fire the given event.
/// - Parameters:
/// - event: a `String` that represents the event name
/// - properties: a `Hash` that represents the properties
/// - blog: a `Blog` asssociated with the event
static func track(_ event: WPAnalyticsEvent, properties: [AnyHashable: Any], blog: Blog) {
var props = properties
props[WPAppAnalyticsKeyBlogID] = blog.dotComID
WPAnalytics.track(event, properties: props)
}

/// Track a event in Obj-C
///
/// This will call each registered tracker and fire the given event
Expand Down
32 changes: 30 additions & 2 deletions WordPress/Classes/Utility/Analytics/WPAppAnalytics+Media.swift
Original file line number Diff line number Diff line change
Expand Up @@ -59,10 +59,16 @@ public struct MediaAnalyticsInfo {
self.selectionMethod = selectionMethod
}

func eventForMediaType(_ mediaType: MediaType) -> WPAnalyticsStat? {
func eventForMediaType(_ mediaType: MediaType) -> WPAnalyticsEvent? {
return origin.eventForMediaType(mediaType)
}

// Old tracking events via WPShared
// Ref: https://iosp2.wordpress.com/2020/03/16/adding-tracks-forget-wordpress-shared/
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably shouldn't include a p2 reference here

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Two more of these below too

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done thanks @frosty

func wpsharedEventForMediaType(_ mediaType: MediaType) -> WPAnalyticsStat? {
return origin.wpsharedEventForMediaType(mediaType)
}

var retryEvent: WPAnalyticsStat? {
switch origin {
case .mediaLibrary:
Expand Down Expand Up @@ -107,8 +113,28 @@ enum MediaUploadOrigin {
case mediaLibrary(MediaSource)
case editor(MediaSource)

func eventForMediaType(_ mediaType: MediaType) -> WPAnalyticsStat? {
// All new media tracking events will be added into WPAnalyticsEvent
// Ref: https://iosp2.wordpress.com/2020/03/16/adding-tracks-forget-wordpress-shared/
func eventForMediaType(_ mediaType: MediaType) -> WPAnalyticsEvent? {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not entirely sure why these definitions need to be split out from the existing definitions below?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey @frosty because the old tracking method uses WPAnalyticsStat from WPShared pod while the new method uses a new enum WPAnalyticsEvent

switch (self, mediaType) {
// Media Library
case (.mediaLibrary(let source), .image) where source == .tenor:
return .mediaLibraryAddedPhotoViaTenor

// Editor
case (.editor(let source), .image) where source == .tenor:
return .editorAddedPhotoViaTenor

default:
return nil
}
}

// This is for the previous events created within WordPressShared
// Ref: https://iosp2.wordpress.com/2020/03/16/adding-tracks-forget-wordpress-shared/
func wpsharedEventForMediaType(_ mediaType: MediaType) -> WPAnalyticsStat? {
switch (self, mediaType) {
// Media Library
case (.mediaLibrary(let source), .image) where source == .deviceLibrary:
return .mediaLibraryAddedPhotoViaDeviceLibrary
case (.mediaLibrary(let source), .image) where source == .giphy:
Expand All @@ -125,6 +151,7 @@ enum MediaUploadOrigin {
return .mediaLibraryAddedVideoViaOtherApps
case (.mediaLibrary(let source), .video) where source == .camera:
return .mediaLibraryAddedVideoViaCamera
// Editor
case (.editor(let source), .image) where source == .giphy :
return .editorAddedPhotoViaGiphy
case (.editor(let source), .image) where source == .deviceLibrary:
Expand Down Expand Up @@ -159,4 +186,5 @@ enum MediaSource {
case camera
case giphy
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note for a future PR: we should remove all the existing Giphy references

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is already a task for this #13803 ;-)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great, thanks!

case mediaEditor
case tenor
}
8 changes: 6 additions & 2 deletions WordPress/Classes/Utility/BuildInformation/FeatureFlag.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ enum FeatureFlag: Int, CaseIterable {
case meMove
case floatingCreateButton
case newReaderNavigation
case tenor

/// Returns a boolean indicating if the feature is enabled
var enabled: Bool {
Expand All @@ -20,8 +21,7 @@ enum FeatureFlag: Int, CaseIterable {
case .jetpackDisconnect:
return BuildConfiguration.current == .localDeveloper
case .debugMenu:
return BuildConfiguration.current ~= [.localDeveloper,
.a8cBranchTest]
return BuildConfiguration.current ~= [.localDeveloper, .a8cBranchTest]
case .unifiedAuth:
return BuildConfiguration.current == .localDeveloper
case .quickActions:
Expand All @@ -32,6 +32,8 @@ enum FeatureFlag: Int, CaseIterable {
return BuildConfiguration.current ~= [.localDeveloper, .a8cBranchTest, .a8cPrereleaseTesting]
case .newReaderNavigation:
return false
case .tenor:
return BuildConfiguration.current ~= [.localDeveloper, .a8cBranchTest]
}
}
}
Expand Down Expand Up @@ -64,6 +66,8 @@ extension FeatureFlag: OverrideableFlag {
return "Floating Create Button"
case .newReaderNavigation:
return "New Reader Navigation"
case .tenor:
return "Tenor GIF media source"
}
}

Expand Down
9 changes: 9 additions & 0 deletions WordPress/Classes/Utility/Media/GIFPlaybackStrategy.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import Foundation

@objc
public enum GIFStrategy: Int {
case tinyGIFs
case smallGIFs
case mediumGIFs
case largeGIFs
Expand All @@ -10,6 +11,8 @@ public enum GIFStrategy: Int {
///
var playbackStrategy: GIFPlaybackStrategy {
switch self {
case .tinyGIFs:
return TinyGIFPlaybackStrategy()
case .smallGIFs:
return SmallGIFPlaybackStrategy()
case .mediumGIFs:
Expand Down Expand Up @@ -51,6 +54,12 @@ extension GIFPlaybackStrategy {
return true
}
}
// This is good for thumbnail GIFs used in a collection view
class TinyGIFPlaybackStrategy: GIFPlaybackStrategy {
var maxSize = 2_000_000 // in MB
var frameBufferCount = 5
var gifStrategy: GIFStrategy = .tinyGIFs
}

class SmallGIFPlaybackStrategy: GIFPlaybackStrategy {
var maxSize = 8_000_000 // in MB
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2394,7 +2394,7 @@ extension AztecPostViewController {
/// Sets the badge title of `attachment` to "GIF" if either the media is being imported from Giphy,
/// or if it's a PHAsset with an animated playback style.
private func setGifBadgeIfNecessary(for attachment: MediaAttachment, asset: ExportableAsset, source: MediaSource) {
var isGif = (source == .giphy)
var isGif = [.giphy, .tenor].contains(source)

if let asset = asset as? PHAsset,
asset.playbackStyle == .imageAnimated {
Expand Down Expand Up @@ -3314,6 +3314,14 @@ extension AztecPostViewController: GiphyPickerDelegate {
}
}

extension AztecPostViewController: TenorPickerDelegate {
func tenorPicker(_ picker: TenorPicker, didFinishPicking assets: [TenorMedia]) {
assets.forEach {
insert(exportableAsset: $0, source: .tenor)
}
}
}

// MARK: - Constants
//
extension AztecPostViewController {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ class GutenbergViewController: UIViewController, PostEditor {
private lazy var filesAppMediaPicker: GutenbergFilesAppMediaSource = {
return GutenbergFilesAppMediaSource(gutenberg: gutenberg, mediaInserter: mediaInserterHelper)
}()
private lazy var tenorMediaPicker: GutenbergTenorMediaPicker = {
return GutenbergTenorMediaPicker(gutenberg: gutenberg, mediaInserter: mediaInserterHelper)
}()

// MARK: - Aztec

Expand Down Expand Up @@ -378,8 +381,14 @@ extension GutenbergViewController: GutenbergBridgeDelegate {
gutenbergDidRequestMediaFromDevicePicker(filter: flags, allowMultipleSelection: allowMultipleSelection, with: callback)
case .deviceCamera:
gutenbergDidRequestMediaFromCameraPicker(filter: flags, with: callback)

case .stockPhotos:
stockPhotos.presentPicker(origin: self, post: post, multipleSelection: allowMultipleSelection, callback: callback)
case .tenor:
tenorMediaPicker.presentPicker(origin: self,
post: post,
multipleSelection: allowMultipleSelection,
callback: callback)
case .filesApp:
filesAppMediaPicker.presentPicker(origin: self, filters: filter, multipleSelection: allowMultipleSelection, callback: callback)
default: break
Expand Down Expand Up @@ -637,6 +646,7 @@ extension GutenbergViewController: GutenbergBridgeDataSource {
func gutenbergMediaSources() -> [Gutenberg.MediaSource] {
return [
post.blog.supports(.stockPhotos) ? .stockPhotos : nil,
FeatureFlag.tenor.enabled ? .tenor : nil,
.filesApp,
].compactMap { $0 }
}
Expand Down Expand Up @@ -738,6 +748,7 @@ extension GutenbergViewController: PostEditorNavigationBarManagerDelegate {
extension Gutenberg.MediaSource {
static let stockPhotos = Gutenberg.MediaSource(id: "wpios-stock-photo-library", label: .freePhotosLibrary, types: [.image])
static let filesApp = Gutenberg.MediaSource(id: "wpios-files-app", label: .files, types: [.image, .video, .audio, .other])
static let tenor = Gutenberg.MediaSource(id: "wpios-tenor", label: .tenor, types: [.image])
}

private extension GutenbergViewController {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
import Gutenberg

class GutenbergTenorMediaPicker {
private var tenor: TenorPicker?
private var mediaPickerCallback: MediaPickerDidPickMediaCallback?
private let mediaInserter: GutenbergMediaInserterHelper
private unowned var gutenberg: Gutenberg
private var multipleSelection = false

init(gutenberg: Gutenberg, mediaInserter: GutenbergMediaInserterHelper) {
self.mediaInserter = mediaInserter
self.gutenberg = gutenberg
}

func presentPicker(origin: UIViewController, post: AbstractPost, multipleSelection: Bool, callback: @escaping MediaPickerDidPickMediaCallback) {
let picker = TenorPicker()
tenor = picker
picker.allowMultipleSelection = true
picker.delegate = self
mediaPickerCallback = callback
picker.presentPicker(origin: origin, blog: post.blog)
self.multipleSelection = multipleSelection
}
}

extension GutenbergTenorMediaPicker: TenorPickerDelegate {
func tenorPicker(_ picker: TenorPicker, didFinishPicking assets: [TenorMedia]) {
defer {
mediaPickerCallback = nil
tenor = nil
}
guard assets.isEmpty == false else {
mediaPickerCallback?(nil)
return
}

// For blocks that support multiple uploads this will upload all images.
// If multiple uploads are not supported then it will seperate them out to Image Blocks.
multipleSelection ? insertOnBlock(with: assets) : insertSingleImages(assets)
}

/// Adds the given image object to the requesting block and seperates multiple images to seperate image blocks
/// - Parameter asset: Tenor Media object to add.
func insertSingleImages(_ assets: [TenorMedia]) {
// Append the first item via callback given by Gutenberg.
if let firstItem = assets.first {
insertOnBlock(with: [firstItem])
}
// Append the rest of images via `.appendMedia` event.
// Ideally we would send all picked images via the given callback, but that seems to not be possible yet.
appendOnNewBlocks(assets: assets.dropFirst())
}

/// Adds the given images to the requesting block
/// - Parameter assets: Tenor Media objects to add.
func insertOnBlock(with assets: [TenorMedia]) {
guard let callback = mediaPickerCallback else {
return assertionFailure("Image picked without callback")
}

let mediaInfo = assets.compactMap { (asset) -> MediaInfo? in
guard let media = self.mediaInserter.insert(exportableAsset: asset, source: .tenor) else {
return nil
}
let mediaUploadID = media.gutenbergUploadID
return MediaInfo(id: mediaUploadID, url: asset.URL.absoluteString, type: media.mediaTypeString)
}

callback(mediaInfo)
}

/// Create a new image block for each of the image objects in the slice.
/// - Parameter assets: Tenor Media objects to append.
func appendOnNewBlocks(assets: ArraySlice<TenorMedia>) {
assets.forEach {
if let media = self.mediaInserter.insert(exportableAsset: $0, source: .tenor) {
self.gutenberg.appendMedia(id: media.gutenbergUploadID, url: $0.URL, type: .image)
}
}
}
}
Loading