mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-12-16 03:09:56 +00:00
Added emoji keyword search
This commit is contained in:
parent
ebc595a62f
commit
8e1b8843b3
@ -388,7 +388,7 @@ class ChatMessageInteractiveInstantVideoNode: ASDisplayNode {
|
||||
updatedPlayerStatusSignal = videoNode.status
|
||||
|> mapToSignal { status -> Signal<MediaPlayerStatus?, NoError> in
|
||||
if let status = status, case .buffering = status.status {
|
||||
return .single(status) |> delay(1.0, queue: Queue.mainQueue())
|
||||
return .single(status) |> delay(0.5, queue: Queue.mainQueue())
|
||||
} else {
|
||||
return .single(status)
|
||||
}
|
||||
|
||||
@ -1005,7 +1005,7 @@ final class ChatMessageInteractiveMediaNode: ASDisplayNode {
|
||||
} else if isSecretMedia, let secretProgressIcon = secretProgressIcon {
|
||||
state = .customIcon(secretProgressIcon)
|
||||
} else if let file = media as? TelegramMediaFile {
|
||||
let isInlinePlayableVideo = file.isVideo && !isSecretMedia && automaticPlayback
|
||||
let isInlinePlayableVideo = file.isVideo && !isSecretMedia && (self.automaticPlayback ?? false)
|
||||
if !isInlinePlayableVideo && file.isVideo {
|
||||
state = .play(bubbleTheme.mediaOverlayControlForegroundColor)
|
||||
} else {
|
||||
@ -1069,11 +1069,13 @@ final class ChatMessageInteractiveMediaNode: ASDisplayNode {
|
||||
}
|
||||
|
||||
if let statusNode = self.statusNode {
|
||||
if state == .none {
|
||||
var removeStatusNode = false
|
||||
if statusNode.state != .none && state == .none {
|
||||
self.statusNode = nil
|
||||
removeStatusNode = true
|
||||
}
|
||||
statusNode.transitionToState(state, completion: { [weak statusNode] in
|
||||
if state == .none {
|
||||
if removeStatusNode {
|
||||
statusNode?.removeFromSupernode()
|
||||
}
|
||||
})
|
||||
@ -1217,6 +1219,8 @@ final class ChatMessageInteractiveMediaNode: ASDisplayNode {
|
||||
var actionAtEnd: MediaPlayerPlayOnceWithSoundActionAtEnd = .loopDisablingSound
|
||||
if let message = self.message, message.id.peerId.namespace == Namespaces.Peer.CloudChannel {
|
||||
actionAtEnd = .loop
|
||||
} else {
|
||||
actionAtEnd = .repeatIfNeeded
|
||||
}
|
||||
|
||||
if let videoNode = self.videoNode, let context = self.context, (self.automaticPlayback ?? false) && !isAnimated {
|
||||
|
||||
@ -72,7 +72,7 @@ final class GifPaneSearchContentNode: ASDisplayNode & PaneSearchContentNode {
|
||||
self.searchDisposable.dispose()
|
||||
}
|
||||
|
||||
func updateText(_ text: String) {
|
||||
func updateText(_ text: String, languageCode: String?) {
|
||||
let signal: Signal<[FileMediaReference]?, NoError>
|
||||
if !text.isEmpty {
|
||||
signal = self.signalForQuery(text)
|
||||
@ -133,7 +133,7 @@ final class GifPaneSearchContentNode: ASDisplayNode & PaneSearchContentNode {
|
||||
}
|
||||
|
||||
if firstLayout {
|
||||
self.updateText("")
|
||||
self.updateText("", languageCode: nil)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -52,6 +52,7 @@ enum MediaPlayerPlayOnceWithSoundActionAtEnd {
|
||||
case loop
|
||||
case loopDisablingSound
|
||||
case stop
|
||||
case repeatIfNeeded
|
||||
}
|
||||
|
||||
enum MediaPlayerPlayOnceWithSoundSeek {
|
||||
|
||||
@ -275,7 +275,27 @@ private final class NativeVideoContentNode: ASDisplayNode, UniversalVideoContent
|
||||
self.player.actionAtEnd = .loopDisablingSound(action)
|
||||
case .stop:
|
||||
self.player.actionAtEnd = .action(action)
|
||||
case .repeatIfNeeded:
|
||||
let _ = (self.player.status
|
||||
|> deliverOnMainQueue
|
||||
|> take(1)).start(next: { [weak self] status in
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
if status.timestamp > status.duration * 0.1 {
|
||||
strongSelf.player.actionAtEnd = .action({ [weak self] in
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
strongSelf.player.seek(timestamp: 0.0)
|
||||
strongSelf.player.actionAtEnd = .loopDisablingSound(action)
|
||||
})
|
||||
} else {
|
||||
strongSelf.player.actionAtEnd = .loopDisablingSound(action)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
self.player.playOnceWithSound(playAndRecord: playAndRecord, seekToStart: seekToStart)
|
||||
}
|
||||
|
||||
@ -298,7 +318,7 @@ private final class NativeVideoContentNode: ASDisplayNode, UniversalVideoContent
|
||||
switch actionAtEnd {
|
||||
case .loop:
|
||||
self.player.actionAtEnd = .loop({})
|
||||
case .loopDisablingSound:
|
||||
case .loopDisablingSound, .repeatIfNeeded:
|
||||
self.player.actionAtEnd = .loopDisablingSound(action)
|
||||
case .stop:
|
||||
self.player.actionAtEnd = .action(action)
|
||||
|
||||
@ -121,7 +121,7 @@ private class PaneSearchBarTextField: UITextField {
|
||||
|
||||
class PaneSearchBarNode: ASDisplayNode, UITextFieldDelegate {
|
||||
var cancel: (() -> Void)?
|
||||
var textUpdated: ((String) -> Void)?
|
||||
var textUpdated: ((String, String) -> Void)?
|
||||
var clearPrefix: (() -> Void)?
|
||||
|
||||
private let backgroundNode: ASDisplayNode
|
||||
@ -446,7 +446,7 @@ class PaneSearchBarNode: ASDisplayNode, UITextFieldDelegate {
|
||||
@objc func textFieldDidChange(_ textField: UITextField) {
|
||||
self.updateIsEmpty()
|
||||
if let textUpdated = self.textUpdated {
|
||||
textUpdated(textField.text ?? "")
|
||||
textUpdated(textField.text ?? "", self.textField.textInputMode?.primaryLanguage ?? "")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -13,7 +13,7 @@ protocol PaneSearchContentNode {
|
||||
var updateActivity: ((Bool) -> Void)? { get set }
|
||||
|
||||
func updateThemeAndStrings(theme: PresentationTheme, strings: PresentationStrings)
|
||||
func updateText(_ text: String)
|
||||
func updateText(_ text: String, languageCode: String?)
|
||||
func updateLayout(size: CGSize, leftInset: CGFloat, rightInset: CGFloat, bottomInset: CGFloat, inputHeight: CGFloat, transition: ContainedViewLayoutTransition)
|
||||
|
||||
func animateIn(additivePosition: CGFloat, transition: ContainedViewLayoutTransition)
|
||||
@ -74,8 +74,8 @@ final class PaneSearchContainerNode: ASDisplayNode {
|
||||
}
|
||||
self.searchBar.activate()
|
||||
|
||||
self.searchBar.textUpdated = { [weak self] text in
|
||||
self?.contentNode.updateText(text)
|
||||
self.searchBar.textUpdated = { [weak self] text, languageCode in
|
||||
self?.contentNode.updateText(text, languageCode: languageCode)
|
||||
}
|
||||
|
||||
self.updateThemeAndStrings(theme: theme, strings: strings)
|
||||
|
||||
@ -207,9 +207,14 @@ public final class RadialStatusNode: ASControlNode {
|
||||
contentNode.frame = self.bounds
|
||||
contentNode.prepareAnimateIn(from: nil)
|
||||
self.addSubnode(contentNode)
|
||||
if animated, case .check = state, self.isNodeLoaded {
|
||||
contentNode.layout()
|
||||
contentNode.animateIn(from: fromState, delay: 0.0)
|
||||
if animated, self.isNodeLoaded {
|
||||
switch state {
|
||||
case .check, .progress:
|
||||
contentNode.layout()
|
||||
contentNode.animateIn(from: fromState, delay: 0.0)
|
||||
default:
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
self.transitionToBackgroundColor(backgroundColor, previousContentNode: nil, animated: animated, completion: completion)
|
||||
|
||||
@ -151,6 +151,11 @@ final class StickerPaneSearchContentNode: ASDisplayNode, PaneSearchContentNode {
|
||||
|
||||
private var enqueuedTransitions: [StickerPaneSearchGridTransition] = []
|
||||
|
||||
private let languageCodePromise = ValuePromise<String>(ignoreRepeated: true)
|
||||
private let emojiKeywordsPromise = Promise<EmojiKeywords?>()
|
||||
|
||||
private var languageCodeDisposable: Disposable?
|
||||
|
||||
private let searchDisposable = MetaDisposable()
|
||||
|
||||
private let queue = Queue()
|
||||
@ -250,34 +255,60 @@ final class StickerPaneSearchContentNode: ASDisplayNode, PaneSearchContentNode {
|
||||
self._ready.set(self.trendingPane.ready)
|
||||
self.trendingPane.activate()
|
||||
|
||||
self.languageCodeDisposable = (self.languageCodePromise.get()
|
||||
|> deliverOnMainQueue).start(next: { [weak self] languageCode in
|
||||
if let strongSelf = self {
|
||||
strongSelf.emojiKeywordsPromise.set(emojiKeywords(accountManager: strongSelf.context.sharedContext.accountManager, network: strongSelf.context.account.network, inputLanguageCode: languageCode))
|
||||
}
|
||||
})
|
||||
|
||||
self.updateThemeAndStrings(theme: theme, strings: strings)
|
||||
}
|
||||
|
||||
deinit {
|
||||
self.languageCodeDisposable?.dispose()
|
||||
self.searchDisposable.dispose()
|
||||
}
|
||||
|
||||
func updateText(_ text: String) {
|
||||
func updateText(_ text: String, languageCode: String?) {
|
||||
let signal: Signal<([(String?, FoundStickerItem)], FoundStickerSets, Bool, FoundStickerSets?)?, NoError>
|
||||
if !text.isEmpty {
|
||||
if let languageCode = languageCode, !languageCode.isEmpty {
|
||||
self.languageCodePromise.set(languageCode)
|
||||
}
|
||||
|
||||
let stickers: Signal<[(String?, FoundStickerItem)], NoError> = Signal { subscriber in
|
||||
var signals: [Signal<(String?, [FoundStickerItem]), NoError>] = []
|
||||
var signals: Signal<[Signal<(String?, [FoundStickerItem]), NoError>], NoError> = .single([])
|
||||
|
||||
if text.trimmingCharacters(in: .whitespacesAndNewlines).isSingleEmoji {
|
||||
signals.append(searchStickers(account: self.context.account, query: text.firstEmoji)
|
||||
let trimmed = text.trimmingCharacters(in: .whitespacesAndNewlines)
|
||||
if trimmed.isSingleEmoji {
|
||||
signals = .single([searchStickers(account: self.context.account, query: text.firstEmoji)
|
||||
|> take(1)
|
||||
|> map { (nil, $0) })
|
||||
} else {
|
||||
for entry in TGEmojiSuggestions.suggestions(forQuery: text.lowercased()) {
|
||||
if let entry = entry as? TGAlphacodeEntry {
|
||||
signals.append(searchStickers(account: self.context.account, query: entry.emoji)
|
||||
|> take(1)
|
||||
|> map { (entry.emoji, $0) })
|
||||
|> map { (nil, $0) }])
|
||||
} else if trimmed.count > 1 {
|
||||
signals = self.emojiKeywordsPromise.get()
|
||||
|> mapToSignal { keywords in
|
||||
if let keywords = keywords {
|
||||
return searchEmojiKeywords(keywords: keywords, query: trimmed.lowercased(), completeMatch: true)
|
||||
|> map { result -> [Signal<(String?, [FoundStickerItem]), NoError>] in
|
||||
var signals: [Signal<(String?, [FoundStickerItem]), NoError>] = []
|
||||
for emoji in result {
|
||||
signals.append(searchStickers(account: self.context.account, query: emoji)
|
||||
|> take(1)
|
||||
|> map { (emoji, $0) })
|
||||
}
|
||||
return signals
|
||||
}
|
||||
} else {
|
||||
return .complete()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return combineLatest(signals).start(next: { results in
|
||||
return (signals
|
||||
|> mapToSignal { signals in
|
||||
return combineLatest(signals)
|
||||
}).start(next: { results in
|
||||
var result: [(String?, FoundStickerItem)] = []
|
||||
for (emoji, stickers) in results {
|
||||
for sticker in stickers {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user