mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
Various improvements
This commit is contained in:
parent
6b528aa70f
commit
c4013c3df6
@ -1244,7 +1244,7 @@ private final class FeaturedPaneSearchContentNode: ASDisplayNode {
|
||||
|
||||
let query = text.trimmingCharacters(in: .whitespacesAndNewlines)
|
||||
if query.isSingleEmoji {
|
||||
signals = .single([context.engine.stickers.searchStickers(query: [text.basicEmoji.0])
|
||||
signals = .single([context.engine.stickers.searchStickers(query: nil, emoticon: [text.basicEmoji.0], inputLanguageCode: "")
|
||||
|> map { (nil, $0.items) }])
|
||||
} else if query.count > 1, let languageCode = languageCode, !languageCode.isEmpty && languageCode != "emoji" {
|
||||
var signal = context.engine.stickers.searchEmojiKeywords(inputLanguageCode: languageCode, query: query.lowercased(), completeMatch: query.count < 3)
|
||||
@ -1260,17 +1260,11 @@ private final class FeaturedPaneSearchContentNode: ASDisplayNode {
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
signals = signal
|
||||
|> map { keywords -> [Signal<(String?, [FoundStickerItem]), NoError>] in
|
||||
var signals: [Signal<(String?, [FoundStickerItem]), NoError>] = []
|
||||
let emoticons = keywords.flatMap { $0.emoticons }
|
||||
for emoji in emoticons {
|
||||
signals.append(context.engine.stickers.searchStickers(query: [emoji.basicEmoji.0])
|
||||
|> take(1)
|
||||
|> map { (emoji, $0.items) })
|
||||
}
|
||||
return signals
|
||||
let emoticon = keywords.flatMap { $0.emoticons }.map { $0.basicEmoji.0 }
|
||||
return [context.engine.stickers.searchStickers(query: query, emoticon: emoticon, inputLanguageCode: languageCode)
|
||||
|> map { (nil, $0.items) }]
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1428,7 +1428,7 @@
|
||||
|| [view isDescendantOfView:_landscapeToolbarView]
|
||||
|| [view isDescendantOfView:_selectedPhotosView]
|
||||
|| [view isDescendantOfView:_captionMixin.inputPanelView]
|
||||
|| [view isDescendantOfView:_captionMixin.dismissView]
|
||||
|| ([view isDescendantOfView:_captionMixin.dismissView] && _captionMixin.dismissView.alpha > 0.0)
|
||||
|| [view isKindOfClass:[TGMenuButtonView class]])
|
||||
|
||||
{
|
||||
|
@ -100,9 +100,9 @@ typedef enum
|
||||
_currentTimeLabel.text = @"0:00";
|
||||
_currentTimeLabel.textColor = [UIColor whiteColor];
|
||||
_currentTimeLabel.layer.shadowOffset = CGSizeMake(0.0, 0.0);
|
||||
_currentTimeLabel.layer.shadowRadius = 2.0;
|
||||
_currentTimeLabel.layer.shadowRadius = 4.0;
|
||||
_currentTimeLabel.layer.shadowColor = [UIColor blackColor].CGColor;
|
||||
_currentTimeLabel.layer.shadowOpacity = 0.4;
|
||||
_currentTimeLabel.layer.shadowOpacity = 0.6;
|
||||
_currentTimeLabel.layer.rasterizationScale = TGScreenScaling();
|
||||
_currentTimeLabel.layer.shouldRasterize = true;
|
||||
[self addSubview:_currentTimeLabel];
|
||||
@ -115,9 +115,9 @@ typedef enum
|
||||
_inverseTimeLabel.textAlignment = NSTextAlignmentRight;
|
||||
_inverseTimeLabel.textColor = [UIColor whiteColor];
|
||||
_inverseTimeLabel.layer.shadowOffset = CGSizeMake(0.0, 0.0);
|
||||
_inverseTimeLabel.layer.shadowRadius = 2.0;
|
||||
_inverseTimeLabel.layer.shadowRadius = 4.0;
|
||||
_inverseTimeLabel.layer.shadowColor = [UIColor blackColor].CGColor;
|
||||
_inverseTimeLabel.layer.shadowOpacity = 0.4;
|
||||
_inverseTimeLabel.layer.shadowOpacity = 0.6;
|
||||
_inverseTimeLabel.layer.rasterizationScale = TGScreenScaling();
|
||||
_inverseTimeLabel.layer.shouldRasterize = true;
|
||||
[self addSubview:_inverseTimeLabel];
|
||||
|
@ -61,7 +61,6 @@
|
||||
_inputPanel.sendPressed = ^(NSAttributedString *string) {
|
||||
__strong TGPhotoCaptionInputMixin *strongSelf = weakSelf;
|
||||
[TGViewController enableAutorotation];
|
||||
strongSelf->_dismissView.hidden = true;
|
||||
|
||||
strongSelf->_editing = false;
|
||||
|
||||
@ -74,9 +73,7 @@
|
||||
[TGViewController disableAutorotation];
|
||||
|
||||
[strongSelf beginEditing];
|
||||
|
||||
strongSelf->_dismissView.hidden = false;
|
||||
|
||||
|
||||
if (strongSelf.panelFocused != nil)
|
||||
strongSelf.panelFocused();
|
||||
|
||||
@ -129,12 +126,13 @@
|
||||
|
||||
_dismissView = [[UIView alloc] initWithFrame:parentView.bounds];
|
||||
_dismissView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
|
||||
_dismissView.backgroundColor = [UIColor colorWithWhite:0.0 alpha:0.4];
|
||||
|
||||
_dismissTapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleDismissTap:)];
|
||||
_dismissTapRecognizer.enabled = false;
|
||||
[_dismissView addGestureRecognizer:_dismissTapRecognizer];
|
||||
|
||||
//[parentView insertSubview:_dismissView belowSubview:_backgroundView];
|
||||
[parentView insertSubview:_dismissView belowSubview:_inputPanelView];
|
||||
}
|
||||
|
||||
- (void)setCaption:(NSAttributedString *)caption
|
||||
@ -168,6 +166,12 @@
|
||||
|
||||
[self createDismissViewIfNeeded];
|
||||
[self createInputPanelIfNeeded];
|
||||
|
||||
_dismissView.alpha = 0.0;
|
||||
[UIView animateWithDuration:0.3 delay:0.0 options:UIViewAnimationOptionCurveEaseInOut animations:^{
|
||||
_dismissView.alpha = 1.0f;
|
||||
} completion:^(BOOL finished) {
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)enableDismissal
|
||||
@ -184,9 +188,7 @@
|
||||
|
||||
if ([self.inputPanel dismissInput]) {
|
||||
_editing = false;
|
||||
|
||||
[_dismissView removeFromSuperview];
|
||||
|
||||
|
||||
if (self.finishedWithCaption != nil)
|
||||
self.finishedWithCaption([_inputPanel caption]);
|
||||
}
|
||||
@ -228,6 +230,19 @@
|
||||
|
||||
_keyboardHeight = keyboardHeight;
|
||||
|
||||
CGFloat fadeAlpha = 1.0;
|
||||
if (keyboardHeight < FLT_EPSILON) {
|
||||
fadeAlpha = 0.0;
|
||||
}
|
||||
|
||||
if (ABS(_dismissView.alpha - fadeAlpha) > FLT_EPSILON) {
|
||||
[UIView animateWithDuration:0.3 delay:0.0 options:UIViewAnimationOptionCurveEaseInOut animations:^{
|
||||
_dismissView.alpha = fadeAlpha;
|
||||
} completion:^(BOOL finished) {
|
||||
|
||||
}];
|
||||
}
|
||||
|
||||
if (!UIInterfaceOrientationIsPortrait([[LegacyComponentsGlobals provider] applicationStatusBarOrientation]) && !TGIsPad())
|
||||
return;
|
||||
|
||||
|
@ -2028,7 +2028,7 @@ public final class ReactionContextNode: ASDisplayNode, ASScrollViewDelegate {
|
||||
))
|
||||
return .single(resultGroups)
|
||||
} else {
|
||||
let remoteSignal = context.engine.stickers.searchEmoji(emojiString: Array(allEmoticons.keys))
|
||||
let remoteSignal = context.engine.stickers.searchEmoji(query: query, emoticon: Array(allEmoticons.keys), inputLanguageCode: languageCode)
|
||||
|
||||
return combineLatest(
|
||||
context.account.postbox.itemCollectionsView(orderedItemListCollectionIds: [], namespaces: [Namespaces.ItemCollection.CloudEmojiPacks], aroundIndex: nil, count: 10000000) |> take(1),
|
||||
|
@ -1608,9 +1608,9 @@ private func monetizationEntries(
|
||||
|
||||
if canViewRevenue {
|
||||
entries.append(.adsTonBalanceTitle(presentationData.theme, isBot ? presentationData.strings.Monetization_Bot_BalanceTitle : presentationData.strings.Monetization_TonBalanceTitle))
|
||||
entries.append(.adsTonBalance(presentationData.theme, data, isCreator && data.balances.availableBalance > 0, data.balances.withdrawEnabled))
|
||||
entries.append(.adsTonBalance(presentationData.theme, data, (isCreator || isBot) && data.balances.availableBalance > 0, data.balances.withdrawEnabled))
|
||||
|
||||
if isCreator {
|
||||
if isCreator || isBot {
|
||||
let withdrawalInfoText: String
|
||||
if data.balances.availableBalance == 0 {
|
||||
withdrawalInfoText = presentationData.strings.Monetization_Balance_ZeroInfo
|
||||
|
@ -210,7 +210,7 @@ public class BoxedMessage: NSObject {
|
||||
|
||||
public class Serialization: NSObject, MTSerialization {
|
||||
public func currentLayer() -> UInt {
|
||||
return 193
|
||||
return 195
|
||||
}
|
||||
|
||||
public func parseMessage(_ data: Data!) -> Any! {
|
||||
|
@ -81,13 +81,20 @@ func _internal_randomGreetingSticker(account: Account) -> Signal<FoundStickerIte
|
||||
}
|
||||
}
|
||||
|
||||
func _internal_searchStickers(account: Account, query: [String], scope: SearchStickersScope = [.installed, .remote]) -> Signal<(items: [FoundStickerItem], isFinalResult: Bool), NoError> {
|
||||
func _internal_searchStickers(account: Account, query: String?, emoticon: [String], inputLanguageCode: String, scope: SearchStickersScope = [.installed, .remote]) -> Signal<(items: [FoundStickerItem], isFinalResult: Bool), NoError> {
|
||||
if scope.isEmpty {
|
||||
return .single(([], true))
|
||||
}
|
||||
var query = query
|
||||
if query == ["\u{2764}"] {
|
||||
query = ["\u{2764}\u{FE0F}"]
|
||||
var emoticon = emoticon
|
||||
if emoticon == ["\u{2764}"] {
|
||||
emoticon = ["\u{2764}\u{FE0F}"]
|
||||
}
|
||||
|
||||
let cacheKey: String
|
||||
if let query, !query.isEmpty {
|
||||
cacheKey = query
|
||||
} else {
|
||||
cacheKey = emoticon.sorted().joined()
|
||||
}
|
||||
|
||||
return account.postbox.transaction { transaction -> ([FoundStickerItem], CachedStickerQueryResult?, Bool, SearchStickersConfiguration) in
|
||||
@ -98,7 +105,7 @@ func _internal_searchStickers(account: Account, query: [String], scope: SearchSt
|
||||
for entry in transaction.getOrderedListItems(collectionId: Namespaces.OrderedItemList.CloudSavedStickers) {
|
||||
if let item = entry.contents.get(SavedStickerItem.self) {
|
||||
for representation in item.stringRepresentations {
|
||||
for queryItem in query {
|
||||
for queryItem in emoticon {
|
||||
if representation.hasPrefix(queryItem) {
|
||||
result.append(FoundStickerItem(file: item.file, stringRepresentations: item.stringRepresentations))
|
||||
break
|
||||
@ -125,7 +132,7 @@ func _internal_searchStickers(account: Account, query: [String], scope: SearchSt
|
||||
currentItems.insert(file.fileId)
|
||||
|
||||
for case let .Sticker(displayText, _, _) in file.attributes {
|
||||
for queryItem in query {
|
||||
for queryItem in emoticon {
|
||||
if displayText.hasPrefix(queryItem) {
|
||||
matchingRecentItemsIds.insert(file.fileId)
|
||||
break
|
||||
@ -143,12 +150,9 @@ func _internal_searchStickers(account: Account, query: [String], scope: SearchSt
|
||||
}
|
||||
}
|
||||
|
||||
var searchQueries: [ItemCollectionSearchQuery] = query.map { queryItem -> ItemCollectionSearchQuery in
|
||||
let searchQueries: [ItemCollectionSearchQuery] = emoticon.map { queryItem -> ItemCollectionSearchQuery in
|
||||
return .exact(ValueBoxKey(queryItem))
|
||||
}
|
||||
if query == ["\u{2764}"] {
|
||||
searchQueries = [.any([ValueBoxKey("\u{2764}"), ValueBoxKey("\u{2764}\u{FE0F}")])]
|
||||
}
|
||||
|
||||
var installedItems: [FoundStickerItem] = []
|
||||
var installedAnimatedItems: [FoundStickerItem] = []
|
||||
@ -187,7 +191,7 @@ func _internal_searchStickers(account: Account, query: [String], scope: SearchSt
|
||||
continue
|
||||
}
|
||||
if matchingRecentItemsIds.contains(file.fileId) {
|
||||
result.append(FoundStickerItem(file: file, stringRepresentations: query))
|
||||
result.append(FoundStickerItem(file: file, stringRepresentations: emoticon))
|
||||
}
|
||||
}
|
||||
|
||||
@ -196,7 +200,7 @@ func _internal_searchStickers(account: Account, query: [String], scope: SearchSt
|
||||
continue
|
||||
}
|
||||
if matchingRecentItemsIds.contains(file.fileId) {
|
||||
result.append(FoundStickerItem(file: file, stringRepresentations: query))
|
||||
result.append(FoundStickerItem(file: file, stringRepresentations: emoticon))
|
||||
}
|
||||
}
|
||||
|
||||
@ -205,8 +209,7 @@ func _internal_searchStickers(account: Account, query: [String], scope: SearchSt
|
||||
result.append(contentsOf: installedItems)
|
||||
}
|
||||
|
||||
let combinedQuery = query.joined(separator: "")
|
||||
var cached = transaction.retrieveItemCacheEntry(id: ItemCacheEntryId(collectionId: Namespaces.CachedItemCollection.cachedStickerQueryResults, key: CachedStickerQueryResult.cacheKey(combinedQuery)))?.get(CachedStickerQueryResult.self)
|
||||
var cached = transaction.retrieveItemCacheEntry(id: ItemCacheEntryId(collectionId: Namespaces.CachedItemCollection.cachedStickerQueryResults, key: CachedStickerQueryResult.cacheKey(cacheKey)))?.get(CachedStickerQueryResult.self)
|
||||
|
||||
let currentTime = Int32(CFAbsoluteTimeGetCurrent() + kCFAbsoluteTimeIntervalSince1970)
|
||||
let appConfiguration: AppConfiguration = transaction.getPreferencesEntry(key: PreferencesKeys.appConfiguration)?.get(AppConfiguration.self) ?? AppConfiguration.defaultValue
|
||||
@ -292,14 +295,17 @@ func _internal_searchStickers(account: Account, query: [String], scope: SearchSt
|
||||
}
|
||||
}
|
||||
|
||||
let remote = account.network.request(Api.functions.messages.getStickers(emoticon: query.joined(separator: ""), hash: cached?.hash ?? 0))
|
||||
|> `catch` { _ -> Signal<Api.messages.Stickers, NoError> in
|
||||
return .single(.stickersNotModified)
|
||||
}
|
||||
|> mapToSignal { result -> Signal<(items: [FoundStickerItem], isFinalResult: Bool), NoError> in
|
||||
return account.postbox.transaction { transaction -> (items: [FoundStickerItem], isFinalResult: Bool) in
|
||||
switch result {
|
||||
case let .stickers(hash, stickers):
|
||||
let remote: Signal<(items: [FoundStickerItem], isFinalResult: Bool), NoError>
|
||||
if let query, !query.isEmpty {
|
||||
let flags: Int32 = 0
|
||||
remote = account.network.request(Api.functions.messages.searchStickers(flags: flags, q: query, emoticon: emoticon.joined(separator: ""), langCode: [inputLanguageCode], offset: 0, limit: 128, hash: cached?.hash ?? 0))
|
||||
|> `catch` { _ -> Signal<Api.messages.FoundStickers, NoError> in
|
||||
return .single(.foundStickersNotModified(flags: 0, nextOffset: nil))
|
||||
}
|
||||
|> mapToSignal { result -> Signal<(items: [FoundStickerItem], isFinalResult: Bool), NoError> in
|
||||
return account.postbox.transaction { transaction -> (items: [FoundStickerItem], isFinalResult: Bool) in
|
||||
switch result {
|
||||
case let .foundStickers(_, _, hash, stickers):
|
||||
var result: [FoundStickerItem] = []
|
||||
let currentItemIds = Set<MediaId>(localItems.map { $0.file.fileId })
|
||||
|
||||
@ -369,19 +375,113 @@ func _internal_searchStickers(account: Account, query: [String], scope: SearchSt
|
||||
}
|
||||
|
||||
let currentTime = Int32(CFAbsoluteTimeGetCurrent() + kCFAbsoluteTimeIntervalSince1970)
|
||||
if let entry = CodableEntry(CachedStickerQueryResult(items: files, hash: hash, timestamp: currentTime)) {
|
||||
transaction.putItemCacheEntry(id: ItemCacheEntryId(collectionId: Namespaces.CachedItemCollection.cachedStickerQueryResults, key: CachedStickerQueryResult.cacheKey(query.joined(separator: ""))), entry: entry)
|
||||
if hash != 0, let entry = CodableEntry(CachedStickerQueryResult(items: files, hash: hash, timestamp: currentTime)) {
|
||||
transaction.putItemCacheEntry(id: ItemCacheEntryId(collectionId: Namespaces.CachedItemCollection.cachedStickerQueryResults, key: CachedStickerQueryResult.cacheKey(cacheKey)), entry: entry)
|
||||
}
|
||||
|
||||
return (result, true)
|
||||
case .stickersNotModified:
|
||||
case .foundStickersNotModified:
|
||||
break
|
||||
}
|
||||
return (tempResult, true)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
remote = account.network.request(Api.functions.messages.getStickers(emoticon: emoticon.joined(separator: ""), hash: cached?.hash ?? 0))
|
||||
|> `catch` { _ -> Signal<Api.messages.Stickers, NoError> in
|
||||
return .single(.stickersNotModified)
|
||||
}
|
||||
|> mapToSignal { result -> Signal<(items: [FoundStickerItem], isFinalResult: Bool), NoError> in
|
||||
return account.postbox.transaction { transaction -> (items: [FoundStickerItem], isFinalResult: Bool) in
|
||||
switch result {
|
||||
case let .stickers(hash, stickers):
|
||||
var result: [FoundStickerItem] = []
|
||||
let currentItemIds = Set<MediaId>(localItems.map { $0.file.fileId })
|
||||
|
||||
var premiumItems: [FoundStickerItem] = []
|
||||
var otherItems: [FoundStickerItem] = []
|
||||
|
||||
for item in localItems {
|
||||
if item.file.isPremiumSticker {
|
||||
premiumItems.append(item)
|
||||
} else {
|
||||
otherItems.append(item)
|
||||
}
|
||||
}
|
||||
|
||||
var foundItems: [FoundStickerItem] = []
|
||||
var foundAnimatedItems: [FoundStickerItem] = []
|
||||
var foundPremiumItems: [FoundStickerItem] = []
|
||||
|
||||
var files: [TelegramMediaFile] = []
|
||||
for sticker in stickers {
|
||||
if let file = telegramMediaFileFromApiDocument(sticker, altDocuments: []), let id = file.id {
|
||||
files.append(file)
|
||||
if !currentItemIds.contains(id) {
|
||||
if file.isPremiumSticker {
|
||||
foundPremiumItems.append(FoundStickerItem(file: file, stringRepresentations: []))
|
||||
} else if file.isAnimatedSticker || file.isVideoSticker {
|
||||
foundAnimatedItems.append(FoundStickerItem(file: file, stringRepresentations: []))
|
||||
} else {
|
||||
foundItems.append(FoundStickerItem(file: file, stringRepresentations: []))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let allPremiumItems = premiumItems + foundPremiumItems
|
||||
let allOtherItems = otherItems + foundAnimatedItems + foundItems
|
||||
|
||||
if isPremium {
|
||||
let batchCount = Int(searchStickersConfiguration.normalStickersPerPremiumCount)
|
||||
if batchCount == 0 {
|
||||
result.append(contentsOf: allPremiumItems)
|
||||
result.append(contentsOf: allOtherItems)
|
||||
} else {
|
||||
if allPremiumItems.isEmpty {
|
||||
result.append(contentsOf: allOtherItems)
|
||||
} else {
|
||||
var i = 0
|
||||
for premiumItem in allPremiumItems {
|
||||
if i < allOtherItems.count {
|
||||
for j in i ..< min(i + batchCount, allOtherItems.count) {
|
||||
result.append(allOtherItems[j])
|
||||
}
|
||||
i += batchCount
|
||||
}
|
||||
result.append(premiumItem)
|
||||
}
|
||||
if i < allOtherItems.count {
|
||||
for j in i ..< allOtherItems.count {
|
||||
result.append(allOtherItems[j])
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
result.append(contentsOf: allOtherItems)
|
||||
result.append(contentsOf: allPremiumItems.prefix(max(0, Int(searchStickersConfiguration.premiumStickersCount))))
|
||||
}
|
||||
|
||||
let currentTime = Int32(CFAbsoluteTimeGetCurrent() + kCFAbsoluteTimeIntervalSince1970)
|
||||
if let entry = CodableEntry(CachedStickerQueryResult(items: files, hash: hash, timestamp: currentTime)) {
|
||||
transaction.putItemCacheEntry(id: ItemCacheEntryId(collectionId: Namespaces.CachedItemCollection.cachedStickerQueryResults, key: CachedStickerQueryResult.cacheKey(cacheKey)), entry: entry)
|
||||
}
|
||||
|
||||
return (result, true)
|
||||
case .stickersNotModified:
|
||||
break
|
||||
}
|
||||
return (tempResult, true)
|
||||
}
|
||||
return (tempResult, true)
|
||||
}
|
||||
}
|
||||
|
||||
return .single((tempResult, false))
|
||||
|> then(remote)
|
||||
|> then(
|
||||
remote
|
||||
|> delay(0.2, queue: Queue.concurrentDefaultQueue())
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@ -770,16 +870,24 @@ func _internal_searchStickers(account: Account, category: EmojiSearchCategories.
|
||||
}
|
||||
}
|
||||
|
||||
func _internal_searchEmoji(account: Account, query: [String], scope: SearchStickersScope = [.installed, .remote]) -> Signal<(items: [FoundStickerItem], isFinalResult: Bool), NoError> {
|
||||
func _internal_searchEmoji(account: Account, query: String?, emoticon: [String], inputLanguageCode: String, scope: SearchStickersScope = [.installed, .remote]) -> Signal<(items: [FoundStickerItem], isFinalResult: Bool), NoError> {
|
||||
if scope.isEmpty {
|
||||
return .single(([], true))
|
||||
}
|
||||
var query = query
|
||||
if query == ["\u{2764}"] {
|
||||
query = ["\u{2764}\u{FE0F}"]
|
||||
var emoticon = emoticon
|
||||
if emoticon == ["\u{2764}"] {
|
||||
emoticon = ["\u{2764}\u{FE0F}"]
|
||||
}
|
||||
let combinedQuery = query.sorted().joined(separator: "")
|
||||
let querySet = Set(query)
|
||||
|
||||
let cacheKey: String
|
||||
if let query, !query.isEmpty {
|
||||
cacheKey = query
|
||||
} else {
|
||||
cacheKey = emoticon.sorted().joined()
|
||||
}
|
||||
|
||||
|
||||
let querySet = Set(emoticon)
|
||||
return account.postbox.transaction { transaction -> ([FoundStickerItem], CachedStickerQueryResult?, Bool, SearchStickersConfiguration) in
|
||||
let isPremium = transaction.getPeer(account.peerId)?.isPremium ?? false
|
||||
|
||||
@ -812,7 +920,7 @@ func _internal_searchEmoji(account: Account, query: [String], scope: SearchStick
|
||||
result.append(contentsOf: installedItems)
|
||||
}
|
||||
|
||||
var cached = transaction.retrieveItemCacheEntry(id: ItemCacheEntryId(collectionId: Namespaces.CachedItemCollection.cachedEmojiQueryResults, key: CachedStickerQueryResult.cacheKey(combinedQuery)))?.get(CachedStickerQueryResult.self)
|
||||
var cached = transaction.retrieveItemCacheEntry(id: ItemCacheEntryId(collectionId: Namespaces.CachedItemCollection.cachedEmojiQueryResults, key: CachedStickerQueryResult.cacheKey(cacheKey)))?.get(CachedStickerQueryResult.self)
|
||||
|
||||
let currentTime = Int32(CFAbsoluteTimeGetCurrent() + kCFAbsoluteTimeIntervalSince1970)
|
||||
let appConfiguration: AppConfiguration = transaction.getPreferencesEntry(key: PreferencesKeys.appConfiguration)?.get(AppConfiguration.self) ?? AppConfiguration.defaultValue
|
||||
@ -839,54 +947,99 @@ func _internal_searchEmoji(account: Account, query: [String], scope: SearchStick
|
||||
}
|
||||
}
|
||||
|
||||
let remote = account.network.request(Api.functions.messages.searchCustomEmoji(emoticon: query.joined(separator: ""), hash: cached?.hash ?? 0))
|
||||
|> `catch` { _ -> Signal<Api.EmojiList, NoError> in
|
||||
return .single(.emojiListNotModified)
|
||||
}
|
||||
|> mapToSignal { result -> Signal<(files: [TelegramMediaFile], hash: Int64)?, NoError> in
|
||||
switch result {
|
||||
case .emojiListNotModified:
|
||||
return .single(nil)
|
||||
case let .emojiList(hash, documentIds):
|
||||
return TelegramEngine(account: account).stickers.resolveInlineStickers(fileIds: documentIds)
|
||||
|> map { fileMap -> (files: [TelegramMediaFile], hash: Int64)? in
|
||||
var files: [TelegramMediaFile] = []
|
||||
for documentId in documentIds {
|
||||
if let file = fileMap[documentId] {
|
||||
files.append(file)
|
||||
}
|
||||
}
|
||||
return (files, hash)
|
||||
}
|
||||
|
||||
let remote: Signal<(items: [FoundStickerItem], isFinalResult: Bool), NoError>
|
||||
if let query, !query.isEmpty {
|
||||
let flags: Int32 = 1 << 0
|
||||
remote = account.network.request(Api.functions.messages.searchStickers(flags: flags, q: query, emoticon: emoticon.joined(separator: ""), langCode: [inputLanguageCode], offset: 0, limit: 128, hash: cached?.hash ?? 0))
|
||||
|> `catch` { _ -> Signal<Api.messages.FoundStickers, NoError> in
|
||||
return .single(.foundStickersNotModified(flags: 0, nextOffset: nil))
|
||||
}
|
||||
}
|
||||
|> mapToSignal { result -> Signal<(items: [FoundStickerItem], isFinalResult: Bool), NoError> in
|
||||
return account.postbox.transaction { transaction -> (items: [FoundStickerItem], isFinalResult: Bool) in
|
||||
if let (fileItems, hash) = result {
|
||||
var result: [FoundStickerItem] = localItems
|
||||
var currentItemIds = Set<MediaId>(localItems.map { $0.file.fileId })
|
||||
|> mapToSignal { result -> Signal<(items: [FoundStickerItem], isFinalResult: Bool), NoError> in
|
||||
return account.postbox.transaction { transaction -> (items: [FoundStickerItem], isFinalResult: Bool) in
|
||||
switch result {
|
||||
case let .foundStickers(_, _, hash, stickers):
|
||||
var result: [FoundStickerItem] = localItems
|
||||
var currentItemIds = Set<MediaId>(localItems.map { $0.file.fileId })
|
||||
|
||||
var files: [TelegramMediaFile] = []
|
||||
for file in fileItems {
|
||||
files.append(file)
|
||||
if !currentItemIds.contains(file.fileId) {
|
||||
currentItemIds.insert(file.fileId)
|
||||
result.append(FoundStickerItem(file: file, stringRepresentations: []))
|
||||
var files: [TelegramMediaFile] = []
|
||||
for sticker in stickers {
|
||||
guard let file = telegramMediaFileFromApiDocument(sticker, altDocuments: nil) else {
|
||||
continue
|
||||
}
|
||||
files.append(file)
|
||||
if !currentItemIds.contains(file.fileId) {
|
||||
currentItemIds.insert(file.fileId)
|
||||
result.append(FoundStickerItem(file: file, stringRepresentations: []))
|
||||
}
|
||||
}
|
||||
|
||||
let currentTime = Int32(CFAbsoluteTimeGetCurrent() + kCFAbsoluteTimeIntervalSince1970)
|
||||
if let entry = CodableEntry(CachedStickerQueryResult(items: files, hash: hash, timestamp: currentTime)) {
|
||||
transaction.putItemCacheEntry(id: ItemCacheEntryId(collectionId: Namespaces.CachedItemCollection.cachedEmojiQueryResults, key: CachedStickerQueryResult.cacheKey(cacheKey)), entry: entry)
|
||||
}
|
||||
|
||||
return (result, true)
|
||||
case .foundStickersNotModified:
|
||||
break
|
||||
}
|
||||
|
||||
let currentTime = Int32(CFAbsoluteTimeGetCurrent() + kCFAbsoluteTimeIntervalSince1970)
|
||||
if let entry = CodableEntry(CachedStickerQueryResult(items: files, hash: hash, timestamp: currentTime)) {
|
||||
transaction.putItemCacheEntry(id: ItemCacheEntryId(collectionId: Namespaces.CachedItemCollection.cachedEmojiQueryResults, key: CachedStickerQueryResult.cacheKey(combinedQuery)), entry: entry)
|
||||
}
|
||||
|
||||
return (result, true)
|
||||
return (intermediateResult, true)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
remote = account.network.request(Api.functions.messages.searchCustomEmoji(emoticon: emoticon.joined(separator: ""), hash: cached?.hash ?? 0))
|
||||
|> `catch` { _ -> Signal<Api.EmojiList, NoError> in
|
||||
return .single(.emojiListNotModified)
|
||||
}
|
||||
|> mapToSignal { result -> Signal<(files: [TelegramMediaFile], hash: Int64)?, NoError> in
|
||||
switch result {
|
||||
case .emojiListNotModified:
|
||||
return .single(nil)
|
||||
case let .emojiList(hash, documentIds):
|
||||
return TelegramEngine(account: account).stickers.resolveInlineStickers(fileIds: documentIds)
|
||||
|> map { fileMap -> (files: [TelegramMediaFile], hash: Int64)? in
|
||||
var files: [TelegramMediaFile] = []
|
||||
for documentId in documentIds {
|
||||
if let file = fileMap[documentId] {
|
||||
files.append(file)
|
||||
}
|
||||
}
|
||||
return (files, hash)
|
||||
}
|
||||
}
|
||||
}
|
||||
|> mapToSignal { result -> Signal<(items: [FoundStickerItem], isFinalResult: Bool), NoError> in
|
||||
return account.postbox.transaction { transaction -> (items: [FoundStickerItem], isFinalResult: Bool) in
|
||||
if let (fileItems, hash) = result {
|
||||
var result: [FoundStickerItem] = localItems
|
||||
var currentItemIds = Set<MediaId>(localItems.map { $0.file.fileId })
|
||||
|
||||
var files: [TelegramMediaFile] = []
|
||||
for file in fileItems {
|
||||
files.append(file)
|
||||
if !currentItemIds.contains(file.fileId) {
|
||||
currentItemIds.insert(file.fileId)
|
||||
result.append(FoundStickerItem(file: file, stringRepresentations: []))
|
||||
}
|
||||
}
|
||||
|
||||
let currentTime = Int32(CFAbsoluteTimeGetCurrent() + kCFAbsoluteTimeIntervalSince1970)
|
||||
if let entry = CodableEntry(CachedStickerQueryResult(items: files, hash: hash, timestamp: currentTime)) {
|
||||
transaction.putItemCacheEntry(id: ItemCacheEntryId(collectionId: Namespaces.CachedItemCollection.cachedEmojiQueryResults, key: CachedStickerQueryResult.cacheKey(cacheKey)), entry: entry)
|
||||
}
|
||||
|
||||
return (result, true)
|
||||
}
|
||||
return (intermediateResult, true)
|
||||
}
|
||||
return (intermediateResult, true)
|
||||
}
|
||||
}
|
||||
|
||||
return .single((intermediateResult, false))
|
||||
|> then(remote)
|
||||
|> then(
|
||||
remote
|
||||
|> delay(0.2, queue: Queue.concurrentDefaultQueue())
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -30,8 +30,8 @@ public extension TelegramEngine {
|
||||
return _internal_randomGreetingSticker(account: self.account)
|
||||
}
|
||||
|
||||
public func searchStickers(query: [String], scope: SearchStickersScope = [.installed, .remote]) -> Signal<(items: [FoundStickerItem], isFinalResult: Bool), NoError> {
|
||||
return _internal_searchStickers(account: self.account, query: query, scope: scope)
|
||||
public func searchStickers(query: String?, emoticon: [String], inputLanguageCode: String = "", scope: SearchStickersScope = [.installed, .remote]) -> Signal<(items: [FoundStickerItem], isFinalResult: Bool), NoError> {
|
||||
return _internal_searchStickers(account: self.account, query: query, emoticon: emoticon, inputLanguageCode: inputLanguageCode, scope: scope)
|
||||
}
|
||||
|
||||
public func searchStickers(category: EmojiSearchCategories.Group, scope: SearchStickersScope = [.installed, .remote]) -> Signal<(items: [FoundStickerItem], isFinalResult: Bool), NoError> {
|
||||
@ -287,15 +287,15 @@ public extension TelegramEngine {
|
||||
return _internal_resolveInlineStickersLocal(postbox: self.account.postbox, fileIds: fileIds)
|
||||
}
|
||||
|
||||
public func searchEmoji(emojiString: [String]) -> Signal<(items: [TelegramMediaFile], isFinalResult: Bool), NoError> {
|
||||
return _internal_searchEmoji(account: self.account, query: emojiString)
|
||||
public func searchEmoji(query: String?, emoticon: [String], inputLanguageCode: String = "") -> Signal<(items: [TelegramMediaFile], isFinalResult: Bool), NoError> {
|
||||
return _internal_searchEmoji(account: self.account, query: query, emoticon: emoticon, inputLanguageCode: inputLanguageCode)
|
||||
|> map { items, isFinalResult -> (items: [TelegramMediaFile], isFinalResult: Bool) in
|
||||
return (items.map(\.file), isFinalResult)
|
||||
}
|
||||
}
|
||||
|
||||
public func searchEmoji(category: EmojiSearchCategories.Group) -> Signal<(items: [TelegramMediaFile], isFinalResult: Bool), NoError> {
|
||||
return _internal_searchEmoji(account: self.account, query: category.identifiers)
|
||||
return _internal_searchEmoji(account: self.account, query: nil, emoticon: category.identifiers, inputLanguageCode: "")
|
||||
|> map { items, isFinalResult -> (items: [TelegramMediaFile], isFinalResult: Bool) in
|
||||
return (items.map(\.file), isFinalResult)
|
||||
}
|
||||
|
@ -338,7 +338,7 @@ final class AvatarEditorScreenComponent: Component {
|
||||
|> mapToSignal { keywords -> Signal<[EmojiPagerContentComponent.ItemGroup], NoError> in
|
||||
return combineLatest(
|
||||
context.account.postbox.itemCollectionsView(orderedItemListCollectionIds: [], namespaces: [Namespaces.ItemCollection.CloudEmojiPacks], aroundIndex: nil, count: 10000000) |> take(1),
|
||||
combineLatest(keywords.map { context.engine.stickers.searchStickers(query: $0.emoticons)
|
||||
combineLatest(keywords.map { context.engine.stickers.searchStickers(query: query, emoticon: $0.emoticons, inputLanguageCode: languageCode)
|
||||
|> map { items -> [FoundStickerItem] in
|
||||
return items.items
|
||||
}
|
||||
|
@ -1020,6 +1020,7 @@ private final class CameraScreenComponent: CombinedComponent {
|
||||
hasAccess: hasAllRequiredAccess,
|
||||
hideControls: component.cameraState.collageProgress > 1.0 - .ulpOfOne,
|
||||
collageProgress: component.cameraState.collageProgress,
|
||||
collageCount: component.cameraState.isCollageEnabled ? component.cameraState.collageGrid.count : nil,
|
||||
tintColor: controlsTintColor,
|
||||
shutterState: shutterState,
|
||||
lastGalleryAsset: state.lastGalleryAsset,
|
||||
@ -1683,6 +1684,7 @@ public class CameraScreenImpl: ViewController, CameraScreen {
|
||||
fileprivate var additionalPreviewView: CameraSimplePreviewView
|
||||
|
||||
fileprivate let previewBlurView: BlurView
|
||||
fileprivate let mainPreviewBlurView: BlurView
|
||||
private var mainPreviewSnapshotView: UIView?
|
||||
private var additionalPreviewSnapshotView: UIView?
|
||||
fileprivate let previewFrameLeftDimView: UIView
|
||||
@ -1795,6 +1797,9 @@ public class CameraScreenImpl: ViewController, CameraScreen {
|
||||
self.previewBlurView = BlurView()
|
||||
self.previewBlurView.isUserInteractionEnabled = false
|
||||
|
||||
self.mainPreviewBlurView = BlurView()
|
||||
self.mainPreviewBlurView.isUserInteractionEnabled = false
|
||||
|
||||
var isDualCameraEnabled = Camera.isDualCameraSupported(forRoundVideo: false)
|
||||
if isDualCameraEnabled {
|
||||
if let isDualCameraEnabledValue = UserDefaults.standard.object(forKey: "TelegramStoryCameraIsDualEnabled") as? NSNumber {
|
||||
@ -2122,9 +2127,17 @@ public class CameraScreenImpl: ViewController, CameraScreen {
|
||||
}
|
||||
}
|
||||
if case .position = modeChange {
|
||||
UIView.transition(with: self.previewContainerView, duration: 0.4, options: [.transitionFlipFromLeft, .curveEaseOut], animations: {
|
||||
self.previewBlurView.effect = UIBlurEffect(style: .dark)
|
||||
})
|
||||
if self.cameraState.isCollageEnabled {
|
||||
self.mainPreviewBlurView.frame = self.mainPreviewContainerView.bounds
|
||||
self.mainPreviewContainerView.addSubview(self.mainPreviewBlurView)
|
||||
UIView.transition(with: self.mainPreviewContainerView, duration: 0.4, options: [.transitionFlipFromLeft, .curveEaseOut], animations: {
|
||||
self.mainPreviewBlurView.effect = UIBlurEffect(style: .dark)
|
||||
})
|
||||
} else {
|
||||
UIView.transition(with: self.previewContainerView, duration: 0.4, options: [.transitionFlipFromLeft, .curveEaseOut], animations: {
|
||||
self.previewBlurView.effect = UIBlurEffect(style: .dark)
|
||||
})
|
||||
}
|
||||
} else {
|
||||
self.previewContainerView.insertSubview(self.previewBlurView, belowSubview: self.additionalPreviewContainerView)
|
||||
|
||||
@ -2137,6 +2150,13 @@ public class CameraScreenImpl: ViewController, CameraScreen {
|
||||
self.previewBlurView.effect = UIBlurEffect(style: .dark)
|
||||
}
|
||||
} else {
|
||||
if self.mainPreviewBlurView.effect != nil {
|
||||
UIView.animate(withDuration: 0.4, animations: {
|
||||
self.mainPreviewBlurView.effect = nil
|
||||
}, completion: { _ in
|
||||
self.mainPreviewBlurView.removeFromSuperview()
|
||||
})
|
||||
}
|
||||
if self.previewBlurView.effect != nil {
|
||||
UIView.animate(withDuration: 0.4, animations: {
|
||||
self.previewBlurView.effect = nil
|
||||
@ -2971,7 +2991,7 @@ public class CameraScreenImpl: ViewController, CameraScreen {
|
||||
}
|
||||
self.updatingCollageProgress = true
|
||||
self.controller?.updateCameraState({ state in
|
||||
return state.updatedCollageProgress(collageState.progress)
|
||||
return state.updatedCollageProgress(collageState.innerProgress)
|
||||
}, transition: .spring(duration: 0.3))
|
||||
self.updatingCollageProgress = false
|
||||
})
|
||||
|
@ -36,6 +36,7 @@ private final class ShutterButtonContentComponent: Component {
|
||||
let shutterState: ShutterButtonState
|
||||
let blobState: ShutterBlobView.BlobState
|
||||
let collageProgress: Float
|
||||
let collageCount: Int?
|
||||
let highlightedAction: ActionSlot<Bool>
|
||||
let updateOffsetX: ActionSlot<(CGFloat, ComponentTransition)>
|
||||
let updateOffsetY: ActionSlot<(CGFloat, ComponentTransition)>
|
||||
@ -47,6 +48,7 @@ private final class ShutterButtonContentComponent: Component {
|
||||
shutterState: ShutterButtonState,
|
||||
blobState: ShutterBlobView.BlobState,
|
||||
collageProgress: Float,
|
||||
collageCount: Int?,
|
||||
highlightedAction: ActionSlot<Bool>,
|
||||
updateOffsetX: ActionSlot<(CGFloat, ComponentTransition)>,
|
||||
updateOffsetY: ActionSlot<(CGFloat, ComponentTransition)>
|
||||
@ -57,6 +59,7 @@ private final class ShutterButtonContentComponent: Component {
|
||||
self.shutterState = shutterState
|
||||
self.blobState = blobState
|
||||
self.collageProgress = collageProgress
|
||||
self.collageCount = collageCount
|
||||
self.highlightedAction = highlightedAction
|
||||
self.updateOffsetX = updateOffsetX
|
||||
self.updateOffsetY = updateOffsetY
|
||||
@ -81,6 +84,9 @@ private final class ShutterButtonContentComponent: Component {
|
||||
if lhs.collageProgress != rhs.collageProgress {
|
||||
return false
|
||||
}
|
||||
if lhs.collageCount != rhs.collageCount {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
@ -314,6 +320,8 @@ private final class ShutterButtonContentComponent: Component {
|
||||
self.innerLayer.bounds = CGRect(origin: .zero, size: innerSize)
|
||||
self.innerLayer.position = CGPoint(x: maximumShutterSize.width / 2.0, y: maximumShutterSize.height / 2.0)
|
||||
|
||||
let totalProgress = component.collageCount.flatMap { 1.0 / Double($0) } ?? 1.0
|
||||
|
||||
self.progressLayer.bounds = CGRect(origin: .zero, size: maximumShutterSize)
|
||||
self.progressLayer.position = CGPoint(x: maximumShutterSize.width / 2.0, y: maximumShutterSize.height / 2.0)
|
||||
transition.setShapeLayerPath(layer: self.progressLayer, path: ringPath)
|
||||
@ -321,10 +329,14 @@ private final class ShutterButtonContentComponent: Component {
|
||||
self.progressLayer.strokeColor = videoRedColor.cgColor
|
||||
self.progressLayer.lineWidth = ringWidth + UIScreenPixel
|
||||
self.progressLayer.lineCap = .round
|
||||
self.progressLayer.transform = CATransform3DMakeRotation(-.pi / 2.0, 0.0, 0.0, 1.0)
|
||||
if totalProgress < 1.0 {
|
||||
self.progressLayer.transform = CATransform3DMakeRotation(-.pi / 2.0 + CGFloat(component.collageProgress) * 2.0 * .pi, 0.0, 0.0, 1.0)
|
||||
} else {
|
||||
self.progressLayer.transform = CATransform3DMakeRotation(-.pi / 2.0, 0.0, 0.0, 1.0)
|
||||
}
|
||||
|
||||
let previousValue = self.progressLayer.strokeEnd
|
||||
self.progressLayer.strokeEnd = CGFloat(recordingProgress ?? 0.0)
|
||||
self.progressLayer.strokeEnd = CGFloat(recordingProgress ?? 0.0) * totalProgress
|
||||
self.progressLayer.animateStrokeEnd(from: previousValue, to: self.progressLayer.strokeEnd, duration: 0.33)
|
||||
|
||||
return maximumShutterSize
|
||||
@ -554,6 +566,7 @@ final class CaptureControlsComponent: Component {
|
||||
let hasAccess: Bool
|
||||
let hideControls: Bool
|
||||
let collageProgress: Float
|
||||
let collageCount: Int?
|
||||
let tintColor: UIColor
|
||||
let shutterState: ShutterButtonState
|
||||
let lastGalleryAsset: PHAsset?
|
||||
@ -576,6 +589,7 @@ final class CaptureControlsComponent: Component {
|
||||
hasAccess: Bool,
|
||||
hideControls: Bool,
|
||||
collageProgress: Float,
|
||||
collageCount: Int?,
|
||||
tintColor: UIColor,
|
||||
shutterState: ShutterButtonState,
|
||||
lastGalleryAsset: PHAsset?,
|
||||
@ -597,6 +611,7 @@ final class CaptureControlsComponent: Component {
|
||||
self.hasAccess = hasAccess
|
||||
self.hideControls = hideControls
|
||||
self.collageProgress = collageProgress
|
||||
self.collageCount = collageCount
|
||||
self.tintColor = tintColor
|
||||
self.shutterState = shutterState
|
||||
self.lastGalleryAsset = lastGalleryAsset
|
||||
@ -632,6 +647,9 @@ final class CaptureControlsComponent: Component {
|
||||
if lhs.collageProgress != rhs.collageProgress {
|
||||
return false
|
||||
}
|
||||
if lhs.collageCount != rhs.collageCount {
|
||||
return false
|
||||
}
|
||||
if lhs.tintColor != rhs.tintColor {
|
||||
return false
|
||||
}
|
||||
@ -1152,6 +1170,7 @@ final class CaptureControlsComponent: Component {
|
||||
shutterState: component.shutterState,
|
||||
blobState: blobState,
|
||||
collageProgress: component.collageProgress,
|
||||
collageCount: component.collageCount,
|
||||
highlightedAction: self.shutterHightlightedAction,
|
||||
updateOffsetX: self.shutterUpdateOffsetX,
|
||||
updateOffsetY: self.shutterUpdateOffsetY
|
||||
|
@ -938,7 +938,7 @@ public final class ChatEntityKeyboardInputNode: ChatInputNode {
|
||||
let remoteSignal: Signal<(items: [TelegramMediaFile], isFinalResult: Bool), NoError>
|
||||
let remotePacksSignal: Signal<(sets: FoundStickerSets, isFinalResult: Bool), NoError>
|
||||
if hasPremium {
|
||||
remoteSignal = context.engine.stickers.searchEmoji(emojiString: Array(allEmoticons.keys))
|
||||
remoteSignal = context.engine.stickers.searchEmoji(query: query, emoticon: Array(allEmoticons.keys), inputLanguageCode: languageCode)
|
||||
remotePacksSignal = context.engine.stickers.searchEmojiSets(query: query)
|
||||
|> mapToSignal { localResult in
|
||||
return .single((localResult, false))
|
||||
|
@ -348,7 +348,7 @@ final class StickerPaneSearchContentNode: ASDisplayNode, PaneSearchContentNode {
|
||||
|
||||
let query = text.trimmingCharacters(in: .whitespacesAndNewlines)
|
||||
if query.isSingleEmoji {
|
||||
signals = .single([context.engine.stickers.searchStickers(query: [text.basicEmoji.0])
|
||||
signals = .single([context.engine.stickers.searchStickers(query: nil, emoticon: [text.basicEmoji.0])
|
||||
|> map { (nil, $0.items) }])
|
||||
} else if query.count > 1, let languageCode = languageCode, !languageCode.isEmpty && languageCode != "emoji" {
|
||||
var signal = context.engine.stickers.searchEmojiKeywords(inputLanguageCode: languageCode, query: query.lowercased(), completeMatch: query.count < 3)
|
||||
@ -364,17 +364,11 @@ final class StickerPaneSearchContentNode: ASDisplayNode, PaneSearchContentNode {
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
signals = signal
|
||||
|> map { keywords -> [Signal<(String?, [FoundStickerItem]), NoError>] in
|
||||
var signals: [Signal<(String?, [FoundStickerItem]), NoError>] = []
|
||||
let emoticons = keywords.flatMap { $0.emoticons }
|
||||
for emoji in emoticons {
|
||||
signals.append(context.engine.stickers.searchStickers(query: [emoji.basicEmoji.0])
|
||||
// |> take(1)
|
||||
|> map { (emoji, $0.items) })
|
||||
}
|
||||
return signals
|
||||
let emoticon = keywords.flatMap { $0.emoticons }.map { $0.basicEmoji.0 }
|
||||
return [context.engine.stickers.searchStickers(query: query, emoticon: emoticon, inputLanguageCode: languageCode)
|
||||
|> map { (nil, $0.items) }]
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -111,7 +111,7 @@ private func updatedContextQueryResultStateForQuery(context: AccountContext, cha
|
||||
case .installed:
|
||||
scope = [.installed]
|
||||
}
|
||||
return context.engine.stickers.searchStickers(query: [query.basicEmoji.0], scope: scope)
|
||||
return context.engine.stickers.searchStickers(query: nil, emoticon: [query.basicEmoji.0], scope: scope)
|
||||
|> map { items -> [FoundStickerItem] in
|
||||
return items.items
|
||||
}
|
||||
|
@ -1759,17 +1759,19 @@ public final class MessageInputPanelComponent: Component {
|
||||
}
|
||||
}
|
||||
|
||||
var lightFieldColor = UIColor(white: 1.0, alpha: 0.09)
|
||||
var fieldBackgroundIsDark = false
|
||||
if component.useGrayBackground {
|
||||
fieldBackgroundIsDark = false
|
||||
} else if component.style == .media {
|
||||
fieldBackgroundIsDark = true
|
||||
fieldBackgroundIsDark = false
|
||||
lightFieldColor = UIColor(white: 0.2, alpha: 0.45)
|
||||
} else if self.textFieldExternalState.hasText && component.alwaysDarkWhenHasText {
|
||||
fieldBackgroundIsDark = true
|
||||
} else if isEditing || component.style == .editor {
|
||||
fieldBackgroundIsDark = true
|
||||
}
|
||||
self.fieldBackgroundView.updateColor(color: fieldBackgroundIsDark ? UIColor(white: 0.0, alpha: 0.5) : UIColor(white: 1.0, alpha: 0.09), transition: transition.containedViewLayoutTransition)
|
||||
self.fieldBackgroundView.updateColor(color: fieldBackgroundIsDark ? UIColor(white: 0.0, alpha: 0.5) : lightFieldColor, transition: transition.containedViewLayoutTransition)
|
||||
if let placeholder = self.placeholder.view, let vibrancyPlaceholderView = self.vibrancyPlaceholder.view {
|
||||
placeholder.isHidden = self.textFieldExternalState.hasText
|
||||
vibrancyPlaceholderView.isHidden = placeholder.isHidden
|
||||
|
@ -687,7 +687,7 @@ final class PeerAllowedReactionsScreenComponent: Component {
|
||||
))
|
||||
return .single(resultGroups)
|
||||
} else {
|
||||
let remoteSignal = context.engine.stickers.searchEmoji(emojiString: Array(allEmoticons.keys))
|
||||
let remoteSignal = context.engine.stickers.searchEmoji(query: query, emoticon: Array(allEmoticons.keys), inputLanguageCode: languageCode)
|
||||
|
||||
return combineLatest(
|
||||
context.account.postbox.itemCollectionsView(orderedItemListCollectionIds: [], namespaces: [Namespaces.ItemCollection.CloudEmojiPacks], aroundIndex: nil, count: 10000000) |> take(1),
|
||||
|
@ -798,7 +798,7 @@ func peerInfoScreenSettingsData(context: AccountContext, peerId: EnginePeer.Id,
|
||||
let botsKey = ValueBoxKey(length: 8)
|
||||
botsKey.setInt64(0, value: 0)
|
||||
|
||||
let iconLoaded = Atomic<[EnginePeer.Id: Bool]>(value: [:])
|
||||
//let iconLoaded = Atomic<[EnginePeer.Id: Bool]>(value: [:])
|
||||
let bots = context.engine.data.subscribe(TelegramEngine.EngineData.Item.ItemCache.Item(collectionId: Namespaces.CachedItemCollection.attachMenuBots, id: botsKey))
|
||||
|> mapToSignal { entry -> Signal<[AttachMenuBot], NoError> in
|
||||
let bots: [AttachMenuBots.Bot] = entry?.get(AttachMenuBots.self)?.bots ?? []
|
||||
@ -811,32 +811,7 @@ func peerInfoScreenSettingsData(context: AccountContext, peerId: EnginePeer.Id,
|
||||
if let maybePeer = peersMap[bot.peerId], let peer = maybePeer {
|
||||
let resultBot = AttachMenuBot(peer: peer, shortName: bot.name, icons: bot.icons, peerTypes: bot.peerTypes, flags: bot.flags)
|
||||
if bot.flags.contains(.showInSettings) {
|
||||
if let peer = PeerReference(peer._asPeer()), let icon = bot.icons[.iOSSettingsStatic] {
|
||||
let fileReference: FileMediaReference = .attachBot(peer: peer, media: icon)
|
||||
let signal: Signal<AttachMenuBot?, NoError>
|
||||
if let _ = iconLoaded.with({ $0 })[peer.id] {
|
||||
signal = .single(resultBot)
|
||||
} else {
|
||||
signal = .single(nil)
|
||||
|> then(
|
||||
preloadedBotIcon(account: context.account, fileReference: fileReference)
|
||||
|> filter { $0 }
|
||||
|> map { _ -> AttachMenuBot? in
|
||||
return resultBot
|
||||
}
|
||||
|> afterNext { _ in
|
||||
let _ = iconLoaded.modify { current in
|
||||
var updated = current
|
||||
updated[peer.id] = true
|
||||
return updated
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
result.append(signal)
|
||||
} else {
|
||||
result.append(.single(resultBot))
|
||||
}
|
||||
result.append(.single(resultBot))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -920,7 +920,7 @@ private func settingsItems(data: PeerInfoScreenData?, context: AccountContext, p
|
||||
}
|
||||
let _ = freeMediaFileInteractiveFetched(account: context.account, userLocation: .other, fileReference: fileReference).startStandalone()
|
||||
} else {
|
||||
iconSignal = .single(UIImage(bundleImageName: "Settings/Menu/Websites")!)
|
||||
iconSignal = .single(UIImage())
|
||||
}
|
||||
let label: PeerInfoScreenDisclosureItem.Label = bot.flags.contains(.notActivated) || bot.flags.contains(.showInSettingsDisclaimer) ? .titleBadge(presentationData.strings.Settings_New, presentationData.theme.list.itemAccentColor) : .none
|
||||
items[.apps]!.append(PeerInfoScreenDisclosureItem(id: bot.peer.id.id._internalGetInt64Value(), label: label, text: bot.shortName, icon: nil, iconSignal: iconSignal, action: {
|
||||
|
@ -370,7 +370,7 @@ final class BusinessIntroSetupScreenComponent: Component {
|
||||
var signals: Signal<[Signal<(String?, [FoundStickerItem]), NoError>], NoError> = .single([])
|
||||
|
||||
if query.isSingleEmoji {
|
||||
signals = .single([context.engine.stickers.searchStickers(query: [query.basicEmoji.0])
|
||||
signals = .single([context.engine.stickers.searchStickers(query: nil, emoticon: [query.basicEmoji.0])
|
||||
|> map { (nil, $0.items) }])
|
||||
} else if query.count > 1, !languageCode.isEmpty && languageCode != "emoji" {
|
||||
var signal = context.engine.stickers.searchEmojiKeywords(inputLanguageCode: languageCode, query: query.lowercased(), completeMatch: query.count < 3)
|
||||
@ -385,18 +385,12 @@ final class BusinessIntroSetupScreenComponent: Component {
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
signals = signal
|
||||
|> map { keywords -> [Signal<(String?, [FoundStickerItem]), NoError>] in
|
||||
var signals: [Signal<(String?, [FoundStickerItem]), NoError>] = []
|
||||
let emoticons = keywords.flatMap { $0.emoticons }
|
||||
for emoji in emoticons {
|
||||
signals.append(context.engine.stickers.searchStickers(query: [emoji.basicEmoji.0])
|
||||
|> take(1)
|
||||
|> map { (emoji, $0.items) })
|
||||
}
|
||||
return signals
|
||||
let emoticon = keywords.flatMap { $0.emoticons }.map { $0.basicEmoji.0 }
|
||||
return [context.engine.stickers.searchStickers(query: query, emoticon: emoticon, inputLanguageCode: languageCode)
|
||||
|> map { (nil, $0.items) }]
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1080,7 +1080,7 @@ public class StickerPickerScreen: ViewController {
|
||||
}
|
||||
let remoteSignal: Signal<(items: [TelegramMediaFile], isFinalResult: Bool), NoError>
|
||||
if hasPremium {
|
||||
remoteSignal = context.engine.stickers.searchEmoji(emojiString: Array(allEmoticons.keys))
|
||||
remoteSignal = context.engine.stickers.searchEmoji(query: query, emoticon: Array(allEmoticons.keys), inputLanguageCode: languageCode)
|
||||
} else {
|
||||
remoteSignal = .single(([], true))
|
||||
}
|
||||
|
@ -95,7 +95,7 @@ private func updatedContextQueryResultStateForQuery(context: AccountContext, pee
|
||||
case .installed:
|
||||
scope = [.installed]
|
||||
}
|
||||
return context.engine.stickers.searchStickers(query: [query.basicEmoji.0], scope: scope)
|
||||
return context.engine.stickers.searchStickers(query: nil, emoticon: [query.basicEmoji.0], scope: scope)
|
||||
|> map { items -> [FoundStickerItem] in
|
||||
return items.items
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user