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
0d4fd4f934
commit
9554305a33
@ -97,13 +97,15 @@ public enum ChatListItemContent {
|
||||
public var messageCount: Int?
|
||||
public var hideSeparator: Bool
|
||||
public var hideDate: Bool
|
||||
public var hidePeerStatus: Bool
|
||||
|
||||
public init(commandPrefix: String?, searchQuery: String?, messageCount: Int?, hideSeparator: Bool, hideDate: Bool) {
|
||||
public init(commandPrefix: String?, searchQuery: String?, messageCount: Int?, hideSeparator: Bool, hideDate: Bool, hidePeerStatus: Bool) {
|
||||
self.commandPrefix = commandPrefix
|
||||
self.searchQuery = searchQuery
|
||||
self.messageCount = messageCount
|
||||
self.hideSeparator = hideSeparator
|
||||
self.hideDate = hideDate
|
||||
self.hidePeerStatus = hidePeerStatus
|
||||
}
|
||||
}
|
||||
|
||||
@ -2340,7 +2342,7 @@ public class ChatListItemNode: ItemListRevealOptionsItemNode {
|
||||
|
||||
attributedText = foldLineBreaks(draftText)
|
||||
}
|
||||
} else if let message = messages.first {
|
||||
} else if let message = messages.last {
|
||||
var composedString: NSMutableAttributedString
|
||||
|
||||
if let peerText = peerText {
|
||||
@ -2942,7 +2944,7 @@ public class ChatListItemNode: ItemListRevealOptionsItemNode {
|
||||
break
|
||||
}
|
||||
} else if case let .chat(itemPeer) = contentPeer, let peer = itemPeer.chatMainPeer {
|
||||
if case let .peer(peerData) = item.content, peerData.customMessageListData != nil {
|
||||
if case let .peer(peerData) = item.content, peerData.customMessageListData?.hidePeerStatus == true {
|
||||
currentCredibilityIconContent = nil
|
||||
} else if case .savedMessagesChats = item.chatListLocation, peer.id == item.context.account.peerId {
|
||||
currentCredibilityIconContent = nil
|
||||
|
@ -1243,7 +1243,7 @@ public func selectivePrivacySettingsController(
|
||||
break
|
||||
}
|
||||
|
||||
let controller = selectivePrivacyPeersController(context: context, title: title, initialPeers: peerIds, initialEnableForPremium: stateValue.with({ $0 }).enableForPremium, displayPremiumCategory: displayPremiumCategory, updated: { updatedPeerIds, enableForPremium in
|
||||
let controller = selectivePrivacyPeersController(context: context, title: title, initialPeers: peerIds, initialEnableForPremium: displayPremiumCategory && stateValue.with({ $0 }).enableForPremium, displayPremiumCategory: displayPremiumCategory, updated: { updatedPeerIds, enableForPremium in
|
||||
updateState { state in
|
||||
if enable {
|
||||
switch target {
|
||||
|
@ -180,7 +180,7 @@ public final class ChatEmptyNodeGreetingChatContent: ASDisplayNode, ChatEmptyNod
|
||||
let previousCustomStickerFile = self.currentCustomStickerFile
|
||||
self.currentCustomStickerFile = customStickerFile
|
||||
|
||||
let stickerSize: CGSize
|
||||
var stickerSize: CGSize
|
||||
let inset: CGFloat
|
||||
if size.width == 320.0 {
|
||||
stickerSize = CGSize(width: 106.0, height: 106.0)
|
||||
@ -189,6 +189,11 @@ public final class ChatEmptyNodeGreetingChatContent: ASDisplayNode, ChatEmptyNod
|
||||
stickerSize = CGSize(width: 160.0, height: 160.0)
|
||||
inset = 15.0
|
||||
}
|
||||
|
||||
if let customStickerFile, let dimensions = customStickerFile.dimensions?.cgSize {
|
||||
stickerSize = dimensions.aspectFitted(stickerSize)
|
||||
}
|
||||
|
||||
if let item = self.stickerItem, previousCustomStickerFile == customStickerFile {
|
||||
self.stickerNode.updateLayout(item: item, size: stickerSize, isVisible: true, synchronousLoads: true)
|
||||
} else if !self.didSetupSticker || previousCustomStickerFile != customStickerFile {
|
||||
|
@ -588,7 +588,8 @@ private final class PeerInfoScreenPersonalChannelItemNode: PeerInfoScreenItemNod
|
||||
searchQuery: nil,
|
||||
messageCount: nil,
|
||||
hideSeparator: true,
|
||||
hideDate: isLoading
|
||||
hideDate: isLoading,
|
||||
hidePeerStatus: false
|
||||
)
|
||||
)),
|
||||
editing: false,
|
||||
|
@ -242,7 +242,8 @@ final class GreetingMessageListItemComponent: Component {
|
||||
searchQuery: nil,
|
||||
messageCount: component.count,
|
||||
hideSeparator: true,
|
||||
hideDate: true
|
||||
hideDate: true,
|
||||
hidePeerStatus: true
|
||||
)
|
||||
)),
|
||||
editing: false,
|
||||
|
@ -272,7 +272,8 @@ final class QuickReplySetupScreenComponent: Component {
|
||||
searchQuery: nil,
|
||||
messageCount: item.totalCount,
|
||||
hideSeparator: false,
|
||||
hideDate: true
|
||||
hideDate: true,
|
||||
hidePeerStatus: true
|
||||
)
|
||||
)),
|
||||
editing: isEditing,
|
||||
|
@ -294,7 +294,7 @@ final class BusinessIntroSetupScreenComponent: Component {
|
||||
if !self.isUpdating {
|
||||
self.state?.updated(transition: .immediate)
|
||||
}
|
||||
case let .text(rawQuery, _):
|
||||
case let .text(rawQuery, languageCode):
|
||||
let query = rawQuery.trimmingCharacters(in: .whitespacesAndNewlines)
|
||||
|
||||
if query.isEmpty {
|
||||
@ -304,7 +304,7 @@ final class BusinessIntroSetupScreenComponent: Component {
|
||||
} else {
|
||||
let context = component.context
|
||||
|
||||
let localSets = context.engine.stickers.searchStickerSets(query: query)
|
||||
/*let localSets = context.engine.stickers.searchStickerSets(query: query)
|
||||
let remoteSets: Signal<FoundStickerSets?, NoError> = .single(nil) |> then(
|
||||
context.engine.stickers.searchStickerSetsRemotely(query: query)
|
||||
|> map(Optional.init)
|
||||
@ -349,6 +349,199 @@ final class BusinessIntroSetupScreenComponent: Component {
|
||||
items.append(item)
|
||||
}
|
||||
|
||||
return .single([EmojiPagerContentComponent.ItemGroup(
|
||||
supergroupId: "search",
|
||||
groupId: "search",
|
||||
title: nil,
|
||||
subtitle: nil,
|
||||
badge: nil,
|
||||
actionButtonTitle: nil,
|
||||
isFeatured: false,
|
||||
isPremiumLocked: false,
|
||||
isEmbedded: false,
|
||||
hasClear: false,
|
||||
hasEdit: false,
|
||||
collapsedLineCount: nil,
|
||||
displayPremiumBadges: false,
|
||||
headerItem: nil,
|
||||
fillWithLoadingPlaceholders: false,
|
||||
items: items
|
||||
)])
|
||||
}*/
|
||||
|
||||
let stickers: Signal<[(String?, FoundStickerItem)], NoError> = Signal { subscriber in
|
||||
var signals: Signal<[Signal<(String?, [FoundStickerItem]), NoError>], NoError> = .single([])
|
||||
|
||||
if query.isSingleEmoji {
|
||||
signals = .single([context.engine.stickers.searchStickers(query: [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)
|
||||
if !languageCode.lowercased().hasPrefix("en") {
|
||||
signal = signal
|
||||
|> mapToSignal { keywords in
|
||||
return .single(keywords)
|
||||
|> then(
|
||||
context.engine.stickers.searchEmojiKeywords(inputLanguageCode: "en-US", query: query.lowercased(), completeMatch: query.count < 3)
|
||||
|> map { englishKeywords in
|
||||
return keywords + englishKeywords
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
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 {
|
||||
result.append((emoji, sticker))
|
||||
}
|
||||
}
|
||||
subscriber.putNext(result)
|
||||
}, completed: {
|
||||
subscriber.putCompletion()
|
||||
})
|
||||
}
|
||||
|
||||
let currentRemotePacks = Atomic<FoundStickerSets?>(value: nil)
|
||||
|
||||
let local = context.engine.stickers.searchStickerSets(query: query)
|
||||
let remote = context.engine.stickers.searchStickerSetsRemotely(query: query)
|
||||
|> delay(0.2, queue: Queue.mainQueue())
|
||||
let rawPacks = local
|
||||
|> mapToSignal { result -> Signal<(FoundStickerSets, Bool, FoundStickerSets?), NoError> in
|
||||
var localResult = result
|
||||
if let currentRemote = currentRemotePacks.with ({ $0 }) {
|
||||
localResult = localResult.merge(with: currentRemote)
|
||||
}
|
||||
return .single((localResult, false, nil))
|
||||
|> then(
|
||||
remote
|
||||
|> map { remote -> (FoundStickerSets, Bool, FoundStickerSets?) in
|
||||
return (result.merge(with: remote), true, remote)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
let installedPackIds = context.account.postbox.combinedView(keys: [.itemCollectionInfos(namespaces: [Namespaces.ItemCollection.CloudStickerPacks])])
|
||||
|> map { view -> Set<ItemCollectionId> in
|
||||
var installedPacks = Set<ItemCollectionId>()
|
||||
if let stickerPacksView = view.views[.itemCollectionInfos(namespaces: [Namespaces.ItemCollection.CloudStickerPacks])] as? ItemCollectionInfosView {
|
||||
if let packsEntries = stickerPacksView.entriesByNamespace[Namespaces.ItemCollection.CloudStickerPacks] {
|
||||
for entry in packsEntries {
|
||||
installedPacks.insert(entry.id)
|
||||
}
|
||||
}
|
||||
}
|
||||
return installedPacks
|
||||
}
|
||||
|> distinctUntilChanged
|
||||
let packs = combineLatest(rawPacks, installedPackIds)
|
||||
|> map { packs, installedPackIds -> (FoundStickerSets, Bool, FoundStickerSets?) in
|
||||
var (localPacks, completed, remotePacks) = packs
|
||||
|
||||
for i in 0 ..< localPacks.infos.count {
|
||||
let installed = installedPackIds.contains(localPacks.infos[i].0)
|
||||
if installed != localPacks.infos[i].3 {
|
||||
localPacks.infos[i].3 = installed
|
||||
}
|
||||
}
|
||||
|
||||
if remotePacks != nil {
|
||||
for i in 0 ..< remotePacks!.infos.count {
|
||||
let installed = installedPackIds.contains(remotePacks!.infos[i].0)
|
||||
if installed != remotePacks!.infos[i].3 {
|
||||
remotePacks!.infos[i].3 = installed
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (localPacks, completed, remotePacks)
|
||||
}
|
||||
|
||||
let signal = combineLatest(stickers, packs)
|
||||
|> map { stickers, packs -> ([(String?, FoundStickerItem)], FoundStickerSets, Bool, FoundStickerSets?)? in
|
||||
return (stickers, packs.0, packs.1, packs.2)
|
||||
}
|
||||
|
||||
let resultSignal: Signal<[EmojiPagerContentComponent.ItemGroup], NoError> = signal
|
||||
|> mapToSignal { result in
|
||||
guard let result else {
|
||||
return .complete()
|
||||
}
|
||||
|
||||
let (foundItems, localSets, complete, remoteSets) = result
|
||||
|
||||
var items: [EmojiPagerContentComponent.Item] = []
|
||||
|
||||
var existingIds = Set<MediaId>()
|
||||
for (_, entry) in foundItems {
|
||||
let itemFile = entry.file
|
||||
|
||||
if existingIds.contains(itemFile.fileId) {
|
||||
continue
|
||||
}
|
||||
existingIds.insert(itemFile.fileId)
|
||||
|
||||
let animationData = EntityKeyboardAnimationData(file: itemFile)
|
||||
let item = EmojiPagerContentComponent.Item(
|
||||
animationData: animationData,
|
||||
content: .animation(animationData),
|
||||
itemFile: itemFile,
|
||||
subgroupId: nil,
|
||||
icon: .none,
|
||||
tintMode: animationData.isTemplate ? .primary : .none
|
||||
)
|
||||
items.append(item)
|
||||
}
|
||||
|
||||
var mergedSets = localSets
|
||||
if let remoteSets {
|
||||
mergedSets = mergedSets.merge(with: remoteSets)
|
||||
}
|
||||
for entry in mergedSets.entries {
|
||||
guard let stickerPackItem = entry.item as? StickerPackItem else {
|
||||
continue
|
||||
}
|
||||
let itemFile = stickerPackItem.file
|
||||
|
||||
if existingIds.contains(itemFile.fileId) {
|
||||
continue
|
||||
}
|
||||
existingIds.insert(itemFile.fileId)
|
||||
|
||||
let animationData = EntityKeyboardAnimationData(file: itemFile)
|
||||
let item = EmojiPagerContentComponent.Item(
|
||||
animationData: animationData,
|
||||
content: .animation(animationData),
|
||||
itemFile: itemFile,
|
||||
subgroupId: nil,
|
||||
icon: .none,
|
||||
tintMode: animationData.isTemplate ? .primary : .none
|
||||
)
|
||||
items.append(item)
|
||||
}
|
||||
|
||||
if items.isEmpty && !complete {
|
||||
return .complete()
|
||||
}
|
||||
|
||||
return .single([EmojiPagerContentComponent.ItemGroup(
|
||||
supergroupId: "search",
|
||||
groupId: "search",
|
||||
@ -825,7 +1018,7 @@ final class BusinessIntroSetupScreenComponent: Component {
|
||||
var stickerSearchResults: EmojiPagerContentComponent.EmptySearchResults?
|
||||
if !stickerSearchResult.groups.contains(where: { !$0.items.isEmpty || $0.fillWithLoadingPlaceholders }) {
|
||||
stickerSearchResults = EmojiPagerContentComponent.EmptySearchResults(
|
||||
text: environment.strings.EmojiSearch_SearchStickersEmptyResult,
|
||||
text: "No stickers found",
|
||||
iconFile: nil
|
||||
)
|
||||
}
|
||||
|
@ -8459,6 +8459,14 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
customChatContents.enqueueMessages(messages: messages)
|
||||
strongSelf.chatDisplayNode.historyNode.scrollToEndOfHistory()
|
||||
case let .businessLinkSetup(link):
|
||||
if messages.count > 1 {
|
||||
strongSelf.present(standardTextAlertController(theme: AlertControllerTheme(presentationData: strongSelf.presentationData), title: nil, text: "The message text limit is 4096 characters", actions: [
|
||||
TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.Common_OK, action: {})
|
||||
]), in: .window(.root))
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
var text: String = ""
|
||||
var entities: [MessageTextEntity] = []
|
||||
if let message = messages.first {
|
||||
|
@ -3321,7 +3321,16 @@ class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDelegate, Ch
|
||||
}
|
||||
|
||||
private func updateCounterTextNode(transition: ContainedViewLayoutTransition) {
|
||||
if let textInputNode = self.textInputNode, let presentationInterfaceState = self.presentationInterfaceState, let editMessage = presentationInterfaceState.interfaceState.editMessage, let inputTextMaxLength = editMessage.inputTextMaxLength {
|
||||
var inputTextMaxLength: Int32?
|
||||
if let presentationInterfaceState = self.presentationInterfaceState {
|
||||
if let editMessage = presentationInterfaceState.interfaceState.editMessage, let inputTextMaxLengthValue = editMessage.inputTextMaxLength {
|
||||
inputTextMaxLength = inputTextMaxLengthValue
|
||||
} else if case let .customChatContents(customChatContents) = presentationInterfaceState.subject, case .businessLinkSetup = customChatContents.kind {
|
||||
inputTextMaxLength = 4096
|
||||
}
|
||||
}
|
||||
|
||||
if let presentationInterfaceState = self.presentationInterfaceState, let textInputNode = self.textInputNode, let inputTextMaxLength {
|
||||
let textCount = Int32(textInputNode.textView.text.count)
|
||||
let counterColor: UIColor = textCount > inputTextMaxLength ? presentationInterfaceState.theme.chat.inputPanel.panelControlDestructiveColor : presentationInterfaceState.theme.chat.inputPanel.panelControlColor
|
||||
|
||||
|
@ -227,7 +227,8 @@ private struct CommandChatInputContextPanelEntry: Comparable, Identifiable {
|
||||
searchQuery: command.searchQuery.flatMap { "/\($0)"},
|
||||
messageCount: shortcut.totalCount,
|
||||
hideSeparator: false,
|
||||
hideDate: true
|
||||
hideDate: true,
|
||||
hidePeerStatus: true
|
||||
)
|
||||
)),
|
||||
editing: false,
|
||||
|
Loading…
x
Reference in New Issue
Block a user