mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-15 21:45:19 +00:00
Refactoring
This commit is contained in:
parent
be3c85abff
commit
a183d69534
@ -696,8 +696,8 @@ public protocol SharedAccountContext: AnyObject {
|
||||
func openStorageUsage(context: AccountContext)
|
||||
func openLocationScreen(context: AccountContext, messageId: MessageId, navigationController: NavigationController)
|
||||
func openExternalUrl(context: AccountContext, urlContext: OpenURLContext, url: String, forceExternal: Bool, presentationData: PresentationData, navigationController: NavigationController?, dismissInput: @escaping () -> Void)
|
||||
func chatAvailableMessageActions(postbox: Postbox, accountPeerId: EnginePeer.Id, messageIds: Set<EngineMessage.Id>) -> Signal<ChatAvailableMessageActions, NoError>
|
||||
func chatAvailableMessageActions(postbox: Postbox, accountPeerId: EnginePeer.Id, messageIds: Set<EngineMessage.Id>, messages: [EngineMessage.Id: EngineMessage], peers: [EnginePeer.Id: EnginePeer]) -> Signal<ChatAvailableMessageActions, NoError>
|
||||
func chatAvailableMessageActions(engine: TelegramEngine, accountPeerId: EnginePeer.Id, messageIds: Set<EngineMessage.Id>) -> Signal<ChatAvailableMessageActions, NoError>
|
||||
func chatAvailableMessageActions(engine: TelegramEngine, accountPeerId: EnginePeer.Id, messageIds: Set<EngineMessage.Id>, messages: [EngineMessage.Id: EngineMessage], peers: [EnginePeer.Id: EnginePeer]) -> Signal<ChatAvailableMessageActions, NoError>
|
||||
func resolveUrl(context: AccountContext, peerId: PeerId?, url: String, skipUrlAuth: Bool) -> Signal<ResolvedUrl, NoError>
|
||||
func openResolvedUrl(_ resolvedUrl: ResolvedUrl, context: AccountContext, urlContext: OpenURLContext, navigationController: NavigationController?, forceExternal: Bool, openPeer: @escaping (PeerId, ChatControllerInteractionNavigateToPeer) -> Void, sendFile: ((FileMediaReference) -> Void)?, sendSticker: ((FileMediaReference, ASDisplayNode, CGRect) -> Bool)?, requestMessageActionUrlAuth: ((MessageActionUrlSubject) -> Void)?, joinVoiceChat: ((PeerId, String?, CachedChannelData.ActiveCall) -> Void)?, present: @escaping (ViewController, Any?) -> Void, dismissInput: @escaping () -> Void, contentContext: Any?)
|
||||
func openAddContact(context: AccountContext, firstName: String, lastName: String, phoneNumber: String, label: String, present: @escaping (ViewController, Any?) -> Void, pushController: @escaping (ViewController) -> Void, completed: @escaping () -> Void)
|
||||
|
@ -16,21 +16,25 @@ import PremiumUI
|
||||
func archiveContextMenuItems(context: AccountContext, groupId: PeerGroupId, chatListController: ChatListControllerImpl?) -> Signal<[ContextMenuItem], NoError> {
|
||||
let presentationData = context.sharedContext.currentPresentationData.with({ $0 })
|
||||
let strings = presentationData.strings
|
||||
return context.account.postbox.transaction { [weak chatListController] transaction -> [ContextMenuItem] in
|
||||
return combineLatest(
|
||||
context.engine.messages.unreadChatListPeerIds(groupId: EngineChatList.Group(groupId), filterPredicate: nil),
|
||||
context.engine.data.get(
|
||||
TelegramEngine.EngineData.Item.Configuration.ApplicationSpecificPreference(key: ApplicationSpecificPreferencesKeys.chatArchiveSettings)
|
||||
)
|
||||
)
|
||||
|> map { [weak chatListController] unreadChatListPeerIds, chatArchiveSettingsPreference -> [ContextMenuItem] in
|
||||
var items: [ContextMenuItem] = []
|
||||
|
||||
if !transaction.getUnreadChatListPeerIds(groupId: groupId, filterPredicate: nil).isEmpty {
|
||||
if !unreadChatListPeerIds.isEmpty {
|
||||
items.append(.action(ContextMenuActionItem(text: strings.ChatList_Context_MarkAllAsRead, icon: { theme in generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/MarkAsRead"), color: theme.contextMenu.primaryColor) }, action: { _, f in
|
||||
let _ = (context.account.postbox.transaction { transaction in
|
||||
markAllChatsAsReadInteractively(transaction: transaction, viewTracker: context.account.viewTracker, groupId: groupId, filterPredicate: nil)
|
||||
}
|
||||
let _ = (context.engine.messages.markAllChatsAsReadInteractively(items: [(groupId: EngineChatList.Group(groupId), filterPredicate: nil)])
|
||||
|> deliverOnMainQueue).start(completed: {
|
||||
f(.default)
|
||||
})
|
||||
})))
|
||||
}
|
||||
|
||||
let settings = transaction.getPreferencesEntry(key: ApplicationSpecificPreferencesKeys.chatArchiveSettings)?.get(ChatArchiveSettings.self) ?? ChatArchiveSettings.default
|
||||
let settings = chatArchiveSettingsPreference?.get(ChatArchiveSettings.self) ?? ChatArchiveSettings.default
|
||||
let isPinned = !settings.isHiddenByDefault
|
||||
items.append(.action(ContextMenuActionItem(text: isPinned ? strings.ChatList_Context_HideArchive : strings.ChatList_Context_UnhideArchive, icon: { theme in generateTintedImage(image: UIImage(bundleImageName: isPinned ? "Chat/Context Menu/Unpin": "Chat/Context Menu/Pin"), color: theme.contextMenu.primaryColor) }, action: { [weak chatListController] _, f in
|
||||
chatListController?.toggleArchivedFolderHiddenByDefault()
|
||||
@ -75,34 +79,41 @@ func chatContextMenuItems(context: AccountContext, peerId: PeerId, promoInfo: Ch
|
||||
)
|
||||
|> mapToSignal { filters, pinnedItemIds -> Signal<[ContextMenuItem], NoError> in
|
||||
let isPinned = pinnedItemIds.contains(.peer(peerId))
|
||||
|
||||
return context.account.postbox.transaction { [weak chatListController] transaction -> [ContextMenuItem] in
|
||||
if promoInfo != nil {
|
||||
return []
|
||||
|
||||
let renderedPeer = context.engine.data.get(TelegramEngine.EngineData.Item.Peer.RenderedPeer(id: peerId))
|
||||
|
||||
return renderedPeer
|
||||
|> mapToSignal { renderedPeer -> Signal<[ContextMenuItem], NoError> in
|
||||
guard let renderedPeer = renderedPeer else {
|
||||
return .single([])
|
||||
}
|
||||
guard let peer = renderedPeer.chatMainPeer else {
|
||||
return .single([])
|
||||
}
|
||||
|
||||
return context.engine.data.get(
|
||||
TelegramEngine.EngineData.Item.Peer.IsContact(id: peer.id),
|
||||
TelegramEngine.EngineData.Item.Peer.NotificationSettings(id: peer.id),
|
||||
TelegramEngine.EngineData.Item.Messages.ReadState(id: peer.id)
|
||||
)
|
||||
|> map { [weak chatListController] isContact, notificationSettings, readState -> [ContextMenuItem] in
|
||||
if promoInfo != nil {
|
||||
return []
|
||||
}
|
||||
|
||||
var items: [ContextMenuItem] = []
|
||||
var items: [ContextMenuItem] = []
|
||||
|
||||
if case let .search(search) = source {
|
||||
switch search {
|
||||
case .recentPeers:
|
||||
items.append(.action(ContextMenuActionItem(text: strings.ChatList_Context_RemoveFromRecents, textColor: .destructive, icon: { theme in generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Clear"), color: theme.contextMenu.destructiveColor) }, action: { _, f in
|
||||
let _ = (context.engine.peers.removeRecentPeer(peerId: peerId)
|
||||
|> deliverOnMainQueue).start(completed: {
|
||||
f(.default)
|
||||
})
|
||||
})))
|
||||
items.append(.separator)
|
||||
case .recentSearch:
|
||||
items.append(.action(ContextMenuActionItem(text: strings.ChatList_Context_RemoveFromRecents, textColor: .destructive, icon: { theme in generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Clear"), color: theme.contextMenu.destructiveColor) }, action: { _, f in
|
||||
let _ = (context.engine.peers.removeRecentlySearchedPeer(peerId: peerId)
|
||||
|> deliverOnMainQueue).start(completed: {
|
||||
f(.default)
|
||||
})
|
||||
})))
|
||||
items.append(.separator)
|
||||
case .search:
|
||||
if recentlySearchedPeers.contains(where: { $0.peer.peerId == peerId }) {
|
||||
if case let .search(search) = source {
|
||||
switch search {
|
||||
case .recentPeers:
|
||||
items.append(.action(ContextMenuActionItem(text: strings.ChatList_Context_RemoveFromRecents, textColor: .destructive, icon: { theme in generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Clear"), color: theme.contextMenu.destructiveColor) }, action: { _, f in
|
||||
let _ = (context.engine.peers.removeRecentPeer(peerId: peerId)
|
||||
|> deliverOnMainQueue).start(completed: {
|
||||
f(.default)
|
||||
})
|
||||
})))
|
||||
items.append(.separator)
|
||||
case .recentSearch:
|
||||
items.append(.action(ContextMenuActionItem(text: strings.ChatList_Context_RemoveFromRecents, textColor: .destructive, icon: { theme in generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Clear"), color: theme.contextMenu.destructiveColor) }, action: { _, f in
|
||||
let _ = (context.engine.peers.removeRecentlySearchedPeer(peerId: peerId)
|
||||
|> deliverOnMainQueue).start(completed: {
|
||||
@ -110,320 +121,308 @@ func chatContextMenuItems(context: AccountContext, peerId: PeerId, promoInfo: Ch
|
||||
})
|
||||
})))
|
||||
items.append(.separator)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let isSavedMessages = peerId == context.account.peerId
|
||||
|
||||
let chatPeer = transaction.getPeer(peerId)
|
||||
var maybePeer: Peer?
|
||||
if let chatPeer = chatPeer {
|
||||
if let chatPeer = chatPeer as? TelegramSecretChat {
|
||||
maybePeer = transaction.getPeer(chatPeer.regularPeerId)
|
||||
} else {
|
||||
maybePeer = chatPeer
|
||||
}
|
||||
}
|
||||
|
||||
guard let peer = maybePeer else {
|
||||
return []
|
||||
}
|
||||
|
||||
if !isSavedMessages, let peer = peer as? TelegramUser, !peer.flags.contains(.isSupport) && peer.botInfo == nil && !peer.isDeleted {
|
||||
if !transaction.isPeerContact(peerId: peer.id) {
|
||||
items.append(.action(ContextMenuActionItem(text: strings.ChatList_Context_AddToContacts, icon: { theme in generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/AddUser"), color: theme.contextMenu.primaryColor) }, action: { _, f in
|
||||
context.sharedContext.openAddPersonContact(context: context, peerId: peerId, pushController: { controller in
|
||||
if let navigationController = chatListController?.navigationController as? NavigationController {
|
||||
navigationController.pushViewController(controller)
|
||||
}
|
||||
}, present: { c, a in
|
||||
if let chatListController = chatListController {
|
||||
chatListController.present(c, in: .window(.root), with: a)
|
||||
}
|
||||
})
|
||||
f(.default)
|
||||
})))
|
||||
items.append(.separator)
|
||||
}
|
||||
}
|
||||
|
||||
var isMuted = false
|
||||
if let notificationSettings = transaction.getPeerNotificationSettings(peerId) as? TelegramPeerNotificationSettings {
|
||||
if case .muted = notificationSettings.muteState {
|
||||
isMuted = true
|
||||
}
|
||||
}
|
||||
|
||||
var isUnread = false
|
||||
if let readState = transaction.getCombinedPeerReadState(peerId), readState.isUnread {
|
||||
isUnread = true
|
||||
}
|
||||
|
||||
let isContact = transaction.isPeerContact(peerId: peerId)
|
||||
|
||||
if case let .chatList(currentFilter) = source {
|
||||
if let currentFilter = currentFilter, case let .filter(id, title, emoticon, data) = currentFilter {
|
||||
items.append(.action(ContextMenuActionItem(text: strings.ChatList_Context_RemoveFromFolder, icon: { theme in generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/RemoveFromFolder"), color: theme.contextMenu.primaryColor) }, action: { c, _ in
|
||||
let _ = (context.engine.peers.updateChatListFiltersInteractively { filters in
|
||||
var filters = filters
|
||||
for i in 0 ..< filters.count {
|
||||
if filters[i].id == currentFilter.id {
|
||||
var updatedData = data
|
||||
let _ = updatedData.addExcludePeer(peerId: peer.id)
|
||||
filters[i] = .filter(id: id, title: title, emoticon: emoticon, data: updatedData)
|
||||
break
|
||||
}
|
||||
}
|
||||
return filters
|
||||
}
|
||||
|> deliverOnMainQueue).start(completed: {
|
||||
c.dismiss(completion: {
|
||||
chatListController?.present(UndoOverlayController(presentationData: presentationData, content: .chatRemovedFromFolder(chatTitle: EnginePeer(peer).displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder), folderTitle: title), elevatedLayout: false, animateInAsReplacement: true, action: { _ in
|
||||
return false
|
||||
}), in: .current)
|
||||
})
|
||||
})
|
||||
})))
|
||||
} else {
|
||||
var hasFolders = false
|
||||
|
||||
for case let .filter(_, _, _, data) in filters {
|
||||
let predicate = chatListFilterPredicate(filter: data)
|
||||
if predicate.includes(peer: peer, groupId: .root, isRemovedFromTotalUnreadCount: isMuted, isUnread: isUnread, isContact: isContact, messageTagSummaryResult: false) {
|
||||
continue
|
||||
}
|
||||
|
||||
var data = data
|
||||
if data.addIncludePeer(peerId: peer.id) {
|
||||
hasFolders = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if hasFolders {
|
||||
items.append(.action(ContextMenuActionItem(text: strings.ChatList_Context_AddToFolder, icon: { theme in generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Folder"), color: theme.contextMenu.primaryColor) }, action: { c, _ in
|
||||
var updatedItems: [ContextMenuItem] = []
|
||||
|
||||
for filter in filters {
|
||||
if case let .filter(_, title, _, data) = filter {
|
||||
let predicate = chatListFilterPredicate(filter: data)
|
||||
if predicate.includes(peer: peer, groupId: .root, isRemovedFromTotalUnreadCount: isMuted, isUnread: isUnread, isContact: isContact, messageTagSummaryResult: false) {
|
||||
continue
|
||||
}
|
||||
|
||||
var data = data
|
||||
if !data.addIncludePeer(peerId: peer.id) {
|
||||
continue
|
||||
}
|
||||
|
||||
let filterType = chatListFilterType(data)
|
||||
updatedItems.append(.action(ContextMenuActionItem(text: title, icon: { theme in
|
||||
let imageName: String
|
||||
switch filterType {
|
||||
case .generic:
|
||||
imageName = "Chat/Context Menu/List"
|
||||
case .unmuted:
|
||||
imageName = "Chat/Context Menu/Unmute"
|
||||
case .unread:
|
||||
imageName = "Chat/Context Menu/MarkAsUnread"
|
||||
case .channels:
|
||||
imageName = "Chat/Context Menu/Channels"
|
||||
case .groups:
|
||||
imageName = "Chat/Context Menu/Groups"
|
||||
case .bots:
|
||||
imageName = "Chat/Context Menu/Bots"
|
||||
case .contacts:
|
||||
imageName = "Chat/Context Menu/User"
|
||||
case .nonContacts:
|
||||
imageName = "Chat/Context Menu/UnknownUser"
|
||||
}
|
||||
return generateTintedImage(image: UIImage(bundleImageName: imageName), color: theme.contextMenu.primaryColor)
|
||||
}, action: { c, f in
|
||||
c.dismiss(completion: {
|
||||
let _ = (context.engine.peers.updateChatListFiltersInteractively { filters in
|
||||
var filters = filters
|
||||
for i in 0 ..< filters.count {
|
||||
if filters[i].id == filter.id {
|
||||
if case let .filter(id, title, emoticon, data) = filter {
|
||||
var updatedData = data
|
||||
let _ = updatedData.addIncludePeer(peerId: peer.id)
|
||||
filters[i] = .filter(id: id, title: title, emoticon: emoticon, data: updatedData)
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
return filters
|
||||
}).start()
|
||||
|
||||
chatListController?.present(UndoOverlayController(presentationData: presentationData, content: .chatAddedToFolder(chatTitle: EnginePeer(peer).displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder), folderTitle: title), elevatedLayout: false, animateInAsReplacement: true, action: { _ in
|
||||
return false
|
||||
}), in: .current)
|
||||
})
|
||||
})))
|
||||
}
|
||||
}
|
||||
|
||||
updatedItems.append(.separator)
|
||||
updatedItems.append(.action(ContextMenuActionItem(text: strings.ChatList_Context_Back, icon: { theme in
|
||||
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Back"), color: theme.contextMenu.primaryColor)
|
||||
}, action: { c, _ in
|
||||
c.setItems(chatContextMenuItems(context: context, peerId: peerId, promoInfo: promoInfo, source: source, chatListController: chatListController, joined: joined) |> map { ContextController.Items(content: .list($0)) }, minHeight: nil)
|
||||
})))
|
||||
|
||||
c.setItems(.single(ContextController.Items(content: .list(updatedItems))), minHeight: nil)
|
||||
})))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if isUnread {
|
||||
items.append(.action(ContextMenuActionItem(text: strings.ChatList_Context_MarkAsRead, icon: { theme in generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/MarkAsRead"), color: theme.contextMenu.primaryColor) }, action: { _, f in
|
||||
let _ = togglePeerUnreadMarkInteractively(postbox: context.account.postbox, viewTracker: context.account.viewTracker, peerId: peerId).start()
|
||||
f(.default)
|
||||
})))
|
||||
} else {
|
||||
items.append(.action(ContextMenuActionItem(text: strings.ChatList_Context_MarkAsUnread, icon: { theme in generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/MarkAsUnread"), color: theme.contextMenu.primaryColor) }, action: { _, f in
|
||||
let _ = togglePeerUnreadMarkInteractively(postbox: context.account.postbox, viewTracker: context.account.viewTracker, peerId: peerId).start()
|
||||
f(.default)
|
||||
})))
|
||||
}
|
||||
|
||||
let archiveEnabled = !isSavedMessages && peerId != PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(777000)) && peerId == context.account.peerId
|
||||
if let group = peerGroup {
|
||||
if archiveEnabled {
|
||||
let isArchived = group == .archive
|
||||
items.append(.action(ContextMenuActionItem(text: isArchived ? strings.ChatList_Context_Unarchive : strings.ChatList_Context_Archive, icon: { theme in generateTintedImage(image: UIImage(bundleImageName: isArchived ? "Chat/Context Menu/Unarchive" : "Chat/Context Menu/Archive"), color: theme.contextMenu.primaryColor) }, action: { _, f in
|
||||
if isArchived {
|
||||
let _ = (context.account.postbox.transaction { transaction -> Void in
|
||||
updatePeerGroupIdInteractively(transaction: transaction, peerId: peerId, groupId: .root)
|
||||
}
|
||||
|> deliverOnMainQueue).start(completed: {
|
||||
f(.default)
|
||||
})
|
||||
} else {
|
||||
if let chatListController = chatListController {
|
||||
chatListController.archiveChats(peerIds: [peerId])
|
||||
f(.default)
|
||||
} else {
|
||||
let _ = (context.account.postbox.transaction { transaction -> Void in
|
||||
updatePeerGroupIdInteractively(transaction: transaction, peerId: peerId, groupId: Namespaces.PeerGroup.archive)
|
||||
}
|
||||
case .search:
|
||||
if recentlySearchedPeers.contains(where: { $0.peer.peerId == peerId }) {
|
||||
items.append(.action(ContextMenuActionItem(text: strings.ChatList_Context_RemoveFromRecents, textColor: .destructive, icon: { theme in generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Clear"), color: theme.contextMenu.destructiveColor) }, action: { _, f in
|
||||
let _ = (context.engine.peers.removeRecentlySearchedPeer(peerId: peerId)
|
||||
|> deliverOnMainQueue).start(completed: {
|
||||
f(.default)
|
||||
})
|
||||
}
|
||||
})))
|
||||
items.append(.separator)
|
||||
}
|
||||
})))
|
||||
}
|
||||
|
||||
if isPinned || chatListFilter == nil || peerId.namespace != Namespaces.Peer.SecretChat {
|
||||
items.append(.action(ContextMenuActionItem(text: isPinned ? strings.ChatList_Context_Unpin : strings.ChatList_Context_Pin, icon: { theme in generateTintedImage(image: UIImage(bundleImageName: isPinned ? "Chat/Context Menu/Unpin" : "Chat/Context Menu/Pin"), color: theme.contextMenu.primaryColor) }, action: { c, f in
|
||||
let _ = (context.engine.peers.toggleItemPinned(location: location, itemId: .peer(peerId))
|
||||
|> deliverOnMainQueue).start(next: { result in
|
||||
switch result {
|
||||
case .done:
|
||||
f(.default)
|
||||
case let .limitExceeded(count, _):
|
||||
f(.default)
|
||||
|
||||
var replaceImpl: ((ViewController) -> Void)?
|
||||
let controller = PremiumLimitScreen(context: context, subject: .pins, count: Int32(count), action: {
|
||||
let premiumScreen = PremiumIntroScreen(context: context, source: .pinnedChats)
|
||||
replaceImpl?(premiumScreen)
|
||||
})
|
||||
chatListController?.push(controller)
|
||||
replaceImpl = { [weak controller] c in
|
||||
controller?.replace(with: c)
|
||||
}
|
||||
}
|
||||
})
|
||||
})))
|
||||
}
|
||||
|
||||
if !isSavedMessages, let notificationSettings = transaction.getPeerNotificationSettings(peerId) as? TelegramPeerNotificationSettings {
|
||||
var isMuted = false
|
||||
if case .muted = notificationSettings.muteState {
|
||||
isMuted = true
|
||||
}
|
||||
items.append(.action(ContextMenuActionItem(text: isMuted ? strings.ChatList_Context_Unmute : strings.ChatList_Context_Mute, icon: { theme in generateTintedImage(image: UIImage(bundleImageName: isMuted ? "Chat/Context Menu/Unmute" : "Chat/Context Menu/Muted"), color: theme.contextMenu.primaryColor) }, action: { _, f in
|
||||
let _ = (context.engine.peers.togglePeerMuted(peerId: peerId)
|
||||
|> deliverOnMainQueue).start(completed: {
|
||||
f(.default)
|
||||
})
|
||||
})))
|
||||
}
|
||||
} else {
|
||||
if case .search = source {
|
||||
if let peer = peer as? TelegramChannel {
|
||||
let text: String
|
||||
if case .broadcast = peer.info {
|
||||
text = strings.ChatList_Context_JoinChannel
|
||||
} else {
|
||||
text = strings.ChatList_Context_JoinChat
|
||||
}
|
||||
items.append(.action(ContextMenuActionItem(text: text, icon: { theme in generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Add"), color: theme.contextMenu.primaryColor) }, action: { _, f in
|
||||
var createSignal = context.peerChannelMemberCategoriesContextsManager.join(engine: context.engine, peerId: peerId, hash: nil)
|
||||
var cancelImpl: (() -> Void)?
|
||||
let progressSignal = Signal<Never, NoError> { subscriber in
|
||||
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||
let controller = OverlayStatusController(theme: presentationData.theme, type: .loading(cancelled: {
|
||||
cancelImpl?()
|
||||
}))
|
||||
chatListController?.present(controller, in: .window(.root))
|
||||
return ActionDisposable { [weak controller] in
|
||||
Queue.mainQueue().async() {
|
||||
controller?.dismiss()
|
||||
}
|
||||
}
|
||||
}
|
||||
|> runOn(Queue.mainQueue())
|
||||
|> delay(0.15, queue: Queue.mainQueue())
|
||||
let progressDisposable = progressSignal.start()
|
||||
|
||||
createSignal = createSignal
|
||||
|> afterDisposed {
|
||||
Queue.mainQueue().async {
|
||||
progressDisposable.dispose()
|
||||
}
|
||||
}
|
||||
let joinChannelDisposable = MetaDisposable()
|
||||
cancelImpl = {
|
||||
joinChannelDisposable.set(nil)
|
||||
}
|
||||
let isSavedMessages = peerId == context.account.peerId
|
||||
|
||||
joinChannelDisposable.set((createSignal
|
||||
|> deliverOnMainQueue).start(next: { _ in
|
||||
}, error: { _ in
|
||||
if !isSavedMessages, case let .user(peer) = peer, !peer.flags.contains(.isSupport), peer.botInfo == nil && !peer.isDeleted {
|
||||
if !isContact {
|
||||
items.append(.action(ContextMenuActionItem(text: strings.ChatList_Context_AddToContacts, icon: { theme in generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/AddUser"), color: theme.contextMenu.primaryColor) }, action: { _, f in
|
||||
context.sharedContext.openAddPersonContact(context: context, peerId: peerId, pushController: { controller in
|
||||
if let navigationController = chatListController?.navigationController as? NavigationController {
|
||||
navigationController.pushViewController(controller)
|
||||
}
|
||||
}, present: { c, a in
|
||||
if let chatListController = chatListController {
|
||||
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||
chatListController.present(textAlertController(context: context, title: nil, text: presentationData.strings.Login_UnknownError, actions: [TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_OK, action: {})]), in: .window(.root))
|
||||
chatListController.present(c, in: .window(.root), with: a)
|
||||
}
|
||||
}, completed: {
|
||||
if let navigationController = (chatListController?.navigationController as? NavigationController) {
|
||||
context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: context, chatLocation: .peer(id: peerId)))
|
||||
}
|
||||
}))
|
||||
})
|
||||
f(.default)
|
||||
})))
|
||||
items.append(.separator)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if case .chatList = source, peerGroup != nil {
|
||||
items.append(.action(ContextMenuActionItem(text: strings.ChatList_Context_Delete, textColor: .destructive, icon: { theme in generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Delete"), color: theme.contextMenu.destructiveColor) }, action: { _, f in
|
||||
if let chatListController = chatListController {
|
||||
chatListController.deletePeerChat(peerId: peerId, joined: joined)
|
||||
var isMuted = false
|
||||
if case .muted = notificationSettings.muteState {
|
||||
isMuted = true
|
||||
}
|
||||
|
||||
var isUnread = false
|
||||
if let readState = readState, readState.isUnread {
|
||||
isUnread = true
|
||||
}
|
||||
|
||||
if case let .chatList(currentFilter) = source {
|
||||
if let currentFilter = currentFilter, case let .filter(id, title, emoticon, data) = currentFilter {
|
||||
items.append(.action(ContextMenuActionItem(text: strings.ChatList_Context_RemoveFromFolder, icon: { theme in generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/RemoveFromFolder"), color: theme.contextMenu.primaryColor) }, action: { c, _ in
|
||||
let _ = (context.engine.peers.updateChatListFiltersInteractively { filters in
|
||||
var filters = filters
|
||||
for i in 0 ..< filters.count {
|
||||
if filters[i].id == currentFilter.id {
|
||||
var updatedData = data
|
||||
let _ = updatedData.addExcludePeer(peerId: peer.id)
|
||||
filters[i] = .filter(id: id, title: title, emoticon: emoticon, data: updatedData)
|
||||
break
|
||||
}
|
||||
}
|
||||
return filters
|
||||
}
|
||||
|> deliverOnMainQueue).start(completed: {
|
||||
c.dismiss(completion: {
|
||||
chatListController?.present(UndoOverlayController(presentationData: presentationData, content: .chatRemovedFromFolder(chatTitle: peer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder), folderTitle: title), elevatedLayout: false, animateInAsReplacement: true, action: { _ in
|
||||
return false
|
||||
}), in: .current)
|
||||
})
|
||||
})
|
||||
})))
|
||||
} else {
|
||||
var hasFolders = false
|
||||
|
||||
for case let .filter(_, _, _, data) in filters {
|
||||
let predicate = chatListFilterPredicate(filter: data)
|
||||
if predicate.includes(peer: peer._asPeer(), groupId: .root, isRemovedFromTotalUnreadCount: isMuted, isUnread: isUnread, isContact: isContact, messageTagSummaryResult: false) {
|
||||
continue
|
||||
}
|
||||
|
||||
var data = data
|
||||
if data.addIncludePeer(peerId: peer.id) {
|
||||
hasFolders = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if hasFolders {
|
||||
items.append(.action(ContextMenuActionItem(text: strings.ChatList_Context_AddToFolder, icon: { theme in generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Folder"), color: theme.contextMenu.primaryColor) }, action: { c, _ in
|
||||
var updatedItems: [ContextMenuItem] = []
|
||||
|
||||
for filter in filters {
|
||||
if case let .filter(_, title, _, data) = filter {
|
||||
let predicate = chatListFilterPredicate(filter: data)
|
||||
if predicate.includes(peer: peer._asPeer(), groupId: .root, isRemovedFromTotalUnreadCount: isMuted, isUnread: isUnread, isContact: isContact, messageTagSummaryResult: false) {
|
||||
continue
|
||||
}
|
||||
|
||||
var data = data
|
||||
if !data.addIncludePeer(peerId: peer.id) {
|
||||
continue
|
||||
}
|
||||
|
||||
let filterType = chatListFilterType(data)
|
||||
updatedItems.append(.action(ContextMenuActionItem(text: title, icon: { theme in
|
||||
let imageName: String
|
||||
switch filterType {
|
||||
case .generic:
|
||||
imageName = "Chat/Context Menu/List"
|
||||
case .unmuted:
|
||||
imageName = "Chat/Context Menu/Unmute"
|
||||
case .unread:
|
||||
imageName = "Chat/Context Menu/MarkAsUnread"
|
||||
case .channels:
|
||||
imageName = "Chat/Context Menu/Channels"
|
||||
case .groups:
|
||||
imageName = "Chat/Context Menu/Groups"
|
||||
case .bots:
|
||||
imageName = "Chat/Context Menu/Bots"
|
||||
case .contacts:
|
||||
imageName = "Chat/Context Menu/User"
|
||||
case .nonContacts:
|
||||
imageName = "Chat/Context Menu/UnknownUser"
|
||||
}
|
||||
return generateTintedImage(image: UIImage(bundleImageName: imageName), color: theme.contextMenu.primaryColor)
|
||||
}, action: { c, f in
|
||||
c.dismiss(completion: {
|
||||
let _ = (context.engine.peers.updateChatListFiltersInteractively { filters in
|
||||
var filters = filters
|
||||
for i in 0 ..< filters.count {
|
||||
if filters[i].id == filter.id {
|
||||
if case let .filter(id, title, emoticon, data) = filter {
|
||||
var updatedData = data
|
||||
let _ = updatedData.addIncludePeer(peerId: peer.id)
|
||||
filters[i] = .filter(id: id, title: title, emoticon: emoticon, data: updatedData)
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
return filters
|
||||
}).start()
|
||||
|
||||
chatListController?.present(UndoOverlayController(presentationData: presentationData, content: .chatAddedToFolder(chatTitle: peer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder), folderTitle: title), elevatedLayout: false, animateInAsReplacement: true, action: { _ in
|
||||
return false
|
||||
}), in: .current)
|
||||
})
|
||||
})))
|
||||
}
|
||||
}
|
||||
|
||||
updatedItems.append(.separator)
|
||||
updatedItems.append(.action(ContextMenuActionItem(text: strings.ChatList_Context_Back, icon: { theme in
|
||||
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Back"), color: theme.contextMenu.primaryColor)
|
||||
}, action: { c, _ in
|
||||
c.setItems(chatContextMenuItems(context: context, peerId: peerId, promoInfo: promoInfo, source: source, chatListController: chatListController, joined: joined) |> map { ContextController.Items(content: .list($0)) }, minHeight: nil)
|
||||
})))
|
||||
|
||||
c.setItems(.single(ContextController.Items(content: .list(updatedItems))), minHeight: nil)
|
||||
})))
|
||||
}
|
||||
}
|
||||
f(.default)
|
||||
})))
|
||||
}
|
||||
}
|
||||
|
||||
if let item = items.last, case .separator = item {
|
||||
items.removeLast()
|
||||
}
|
||||
if isUnread {
|
||||
items.append(.action(ContextMenuActionItem(text: strings.ChatList_Context_MarkAsRead, icon: { theme in generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/MarkAsRead"), color: theme.contextMenu.primaryColor) }, action: { _, f in
|
||||
let _ = togglePeerUnreadMarkInteractively(postbox: context.account.postbox, viewTracker: context.account.viewTracker, peerId: peerId).start()
|
||||
f(.default)
|
||||
})))
|
||||
} else {
|
||||
items.append(.action(ContextMenuActionItem(text: strings.ChatList_Context_MarkAsUnread, icon: { theme in generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/MarkAsUnread"), color: theme.contextMenu.primaryColor) }, action: { _, f in
|
||||
let _ = togglePeerUnreadMarkInteractively(postbox: context.account.postbox, viewTracker: context.account.viewTracker, peerId: peerId).start()
|
||||
f(.default)
|
||||
})))
|
||||
}
|
||||
|
||||
return items
|
||||
let archiveEnabled = !isSavedMessages && peerId != PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(777000)) && peerId == context.account.peerId
|
||||
if let group = peerGroup {
|
||||
if archiveEnabled {
|
||||
let isArchived = group == .archive
|
||||
items.append(.action(ContextMenuActionItem(text: isArchived ? strings.ChatList_Context_Unarchive : strings.ChatList_Context_Archive, icon: { theme in generateTintedImage(image: UIImage(bundleImageName: isArchived ? "Chat/Context Menu/Unarchive" : "Chat/Context Menu/Archive"), color: theme.contextMenu.primaryColor) }, action: { _, f in
|
||||
if isArchived {
|
||||
let _ = (context.engine.peers.updatePeersGroupIdInteractively(peerIds: [peerId], groupId: .root)
|
||||
|> deliverOnMainQueue).start(completed: {
|
||||
f(.default)
|
||||
})
|
||||
} else {
|
||||
if let chatListController = chatListController {
|
||||
chatListController.archiveChats(peerIds: [peerId])
|
||||
f(.default)
|
||||
} else {
|
||||
let _ = (context.engine.peers.updatePeersGroupIdInteractively(peerIds: [peerId], groupId: .archive)
|
||||
|> deliverOnMainQueue).start(completed: {
|
||||
f(.default)
|
||||
})
|
||||
}
|
||||
}
|
||||
})))
|
||||
}
|
||||
|
||||
if isPinned || chatListFilter == nil || peerId.namespace != Namespaces.Peer.SecretChat {
|
||||
items.append(.action(ContextMenuActionItem(text: isPinned ? strings.ChatList_Context_Unpin : strings.ChatList_Context_Pin, icon: { theme in generateTintedImage(image: UIImage(bundleImageName: isPinned ? "Chat/Context Menu/Unpin" : "Chat/Context Menu/Pin"), color: theme.contextMenu.primaryColor) }, action: { c, f in
|
||||
let _ = (context.engine.peers.toggleItemPinned(location: location, itemId: .peer(peerId))
|
||||
|> deliverOnMainQueue).start(next: { result in
|
||||
switch result {
|
||||
case .done:
|
||||
f(.default)
|
||||
case let .limitExceeded(count, _):
|
||||
f(.default)
|
||||
|
||||
var replaceImpl: ((ViewController) -> Void)?
|
||||
let controller = PremiumLimitScreen(context: context, subject: .pins, count: Int32(count), action: {
|
||||
let premiumScreen = PremiumIntroScreen(context: context, source: .pinnedChats)
|
||||
replaceImpl?(premiumScreen)
|
||||
})
|
||||
chatListController?.push(controller)
|
||||
replaceImpl = { [weak controller] c in
|
||||
controller?.replace(with: c)
|
||||
}
|
||||
}
|
||||
})
|
||||
})))
|
||||
}
|
||||
|
||||
if !isSavedMessages {
|
||||
var isMuted = false
|
||||
if case .muted = notificationSettings.muteState {
|
||||
isMuted = true
|
||||
}
|
||||
items.append(.action(ContextMenuActionItem(text: isMuted ? strings.ChatList_Context_Unmute : strings.ChatList_Context_Mute, icon: { theme in generateTintedImage(image: UIImage(bundleImageName: isMuted ? "Chat/Context Menu/Unmute" : "Chat/Context Menu/Muted"), color: theme.contextMenu.primaryColor) }, action: { _, f in
|
||||
let _ = (context.engine.peers.togglePeerMuted(peerId: peerId)
|
||||
|> deliverOnMainQueue).start(completed: {
|
||||
f(.default)
|
||||
})
|
||||
})))
|
||||
}
|
||||
} else {
|
||||
if case .search = source {
|
||||
if case let .channel(peer) = peer {
|
||||
let text: String
|
||||
if case .broadcast = peer.info {
|
||||
text = strings.ChatList_Context_JoinChannel
|
||||
} else {
|
||||
text = strings.ChatList_Context_JoinChat
|
||||
}
|
||||
items.append(.action(ContextMenuActionItem(text: text, icon: { theme in generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Add"), color: theme.contextMenu.primaryColor) }, action: { _, f in
|
||||
var createSignal = context.peerChannelMemberCategoriesContextsManager.join(engine: context.engine, peerId: peerId, hash: nil)
|
||||
var cancelImpl: (() -> Void)?
|
||||
let progressSignal = Signal<Never, NoError> { subscriber in
|
||||
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||
let controller = OverlayStatusController(theme: presentationData.theme, type: .loading(cancelled: {
|
||||
cancelImpl?()
|
||||
}))
|
||||
chatListController?.present(controller, in: .window(.root))
|
||||
return ActionDisposable { [weak controller] in
|
||||
Queue.mainQueue().async() {
|
||||
controller?.dismiss()
|
||||
}
|
||||
}
|
||||
}
|
||||
|> runOn(Queue.mainQueue())
|
||||
|> delay(0.15, queue: Queue.mainQueue())
|
||||
let progressDisposable = progressSignal.start()
|
||||
|
||||
createSignal = createSignal
|
||||
|> afterDisposed {
|
||||
Queue.mainQueue().async {
|
||||
progressDisposable.dispose()
|
||||
}
|
||||
}
|
||||
let joinChannelDisposable = MetaDisposable()
|
||||
cancelImpl = {
|
||||
joinChannelDisposable.set(nil)
|
||||
}
|
||||
|
||||
joinChannelDisposable.set((createSignal
|
||||
|> deliverOnMainQueue).start(next: { _ in
|
||||
}, error: { _ in
|
||||
if let chatListController = chatListController {
|
||||
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||
chatListController.present(textAlertController(context: context, title: nil, text: presentationData.strings.Login_UnknownError, actions: [TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_OK, action: {})]), in: .window(.root))
|
||||
}
|
||||
}, completed: {
|
||||
if let navigationController = (chatListController?.navigationController as? NavigationController) {
|
||||
context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: context, chatLocation: .peer(id: peerId)))
|
||||
}
|
||||
}))
|
||||
f(.default)
|
||||
})))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if case .chatList = source, peerGroup != nil {
|
||||
items.append(.action(ContextMenuActionItem(text: strings.ChatList_Context_Delete, textColor: .destructive, icon: { theme in generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Delete"), color: theme.contextMenu.destructiveColor) }, action: { _, f in
|
||||
if let chatListController = chatListController {
|
||||
chatListController.deletePeerChat(peerId: peerId, joined: joined)
|
||||
}
|
||||
f(.default)
|
||||
})))
|
||||
}
|
||||
|
||||
if let item = items.last, case .separator = item {
|
||||
items.removeLast()
|
||||
}
|
||||
|
||||
return items
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -964,7 +964,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
|
||||
strongSelf.archiveChats(peerIds: [peerId])
|
||||
} else {
|
||||
strongSelf.chatListDisplayNode.containerNode.currentItemNode.setCurrentRemovingPeerId(peerId)
|
||||
let _ = updatePeerGroupIdInteractively(postbox: strongSelf.context.account.postbox, peerId: peerId, groupId: group ? Namespaces.PeerGroup.archive : .root).start(completed: {
|
||||
let _ = strongSelf.context.engine.peers.updatePeersGroupIdInteractively(peerIds: [peerId], groupId: group ? .archive : .root).start(completed: {
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
@ -2419,7 +2419,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
|
||||
override public func toolbarActionSelected(action: ToolbarActionOption) {
|
||||
let peerIds = self.chatListDisplayNode.containerNode.currentItemNode.currentState.selectedPeerIds
|
||||
if case .left = action {
|
||||
let signal: Signal<Void, NoError>
|
||||
let signal: Signal<Never, NoError>
|
||||
var completion: (() -> Void)?
|
||||
let context = self.context
|
||||
if !peerIds.isEmpty {
|
||||
@ -2432,6 +2432,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
|
||||
togglePeerUnreadMarkInteractively(transaction: transaction, viewTracker: context.account.viewTracker, peerId: peerId, setToValue: false)
|
||||
}
|
||||
}
|
||||
|> ignoreValues
|
||||
} else {
|
||||
let groupId = self.groupId
|
||||
let filterPredicate: ChatListFilterPredicate?
|
||||
@ -2440,14 +2441,14 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
|
||||
} else {
|
||||
filterPredicate = nil
|
||||
}
|
||||
signal = self.context.account.postbox.transaction { transaction -> Void in
|
||||
markAllChatsAsReadInteractively(transaction: transaction, viewTracker: context.account.viewTracker, groupId: groupId, filterPredicate: filterPredicate)
|
||||
if let filterPredicate = filterPredicate {
|
||||
for additionalGroupId in filterPredicate.includeAdditionalPeerGroupIds {
|
||||
markAllChatsAsReadInteractively(transaction: transaction, viewTracker: context.account.viewTracker, groupId: additionalGroupId, filterPredicate: filterPredicate)
|
||||
}
|
||||
var markItems: [(groupId: EngineChatList.Group, filterPredicate: ChatListFilterPredicate?)] = []
|
||||
markItems.append((EngineChatList.Group(groupId), filterPredicate))
|
||||
if let filterPredicate = filterPredicate {
|
||||
for additionalGroupId in filterPredicate.includeAdditionalPeerGroupIds {
|
||||
markItems.append((EngineChatList.Group(additionalGroupId), filterPredicate))
|
||||
}
|
||||
}
|
||||
signal = self.context.engine.messages.markAllChatsAsReadInteractively(items: markItems)
|
||||
}
|
||||
let _ = (signal
|
||||
|> deliverOnMainQueue).start(completed: { [weak self] in
|
||||
@ -2545,11 +2546,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
|
||||
} else {
|
||||
if !peerIds.isEmpty {
|
||||
self.chatListDisplayNode.containerNode.currentItemNode.setCurrentRemovingPeerId(peerIds.first!)
|
||||
let _ = (self.context.account.postbox.transaction { transaction -> Void in
|
||||
for peerId in peerIds {
|
||||
updatePeerGroupIdInteractively(transaction: transaction, peerId: peerId, groupId: .root)
|
||||
}
|
||||
}
|
||||
let _ = (self.context.engine.peers.updatePeersGroupIdInteractively(peerIds: Array(peerIds), groupId: .root)
|
||||
|> deliverOnMainQueue).start(completed: { [weak self] in
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
@ -3047,15 +3044,11 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
|
||||
guard !peerIds.isEmpty else {
|
||||
return
|
||||
}
|
||||
let postbox = self.context.account.postbox
|
||||
let engine = self.context.engine
|
||||
self.chatListDisplayNode.containerNode.currentItemNode.setCurrentRemovingPeerId(peerIds[0])
|
||||
let _ = (ApplicationSpecificNotice.incrementArchiveChatTips(accountManager: self.context.sharedContext.accountManager, count: 1)
|
||||
|> deliverOnMainQueue).start(next: { [weak self] previousHintCount in
|
||||
let _ = (postbox.transaction { transaction -> Void in
|
||||
for peerId in peerIds {
|
||||
updatePeerGroupIdInteractively(transaction: transaction, peerId: peerId, groupId: Namespaces.PeerGroup.archive)
|
||||
}
|
||||
}
|
||||
let _ = (engine.peers.updatePeersGroupIdInteractively(peerIds: peerIds, groupId: .archive)
|
||||
|> deliverOnMainQueue).start(completed: {
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
@ -3072,11 +3065,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
|
||||
}
|
||||
if value == .undo {
|
||||
strongSelf.chatListDisplayNode.containerNode.currentItemNode.setCurrentRemovingPeerId(peerIds[0])
|
||||
let _ = (postbox.transaction { transaction -> Void in
|
||||
for peerId in peerIds {
|
||||
updatePeerGroupIdInteractively(transaction: transaction, peerId: peerId, groupId: .root)
|
||||
}
|
||||
}
|
||||
let _ = (engine.peers.updatePeersGroupIdInteractively(peerIds: peerIds, groupId: .root)
|
||||
|> deliverOnMainQueue).start(completed: {
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
|
@ -719,7 +719,7 @@ public final class ChatListSearchContainerNode: SearchDisplayControllerContentNo
|
||||
}
|
||||
|
||||
let (peers, messages) = strongSelf.currentMessages
|
||||
return strongSelf.context.sharedContext.chatAvailableMessageActions(postbox: strongSelf.context.account.postbox, accountPeerId: strongSelf.context.account.peerId, messageIds: messageIds, messages: messages, peers: peers)
|
||||
return strongSelf.context.sharedContext.chatAvailableMessageActions(engine: strongSelf.context.engine, accountPeerId: strongSelf.context.account.peerId, messageIds: messageIds, messages: messages, peers: peers)
|
||||
}
|
||||
self.selectionPanelNode = selectionPanelNode
|
||||
self.addSubnode(selectionPanelNode)
|
||||
@ -825,7 +825,7 @@ public final class ChatListSearchContainerNode: SearchDisplayControllerContentNo
|
||||
}
|
||||
|
||||
let items = combineLatest(queue: .mainQueue(),
|
||||
context.sharedContext.chatAvailableMessageActions(postbox: context.account.postbox, accountPeerId: context.account.peerId, messageIds: [message.id], messages: [message.id: message], peers: [:]),
|
||||
context.sharedContext.chatAvailableMessageActions(engine: context.engine, accountPeerId: context.account.peerId, messageIds: [message.id], messages: [message.id: message], peers: [:]),
|
||||
isCachedValue |> take(1)
|
||||
)
|
||||
|> deliverOnMainQueue
|
||||
@ -934,7 +934,7 @@ public final class ChatListSearchContainerNode: SearchDisplayControllerContentNo
|
||||
|
||||
let context = self.context
|
||||
let (peers, messages) = self.currentMessages
|
||||
let items = context.sharedContext.chatAvailableMessageActions(postbox: context.account.postbox, accountPeerId: context.account.peerId, messageIds: [message.id], messages: messages, peers: peers)
|
||||
let items = context.sharedContext.chatAvailableMessageActions(engine: context.engine, accountPeerId: context.account.peerId, messageIds: [message.id], messages: messages, peers: peers)
|
||||
|> map { [weak self] actions -> [ContextMenuItem] in
|
||||
guard let strongSelf = self else {
|
||||
return []
|
||||
@ -1000,7 +1000,7 @@ public final class ChatListSearchContainerNode: SearchDisplayControllerContentNo
|
||||
let strings = strongSelf.presentationData.strings
|
||||
|
||||
let (peers, messages) = strongSelf.currentMessages
|
||||
let items = context.sharedContext.chatAvailableMessageActions(postbox: context.account.postbox, accountPeerId: context.account.peerId, messageIds: [message.id], messages: messages, peers: peers)
|
||||
let items = context.sharedContext.chatAvailableMessageActions(engine: context.engine, accountPeerId: context.account.peerId, messageIds: [message.id], messages: messages, peers: peers)
|
||||
|> map { actions -> [ContextMenuItem] in
|
||||
var items: [ContextMenuItem] = []
|
||||
|
||||
@ -1129,7 +1129,7 @@ public final class ChatListSearchContainerNode: SearchDisplayControllerContentNo
|
||||
|
||||
self.context.engine.messages.ensureMessagesAreLocallyAvailable(messages: messages.values.filter { messageIds.contains($0.id) })
|
||||
|
||||
self.activeActionDisposable.set((self.context.sharedContext.chatAvailableMessageActions(postbox: self.context.account.postbox, accountPeerId: self.context.account.peerId, messageIds: messageIds, messages: messages, peers: peers)
|
||||
self.activeActionDisposable.set((self.context.sharedContext.chatAvailableMessageActions(engine: self.context.engine, accountPeerId: self.context.account.peerId, messageIds: messageIds, messages: messages, peers: peers)
|
||||
|> deliverOnMainQueue).start(next: { [weak self] actions in
|
||||
if let strongSelf = self, !actions.options.isEmpty {
|
||||
let actionSheet = ActionSheetController(presentationData: strongSelf.presentationData)
|
||||
|
@ -581,8 +581,6 @@ public enum ChatListGlobalScrollOption {
|
||||
}
|
||||
|
||||
public enum ChatListNodeScrollPosition {
|
||||
case auto
|
||||
case autoUp
|
||||
case top
|
||||
}
|
||||
|
||||
@ -1895,29 +1893,6 @@ public final class ChatListNode: ListView {
|
||||
|
||||
public func scrollToPosition(_ position: ChatListNodeScrollPosition) {
|
||||
if let view = self.chatListView?.originalView {
|
||||
if case .auto = position {
|
||||
switch self.visibleContentOffset() {
|
||||
case .none, .unknown:
|
||||
if let maxVisibleChatListIndex = self.currentlyVisibleLatestChatListIndex() {
|
||||
self.scrollToEarliestUnread(earlierThan: maxVisibleChatListIndex)
|
||||
return
|
||||
}
|
||||
case let .known(offset):
|
||||
if offset <= 0.0 {
|
||||
self.scrollToEarliestUnread(earlierThan: nil)
|
||||
return
|
||||
} else {
|
||||
if let maxVisibleChatListIndex = self.currentlyVisibleLatestChatListIndex() {
|
||||
self.scrollToEarliestUnread(earlierThan: maxVisibleChatListIndex)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if case .autoUp = position, let maxVisibleChatListIndex = self.currentlyVisibleLatestChatListIndex() {
|
||||
self.scrollToEarliestUnread(earlierThan: maxVisibleChatListIndex)
|
||||
return
|
||||
}
|
||||
|
||||
if view.laterIndex == nil {
|
||||
self.transaction(deleteIndices: [], insertIndicesAndItems: [], updateIndicesAndItems: [], options: [.Synchronous], scrollToItem: ListViewScrollToItem(index: 0, position: .top(0.0), animated: true, curve: .Default(duration: nil), directionHint: .Up), updateSizeAndInsets: nil, stationaryItemRange: nil, updateOpaqueState: nil, completion: { _ in })
|
||||
} else {
|
||||
@ -1938,7 +1913,7 @@ public final class ChatListNode: ListView {
|
||||
|
||||
private func relativeUnreadChatListIndex(position: EngineChatList.RelativePosition) -> Signal<EngineChatList.Item.Index?, NoError> {
|
||||
let groupId = self.groupId
|
||||
let postbox = self.context.account.postbox
|
||||
let engine = self.context.engine
|
||||
return self.context.sharedContext.accountManager.transaction { transaction -> Signal<EngineChatList.Item.Index?, NoError> in
|
||||
var filter = true
|
||||
if let inAppNotificationSettings = transaction.getSharedData(ApplicationSpecificSharedDataKeys.inAppNotificationSettings)?.get(InAppNotificationSettings.self) {
|
||||
@ -1947,31 +1922,11 @@ public final class ChatListNode: ListView {
|
||||
filter = true
|
||||
}
|
||||
}
|
||||
return postbox.transaction { transaction -> EngineChatList.Item.Index? in
|
||||
return transaction.getRelativeUnreadChatListIndex(filtered: filter, position: position._asPosition(), groupId: groupId._asGroup())
|
||||
}
|
||||
return engine.messages.getRelativeUnreadChatListIndex(filtered: filter, position: position, groupId: groupId)
|
||||
}
|
||||
|> switchToLatest
|
||||
}
|
||||
|
||||
public func scrollToEarliestUnread(earlierThan: EngineChatList.Item.Index?) {
|
||||
let _ = (relativeUnreadChatListIndex(position: .earlier(than: earlierThan)) |> deliverOnMainQueue).start(next: { [weak self] index in
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
|
||||
if let index = index {
|
||||
let location: ChatListNodeLocation = .scroll(index: index, sourceIndex: self?.currentlyVisibleLatestChatListIndex() ?? .absoluteUpperBound
|
||||
, scrollPosition: .center(.top), animated: true, filter: strongSelf.chatListFilter)
|
||||
strongSelf.setChatListLocation(location)
|
||||
} else {
|
||||
let location: ChatListNodeLocation = .scroll(index: .absoluteUpperBound, sourceIndex: .absoluteLowerBound
|
||||
, scrollPosition: .top(0.0), animated: true, filter: strongSelf.chatListFilter)
|
||||
strongSelf.setChatListLocation(location)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
public func selectChat(_ option: ChatListSelectionOption) {
|
||||
guard let interaction = self.interaction else {
|
||||
return
|
||||
|
@ -230,7 +230,7 @@ public func chatMessageGalleryControllerData(context: AccountContext, chatLocati
|
||||
if let timecode = timecode {
|
||||
startState = .single((timecode: timecode, rate: 1.0))
|
||||
} else {
|
||||
startState = mediaPlaybackStoredState(postbox: context.account.postbox, messageId: message.id)
|
||||
startState = mediaPlaybackStoredState(engine: context.engine, messageId: message.id)
|
||||
|> map { state in
|
||||
return (state?.timestamp, state?.playbackRate.doubleValue ?? 1.0)
|
||||
}
|
||||
|
@ -1093,7 +1093,7 @@ final class ChatItemGalleryFooterContentNode: GalleryFooterContentNode, UIScroll
|
||||
}
|
||||
|
||||
private func commitDeleteMessages(_ messages: [EngineMessage], ask: Bool) {
|
||||
self.messageContextDisposable.set((self.context.sharedContext.chatAvailableMessageActions(postbox: self.context.account.postbox, accountPeerId: self.context.account.peerId, messageIds: Set(messages.map { $0.id })) |> deliverOnMainQueue).start(next: { [weak self] actions in
|
||||
self.messageContextDisposable.set((self.context.sharedContext.chatAvailableMessageActions(engine: self.context.engine, accountPeerId: self.context.account.peerId, messageIds: Set(messages.map { $0.id })) |> deliverOnMainQueue).start(next: { [weak self] actions in
|
||||
if let strongSelf = self, let controllerInteration = strongSelf.controllerInteraction, !actions.options.isEmpty {
|
||||
var presentationData = strongSelf.presentationData
|
||||
if !presentationData.theme.overallDarkAppearance {
|
||||
|
@ -317,7 +317,7 @@ final class ChatImageGalleryItemNode: ZoomableContentGalleryItemNode {
|
||||
|
||||
Queue.concurrentDefaultQueue().async {
|
||||
if let message = strongSelf.message, !message.isCopyProtected() && !imageReference.media.flags.contains(.hasStickers) {
|
||||
strongSelf.recognitionDisposable.set((recognizedContent(postbox: strongSelf.context.account.postbox, image: { return generate(TransformImageArguments(corners: ImageCorners(), imageSize: displaySize, boundingSize: displaySize, intrinsicInsets: UIEdgeInsets()))?.generateImage() }, messageId: message.id)
|
||||
strongSelf.recognitionDisposable.set((recognizedContent(engine: strongSelf.context.engine, image: { return generate(TransformImageArguments(corners: ImageCorners(), imageSize: displaySize, boundingSize: displaySize, intrinsicInsets: UIEdgeInsets()))?.generateImage() }, messageId: message.id)
|
||||
|> deliverOnMainQueue).start(next: { [weak self] results in
|
||||
if let strongSelf = self {
|
||||
strongSelf.recognizedContentNode?.removeFromSupernode()
|
||||
|
@ -26,36 +26,30 @@ private final class CachedImageRecognizedContent: Codable {
|
||||
}
|
||||
}
|
||||
|
||||
private func cachedImageRecognizedContent(postbox: Postbox, messageId: MessageId) -> Signal<CachedImageRecognizedContent?, NoError> {
|
||||
return postbox.transaction { transaction -> CachedImageRecognizedContent? in
|
||||
let key = ValueBoxKey(length: 20)
|
||||
key.setInt32(0, value: messageId.namespace)
|
||||
key.setInt32(4, value: messageId.peerId.namespace._internalGetInt32Value())
|
||||
key.setInt64(8, value: messageId.peerId.id._internalGetInt64Value())
|
||||
key.setInt32(16, value: messageId.id)
|
||||
if let entry = transaction.retrieveItemCacheEntry(id: ItemCacheEntryId(collectionId: ApplicationSpecificItemCacheCollectionId.cachedImageRecognizedContent, key: key))?.get(CachedImageRecognizedContent.self) {
|
||||
return entry
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
private func cachedImageRecognizedContent(engine: TelegramEngine, messageId: MessageId) -> Signal<CachedImageRecognizedContent?, NoError> {
|
||||
let key = ValueBoxKey(length: 20)
|
||||
key.setInt32(0, value: messageId.namespace)
|
||||
key.setInt32(4, value: messageId.peerId.namespace._internalGetInt32Value())
|
||||
key.setInt64(8, value: messageId.peerId.id._internalGetInt64Value())
|
||||
key.setInt32(16, value: messageId.id)
|
||||
|
||||
return engine.data.get(TelegramEngine.EngineData.Item.ItemCache.Item(collectionId: ApplicationSpecificItemCacheCollectionId.cachedImageRecognizedContent, id: key))
|
||||
|> map { entry -> CachedImageRecognizedContent? in
|
||||
return entry?.get(CachedImageRecognizedContent.self)
|
||||
}
|
||||
}
|
||||
|
||||
private let collectionSpec = ItemCacheCollectionSpec(lowWaterItemCount: 50, highWaterItemCount: 100)
|
||||
|
||||
private func updateCachedImageRecognizedContent(postbox: Postbox, messageId: MessageId, content: CachedImageRecognizedContent?) -> Signal<Void, NoError> {
|
||||
return postbox.transaction { transaction -> Void in
|
||||
let key = ValueBoxKey(length: 20)
|
||||
key.setInt32(0, value: messageId.namespace)
|
||||
key.setInt32(4, value: messageId.peerId.namespace._internalGetInt32Value())
|
||||
key.setInt64(8, value: messageId.peerId.id._internalGetInt64Value())
|
||||
key.setInt32(16, value: messageId.id)
|
||||
let id = ItemCacheEntryId(collectionId: ApplicationSpecificItemCacheCollectionId.cachedImageRecognizedContent, key: key)
|
||||
if let content = content, let entry = CodableEntry(content) {
|
||||
transaction.putItemCacheEntry(id: id, entry: entry, collectionSpec: collectionSpec)
|
||||
} else {
|
||||
transaction.removeItemCacheEntry(id: id)
|
||||
}
|
||||
private func updateCachedImageRecognizedContent(engine: TelegramEngine, messageId: MessageId, content: CachedImageRecognizedContent?) -> Signal<Never, NoError> {
|
||||
let key = ValueBoxKey(length: 20)
|
||||
key.setInt32(0, value: messageId.namespace)
|
||||
key.setInt32(4, value: messageId.peerId.namespace._internalGetInt32Value())
|
||||
key.setInt64(8, value: messageId.peerId.id._internalGetInt64Value())
|
||||
key.setInt32(16, value: messageId.id)
|
||||
|
||||
if let content = content {
|
||||
return engine.itemCache.put(collectionId: ApplicationSpecificItemCacheCollectionId.cachedImageRecognizedContent, id: key, item: content)
|
||||
} else {
|
||||
return engine.itemCache.remove(collectionId: ApplicationSpecificItemCacheCollectionId.cachedImageRecognizedContent, id: key)
|
||||
}
|
||||
}
|
||||
|
||||
@ -338,8 +332,8 @@ private func recognizeContent(in image: UIImage?) -> Signal<[RecognizedContent],
|
||||
}
|
||||
}
|
||||
|
||||
public func recognizedContent(postbox: Postbox, image: @escaping () -> UIImage?, messageId: MessageId) -> Signal<[RecognizedContent], NoError> {
|
||||
return cachedImageRecognizedContent(postbox: postbox, messageId: messageId)
|
||||
public func recognizedContent(engine: TelegramEngine, image: @escaping () -> UIImage?, messageId: MessageId) -> Signal<[RecognizedContent], NoError> {
|
||||
return cachedImageRecognizedContent(engine: engine, messageId: messageId)
|
||||
|> mapToSignal { cachedContent -> Signal<[RecognizedContent], NoError> in
|
||||
if let cachedContent = cachedContent {
|
||||
return .single(cachedContent.results)
|
||||
@ -349,7 +343,7 @@ public func recognizedContent(postbox: Postbox, image: @escaping () -> UIImage?,
|
||||
|> then(
|
||||
recognizeContent(in: image())
|
||||
|> beforeNext { results in
|
||||
let _ = updateCachedImageRecognizedContent(postbox: postbox, messageId: messageId, content: CachedImageRecognizedContent(results: results)).start()
|
||||
let _ = updateCachedImageRecognizedContent(engine: engine, messageId: messageId, content: CachedImageRecognizedContent(results: results)).start()
|
||||
}
|
||||
)
|
||||
}
|
||||
|
@ -32,29 +32,23 @@ public final class CachedInstantPage: Codable {
|
||||
}
|
||||
}
|
||||
|
||||
public func cachedInstantPage(postbox: Postbox, url: String) -> Signal<CachedInstantPage?, NoError> {
|
||||
return postbox.transaction { transaction -> CachedInstantPage? in
|
||||
let key = ValueBoxKey(length: 8)
|
||||
key.setInt64(0, value: Int64(bitPattern: url.persistentHashValue))
|
||||
if let entry = transaction.retrieveItemCacheEntry(id: ItemCacheEntryId(collectionId: ApplicationSpecificItemCacheCollectionId.cachedInstantPages, key: key))?.get(CachedInstantPage.self) {
|
||||
return entry
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
public func cachedInstantPage(engine: TelegramEngine, url: String) -> Signal<CachedInstantPage?, NoError> {
|
||||
let key = ValueBoxKey(length: 8)
|
||||
key.setInt64(0, value: Int64(bitPattern: url.persistentHashValue))
|
||||
|
||||
return engine.data.get(TelegramEngine.EngineData.Item.ItemCache.Item(collectionId: ApplicationSpecificItemCacheCollectionId.cachedInstantPages, id: key))
|
||||
|> map { entry -> CachedInstantPage? in
|
||||
return entry?.get(CachedInstantPage.self)
|
||||
}
|
||||
}
|
||||
|
||||
private let collectionSpec = ItemCacheCollectionSpec(lowWaterItemCount: 5, highWaterItemCount: 10)
|
||||
|
||||
public func updateCachedInstantPage(postbox: Postbox, url: String, webPage: TelegramMediaWebpage?) -> Signal<Void, NoError> {
|
||||
return postbox.transaction { transaction -> Void in
|
||||
let key = ValueBoxKey(length: 8)
|
||||
key.setInt64(0, value: Int64(bitPattern: url.persistentHashValue))
|
||||
let id = ItemCacheEntryId(collectionId: ApplicationSpecificItemCacheCollectionId.cachedInstantPages, key: key)
|
||||
if let webPage = webPage, let entry = CodableEntry(CachedInstantPage(webPage: webPage, timestamp: Int32(CFAbsoluteTimeGetCurrent()))) {
|
||||
transaction.putItemCacheEntry(id: id, entry: entry, collectionSpec: collectionSpec)
|
||||
} else {
|
||||
transaction.removeItemCacheEntry(id: id)
|
||||
}
|
||||
public func updateCachedInstantPage(engine: TelegramEngine, url: String, webPage: TelegramMediaWebpage?) -> Signal<Never, NoError> {
|
||||
let key = ValueBoxKey(length: 8)
|
||||
key.setInt64(0, value: Int64(bitPattern: url.persistentHashValue))
|
||||
|
||||
if let webPage = webPage {
|
||||
return engine.itemCache.put(collectionId: ApplicationSpecificItemCacheCollectionId.cachedInstantPages, id: key, item: CachedInstantPage(webPage: webPage, timestamp: Int32(CFAbsoluteTimeGetCurrent())))
|
||||
} else {
|
||||
return engine.itemCache.remove(collectionId: ApplicationSpecificItemCacheCollectionId.cachedInstantPages, id: key)
|
||||
}
|
||||
}
|
||||
|
@ -51,18 +51,18 @@ public func cachedPrivacyPage(context: AccountContext) -> Signal<ResolvedUrl, No
|
||||
|
||||
private func cachedInternalInstantPage(context: AccountContext, url: String) -> Signal<ResolvedUrl, NoError> {
|
||||
let (cachedUrl, anchor) = extractAnchor(string: url)
|
||||
return cachedInstantPage(postbox: context.account.postbox, url: cachedUrl)
|
||||
return cachedInstantPage(engine: context.engine, url: cachedUrl)
|
||||
|> mapToSignal { cachedInstantPage -> Signal<ResolvedUrl, NoError> in
|
||||
let updated = resolveInstantViewUrl(account: context.account, url: url)
|
||||
|> afterNext { result in
|
||||
if case let .instantView(webPage, _) = result, case let .Loaded(content) = webPage.content, let instantPage = content.instantPage {
|
||||
if instantPage.isComplete {
|
||||
let _ = updateCachedInstantPage(postbox: context.account.postbox, url: cachedUrl, webPage: webPage).start()
|
||||
let _ = updateCachedInstantPage(engine: context.engine, url: cachedUrl, webPage: webPage).start()
|
||||
} else {
|
||||
let _ = (actualizedWebpage(postbox: context.account.postbox, network: context.account.network, webpage: webPage)
|
||||
|> mapToSignal { webPage -> Signal<Void, NoError> in
|
||||
|> mapToSignal { webPage -> Signal<Never, NoError> in
|
||||
if case let .Loaded(content) = webPage.content, let instantPage = content.instantPage, instantPage.isComplete {
|
||||
return updateCachedInstantPage(postbox: context.account.postbox, url: cachedUrl, webPage: webPage)
|
||||
return updateCachedInstantPage(engine: context.engine, url: cachedUrl, webPage: webPage)
|
||||
} else {
|
||||
return .complete()
|
||||
}
|
||||
|
@ -141,7 +141,7 @@ public final class InstantPageController: ViewController {
|
||||
}
|
||||
|
||||
override public func viewWillDisappear(_ animated: Bool) {
|
||||
let _ = updateInstantPageStoredStateInteractively(postbox: self.context.account.postbox, webPage: self.webPage, state: self.controllerNode.currentState).start()
|
||||
let _ = updateInstantPageStoredStateInteractively(engine: self.context.engine, webPage: self.webPage, state: self.controllerNode.currentState).start()
|
||||
}
|
||||
|
||||
override public func loadDisplayNode() {
|
||||
@ -167,7 +167,7 @@ public final class InstantPageController: ViewController {
|
||||
}
|
||||
})
|
||||
|
||||
self.storedStateDisposable = (instantPageStoredState(postbox: self.context.account.postbox, webPage: self.webPage)
|
||||
self.storedStateDisposable = (instantPageStoredState(engine: self.context.engine, webPage: self.webPage)
|
||||
|> deliverOnMainQueue).start(next: { [weak self] state in
|
||||
if let strongSelf = self {
|
||||
strongSelf.controllerNode.updateWebPage(strongSelf.webPage, anchor: strongSelf.anchor, state: state)
|
||||
|
@ -57,29 +57,23 @@ public final class InstantPageStoredState: Codable {
|
||||
}
|
||||
}
|
||||
|
||||
public func instantPageStoredState(postbox: Postbox, webPage: TelegramMediaWebpage) -> Signal<InstantPageStoredState?, NoError> {
|
||||
return postbox.transaction { transaction -> InstantPageStoredState? in
|
||||
let key = ValueBoxKey(length: 8)
|
||||
key.setInt64(0, value: webPage.webpageId.id)
|
||||
if let entry = transaction.retrieveItemCacheEntry(id: ItemCacheEntryId(collectionId: ApplicationSpecificItemCacheCollectionId.instantPageStoredState, key: key))?.get(InstantPageStoredState.self) {
|
||||
return entry
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
public func instantPageStoredState(engine: TelegramEngine, webPage: TelegramMediaWebpage) -> Signal<InstantPageStoredState?, NoError> {
|
||||
let key = ValueBoxKey(length: 8)
|
||||
key.setInt64(0, value: webPage.webpageId.id)
|
||||
|
||||
return engine.data.get(TelegramEngine.EngineData.Item.ItemCache.Item(collectionId: ApplicationSpecificItemCacheCollectionId.instantPageStoredState, id: key))
|
||||
|> map { entry -> InstantPageStoredState? in
|
||||
return entry?.get(InstantPageStoredState.self)
|
||||
}
|
||||
}
|
||||
|
||||
private let collectionSpec = ItemCacheCollectionSpec(lowWaterItemCount: 100, highWaterItemCount: 200)
|
||||
|
||||
public func updateInstantPageStoredStateInteractively(postbox: Postbox, webPage: TelegramMediaWebpage, state: InstantPageStoredState?) -> Signal<Void, NoError> {
|
||||
return postbox.transaction { transaction -> Void in
|
||||
let key = ValueBoxKey(length: 8)
|
||||
key.setInt64(0, value: webPage.webpageId.id)
|
||||
let id = ItemCacheEntryId(collectionId: ApplicationSpecificItemCacheCollectionId.instantPageStoredState, key: key)
|
||||
if let state = state, let entry = CodableEntry(state) {
|
||||
transaction.putItemCacheEntry(id: id, entry: entry, collectionSpec: collectionSpec)
|
||||
} else {
|
||||
transaction.removeItemCacheEntry(id: id)
|
||||
}
|
||||
public func updateInstantPageStoredStateInteractively(engine: TelegramEngine, webPage: TelegramMediaWebpage, state: InstantPageStoredState?) -> Signal<Never, NoError> {
|
||||
let key = ValueBoxKey(length: 8)
|
||||
key.setInt64(0, value: webPage.webpageId.id)
|
||||
|
||||
if let state = state {
|
||||
return engine.itemCache.put(collectionId: ApplicationSpecificItemCacheCollectionId.instantPageStoredState, id: key, item: state)
|
||||
} else {
|
||||
return engine.itemCache.remove(collectionId: ApplicationSpecificItemCacheCollectionId.instantPageStoredState, id: key)
|
||||
}
|
||||
}
|
||||
|
@ -32,34 +32,27 @@ public final class CachedGeocode: Codable {
|
||||
}
|
||||
}
|
||||
|
||||
private func cachedGeocode(postbox: Postbox, address: DeviceContactAddressData) -> Signal<CachedGeocode?, NoError> {
|
||||
return postbox.transaction { transaction -> CachedGeocode? in
|
||||
let key = ValueBoxKey(length: 8)
|
||||
key.setInt64(0, value: Int64(bitPattern: address.string.persistentHashValue))
|
||||
if let entry = transaction.retrieveItemCacheEntry(id: ItemCacheEntryId(collectionId: ApplicationSpecificItemCacheCollectionId.cachedGeocodes, key: key))?.get(CachedGeocode.self) {
|
||||
return entry
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
private func cachedGeocode(engine: TelegramEngine, address: DeviceContactAddressData) -> Signal<CachedGeocode?, NoError> {
|
||||
let key = ValueBoxKey(length: 8)
|
||||
key.setInt64(0, value: Int64(bitPattern: address.string.persistentHashValue))
|
||||
|
||||
return engine.data.get(TelegramEngine.EngineData.Item.ItemCache.Item(collectionId: ApplicationSpecificItemCacheCollectionId.cachedGeocodes, id: key))
|
||||
|> map { entry -> CachedGeocode? in
|
||||
return entry?.get(CachedGeocode.self)
|
||||
}
|
||||
}
|
||||
|
||||
private let collectionSpec = ItemCacheCollectionSpec(lowWaterItemCount: 10, highWaterItemCount: 20)
|
||||
|
||||
private func updateCachedGeocode(postbox: Postbox, address: DeviceContactAddressData, latitude: Double, longitude: Double) -> Signal<(Double, Double), NoError> {
|
||||
return postbox.transaction { transaction -> (Double, Double) in
|
||||
let key = ValueBoxKey(length: 8)
|
||||
key.setInt64(0, value: Int64(bitPattern: address.string.persistentHashValue))
|
||||
let id = ItemCacheEntryId(collectionId: ApplicationSpecificItemCacheCollectionId.cachedGeocodes, key: key)
|
||||
if let entry = CodableEntry(CachedGeocode(latitude: latitude, longitude: longitude)) {
|
||||
transaction.putItemCacheEntry(id: id, entry: entry, collectionSpec: collectionSpec)
|
||||
}
|
||||
return (latitude, longitude)
|
||||
}
|
||||
private func updateCachedGeocode(engine: TelegramEngine, address: DeviceContactAddressData, latitude: Double, longitude: Double) -> Signal<(Double, Double), NoError> {
|
||||
let key = ValueBoxKey(length: 8)
|
||||
key.setInt64(0, value: Int64(bitPattern: address.string.persistentHashValue))
|
||||
|
||||
return engine.itemCache.put(collectionId: ApplicationSpecificItemCacheCollectionId.cachedGeocodes, id: key, item: CachedGeocode(latitude: latitude, longitude: longitude))
|
||||
|> map { _ -> (Double, Double) in }
|
||||
|> then(.single((latitude, longitude)))
|
||||
}
|
||||
|
||||
public func geocodeAddress(postbox: Postbox, address: DeviceContactAddressData) -> Signal<(Double, Double)?, NoError> {
|
||||
return cachedGeocode(postbox: postbox, address: address)
|
||||
public func geocodeAddress(engine: TelegramEngine, address: DeviceContactAddressData) -> Signal<(Double, Double)?, NoError> {
|
||||
return cachedGeocode(engine: engine, address: address)
|
||||
|> mapToSignal { cached -> Signal<(Double, Double)?, NoError> in
|
||||
if let cached = cached {
|
||||
return .single((cached.latitude, cached.longitude))
|
||||
@ -67,7 +60,7 @@ public func geocodeAddress(postbox: Postbox, address: DeviceContactAddressData)
|
||||
return geocodeLocation(dictionary: address.dictionary)
|
||||
|> mapToSignal { coordinate in
|
||||
if let (latitude, longitude) = coordinate {
|
||||
return updateCachedGeocode(postbox: postbox, address: address, latitude: latitude, longitude: longitude)
|
||||
return updateCachedGeocode(engine: engine, address: address, latitude: latitude, longitude: longitude)
|
||||
|> map(Optional.init)
|
||||
} else {
|
||||
return .single(nil)
|
||||
|
@ -420,12 +420,12 @@ final class LocationPickerControllerNode: ViewControllerTracingNode, CLLocationM
|
||||
let home: Signal<(Double, Double)?, NoError>
|
||||
let work: Signal<(Double, Double)?, NoError>
|
||||
if let address = homeAddress {
|
||||
home = geocodeAddress(postbox: context.account.postbox, address: address)
|
||||
home = geocodeAddress(engine: context.engine, address: address)
|
||||
} else {
|
||||
home = .single(nil)
|
||||
}
|
||||
if let address = workAddress {
|
||||
work = geocodeAddress(postbox: context.account.postbox, address: address)
|
||||
work = geocodeAddress(engine: context.engine, address: address)
|
||||
} else {
|
||||
work = .single(nil)
|
||||
}
|
||||
|
@ -33,9 +33,8 @@ public func ==(lhs: CLLocationCoordinate2D, rhs: CLLocationCoordinate2D) -> Bool
|
||||
}
|
||||
|
||||
public func nearbyVenues(context: AccountContext, latitude: Double, longitude: Double, query: String? = nil) -> Signal<[TelegramMediaMap], NoError> {
|
||||
return context.account.postbox.transaction { transaction -> SearchBotsConfiguration in
|
||||
return currentSearchBotsConfiguration(transaction: transaction)
|
||||
} |> mapToSignal { searchBotsConfiguration in
|
||||
return context.engine.data.get(TelegramEngine.EngineData.Item.Configuration.SearchBots())
|
||||
|> mapToSignal { searchBotsConfiguration in
|
||||
return context.engine.peers.resolvePeerByName(name: searchBotsConfiguration.venueBotUsername ?? "foursquare")
|
||||
|> take(1)
|
||||
|> mapToSignal { peer -> Signal<ChatContextResultCollection?, NoError> in
|
||||
|
@ -29,35 +29,29 @@ public final class MediaPlaybackStoredState: Codable {
|
||||
}
|
||||
}
|
||||
|
||||
public func mediaPlaybackStoredState(postbox: Postbox, messageId: MessageId) -> Signal<MediaPlaybackStoredState?, NoError> {
|
||||
return postbox.transaction { transaction -> MediaPlaybackStoredState? in
|
||||
let key = ValueBoxKey(length: 20)
|
||||
key.setInt32(0, value: messageId.namespace)
|
||||
key.setInt32(4, value: messageId.peerId.namespace._internalGetInt32Value())
|
||||
key.setInt64(8, value: messageId.peerId.id._internalGetInt64Value())
|
||||
key.setInt32(16, value: messageId.id)
|
||||
if let entry = transaction.retrieveItemCacheEntry(id: ItemCacheEntryId(collectionId: ApplicationSpecificItemCacheCollectionId.mediaPlaybackStoredState, key: key))?.get(MediaPlaybackStoredState.self) {
|
||||
return entry
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
public func mediaPlaybackStoredState(engine: TelegramEngine, messageId: MessageId) -> Signal<MediaPlaybackStoredState?, NoError> {
|
||||
let key = ValueBoxKey(length: 20)
|
||||
key.setInt32(0, value: messageId.namespace)
|
||||
key.setInt32(4, value: messageId.peerId.namespace._internalGetInt32Value())
|
||||
key.setInt64(8, value: messageId.peerId.id._internalGetInt64Value())
|
||||
key.setInt32(16, value: messageId.id)
|
||||
|
||||
return engine.data.get(TelegramEngine.EngineData.Item.ItemCache.Item(collectionId: ApplicationSpecificItemCacheCollectionId.mediaPlaybackStoredState, id: key))
|
||||
|> map { entry -> MediaPlaybackStoredState? in
|
||||
return entry?.get(MediaPlaybackStoredState.self)
|
||||
}
|
||||
}
|
||||
|
||||
private let collectionSpec = ItemCacheCollectionSpec(lowWaterItemCount: 25, highWaterItemCount: 50)
|
||||
|
||||
public func updateMediaPlaybackStoredStateInteractively(postbox: Postbox, messageId: MessageId, state: MediaPlaybackStoredState?) -> Signal<Void, NoError> {
|
||||
return postbox.transaction { transaction -> Void in
|
||||
let key = ValueBoxKey(length: 20)
|
||||
key.setInt32(0, value: messageId.namespace)
|
||||
key.setInt32(4, value: messageId.peerId.namespace._internalGetInt32Value())
|
||||
key.setInt64(8, value: messageId.peerId.id._internalGetInt64Value())
|
||||
key.setInt32(16, value: messageId.id)
|
||||
let id = ItemCacheEntryId(collectionId: ApplicationSpecificItemCacheCollectionId.mediaPlaybackStoredState, key: key)
|
||||
if let state = state, let entry = CodableEntry(state) {
|
||||
transaction.putItemCacheEntry(id: id, entry: entry, collectionSpec: collectionSpec)
|
||||
} else {
|
||||
transaction.removeItemCacheEntry(id: id)
|
||||
}
|
||||
public func updateMediaPlaybackStoredStateInteractively(engine: TelegramEngine, messageId: MessageId, state: MediaPlaybackStoredState?) -> Signal<Never, NoError> {
|
||||
let key = ValueBoxKey(length: 20)
|
||||
key.setInt32(0, value: messageId.namespace)
|
||||
key.setInt32(4, value: messageId.peerId.namespace._internalGetInt32Value())
|
||||
key.setInt64(8, value: messageId.peerId.id._internalGetInt64Value())
|
||||
key.setInt32(16, value: messageId.id)
|
||||
|
||||
if let state = state {
|
||||
return engine.itemCache.put(collectionId: ApplicationSpecificItemCacheCollectionId.mediaPlaybackStoredState, id: key, item: state)
|
||||
} else {
|
||||
return engine.itemCache.remove(collectionId: ApplicationSpecificItemCacheCollectionId.mediaPlaybackStoredState, id: key)
|
||||
}
|
||||
}
|
||||
|
@ -387,11 +387,7 @@ private final class ContextControllerContentSourceImpl: ContextControllerContent
|
||||
}
|
||||
|
||||
private func peerNearbyContextMenuItems(context: AccountContext, peerId: EnginePeer.Id, present: @escaping (ViewController) -> Void) -> Signal<[ContextMenuItem], NoError> {
|
||||
return context.account.postbox.transaction { _ -> [ContextMenuItem] in
|
||||
let items: [ContextMenuItem] = []
|
||||
|
||||
return items
|
||||
}
|
||||
return .single([])
|
||||
}
|
||||
|
||||
private class PeersNearbyControllerImpl: ItemListController {
|
||||
|
@ -2,16 +2,6 @@ import Foundation
|
||||
|
||||
public typealias ItemCacheCollectionId = Int8
|
||||
|
||||
public struct ItemCacheCollectionSpec {
|
||||
public let lowWaterItemCount: Int32
|
||||
public let highWaterItemCount: Int32
|
||||
|
||||
public init(lowWaterItemCount: Int32, highWaterItemCount: Int32) {
|
||||
self.lowWaterItemCount = lowWaterItemCount
|
||||
self.highWaterItemCount = highWaterItemCount
|
||||
}
|
||||
}
|
||||
|
||||
struct ItemCacheCollectionState: PostboxCoding {
|
||||
let nextAccessIndex: Int32
|
||||
|
||||
|
@ -740,9 +740,9 @@ public final class Transaction {
|
||||
return self.postbox?.storedMessageId(peerId: peerId, namespace: namespace, timestamp: timestamp)
|
||||
}
|
||||
|
||||
public func putItemCacheEntry(id: ItemCacheEntryId, entry: CodableEntry, collectionSpec: ItemCacheCollectionSpec) {
|
||||
public func putItemCacheEntry(id: ItemCacheEntryId, entry: CodableEntry) {
|
||||
assert(!self.disposed)
|
||||
self.postbox?.putItemCacheEntry(id: id, entry: entry, collectionSpec: collectionSpec)
|
||||
self.postbox?.putItemCacheEntry(id: id, entry: entry)
|
||||
}
|
||||
|
||||
public func removeItemCacheEntry(id: ItemCacheEntryId) {
|
||||
@ -2351,7 +2351,7 @@ final class PostboxImpl {
|
||||
}
|
||||
}
|
||||
|
||||
fileprivate func putItemCacheEntry(id: ItemCacheEntryId, entry: CodableEntry, collectionSpec: ItemCacheCollectionSpec) {
|
||||
fileprivate func putItemCacheEntry(id: ItemCacheEntryId, entry: CodableEntry) {
|
||||
self.itemCacheTable.put(id: id, entry: entry, metaTable: self.itemCacheMetaTable)
|
||||
self.currentUpdatedCacheEntryKeys.insert(id)
|
||||
}
|
||||
|
@ -675,9 +675,7 @@ public func notificationsAndSoundsController(context: AccountContext, exceptions
|
||||
ActionSheetButtonItem(title: presentationData.strings.Notifications_Reset, color: .destructive, action: { [weak actionSheet] in
|
||||
actionSheet?.dismissAnimated()
|
||||
|
||||
let modifyPeers = context.account.postbox.transaction { transaction -> Void in
|
||||
transaction.resetAllPeerNotificationSettings(TelegramPeerNotificationSettings.defaultSettings)
|
||||
}
|
||||
let modifyPeers = context.engine.peers.resetAllPeerNotificationSettings()
|
||||
let updateGlobal = updateGlobalNotificationSettingsInteractively(postbox: context.account.postbox, { _ in
|
||||
return GlobalNotificationSettingsSet.defaultSettings
|
||||
})
|
||||
|
@ -222,9 +222,7 @@ public func selectivePrivacyPeersController(context: AccountContext, title: Stri
|
||||
actionsDisposable.add(removePeerDisposable)
|
||||
|
||||
let peersPromise = Promise<[SelectivePrivacyPeer]>()
|
||||
peersPromise.set(context.account.postbox.transaction { transaction -> [SelectivePrivacyPeer] in
|
||||
return Array(initialPeers.values)
|
||||
})
|
||||
peersPromise.set(.single(Array(initialPeers.values)))
|
||||
|
||||
let arguments = SelectivePrivacyPeersControllerArguments(context: context, setPeerIdWithRevealedOptions: { peerId, fromPeerId in
|
||||
updateState { state in
|
||||
|
@ -365,10 +365,10 @@ public final class SettingsSearchContainerNode: SearchDisplayControllerContentNo
|
||||
self.addSubnode(self.listNode)
|
||||
|
||||
let interaction = SettingsSearchInteraction(openItem: { result in
|
||||
addRecentSettingsSearchItem(postbox: context.account.postbox, item: result.id)
|
||||
addRecentSettingsSearchItem(engine: context.engine, item: result.id)
|
||||
openResult(result)
|
||||
}, deleteRecentItem: { id in
|
||||
removeRecentSettingsSearchItem(postbox: context.account.postbox, item: id)
|
||||
removeRecentSettingsSearchItem(engine: context.engine, item: id)
|
||||
})
|
||||
|
||||
let searchableItems = Promise<[SettingsSearchableItem]>()
|
||||
@ -449,7 +449,7 @@ public final class SettingsSearchContainerNode: SearchDisplayControllerContentNo
|
||||
|> deliverOnMainQueue).start(next: { [weak self] recentSearchItems, faqItems, presentationData in
|
||||
if let strongSelf = self {
|
||||
let recentHeader = ChatListSearchItemHeader(type: .recentPeers, theme: presentationData.theme, strings: presentationData.strings, actionTitle: presentationData.strings.WebSearch_RecentSectionClear, action: {
|
||||
clearRecentSettingsSearchItems(postbox: context.account.postbox)
|
||||
clearRecentSettingsSearchItems(engine: context.engine)
|
||||
})
|
||||
let faqHeader = ChatListSearchItemHeader(type: .faq, theme: presentationData.theme, strings: presentationData.strings)
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
import Foundation
|
||||
import UIKit
|
||||
import Postbox
|
||||
import TelegramCore
|
||||
import SwiftSignalKit
|
||||
import TelegramUIPreferences
|
||||
|
||||
@ -37,42 +38,32 @@ public final class RecentSettingsSearchQueryItem: Codable {
|
||||
}
|
||||
}
|
||||
|
||||
func addRecentSettingsSearchItem(postbox: Postbox, item: SettingsSearchableItemId) {
|
||||
let _ = (postbox.transaction { transaction in
|
||||
let itemId = SettingsSearchRecentQueryItemId(item.index)
|
||||
if let entry = CodableEntry(RecentSettingsSearchQueryItem()) {
|
||||
transaction.addOrMoveToFirstPositionOrderedItemListItem(collectionId: ApplicationSpecificOrderedItemListCollectionId.settingsSearchRecentItems, item: OrderedItemListEntry(id: itemId.rawValue, contents: entry), removeTailIfCountExceeds: 100)
|
||||
}
|
||||
}).start()
|
||||
func addRecentSettingsSearchItem(engine: TelegramEngine, item: SettingsSearchableItemId) {
|
||||
let itemId = SettingsSearchRecentQueryItemId(item.index)
|
||||
let _ = engine.orderedLists.addOrMoveToFirstPosition(collectionId: ApplicationSpecificOrderedItemListCollectionId.settingsSearchRecentItems, id: itemId.rawValue, item: RecentSettingsSearchQueryItem(), removeTailIfCountExceeds: 100).start()
|
||||
}
|
||||
|
||||
func removeRecentSettingsSearchItem(postbox: Postbox, item: SettingsSearchableItemId) {
|
||||
let _ = (postbox.transaction { transaction -> Void in
|
||||
let itemId = SettingsSearchRecentQueryItemId(item.index)
|
||||
transaction.removeOrderedItemListItem(collectionId: ApplicationSpecificOrderedItemListCollectionId.settingsSearchRecentItems, itemId: itemId.rawValue)
|
||||
}).start()
|
||||
func removeRecentSettingsSearchItem(engine: TelegramEngine, item: SettingsSearchableItemId) {
|
||||
let itemId = SettingsSearchRecentQueryItemId(item.index)
|
||||
let _ = engine.orderedLists.removeItem(collectionId: ApplicationSpecificOrderedItemListCollectionId.settingsSearchRecentItems, id: itemId.rawValue).start()
|
||||
}
|
||||
|
||||
func clearRecentSettingsSearchItems(postbox: Postbox) {
|
||||
let _ = (postbox.transaction { transaction -> Void in
|
||||
transaction.replaceOrderedItemListItems(collectionId: ApplicationSpecificOrderedItemListCollectionId.settingsSearchRecentItems, items: [])
|
||||
}).start()
|
||||
func clearRecentSettingsSearchItems(engine: TelegramEngine) {
|
||||
let _ = engine.orderedLists.clear(collectionId: ApplicationSpecificOrderedItemListCollectionId.settingsSearchRecentItems).start()
|
||||
}
|
||||
|
||||
func settingsSearchRecentItems(postbox: Postbox) -> Signal<[SettingsSearchableItemId], NoError> {
|
||||
return postbox.combinedView(keys: [.orderedItemList(id: ApplicationSpecificOrderedItemListCollectionId.settingsSearchRecentItems)])
|
||||
|> mapToSignal { view -> Signal<[SettingsSearchableItemId], NoError> in
|
||||
return postbox.transaction { transaction -> [SettingsSearchableItemId] in
|
||||
var result: [SettingsSearchableItemId] = []
|
||||
if let view = view.views[.orderedItemList(id: ApplicationSpecificOrderedItemListCollectionId.settingsSearchRecentItems)] as? OrderedItemListView {
|
||||
for item in view.items {
|
||||
let index = SettingsSearchRecentQueryItemId(item.id).value
|
||||
if let itemId = SettingsSearchableItemId(index: index) {
|
||||
result.append(itemId)
|
||||
}
|
||||
|> map { view -> [SettingsSearchableItemId] in
|
||||
var result: [SettingsSearchableItemId] = []
|
||||
if let view = view.views[.orderedItemList(id: ApplicationSpecificOrderedItemListCollectionId.settingsSearchRecentItems)] as? OrderedItemListView {
|
||||
for item in view.items {
|
||||
let index = SettingsSearchRecentQueryItemId(item.id).value
|
||||
if let itemId = SettingsSearchableItemId(index: index) {
|
||||
result.append(itemId)
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
@ -599,7 +599,7 @@ public func editThemeController(context: AccountContext, mode: EditThemeControll
|
||||
let resolvedWallpaper: TelegramWallpaper?
|
||||
if let theme = theme, case let .file(file) = theme.chat.defaultWallpaper, file.id != 0 {
|
||||
resolvedWallpaper = theme.chat.defaultWallpaper
|
||||
updateCachedWallpaper(account: context.account, wallpaper: theme.chat.defaultWallpaper)
|
||||
updateCachedWallpaper(engine: context.engine, wallpaper: theme.chat.defaultWallpaper)
|
||||
} else {
|
||||
resolvedWallpaper = nil
|
||||
}
|
||||
|
@ -433,7 +433,7 @@ final class ThemeGridSearchContentNode: SearchDisplayControllerContentNode {
|
||||
|
||||
let query = strongSelf.queryValue.query
|
||||
if !query.isEmpty {
|
||||
let _ = addRecentWallpaperSearchQuery(postbox: strongSelf.context.account.postbox, string: query).start()
|
||||
let _ = addRecentWallpaperSearchQuery(engine: strongSelf.context.engine, string: query).start()
|
||||
}
|
||||
}
|
||||
}, selectColor: { [weak self] color in
|
||||
@ -444,12 +444,10 @@ final class ThemeGridSearchContentNode: SearchDisplayControllerContentNode {
|
||||
return query
|
||||
}, updateInterface: true)
|
||||
}, deleteRecentQuery: { query in
|
||||
let _ = removeRecentWallpaperSearchQuery(postbox: context.account.postbox, string: query).start()
|
||||
let _ = removeRecentWallpaperSearchQuery(engine: context.engine, string: query).start()
|
||||
})
|
||||
|
||||
let configuration = self.context.account.postbox.transaction { transaction -> SearchBotsConfiguration in
|
||||
return currentSearchBotsConfiguration(transaction: transaction)
|
||||
}
|
||||
let configuration = self.context.engine.data.get(TelegramEngine.EngineData.Item.Configuration.SearchBots())
|
||||
|
||||
let foundItems = self.queryPromise.get()
|
||||
|> mapToSignal { query -> Signal<([ThemeGridSearchEntry], Bool)?, NoError> in
|
||||
@ -582,7 +580,7 @@ final class ThemeGridSearchContentNode: SearchDisplayControllerContentNode {
|
||||
}
|
||||
|
||||
let header = ChatListSearchItemHeader(type: .recentPeers, theme: presentationData.theme, strings: presentationData.strings, actionTitle: presentationData.strings.WebSearch_RecentSectionClear, action: {
|
||||
_ = clearRecentWallpaperSearchQueries(postbox: strongSelf.context.account.postbox).start()
|
||||
let _ = clearRecentWallpaperSearchQueries(engine: strongSelf.context.engine).start()
|
||||
})
|
||||
|
||||
let previousEntries = previousRecentItems.swap(entries)
|
||||
|
@ -1,5 +1,6 @@
|
||||
import Foundation
|
||||
import Postbox
|
||||
import TelegramCore
|
||||
import SwiftSignalKit
|
||||
import TelegramUIPreferences
|
||||
|
||||
@ -34,42 +35,36 @@ public final class RecentWallpaperSearchQueryItem: Codable {
|
||||
}
|
||||
}
|
||||
|
||||
func addRecentWallpaperSearchQuery(postbox: Postbox, string: String) -> Signal<Void, NoError> {
|
||||
return postbox.transaction { transaction in
|
||||
if let itemId = WallpaperSearchRecentQueryItemId(string) {
|
||||
if let entry = CodableEntry(RecentWallpaperSearchQueryItem()) {
|
||||
transaction.addOrMoveToFirstPositionOrderedItemListItem(collectionId: ApplicationSpecificOrderedItemListCollectionId.wallpaperSearchRecentQueries, item: OrderedItemListEntry(id: itemId.rawValue, contents: entry), removeTailIfCountExceeds: 100)
|
||||
}
|
||||
}
|
||||
func addRecentWallpaperSearchQuery(engine: TelegramEngine, string: String) -> Signal<Never, NoError> {
|
||||
if let itemId = WallpaperSearchRecentQueryItemId(string) {
|
||||
return engine.orderedLists.addOrMoveToFirstPosition(collectionId: ApplicationSpecificOrderedItemListCollectionId.wallpaperSearchRecentQueries, id: itemId.rawValue, item: RecentWallpaperSearchQueryItem(), removeTailIfCountExceeds: 100)
|
||||
} else {
|
||||
return .complete()
|
||||
}
|
||||
}
|
||||
|
||||
func removeRecentWallpaperSearchQuery(postbox: Postbox, string: String) -> Signal<Void, NoError> {
|
||||
return postbox.transaction { transaction -> Void in
|
||||
if let itemId = WallpaperSearchRecentQueryItemId(string) {
|
||||
transaction.removeOrderedItemListItem(collectionId: ApplicationSpecificOrderedItemListCollectionId.wallpaperSearchRecentQueries, itemId: itemId.rawValue)
|
||||
}
|
||||
func removeRecentWallpaperSearchQuery(engine: TelegramEngine, string: String) -> Signal<Never, NoError> {
|
||||
if let itemId = WallpaperSearchRecentQueryItemId(string) {
|
||||
return engine.orderedLists.removeItem(collectionId: ApplicationSpecificOrderedItemListCollectionId.wallpaperSearchRecentQueries, id: itemId.rawValue)
|
||||
} else {
|
||||
return .complete()
|
||||
}
|
||||
}
|
||||
|
||||
func clearRecentWallpaperSearchQueries(postbox: Postbox) -> Signal<Void, NoError> {
|
||||
return postbox.transaction { transaction -> Void in
|
||||
transaction.replaceOrderedItemListItems(collectionId: ApplicationSpecificOrderedItemListCollectionId.wallpaperSearchRecentQueries, items: [])
|
||||
}
|
||||
func clearRecentWallpaperSearchQueries(engine: TelegramEngine) -> Signal<Never, NoError> {
|
||||
return engine.orderedLists.clear(collectionId: ApplicationSpecificOrderedItemListCollectionId.wallpaperSearchRecentQueries)
|
||||
}
|
||||
|
||||
func wallpaperSearchRecentQueries(postbox: Postbox) -> Signal<[String], NoError> {
|
||||
return postbox.combinedView(keys: [.orderedItemList(id: ApplicationSpecificOrderedItemListCollectionId.wallpaperSearchRecentQueries)])
|
||||
|> mapToSignal { view -> Signal<[String], NoError> in
|
||||
return postbox.transaction { transaction -> [String] in
|
||||
var result: [String] = []
|
||||
if let view = view.views[.orderedItemList(id: ApplicationSpecificOrderedItemListCollectionId.wallpaperSearchRecentQueries)] as? OrderedItemListView {
|
||||
for item in view.items {
|
||||
let value = WallpaperSearchRecentQueryItemId(item.id).value
|
||||
result.append(value)
|
||||
}
|
||||
}
|
||||
return result
|
||||
|> map { view -> [String] in
|
||||
var result: [String] = []
|
||||
if let view = view.views[.orderedItemList(id: ApplicationSpecificOrderedItemListCollectionId.wallpaperSearchRecentQueries)] as? OrderedItemListView {
|
||||
for item in view.items {
|
||||
let value = WallpaperSearchRecentQueryItemId(item.id).value
|
||||
result.append(value)
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
@ -673,24 +673,19 @@ public final class ShareController: ViewController {
|
||||
for (id, status, error) in statuses {
|
||||
if let error = error {
|
||||
Queue.mainQueue().async {
|
||||
let _ = (account.postbox.transaction { transaction -> Peer? in
|
||||
TelegramEngine(account: account).messages.deleteMessages(transaction: transaction, ids: [id])
|
||||
return transaction.getPeer(id.peerId)
|
||||
}
|
||||
let _ = TelegramEngine(account: account).messages.deleteMessagesInteractively(messageIds: [id], type: .forEveryone).start()
|
||||
let _ = (TelegramEngine(account: account).data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: id.peerId))
|
||||
|> deliverOnMainQueue).start(next: { peer in
|
||||
guard let strongSelf = self, let peer = peer else {
|
||||
return
|
||||
}
|
||||
if !displayedError, case .slowmodeActive = error {
|
||||
displayedError = true
|
||||
strongSelf.present(standardTextAlertController(theme: AlertControllerTheme(presentationData: strongSelf.presentationData), title: EnginePeer(peer).displayTitle(strings: strongSelf.presentationData.strings, displayOrder: strongSelf.presentationData.nameDisplayOrder), text: strongSelf.presentationData.strings.Chat_SlowmodeSendError, actions: [TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.Common_OK, action: {})]), in: .window(.root))
|
||||
strongSelf.present(standardTextAlertController(theme: AlertControllerTheme(presentationData: strongSelf.presentationData), title: peer.displayTitle(strings: strongSelf.presentationData.strings, displayOrder: strongSelf.presentationData.nameDisplayOrder), text: strongSelf.presentationData.strings.Chat_SlowmodeSendError, actions: [TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.Common_OK, action: {})]), in: .window(.root))
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
let _ = account.postbox.transaction({ transaction in
|
||||
|
||||
}).start()
|
||||
if status != nil {
|
||||
hasStatuses = true
|
||||
}
|
||||
|
@ -211,7 +211,6 @@ public final class PresentationCallImpl: PresentationCall {
|
||||
|
||||
private let serializedData: String?
|
||||
private let dataSaving: VoiceCallDataSaving
|
||||
private let derivedState: VoipDerivedState
|
||||
private let proxyServer: ProxyServerSettings?
|
||||
private let auxiliaryServers: [OngoingCallContext.AuxiliaryServer]
|
||||
private let currentNetworkType: NetworkType
|
||||
@ -307,7 +306,6 @@ public final class PresentationCallImpl: PresentationCall {
|
||||
callKitIntegration: CallKitIntegration?,
|
||||
serializedData: String?,
|
||||
dataSaving: VoiceCallDataSaving,
|
||||
derivedState: VoipDerivedState,
|
||||
getDeviceAccessData: @escaping () -> (presentationData: PresentationData, present: (ViewController, Any?) -> Void, openSettings: () -> Void),
|
||||
initialState: CallSession?,
|
||||
internalId: CallSessionInternalId,
|
||||
@ -363,7 +361,6 @@ public final class PresentationCallImpl: PresentationCall {
|
||||
|
||||
self.serializedData = serializedData
|
||||
self.dataSaving = dataSaving
|
||||
self.derivedState = derivedState
|
||||
self.proxyServer = proxyServer
|
||||
self.currentNetworkType = currentNetworkType
|
||||
self.updatedNetworkType = updatedNetworkType
|
||||
@ -692,7 +689,7 @@ public final class PresentationCallImpl: PresentationCall {
|
||||
|
||||
let updatedConnections = connections
|
||||
|
||||
let ongoingContext = OngoingCallContext(account: self.context.account, callSessionManager: self.callSessionManager, callId: id, internalId: self.internalId, proxyServer: proxyServer, initialNetworkType: self.currentNetworkType, updatedNetworkType: self.updatedNetworkType, serializedData: self.serializedData, dataSaving: dataSaving, derivedState: self.derivedState, key: key, isOutgoing: sessionState.isOutgoing, video: self.videoCapturer, connections: updatedConnections, maxLayer: maxLayer, version: version, allowP2P: allowsP2P, enableTCP: self.enableTCP, enableStunMarking: self.enableStunMarking, audioSessionActive: self.audioSessionActive.get(), logName: logName, preferredVideoCodec: self.preferredVideoCodec)
|
||||
let ongoingContext = OngoingCallContext(account: self.context.account, callSessionManager: self.callSessionManager, callId: id, internalId: self.internalId, proxyServer: proxyServer, initialNetworkType: self.currentNetworkType, updatedNetworkType: self.updatedNetworkType, serializedData: self.serializedData, dataSaving: dataSaving, key: key, isOutgoing: sessionState.isOutgoing, video: self.videoCapturer, connections: updatedConnections, maxLayer: maxLayer, version: version, allowP2P: allowsP2P, enableTCP: self.enableTCP, enableStunMarking: self.enableStunMarking, audioSessionActive: self.audioSessionActive.get(), logName: logName, preferredVideoCodec: self.preferredVideoCodec)
|
||||
self.ongoingContext = ongoingContext
|
||||
ongoingContext.setIsMuted(self.isMutedValue)
|
||||
if let requestedVideoAspect = self.requestedVideoAspect {
|
||||
|
@ -287,14 +287,13 @@ public final class PresentationCallManagerImpl: PresentationCallManager {
|
||||
private func ringingStatesUpdated(_ ringingStates: [(AccountContext, Peer, CallSessionRingingState, Bool, NetworkType)], enableCallKit: Bool) {
|
||||
if let firstState = ringingStates.first {
|
||||
if self.currentCall == nil && self.currentGroupCall == nil {
|
||||
self.currentCallDisposable.set((combineLatest(firstState.0.account.postbox.preferencesView(keys: [PreferencesKeys.voipConfiguration, ApplicationSpecificPreferencesKeys.voipDerivedState, PreferencesKeys.appConfiguration]) |> take(1), accountManager.sharedData(keys: [SharedDataKeys.autodownloadSettings, ApplicationSpecificSharedDataKeys.experimentalUISettings]) |> take(1))
|
||||
self.currentCallDisposable.set((combineLatest(firstState.0.account.postbox.preferencesView(keys: [PreferencesKeys.voipConfiguration, PreferencesKeys.appConfiguration]) |> take(1), accountManager.sharedData(keys: [SharedDataKeys.autodownloadSettings, ApplicationSpecificSharedDataKeys.experimentalUISettings]) |> take(1))
|
||||
|> deliverOnMainQueue).start(next: { [weak self] preferences, sharedData in
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
|
||||
let configuration = preferences.values[PreferencesKeys.voipConfiguration]?.get(VoipConfiguration.self) ?? .defaultValue
|
||||
let derivedState = preferences.values[ApplicationSpecificPreferencesKeys.voipDerivedState]?.get(VoipDerivedState.self) ?? .default
|
||||
let autodownloadSettings = sharedData.entries[SharedDataKeys.autodownloadSettings]?.get(AutodownloadSettings.self) ?? .defaultSettings
|
||||
let experimentalSettings = sharedData.entries[ApplicationSpecificSharedDataKeys.experimentalUISettings]?.get(ExperimentalUISettings.self) ?? .defaultSettings
|
||||
let appConfiguration = preferences.values[PreferencesKeys.appConfiguration]?.get(AppConfiguration.self) ?? AppConfiguration.defaultValue
|
||||
@ -306,7 +305,6 @@ public final class PresentationCallManagerImpl: PresentationCallManager {
|
||||
callKitIntegration: enableCallKit ? callKitIntegrationIfEnabled(strongSelf.callKitIntegration, settings: strongSelf.callSettings) : nil,
|
||||
serializedData: configuration.serializedData,
|
||||
dataSaving: effectiveDataSaving(for: strongSelf.callSettings, autodownloadSettings: autodownloadSettings),
|
||||
derivedState: derivedState,
|
||||
getDeviceAccessData: strongSelf.getDeviceAccessData,
|
||||
initialState: nil,
|
||||
internalId: firstState.2.id,
|
||||
@ -508,7 +506,7 @@ public final class PresentationCallManagerImpl: PresentationCallManager {
|
||||
|
||||
return (combineLatest(queue: .mainQueue(), request, networkType |> take(1), context.account.postbox.peerView(id: peerId) |> map { peerView -> Bool in
|
||||
return peerView.peerIsContact
|
||||
} |> take(1), context.account.postbox.preferencesView(keys: [PreferencesKeys.voipConfiguration, ApplicationSpecificPreferencesKeys.voipDerivedState, PreferencesKeys.appConfiguration]) |> take(1), accountManager.sharedData(keys: [SharedDataKeys.autodownloadSettings, ApplicationSpecificSharedDataKeys.experimentalUISettings]) |> take(1), areVideoCallsAvailable)
|
||||
} |> take(1), context.account.postbox.preferencesView(keys: [PreferencesKeys.voipConfiguration, PreferencesKeys.appConfiguration]) |> take(1), accountManager.sharedData(keys: [SharedDataKeys.autodownloadSettings, ApplicationSpecificSharedDataKeys.experimentalUISettings]) |> take(1), areVideoCallsAvailable)
|
||||
|> deliverOnMainQueue
|
||||
|> beforeNext { internalId, currentNetworkType, isContact, preferences, sharedData, areVideoCallsAvailable in
|
||||
if let strongSelf = self, accessEnabled {
|
||||
@ -517,7 +515,6 @@ public final class PresentationCallManagerImpl: PresentationCallManager {
|
||||
}
|
||||
|
||||
let configuration = preferences.values[PreferencesKeys.voipConfiguration]?.get(VoipConfiguration.self) ?? .defaultValue
|
||||
let derivedState = preferences.values[ApplicationSpecificPreferencesKeys.voipDerivedState]?.get(VoipDerivedState.self) ?? .default
|
||||
let autodownloadSettings = sharedData.entries[SharedDataKeys.autodownloadSettings]?.get(AutodownloadSettings.self) ?? .defaultSettings
|
||||
let appConfiguration = preferences.values[PreferencesKeys.appConfiguration]?.get(AppConfiguration.self) ?? AppConfiguration.defaultValue
|
||||
|
||||
@ -535,7 +532,6 @@ public final class PresentationCallManagerImpl: PresentationCallManager {
|
||||
),
|
||||
serializedData: configuration.serializedData,
|
||||
dataSaving: effectiveDataSaving(for: strongSelf.callSettings, autodownloadSettings: autodownloadSettings),
|
||||
derivedState: derivedState,
|
||||
getDeviceAccessData: strongSelf.getDeviceAccessData,
|
||||
initialState: nil,
|
||||
internalId: internalId,
|
||||
|
@ -1708,17 +1708,19 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
|
||||
|> distinctUntilChanged
|
||||
|> runOn(.mainQueue())
|
||||
} else {
|
||||
peerAdminIds = strongSelf.account.postbox.transaction { transaction -> [PeerId] in
|
||||
var result: [PeerId] = []
|
||||
if let cachedData = transaction.getPeerCachedData(peerId: peerId) as? CachedGroupData {
|
||||
if let participants = cachedData.participants {
|
||||
for participant in participants.participants {
|
||||
if case .creator = participant {
|
||||
result.append(participant.peerId)
|
||||
} else if case .admin = participant {
|
||||
result.append(participant.peerId)
|
||||
}
|
||||
}
|
||||
peerAdminIds = strongSelf.accountContext.engine.data.get(
|
||||
TelegramEngine.EngineData.Item.Peer.LegacyGroupParticipants(id: peerId)
|
||||
)
|
||||
|> map { participants -> [EnginePeer.Id] in
|
||||
guard case let .known(participants) = participants else {
|
||||
return []
|
||||
}
|
||||
var result: [EnginePeer.Id] = []
|
||||
for participant in participants {
|
||||
if case .creator = participant {
|
||||
result.append(participant.peerId)
|
||||
} else if case .admin = participant {
|
||||
result.append(participant.peerId)
|
||||
}
|
||||
}
|
||||
return result
|
||||
@ -1801,17 +1803,6 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
|
||||
} else if case .invalidJoinAsPeer = error {
|
||||
let peerId = strongSelf.peerId
|
||||
let _ = strongSelf.accountContext.engine.calls.clearCachedGroupCallDisplayAsAvailablePeers(peerId: peerId).start()
|
||||
let _ = (strongSelf.accountContext.account.postbox.transaction { transaction -> Void in
|
||||
transaction.updatePeerCachedData(peerIds: Set([peerId]), update: { _, current in
|
||||
if let current = current as? CachedChannelData {
|
||||
return current.withUpdatedCallJoinPeerId(nil)
|
||||
} else if let current = current as? CachedGroupData {
|
||||
return current.withUpdatedCallJoinPeerId(nil)
|
||||
} else {
|
||||
return current
|
||||
}
|
||||
})
|
||||
}).start()
|
||||
}
|
||||
strongSelf.markAsCanBeRemoved()
|
||||
}))
|
||||
|
@ -13,7 +13,7 @@ public struct ContentSettings: Equatable {
|
||||
}
|
||||
}
|
||||
|
||||
private extension ContentSettings {
|
||||
extension ContentSettings {
|
||||
init(appConfiguration: AppConfiguration) {
|
||||
var reasons: [String] = []
|
||||
if let data = appConfiguration.data, let reasonsData = data["ignore_restriction_reasons"] as? [String] {
|
||||
|
@ -39,7 +39,8 @@ extension PeerStatusSettings {
|
||||
|
||||
public func unarchiveAutomaticallyArchivedPeer(account: Account, peerId: PeerId) {
|
||||
let _ = (account.postbox.transaction { transaction -> Void in
|
||||
updatePeerGroupIdInteractively(transaction: transaction, peerId: peerId, groupId: .root)
|
||||
_internal_updatePeerGroupIdInteractively(transaction: transaction, peerId: peerId, groupId: .root)
|
||||
|
||||
transaction.updatePeerCachedData(peerIds: Set([peerId]), update: { _, current in
|
||||
if let currentData = current as? CachedUserData, let currentStatusSettings = currentData.peerStatusSettings {
|
||||
var statusSettings = currentStatusSettings
|
||||
|
@ -258,7 +258,7 @@ func _internal_setCachedAvailableReactions(transaction: Transaction, availableRe
|
||||
key.setInt64(0, value: 0)
|
||||
|
||||
if let entry = CodableEntry(availableReactions) {
|
||||
transaction.putItemCacheEntry(id: ItemCacheEntryId(collectionId: Namespaces.CachedItemCollection.availableReactions, key: key), entry: entry, collectionSpec: ItemCacheCollectionSpec(lowWaterItemCount: 10, highWaterItemCount: 10))
|
||||
transaction.putItemCacheEntry(id: ItemCacheEntryId(collectionId: Namespaces.CachedItemCollection.availableReactions, key: key), entry: entry)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2,9 +2,6 @@ import Foundation
|
||||
import Postbox
|
||||
import SwiftSignalKit
|
||||
|
||||
|
||||
private let cachedSentMediaCollectionSpec = ItemCacheCollectionSpec(lowWaterItemCount: 10000, highWaterItemCount: 20000)
|
||||
|
||||
enum CachedSentMediaReferenceKey {
|
||||
case image(hash: Data)
|
||||
case file(hash: Data)
|
||||
@ -39,5 +36,5 @@ func cachedSentMediaReference(postbox: Postbox, key: CachedSentMediaReferenceKey
|
||||
}
|
||||
|
||||
func storeCachedSentMediaReference(transaction: Transaction, key: CachedSentMediaReferenceKey, media: Media) {
|
||||
//transaction.putItemCacheEntry(id: ItemCacheEntryId(collectionId: Namespaces.CachedItemCollection.cachedSentMediaReferences, key: key.key), entry: media, collectionSpec: cachedSentMediaCollectionSpec)
|
||||
//transaction.putItemCacheEntry(id: ItemCacheEntryId(collectionId: Namespaces.CachedItemCollection.cachedSentMediaReferences, key: key.key), entry: media)
|
||||
}
|
||||
|
@ -2,14 +2,7 @@ import Foundation
|
||||
import Postbox
|
||||
import SwiftSignalKit
|
||||
|
||||
|
||||
public func updatePeerGroupIdInteractively(postbox: Postbox, peerId: PeerId, groupId: PeerGroupId) -> Signal<Void, NoError> {
|
||||
return postbox.transaction { transaction -> Void in
|
||||
updatePeerGroupIdInteractively(transaction: transaction, peerId: peerId, groupId: groupId)
|
||||
}
|
||||
}
|
||||
|
||||
public func updatePeerGroupIdInteractively(transaction: Transaction, peerId: PeerId, groupId: PeerGroupId) {
|
||||
func _internal_updatePeerGroupIdInteractively(transaction: Transaction, peerId: PeerId, groupId: PeerGroupId) {
|
||||
let initialInclusion = transaction.getPeerChatListInclusion(peerId)
|
||||
var updatedInclusion = initialInclusion
|
||||
switch initialInclusion {
|
||||
|
@ -40,7 +40,7 @@ func addRecentlyUsedSticker(transaction: Transaction, fileReference: FileMediaRe
|
||||
}
|
||||
}
|
||||
|
||||
public func clearRecentlyUsedStickers(transaction: Transaction) {
|
||||
func _internal_clearRecentlyUsedStickers(transaction: Transaction) {
|
||||
transaction.replaceOrderedItemListItems(collectionId: Namespaces.OrderedItemList.CloudRecentStickers, items: [])
|
||||
addSynchronizeRecentlyUsedMediaOperation(transaction: transaction, category: .stickers, operation: .clear)
|
||||
}
|
||||
|
@ -23,7 +23,7 @@ func addSynchronizeSavedGifsOperation(transaction: Transaction, operation: Synch
|
||||
transaction.operationLogAddEntry(peerId: peerId, tag: tag, tagLocalIndex: .automatic, tagMergedIndex: .automatic, contents: SynchronizeSavedGifsOperation(content: .sync))
|
||||
}
|
||||
|
||||
public func isGifSaved(transaction: Transaction, mediaId: MediaId) -> Bool {
|
||||
public func getIsGifSaved(transaction: Transaction, mediaId: MediaId) -> Bool {
|
||||
if transaction.getOrderedItemListItem(collectionId: Namespaces.OrderedItemList.CloudRecentGifs, itemId: RecentMediaItemId(mediaId).rawValue) != nil {
|
||||
return true
|
||||
}
|
||||
|
@ -353,7 +353,7 @@ func _internal_cacheTwoStepPasswordToken(postbox: Postbox, token: TemporaryTwoSt
|
||||
let key = ValueBoxKey(length: 1)
|
||||
key.setUInt8(0, value: 0)
|
||||
if let token = token.flatMap(CodableEntry.init) {
|
||||
transaction.putItemCacheEntry(id: ItemCacheEntryId(collectionId: Namespaces.CachedItemCollection.cachedTwoStepToken, key: key), entry: token, collectionSpec: ItemCacheCollectionSpec(lowWaterItemCount: 1, highWaterItemCount: 1))
|
||||
transaction.putItemCacheEntry(id: ItemCacheEntryId(collectionId: Namespaces.CachedItemCollection.cachedTwoStepToken, key: key), entry: token)
|
||||
} else {
|
||||
transaction.removeItemCacheEntry(id: ItemCacheEntryId(collectionId: Namespaces.CachedItemCollection.cachedTwoStepToken, key: key))
|
||||
}
|
||||
|
@ -480,6 +480,18 @@ func _internal_joinGroupCall(account: Account, peerId: PeerId, joinAs: PeerId?,
|
||||
} else if error.errorDescription == "GROUPCALL_PARTICIPANTS_TOO_MUCH" {
|
||||
return .fail(.tooManyParticipants)
|
||||
} else if error.errorDescription == "JOIN_AS_PEER_INVALID" {
|
||||
let _ = (account.postbox.transaction { transaction -> Void in
|
||||
transaction.updatePeerCachedData(peerIds: Set([peerId]), update: { _, current in
|
||||
if let current = current as? CachedChannelData {
|
||||
return current.withUpdatedCallJoinPeerId(nil)
|
||||
} else if let current = current as? CachedGroupData {
|
||||
return current.withUpdatedCallJoinPeerId(nil)
|
||||
} else {
|
||||
return current
|
||||
}
|
||||
})
|
||||
}).start()
|
||||
|
||||
return .fail(.invalidJoinAsPeer)
|
||||
} else if error.errorDescription == "GROUPCALL_INVALID" {
|
||||
return account.postbox.transaction { transaction -> Signal<Api.Updates, JoinGroupCallError> in
|
||||
@ -2381,7 +2393,7 @@ func _internal_cachedGroupCallDisplayAsAvailablePeers(account: Account, peerId:
|
||||
return account.postbox.transaction { transaction -> [FoundPeer] in
|
||||
let currentTimestamp = Int32(CFAbsoluteTimeGetCurrent() + kCFAbsoluteTimeIntervalSince1970)
|
||||
if let entry = CodableEntry(CachedDisplayAsPeers(peerIds: peers.map { $0.peer.id }, timestamp: currentTimestamp)) {
|
||||
transaction.putItemCacheEntry(id: ItemCacheEntryId(collectionId: Namespaces.CachedItemCollection.cachedGroupCallDisplayAsPeers, key: key), entry: entry, collectionSpec: ItemCacheCollectionSpec(lowWaterItemCount: 10, highWaterItemCount: 20))
|
||||
transaction.putItemCacheEntry(id: ItemCacheEntryId(collectionId: Namespaces.CachedItemCollection.cachedGroupCallDisplayAsPeers, key: key), entry: entry)
|
||||
}
|
||||
return peers
|
||||
}
|
||||
|
@ -11,6 +11,7 @@ public enum EngineConfiguration {
|
||||
public var maxSupergroupMemberCount: Int32
|
||||
public var maxMessageForwardBatchSize: Int32
|
||||
public var maxSavedGifCount: Int32
|
||||
public var maxFavedStickerCount: Int32
|
||||
public var maxRecentStickerCount: Int32
|
||||
public var maxMessageEditingInterval: Int32
|
||||
public var maxMediaCaptionLength: Int32
|
||||
@ -25,6 +26,7 @@ public enum EngineConfiguration {
|
||||
maxSupergroupMemberCount: Int32,
|
||||
maxMessageForwardBatchSize: Int32,
|
||||
maxSavedGifCount: Int32,
|
||||
maxFavedStickerCount: Int32,
|
||||
maxRecentStickerCount: Int32,
|
||||
maxMessageEditingInterval: Int32,
|
||||
maxMediaCaptionLength: Int32,
|
||||
@ -38,6 +40,7 @@ public enum EngineConfiguration {
|
||||
self.maxSupergroupMemberCount = maxSupergroupMemberCount
|
||||
self.maxMessageForwardBatchSize = maxMessageForwardBatchSize
|
||||
self.maxSavedGifCount = maxSavedGifCount
|
||||
self.maxFavedStickerCount = maxFavedStickerCount
|
||||
self.maxRecentStickerCount = maxRecentStickerCount
|
||||
self.maxMessageEditingInterval = maxMessageEditingInterval
|
||||
self.maxMediaCaptionLength = maxMediaCaptionLength
|
||||
@ -89,7 +92,9 @@ public enum EngineConfiguration {
|
||||
}
|
||||
}
|
||||
|
||||
extension EngineConfiguration.Limits {
|
||||
public typealias EngineContentSettings = ContentSettings
|
||||
|
||||
public extension EngineConfiguration.Limits {
|
||||
init(_ limitsConfiguration: LimitsConfiguration) {
|
||||
self.init(
|
||||
maxPinnedChatCount: limitsConfiguration.maxPinnedChatCount,
|
||||
@ -98,6 +103,7 @@ extension EngineConfiguration.Limits {
|
||||
maxSupergroupMemberCount: limitsConfiguration.maxSupergroupMemberCount,
|
||||
maxMessageForwardBatchSize: limitsConfiguration.maxMessageForwardBatchSize,
|
||||
maxSavedGifCount: limitsConfiguration.maxSavedGifCount,
|
||||
maxFavedStickerCount: limitsConfiguration.maxFavedStickerCount,
|
||||
maxRecentStickerCount: limitsConfiguration.maxRecentStickerCount,
|
||||
maxMessageEditingInterval: limitsConfiguration.maxMessageEditingInterval,
|
||||
maxMediaCaptionLength: limitsConfiguration.maxMediaCaptionLength,
|
||||
@ -106,6 +112,24 @@ extension EngineConfiguration.Limits {
|
||||
maxMessageRevokeIntervalInPrivateChats: limitsConfiguration.maxMessageRevokeIntervalInPrivateChats
|
||||
)
|
||||
}
|
||||
|
||||
func _asLimits() -> LimitsConfiguration {
|
||||
return LimitsConfiguration(
|
||||
maxPinnedChatCount: self.maxPinnedChatCount,
|
||||
maxArchivedPinnedChatCount: self.maxArchivedPinnedChatCount,
|
||||
maxGroupMemberCount: self.maxGroupMemberCount,
|
||||
maxSupergroupMemberCount: self.maxSupergroupMemberCount,
|
||||
maxMessageForwardBatchSize: self.maxMessageForwardBatchSize,
|
||||
maxSavedGifCount: self.maxSavedGifCount,
|
||||
maxRecentStickerCount: self.maxRecentStickerCount,
|
||||
maxFavedStickerCount: self.maxFavedStickerCount,
|
||||
maxMessageEditingInterval: self.maxMessageEditingInterval,
|
||||
maxMediaCaptionLength: self.maxMediaCaptionLength,
|
||||
canRemoveIncomingMessagesInPrivateChats: self.canRemoveIncomingMessagesInPrivateChats,
|
||||
maxMessageRevokeInterval: self.maxMessageRevokeInterval,
|
||||
maxMessageRevokeIntervalInPrivateChats: self.maxMessageRevokeIntervalInPrivateChats
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
public extension EngineConfiguration.UserLimits {
|
||||
@ -155,6 +179,27 @@ public extension EngineConfiguration.SearchBots {
|
||||
|
||||
public extension TelegramEngine.EngineData.Item {
|
||||
enum Configuration {
|
||||
public struct App: TelegramEngineDataItem, PostboxViewDataItem {
|
||||
public typealias Result = AppConfiguration
|
||||
|
||||
public init() {
|
||||
}
|
||||
|
||||
var key: PostboxViewKey {
|
||||
return .preferences(keys: Set([PreferencesKeys.appConfiguration]))
|
||||
}
|
||||
|
||||
func extract(view: PostboxView) -> Result {
|
||||
guard let view = view as? PreferencesView else {
|
||||
preconditionFailure()
|
||||
}
|
||||
guard let appConfiguration = view.values[PreferencesKeys.appConfiguration]?.get(AppConfiguration.self) else {
|
||||
return AppConfiguration.defaultValue
|
||||
}
|
||||
return appConfiguration
|
||||
}
|
||||
}
|
||||
|
||||
public struct Limits: TelegramEngineDataItem, PostboxViewDataItem {
|
||||
public typealias Result = EngineConfiguration.Limits
|
||||
|
||||
@ -240,5 +285,49 @@ public extension TelegramEngine.EngineData.Item {
|
||||
return EngineConfiguration.SearchBots(value)
|
||||
}
|
||||
}
|
||||
|
||||
public struct ApplicationSpecificPreference: TelegramEngineDataItem, PostboxViewDataItem {
|
||||
public typealias Result = PreferencesEntry?
|
||||
|
||||
private let itemKey: ValueBoxKey
|
||||
public init(key: ValueBoxKey) {
|
||||
self.itemKey = key
|
||||
}
|
||||
|
||||
var key: PostboxViewKey {
|
||||
return .preferences(keys: Set([self.itemKey]))
|
||||
}
|
||||
|
||||
func extract(view: PostboxView) -> Result {
|
||||
guard let view = view as? PreferencesView else {
|
||||
preconditionFailure()
|
||||
}
|
||||
guard let value = view.values[self.itemKey] else {
|
||||
return nil
|
||||
}
|
||||
return value
|
||||
}
|
||||
}
|
||||
|
||||
public struct ContentSettings: TelegramEngineDataItem, PostboxViewDataItem {
|
||||
public typealias Result = EngineContentSettings
|
||||
|
||||
public init() {
|
||||
}
|
||||
|
||||
var key: PostboxViewKey {
|
||||
return .preferences(keys: Set([PreferencesKeys.appConfiguration]))
|
||||
}
|
||||
|
||||
func extract(view: PostboxView) -> Result {
|
||||
guard let view = view as? PreferencesView else {
|
||||
preconditionFailure()
|
||||
}
|
||||
guard let appConfiguration = view.values[PreferencesKeys.appConfiguration]?.get(AppConfiguration.self) else {
|
||||
return EngineContentSettings(appConfiguration: AppConfiguration.defaultValue)
|
||||
}
|
||||
return EngineContentSettings(appConfiguration: appConfiguration)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,29 @@
|
||||
import SwiftSignalKit
|
||||
import Postbox
|
||||
|
||||
public extension TelegramEngine.EngineData.Item {
|
||||
enum ItemCache {
|
||||
public struct Item: TelegramEngineDataItem, PostboxViewDataItem {
|
||||
public typealias Result = CodableEntry?
|
||||
|
||||
private let collectionId: Int8
|
||||
private let id: ValueBoxKey
|
||||
|
||||
public init(collectionId: Int8, id: ValueBoxKey) {
|
||||
self.collectionId = collectionId
|
||||
self.id = id
|
||||
}
|
||||
|
||||
var key: PostboxViewKey {
|
||||
return .cachedItem(ItemCacheEntryId(collectionId: collectionId, key: self.id))
|
||||
}
|
||||
|
||||
func extract(view: PostboxView) -> Result {
|
||||
guard let view = view as? CachedItemView else {
|
||||
preconditionFailure()
|
||||
}
|
||||
return view.value
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -127,6 +127,31 @@ public extension TelegramEngine.EngineData.Item {
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
public struct ReadState: TelegramEngineDataItem, TelegramEngineMapKeyDataItem, PostboxViewDataItem {
|
||||
public typealias Result = CombinedPeerReadState?
|
||||
|
||||
fileprivate let id: EnginePeer.Id
|
||||
public var mapKey: EnginePeer.Id {
|
||||
return self.id
|
||||
}
|
||||
|
||||
var key: PostboxViewKey {
|
||||
return .combinedReadState(peerId: self.id)
|
||||
}
|
||||
|
||||
public init(id: EnginePeer.Id) {
|
||||
self.id = id
|
||||
}
|
||||
|
||||
func extract(view: PostboxView) -> Result {
|
||||
guard let view = view as? CombinedReadStateView else {
|
||||
preconditionFailure()
|
||||
}
|
||||
|
||||
return view.state
|
||||
}
|
||||
}
|
||||
|
||||
public struct PeerUnreadCount: TelegramEngineDataItem, TelegramEngineMapKeyDataItem, PostboxViewDataItem {
|
||||
public typealias Result = Int
|
||||
@ -144,7 +169,7 @@ public extension TelegramEngine.EngineData.Item {
|
||||
self.id = id
|
||||
}
|
||||
|
||||
func extract(view: PostboxView) -> Int {
|
||||
func extract(view: PostboxView) -> Result {
|
||||
guard let view = view as? UnreadMessageCountsView else {
|
||||
preconditionFailure()
|
||||
}
|
||||
|
@ -8,6 +8,81 @@ public enum EnginePeerCachedInfoItem<T> {
|
||||
case unknown
|
||||
}
|
||||
|
||||
public enum EngineChannelParticipant: Equatable {
|
||||
case creator(id: EnginePeer.Id, adminInfo: ChannelParticipantAdminInfo?, rank: String?)
|
||||
case member(id: EnginePeer.Id, invitedAt: Int32, adminInfo: ChannelParticipantAdminInfo?, banInfo: ChannelParticipantBannedInfo?, rank: String?)
|
||||
|
||||
public var peerId: EnginePeer.Id {
|
||||
switch self {
|
||||
case let .creator(id, _, _):
|
||||
return id
|
||||
case let .member(id, _, _, _, _):
|
||||
return id
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public extension EngineChannelParticipant {
|
||||
init(_ participant: ChannelParticipant) {
|
||||
switch participant {
|
||||
case let .creator(id, adminInfo, rank):
|
||||
self = .creator(id: id, adminInfo: adminInfo, rank: rank)
|
||||
case let .member(id, invitedAt, adminInfo, banInfo, rank):
|
||||
self = .member(id: id, invitedAt: invitedAt, adminInfo: adminInfo, banInfo: banInfo, rank: rank)
|
||||
}
|
||||
}
|
||||
|
||||
func _asParticipant() -> ChannelParticipant {
|
||||
switch self {
|
||||
case let .creator(id, adminInfo, rank):
|
||||
return .creator(id: id, adminInfo: adminInfo, rank: rank)
|
||||
case let .member(id, invitedAt, adminInfo, banInfo, rank):
|
||||
return .member(id: id, invitedAt: invitedAt, adminInfo: adminInfo, banInfo: banInfo, rank: rank)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public enum EngineLegacyGroupParticipant: Equatable {
|
||||
case member(id: EnginePeer.Id, invitedBy: EnginePeer.Id, invitedAt: Int32)
|
||||
case creator(id: EnginePeer.Id)
|
||||
case admin(id: EnginePeer.Id, invitedBy: EnginePeer.Id, invitedAt: Int32)
|
||||
|
||||
public var peerId: EnginePeer.Id {
|
||||
switch self {
|
||||
case let .member(id, _, _):
|
||||
return id
|
||||
case let .creator(id):
|
||||
return id
|
||||
case let .admin(id, _, _):
|
||||
return id
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public extension EngineLegacyGroupParticipant {
|
||||
init(_ participant: GroupParticipant) {
|
||||
switch participant {
|
||||
case let .member(id, invitedBy, invitedAt):
|
||||
self = .member(id: id, invitedBy: invitedBy, invitedAt: invitedAt)
|
||||
case let .creator(id):
|
||||
self = .creator(id: id)
|
||||
case let .admin(id, invitedBy, invitedAt):
|
||||
self = .admin(id: id, invitedBy: invitedBy, invitedAt: invitedAt)
|
||||
}
|
||||
}
|
||||
|
||||
func _asParticipant() -> GroupParticipant {
|
||||
switch self {
|
||||
case let .member(id, invitedBy, invitedAt):
|
||||
return .member(id: id, invitedBy: invitedBy, invitedAt: invitedAt)
|
||||
case let .creator(id):
|
||||
return .creator(id: id)
|
||||
case let .admin(id, invitedBy, invitedAt):
|
||||
return .admin(id: id, invitedBy: invitedBy, invitedAt: invitedAt)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public extension TelegramEngine.EngineData.Item {
|
||||
enum NotificationSettings {
|
||||
public struct Global: TelegramEngineDataItem, PostboxViewDataItem {
|
||||
@ -675,5 +750,37 @@ public extension TelegramEngine.EngineData.Item {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public struct LegacyGroupParticipants: TelegramEngineDataItem, TelegramEngineMapKeyDataItem, PostboxViewDataItem {
|
||||
public typealias Result = EnginePeerCachedInfoItem<[EngineLegacyGroupParticipant]>
|
||||
|
||||
fileprivate var id: EnginePeer.Id
|
||||
public var mapKey: EnginePeer.Id {
|
||||
return self.id
|
||||
}
|
||||
|
||||
public init(id: EnginePeer.Id) {
|
||||
self.id = id
|
||||
}
|
||||
|
||||
var key: PostboxViewKey {
|
||||
return .cachedPeerData(peerId: self.id)
|
||||
}
|
||||
|
||||
func extract(view: PostboxView) -> Result {
|
||||
guard let view = view as? CachedPeerDataView else {
|
||||
preconditionFailure()
|
||||
}
|
||||
if let cachedData = view.cachedPeerData as? CachedGroupData {
|
||||
if let participants = cachedData.participants {
|
||||
return .known(participants.participants.map(EngineLegacyGroupParticipant.init))
|
||||
} else {
|
||||
return .unknown
|
||||
}
|
||||
} else {
|
||||
return .unknown
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,29 @@
|
||||
import Foundation
|
||||
import SwiftSignalKit
|
||||
import Postbox
|
||||
|
||||
public extension TelegramEngine {
|
||||
final class ItemCache {
|
||||
private let account: Account
|
||||
|
||||
init(account: Account) {
|
||||
self.account = account
|
||||
}
|
||||
|
||||
public func put<T: Codable>(collectionId: Int8, id: ValueBoxKey, item: T) -> Signal<Never, NoError> {
|
||||
return self.account.postbox.transaction { transaction -> Void in
|
||||
if let entry = CodableEntry(item) {
|
||||
transaction.putItemCacheEntry(id: ItemCacheEntryId(collectionId: collectionId, key: id), entry: entry)
|
||||
}
|
||||
}
|
||||
|> ignoreValues
|
||||
}
|
||||
|
||||
public func remove(collectionId: Int8, id: ValueBoxKey) -> Signal<Never, NoError> {
|
||||
return self.account.postbox.transaction { transaction -> Void in
|
||||
transaction.removeItemCacheEntry(id: ItemCacheEntryId(collectionId: collectionId, key: id))
|
||||
}
|
||||
|> ignoreValues
|
||||
}
|
||||
}
|
||||
}
|
@ -57,7 +57,7 @@ func _internal_availableLocalizations(postbox: Postbox, network: Network, allowC
|
||||
let infos: [LocalizationInfo] = languages.map(LocalizationInfo.init(apiLanguage:))
|
||||
return postbox.transaction { transaction -> [LocalizationInfo] in
|
||||
if let entry = CodableEntry(CachedLocalizationInfos(list: infos)) {
|
||||
transaction.putItemCacheEntry(id: ItemCacheEntryId(collectionId: Namespaces.CachedItemCollection.cachedAvailableLocalizations, key: ValueBoxKey(length: 0)), entry: entry, collectionSpec: ItemCacheCollectionSpec(lowWaterItemCount: 1, highWaterItemCount: 1))
|
||||
transaction.putItemCacheEntry(id: ItemCacheEntryId(collectionId: Namespaces.CachedItemCollection.cachedAvailableLocalizations, key: ValueBoxKey(length: 0)), entry: entry)
|
||||
}
|
||||
return infos
|
||||
}
|
||||
|
@ -304,8 +304,6 @@ private class AdMessagesHistoryContextImpl {
|
||||
}, forKey: "messages")
|
||||
}
|
||||
|
||||
private static let collectionSpec = ItemCacheCollectionSpec(lowWaterItemCount: 5, highWaterItemCount: 10)
|
||||
|
||||
public static func getCached(postbox: Postbox, peerId: PeerId) -> Signal<CachedState?, NoError> {
|
||||
return postbox.transaction { transaction -> CachedState? in
|
||||
let key = ValueBoxKey(length: 8)
|
||||
@ -323,7 +321,7 @@ private class AdMessagesHistoryContextImpl {
|
||||
key.setInt64(0, value: peerId.toInt64())
|
||||
let id = ItemCacheEntryId(collectionId: Namespaces.CachedItemCollection.cachedAdMessageStates, key: key)
|
||||
if let state = state, let entry = CodableEntry(state) {
|
||||
transaction.putItemCacheEntry(id: id, entry: entry, collectionSpec: collectionSpec)
|
||||
transaction.putItemCacheEntry(id: id, entry: entry)
|
||||
} else {
|
||||
transaction.removeItemCacheEntry(id: id)
|
||||
}
|
||||
|
@ -176,7 +176,7 @@ public func clearPeerUnseenReactionsInteractively(account: Account, peerId: Peer
|
||||
|> ignoreValues
|
||||
}
|
||||
|
||||
public func markAllChatsAsReadInteractively(transaction: Transaction, viewTracker: AccountViewTracker, groupId: PeerGroupId, filterPredicate: ChatListFilterPredicate?) {
|
||||
func _internal_markAllChatsAsReadInteractively(transaction: Transaction, viewTracker: AccountViewTracker, groupId: PeerGroupId, filterPredicate: ChatListFilterPredicate?) {
|
||||
for peerId in transaction.getUnreadChatListPeerIds(groupId: groupId, filterPredicate: filterPredicate) {
|
||||
togglePeerUnreadMarkInteractively(transaction: transaction, viewTracker: viewTracker, peerId: peerId, setToValue: false)
|
||||
}
|
||||
|
@ -222,7 +222,7 @@ private func setCachedAttachMenuBots(transaction: Transaction, attachMenuBots: A
|
||||
|
||||
let entryId = ItemCacheEntryId(collectionId: Namespaces.CachedItemCollection.attachMenuBots, key: key)
|
||||
if let entry = CodableEntry(attachMenuBots) {
|
||||
transaction.putItemCacheEntry(id: entryId, entry: entry, collectionSpec: ItemCacheCollectionSpec(lowWaterItemCount: 10, highWaterItemCount: 10))
|
||||
transaction.putItemCacheEntry(id: entryId, entry: entry)
|
||||
} else {
|
||||
transaction.removeItemCacheEntry(id: entryId)
|
||||
}
|
||||
|
@ -149,8 +149,6 @@ func _internal_requestClosePoll(postbox: Postbox, network: Network, stateManager
|
||||
}
|
||||
}
|
||||
|
||||
private let cachedPollResultsCollectionSpec = ItemCacheCollectionSpec(lowWaterItemCount: 20, highWaterItemCount: 40)
|
||||
|
||||
final class CachedPollOptionResult: Codable {
|
||||
let peerIds: [PeerId]
|
||||
let count: Int32
|
||||
@ -299,7 +297,7 @@ private final class PollResultsOptionContext {
|
||||
}
|
||||
if populateCache {
|
||||
if let entry = CodableEntry(CachedPollOptionResult(peerIds: resultPeers.map { $0.peerId }, count: count)) {
|
||||
transaction.putItemCacheEntry(id: ItemCacheEntryId(collectionId: Namespaces.CachedItemCollection.cachedPollResults, key: CachedPollOptionResult.key(pollId: pollId, optionOpaqueIdentifier: opaqueIdentifier)), entry: entry, collectionSpec: cachedPollResultsCollectionSpec)
|
||||
transaction.putItemCacheEntry(id: ItemCacheEntryId(collectionId: Namespaces.CachedItemCollection.cachedPollResults, key: CachedPollOptionResult.key(pollId: pollId, optionOpaqueIdentifier: opaqueIdentifier)), entry: entry)
|
||||
}
|
||||
}
|
||||
return (resultPeers, Int(count), nextOffset)
|
||||
|
@ -33,8 +33,6 @@ public final class CachedChatContextResult: Codable {
|
||||
}
|
||||
}
|
||||
|
||||
private let collectionSpec = ItemCacheCollectionSpec(lowWaterItemCount: 40, highWaterItemCount: 60)
|
||||
|
||||
private struct RequestData: Codable {
|
||||
let version: String
|
||||
let botId: PeerId
|
||||
@ -146,7 +144,7 @@ func _internal_requestChatContextResults(account: Account, botId: PeerId, peerId
|
||||
if let keyData = try? JSONEncoder().encode(requestData) {
|
||||
let key = ValueBoxKey(MemoryBuffer(data: keyData))
|
||||
if let entry = CodableEntry(CachedChatContextResult(data: resultData, timestamp: Int32(Date().timeIntervalSince1970))) {
|
||||
transaction.putItemCacheEntry(id: ItemCacheEntryId(collectionId: Namespaces.CachedItemCollection.cachedContextResults, key: key), entry: entry, collectionSpec: collectionSpec)
|
||||
transaction.putItemCacheEntry(id: ItemCacheEntryId(collectionId: Namespaces.CachedItemCollection.cachedContextResults, key: key), entry: entry)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -62,7 +62,7 @@ func _internal_cachedPeerSendAsAvailablePeers(account: Account, peerId: PeerId)
|
||||
return account.postbox.transaction { transaction -> [FoundPeer] in
|
||||
let currentTimestamp = Int32(CFAbsoluteTimeGetCurrent() + kCFAbsoluteTimeIntervalSince1970)
|
||||
if let entry = CodableEntry(CachedSendAsPeers(peerIds: peers.map { $0.peer.id }, timestamp: currentTimestamp)) {
|
||||
transaction.putItemCacheEntry(id: ItemCacheEntryId(collectionId: Namespaces.CachedItemCollection.cachedSendAsPeers, key: key), entry: entry, collectionSpec: ItemCacheCollectionSpec(lowWaterItemCount: 10, highWaterItemCount: 20))
|
||||
transaction.putItemCacheEntry(id: ItemCacheEntryId(collectionId: Namespaces.CachedItemCollection.cachedSendAsPeers, key: key), entry: entry)
|
||||
}
|
||||
return peers
|
||||
}
|
||||
|
@ -51,12 +51,15 @@ public extension TelegramEngine {
|
||||
return _internal_searchMessageIdByTimestamp(account: self.account, peerId: peerId, threadId: threadId, timestamp: timestamp)
|
||||
}
|
||||
|
||||
public func deleteMessages(transaction: Transaction, ids: [MessageId], deleteMedia: Bool = true, manualAddMessageThreadStatsDifference: ((MessageId, Int, Int) -> Void)? = nil) {
|
||||
return _internal_deleteMessages(transaction: transaction, mediaBox: self.account.postbox.mediaBox, ids: ids, deleteMedia: deleteMedia, manualAddMessageThreadStatsDifference: manualAddMessageThreadStatsDifference)
|
||||
public func deleteMessages(transaction: Transaction, ids: [MessageId]) {
|
||||
return _internal_deleteMessages(transaction: transaction, mediaBox: self.account.postbox.mediaBox, ids: ids, deleteMedia: true, manualAddMessageThreadStatsDifference: nil)
|
||||
}
|
||||
|
||||
public func deleteAllMessagesWithAuthor(transaction: Transaction, peerId: PeerId, authorId: PeerId, namespace: MessageId.Namespace) {
|
||||
return _internal_deleteAllMessagesWithAuthor(transaction: transaction, mediaBox: self.account.postbox.mediaBox, peerId: peerId, authorId: authorId, namespace: namespace)
|
||||
public func deleteAllMessagesWithAuthor(peerId: PeerId, authorId: PeerId, namespace: MessageId.Namespace) -> Signal<Never, NoError> {
|
||||
return self.account.postbox.transaction { transaction -> Void in
|
||||
_internal_deleteAllMessagesWithAuthor(transaction: transaction, mediaBox: self.account.postbox.mediaBox, peerId: peerId, authorId: authorId, namespace: namespace)
|
||||
}
|
||||
|> ignoreValues
|
||||
}
|
||||
|
||||
public func deleteAllMessagesWithForwardAuthor(transaction: Transaction, peerId: PeerId, forwardAuthorId: PeerId, namespace: MessageId.Namespace) {
|
||||
@ -378,5 +381,27 @@ public extension TelegramEngine {
|
||||
return transaction.getMessageFailedGroup(id)?.map(EngineMessage.init) ?? []
|
||||
}
|
||||
}
|
||||
|
||||
public func unreadChatListPeerIds(groupId: EngineChatList.Group, filterPredicate: ChatListFilterPredicate?) -> Signal<[EnginePeer.Id], NoError> {
|
||||
return self.account.postbox.transaction { transaction -> [EnginePeer.Id] in
|
||||
return transaction.getUnreadChatListPeerIds(groupId: groupId._asGroup(), filterPredicate: filterPredicate)
|
||||
}
|
||||
}
|
||||
|
||||
public func markAllChatsAsReadInteractively(items: [(groupId: EngineChatList.Group, filterPredicate: ChatListFilterPredicate?)]) -> Signal<Never, NoError> {
|
||||
let account = self.account
|
||||
return self.account.postbox.transaction { transaction -> Void in
|
||||
for (groupId, filterPredicate) in items {
|
||||
_internal_markAllChatsAsReadInteractively(transaction: transaction, viewTracker: account.viewTracker, groupId: groupId._asGroup(), filterPredicate: filterPredicate)
|
||||
}
|
||||
}
|
||||
|> ignoreValues
|
||||
}
|
||||
|
||||
public func getRelativeUnreadChatListIndex(filtered: Bool, position: EngineChatList.RelativePosition, groupId: EngineChatList.Group) -> Signal<EngineChatList.Item.Index?, NoError> {
|
||||
return self.account.postbox.transaction { transaction -> EngineChatList.Item.Index? in
|
||||
return transaction.getRelativeUnreadChatListIndex(filtered: filtered, position: position._asPosition(), groupId: groupId._asGroup())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -10,6 +10,27 @@ public extension TelegramEngine {
|
||||
self.account = account
|
||||
}
|
||||
|
||||
public func addOrMoveToFirstPosition<T: Codable>(collectionId: Int32, id: MemoryBuffer, item: T, removeTailIfCountExceeds: Int?) -> Signal<Never, NoError> {
|
||||
return self.account.postbox.transaction { transaction -> Void in
|
||||
if let entry = CodableEntry(item) {
|
||||
transaction.addOrMoveToFirstPositionOrderedItemListItem(collectionId: collectionId, item: OrderedItemListEntry(id: id, contents: entry), removeTailIfCountExceeds: removeTailIfCountExceeds)
|
||||
}
|
||||
}
|
||||
|> ignoreValues
|
||||
}
|
||||
|
||||
public func clear(collectionId: Int32) -> Signal<Never, NoError> {
|
||||
return self.account.postbox.transaction { transaction -> Void in
|
||||
transaction.replaceOrderedItemListItems(collectionId: collectionId, items: [])
|
||||
}
|
||||
|> ignoreValues
|
||||
}
|
||||
|
||||
public func removeItem(collectionId: Int32, id: MemoryBuffer) -> Signal<Never, NoError> {
|
||||
return self.account.postbox.transaction { transaction -> Void in
|
||||
transaction.removeOrderedItemListItem(collectionId: collectionId, itemId: id)
|
||||
}
|
||||
|> ignoreValues
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -317,8 +317,6 @@ func _internal_deleteAllRevokedPeerExportedInvitations(account: Account, peerId:
|
||||
|> switchToLatest
|
||||
}
|
||||
|
||||
private let cachedPeerExportedInvitationsCollectionSpec = ItemCacheCollectionSpec(lowWaterItemCount: 10, highWaterItemCount: 20)
|
||||
|
||||
public struct PeerExportedInvitationsState: Equatable {
|
||||
public var invitations: [ExportedInvitation]
|
||||
public var isLoadingMore: Bool
|
||||
@ -500,7 +498,7 @@ private final class PeerExportedInvitationsContextImpl {
|
||||
let invitations: [ExportedInvitation] = invites.compactMap { ExportedInvitation(apiExportedInvite: $0) }
|
||||
if populateCache {
|
||||
if let entry = CodableEntry(CachedPeerExportedInvitations(invitations: invitations, canLoadMore: count >= 50, count: count)) {
|
||||
transaction.putItemCacheEntry(id: ItemCacheEntryId(collectionId: Namespaces.CachedItemCollection.cachedPeerExportedInvitations, key: CachedPeerExportedInvitations.key(peerId: peerId, revoked: revoked)), entry: entry, collectionSpec: cachedPeerExportedInvitationsCollectionSpec)
|
||||
transaction.putItemCacheEntry(id: ItemCacheEntryId(collectionId: Namespaces.CachedItemCollection.cachedPeerExportedInvitations, key: CachedPeerExportedInvitations.key(peerId: peerId, revoked: revoked)), entry: entry)
|
||||
}
|
||||
}
|
||||
return (invitations, count)
|
||||
@ -590,7 +588,7 @@ private final class PeerExportedInvitationsContextImpl {
|
||||
let count = self.count
|
||||
self.updateDisposable.set(self.account.postbox.transaction({ transaction in
|
||||
if let entry = CodableEntry(CachedPeerExportedInvitations(invitations: invitations, canLoadMore: canLoadMore, count: count)) {
|
||||
transaction.putItemCacheEntry(id: ItemCacheEntryId(collectionId: Namespaces.CachedItemCollection.cachedPeerExportedInvitations, key: CachedPeerExportedInvitations.key(peerId: peerId, revoked: revoked)), entry: entry, collectionSpec: cachedPeerExportedInvitationsCollectionSpec)
|
||||
transaction.putItemCacheEntry(id: ItemCacheEntryId(collectionId: Namespaces.CachedItemCollection.cachedPeerExportedInvitations, key: CachedPeerExportedInvitations.key(peerId: peerId, revoked: revoked)), entry: entry)
|
||||
}
|
||||
}).start())
|
||||
}
|
||||
@ -660,10 +658,6 @@ public final class PeerExportedInvitationsContext {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
private let cachedPeerInvitationImportersCollectionSpec = ItemCacheCollectionSpec(lowWaterItemCount: 10, highWaterItemCount: 20)
|
||||
|
||||
public struct PeerInvitationImportersState: Equatable {
|
||||
public struct Importer: Equatable {
|
||||
public var peer: RenderedPeer
|
||||
@ -977,7 +971,7 @@ private final class PeerInvitationImportersContextImpl {
|
||||
}
|
||||
if populateCache && query == nil {
|
||||
if let entry = CodableEntry(CachedPeerInvitationImporters(importers: resultImporters, count: count)) {
|
||||
transaction.putItemCacheEntry(id: ItemCacheEntryId(collectionId: Namespaces.CachedItemCollection.cachedPeerInvitationImporters, key: CachedPeerInvitationImporters.key(peerId: peerId, link: link ?? "requests", requested: self.requested)), entry: entry, collectionSpec: cachedPeerInvitationImportersCollectionSpec)
|
||||
transaction.putItemCacheEntry(id: ItemCacheEntryId(collectionId: Namespaces.CachedItemCollection.cachedPeerInvitationImporters, key: CachedPeerInvitationImporters.key(peerId: peerId, link: link ?? "requests", requested: self.requested)), entry: entry)
|
||||
}
|
||||
}
|
||||
return (resultImporters, count)
|
||||
@ -1073,7 +1067,7 @@ private final class PeerInvitationImportersContextImpl {
|
||||
let link = self.link
|
||||
self.updateDisposables.add(self.account.postbox.transaction({ transaction in
|
||||
if let entry = CodableEntry(CachedPeerInvitationImporters(importers: resultImporters, count: count)) {
|
||||
transaction.putItemCacheEntry(id: ItemCacheEntryId(collectionId: Namespaces.CachedItemCollection.cachedPeerInvitationImporters, key: CachedPeerInvitationImporters.key(peerId: peerId, link: link ?? "requests", requested: self.requested)), entry: entry, collectionSpec: cachedPeerInvitationImportersCollectionSpec)
|
||||
transaction.putItemCacheEntry(id: ItemCacheEntryId(collectionId: Namespaces.CachedItemCollection.cachedPeerInvitationImporters, key: CachedPeerInvitationImporters.key(peerId: peerId, link: link ?? "requests", requested: self.requested)), entry: entry)
|
||||
}
|
||||
}).start())
|
||||
}
|
||||
|
@ -135,7 +135,7 @@ public func _internal_cachedNotificationSoundList(transaction: Transaction) -> N
|
||||
|
||||
func _internal_setCachedNotificationSoundList(transaction: Transaction, notificationSoundList: NotificationSoundList) {
|
||||
if let entry = CodableEntry(notificationSoundList) {
|
||||
transaction.putItemCacheEntry(id: _internal_cachedNotificationSoundListCacheKey(), entry: entry, collectionSpec: ItemCacheCollectionSpec(lowWaterItemCount: 10, highWaterItemCount: 10))
|
||||
transaction.putItemCacheEntry(id: _internal_cachedNotificationSoundListCacheKey(), entry: entry)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3,14 +3,11 @@ import Postbox
|
||||
import TelegramApi
|
||||
import SwiftSignalKit
|
||||
|
||||
|
||||
public enum RecentPeers {
|
||||
case peers([Peer])
|
||||
case disabled
|
||||
}
|
||||
|
||||
private let collectionSpec = ItemCacheCollectionSpec(lowWaterItemCount: 1, highWaterItemCount: 1)
|
||||
|
||||
private func cachedRecentPeersEntryId() -> ItemCacheEntryId {
|
||||
return ItemCacheEntryId(collectionId: 101, key: CachedRecentPeers.cacheKey())
|
||||
}
|
||||
@ -82,13 +79,13 @@ func _internal_managedUpdatedRecentPeers(accountPeerId: PeerId, postbox: Postbox
|
||||
updatePeerPresences(transaction: transaction, accountPeerId: accountPeerId, peerPresences: peerPresences)
|
||||
|
||||
if let entry = CodableEntry(CachedRecentPeers(enabled: true, ids: peers.map { $0.id })) {
|
||||
transaction.putItemCacheEntry(id: cachedRecentPeersEntryId(), entry: entry, collectionSpec: collectionSpec)
|
||||
transaction.putItemCacheEntry(id: cachedRecentPeersEntryId(), entry: entry)
|
||||
}
|
||||
case .topPeersNotModified:
|
||||
break
|
||||
case .topPeersDisabled:
|
||||
if let entry = CodableEntry(CachedRecentPeers(enabled: false, ids: [])) {
|
||||
transaction.putItemCacheEntry(id: cachedRecentPeersEntryId(), entry: entry, collectionSpec: collectionSpec)
|
||||
transaction.putItemCacheEntry(id: cachedRecentPeersEntryId(), entry: entry)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -109,7 +106,7 @@ func _internal_removeRecentPeer(account: Account, peerId: PeerId) -> Signal<Void
|
||||
var updatedIds = entry.ids
|
||||
updatedIds.remove(at: index)
|
||||
if let entry = CodableEntry(CachedRecentPeers(enabled: entry.enabled, ids: updatedIds)) {
|
||||
transaction.putItemCacheEntry(id: cachedRecentPeersEntryId(), entry: entry, collectionSpec: collectionSpec)
|
||||
transaction.putItemCacheEntry(id: cachedRecentPeersEntryId(), entry: entry)
|
||||
}
|
||||
}
|
||||
if let peer = transaction.getPeer(peerId), let apiPeer = apiInputPeer(peer) {
|
||||
@ -145,12 +142,12 @@ func _internal_updateRecentPeersEnabled(postbox: Postbox, network: Network, enab
|
||||
return postbox.transaction { transaction -> Void in
|
||||
if !enabled {
|
||||
if let entry = CodableEntry(CachedRecentPeers(enabled: false, ids: [])) {
|
||||
transaction.putItemCacheEntry(id: cachedRecentPeersEntryId(), entry: entry, collectionSpec: collectionSpec)
|
||||
transaction.putItemCacheEntry(id: cachedRecentPeersEntryId(), entry: entry)
|
||||
}
|
||||
} else {
|
||||
let entry = transaction.retrieveItemCacheEntry(id: cachedRecentPeersEntryId())?.get(CachedRecentPeers.self)
|
||||
if let codableEntry = CodableEntry(CachedRecentPeers(enabled: true, ids: entry?.ids ?? [])) {
|
||||
transaction.putItemCacheEntry(id: cachedRecentPeersEntryId(), entry: codableEntry, collectionSpec: collectionSpec)
|
||||
transaction.putItemCacheEntry(id: cachedRecentPeersEntryId(), entry: codableEntry)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3,9 +3,6 @@ import Postbox
|
||||
import TelegramApi
|
||||
import SwiftSignalKit
|
||||
|
||||
|
||||
private let resolvedByNamePeersCollectionSpec = ItemCacheCollectionSpec(lowWaterItemCount: 150, highWaterItemCount: 200)
|
||||
|
||||
public enum ResolvePeerByNameOptionCached {
|
||||
case none
|
||||
case cached
|
||||
@ -65,7 +62,7 @@ func _internal_resolvePeerByName(account: Account, name: String, ageLimit: Int32
|
||||
|
||||
let timestamp = Int32(CFAbsoluteTimeGetCurrent() + NSTimeIntervalSince1970)
|
||||
if let entry = CodableEntry(CachedResolvedByNamePeer(peerId: peerId, timestamp: timestamp)) {
|
||||
transaction.putItemCacheEntry(id: ItemCacheEntryId(collectionId: Namespaces.CachedItemCollection.resolvedByNamePeers, key: CachedResolvedByNamePeer.key(name: normalizedName)), entry: entry, collectionSpec: resolvedByNamePeersCollectionSpec)
|
||||
transaction.putItemCacheEntry(id: ItemCacheEntryId(collectionId: Namespaces.CachedItemCollection.resolvedByNamePeers, key: CachedResolvedByNamePeer.key(name: normalizedName)), entry: entry)
|
||||
}
|
||||
return peerId
|
||||
}
|
||||
@ -78,8 +75,6 @@ func _internal_resolvePeerByName(account: Account, name: String, ageLimit: Int32
|
||||
}
|
||||
}
|
||||
|
||||
private let resolvedByPhonePeersCollectionSpec = ItemCacheCollectionSpec(lowWaterItemCount: 150, highWaterItemCount: 200)
|
||||
|
||||
func _internal_resolvePeerByPhone(account: Account, phone: String, ageLimit: Int32 = 2 * 60 * 60 * 24) -> Signal<PeerId?, NoError> {
|
||||
var normalizedPhone = phone
|
||||
if normalizedPhone.hasPrefix("+") {
|
||||
@ -128,7 +123,7 @@ func _internal_resolvePeerByPhone(account: Account, phone: String, ageLimit: Int
|
||||
|
||||
let timestamp = Int32(CFAbsoluteTimeGetCurrent() + NSTimeIntervalSince1970)
|
||||
if let entry = CodableEntry(CachedResolvedByPhonePeer(peerId: peerId, timestamp: timestamp)) {
|
||||
transaction.putItemCacheEntry(id: ItemCacheEntryId(collectionId: Namespaces.CachedItemCollection.resolvedByPhonePeers, key: CachedResolvedByPhonePeer.key(name: normalizedPhone)), entry: entry, collectionSpec: resolvedByNamePeersCollectionSpec)
|
||||
transaction.putItemCacheEntry(id: ItemCacheEntryId(collectionId: Namespaces.CachedItemCollection.resolvedByPhonePeers, key: CachedResolvedByPhonePeer.key(name: normalizedPhone)), entry: entry)
|
||||
}
|
||||
return peerId
|
||||
}
|
||||
|
@ -756,6 +756,22 @@ public extension TelegramEngine {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public func updatePeersGroupIdInteractively(peerIds: [EnginePeer.Id], groupId: EngineChatList.Group) -> Signal<Never, NoError> {
|
||||
return self.account.postbox.transaction { transaction -> Void in
|
||||
for peerId in peerIds {
|
||||
_internal_updatePeerGroupIdInteractively(transaction: transaction, peerId: peerId, groupId: groupId._asGroup())
|
||||
}
|
||||
}
|
||||
|> ignoreValues
|
||||
}
|
||||
|
||||
public func resetAllPeerNotificationSettings() -> Signal<Never, NoError> {
|
||||
return self.account.postbox.transaction { transaction -> Void in
|
||||
transaction.resetAllPeerNotificationSettings(TelegramPeerNotificationSettings.defaultSettings)
|
||||
}
|
||||
|> ignoreValues
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -36,7 +36,7 @@ public func secureIdConfiguration(postbox: Postbox, network: Network) -> Signal<
|
||||
}
|
||||
return postbox.transaction { transaction -> SecureIdConfiguration in
|
||||
if let entry = CodableEntry(parsed) {
|
||||
transaction.putItemCacheEntry(id: ItemCacheEntryId(collectionId: Namespaces.CachedItemCollection.cachedSecureIdConfiguration, key: ValueBoxKey(length: 0)), entry: entry, collectionSpec: ItemCacheCollectionSpec(lowWaterItemCount: 1, highWaterItemCount: 1))
|
||||
transaction.putItemCacheEntry(id: ItemCacheEntryId(collectionId: Namespaces.CachedItemCollection.cachedSecureIdConfiguration, key: ValueBoxKey(length: 0)), entry: entry)
|
||||
}
|
||||
return parsed.value
|
||||
}
|
||||
|
@ -3,9 +3,6 @@ import Postbox
|
||||
import SwiftSignalKit
|
||||
import MurMurHash32
|
||||
|
||||
|
||||
private let collectionSpec = ItemCacheCollectionSpec(lowWaterItemCount: 100, highWaterItemCount: 200)
|
||||
|
||||
public enum CachedStickerPackResult {
|
||||
case none
|
||||
case fetching
|
||||
@ -14,10 +11,10 @@ public enum CachedStickerPackResult {
|
||||
|
||||
func cacheStickerPack(transaction: Transaction, info: StickerPackCollectionInfo, items: [StickerPackItem], reference: StickerPackReference? = nil) {
|
||||
if let entry = CodableEntry(CachedStickerPack(info: info, items: items, hash: info.hash)) {
|
||||
transaction.putItemCacheEntry(id: ItemCacheEntryId(collectionId: Namespaces.CachedItemCollection.cachedStickerPacks, key: CachedStickerPack.cacheKey(info.id)), entry: entry, collectionSpec: collectionSpec)
|
||||
transaction.putItemCacheEntry(id: ItemCacheEntryId(collectionId: Namespaces.CachedItemCollection.cachedStickerPacks, key: CachedStickerPack.cacheKey(info.id)), entry: entry)
|
||||
}
|
||||
if let entry = CodableEntry(CachedStickerPack(info: info, items: items, hash: info.hash)) {
|
||||
transaction.putItemCacheEntry(id: ItemCacheEntryId(collectionId: Namespaces.CachedItemCollection.cachedStickerPacks, key: CachedStickerPack.cacheKey(shortName: info.shortName.lowercased())), entry: entry, collectionSpec: collectionSpec)
|
||||
transaction.putItemCacheEntry(id: ItemCacheEntryId(collectionId: Namespaces.CachedItemCollection.cachedStickerPacks, key: CachedStickerPack.cacheKey(shortName: info.shortName.lowercased())), entry: entry)
|
||||
}
|
||||
|
||||
if let reference = reference {
|
||||
@ -38,7 +35,7 @@ func cacheStickerPack(transaction: Transaction, info: StickerPackCollectionInfo,
|
||||
}
|
||||
if let namespace = namespace, let id = id {
|
||||
if let entry = CodableEntry(CachedStickerPack(info: info, items: items, hash: info.hash)) {
|
||||
transaction.putItemCacheEntry(id: ItemCacheEntryId(collectionId: Namespaces.CachedItemCollection.cachedStickerPacks, key: CachedStickerPack.cacheKey(ItemCollectionId(namespace: namespace, id: id))), entry: entry, collectionSpec: collectionSpec)
|
||||
transaction.putItemCacheEntry(id: ItemCacheEntryId(collectionId: Namespaces.CachedItemCollection.cachedStickerPacks, key: CachedStickerPack.cacheKey(ItemCollectionId(namespace: namespace, id: id))), entry: entry)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -43,8 +43,6 @@ public final class FoundStickerItem: Equatable {
|
||||
}
|
||||
}
|
||||
|
||||
private let collectionSpec = ItemCacheCollectionSpec(lowWaterItemCount: 100, highWaterItemCount: 200)
|
||||
|
||||
public struct SearchStickersScope: OptionSet {
|
||||
public var rawValue: Int32
|
||||
|
||||
@ -244,7 +242,7 @@ func _internal_searchStickers(account: Account, query: String, scope: SearchStic
|
||||
|
||||
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)), entry: entry, collectionSpec: collectionSpec)
|
||||
transaction.putItemCacheEntry(id: ItemCacheEntryId(collectionId: Namespaces.CachedItemCollection.cachedStickerQueryResults, key: CachedStickerQueryResult.cacheKey(query)), entry: entry)
|
||||
}
|
||||
|
||||
return result
|
||||
|
@ -118,5 +118,18 @@ public extension TelegramEngine {
|
||||
return getIsStickerSaved(transaction: transaction, fileId: id)
|
||||
}
|
||||
}
|
||||
|
||||
public func isGifSaved(id: EngineMedia.Id) -> Signal<Bool, NoError> {
|
||||
return self.account.postbox.transaction { transaction -> Bool in
|
||||
return getIsGifSaved(transaction: transaction, mediaId: id)
|
||||
}
|
||||
}
|
||||
|
||||
public func clearRecentlyUsedStickers() -> Signal<Never, NoError> {
|
||||
return self.account.postbox.transaction { transaction -> Void in
|
||||
_internal_clearRecentlyUsedStickers(transaction: transaction)
|
||||
}
|
||||
|> ignoreValues
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -79,6 +79,10 @@ public final class TelegramEngine {
|
||||
public lazy var orderedLists: OrderedLists = {
|
||||
return OrderedLists(account: self.account)
|
||||
}()
|
||||
|
||||
public lazy var itemCache: ItemCache = {
|
||||
return ItemCache(account: self.account)
|
||||
}()
|
||||
}
|
||||
|
||||
public final class TelegramEngineUnauthorized {
|
||||
|
@ -55,7 +55,7 @@ public func telegramThemes(postbox: Postbox, network: Network, accountManager: A
|
||||
}
|
||||
transaction.replaceOrderedItemListItems(collectionId: Namespaces.OrderedItemList.CloudThemes, items: entries)
|
||||
if let entry = CodableEntry(CachedThemesConfiguration(hash: hash)) {
|
||||
transaction.putItemCacheEntry(id: ItemCacheEntryId(collectionId: Namespaces.CachedItemCollection.cachedThemesConfiguration, key: ValueBoxKey(length: 0)), entry: entry, collectionSpec: ItemCacheCollectionSpec(lowWaterItemCount: 1, highWaterItemCount: 1))
|
||||
transaction.putItemCacheEntry(id: ItemCacheEntryId(collectionId: Namespaces.CachedItemCollection.cachedThemesConfiguration, key: ValueBoxKey(length: 0)), entry: entry)
|
||||
}
|
||||
return items
|
||||
}
|
||||
|
@ -49,7 +49,7 @@ public func telegramWallpapers(postbox: Postbox, network: Network, forceUpdate:
|
||||
}
|
||||
transaction.replaceOrderedItemListItems(collectionId: Namespaces.OrderedItemList.CloudWallpapers, items: entries)
|
||||
if let entry = CodableEntry(CachedWallpapersConfiguration(hash: hash)) {
|
||||
transaction.putItemCacheEntry(id: ItemCacheEntryId(collectionId: Namespaces.CachedItemCollection.cachedWallpapersConfiguration, key: ValueBoxKey(length: 0)), entry: entry, collectionSpec: ItemCacheCollectionSpec(lowWaterItemCount: 1, highWaterItemCount: 1))
|
||||
transaction.putItemCacheEntry(id: ItemCacheEntryId(collectionId: Namespaces.CachedItemCollection.cachedWallpapersConfiguration, key: ValueBoxKey(length: 0)), entry: entry)
|
||||
}
|
||||
return items
|
||||
}
|
||||
|
@ -893,7 +893,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
if let timestamp = timestamp {
|
||||
storedState = MediaPlaybackStoredState(timestamp: timestamp, playbackRate: AudioPlaybackRate(playbackRate))
|
||||
}
|
||||
let _ = updateMediaPlaybackStoredStateInteractively(postbox: strongSelf.context.account.postbox, messageId: messageId, state: storedState).start()
|
||||
let _ = updateMediaPlaybackStoredStateInteractively(engine: strongSelf.context.engine, messageId: messageId, state: storedState).start()
|
||||
}, editMedia: { [weak self] messageId, snapshots, transitionCompletion in
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
@ -6517,7 +6517,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
}, deleteSelectedMessages: { [weak self] in
|
||||
if let strongSelf = self {
|
||||
if let messageIds = strongSelf.presentationInterfaceState.interfaceState.selectionState?.selectedIds, !messageIds.isEmpty {
|
||||
strongSelf.messageContextDisposable.set((strongSelf.context.sharedContext.chatAvailableMessageActions(postbox: strongSelf.context.account.postbox, accountPeerId: strongSelf.context.account.peerId, messageIds: messageIds)
|
||||
strongSelf.messageContextDisposable.set((strongSelf.context.sharedContext.chatAvailableMessageActions(engine: strongSelf.context.engine, accountPeerId: strongSelf.context.account.peerId, messageIds: messageIds)
|
||||
|> deliverOnMainQueue).start(next: { actions in
|
||||
if let strongSelf = self, !actions.options.isEmpty {
|
||||
if let banAuthor = actions.banAuthor {
|
||||
@ -6633,7 +6633,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
}, deleteMessages: { [weak self] messages, contextController, completion in
|
||||
if let strongSelf = self, !messages.isEmpty {
|
||||
let messageIds = Set(messages.map { $0.id })
|
||||
strongSelf.messageContextDisposable.set((strongSelf.context.sharedContext.chatAvailableMessageActions(postbox: strongSelf.context.account.postbox, accountPeerId: strongSelf.context.account.peerId, messageIds: messageIds)
|
||||
strongSelf.messageContextDisposable.set((strongSelf.context.sharedContext.chatAvailableMessageActions(engine: strongSelf.context.engine, accountPeerId: strongSelf.context.account.peerId, messageIds: messageIds)
|
||||
|> deliverOnMainQueue).start(next: { actions in
|
||||
if let strongSelf = self, !actions.options.isEmpty {
|
||||
if let banAuthor = actions.banAuthor {
|
||||
@ -7968,20 +7968,14 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
}
|
||||
if let stickerFile = stickerFile {
|
||||
let context = strongSelf.context
|
||||
let _ = (context.account.postbox.transaction { transaction -> Signal<(SavedStickerResult, Bool), AddSavedStickerError> in
|
||||
let isSaved: Bool
|
||||
if getIsStickerSaved(transaction: transaction, fileId: stickerFile.fileId) {
|
||||
isSaved = true
|
||||
} else {
|
||||
isSaved = false
|
||||
}
|
||||
let _ = (context.engine.stickers.isStickerSaved(id: stickerFile.fileId)
|
||||
|> castError(AddSavedStickerError.self)
|
||||
|> mapToSignal { isSaved -> Signal<(SavedStickerResult, Bool), AddSavedStickerError> in
|
||||
return context.engine.stickers.toggleStickerSaved(file: stickerFile, saved: !isSaved)
|
||||
|> map { result -> (SavedStickerResult, Bool) in
|
||||
return (result, !isSaved)
|
||||
}
|
||||
}
|
||||
|> castError(AddSavedStickerError.self)
|
||||
|> switchToLatest
|
||||
|> deliverOnMainQueue).start(next: { [weak self] result, added in
|
||||
if let strongSelf = self {
|
||||
switch result {
|
||||
@ -8185,9 +8179,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
})
|
||||
})
|
||||
})
|
||||
let _ = (strongSelf.context.account.postbox.transaction { transaction -> Void in
|
||||
updatePeerGroupIdInteractively(transaction: transaction, peerId: peerId, groupId: .root)
|
||||
}
|
||||
let _ = (strongSelf.context.engine.peers.updatePeersGroupIdInteractively(peerIds: [peerId], groupId: .root)
|
||||
|> deliverOnMainQueue).start()
|
||||
}, openLinkEditing: { [weak self] in
|
||||
if let strongSelf = self {
|
||||
@ -15068,9 +15060,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
strongSelf.updateChatPresentationInterfaceState(animated: true, interactive: true, { $0.updatedInterfaceState { $0.withoutSelectionState() } })
|
||||
if actions.contains(3) {
|
||||
let context = strongSelf.context
|
||||
let _ = context.account.postbox.transaction({ transaction -> Void in
|
||||
context.engine.messages.deleteAllMessagesWithAuthor(transaction: transaction, peerId: peerId, authorId: author.id, namespace: Namespaces.Message.Cloud)
|
||||
}).start()
|
||||
let _ = context.engine.messages.deleteAllMessagesWithAuthor(peerId: peerId, authorId: author.id, namespace: Namespaces.Message.Cloud).start()
|
||||
let _ = strongSelf.context.engine.messages.clearAuthorHistory(peerId: peerId, memberId: author.id).start()
|
||||
} else if actions.contains(0) {
|
||||
let _ = strongSelf.context.engine.messages.deleteMessagesInteractively(messageIds: Array(messageIds), type: .forEveryone).start()
|
||||
|
@ -1583,129 +1583,6 @@ public final class ChatHistoryListNode: ListView, ChatHistoryNode {
|
||||
self.loadStateUpdated = f
|
||||
}
|
||||
|
||||
/*private func updateHistoryScrollingArea(transition: ContainedViewLayoutTransition) {
|
||||
guard let historyScrollingArea = self.historyScrollingArea else {
|
||||
return
|
||||
}
|
||||
guard let transactionState = self.opaqueTransactionState as? ChatHistoryTransactionOpaqueState else {
|
||||
return
|
||||
}
|
||||
|
||||
let historyView = transactionState.historyView
|
||||
|
||||
var updatedScrollingState = self.scrollingState
|
||||
if var scrollingState = updatedScrollingState {
|
||||
let convertedIndex = historyView.filteredEntries.count - scrollingState.topItem.index - 1
|
||||
if convertedIndex < 0 || convertedIndex >= historyView.filteredEntries.count {
|
||||
return
|
||||
}
|
||||
let firstItem = historyView.filteredEntries[convertedIndex]
|
||||
var location: MessageHistoryEntryLocation?
|
||||
switch firstItem {
|
||||
case let .MessageEntry(_, _, _, locationValue, _, _):
|
||||
location = locationValue
|
||||
case let .MessageGroupEntry(_, group, _):
|
||||
if let locationValue = group.last?.4 {
|
||||
location = locationValue
|
||||
}
|
||||
default:
|
||||
break
|
||||
}
|
||||
|
||||
if let location = location {
|
||||
let locationDelta = (location.count - location.index - 1) - scrollingState.topItem.index
|
||||
scrollingState.topItem.index += locationDelta
|
||||
scrollingState.bottomItem.index += locationDelta
|
||||
scrollingState.itemCount = max(scrollingState.itemCount, location.count)
|
||||
}
|
||||
|
||||
updatedScrollingState = scrollingState
|
||||
}
|
||||
|
||||
historyScrollingArea.update(
|
||||
containerSize: self.bounds.size,
|
||||
containerInsets: UIEdgeInsets(top: self.scrollIndicatorInsets.top, left: 0.0, bottom: self.scrollIndicatorInsets.bottom, right: 0.0),
|
||||
scrollingState: updatedScrollingState,
|
||||
isScrolling: self.isDragging || self.isDeceleratingAfterTracking,
|
||||
theme: self.currentPresentationData.theme.theme,
|
||||
transition: transition
|
||||
)
|
||||
}
|
||||
|
||||
private func navigateToAbsolutePosition(position: Float) {
|
||||
guard let transactionState = self.opaqueTransactionState as? ChatHistoryTransactionOpaqueState else {
|
||||
return
|
||||
}
|
||||
|
||||
let historyView = transactionState.historyView
|
||||
|
||||
let convertedIndex = 0
|
||||
if convertedIndex < 0 || convertedIndex >= historyView.filteredEntries.count {
|
||||
self.historyScrollingArea?.resetNavigatingToPosition()
|
||||
return
|
||||
}
|
||||
let firstItem = historyView.filteredEntries[convertedIndex]
|
||||
var location: MessageHistoryEntryLocation?
|
||||
switch firstItem {
|
||||
case let .MessageEntry(_, _, _, locationValue, _, _):
|
||||
location = locationValue
|
||||
case let .MessageGroupEntry(_, group, _):
|
||||
if let locationValue = group.last?.4 {
|
||||
location = locationValue
|
||||
}
|
||||
default:
|
||||
break
|
||||
}
|
||||
|
||||
if let location = location {
|
||||
var absoluteIndex = Int(Float(location.count) * position)
|
||||
if absoluteIndex >= location.count {
|
||||
absoluteIndex = location.count - 1
|
||||
}
|
||||
if absoluteIndex < 0 {
|
||||
absoluteIndex = 0
|
||||
}
|
||||
if case let .peer(peerId) = self.chatLocation {
|
||||
let _ = (self.context.account.postbox.transaction { transaction -> MessageIndex? in
|
||||
return transaction.findMessageAtAbsoluteIndex(peerId: peerId, namespace: Namespaces.Message.Cloud, index: absoluteIndex)
|
||||
}
|
||||
|> deliverOnMainQueue).start(next: { [weak self] index in
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
if let index = index {
|
||||
let content: ChatHistoryLocation = .Scroll(index: .message(index), anchorIndex: .message(index), sourceIndex: .message(index), scrollPosition: .top(0.0), animated: false, highlight: false)
|
||||
|
||||
strongSelf.scrollNavigationDisposable.set((preloadedChatHistoryViewForLocation(ChatHistoryLocationInput(content: content, id: 0), context: strongSelf.context, chatLocation: strongSelf.chatLocation, subject: strongSelf.subject, chatLocationContextHolder: strongSelf.chatLocationContextHolder, fixedCombinedReadStates: nil, tagMask: nil, additionalData: [])
|
||||
|> map { historyView -> Bool in
|
||||
switch historyView {
|
||||
case .Loading:
|
||||
return false
|
||||
case .HistoryView:
|
||||
return true
|
||||
}
|
||||
}
|
||||
|> filter { $0 }
|
||||
|> take(1)
|
||||
|> deliverOnMainQueue).start(next: { _ in
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
strongSelf.chatHistoryLocationValue = ChatHistoryLocationInput(content: content, id: (strongSelf.chatHistoryLocationValue?.id).flatMap({ $0 + 1 }) ?? 0)
|
||||
Queue.mainQueue().after(0.5, {
|
||||
self?.historyScrollingArea?.resetNavigatingToPosition()
|
||||
})
|
||||
}))
|
||||
} else {
|
||||
strongSelf.historyScrollingArea?.resetNavigatingToPosition()
|
||||
}
|
||||
})
|
||||
}
|
||||
} else {
|
||||
self.historyScrollingArea?.resetNavigatingToPosition()
|
||||
}
|
||||
}*/
|
||||
|
||||
private func maybeUpdateOverscrollAction(offset: CGFloat?) {
|
||||
if self.freezeOverscrollControl {
|
||||
return
|
||||
@ -2304,7 +2181,7 @@ public final class ChatHistoryListNode: ListView, ChatHistoryNode {
|
||||
if historyView.originalView.laterId == nil {
|
||||
for entry in historyView.filteredEntries.reversed() {
|
||||
if case let .MessageEntry(message, _, _, _, _, _) = entry {
|
||||
if canEditMessage(context: context, limitsConfiguration: context.currentLimitsConfiguration.with { $0 }, message: message) {
|
||||
if canEditMessage(context: context, limitsConfiguration: context.currentLimitsConfiguration.with { EngineConfiguration.Limits($0) }, message: message) {
|
||||
return message
|
||||
}
|
||||
}
|
||||
|
@ -42,11 +42,11 @@ private struct MessageContextMenuData {
|
||||
let messageActions: ChatAvailableMessageActions
|
||||
}
|
||||
|
||||
func canEditMessage(context: AccountContext, limitsConfiguration: LimitsConfiguration, message: Message) -> Bool {
|
||||
func canEditMessage(context: AccountContext, limitsConfiguration: EngineConfiguration.Limits, message: Message) -> Bool {
|
||||
return canEditMessage(accountPeerId: context.account.peerId, limitsConfiguration: limitsConfiguration, message: message)
|
||||
}
|
||||
|
||||
private func canEditMessage(accountPeerId: PeerId, limitsConfiguration: LimitsConfiguration, message: Message, reschedule: Bool = false) -> Bool {
|
||||
private func canEditMessage(accountPeerId: PeerId, limitsConfiguration: EngineConfiguration.Limits, message: Message, reschedule: Bool = false) -> Bool {
|
||||
var hasEditRights = false
|
||||
var unlimitedInterval = reschedule
|
||||
|
||||
@ -153,7 +153,7 @@ private func canEditMessage(accountPeerId: PeerId, limitsConfiguration: LimitsCo
|
||||
}
|
||||
|
||||
if !hasUneditableAttributes || reschedule {
|
||||
if canPerformEditingActions(limits: limitsConfiguration, accountPeerId: accountPeerId, message: message, unlimitedInterval: unlimitedInterval) {
|
||||
if canPerformEditingActions(limits: limitsConfiguration._asLimits(), accountPeerId: accountPeerId, message: message, unlimitedInterval: unlimitedInterval) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
@ -161,7 +161,7 @@ private func canEditMessage(accountPeerId: PeerId, limitsConfiguration: LimitsCo
|
||||
return false
|
||||
}
|
||||
|
||||
private func canViewReadStats(message: Message, cachedData: CachedPeerData?, isMessageRead: Bool, appConfig: AppConfiguration) -> Bool {
|
||||
private func canViewReadStats(message: Message, participantCount: Int?, isMessageRead: Bool, appConfig: AppConfiguration) -> Bool {
|
||||
guard let peer = message.peers[message.id.peerId] else {
|
||||
return false
|
||||
}
|
||||
@ -210,12 +210,8 @@ private func canViewReadStats(message: Message, cachedData: CachedPeerData?, isM
|
||||
case let channel as TelegramChannel:
|
||||
if case .broadcast = channel.info {
|
||||
return false
|
||||
} else if let cachedData = cachedData as? CachedChannelData {
|
||||
if let memberCount = cachedData.participantsSummary.memberCount {
|
||||
if Int(memberCount) > maxParticipantCount {
|
||||
return false
|
||||
}
|
||||
} else {
|
||||
} else if let participantCount = participantCount {
|
||||
if participantCount > maxParticipantCount {
|
||||
return false
|
||||
}
|
||||
} else {
|
||||
@ -555,36 +551,47 @@ func contextMenuForChatPresentationInterfaceState(chatPresentationInterfaceState
|
||||
|> map(Optional.init)
|
||||
}
|
||||
|
||||
let loadLimits = context.account.postbox.transaction { transaction -> (LimitsConfiguration, AppConfiguration) in
|
||||
let limitsConfiguration = transaction.getPreferencesEntry(key: PreferencesKeys.limitsConfiguration)?.get(LimitsConfiguration.self) ?? LimitsConfiguration.defaultValue
|
||||
let appConfig = transaction.getPreferencesEntry(key: PreferencesKeys.appConfiguration)?.get(AppConfiguration.self) ?? AppConfiguration.defaultValue
|
||||
return (limitsConfiguration, appConfig)
|
||||
let loadLimits = context.engine.data.get(
|
||||
TelegramEngine.EngineData.Item.Configuration.Limits(),
|
||||
TelegramEngine.EngineData.Item.Configuration.App()
|
||||
)
|
||||
|
||||
struct InfoSummaryData {
|
||||
var linkedDiscusionPeerId: EnginePeerCachedInfoItem<EnginePeer.Id?>
|
||||
var canViewStats: Bool
|
||||
var participantCount: Int?
|
||||
}
|
||||
|
||||
let cachedData = context.account.postbox.transaction { transaction -> CachedPeerData? in
|
||||
return transaction.getPeerCachedData(peerId: messages[0].id.peerId)
|
||||
let infoSummaryData = context.engine.data.get(
|
||||
TelegramEngine.EngineData.Item.Peer.LinkedDiscussionPeerId(id: messages[0].id.peerId),
|
||||
TelegramEngine.EngineData.Item.Peer.CanViewStats(id: messages[0].id.peerId),
|
||||
TelegramEngine.EngineData.Item.Peer.ParticipantCount(id: messages[0].id.peerId)
|
||||
)
|
||||
|> map { linkedDiscusionPeerId, canViewStats, participantCount -> InfoSummaryData in
|
||||
return InfoSummaryData(
|
||||
linkedDiscusionPeerId: linkedDiscusionPeerId,
|
||||
canViewStats: canViewStats,
|
||||
participantCount: participantCount
|
||||
)
|
||||
}
|
||||
|
||||
//let readState = context.engine.data.get(TelegramEngine.EngineData.Item.Messages.PeerUnreadCount)
|
||||
let readState = context.account.postbox.transaction { transaction -> CombinedPeerReadState? in
|
||||
return transaction.getCombinedPeerReadState(messages[0].id.peerId)
|
||||
}
|
||||
let readState = context.engine.data.get(TelegramEngine.EngineData.Item.Messages.ReadState(id: messages[0].id.peerId))
|
||||
|
||||
let dataSignal: Signal<(MessageContextMenuData, [MessageId: ChatUpdatingMessageMedia], CachedPeerData?, AppConfiguration, Bool, Int32, AvailableReactions?, TranslationSettings, LoggingSettings, NotificationSoundList?), NoError> = combineLatest(
|
||||
let dataSignal: Signal<(MessageContextMenuData, [MessageId: ChatUpdatingMessageMedia], InfoSummaryData, AppConfiguration, Bool, Int32, AvailableReactions?, TranslationSettings, LoggingSettings, NotificationSoundList?), NoError> = combineLatest(
|
||||
loadLimits,
|
||||
loadStickerSaveStatusSignal,
|
||||
loadResourceStatusSignal,
|
||||
context.sharedContext.chatAvailableMessageActions(postbox: context.account.postbox, accountPeerId: context.account.peerId, messageIds: Set(messages.map { $0.id })),
|
||||
context.sharedContext.chatAvailableMessageActions(engine: context.engine, accountPeerId: context.account.peerId, messageIds: Set(messages.map { $0.id })),
|
||||
context.account.pendingUpdateMessageManager.updatingMessageMedia
|
||||
|> take(1),
|
||||
cachedData,
|
||||
infoSummaryData,
|
||||
readState,
|
||||
ApplicationSpecificNotice.getMessageViewsPrivacyTips(accountManager: context.sharedContext.accountManager),
|
||||
context.engine.stickers.availableReactions(),
|
||||
context.sharedContext.accountManager.sharedData(keys: [ApplicationSpecificSharedDataKeys.translationSettings, SharedDataKeys.loggingSettings]),
|
||||
context.engine.peers.notificationSoundList() |> take(1)
|
||||
)
|
||||
|> map { limitsAndAppConfig, stickerSaveStatus, resourceStatus, messageActions, updatingMessageMedia, cachedData, readState, messageViewsPrivacyTips, availableReactions, sharedData, notificationSoundList -> (MessageContextMenuData, [MessageId: ChatUpdatingMessageMedia], CachedPeerData?, AppConfiguration, Bool, Int32, AvailableReactions?, TranslationSettings, LoggingSettings, NotificationSoundList?) in
|
||||
|> map { limitsAndAppConfig, stickerSaveStatus, resourceStatus, messageActions, updatingMessageMedia, infoSummaryData, readState, messageViewsPrivacyTips, availableReactions, sharedData, notificationSoundList -> (MessageContextMenuData, [MessageId: ChatUpdatingMessageMedia], InfoSummaryData, AppConfiguration, Bool, Int32, AvailableReactions?, TranslationSettings, LoggingSettings, NotificationSoundList?) in
|
||||
let (limitsConfiguration, appConfig) = limitsAndAppConfig
|
||||
var canEdit = false
|
||||
if !isAction {
|
||||
@ -611,12 +618,12 @@ func contextMenuForChatPresentationInterfaceState(chatPresentationInterfaceState
|
||||
loggingSettings = LoggingSettings.defaultSettings
|
||||
}
|
||||
|
||||
return (MessageContextMenuData(starStatus: stickerSaveStatus, canReply: canReply, canPin: canPin, canEdit: canEdit, canSelect: canSelect, resourceStatus: resourceStatus, messageActions: messageActions), updatingMessageMedia, cachedData, appConfig, isMessageRead, messageViewsPrivacyTips, availableReactions, translationSettings, loggingSettings, notificationSoundList)
|
||||
return (MessageContextMenuData(starStatus: stickerSaveStatus, canReply: canReply, canPin: canPin, canEdit: canEdit, canSelect: canSelect, resourceStatus: resourceStatus, messageActions: messageActions), updatingMessageMedia, infoSummaryData, appConfig, isMessageRead, messageViewsPrivacyTips, availableReactions, translationSettings, loggingSettings, notificationSoundList)
|
||||
}
|
||||
|
||||
return dataSignal
|
||||
|> deliverOnMainQueue
|
||||
|> map { data, updatingMessageMedia, cachedData, appConfig, isMessageRead, messageViewsPrivacyTips, availableReactions, translationSettings, loggingSettings, notificationSoundList -> ContextController.Items in
|
||||
|> map { data, updatingMessageMedia, infoSummaryData, appConfig, isMessageRead, messageViewsPrivacyTips, availableReactions, translationSettings, loggingSettings, notificationSoundList -> ContextController.Items in
|
||||
var actions: [ContextMenuItem] = []
|
||||
|
||||
var isPinnedMessages = false
|
||||
@ -988,7 +995,7 @@ func contextMenuForChatPresentationInterfaceState(chatPresentationInterfaceState
|
||||
var threadId: Int64?
|
||||
var threadMessageCount: Int = 0
|
||||
if case .peer = chatPresentationInterfaceState.chatLocation, let channel = chatPresentationInterfaceState.renderedPeer?.peer as? TelegramChannel, case .group = channel.info {
|
||||
if let cachedData = cachedData as? CachedChannelData, case let .known(maybeValue) = cachedData.linkedDiscussionPeerId, let _ = maybeValue {
|
||||
if case let .known(maybeValue) = infoSummaryData.linkedDiscusionPeerId, let _ = maybeValue {
|
||||
if let value = messages[0].threadId {
|
||||
threadId = value
|
||||
} else {
|
||||
@ -1265,7 +1272,7 @@ func contextMenuForChatPresentationInterfaceState(chatPresentationInterfaceState
|
||||
}
|
||||
}
|
||||
|
||||
if let cachedData = cachedData as? CachedChannelData, cachedData.flags.contains(.canViewStats), views >= 100 {
|
||||
if infoSummaryData.canViewStats, views >= 100 {
|
||||
actions.append(.action(ContextMenuActionItem(text: chatPresentationInterfaceState.strings.Conversation_ContextViewStats, icon: { theme in
|
||||
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Statistics"), color: theme.actionSheet.primaryTextColor)
|
||||
}, action: { c, _ in
|
||||
@ -1359,7 +1366,7 @@ func contextMenuForChatPresentationInterfaceState(chatPresentationInterfaceState
|
||||
}
|
||||
}
|
||||
|
||||
let canViewStats = canViewReadStats(message: message, cachedData: cachedData, isMessageRead: isMessageRead, appConfig: appConfig)
|
||||
let canViewStats = canViewReadStats(message: message, participantCount: infoSummaryData.participantCount, isMessageRead: isMessageRead, appConfig: appConfig)
|
||||
var reactionCount = 0
|
||||
for reaction in mergedMessageReactionsAndPeers(message: message).reactions {
|
||||
reactionCount += Int(reaction.count)
|
||||
@ -1467,9 +1474,13 @@ private func canPerformDeleteActions(limits: LimitsConfiguration, accountPeerId:
|
||||
return false
|
||||
}
|
||||
|
||||
func chatAvailableMessageActionsImpl(postbox: Postbox, accountPeerId: PeerId, messageIds: Set<MessageId>, messages: [MessageId: Message] = [:], peers: [PeerId: Peer] = [:]) -> Signal<ChatAvailableMessageActions, NoError> {
|
||||
return postbox.transaction { transaction -> ChatAvailableMessageActions in
|
||||
let limitsConfiguration: LimitsConfiguration = transaction.getPreferencesEntry(key: PreferencesKeys.limitsConfiguration)?.get(LimitsConfiguration.self) ?? LimitsConfiguration.defaultValue
|
||||
func chatAvailableMessageActionsImpl(engine: TelegramEngine, accountPeerId: PeerId, messageIds: Set<MessageId>, messages: [MessageId: Message] = [:], peers: [PeerId: Peer] = [:]) -> Signal<ChatAvailableMessageActions, NoError> {
|
||||
return engine.data.get(
|
||||
TelegramEngine.EngineData.Item.Configuration.Limits(),
|
||||
EngineDataMap(Set(messageIds.map(\.peerId)).map(TelegramEngine.EngineData.Item.Peer.Peer.init)),
|
||||
EngineDataMap(Set(messageIds).map(TelegramEngine.EngineData.Item.Messages.Message.init))
|
||||
)
|
||||
|> map { limitsConfiguration, peerMap, messageMap -> ChatAvailableMessageActions in
|
||||
var optionsMap: [MessageId: ChatAvailableMessageActionOptions] = [:]
|
||||
var banPeer: Peer?
|
||||
var hadPersonalIncoming = false
|
||||
@ -1478,8 +1489,8 @@ func chatAvailableMessageActionsImpl(postbox: Postbox, accountPeerId: PeerId, me
|
||||
var isCopyProtected = false
|
||||
|
||||
func getPeer(_ peerId: PeerId) -> Peer? {
|
||||
if let peer = transaction.getPeer(peerId) {
|
||||
return peer
|
||||
if let maybePeer = peerMap[peerId], let peer = maybePeer {
|
||||
return peer._asPeer()
|
||||
} else if let peer = peers[peerId] {
|
||||
return peer
|
||||
} else {
|
||||
@ -1488,8 +1499,8 @@ func chatAvailableMessageActionsImpl(postbox: Postbox, accountPeerId: PeerId, me
|
||||
}
|
||||
|
||||
func getMessage(_ messageId: MessageId) -> Message? {
|
||||
if let message = transaction.getMessage(messageId) {
|
||||
return message
|
||||
if let maybeMessage = messageMap[messageId], let message = maybeMessage {
|
||||
return message._asMessage()
|
||||
} else if let message = messages[messageId] {
|
||||
return message
|
||||
} else {
|
||||
@ -1638,7 +1649,7 @@ func chatAvailableMessageActionsImpl(postbox: Postbox, accountPeerId: PeerId, me
|
||||
}
|
||||
optionsMap[id]!.insert(.deleteLocally)
|
||||
var canDeleteGlobally = false
|
||||
if canPerformDeleteActions(limits: limitsConfiguration, accountPeerId: accountPeerId, message: message) {
|
||||
if canPerformDeleteActions(limits: limitsConfiguration._asLimits(), accountPeerId: accountPeerId, message: message) {
|
||||
canDeleteGlobally = true
|
||||
} else if limitsConfiguration.canRemoveIncomingMessagesInPrivateChats {
|
||||
canDeleteGlobally = true
|
||||
|
@ -928,9 +928,7 @@ final class ChatMediaInputNode: ChatInputNode {
|
||||
var items: [ActionSheetItem] = []
|
||||
items.append(ActionSheetButtonItem(title: strongSelf.strings.Stickers_ClearRecent, color: .destructive, action: { [weak actionSheet] in
|
||||
actionSheet?.dismissAnimated()
|
||||
let _ = (context.account.postbox.transaction { transaction in
|
||||
clearRecentlyUsedStickers(transaction: transaction)
|
||||
}).start()
|
||||
let _ = context.engine.stickers.clearRecentlyUsedStickers().start()
|
||||
}))
|
||||
actionSheet.setItemGroups([ActionSheetItemGroup(items: items), ActionSheetItemGroup(items: [
|
||||
ActionSheetButtonItem(title: strongSelf.strings.Common_Cancel, color: .accent, font: .bold, action: { [weak actionSheet] in
|
||||
@ -1407,16 +1405,15 @@ final class ChatMediaInputNode: ChatInputNode {
|
||||
canSaveGif = false
|
||||
}
|
||||
|
||||
let _ = (self.context.account.postbox.transaction { transaction -> Bool in
|
||||
if !canSaveGif {
|
||||
return false
|
||||
}
|
||||
return isGifSaved(transaction: transaction, mediaId: file.file.media.fileId)
|
||||
}
|
||||
let _ = (self.context.engine.stickers.isGifSaved(id: file.file.media.fileId)
|
||||
|> deliverOnMainQueue).start(next: { [weak self] isGifSaved in
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
var isGifSaved = isGifSaved
|
||||
if !canSaveGif {
|
||||
isGifSaved = false
|
||||
}
|
||||
let presentationData = strongSelf.context.sharedContext.currentPresentationData.with { $0 }
|
||||
|
||||
let message = Message(stableId: 0, stableVersion: 0, id: MessageId(peerId: PeerId(0), namespace: Namespaces.Message.Local, id: 0), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 0, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: nil, text: "", attributes: [], media: [file.file.media], peers: SimpleDictionary(), associatedMessages: SimpleDictionary(), associatedMessageIds: [])
|
||||
@ -1530,9 +1527,7 @@ final class ChatMediaInputNode: ChatInputNode {
|
||||
|
||||
if let (itemNode, item) = searchContainerNode.itemAt(point: point.offsetBy(dx: -searchContainerNode.frame.minX, dy: -searchContainerNode.frame.minY)) {
|
||||
if let item = item as? StickerPreviewPeekItem {
|
||||
return strongSelf.context.account.postbox.transaction { transaction -> Bool in
|
||||
return getIsStickerSaved(transaction: transaction, fileId: item.file.fileId)
|
||||
}
|
||||
return strongSelf.context.engine.stickers.isStickerSaved(id: item.file.fileId)
|
||||
|> deliverOnMainQueue
|
||||
|> map { isStarred -> (ASDisplayNode, PeekControllerContent)? in
|
||||
if let strongSelf = self {
|
||||
|
@ -292,9 +292,7 @@ final class ChatMessageInteractiveFileNode: ASDisplayNode {
|
||||
switch resourceStatus.mediaStatus {
|
||||
case let .fetchStatus(fetchStatus):
|
||||
if let context = self.context, let message = self.message, message.flags.isSending {
|
||||
let _ = context.account.postbox.transaction({ transaction -> Void in
|
||||
context.engine.messages.deleteMessages(transaction: transaction, ids: [message.id])
|
||||
}).start()
|
||||
let _ = context.engine.messages.deleteMessagesInteractively(messageIds: [message.id], type: .forEveryone).start()
|
||||
} else {
|
||||
switch fetchStatus {
|
||||
case .Fetching:
|
||||
|
@ -846,10 +846,7 @@ class ChatMessageInteractiveInstantVideoNode: ASDisplayNode {
|
||||
switch fetchStatus {
|
||||
case .Fetching:
|
||||
if item.message.flags.isSending {
|
||||
let messageId = item.message.id
|
||||
let _ = item.context.account.postbox.transaction({ transaction -> Void in
|
||||
item.context.engine.messages.deleteMessages(transaction: transaction, ids: [messageId])
|
||||
}).start()
|
||||
let _ = item.context.engine.messages.deleteMessagesInteractively(messageIds: [item.message.id], type: .forEveryone).start()
|
||||
} else {
|
||||
messageMediaFileCancelInteractiveFetch(context: item.context, messageId: item.message.id, file: file)
|
||||
}
|
||||
|
@ -307,9 +307,7 @@ final class ChatMessageInteractiveMediaNode: ASDisplayNode, GalleryItemTransitio
|
||||
switch fetchStatus {
|
||||
case .Fetching:
|
||||
if let context = self.context, let message = self.message, message.flags.isSending {
|
||||
let _ = context.account.postbox.transaction({ transaction -> Void in
|
||||
context.engine.messages.deleteMessages(transaction: transaction, ids: [message.id])
|
||||
}).start()
|
||||
let _ = context.engine.messages.deleteMessagesInteractively(messageIds: [message.id], type: .forEveryone).start()
|
||||
} else if let media = media, let context = self.context, let message = message {
|
||||
if let media = media as? TelegramMediaFile {
|
||||
messageMediaFileCancelInteractiveFetch(context: context, messageId: message.id, file: media)
|
||||
|
@ -38,7 +38,7 @@ final class ChatMessageSelectionInputPanelNode: ChatInputPanelNode {
|
||||
}
|
||||
self.canDeleteMessagesDisposable.set(nil)
|
||||
} else if let context = self.context {
|
||||
self.canDeleteMessagesDisposable.set((context.sharedContext.chatAvailableMessageActions(postbox: context.account.postbox, accountPeerId: context.account.peerId, messageIds: self.selectedMessages)
|
||||
self.canDeleteMessagesDisposable.set((context.sharedContext.chatAvailableMessageActions(engine: context.engine, accountPeerId: context.account.peerId, messageIds: self.selectedMessages)
|
||||
|> deliverOnMainQueue).start(next: { [weak self] actions in
|
||||
if let strongSelf = self {
|
||||
strongSelf.actions = actions
|
||||
|
@ -117,11 +117,10 @@ class ContactMultiselectionControllerImpl: ViewController, ContactMultiselection
|
||||
}
|
||||
})
|
||||
|
||||
self.limitsConfigurationDisposable = (context.account.postbox.transaction { transaction -> LimitsConfiguration in
|
||||
return currentLimitsConfiguration(transaction: transaction)
|
||||
} |> deliverOnMainQueue).start(next: { [weak self] value in
|
||||
self.limitsConfigurationDisposable = (context.engine.data.get(TelegramEngine.EngineData.Item.Configuration.Limits())
|
||||
|> deliverOnMainQueue).start(next: { [weak self] value in
|
||||
if let strongSelf = self {
|
||||
strongSelf.limitsConfiguration = value
|
||||
strongSelf.limitsConfiguration = value._asLimits()
|
||||
strongSelf.updateTitle()
|
||||
strongSelf._limitsReady.set(.single(true))
|
||||
}
|
||||
|
@ -326,9 +326,7 @@ private final class DrawingStickersScreenNode: ViewControllerTracingNode {
|
||||
var items: [ActionSheetItem] = []
|
||||
items.append(ActionSheetButtonItem(title: strongSelf.presentationData.strings.Stickers_ClearRecent, color: .destructive, action: { [weak actionSheet] in
|
||||
actionSheet?.dismissAnimated()
|
||||
let _ = (context.account.postbox.transaction { transaction in
|
||||
clearRecentlyUsedStickers(transaction: transaction)
|
||||
}).start()
|
||||
let _ = context.engine.stickers.clearRecentlyUsedStickers().start()
|
||||
}))
|
||||
actionSheet.setItemGroups([ActionSheetItemGroup(items: items), ActionSheetItemGroup(items: [
|
||||
ActionSheetButtonItem(title: strongSelf.presentationData.strings.Common_Cancel, color: .accent, font: .bold, action: { [weak actionSheet] in
|
||||
@ -441,9 +439,7 @@ private final class DrawingStickersScreenNode: ViewControllerTracingNode {
|
||||
var items: [ActionSheetItem] = []
|
||||
items.append(ActionSheetButtonItem(title: strongSelf.presentationData.strings.Stickers_ClearRecent, color: .destructive, action: { [weak actionSheet] in
|
||||
actionSheet?.dismissAnimated()
|
||||
let _ = (context.account.postbox.transaction { transaction in
|
||||
clearRecentlyUsedStickers(transaction: transaction)
|
||||
}).start()
|
||||
let _ = context.engine.stickers.clearRecentlyUsedStickers().start()
|
||||
}))
|
||||
actionSheet.setItemGroups([ActionSheetItemGroup(items: items), ActionSheetItemGroup(items: [
|
||||
ActionSheetButtonItem(title: strongSelf.presentationData.strings.Common_Cancel, color: .accent, font: .bold, action: { [weak actionSheet] in
|
||||
|
@ -476,9 +476,7 @@ private final class FeaturedStickersScreenNode: ViewControllerTracingNode {
|
||||
if let searchNode = strongSelf.searchNode, searchNode.isActive {
|
||||
if let (itemNode, item) = searchNode.itemAt(point: strongSelf.view.convert(point, to: searchNode.view)) {
|
||||
if let item = item as? StickerPreviewPeekItem {
|
||||
return strongSelf.context.account.postbox.transaction { transaction -> Bool in
|
||||
return getIsStickerSaved(transaction: transaction, fileId: item.file.fileId)
|
||||
}
|
||||
return strongSelf.context.engine.stickers.isStickerSaved(id: item.file.fileId)
|
||||
|> deliverOnMainQueue
|
||||
|> map { isStarred -> (ASDisplayNode, PeekControllerContent)? in
|
||||
if let strongSelf = self {
|
||||
@ -563,9 +561,7 @@ private final class FeaturedStickersScreenNode: ViewControllerTracingNode {
|
||||
|
||||
let itemNodeAndItem: (ASDisplayNode, StickerPackItem)? = strongSelf.itemAt(point: point)
|
||||
if let (itemNode, item) = itemNodeAndItem {
|
||||
return strongSelf.context.account.postbox.transaction { transaction -> Bool in
|
||||
return getIsStickerSaved(transaction: transaction, fileId: item.file.fileId)
|
||||
}
|
||||
return strongSelf.context.engine.stickers.isStickerSaved(id: item.file.fileId)
|
||||
|> deliverOnMainQueue
|
||||
|> map { isStarred -> (ASDisplayNode, PeekControllerContent)? in
|
||||
if let strongSelf = self {
|
||||
|
@ -25,11 +25,9 @@ class PaneGifSearchForQueryResult {
|
||||
}
|
||||
|
||||
func paneGifSearchForQuery(context: AccountContext, query: String, offset: String?, incompleteResults: Bool = false, staleCachedResults: Bool = false, delayRequest: Bool = true, updateActivity: ((Bool) -> Void)?) -> Signal<PaneGifSearchForQueryResult?, NoError> {
|
||||
let contextBot = context.account.postbox.transaction { transaction -> String in
|
||||
let configuration = currentSearchBotsConfiguration(transaction: transaction)
|
||||
return configuration.gifBotUsername ?? "gif"
|
||||
}
|
||||
|> mapToSignal { botName -> Signal<EnginePeer?, NoError> in
|
||||
let contextBot = context.engine.data.get(TelegramEngine.EngineData.Item.Configuration.SearchBots())
|
||||
|> mapToSignal { searchBots -> Signal<EnginePeer?, NoError> in
|
||||
let botName = searchBots.gifBotUsername ?? "gif"
|
||||
return context.engine.peers.resolvePeerByName(name: botName)
|
||||
}
|
||||
|> mapToSignal { peer -> Signal<(ChatPresentationInputQueryResult?, Bool, Bool), NoError> in
|
||||
|
@ -171,9 +171,7 @@ final class HorizontalStickersChatContextPanelNode: ChatInputContextPanelNode {
|
||||
}
|
||||
|
||||
if let itemNode = strongSelf.gridNode.itemNodeAtPoint(strongSelf.view.convert(point, to: strongSelf.gridNode.view)) as? HorizontalStickerGridItemNode, let item = itemNode.stickerItem {
|
||||
return strongSelf.context.account.postbox.transaction { transaction -> Bool in
|
||||
return getIsStickerSaved(transaction: transaction, fileId: item.file.fileId)
|
||||
}
|
||||
return strongSelf.context.engine.stickers.isStickerSaved(id: item.file.fileId)
|
||||
|> deliverOnMainQueue
|
||||
|> map { isStarred -> (ASDisplayNode, PeekControllerContent)? in
|
||||
if let strongSelf = self, let controllerInteraction = strongSelf.controllerInteraction {
|
||||
|
@ -99,9 +99,7 @@ private final class InlineReactionSearchStickersNode: ASDisplayNode, UIScrollVie
|
||||
}
|
||||
|
||||
if let itemNode = selectedNode, let item = itemNode.stickerItem {
|
||||
return strongSelf.context.account.postbox.transaction { transaction -> Bool in
|
||||
return getIsStickerSaved(transaction: transaction, fileId: item.file.fileId)
|
||||
}
|
||||
return strongSelf.context.engine.stickers.isStickerSaved(id: item.file.fileId)
|
||||
|> deliverOnMainQueue
|
||||
|> map { isStarred -> (ASDisplayNode, PeekControllerContent)? in
|
||||
if let strongSelf = self, let controllerInteraction = strongSelf.getControllerInteraction?() {
|
||||
|
@ -434,7 +434,7 @@ public final class MediaManagerImpl: NSObject, MediaManager {
|
||||
if state.status.timestamp > 5.0 && state.status.timestamp < state.status.duration - 5.0 {
|
||||
storedState = MediaPlaybackStoredState(timestamp: state.status.timestamp, playbackRate: state.status.baseRate > 1.0 ? .x2 : .x1)
|
||||
}
|
||||
let _ = updateMediaPlaybackStoredStateInteractively(postbox: account.postbox, messageId: item.message.id, state: storedState).start()
|
||||
let _ = updateMediaPlaybackStoredStateInteractively(engine: TelegramEngine(account: account), messageId: item.message.id, state: storedState).start()
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -487,7 +487,7 @@ public final class MediaManagerImpl: NSObject, MediaManager {
|
||||
let settings = sharedData.entries[ApplicationSpecificSharedDataKeys.musicPlaybackSettings]?.get(MusicPlaybackSettings.self) ?? MusicPlaybackSettings.defaultSettings
|
||||
|
||||
if let location = playlist.location as? PeerMessagesPlaylistLocation, let messageId = location.messageId {
|
||||
return mediaPlaybackStoredState(postbox: account.postbox, messageId: messageId)
|
||||
return mediaPlaybackStoredState(engine: TelegramEngine(account: account), messageId: messageId)
|
||||
|> map { storedState in
|
||||
return (account, playlist, settings, storedState)
|
||||
}
|
||||
|
@ -1849,7 +1849,7 @@ final class PeerInfoVisualMediaPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScro
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
let _ = updateVisualMediaStoredState(postbox: strongSelf.context.account.postbox, peerId: strongSelf.peerId, messageTag: strongSelf.stateTag, state: VisualMediaStoredState(zoomLevel: Int32(zoomLevel.rawValue))).start()
|
||||
let _ = updateVisualMediaStoredState(engine: strongSelf.context.engine, peerId: strongSelf.peerId, messageTag: strongSelf.stateTag, state: VisualMediaStoredState(zoomLevel: Int32(zoomLevel.rawValue))).start()
|
||||
}
|
||||
|
||||
self._itemInteraction = VisualMediaItemInteraction(
|
||||
@ -1946,7 +1946,7 @@ final class PeerInfoVisualMediaPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScro
|
||||
strongSelf.itemGrid.cancelGestures()
|
||||
}
|
||||
|
||||
self.storedStateDisposable = (visualMediaStoredState(postbox: context.account.postbox, peerId: peerId, messageTag: self.stateTag)
|
||||
self.storedStateDisposable = (visualMediaStoredState(engine: context.engine, peerId: peerId, messageTag: self.stateTag)
|
||||
|> deliverOnMainQueue).start(next: { [weak self] value in
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
@ -2200,7 +2200,7 @@ final class PeerInfoVisualMediaPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScro
|
||||
func updateZoomLevel(level: ZoomLevel) {
|
||||
self.itemGrid.setZoomLevel(level: level.value)
|
||||
|
||||
let _ = updateVisualMediaStoredState(postbox: self.context.account.postbox, peerId: self.peerId, messageTag: self.stateTag, state: VisualMediaStoredState(zoomLevel: level.rawValue)).start()
|
||||
let _ = updateVisualMediaStoredState(engine: self.context.engine, peerId: self.peerId, messageTag: self.stateTag, state: VisualMediaStoredState(zoomLevel: level.rawValue)).start()
|
||||
}
|
||||
|
||||
func ensureMessageIsVisible(id: MessageId) {
|
||||
@ -2575,32 +2575,25 @@ final class VisualMediaStoredState: Codable {
|
||||
}
|
||||
}
|
||||
|
||||
func visualMediaStoredState(postbox: Postbox, peerId: PeerId, messageTag: MessageTags) -> Signal<VisualMediaStoredState?, NoError> {
|
||||
return postbox.transaction { transaction -> VisualMediaStoredState? in
|
||||
let key = ValueBoxKey(length: 8 + 4)
|
||||
key.setInt64(0, value: peerId.toInt64())
|
||||
key.setUInt32(8, value: messageTag.rawValue)
|
||||
if let entry = transaction.retrieveItemCacheEntry(id: ItemCacheEntryId(collectionId: ApplicationSpecificItemCacheCollectionId.visualMediaStoredState, key: key))?.get(VisualMediaStoredState.self) {
|
||||
return entry
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
func visualMediaStoredState(engine: TelegramEngine, peerId: PeerId, messageTag: MessageTags) -> Signal<VisualMediaStoredState?, NoError> {
|
||||
let key = ValueBoxKey(length: 8 + 4)
|
||||
key.setInt64(0, value: peerId.toInt64())
|
||||
key.setUInt32(8, value: messageTag.rawValue)
|
||||
|
||||
return engine.data.get(TelegramEngine.EngineData.Item.ItemCache.Item(collectionId: ApplicationSpecificItemCacheCollectionId.visualMediaStoredState, id: key))
|
||||
|> map { entry -> VisualMediaStoredState? in
|
||||
return entry?.get(VisualMediaStoredState.self)
|
||||
}
|
||||
}
|
||||
|
||||
private let collectionSpec = ItemCacheCollectionSpec(lowWaterItemCount: 25, highWaterItemCount: 50)
|
||||
|
||||
func updateVisualMediaStoredState(postbox: Postbox, peerId: PeerId, messageTag: MessageTags, state: VisualMediaStoredState?) -> Signal<Void, NoError> {
|
||||
return postbox.transaction { transaction -> Void in
|
||||
let key = ValueBoxKey(length: 8 + 4)
|
||||
key.setInt64(0, value: peerId.toInt64())
|
||||
key.setUInt32(8, value: messageTag.rawValue)
|
||||
|
||||
let id = ItemCacheEntryId(collectionId: ApplicationSpecificItemCacheCollectionId.visualMediaStoredState, key: key)
|
||||
if let state = state, let entry = CodableEntry(state) {
|
||||
transaction.putItemCacheEntry(id: id, entry: entry, collectionSpec: collectionSpec)
|
||||
} else {
|
||||
transaction.removeItemCacheEntry(id: id)
|
||||
}
|
||||
func updateVisualMediaStoredState(engine: TelegramEngine, peerId: PeerId, messageTag: MessageTags, state: VisualMediaStoredState?) -> Signal<Never, NoError> {
|
||||
let key = ValueBoxKey(length: 8 + 4)
|
||||
key.setInt64(0, value: peerId.toInt64())
|
||||
key.setUInt32(8, value: messageTag.rawValue)
|
||||
|
||||
if let state = state {
|
||||
return engine.itemCache.put(collectionId: ApplicationSpecificItemCacheCollectionId.visualMediaStoredState, id: key, item: state)
|
||||
} else {
|
||||
return engine.itemCache.remove(collectionId: ApplicationSpecificItemCacheCollectionId.visualMediaStoredState, id: key)
|
||||
}
|
||||
}
|
||||
|
@ -1861,7 +1861,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate
|
||||
}
|
||||
|
||||
let gesture: ContextGesture? = anyRecognizer as? ContextGesture
|
||||
let _ = (chatAvailableMessageActionsImpl(postbox: strongSelf.context.account.postbox, accountPeerId: strongSelf.context.account.peerId, messageIds: [message.id])
|
||||
let _ = (chatAvailableMessageActionsImpl(engine: strongSelf.context.engine, accountPeerId: strongSelf.context.account.peerId, messageIds: [message.id])
|
||||
|> deliverOnMainQueue).start(next: { actions in
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
@ -2016,7 +2016,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate
|
||||
if let previewData = previewData {
|
||||
let context = strongSelf.context
|
||||
let strings = strongSelf.presentationData.strings
|
||||
let items = chatAvailableMessageActionsImpl(postbox: strongSelf.context.account.postbox, accountPeerId: strongSelf.context.account.peerId, messageIds: [message.id])
|
||||
let items = chatAvailableMessageActionsImpl(engine: strongSelf.context.engine, accountPeerId: strongSelf.context.account.peerId, messageIds: [message.id])
|
||||
|> map { actions -> [ContextMenuItem] in
|
||||
var items: [ContextMenuItem] = []
|
||||
|
||||
@ -3285,7 +3285,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate
|
||||
if let timestamp = timestamp {
|
||||
storedState = MediaPlaybackStoredState(timestamp: timestamp, playbackRate: AudioPlaybackRate(playbackRate))
|
||||
}
|
||||
let _ = updateMediaPlaybackStoredStateInteractively(postbox: strongSelf.context.account.postbox, messageId: messageId, state: storedState).start()
|
||||
let _ = updateMediaPlaybackStoredStateInteractively(engine: strongSelf.context.engine, messageId: messageId, state: storedState).start()
|
||||
}, editMedia: { [weak self] messageId, snapshots, transitionCompletion in
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
@ -6379,14 +6379,13 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate
|
||||
|
||||
private func accountContextMenuItems(context: AccountContext, logout: @escaping () -> Void) -> Signal<[ContextMenuItem], NoError> {
|
||||
let strings = context.sharedContext.currentPresentationData.with({ $0 }).strings
|
||||
return context.account.postbox.transaction { transaction -> [ContextMenuItem] in
|
||||
return context.engine.messages.unreadChatListPeerIds(groupId: .root, filterPredicate: nil)
|
||||
|> map { unreadChatListPeerIds -> [ContextMenuItem] in
|
||||
var items: [ContextMenuItem] = []
|
||||
|
||||
if !transaction.getUnreadChatListPeerIds(groupId: .root, filterPredicate: nil).isEmpty {
|
||||
if !unreadChatListPeerIds.isEmpty {
|
||||
items.append(.action(ContextMenuActionItem(text: strings.ChatList_Context_MarkAllAsRead, icon: { theme in generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/MarkAsRead"), color: theme.contextMenu.primaryColor) }, action: { _, f in
|
||||
let _ = (context.account.postbox.transaction { transaction in
|
||||
markAllChatsAsReadInteractively(transaction: transaction, viewTracker: context.account.viewTracker, groupId: .root, filterPredicate: nil)
|
||||
}
|
||||
let _ = (context.engine.messages.markAllChatsAsReadInteractively(items: [(groupId: .root, filterPredicate: nil)])
|
||||
|> deliverOnMainQueue).start(completed: {
|
||||
f(.default)
|
||||
})
|
||||
@ -6436,7 +6435,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate
|
||||
|
||||
private func deleteMessages(messageIds: Set<MessageId>?) {
|
||||
if let messageIds = messageIds ?? self.state.selectedMessageIds, !messageIds.isEmpty {
|
||||
self.activeActionDisposable.set((self.context.sharedContext.chatAvailableMessageActions(postbox: self.context.account.postbox, accountPeerId: self.context.account.peerId, messageIds: messageIds)
|
||||
self.activeActionDisposable.set((self.context.sharedContext.chatAvailableMessageActions(engine: self.context.engine, accountPeerId: self.context.account.peerId, messageIds: messageIds)
|
||||
|> deliverOnMainQueue).start(next: { [weak self] actions in
|
||||
if let strongSelf = self, let peer = strongSelf.data?.peer, !actions.options.isEmpty {
|
||||
let actionSheet = ActionSheetController(presentationData: strongSelf.presentationData)
|
||||
|
@ -299,20 +299,19 @@ public class ShareRootControllerImpl {
|
||||
|
||||
let applicationInterface = account
|
||||
|> mapToSignal { sharedContext, account, otherAccounts -> Signal<(AccountContext, PostboxAccessChallengeData, [AccountWithInfo]), ShareAuthorizationError> in
|
||||
let limitsConfigurationAndContentSettings = account.postbox.transaction { transaction -> (LimitsConfiguration, ContentSettings, AppConfiguration) in
|
||||
return (
|
||||
transaction.getPreferencesEntry(key: PreferencesKeys.limitsConfiguration)?.get(LimitsConfiguration.self) ?? LimitsConfiguration.defaultValue,
|
||||
getContentSettings(transaction: transaction),
|
||||
getAppConfiguration(transaction: transaction)
|
||||
)
|
||||
}
|
||||
let limitsConfigurationAndContentSettings = TelegramEngine(account: account).data.get(
|
||||
TelegramEngine.EngineData.Item.Configuration.Limits(),
|
||||
TelegramEngine.EngineData.Item.Configuration.ContentSettings(),
|
||||
TelegramEngine.EngineData.Item.Configuration.App()
|
||||
)
|
||||
|
||||
return combineLatest(sharedContext.accountManager.sharedData(keys: [ApplicationSpecificSharedDataKeys.presentationPasscodeSettings]), limitsConfigurationAndContentSettings, sharedContext.accountManager.accessChallengeData())
|
||||
|> take(1)
|
||||
|> deliverOnMainQueue
|
||||
|> castError(ShareAuthorizationError.self)
|
||||
|> map { sharedData, limitsConfigurationAndContentSettings, data -> (AccountContext, PostboxAccessChallengeData, [AccountWithInfo]) in
|
||||
updateLegacyLocalization(strings: sharedContext.currentPresentationData.with({ $0 }).strings)
|
||||
let context = AccountContextImpl(sharedContext: sharedContext, account: account, limitsConfiguration: limitsConfigurationAndContentSettings.0, contentSettings: limitsConfigurationAndContentSettings.1, appConfiguration: limitsConfigurationAndContentSettings.2)
|
||||
let context = AccountContextImpl(sharedContext: sharedContext, account: account, limitsConfiguration: limitsConfigurationAndContentSettings.0._asLimits(), contentSettings: limitsConfigurationAndContentSettings.1, appConfiguration: limitsConfigurationAndContentSettings.2)
|
||||
return (context, data.data, otherAccounts)
|
||||
}
|
||||
}
|
||||
|
@ -412,11 +412,13 @@ public final class SharedAccountContextImpl: SharedAccountContext {
|
||||
switch result {
|
||||
case let .authorized(account):
|
||||
setupAccount(account, fetchCachedResourceRepresentation: fetchCachedResourceRepresentation, transformOutgoingMessageMedia: transformOutgoingMessageMedia)
|
||||
return account.postbox.transaction { transaction -> AddedAccountResult in
|
||||
let limitsConfiguration = transaction.getPreferencesEntry(key: PreferencesKeys.limitsConfiguration)?.get(LimitsConfiguration.self) ?? LimitsConfiguration.defaultValue
|
||||
let contentSettings = getContentSettings(transaction: transaction)
|
||||
let appConfiguration = getAppConfiguration(transaction: transaction)
|
||||
return .ready(id, account, attributes.sortIndex, limitsConfiguration, contentSettings, appConfiguration)
|
||||
return TelegramEngine(account: account).data.get(
|
||||
TelegramEngine.EngineData.Item.Configuration.Limits(),
|
||||
TelegramEngine.EngineData.Item.Configuration.ContentSettings(),
|
||||
TelegramEngine.EngineData.Item.Configuration.App()
|
||||
)
|
||||
|> map { limitsConfiguration, contentSettings, appConfiguration -> AddedAccountResult in
|
||||
return .ready(id, account, attributes.sortIndex, limitsConfiguration._asLimits(), contentSettings, appConfiguration)
|
||||
}
|
||||
case let .upgrading(progress):
|
||||
return .single(.upgrading(progress))
|
||||
@ -1140,12 +1142,12 @@ public final class SharedAccountContextImpl: SharedAccountContext {
|
||||
openExternalUrlImpl(context: context, urlContext: urlContext, url: url, forceExternal: forceExternal, presentationData: presentationData, navigationController: navigationController, dismissInput: dismissInput)
|
||||
}
|
||||
|
||||
public func chatAvailableMessageActions(postbox: Postbox, accountPeerId: EnginePeer.Id, messageIds: Set<EngineMessage.Id>) -> Signal<ChatAvailableMessageActions, NoError> {
|
||||
return chatAvailableMessageActionsImpl(postbox: postbox, accountPeerId: accountPeerId, messageIds: messageIds)
|
||||
public func chatAvailableMessageActions(engine: TelegramEngine, accountPeerId: EnginePeer.Id, messageIds: Set<EngineMessage.Id>) -> Signal<ChatAvailableMessageActions, NoError> {
|
||||
return chatAvailableMessageActionsImpl(engine: engine, accountPeerId: accountPeerId, messageIds: messageIds)
|
||||
}
|
||||
|
||||
public func chatAvailableMessageActions(postbox: Postbox, accountPeerId: EnginePeer.Id, messageIds: Set<EngineMessage.Id>, messages: [EngineMessage.Id: EngineMessage] = [:], peers: [EnginePeer.Id: EnginePeer] = [:]) -> Signal<ChatAvailableMessageActions, NoError> {
|
||||
return chatAvailableMessageActionsImpl(postbox: postbox, accountPeerId: accountPeerId, messageIds: messageIds, messages: messages.mapValues({ $0._asMessage() }), peers: peers.mapValues({ $0._asPeer() }))
|
||||
public func chatAvailableMessageActions(engine: TelegramEngine, accountPeerId: EnginePeer.Id, messageIds: Set<EngineMessage.Id>, messages: [EngineMessage.Id: EngineMessage] = [:], peers: [EnginePeer.Id: EnginePeer] = [:]) -> Signal<ChatAvailableMessageActions, NoError> {
|
||||
return chatAvailableMessageActionsImpl(engine: engine, accountPeerId: accountPeerId, messageIds: messageIds, messages: messages.mapValues({ $0._asMessage() }), peers: peers.mapValues({ $0._asPeer() }))
|
||||
}
|
||||
|
||||
public func navigateToChatController(_ params: NavigateToChatControllerParams) {
|
||||
|
@ -127,9 +127,7 @@ final class StickersChatInputContextPanelNode: ChatInputContextPanelNode {
|
||||
if let stickersNode = stickersNode {
|
||||
let point = strongSelf.listView.view.convert(point, to: stickersNode.view)
|
||||
if let (item, itemNode) = stickersNode.stickerItem(at: point) {
|
||||
return strongSelf.context.account.postbox.transaction { transaction -> Bool in
|
||||
return getIsStickerSaved(transaction: transaction, fileId: item.file.fileId)
|
||||
}
|
||||
return strongSelf.context.engine.stickers.isStickerSaved(id: item.file.fileId)
|
||||
|> deliverOnMainQueue
|
||||
|> map { isStarred -> (ASDisplayNode, PeekControllerContent)? in
|
||||
if let strongSelf = self, let controllerInteraction = strongSelf.controllerInteraction {
|
||||
|
@ -1,283 +0,0 @@
|
||||
#if ENABLE_WALLET
|
||||
|
||||
import Foundation
|
||||
import UIKit
|
||||
import Display
|
||||
import WalletUI
|
||||
import Postbox
|
||||
import TelegramCore
|
||||
import AccountContext
|
||||
import SwiftSignalKit
|
||||
import TelegramPresentationData
|
||||
import ShareController
|
||||
import DeviceAccess
|
||||
import PresentationDataUtils
|
||||
import WalletCore
|
||||
|
||||
extension WalletConfiguration {
|
||||
static func with(appConfiguration: AppConfiguration) -> WalletConfiguration {
|
||||
if let data = appConfiguration.data, let config = data["wallet_config"] as? String, let blockchainName = data["wallet_blockchain_name"] as? String {
|
||||
var disableProxy = false
|
||||
if let value = data["wallet_disable_proxy"] as? String {
|
||||
disableProxy = value != "0"
|
||||
} else if let value = data["wallet_disable_proxy"] as? Int {
|
||||
disableProxy = value != 0
|
||||
}
|
||||
return WalletConfiguration(config: config, blockchainName: blockchainName, disableProxy: disableProxy)
|
||||
} else {
|
||||
return .defaultValue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
final class WalletStorageInterfaceImpl: WalletStorageInterface {
|
||||
private let postbox: Postbox
|
||||
|
||||
init(postbox: Postbox) {
|
||||
self.postbox = postbox
|
||||
}
|
||||
|
||||
func watchWalletRecords() -> Signal<[WalletStateRecord], NoError> {
|
||||
return self.postbox.preferencesView(keys: [PreferencesKeys.walletCollection])
|
||||
|> map { view -> [WalletStateRecord] in
|
||||
guard let walletCollection = view.values[PreferencesKeys.walletCollection] as? WalletCollection else {
|
||||
return []
|
||||
}
|
||||
return walletCollection.wallets.flatMap { item -> WalletStateRecord? in
|
||||
do {
|
||||
return WalletStateRecord(info: try JSONDecoder().decode(WalletInfo.self, from: item.info), exportCompleted: item.exportCompleted, state: item.state.flatMap { try? JSONDecoder().decode(CombinedWalletState.self, from: $0) })
|
||||
} catch {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func getWalletRecords() -> Signal<[WalletStateRecord], NoError> {
|
||||
return self.postbox.transaction { transaction -> [WalletStateRecord] in
|
||||
guard let walletCollection = transaction.getPreferencesEntry(key: PreferencesKeys.walletCollection) as? WalletCollection else {
|
||||
return []
|
||||
}
|
||||
return walletCollection.wallets.flatMap { item -> WalletStateRecord? in
|
||||
do {
|
||||
return WalletStateRecord(info: try JSONDecoder().decode(WalletInfo.self, from: item.info), exportCompleted: item.exportCompleted, state: item.state.flatMap { try? JSONDecoder().decode(CombinedWalletState.self, from: $0) })
|
||||
} catch {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func updateWalletRecords(_ f: @escaping ([WalletStateRecord]) -> [WalletStateRecord]) -> Signal<[WalletStateRecord], NoError> {
|
||||
return self.postbox.transaction { transaction -> [WalletStateRecord] in
|
||||
var updatedRecords: [WalletStateRecord] = []
|
||||
transaction.updatePreferencesEntry(key: PreferencesKeys.walletCollection, { current in
|
||||
var walletCollection = (current as? WalletCollection) ?? WalletCollection(wallets: [])
|
||||
let updatedItems = f(walletCollection.wallets.flatMap { item -> WalletStateRecord? in
|
||||
do {
|
||||
return WalletStateRecord(info: try JSONDecoder().decode(WalletInfo.self, from: item.info), exportCompleted: item.exportCompleted, state: item.state.flatMap { try? JSONDecoder().decode(CombinedWalletState.self, from: $0) })
|
||||
} catch {
|
||||
return nil
|
||||
}
|
||||
})
|
||||
walletCollection.wallets = updatedItems.flatMap { item in
|
||||
do {
|
||||
return WalletCollectionItem(info: try JSONEncoder().encode(item.info), exportCompleted: item.exportCompleted, state: item.state.flatMap {
|
||||
try? JSONEncoder().encode($0)
|
||||
})
|
||||
} catch {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
return walletCollection
|
||||
})
|
||||
return updatedRecords
|
||||
}
|
||||
}
|
||||
|
||||
func localWalletConfiguration() -> Signal<LocalWalletConfiguration, NoError> {
|
||||
return .single(LocalWalletConfiguration(source: .string(""), blockchainName: ""))
|
||||
}
|
||||
|
||||
func updateLocalWalletConfiguration(_ f: @escaping (LocalWalletConfiguration) -> LocalWalletConfiguration) -> Signal<Never, NoError> {
|
||||
return .complete()
|
||||
}
|
||||
}
|
||||
|
||||
final class WalletContextImpl: WalletContext {
|
||||
private let context: AccountContext
|
||||
|
||||
let storage: WalletStorageInterface
|
||||
let tonInstance: TonInstance
|
||||
let keychain: TonKeychain
|
||||
let strings: PresentationStrings
|
||||
let presentationData: WalletPresentationData
|
||||
|
||||
let supportsCustomConfigurations: Bool = false
|
||||
var termsUrl: String? {
|
||||
return self.strings.TelegramWallet_Intro_TermsUrl
|
||||
}
|
||||
var feeInfoUrl: String? {
|
||||
return self.strings.AppWallet_TransactionInfo_FeeInfoURL
|
||||
}
|
||||
|
||||
var inForeground: Signal<Bool, NoError> {
|
||||
return self.context.sharedContext.applicationBindings.applicationInForeground
|
||||
}
|
||||
|
||||
func downloadFile(url: URL) -> Signal<Data, WalletDownloadFileError> {
|
||||
return .fail(.generic)
|
||||
}
|
||||
|
||||
func updateResolvedWalletConfiguration(source: LocalWalletConfigurationSource, blockchainName: String, resolvedValue: String) -> Signal<Never, NoError> {
|
||||
return .complete()
|
||||
}
|
||||
|
||||
init(context: AccountContext, tonContext: TonContext) {
|
||||
self.context = context
|
||||
|
||||
self.storage = WalletStorageInterfaceImpl(postbox: self.context.account.postbox)
|
||||
|
||||
self.tonInstance = tonContext.instance
|
||||
self.keychain = tonContext.keychain
|
||||
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||
self.strings = presentationData.strings
|
||||
let theme = presentationData.theme
|
||||
let strings = presentationData.strings
|
||||
let timeFormat: WalletTimeFormat
|
||||
switch presentationData.dateTimeFormat.timeFormat {
|
||||
case .military:
|
||||
timeFormat = .military
|
||||
case .regular:
|
||||
timeFormat = .regular
|
||||
}
|
||||
let dateFormat: WalletDateFormat
|
||||
switch presentationData.dateTimeFormat.dateFormat {
|
||||
case .dayFirst:
|
||||
dateFormat = .dayFirst
|
||||
case .monthFirst:
|
||||
dateFormat = .monthFirst
|
||||
}
|
||||
|
||||
let navigationBarData = NavigationBarPresentationData(presentationData: presentationData)
|
||||
|
||||
self.presentationData = WalletPresentationData(
|
||||
theme: WalletTheme(
|
||||
info: WalletInfoTheme(
|
||||
buttonBackgroundColor: UIColor(rgb: 0x32aafe),
|
||||
buttonTextColor: .white,
|
||||
incomingFundsTitleColor: theme.chatList.secretTitleColor,
|
||||
outgoingFundsTitleColor: theme.list.itemDestructiveColor
|
||||
), transaction: WalletTransactionTheme(
|
||||
descriptionBackgroundColor: theme.chat.message.incoming.bubble.withoutWallpaper.fill,
|
||||
descriptionTextColor: theme.chat.message.incoming.primaryTextColor
|
||||
), setup: WalletSetupTheme(
|
||||
buttonFillColor: theme.list.itemCheckColors.fillColor,
|
||||
buttonForegroundColor: theme.list.itemCheckColors.foregroundColor,
|
||||
inputBackgroundColor: theme.actionSheet.inputBackgroundColor,
|
||||
inputPlaceholderColor: theme.actionSheet.inputPlaceholderColor,
|
||||
inputTextColor: theme.actionSheet.inputTextColor,
|
||||
inputClearButtonColor: theme.actionSheet.inputClearButtonColor.withAlphaComponent(0.8)
|
||||
),
|
||||
list: WalletListTheme(
|
||||
itemPrimaryTextColor: theme.list.itemPrimaryTextColor,
|
||||
itemSecondaryTextColor: theme.list.itemSecondaryTextColor,
|
||||
itemPlaceholderTextColor: theme.list.itemPlaceholderTextColor,
|
||||
itemDestructiveColor: theme.list.itemDestructiveColor,
|
||||
itemAccentColor: theme.list.itemAccentColor,
|
||||
itemDisabledTextColor: theme.list.itemDisabledTextColor,
|
||||
plainBackgroundColor: theme.list.plainBackgroundColor,
|
||||
blocksBackgroundColor: theme.list.blocksBackgroundColor,
|
||||
itemPlainSeparatorColor: theme.list.itemPlainSeparatorColor,
|
||||
itemBlocksBackgroundColor: theme.list.itemBlocksBackgroundColor,
|
||||
itemBlocksSeparatorColor: theme.list.itemBlocksSeparatorColor,
|
||||
itemHighlightedBackgroundColor: theme.list.itemHighlightedBackgroundColor,
|
||||
sectionHeaderTextColor: theme.list.sectionHeaderTextColor,
|
||||
freeTextColor: theme.list.freeTextColor,
|
||||
freeTextErrorColor: theme.list.freeTextErrorColor,
|
||||
inputClearButtonColor: theme.list.inputClearButtonColor
|
||||
),
|
||||
statusBarStyle: theme.rootController.statusBarStyle.style,
|
||||
navigationBar: navigationBarData.theme,
|
||||
keyboardAppearance: theme.rootController.keyboardColor.keyboardAppearance,
|
||||
alert: AlertControllerTheme(presentationData: presentationData),
|
||||
actionSheet: ActionSheetControllerTheme(presentationData: presentationData)
|
||||
), strings: WalletStrings(
|
||||
primaryComponent: WalletStringsComponent(
|
||||
languageCode: strings.primaryComponent.languageCode,
|
||||
localizedName: strings.primaryComponent.localizedName,
|
||||
pluralizationRulesCode: strings.primaryComponent.pluralizationRulesCode,
|
||||
dict: strings.primaryComponent.dict
|
||||
),
|
||||
secondaryComponent: strings.secondaryComponent.flatMap { component in
|
||||
return WalletStringsComponent(
|
||||
languageCode: component.languageCode,
|
||||
localizedName: component.localizedName,
|
||||
pluralizationRulesCode: component.pluralizationRulesCode,
|
||||
dict: component.dict
|
||||
)
|
||||
},
|
||||
groupingSeparator: strings.groupingSeparator
|
||||
), dateTimeFormat: WalletPresentationDateTimeFormat(
|
||||
timeFormat: timeFormat,
|
||||
dateFormat: dateFormat,
|
||||
dateSeparator: presentationData.dateTimeFormat.dateSeparator,
|
||||
decimalSeparator: presentationData.dateTimeFormat.decimalSeparator,
|
||||
groupingSeparator: presentationData.dateTimeFormat.groupingSeparator
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
func getServerSalt() -> Signal<Data, WalletContextGetServerSaltError> {
|
||||
return getServerWalletSalt(network: self.context.account.network)
|
||||
|> mapError { _ -> WalletContextGetServerSaltError in
|
||||
return .generic
|
||||
}
|
||||
}
|
||||
|
||||
func presentNativeController(_ controller: UIViewController) {
|
||||
self.context.sharedContext.mainWindow?.presentNative(controller)
|
||||
}
|
||||
|
||||
func idleTimerExtension() -> Disposable {
|
||||
return self.context.sharedContext.applicationBindings.pushIdleTimerExtension()
|
||||
}
|
||||
|
||||
func openUrl(_ url: String) {
|
||||
return self.context.sharedContext.openExternalUrl(context: self.context, urlContext: .generic, url: url, forceExternal: true, presentationData: context.sharedContext.currentPresentationData.with { $0 }, navigationController: nil, dismissInput: {})
|
||||
}
|
||||
|
||||
func shareUrl(_ url: String) {
|
||||
let controller = ShareController(context: self.context, subject: .url(url))
|
||||
self.context.sharedContext.mainWindow?.present(controller, on: .root)
|
||||
}
|
||||
|
||||
func openPlatformSettings() {
|
||||
self.context.sharedContext.applicationBindings.openSettings()
|
||||
}
|
||||
|
||||
func authorizeAccessToCamera(completion: @escaping () -> Void) {
|
||||
let presentationData = self.context.sharedContext.currentPresentationData.with { $0 }
|
||||
DeviceAccess.authorizeAccess(to: .camera(.video), presentationData: presentationData, present: { c, a in
|
||||
c.presentationArguments = a
|
||||
self.context.sharedContext.mainWindow?.present(c, on: .root)
|
||||
}, openSettings: { [weak self] in
|
||||
self?.openPlatformSettings()
|
||||
}, { granted in
|
||||
guard granted else {
|
||||
return
|
||||
}
|
||||
completion()
|
||||
})
|
||||
}
|
||||
|
||||
func pickImage(present: @escaping (ViewController) -> Void, completion: @escaping (UIImage) -> Void) {
|
||||
self.context.sharedContext.openImagePicker(context: self.context, completion: { image in
|
||||
completion(image)
|
||||
}, present: { [weak self] controller in
|
||||
present(controller)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
@ -1,42 +0,0 @@
|
||||
import Foundation
|
||||
import Postbox
|
||||
import TelegramCore
|
||||
import SwiftSignalKit
|
||||
|
||||
public struct VoipDerivedState: Codable, Equatable {
|
||||
public var data: Data
|
||||
|
||||
public static var `default`: VoipDerivedState {
|
||||
return VoipDerivedState(data: Data())
|
||||
}
|
||||
|
||||
public init(data: Data) {
|
||||
self.data = data
|
||||
}
|
||||
|
||||
public init(from decoder: Decoder) throws {
|
||||
let container = try decoder.container(keyedBy: StringCodingKey.self)
|
||||
|
||||
self.data = try container.decode(Data.self, forKey: "data")
|
||||
}
|
||||
|
||||
public func encode(to encoder: Encoder) throws {
|
||||
var container = encoder.container(keyedBy: StringCodingKey.self)
|
||||
|
||||
try container.encode(self.data, forKey: "data")
|
||||
}
|
||||
}
|
||||
|
||||
public func updateVoipDerivedStateInteractively(postbox: Postbox, _ f: @escaping (VoipDerivedState) -> VoipDerivedState) -> Signal<Void, NoError> {
|
||||
return postbox.transaction { transaction -> Void in
|
||||
transaction.updatePreferencesEntry(key: ApplicationSpecificPreferencesKeys.voipDerivedState, { entry in
|
||||
let currentSettings: VoipDerivedState
|
||||
if let entry = entry?.get(VoipDerivedState.self) {
|
||||
currentSettings = entry
|
||||
} else {
|
||||
currentSettings = .default
|
||||
}
|
||||
return PreferencesEntry(f(currentSettings))
|
||||
})
|
||||
}
|
||||
}
|
@ -755,7 +755,7 @@ public final class OngoingCallContext {
|
||||
}
|
||||
}
|
||||
|
||||
public init(account: Account, callSessionManager: CallSessionManager, callId: CallId, internalId: CallSessionInternalId, proxyServer: ProxyServerSettings?, initialNetworkType: NetworkType, updatedNetworkType: Signal<NetworkType, NoError>, serializedData: String?, dataSaving: VoiceCallDataSaving, derivedState: VoipDerivedState, key: Data, isOutgoing: Bool, video: OngoingCallVideoCapturer?, connections: CallSessionConnectionSet, maxLayer: Int32, version: String, allowP2P: Bool, enableTCP: Bool, enableStunMarking: Bool, audioSessionActive: Signal<Bool, NoError>, logName: String, preferredVideoCodec: String?) {
|
||||
public init(account: Account, callSessionManager: CallSessionManager, callId: CallId, internalId: CallSessionInternalId, proxyServer: ProxyServerSettings?, initialNetworkType: NetworkType, updatedNetworkType: Signal<NetworkType, NoError>, serializedData: String?, dataSaving: VoiceCallDataSaving, key: Data, isOutgoing: Bool, video: OngoingCallVideoCapturer?, connections: CallSessionConnectionSet, maxLayer: Int32, version: String, allowP2P: Bool, enableTCP: Bool, enableStunMarking: Bool, audioSessionActive: Signal<Bool, NoError>, logName: String, preferredVideoCodec: String?) {
|
||||
let _ = setupLogs
|
||||
OngoingCallThreadLocalContext.applyServerConfig(serializedData)
|
||||
|
||||
@ -871,7 +871,7 @@ public final class OngoingCallContext {
|
||||
}
|
||||
}
|
||||
|
||||
let context = OngoingCallThreadLocalContextWebrtc(version: version, queue: OngoingCallThreadLocalContextQueueImpl(queue: queue), proxy: voipProxyServer, networkType: ongoingNetworkTypeForTypeWebrtc(initialNetworkType), dataSaving: ongoingDataSavingForTypeWebrtc(dataSaving), derivedState: derivedState.data, key: key, isOutgoing: isOutgoing, connections: filteredConnections, maxLayer: maxLayer, allowP2P: allowP2P, allowTCP: enableTCP, enableStunMarking: enableStunMarking, logPath: tempLogPath, statsLogPath: tempStatsLogPath, sendSignalingData: { [weak callSessionManager] data in
|
||||
let context = OngoingCallThreadLocalContextWebrtc(version: version, queue: OngoingCallThreadLocalContextQueueImpl(queue: queue), proxy: voipProxyServer, networkType: ongoingNetworkTypeForTypeWebrtc(initialNetworkType), dataSaving: ongoingDataSavingForTypeWebrtc(dataSaving), derivedState: Data(), key: key, isOutgoing: isOutgoing, connections: filteredConnections, maxLayer: maxLayer, allowP2P: allowP2P, allowTCP: enableTCP, enableStunMarking: enableStunMarking, logPath: tempLogPath, statsLogPath: tempStatsLogPath, sendSignalingData: { [weak callSessionManager] data in
|
||||
queue.async {
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
@ -966,7 +966,7 @@ public final class OngoingCallContext {
|
||||
break
|
||||
}
|
||||
}
|
||||
let context = OngoingCallThreadLocalContext(queue: OngoingCallThreadLocalContextQueueImpl(queue: queue), proxy: voipProxyServer, networkType: ongoingNetworkTypeForType(initialNetworkType), dataSaving: ongoingDataSavingForType(dataSaving), derivedState: derivedState.data, key: key, isOutgoing: isOutgoing, primaryConnection: callConnectionDescription(connections.primary)!, alternativeConnections: connections.alternatives.compactMap(callConnectionDescription), maxLayer: maxLayer, allowP2P: allowP2P, logPath: logPath)
|
||||
let context = OngoingCallThreadLocalContext(queue: OngoingCallThreadLocalContextQueueImpl(queue: queue), proxy: voipProxyServer, networkType: ongoingNetworkTypeForType(initialNetworkType), dataSaving: ongoingDataSavingForType(dataSaving), derivedState: Data(), key: key, isOutgoing: isOutgoing, primaryConnection: callConnectionDescription(connections.primary)!, alternativeConnections: connections.alternatives.compactMap(callConnectionDescription), maxLayer: maxLayer, allowP2P: allowP2P, logPath: logPath)
|
||||
|
||||
strongSelf.contextRef = Unmanaged.passRetained(OngoingCallThreadLocalContextHolder(context))
|
||||
context.stateChanged = { state in
|
||||
@ -1089,10 +1089,6 @@ public final class OngoingCallContext {
|
||||
})
|
||||
}
|
||||
}
|
||||
let derivedState = context.nativeGetDerivedState()
|
||||
let _ = updateVoipDerivedStateInteractively(postbox: self.account.postbox, { _ in
|
||||
return VoipDerivedState(data: derivedState)
|
||||
}).start()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -94,16 +94,10 @@ public final class CachedChannelAdminRanks: Codable {
|
||||
}
|
||||
}
|
||||
|
||||
private let collectionSpec = ItemCacheCollectionSpec(lowWaterItemCount: 100, highWaterItemCount: 200)
|
||||
|
||||
public func cachedChannelAdminRanksEntryId(peerId: PeerId) -> ItemCacheEntryId {
|
||||
return ItemCacheEntryId(collectionId: 100, key: CachedChannelAdminRanks.cacheKey(peerId: peerId))
|
||||
}
|
||||
|
||||
func updateCachedChannelAdminRanks(postbox: Postbox, peerId: PeerId, ranks: Dictionary<PeerId, CachedChannelAdminRank>) -> Signal<Void, NoError> {
|
||||
return postbox.transaction { transaction -> Void in
|
||||
if let entry = CodableEntry(CachedChannelAdminRanks(ranks: ranks)) {
|
||||
transaction.putItemCacheEntry(id: ItemCacheEntryId(collectionId: 100, key: CachedChannelAdminRanks.cacheKey(peerId: peerId)), entry: entry, collectionSpec: collectionSpec)
|
||||
}
|
||||
}
|
||||
func updateCachedChannelAdminRanks(engine: TelegramEngine, peerId: PeerId, ranks: Dictionary<PeerId, CachedChannelAdminRank>) -> Signal<Never, NoError> {
|
||||
return engine.itemCache.put(collectionId: 100, id: CachedChannelAdminRanks.cacheKey(peerId: peerId), item: CachedChannelAdminRanks(ranks: ranks))
|
||||
}
|
||||
|
@ -132,7 +132,7 @@ private final class ChannelMemberSingleCategoryListContext: ChannelMemberCategor
|
||||
return ranks
|
||||
}
|
||||
if ranks != previousRanks {
|
||||
let _ = updateCachedChannelAdminRanks(postbox: self.postbox, peerId: self.peerId, ranks: ranks).start()
|
||||
let _ = updateCachedChannelAdminRanks(engine: self.engine, peerId: self.peerId, ranks: ranks).start()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -727,8 +727,8 @@ public func resolveUrlImpl(context: AccountContext, peerId: PeerId?, url: String
|
||||
|
||||
return ApplicationSpecificNotice.getSecretChatLinkPreviews(accountManager: context.sharedContext.accountManager)
|
||||
|> mapToSignal { linkPreviews -> Signal<ResolvedUrl, NoError> in
|
||||
return context.account.postbox.transaction { transaction -> Signal<ResolvedUrl, NoError> in
|
||||
let appConfiguration: AppConfiguration = transaction.getPreferencesEntry(key: PreferencesKeys.appConfiguration)?.get(AppConfiguration.self) ?? AppConfiguration.defaultValue
|
||||
return context.engine.data.get(TelegramEngine.EngineData.Item.Configuration.App())
|
||||
|> mapToSignal { appConfiguration -> Signal<ResolvedUrl, NoError> in
|
||||
let urlHandlingConfiguration = UrlHandlingConfiguration.with(appConfiguration: appConfiguration)
|
||||
|
||||
var skipUrlAuth = skipUrlAuth
|
||||
@ -786,7 +786,7 @@ public func resolveUrlImpl(context: AccountContext, peerId: PeerId?, url: String
|
||||
}
|
||||
}
|
||||
return .single(.externalUrl(url))
|
||||
} |> switchToLatest
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -27,8 +27,6 @@ public final class CachedWallpaper: Codable {
|
||||
}
|
||||
}
|
||||
|
||||
private let collectionSpec = ItemCacheCollectionSpec(lowWaterItemCount: 10000, highWaterItemCount: 20000)
|
||||
|
||||
public func cachedWallpaper(account: Account, slug: String, settings: WallpaperSettings?, update: Bool = false) -> Signal<CachedWallpaper?, NoError> {
|
||||
return account.postbox.transaction { transaction -> Signal<CachedWallpaper?, NoError> in
|
||||
let key = ValueBoxKey(length: 8)
|
||||
@ -58,7 +56,7 @@ public func cachedWallpaper(account: Account, slug: String, settings: WallpaperS
|
||||
break
|
||||
}
|
||||
if let entry = CodableEntry(CachedWallpaper(wallpaper: wallpaper)) {
|
||||
transaction.putItemCacheEntry(id: id, entry: entry, collectionSpec: collectionSpec)
|
||||
transaction.putItemCacheEntry(id: id, entry: entry)
|
||||
}
|
||||
if let settings = settings {
|
||||
return CachedWallpaper(wallpaper: wallpaper.withUpdatedSettings(settings))
|
||||
@ -75,16 +73,12 @@ public func cachedWallpaper(account: Account, slug: String, settings: WallpaperS
|
||||
} |> switchToLatest
|
||||
}
|
||||
|
||||
public func updateCachedWallpaper(account: Account, wallpaper: TelegramWallpaper) {
|
||||
public func updateCachedWallpaper(engine: TelegramEngine, wallpaper: TelegramWallpaper) {
|
||||
guard case let .file(file) = wallpaper, file.id != 0 else {
|
||||
return
|
||||
}
|
||||
let _ = (account.postbox.transaction { transaction in
|
||||
let key = ValueBoxKey(length: 8)
|
||||
key.setInt64(0, value: Int64(bitPattern: file.slug.persistentHashValue))
|
||||
let id = ItemCacheEntryId(collectionId: ApplicationSpecificItemCacheCollectionId.cachedWallpapers, key: key)
|
||||
if let entry = CodableEntry(CachedWallpaper(wallpaper: wallpaper)) {
|
||||
transaction.putItemCacheEntry(id: id, entry: entry, collectionSpec: collectionSpec)
|
||||
}
|
||||
}).start()
|
||||
let key = ValueBoxKey(length: 8)
|
||||
key.setInt64(0, value: Int64(bitPattern: file.slug.persistentHashValue))
|
||||
|
||||
let _ = engine.itemCache.put(collectionId: ApplicationSpecificItemCacheCollectionId.cachedWallpapers, id: key, item: CachedWallpaper(wallpaper: wallpaper)).start()
|
||||
}
|
||||
|
@ -280,7 +280,7 @@ public final class WebSearchController: ViewController {
|
||||
}
|
||||
}, deleteRecentQuery: { [weak self] query in
|
||||
if let strongSelf = self {
|
||||
_ = removeRecentWebSearchQuery(postbox: strongSelf.context.account.postbox, string: query).start()
|
||||
let _ = removeRecentWebSearchQuery(engine: strongSelf.context.engine, string: query).start()
|
||||
}
|
||||
}, toggleSelection: { [weak self] result, value in
|
||||
if let strongSelf = self {
|
||||
@ -415,7 +415,7 @@ public final class WebSearchController: ViewController {
|
||||
|
||||
private func updateSearchQuery(_ query: String) {
|
||||
if !query.isEmpty {
|
||||
let _ = addRecentWebSearchQuery(postbox: self.context.account.postbox, string: query).start()
|
||||
let _ = addRecentWebSearchQuery(engine: self.context.engine, string: query).start()
|
||||
}
|
||||
|
||||
let scope: Signal<WebSearchScope?, NoError>
|
||||
|
@ -291,7 +291,7 @@ class WebSearchControllerNode: ASDisplayNode {
|
||||
}
|
||||
|
||||
let header = ChatListSearchItemHeader(type: .recentPeers, theme: interfaceState.presentationData.theme, strings: interfaceState.presentationData.strings, actionTitle: interfaceState.presentationData.strings.WebSearch_RecentSectionClear, action: {
|
||||
_ = clearRecentWebSearchQueries(postbox: strongSelf.context.account.postbox).start()
|
||||
let _ = clearRecentWebSearchQueries(engine: strongSelf.context.engine).start()
|
||||
})
|
||||
|
||||
let previousEntries = previousRecentItems.swap(entries)
|
||||
|
@ -1,6 +1,7 @@
|
||||
import Foundation
|
||||
import UIKit
|
||||
import Postbox
|
||||
import TelegramCore
|
||||
import SwiftSignalKit
|
||||
import TelegramUIPreferences
|
||||
|
||||
@ -35,42 +36,36 @@ public final class RecentWebSearchQueryItem: Codable {
|
||||
}
|
||||
}
|
||||
|
||||
func addRecentWebSearchQuery(postbox: Postbox, string: String) -> Signal<Void, NoError> {
|
||||
return postbox.transaction { transaction in
|
||||
if let itemId = WebSearchRecentQueryItemId(string) {
|
||||
if let entry = CodableEntry(RecentWebSearchQueryItem()) {
|
||||
transaction.addOrMoveToFirstPositionOrderedItemListItem(collectionId: ApplicationSpecificOrderedItemListCollectionId.webSearchRecentQueries, item: OrderedItemListEntry(id: itemId.rawValue, contents: entry), removeTailIfCountExceeds: 100)
|
||||
}
|
||||
}
|
||||
func addRecentWebSearchQuery(engine: TelegramEngine, string: String) -> Signal<Never, NoError> {
|
||||
if let itemId = WebSearchRecentQueryItemId(string) {
|
||||
return engine.orderedLists.addOrMoveToFirstPosition(collectionId: ApplicationSpecificOrderedItemListCollectionId.webSearchRecentQueries, id: itemId.rawValue, item: RecentWebSearchQueryItem(), removeTailIfCountExceeds: 100)
|
||||
} else {
|
||||
return .complete()
|
||||
}
|
||||
}
|
||||
|
||||
func removeRecentWebSearchQuery(postbox: Postbox, string: String) -> Signal<Void, NoError> {
|
||||
return postbox.transaction { transaction -> Void in
|
||||
if let itemId = WebSearchRecentQueryItemId(string) {
|
||||
transaction.removeOrderedItemListItem(collectionId: ApplicationSpecificOrderedItemListCollectionId.webSearchRecentQueries, itemId: itemId.rawValue)
|
||||
}
|
||||
func removeRecentWebSearchQuery(engine: TelegramEngine, string: String) -> Signal<Never, NoError> {
|
||||
if let itemId = WebSearchRecentQueryItemId(string) {
|
||||
return engine.orderedLists.removeItem(collectionId: ApplicationSpecificOrderedItemListCollectionId.webSearchRecentQueries, id: itemId.rawValue)
|
||||
} else {
|
||||
return .complete()
|
||||
}
|
||||
}
|
||||
|
||||
func clearRecentWebSearchQueries(postbox: Postbox) -> Signal<Void, NoError> {
|
||||
return postbox.transaction { transaction -> Void in
|
||||
transaction.replaceOrderedItemListItems(collectionId: ApplicationSpecificOrderedItemListCollectionId.webSearchRecentQueries, items: [])
|
||||
}
|
||||
func clearRecentWebSearchQueries(engine: TelegramEngine) -> Signal<Never, NoError> {
|
||||
return engine.orderedLists.clear(collectionId: ApplicationSpecificOrderedItemListCollectionId.webSearchRecentQueries)
|
||||
}
|
||||
|
||||
func webSearchRecentQueries(postbox: Postbox) -> Signal<[String], NoError> {
|
||||
return postbox.combinedView(keys: [.orderedItemList(id: ApplicationSpecificOrderedItemListCollectionId.webSearchRecentQueries)])
|
||||
|> mapToSignal { view -> Signal<[String], NoError> in
|
||||
return postbox.transaction { transaction -> [String] in
|
||||
var result: [String] = []
|
||||
if let view = view.views[.orderedItemList(id: ApplicationSpecificOrderedItemListCollectionId.webSearchRecentQueries)] as? OrderedItemListView {
|
||||
for item in view.items {
|
||||
let value = WebSearchRecentQueryItemId(item.id).value
|
||||
result.append(value)
|
||||
}
|
||||
}
|
||||
return result
|
||||
|> mapToSignal { view -> Signal<[String], NoError> in
|
||||
var result: [String] = []
|
||||
if let view = view.views[.orderedItemList(id: ApplicationSpecificOrderedItemListCollectionId.webSearchRecentQueries)] as? OrderedItemListView {
|
||||
for item in view.items {
|
||||
let value = WebSearchRecentQueryItemId(item.id).value
|
||||
result.append(value)
|
||||
}
|
||||
}
|
||||
return .single(result)
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user