mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
Merge commit '47fb248cc7d85ac585ea89f0cd6a5b0d7cd51d3a'
This commit is contained in:
commit
4afd49ee48
@ -33,6 +33,7 @@ swift_library(
|
|||||||
"//submodules/MediaResources:MediaResources",
|
"//submodules/MediaResources:MediaResources",
|
||||||
"//submodules/MediaPlayer:UniversalMediaPlayer",
|
"//submodules/MediaPlayer:UniversalMediaPlayer",
|
||||||
"//submodules/ManagedFile:ManagedFile",
|
"//submodules/ManagedFile:ManagedFile",
|
||||||
|
"//submodules/TelegramCore:TelegramCore",
|
||||||
],
|
],
|
||||||
visibility = [
|
visibility = [
|
||||||
"//visibility:public",
|
"//visibility:public",
|
||||||
|
@ -6,6 +6,7 @@ import UniversalMediaPlayer
|
|||||||
import CoreMedia
|
import CoreMedia
|
||||||
import ManagedFile
|
import ManagedFile
|
||||||
import Accelerate
|
import Accelerate
|
||||||
|
import TelegramCore
|
||||||
|
|
||||||
private let sharedStoreQueue = Queue.concurrentDefaultQueue()
|
private let sharedStoreQueue = Queue.concurrentDefaultQueue()
|
||||||
|
|
||||||
@ -20,6 +21,7 @@ private final class VideoStickerFrameSourceCache {
|
|||||||
|
|
||||||
private let queue: Queue
|
private let queue: Queue
|
||||||
private let storeQueue: Queue
|
private let storeQueue: Queue
|
||||||
|
private let path: String
|
||||||
private let file: ManagedFile
|
private let file: ManagedFile
|
||||||
private let width: Int
|
private let width: Int
|
||||||
private let height: Int
|
private let height: Int
|
||||||
@ -28,6 +30,9 @@ private final class VideoStickerFrameSourceCache {
|
|||||||
public private(set) var frameCount: Int32 = 0
|
public private(set) var frameCount: Int32 = 0
|
||||||
|
|
||||||
private var isStoringFrames = Set<Int>()
|
private var isStoringFrames = Set<Int>()
|
||||||
|
var storedFrames: Int {
|
||||||
|
return self.isStoringFrames.count
|
||||||
|
}
|
||||||
|
|
||||||
private var scratchBuffer: Data
|
private var scratchBuffer: Data
|
||||||
private var decodeBuffer: Data
|
private var decodeBuffer: Data
|
||||||
@ -40,13 +45,13 @@ private final class VideoStickerFrameSourceCache {
|
|||||||
self.height = height
|
self.height = height
|
||||||
|
|
||||||
let version: Int = 1
|
let version: Int = 1
|
||||||
let path = "\(pathPrefix)_\(width)x\(height)-v\(version).vstickerframecache"
|
self.path = "\(pathPrefix)_\(width)x\(height)-v\(version).vstickerframecache"
|
||||||
var file = ManagedFile(queue: queue, path: path, mode: .readwrite)
|
var file = ManagedFile(queue: queue, path: self.path, mode: .readwrite)
|
||||||
if let file = file {
|
if let file = file {
|
||||||
self.file = file
|
self.file = file
|
||||||
} else {
|
} else {
|
||||||
let _ = try? FileManager.default.removeItem(atPath: path)
|
let _ = try? FileManager.default.removeItem(atPath: self.path)
|
||||||
file = ManagedFile(queue: queue, path: path, mode: .readwrite)
|
file = ManagedFile(queue: queue, path: self.path, mode: .readwrite)
|
||||||
if let file = file {
|
if let file = file {
|
||||||
self.file = file
|
self.file = file
|
||||||
} else {
|
} else {
|
||||||
@ -63,6 +68,12 @@ private final class VideoStickerFrameSourceCache {
|
|||||||
self.initializeFrameTable()
|
self.initializeFrameTable()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
deinit {
|
||||||
|
if self.frameCount == 0 {
|
||||||
|
let _ = try? FileManager.default.removeItem(atPath: self.path)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private func initializeFrameTable() {
|
private func initializeFrameTable() {
|
||||||
var reset = true
|
var reset = true
|
||||||
if let size = self.file.getSize(), size >= maximumFrameCount {
|
if let size = self.file.getSize(), size >= maximumFrameCount {
|
||||||
@ -107,6 +118,7 @@ private final class VideoStickerFrameSourceCache {
|
|||||||
if self.file.read(&frameCount, 4) != 4 {
|
if self.file.read(&frameCount, 4) != 4 {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
if frameCount < 0 {
|
if frameCount < 0 {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@ -205,48 +217,6 @@ private final class VideoStickerFrameSourceCache {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func storeUncompressedYuvaFrame(index: Int, yuvaData: Data) {
|
|
||||||
if index < 0 || index >= maximumFrameCount {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if self.isStoringFrames.contains(index) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
self.isStoringFrames.insert(index)
|
|
||||||
|
|
||||||
let width = self.width
|
|
||||||
let height = self.height
|
|
||||||
|
|
||||||
let queue = self.queue
|
|
||||||
self.storeQueue.async { [weak self] in
|
|
||||||
let compressedData = compressFrame(width: width, height: height, yuvaData: yuvaData)
|
|
||||||
|
|
||||||
queue.async {
|
|
||||||
guard let strongSelf = self else {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
guard let currentSize = strongSelf.file.getSize() else {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
guard let compressedData = compressedData else {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
strongSelf.file.seek(position: Int64(8 + index * 4 * 2))
|
|
||||||
var offset = Int32(currentSize)
|
|
||||||
var length = Int32(compressedData.count)
|
|
||||||
let _ = strongSelf.file.write(&offset, count: 4)
|
|
||||||
let _ = strongSelf.file.write(&length, count: 4)
|
|
||||||
strongSelf.file.seek(position: Int64(currentSize))
|
|
||||||
compressedData.withUnsafeBytes { (buffer: UnsafeRawBufferPointer) -> Void in
|
|
||||||
if let baseAddress = buffer.baseAddress {
|
|
||||||
let _ = strongSelf.file.write(baseAddress, count: Int(length))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func readUncompressedYuvaFrame(index: Int) -> Data? {
|
func readUncompressedYuvaFrame(index: Int) -> Data? {
|
||||||
if index < 0 || index >= maximumFrameCount {
|
if index < 0 || index >= maximumFrameCount {
|
||||||
return nil
|
return nil
|
||||||
@ -360,9 +330,22 @@ final class VideoStickerDirectFrameSource: AnimatedStickerFrameSource {
|
|||||||
} else if let source = self.source {
|
} else if let source = self.source {
|
||||||
let frameAndLoop = source.readFrame(maxPts: nil)
|
let frameAndLoop = source.readFrame(maxPts: nil)
|
||||||
if frameAndLoop.0 == nil {
|
if frameAndLoop.0 == nil {
|
||||||
if frameAndLoop.3 && self.frameCount == 0 {
|
if frameAndLoop.3 {
|
||||||
|
if self.frameCount == 0 {
|
||||||
|
if let cache = self.cache {
|
||||||
|
if cache.storedFrames == frameIndex {
|
||||||
self.frameCount = frameIndex
|
self.frameCount = frameIndex
|
||||||
self.cache?.storeFrameRateAndCount(frameRate: self.frameRate, frameCount: self.frameCount)
|
cache.storeFrameRateAndCount(frameRate: self.frameRate, frameCount: self.frameCount)
|
||||||
|
} else {
|
||||||
|
Logger.shared.log("VideoSticker", "Missed a frame? \(frameIndex) \(cache.storedFrames)")
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
self.frameCount = frameIndex
|
||||||
|
}
|
||||||
|
}
|
||||||
|
self.currentFrame = 0
|
||||||
|
} else {
|
||||||
|
Logger.shared.log("VideoSticker", "Skipped a frame?")
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -437,12 +437,10 @@ final class ChatImageGalleryItemNode: ZoomableContentGalleryItemNode {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||||
let progressSignal = Signal<Never, NoError> { [weak self] subscriber in
|
let topController = (self.baseNavigationController()?.topViewController as? ViewController)
|
||||||
guard let strongSelf = self else {
|
let progressSignal = Signal<Never, NoError> { subscriber in
|
||||||
return EmptyDisposable
|
|
||||||
}
|
|
||||||
let controller = OverlayStatusController(theme: presentationData.theme, type: .loading(cancelled: nil))
|
let controller = OverlayStatusController(theme: presentationData.theme, type: .loading(cancelled: nil))
|
||||||
(strongSelf.baseNavigationController()?.topViewController as? ViewController)?.present(controller, in: .window(.root), with: nil)
|
topController?.present(controller, in: .window(.root), with: nil)
|
||||||
return ActionDisposable { [weak controller] in
|
return ActionDisposable { [weak controller] in
|
||||||
Queue.mainQueue().async() {
|
Queue.mainQueue().async() {
|
||||||
controller?.dismiss()
|
controller?.dismiss()
|
||||||
@ -466,7 +464,22 @@ final class ChatImageGalleryItemNode: ZoomableContentGalleryItemNode {
|
|||||||
}
|
}
|
||||||
let baseNavigationController = strongSelf.baseNavigationController()
|
let baseNavigationController = strongSelf.baseNavigationController()
|
||||||
baseNavigationController?.view.endEditing(true)
|
baseNavigationController?.view.endEditing(true)
|
||||||
let controller = StickerPackScreen(context: context, mainStickerPack: packs[0], stickerPacks: packs, sendSticker: nil)
|
let controller = StickerPackScreen(context: context, mainStickerPack: packs[0], stickerPacks: packs, sendSticker: nil, actionPerformed: { info, items, action in
|
||||||
|
let animateInAsReplacement = false
|
||||||
|
switch action {
|
||||||
|
case .add:
|
||||||
|
topController?.present(UndoOverlayController(presentationData: presentationData, content: .stickersModified(title: presentationData.strings.StickerPackActionInfo_AddedTitle, text: presentationData.strings.StickerPackActionInfo_AddedText(info.title).string, undo: false, info: info, topItem: items.first, context: context), elevatedLayout: true, animateInAsReplacement: animateInAsReplacement, action: { _ in
|
||||||
|
return true
|
||||||
|
}), in: .window(.root))
|
||||||
|
case let .remove(positionInList):
|
||||||
|
topController?.present(UndoOverlayController(presentationData: presentationData, content: .stickersModified(title: presentationData.strings.StickerPackActionInfo_RemovedTitle, text: presentationData.strings.StickerPackActionInfo_RemovedText(info.title).string, undo: true, info: info, topItem: items.first, context: context), elevatedLayout: true, animateInAsReplacement: animateInAsReplacement, action: { action in
|
||||||
|
if case .undo = action {
|
||||||
|
let _ = context.engine.stickers.addStickerPackInteractively(info: info, items: items, positionInList: positionInList).start()
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}), in: .window(.root))
|
||||||
|
}
|
||||||
|
})
|
||||||
(baseNavigationController?.topViewController as? ViewController)?.present(controller, in: .window(.root), with: nil)
|
(baseNavigationController?.topViewController as? ViewController)?.present(controller, in: .window(.root), with: nil)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -2579,15 +2579,14 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode {
|
|||||||
|
|
||||||
@objc func openStickersButtonPressed() {
|
@objc func openStickersButtonPressed() {
|
||||||
if let content = self.item?.content as? NativeVideoContent {
|
if let content = self.item?.content as? NativeVideoContent {
|
||||||
|
let context = self.context
|
||||||
let media = content.fileReference.abstract
|
let media = content.fileReference.abstract
|
||||||
|
|
||||||
let presentationData = self.context.sharedContext.currentPresentationData.with { $0 }
|
let presentationData = self.context.sharedContext.currentPresentationData.with { $0 }
|
||||||
let progressSignal = Signal<Never, NoError> { [weak self] subscriber in
|
let topController = (self.baseNavigationController()?.topViewController as? ViewController)
|
||||||
guard let strongSelf = self else {
|
let progressSignal = Signal<Never, NoError> { subscriber in
|
||||||
return EmptyDisposable
|
|
||||||
}
|
|
||||||
let controller = OverlayStatusController(theme: presentationData.theme, type: .loading(cancelled: nil))
|
let controller = OverlayStatusController(theme: presentationData.theme, type: .loading(cancelled: nil))
|
||||||
(strongSelf.baseNavigationController()?.topViewController as? ViewController)?.present(controller, in: .window(.root), with: nil)
|
topController?.present(controller, in: .window(.root), with: nil)
|
||||||
return ActionDisposable { [weak controller] in
|
return ActionDisposable { [weak controller] in
|
||||||
Queue.mainQueue().async() {
|
Queue.mainQueue().async() {
|
||||||
controller?.dismiss()
|
controller?.dismiss()
|
||||||
@ -2613,7 +2612,22 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode {
|
|||||||
}
|
}
|
||||||
let baseNavigationController = strongSelf.baseNavigationController()
|
let baseNavigationController = strongSelf.baseNavigationController()
|
||||||
baseNavigationController?.view.endEditing(true)
|
baseNavigationController?.view.endEditing(true)
|
||||||
let controller = StickerPackScreen(context: strongSelf.context, mainStickerPack: packs[0], stickerPacks: packs, sendSticker: nil, dismissed: { [weak self] in
|
let controller = StickerPackScreen(context: strongSelf.context, mainStickerPack: packs[0], stickerPacks: packs, sendSticker: nil, actionPerformed: { info, items, action in
|
||||||
|
let animateInAsReplacement = false
|
||||||
|
switch action {
|
||||||
|
case .add:
|
||||||
|
topController?.present(UndoOverlayController(presentationData: presentationData, content: .stickersModified(title: presentationData.strings.StickerPackActionInfo_AddedTitle, text: presentationData.strings.StickerPackActionInfo_AddedText(info.title).string, undo: false, info: info, topItem: items.first, context: context), elevatedLayout: true, animateInAsReplacement: animateInAsReplacement, action: { _ in
|
||||||
|
return true
|
||||||
|
}), in: .window(.root))
|
||||||
|
case let .remove(positionInList):
|
||||||
|
topController?.present(UndoOverlayController(presentationData: presentationData, content: .stickersModified(title: presentationData.strings.StickerPackActionInfo_RemovedTitle, text: presentationData.strings.StickerPackActionInfo_RemovedText(info.title).string, undo: true, info: info, topItem: items.first, context: context), elevatedLayout: true, animateInAsReplacement: animateInAsReplacement, action: { action in
|
||||||
|
if case .undo = action {
|
||||||
|
let _ = context.engine.stickers.addStickerPackInteractively(info: info, items: items, positionInList: positionInList).start()
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}), in: .window(.root))
|
||||||
|
}
|
||||||
|
}, dismissed: { [weak self] in
|
||||||
self?.isInteractingPromise.set(false)
|
self?.isInteractingPromise.set(false)
|
||||||
})
|
})
|
||||||
(baseNavigationController?.topViewController as? ViewController)?.present(controller, in: .window(.root), with: nil)
|
(baseNavigationController?.topViewController as? ViewController)?.present(controller, in: .window(.root), with: nil)
|
||||||
|
@ -292,7 +292,7 @@ private func channelMembersControllerEntries(context: AccountContext, presentati
|
|||||||
|
|
||||||
var entries: [ChannelMembersEntry] = []
|
var entries: [ChannelMembersEntry] = []
|
||||||
|
|
||||||
if let participants = participants {
|
if let participants = participants, let contacts = contacts {
|
||||||
var canAddMember: Bool = false
|
var canAddMember: Bool = false
|
||||||
if let peer = view.peers[view.peerId] as? TelegramChannel {
|
if let peer = view.peers[view.peerId] as? TelegramChannel {
|
||||||
canAddMember = peer.hasPermission(.inviteMembers)
|
canAddMember = peer.hasPermission(.inviteMembers)
|
||||||
@ -322,7 +322,7 @@ private func channelMembersControllerEntries(context: AccountContext, presentati
|
|||||||
var existingPeerIds = Set<PeerId>()
|
var existingPeerIds = Set<PeerId>()
|
||||||
|
|
||||||
var addedContactsHeader = false
|
var addedContactsHeader = false
|
||||||
if let contacts = contacts, !contacts.isEmpty {
|
if !contacts.isEmpty {
|
||||||
addedContactsHeader = true
|
addedContactsHeader = true
|
||||||
|
|
||||||
entries.append(.contactsTitle(presentationData.theme, isGroup ? presentationData.strings.Group_Members_Contacts : presentationData.strings.Channel_Members_Contacts))
|
entries.append(.contactsTitle(presentationData.theme, isGroup ? presentationData.strings.Group_Members_Contacts : presentationData.strings.Channel_Members_Contacts))
|
||||||
@ -603,12 +603,14 @@ public func channelMembersController(context: AccountContext, updatedPresentatio
|
|||||||
currentPeers = peers
|
currentPeers = peers
|
||||||
|
|
||||||
var animateChanges = false
|
var animateChanges = false
|
||||||
if let previousContacts = previousContacts, let contacts = contacts, previousContacts.count >= contacts.count {
|
if let previousContacts = previousContacts, let contacts = contacts, let previousPeers = previousPeers, let peers = peers {
|
||||||
|
if previousContacts.count >= contacts.count {
|
||||||
animateChanges = true
|
animateChanges = true
|
||||||
}
|
}
|
||||||
if let previousPeers = previousPeers, let peers = peers, previousPeers.count >= peers.count {
|
if previousPeers.count >= peers.count {
|
||||||
animateChanges = true
|
animateChanges = true
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let controllerState = ItemListControllerState(presentationData: ItemListPresentationData(presentationData), title: .text(isGroup ? presentationData.strings.Group_Members_Title : presentationData.strings.Channel_Subscribers_Title), leftNavigationButton: nil, rightNavigationButton: rightNavigationButton, secondaryRightNavigationButton: secondaryRightNavigationButton, backNavigationButton: ItemListBackButton(title: presentationData.strings.Common_Back), animateChanges: true)
|
let controllerState = ItemListControllerState(presentationData: ItemListPresentationData(presentationData), title: .text(isGroup ? presentationData.strings.Group_Members_Title : presentationData.strings.Channel_Subscribers_Title), leftNavigationButton: nil, rightNavigationButton: rightNavigationButton, secondaryRightNavigationButton: secondaryRightNavigationButton, backNavigationButton: ItemListBackButton(title: presentationData.strings.Common_Back), animateChanges: true)
|
||||||
let listState = ItemListNodeState(presentationData: ItemListPresentationData(presentationData), entries: channelMembersControllerEntries(context: context, presentationData: presentationData, view: view, state: state, contacts: contacts, participants: peers, isGroup: isGroup), style: .blocks, emptyStateItem: emptyStateItem, searchItem: searchItem, animateChanges: animateChanges)
|
let listState = ItemListNodeState(presentationData: ItemListPresentationData(presentationData), entries: channelMembersControllerEntries(context: context, presentationData: presentationData, view: view, state: state, contacts: contacts, participants: peers, isGroup: isGroup), style: .blocks, emptyStateItem: emptyStateItem, searchItem: searchItem, animateChanges: animateChanges)
|
||||||
|
@ -1086,7 +1086,7 @@ func contextMenuForChatPresentationInterfaceState(chatPresentationInterfaceState
|
|||||||
}
|
}
|
||||||
if let file = media as? TelegramMediaFile, !chatPresentationInterfaceState.copyProtectionEnabled && !message.isCopyProtected() {
|
if let file = media as? TelegramMediaFile, !chatPresentationInterfaceState.copyProtectionEnabled && !message.isCopyProtected() {
|
||||||
if file.isVideo {
|
if file.isVideo {
|
||||||
if file.isAnimated {
|
if file.isAnimated && !file.isVideoSticker {
|
||||||
actions.append(.action(ContextMenuActionItem(text: chatPresentationInterfaceState.strings.Conversation_LinkDialogSave, icon: { theme in
|
actions.append(.action(ContextMenuActionItem(text: chatPresentationInterfaceState.strings.Conversation_LinkDialogSave, icon: { theme in
|
||||||
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Save"), color: theme.actionSheet.primaryTextColor)
|
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Save"), color: theme.actionSheet.primaryTextColor)
|
||||||
}, action: { _, f in
|
}, action: { _, f in
|
||||||
|
@ -147,7 +147,21 @@ func openResolvedUrlImpl(_ resolvedUrl: ResolvedUrl, context: AccountContext, ur
|
|||||||
present(controller, nil)
|
present(controller, nil)
|
||||||
}
|
}
|
||||||
} else {*/
|
} else {*/
|
||||||
let controller = StickerPackScreen(context: context, updatedPresentationData: updatedPresentationData, mainStickerPack: .name(name), stickerPacks: [.name(name)], parentNavigationController: navigationController, sendSticker: sendSticker)
|
let controller = StickerPackScreen(context: context, updatedPresentationData: updatedPresentationData, mainStickerPack: .name(name), stickerPacks: [.name(name)], parentNavigationController: navigationController, sendSticker: sendSticker, actionPerformed: { info, items, action in
|
||||||
|
switch action {
|
||||||
|
case .add:
|
||||||
|
present(UndoOverlayController(presentationData: presentationData, content: .stickersModified(title: presentationData.strings.StickerPackActionInfo_AddedTitle, text: presentationData.strings.StickerPackActionInfo_AddedText(info.title).string, undo: false, info: info, topItem: items.first, context: context), elevatedLayout: true, animateInAsReplacement: false, action: { _ in
|
||||||
|
return true
|
||||||
|
}), nil)
|
||||||
|
case let .remove(positionInList):
|
||||||
|
present(UndoOverlayController(presentationData: presentationData, content: .stickersModified(title: presentationData.strings.StickerPackActionInfo_RemovedTitle, text: presentationData.strings.StickerPackActionInfo_RemovedText(info.title).string, undo: true, info: info, topItem: items.first, context: context), elevatedLayout: true, animateInAsReplacement: false, action: { action in
|
||||||
|
if case .undo = action {
|
||||||
|
let _ = context.engine.stickers.addStickerPackInteractively(info: info, items: items, positionInList: positionInList).start()
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}), nil)
|
||||||
|
}
|
||||||
|
})
|
||||||
present(controller, nil)
|
present(controller, nil)
|
||||||
//}
|
//}
|
||||||
case let .instantView(webpage, anchor):
|
case let .instantView(webpage, anchor):
|
||||||
|
@ -734,7 +734,7 @@ final class PeerChannelMemberCategoriesContext {
|
|||||||
let context: ChannelMemberCategoryListContext
|
let context: ChannelMemberCategoryListContext
|
||||||
let emptyTimeout: Double
|
let emptyTimeout: Double
|
||||||
switch key {
|
switch key {
|
||||||
case .admins(nil), .banned(nil), .recentSearch(nil), .restricted(nil), .restrictedAndBanned(nil), .recent:
|
case .admins(nil), .banned(nil), .recentSearch(nil), .restricted(nil), .restrictedAndBanned(nil), .recent, .contacts:
|
||||||
emptyTimeout = defaultEmptyTimeout
|
emptyTimeout = defaultEmptyTimeout
|
||||||
default:
|
default:
|
||||||
emptyTimeout = 0.0
|
emptyTimeout = 0.0
|
||||||
|
Loading…
x
Reference in New Issue
Block a user