diff --git a/submodules/TelegramUI/Images.xcassets/Media Grid/Tenor.imageset/Contents.json b/submodules/TelegramUI/Images.xcassets/Media Grid/Tenor.imageset/Contents.json new file mode 100644 index 0000000000..3c9e5dfc42 --- /dev/null +++ b/submodules/TelegramUI/Images.xcassets/Media Grid/Tenor.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "tenor@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "tenor@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/submodules/TelegramUI/Images.xcassets/Media Grid/Tenor.imageset/tenor@2x.png b/submodules/TelegramUI/Images.xcassets/Media Grid/Tenor.imageset/tenor@2x.png new file mode 100644 index 0000000000..2cda9ab0e9 Binary files /dev/null and b/submodules/TelegramUI/Images.xcassets/Media Grid/Tenor.imageset/tenor@2x.png differ diff --git a/submodules/TelegramUI/Images.xcassets/Media Grid/Tenor.imageset/tenor@3x.png b/submodules/TelegramUI/Images.xcassets/Media Grid/Tenor.imageset/tenor@3x.png new file mode 100644 index 0000000000..61b54741c1 Binary files /dev/null and b/submodules/TelegramUI/Images.xcassets/Media Grid/Tenor.imageset/tenor@3x.png differ diff --git a/submodules/WebSearchUI/Sources/WebSearchController.swift b/submodules/WebSearchUI/Sources/WebSearchController.swift index d5f037e7c6..5dce5d8175 100644 --- a/submodules/WebSearchUI/Sources/WebSearchController.swift +++ b/submodules/WebSearchUI/Sources/WebSearchController.swift @@ -104,6 +104,18 @@ private func selectionChangedSignal(selectionState: TGMediaSelectionContext) -> } } +public struct WebSearchConfiguration: Equatable { + public let gifProvider: String? + + public init(appConfiguration: AppConfiguration) { + var gifProvider: String? = nil + if let data = appConfiguration.data, let value = data["gif_search_branding"] as? String { + gifProvider = value + } + self.gifProvider = gifProvider + } +} + public final class WebSearchController: ViewController { private var validLayout: ContainerViewLayout? @@ -165,9 +177,19 @@ public final class WebSearchController: ViewController { return WebSearchSettings.defaultSettings } } + + let gifProvider = self.context.account.postbox.preferencesView(keys: [PreferencesKeys.appConfiguration]) + |> map { view -> String? in + guard let appConfiguration = view.values[PreferencesKeys.appConfiguration] as? AppConfiguration else { + return nil + } + let configuration = WebSearchConfiguration(appConfiguration: appConfiguration) + return configuration.gifProvider + } + |> distinctUntilChanged - self.disposable = ((combineLatest(settings, context.sharedContext.presentationData)) - |> deliverOnMainQueue).start(next: { [weak self] settings, presentationData in + self.disposable = ((combineLatest(settings, context.sharedContext.presentationData, gifProvider)) + |> deliverOnMainQueue).start(next: { [weak self] settings, presentationData, gifProvider in guard let strongSelf = self else { return } @@ -179,6 +201,9 @@ public final class WebSearchController: ViewController { if current.presentationData !== presentationData { updated = updated.withUpdatedPresentationData(presentationData) } + if current.gifProvider != gifProvider { + updated = updated.withUpdatedGifProvider(gifProvider) + } return updated } }) @@ -310,13 +335,14 @@ public final class WebSearchController: ViewController { let previousInterfaceState = self.interfaceState let previousTheme = self.interfaceState.presentationData.theme let previousStrings = self.interfaceState.presentationData.theme + let previousGifProvider = self.interfaceState.gifProvider let updatedInterfaceState = f(self.interfaceState) self.interfaceState = updatedInterfaceState self.interfaceStatePromise.set(updatedInterfaceState) if self.isNodeLoaded { - if previousTheme !== updatedInterfaceState.presentationData.theme || previousStrings !== updatedInterfaceState.presentationData.strings { + if previousTheme !== updatedInterfaceState.presentationData.theme || previousStrings !== updatedInterfaceState.presentationData.strings || previousGifProvider != updatedInterfaceState.gifProvider { self.controllerNode.updatePresentationData(theme: updatedInterfaceState.presentationData.theme, strings: updatedInterfaceState.presentationData.strings) } if previousInterfaceState != self.interfaceState { diff --git a/submodules/WebSearchUI/Sources/WebSearchControllerNode.swift b/submodules/WebSearchUI/Sources/WebSearchControllerNode.swift index e68aa0ddf3..d503def187 100644 --- a/submodules/WebSearchUI/Sources/WebSearchControllerNode.swift +++ b/submodules/WebSearchUI/Sources/WebSearchControllerNode.swift @@ -348,8 +348,26 @@ class WebSearchControllerNode: ASDisplayNode { self.segmentedControlNode.updateTheme(SegmentedControlTheme(theme: self.theme)) self.toolbarBackgroundNode.backgroundColor = self.theme.rootController.navigationBar.backgroundColor self.toolbarSeparatorNode.backgroundColor = self.theme.rootController.navigationBar.separatorColor - - self.attributionNode.image = generateTintedImage(image: UIImage(bundleImageName: "Media Grid/Giphy"), color: self.theme.list.itemSecondaryTextColor) + } + + let gifProviderImage: UIImage? + if let gifProvider = self.webSearchInterfaceState.gifProvider { + switch gifProvider { + case "tenor": + gifProviderImage = generateTintedImage(image: UIImage(bundleImageName: "Media Grid/Tenor"), color: self.theme.list.itemSecondaryTextColor) + case "giphy": + gifProviderImage = generateTintedImage(image: UIImage(bundleImageName: "Media Grid/Giphy"), color: self.theme.list.itemSecondaryTextColor) + default: + gifProviderImage = nil + } + } else { + gifProviderImage = nil + } + let previousGifProviderImage = self.attributionNode.image + self.attributionNode.image = gifProviderImage + + if previousGifProviderImage == nil, let validLayout = self.containerLayout { + self.containerLayoutUpdated(validLayout.0, navigationBarHeight: validLayout.1, transition: .immediate) } } @@ -386,7 +404,7 @@ class WebSearchControllerNode: ASDisplayNode { transition.updateFrame(node: self.toolbarSeparatorNode, frame: CGRect(origin: CGPoint(x: 0.0, y: toolbarY), size: CGSize(width: layout.size.width, height: UIScreenPixel))) if let image = self.attributionNode.image { - transition.updateFrame(node: self.attributionNode, frame: CGRect(origin: CGPoint(x: floor((layout.size.width - image.size.width) / 2.0), y: toolbarY + floor((toolbarHeight - image.size.height) / 2.0)), size: image.size)) + self.attributionNode.frame = CGRect(origin: CGPoint(x: floor((layout.size.width - image.size.width) / 2.0), y: toolbarY + floor((toolbarHeight - image.size.height) / 2.0)), size: image.size) transition.updateAlpha(node: self.attributionNode, alpha: self.webSearchInterfaceState.state?.scope == .gifs ? 1.0 : 0.0) } @@ -456,6 +474,7 @@ class WebSearchControllerNode: ASDisplayNode { } func updateInterfaceState(_ interfaceState: WebSearchInterfaceState, animated: Bool) { + let previousGifProvider = self.webSearchInterfaceState.gifProvider self.webSearchInterfaceState = interfaceState self.webSearchInterfaceStatePromise.set(self.webSearchInterfaceState) @@ -463,6 +482,10 @@ class WebSearchControllerNode: ASDisplayNode { self.segmentedControlNode.selectedIndex = Int(state.scope.rawValue) } + if previousGifProvider != interfaceState.gifProvider { + self.applyPresentationData(themeUpdated: false) + } + if let validLayout = self.containerLayout { self.containerLayoutUpdated(validLayout.0, navigationBarHeight: validLayout.1, transition: animated ? .animated(duration: 0.4, curve: .spring) : .immediate) } diff --git a/submodules/WebSearchUI/Sources/WebSearchInterfaceState.swift b/submodules/WebSearchUI/Sources/WebSearchInterfaceState.swift index bc67ae5408..ddeb5e1684 100644 --- a/submodules/WebSearchUI/Sources/WebSearchInterfaceState.swift +++ b/submodules/WebSearchUI/Sources/WebSearchInterfaceState.swift @@ -11,26 +11,33 @@ struct WebSearchInterfaceInnerState: Equatable { struct WebSearchInterfaceState: Equatable { let state: WebSearchInterfaceInnerState? let presentationData: PresentationData + let gifProvider: String? init (presentationData: PresentationData) { self.state = nil self.presentationData = presentationData + self.gifProvider = nil } - init(state: WebSearchInterfaceInnerState?, presentationData: PresentationData) { + init(state: WebSearchInterfaceInnerState?, presentationData: PresentationData, gifProvider: String? = nil) { self.state = state self.presentationData = presentationData + self.gifProvider = gifProvider } func withUpdatedScope(_ scope: WebSearchScope) -> WebSearchInterfaceState { - return WebSearchInterfaceState(state: WebSearchInterfaceInnerState(scope: scope, query: self.state?.query ?? ""), presentationData: self.presentationData) + return WebSearchInterfaceState(state: WebSearchInterfaceInnerState(scope: scope, query: self.state?.query ?? ""), presentationData: self.presentationData, gifProvider: self.gifProvider) } func withUpdatedQuery(_ query: String) -> WebSearchInterfaceState { - return WebSearchInterfaceState(state: WebSearchInterfaceInnerState(scope: self.state?.scope ?? .images, query: query), presentationData: self.presentationData) + return WebSearchInterfaceState(state: WebSearchInterfaceInnerState(scope: self.state?.scope ?? .images, query: query), presentationData: self.presentationData, gifProvider: self.gifProvider) } func withUpdatedPresentationData(_ presentationData: PresentationData) -> WebSearchInterfaceState { - return WebSearchInterfaceState(state: self.state, presentationData: presentationData) + return WebSearchInterfaceState(state: self.state, presentationData: presentationData, gifProvider: self.gifProvider) + } + + func withUpdatedGifProvider(_ gifProvider: String?) -> WebSearchInterfaceState { + return WebSearchInterfaceState(state: self.state, presentationData: self.presentationData, gifProvider: gifProvider) } }