[Temp] Input panel progress

This commit is contained in:
Ali
2022-06-21 21:47:01 +01:00
parent abe701f625
commit 0f1b382265
44 changed files with 1728 additions and 196 deletions

View File

@@ -12,24 +12,31 @@ import MultiAnimationRenderer
import Postbox
import TelegramCore
import ComponentDisplayAdapters
import SettingsUI
final class ChatEntityKeyboardInputNode: ChatInputNode {
struct InputData: Equatable {
let emoji: EmojiPagerContentComponent
let stickers: EmojiPagerContentComponent
let gifs: GifPagerContentComponent
init(
emoji: EmojiPagerContentComponent,
stickers: EmojiPagerContentComponent
stickers: EmojiPagerContentComponent,
gifs: GifPagerContentComponent
) {
self.emoji = emoji
self.stickers = stickers
self.gifs = gifs
}
}
static func inputData(context: AccountContext, interfaceInteraction: ChatPanelInterfaceInteraction) -> Signal<InputData, NoError> {
static func inputData(context: AccountContext, interfaceInteraction: ChatPanelInterfaceInteraction, controllerInteraction: ChatControllerInteraction) -> Signal<InputData, NoError> {
let premiumConfiguration = PremiumConfiguration.with(appConfiguration: context.currentAppConfiguration.with { $0 })
let isPremiumDisabled = premiumConfiguration.isPremiumDisabled
let emojiInputInteraction = EmojiPagerContentComponent.InputInteraction(
performItemAction: { [weak interfaceInteraction] item, _, _ in
performItemAction: { [weak interfaceInteraction] item, _, _, _ in
guard let interfaceInteraction = interfaceInteraction else {
return
}
@@ -40,20 +47,38 @@ final class ChatEntityKeyboardInputNode: ChatInputNode {
return
}
interfaceInteraction.backwardsDeleteText()
},
openStickerSettings: {
}
)
let stickerInputInteraction = EmojiPagerContentComponent.InputInteraction(
performItemAction: { [weak interfaceInteraction] item, view, rect in
performItemAction: { [weak interfaceInteraction] item, view, rect, layer in
guard let interfaceInteraction = interfaceInteraction else {
return
}
let _ = interfaceInteraction.sendSticker(.standalone(media: item.file), false, view, rect)
let _ = interfaceInteraction.sendSticker(.standalone(media: item.file), false, view, rect, layer)
},
deleteBackwards: { [weak interfaceInteraction] in
guard let interfaceInteraction = interfaceInteraction else {
return
}
interfaceInteraction.backwardsDeleteText()
},
openStickerSettings: { [weak controllerInteraction] in
guard let controllerInteraction = controllerInteraction else {
return
}
let controller = installedStickerPacksController(context: context, mode: .modal)
controller.navigationPresentation = .modal
controllerInteraction.navigationController()?.pushViewController(controller)
}
)
let gifInputInteraction = GifPagerContentComponent.InputInteraction(
performItemAction: { [weak controllerInteraction] item, view, rect in
guard let controllerInteraction = controllerInteraction else {
return
}
let _ = controllerInteraction.sendGif(.savedGif(media: item.file), view, rect, false, false)
}
)
@@ -62,10 +87,24 @@ final class ChatEntityKeyboardInputNode: ChatInputNode {
})
let animationRenderer = MultiAnimationRendererImpl()
let emojiItems: Signal<EmojiPagerContentComponent, NoError> = context.engine.stickers.loadedStickerPack(reference: .animatedEmoji, forceActualized: false)
|> map { animatedEmoji -> EmojiPagerContentComponent in
let emojiItems: Signal<EmojiPagerContentComponent, NoError> = combineLatest(
context.engine.stickers.loadedStickerPack(reference: .animatedEmoji, forceActualized: false),
context.engine.data.subscribe(TelegramEngine.EngineData.Item.OrderedLists.ListItems(collectionId: Namespaces.OrderedItemList.CloudSavedStickers))
)
|> map { animatedEmoji, savedStickers -> EmojiPagerContentComponent in
var emojiItems: [EmojiPagerContentComponent.Item] = []
for item in savedStickers {
if let item = item.contents.get(SavedStickerItem.self) {
if item.file.isVideoSticker {
emojiItems.append(EmojiPagerContentComponent.Item(
emoji: "",
file: item.file
))
}
}
}
switch animatedEmoji {
case let .result(_, items, _):
for item in items {
@@ -97,24 +136,146 @@ final class ChatEntityKeyboardInputNode: ChatInputNode {
)
}
let orderedItemListCollectionIds: [Int32] = [Namespaces.OrderedItemList.CloudSavedStickers]
let hasPremium = context.engine.data.subscribe(TelegramEngine.EngineData.Item.Peer.Peer(id: context.account.peerId))
|> map { peer -> Bool in
guard case let .user(user) = peer else {
return false
}
return user.isPremium
}
|> distinctUntilChanged
let orderedItemListCollectionIds: [Int32] = [Namespaces.OrderedItemList.CloudSavedStickers, Namespaces.OrderedItemList.CloudRecentStickers, Namespaces.OrderedItemList.PremiumStickers, Namespaces.OrderedItemList.CloudPremiumStickers]
let namespaces: [ItemCollectionId.Namespace] = [Namespaces.ItemCollection.CloudStickerPacks]
let stickerItems: Signal<EmojiPagerContentComponent, NoError> = context.account.postbox.itemCollectionsView(orderedItemListCollectionIds: orderedItemListCollectionIds, namespaces: namespaces, aroundIndex: nil, count: 10000000)
|> map { view -> EmojiPagerContentComponent in
let stickerItems: Signal<EmojiPagerContentComponent, NoError> = combineLatest(
context.account.postbox.itemCollectionsView(orderedItemListCollectionIds: orderedItemListCollectionIds, namespaces: namespaces, aroundIndex: nil, count: 10000000),
hasPremium
)
|> map { view, hasPremium -> EmojiPagerContentComponent in
struct ItemGroup {
var id: ItemCollectionId
var id: AnyHashable
var items: [EmojiPagerContentComponent.Item]
}
var itemGroups: [ItemGroup] = []
var itemGroupIndexById: [AnyHashable: Int] = [:]
var savedStickers: OrderedItemListView?
var recentStickers: OrderedItemListView?
var premiumStickers: OrderedItemListView?
var cloudPremiumStickers: OrderedItemListView?
for orderedView in view.orderedItemListsViews {
if orderedView.collectionId == Namespaces.OrderedItemList.CloudRecentStickers {
recentStickers = orderedView
} else if orderedView.collectionId == Namespaces.OrderedItemList.CloudSavedStickers {
savedStickers = orderedView
} else if orderedView.collectionId == Namespaces.OrderedItemList.PremiumStickers {
premiumStickers = orderedView
} else if orderedView.collectionId == Namespaces.OrderedItemList.CloudPremiumStickers {
cloudPremiumStickers = orderedView
}
}
if let savedStickers = savedStickers {
for item in savedStickers.items {
guard let item = item.contents.get(SavedStickerItem.self) else {
continue
}
if isPremiumDisabled && item.file.isPremiumSticker {
continue
}
let resultItem = EmojiPagerContentComponent.Item(
emoji: "",
file: item.file
)
let groupId = "saved"
if let groupIndex = itemGroupIndexById[groupId] {
itemGroups[groupIndex].items.append(resultItem)
} else {
itemGroupIndexById[groupId] = itemGroups.count
itemGroups.append(ItemGroup(id: groupId, items: [resultItem]))
}
}
}
if let recentStickers = recentStickers {
var count = 0
for item in recentStickers.items {
guard let item = item.contents.get(RecentMediaItem.self) else {
continue
}
if isPremiumDisabled && item.media.isPremiumSticker {
continue
}
let resultItem = EmojiPagerContentComponent.Item(
emoji: "",
file: item.media
)
let groupId = "recent"
if let groupIndex = itemGroupIndexById[groupId] {
itemGroups[groupIndex].items.append(resultItem)
} else {
itemGroupIndexById[groupId] = itemGroups.count
itemGroups.append(ItemGroup(id: groupId, items: [resultItem]))
}
count += 1
if count >= 5 {
break
}
}
}
var hasPremiumStickers = false
if hasPremium {
if let premiumStickers = premiumStickers, !premiumStickers.items.isEmpty {
hasPremiumStickers = true
} else if let cloudPremiumStickers = cloudPremiumStickers, !cloudPremiumStickers.items.isEmpty {
hasPremiumStickers = true
}
}
if hasPremiumStickers {
var premiumStickers = premiumStickers?.items ?? []
if let cloudPremiumStickers = cloudPremiumStickers {
premiumStickers.append(contentsOf: cloudPremiumStickers.items)
}
var processedIds = Set<MediaId>()
for item in premiumStickers {
guard let item = item.contents.get(RecentMediaItem.self) else {
continue
}
if isPremiumDisabled && item.media.isPremiumSticker {
continue
}
if processedIds.contains(item.media.fileId) {
continue
}
processedIds.insert(item.media.fileId)
let resultItem = EmojiPagerContentComponent.Item(
emoji: "",
file: item.media
)
let groupId = "premium"
if let groupIndex = itemGroupIndexById[groupId] {
itemGroups[groupIndex].items.append(resultItem)
} else {
itemGroupIndexById[groupId] = itemGroups.count
itemGroups.append(ItemGroup(id: groupId, items: [resultItem]))
}
}
}
for entry in view.entries {
guard let item = entry.item as? StickerPackItem else {
continue
}
if !item.file.isAnimatedSticker {
continue
}
let resultItem = EmojiPagerContentComponent.Item(
emoji: "",
file: item.file
@@ -135,10 +296,20 @@ final class ChatEntityKeyboardInputNode: ChatInputNode {
inputInteraction: stickerInputInteraction,
itemGroups: itemGroups.map { group -> EmojiPagerContentComponent.ItemGroup in
var title: String?
for (id, info, _) in view.collectionInfos {
if id == group.id, let info = info as? StickerPackCollectionInfo {
title = info.title.uppercased()
break
if group.id == AnyHashable("saved") {
title = nil
} else if group.id == AnyHashable("recent") {
//TODO:localize
title = "Recently Used".uppercased()
} else if group.id == AnyHashable("premium") {
//TODO:localize
title = "Premium".uppercased()
} else {
for (id, info, _) in view.collectionInfos {
if AnyHashable(id) == group.id, let info = info as? StickerPackCollectionInfo {
title = info.title.uppercased()
break
}
}
}
@@ -148,14 +319,31 @@ final class ChatEntityKeyboardInputNode: ChatInputNode {
)
}
let gifItems: Signal<GifPagerContentComponent, NoError> = context.engine.data.subscribe(TelegramEngine.EngineData.Item.OrderedLists.ListItems(collectionId: Namespaces.OrderedItemList.CloudRecentGifs))
|> map { savedGifs -> GifPagerContentComponent in
var items: [GifPagerContentComponent.Item] = []
for gifItem in savedGifs {
items.append(GifPagerContentComponent.Item(
file: gifItem.contents.get(RecentMediaItem.self)!.media
))
}
return GifPagerContentComponent(
context: context,
inputInteraction: gifInputInteraction,
items: items
)
}
return combineLatest(queue: .mainQueue(),
emojiItems,
stickerItems
stickerItems,
gifItems
)
|> map { emoji, stickers -> InputData in
|> map { emoji, stickers, gifs -> InputData in
return InputData(
emoji: emoji,
stickers: stickers
stickers: stickers,
gifs: gifs
)
}
}
@@ -196,6 +384,7 @@ final class ChatEntityKeyboardInputNode: ChatInputNode {
bottomInset: bottomInset,
emojiContent: self.currentInputData.emoji,
stickerContent: self.currentInputData.stickers,
gifContent: self.currentInputData.gifs,
externalTopPanelContainer: self.externalTopPanelContainer,
topPanelExtensionUpdated: { [weak self] topPanelExtension, transition in
guard let strongSelf = self else {