mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-11-07 09:20:08 +00:00
Added option to disable animated stickers looped playback across all the app
This commit is contained in:
parent
6ff5c91fa3
commit
0197abb082
@ -5,6 +5,7 @@ import SwiftSignalKit
|
|||||||
import Postbox
|
import Postbox
|
||||||
import TelegramCore
|
import TelegramCore
|
||||||
import TelegramPresentationData
|
import TelegramPresentationData
|
||||||
|
import TelegramUIPreferences
|
||||||
|
|
||||||
public enum ArchivedStickerPacksControllerMode {
|
public enum ArchivedStickerPacksControllerMode {
|
||||||
case stickers
|
case stickers
|
||||||
@ -65,7 +66,7 @@ private enum ArchivedStickerPacksEntryId: Hashable {
|
|||||||
|
|
||||||
private enum ArchivedStickerPacksEntry: ItemListNodeEntry {
|
private enum ArchivedStickerPacksEntry: ItemListNodeEntry {
|
||||||
case info(PresentationTheme, String)
|
case info(PresentationTheme, String)
|
||||||
case pack(Int32, PresentationTheme, PresentationStrings, StickerPackCollectionInfo, StickerPackItem?, String, Bool, ItemListStickerPackItemEditing)
|
case pack(Int32, PresentationTheme, PresentationStrings, StickerPackCollectionInfo, StickerPackItem?, String, Bool, Bool, ItemListStickerPackItemEditing)
|
||||||
|
|
||||||
var section: ItemListSectionId {
|
var section: ItemListSectionId {
|
||||||
switch self {
|
switch self {
|
||||||
@ -78,7 +79,7 @@ private enum ArchivedStickerPacksEntry: ItemListNodeEntry {
|
|||||||
switch self {
|
switch self {
|
||||||
case .info:
|
case .info:
|
||||||
return .index(0)
|
return .index(0)
|
||||||
case let .pack(_, _, _, info, _, _, _, _):
|
case let .pack(_, _, _, info, _, _, _, _, _):
|
||||||
return .pack(info.id)
|
return .pack(info.id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -91,8 +92,8 @@ private enum ArchivedStickerPacksEntry: ItemListNodeEntry {
|
|||||||
} else {
|
} else {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
case let .pack(lhsIndex, lhsTheme, lhsStrings, lhsInfo, lhsTopItem, lhsCount, lhsEnabled, lhsEditing):
|
case let .pack(lhsIndex, lhsTheme, lhsStrings, lhsInfo, lhsTopItem, lhsCount, lhsPlayAnimatedStickers, lhsEnabled, lhsEditing):
|
||||||
if case let .pack(rhsIndex, rhsTheme, rhsStrings, rhsInfo, rhsTopItem, rhsCount, rhsEnabled, rhsEditing) = rhs {
|
if case let .pack(rhsIndex, rhsTheme, rhsStrings, rhsInfo, rhsTopItem, rhsCount, rhsPlayAnimatedStickers, rhsEnabled, rhsEditing) = rhs {
|
||||||
if lhsIndex != rhsIndex {
|
if lhsIndex != rhsIndex {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@ -111,6 +112,9 @@ private enum ArchivedStickerPacksEntry: ItemListNodeEntry {
|
|||||||
if lhsCount != rhsCount {
|
if lhsCount != rhsCount {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
if lhsPlayAnimatedStickers != rhsPlayAnimatedStickers {
|
||||||
|
return false
|
||||||
|
}
|
||||||
if lhsEnabled != rhsEnabled {
|
if lhsEnabled != rhsEnabled {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@ -133,9 +137,9 @@ private enum ArchivedStickerPacksEntry: ItemListNodeEntry {
|
|||||||
default:
|
default:
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
case let .pack(lhsIndex, _, _, _, _, _, _, _):
|
case let .pack(lhsIndex, _, _, _, _, _, _, _, _):
|
||||||
switch rhs {
|
switch rhs {
|
||||||
case let .pack(rhsIndex, _, _, _, _, _, _, _):
|
case let .pack(rhsIndex, _, _, _, _, _, _, _, _):
|
||||||
return lhsIndex < rhsIndex
|
return lhsIndex < rhsIndex
|
||||||
default:
|
default:
|
||||||
return false
|
return false
|
||||||
@ -147,8 +151,8 @@ private enum ArchivedStickerPacksEntry: ItemListNodeEntry {
|
|||||||
switch self {
|
switch self {
|
||||||
case let .info(theme, text):
|
case let .info(theme, text):
|
||||||
return ItemListTextItem(theme: theme, text: .plain(text), sectionId: self.section)
|
return ItemListTextItem(theme: theme, text: .plain(text), sectionId: self.section)
|
||||||
case let .pack(_, theme, strings, info, topItem, count, enabled, editing):
|
case let .pack(_, theme, strings, info, topItem, count, animatedStickers, enabled, editing):
|
||||||
return ItemListStickerPackItem(theme: theme, strings: strings, account: arguments.account, packInfo: info, itemCount: count, topItem: topItem, unread: false, control: .installation(installed: false), editing: editing, enabled: enabled, sectionId: self.section, action: {
|
return ItemListStickerPackItem(theme: theme, strings: strings, account: arguments.account, packInfo: info, itemCount: count, topItem: topItem, unread: false, control: .installation(installed: false), editing: editing, enabled: enabled, playAnimatedStickers: animatedStickers, sectionId: self.section, action: {
|
||||||
arguments.openStickerPack(info)
|
arguments.openStickerPack(info)
|
||||||
}, setPackIdWithRevealedOptions: { current, previous in
|
}, setPackIdWithRevealedOptions: { current, previous in
|
||||||
arguments.setPackIdWithRevealedOptions(current, previous)
|
arguments.setPackIdWithRevealedOptions(current, previous)
|
||||||
@ -205,7 +209,7 @@ private struct ArchivedStickerPacksControllerState: Equatable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private func archivedStickerPacksControllerEntries(presentationData: PresentationData, state: ArchivedStickerPacksControllerState, packs: [ArchivedStickerPackItem]?, installedView: CombinedView) -> [ArchivedStickerPacksEntry] {
|
private func archivedStickerPacksControllerEntries(presentationData: PresentationData, state: ArchivedStickerPacksControllerState, packs: [ArchivedStickerPackItem]?, installedView: CombinedView, stickerSettings: StickerSettings) -> [ArchivedStickerPacksEntry] {
|
||||||
var entries: [ArchivedStickerPacksEntry] = []
|
var entries: [ArchivedStickerPacksEntry] = []
|
||||||
|
|
||||||
if let packs = packs {
|
if let packs = packs {
|
||||||
@ -219,7 +223,7 @@ private func archivedStickerPacksControllerEntries(presentationData: Presentatio
|
|||||||
var index: Int32 = 0
|
var index: Int32 = 0
|
||||||
for item in packs {
|
for item in packs {
|
||||||
if !installedIds.contains(item.info.id) {
|
if !installedIds.contains(item.info.id) {
|
||||||
entries.append(.pack(index, presentationData.theme, presentationData.strings, item.info, item.topItems.first, presentationData.strings.StickerPack_StickerCount(item.info.count), !state.removingPackIds.contains(item.info.id), ItemListStickerPackItemEditing(editable: true, editing: state.editing, revealed: state.packIdWithRevealedOptions == item.info.id, reorderable: false)))
|
entries.append(.pack(index, presentationData.theme, presentationData.strings, item.info, item.topItems.first, presentationData.strings.StickerPack_StickerCount(item.info.count), stickerSettings.loopAnimatedStickers, !state.removingPackIds.contains(item.info.id), ItemListStickerPackItemEditing(editable: true, editing: state.editing, revealed: state.packIdWithRevealedOptions == item.info.id, reorderable: false)))
|
||||||
index += 1
|
index += 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -369,9 +373,14 @@ public func archivedStickerPacksController(context: AccountContext, mode: Archiv
|
|||||||
|
|
||||||
var previousPackCount: Int?
|
var previousPackCount: Int?
|
||||||
|
|
||||||
let signal = combineLatest(context.sharedContext.presentationData, statePromise.get() |> deliverOnMainQueue, stickerPacks.get() |> deliverOnMainQueue, installedStickerPacks.get() |> deliverOnMainQueue)
|
let signal = combineLatest(context.sharedContext.presentationData, statePromise.get() |> deliverOnMainQueue, stickerPacks.get() |> deliverOnMainQueue, installedStickerPacks.get() |> deliverOnMainQueue, context.sharedContext.accountManager.sharedData(keys: [ApplicationSpecificSharedDataKeys.stickerSettings]) |> deliverOnMainQueue)
|
||||||
|> deliverOnMainQueue
|
|> deliverOnMainQueue
|
||||||
|> map { presentationData, state, packs, installedView -> (ItemListControllerState, (ItemListNodeState<ArchivedStickerPacksEntry>, ArchivedStickerPacksEntry.ItemGenerationArguments)) in
|
|> map { presentationData, state, packs, installedView, sharedData -> (ItemListControllerState, (ItemListNodeState<ArchivedStickerPacksEntry>, ArchivedStickerPacksEntry.ItemGenerationArguments)) in
|
||||||
|
var stickerSettings = StickerSettings.defaultSettings
|
||||||
|
if let value = sharedData.entries[ApplicationSpecificSharedDataKeys.stickerSettings] as? StickerSettings {
|
||||||
|
stickerSettings = value
|
||||||
|
}
|
||||||
|
|
||||||
var rightNavigationButton: ItemListNavigationButton?
|
var rightNavigationButton: ItemListNavigationButton?
|
||||||
if let packs = packs, packs.count != 0 {
|
if let packs = packs, packs.count != 0 {
|
||||||
if state.editing {
|
if state.editing {
|
||||||
@ -399,7 +408,7 @@ public func archivedStickerPacksController(context: AccountContext, mode: Archiv
|
|||||||
|
|
||||||
let controllerState = ItemListControllerState(theme: presentationData.theme, title: .text(presentationData.strings.StickerPacksSettings_ArchivedPacks), leftNavigationButton: nil, rightNavigationButton: rightNavigationButton, backNavigationButton: ItemListBackButton(title: presentationData.strings.Common_Back), animateChanges: true)
|
let controllerState = ItemListControllerState(theme: presentationData.theme, title: .text(presentationData.strings.StickerPacksSettings_ArchivedPacks), leftNavigationButton: nil, rightNavigationButton: rightNavigationButton, backNavigationButton: ItemListBackButton(title: presentationData.strings.Common_Back), animateChanges: true)
|
||||||
|
|
||||||
let listState = ItemListNodeState(entries: archivedStickerPacksControllerEntries(presentationData: presentationData, state: state, packs: packs, installedView: installedView), style: .blocks, emptyStateItem: emptyStateItem, animateChanges: previous != nil && packs != nil && (previous! != 0 && previous! >= packs!.count - 10))
|
let listState = ItemListNodeState(entries: archivedStickerPacksControllerEntries(presentationData: presentationData, state: state, packs: packs, installedView: installedView, stickerSettings: stickerSettings), style: .blocks, emptyStateItem: emptyStateItem, animateChanges: previous != nil && packs != nil && (previous! != 0 && previous! >= packs!.count - 10))
|
||||||
return (controllerState, (listState, arguments))
|
return (controllerState, (listState, arguments))
|
||||||
} |> afterDisposed {
|
} |> afterDisposed {
|
||||||
actionsDisposable.dispose()
|
actionsDisposable.dispose()
|
||||||
|
|||||||
@ -208,6 +208,9 @@ public final class ChatController: TelegramController, GalleryHiddenMediaTarget,
|
|||||||
private var automaticMediaDownloadSettings: MediaAutoDownloadSettings
|
private var automaticMediaDownloadSettings: MediaAutoDownloadSettings
|
||||||
private var automaticMediaDownloadSettingsDisposable: Disposable?
|
private var automaticMediaDownloadSettingsDisposable: Disposable?
|
||||||
|
|
||||||
|
private var stickerSettings: ChatInterfaceStickerSettings
|
||||||
|
private var stickerSettingsDisposable: Disposable?
|
||||||
|
|
||||||
private var applicationInForegroundDisposable: Disposable?
|
private var applicationInForegroundDisposable: Disposable?
|
||||||
|
|
||||||
private var checkedPeerChatServiceActions = false
|
private var checkedPeerChatServiceActions = false
|
||||||
@ -264,6 +267,8 @@ public final class ChatController: TelegramController, GalleryHiddenMediaTarget,
|
|||||||
self.presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
self.presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||||
self.automaticMediaDownloadSettings = context.sharedContext.currentAutomaticMediaDownloadSettings.with { $0 }
|
self.automaticMediaDownloadSettings = context.sharedContext.currentAutomaticMediaDownloadSettings.with { $0 }
|
||||||
|
|
||||||
|
self.stickerSettings = ChatInterfaceStickerSettings(loopAnimatedStickers: false)
|
||||||
|
|
||||||
self.presentationInterfaceState = ChatPresentationInterfaceState(chatWallpaper: self.presentationData.chatWallpaper, theme: self.presentationData.theme, strings: self.presentationData.strings, dateTimeFormat: self.presentationData.dateTimeFormat, nameDisplayOrder: self.presentationData.nameDisplayOrder, limitsConfiguration: context.currentLimitsConfiguration.with { $0 }, fontSize: self.presentationData.fontSize, accountPeerId: context.account.peerId, mode: mode, chatLocation: chatLocation)
|
self.presentationInterfaceState = ChatPresentationInterfaceState(chatWallpaper: self.presentationData.chatWallpaper, theme: self.presentationData.theme, strings: self.presentationData.strings, dateTimeFormat: self.presentationData.dateTimeFormat, nameDisplayOrder: self.presentationData.nameDisplayOrder, limitsConfiguration: context.currentLimitsConfiguration.with { $0 }, fontSize: self.presentationData.fontSize, accountPeerId: context.account.peerId, mode: mode, chatLocation: chatLocation)
|
||||||
|
|
||||||
var mediaAccessoryPanelVisibility = MediaAccessoryPanelVisibility.none
|
var mediaAccessoryPanelVisibility = MediaAccessoryPanelVisibility.none
|
||||||
@ -1378,8 +1383,7 @@ public final class ChatController: TelegramController, GalleryHiddenMediaTarget,
|
|||||||
}, cancelInteractiveKeyboardGestures: { [weak self] in
|
}, cancelInteractiveKeyboardGestures: { [weak self] in
|
||||||
(self?.view.window as? WindowHost)?.cancelInteractiveKeyboardGestures()
|
(self?.view.window as? WindowHost)?.cancelInteractiveKeyboardGestures()
|
||||||
self?.chatDisplayNode.cancelInteractiveKeyboardGestures()
|
self?.chatDisplayNode.cancelInteractiveKeyboardGestures()
|
||||||
}, automaticMediaDownloadSettings: self.automaticMediaDownloadSettings,
|
}, automaticMediaDownloadSettings: self.automaticMediaDownloadSettings, pollActionState: ChatInterfacePollActionState(), stickerSettings: self.stickerSettings)
|
||||||
pollActionState: ChatInterfacePollActionState())
|
|
||||||
|
|
||||||
self.controllerInteraction = controllerInteraction
|
self.controllerInteraction = controllerInteraction
|
||||||
|
|
||||||
@ -1884,6 +1888,24 @@ public final class ChatController: TelegramController, GalleryHiddenMediaTarget,
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
self.stickerSettingsDisposable = (context.sharedContext.accountManager.sharedData(keys: [ApplicationSpecificSharedDataKeys.stickerSettings])
|
||||||
|
|> deliverOnMainQueue).start(next: { [weak self] sharedData in
|
||||||
|
var stickerSettings = StickerSettings.defaultSettings
|
||||||
|
if let value = sharedData.entries[ApplicationSpecificSharedDataKeys.stickerSettings] as? StickerSettings {
|
||||||
|
stickerSettings = value
|
||||||
|
}
|
||||||
|
|
||||||
|
let chatStickerSettings = ChatInterfaceStickerSettings(stickerSettings: stickerSettings)
|
||||||
|
|
||||||
|
if let strongSelf = self, strongSelf.stickerSettings != chatStickerSettings {
|
||||||
|
strongSelf.stickerSettings = chatStickerSettings
|
||||||
|
strongSelf.controllerInteraction?.stickerSettings = chatStickerSettings
|
||||||
|
if strongSelf.isNodeLoaded {
|
||||||
|
strongSelf.chatDisplayNode.updateStickerSettings(chatStickerSettings)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
self.applicationInForegroundDisposable = (context.sharedContext.applicationBindings.applicationInForeground
|
self.applicationInForegroundDisposable = (context.sharedContext.applicationBindings.applicationInForeground
|
||||||
|> distinctUntilChanged
|
|> distinctUntilChanged
|
||||||
|> deliverOn(Queue.mainQueue())).start(next: { [weak self] value in
|
|> deliverOn(Queue.mainQueue())).start(next: { [weak self] value in
|
||||||
|
|||||||
@ -31,6 +31,22 @@ struct ChatInterfaceHighlightedState: Equatable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct ChatInterfaceStickerSettings: Equatable {
|
||||||
|
let loopAnimatedStickers: Bool
|
||||||
|
|
||||||
|
public init(loopAnimatedStickers: Bool) {
|
||||||
|
self.loopAnimatedStickers = loopAnimatedStickers
|
||||||
|
}
|
||||||
|
|
||||||
|
public init(stickerSettings: StickerSettings) {
|
||||||
|
self.loopAnimatedStickers = stickerSettings.loopAnimatedStickers
|
||||||
|
}
|
||||||
|
|
||||||
|
static func ==(lhs: ChatInterfaceStickerSettings, rhs: ChatInterfaceStickerSettings) -> Bool {
|
||||||
|
return lhs.loopAnimatedStickers == rhs.loopAnimatedStickers
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public enum ChatControllerInteractionLongTapAction {
|
public enum ChatControllerInteractionLongTapAction {
|
||||||
case url(String)
|
case url(String)
|
||||||
case mention(String)
|
case mention(String)
|
||||||
@ -104,9 +120,10 @@ public final class ChatControllerInteraction {
|
|||||||
var contextHighlightedState: ChatInterfaceHighlightedState?
|
var contextHighlightedState: ChatInterfaceHighlightedState?
|
||||||
var automaticMediaDownloadSettings: MediaAutoDownloadSettings
|
var automaticMediaDownloadSettings: MediaAutoDownloadSettings
|
||||||
var pollActionState: ChatInterfacePollActionState
|
var pollActionState: ChatInterfacePollActionState
|
||||||
|
var stickerSettings: ChatInterfaceStickerSettings
|
||||||
var searchTextHighightState: String?
|
var searchTextHighightState: String?
|
||||||
|
|
||||||
init(openMessage: @escaping (Message, ChatControllerInteractionOpenMessageMode) -> Bool, openPeer: @escaping (PeerId?, ChatControllerInteractionNavigateToPeer, Message?) -> Void, openPeerMention: @escaping (String) -> Void, openMessageContextMenu: @escaping (Message, Bool, ASDisplayNode, CGRect) -> Void, navigateToMessage: @escaping (MessageId, MessageId) -> Void, clickThroughMessage: @escaping () -> Void, toggleMessagesSelection: @escaping ([MessageId], Bool) -> Void, sendMessage: @escaping (String) -> Void, sendSticker: @escaping (FileMediaReference, Bool) -> Void, sendGif: @escaping (FileMediaReference) -> Void, requestMessageActionCallback: @escaping (MessageId, MemoryBuffer?, Bool) -> Void, requestMessageActionUrlAuth: @escaping (String, MessageId, Int32) -> Void, activateSwitchInline: @escaping (PeerId?, String) -> Void, openUrl: @escaping (String, Bool, Bool?) -> Void, shareCurrentLocation: @escaping () -> Void, shareAccountContact: @escaping () -> Void, sendBotCommand: @escaping (MessageId?, String) -> Void, openInstantPage: @escaping (Message, ChatMessageItemAssociatedData?) -> Void, openWallpaper: @escaping (Message) -> Void, openHashtag: @escaping (String?, String) -> Void, updateInputState: @escaping ((ChatTextInputState) -> ChatTextInputState) -> Void, updateInputMode: @escaping ((ChatInputMode) -> ChatInputMode) -> Void, openMessageShareMenu: @escaping (MessageId) -> Void, presentController: @escaping (ViewController, Any?) -> Void, navigationController: @escaping () -> NavigationController?, presentGlobalOverlayController: @escaping (ViewController, Any?) -> Void, callPeer: @escaping (PeerId) -> Void, longTap: @escaping (ChatControllerInteractionLongTapAction, Message?) -> Void, openCheckoutOrReceipt: @escaping (MessageId) -> Void, openSearch: @escaping () -> Void, setupReply: @escaping (MessageId) -> Void, canSetupReply: @escaping (Message) -> Bool, navigateToFirstDateMessage: @escaping(Int32) ->Void, requestRedeliveryOfFailedMessages: @escaping (MessageId) -> Void, addContact: @escaping (String) -> Void, rateCall: @escaping (Message, CallId) -> Void, requestSelectMessagePollOption: @escaping (MessageId, Data) -> Void, openAppStorePage: @escaping () -> Void, displayMessageTooltip: @escaping (MessageId, String, ASDisplayNode?, CGRect?) -> Void, seekToTimecode: @escaping (Message, Double, Bool) -> Void, requestMessageUpdate: @escaping (MessageId) -> Void, cancelInteractiveKeyboardGestures: @escaping () -> Void, automaticMediaDownloadSettings: MediaAutoDownloadSettings, pollActionState: ChatInterfacePollActionState) {
|
init(openMessage: @escaping (Message, ChatControllerInteractionOpenMessageMode) -> Bool, openPeer: @escaping (PeerId?, ChatControllerInteractionNavigateToPeer, Message?) -> Void, openPeerMention: @escaping (String) -> Void, openMessageContextMenu: @escaping (Message, Bool, ASDisplayNode, CGRect) -> Void, navigateToMessage: @escaping (MessageId, MessageId) -> Void, clickThroughMessage: @escaping () -> Void, toggleMessagesSelection: @escaping ([MessageId], Bool) -> Void, sendMessage: @escaping (String) -> Void, sendSticker: @escaping (FileMediaReference, Bool) -> Void, sendGif: @escaping (FileMediaReference) -> Void, requestMessageActionCallback: @escaping (MessageId, MemoryBuffer?, Bool) -> Void, requestMessageActionUrlAuth: @escaping (String, MessageId, Int32) -> Void, activateSwitchInline: @escaping (PeerId?, String) -> Void, openUrl: @escaping (String, Bool, Bool?) -> Void, shareCurrentLocation: @escaping () -> Void, shareAccountContact: @escaping () -> Void, sendBotCommand: @escaping (MessageId?, String) -> Void, openInstantPage: @escaping (Message, ChatMessageItemAssociatedData?) -> Void, openWallpaper: @escaping (Message) -> Void, openHashtag: @escaping (String?, String) -> Void, updateInputState: @escaping ((ChatTextInputState) -> ChatTextInputState) -> Void, updateInputMode: @escaping ((ChatInputMode) -> ChatInputMode) -> Void, openMessageShareMenu: @escaping (MessageId) -> Void, presentController: @escaping (ViewController, Any?) -> Void, navigationController: @escaping () -> NavigationController?, presentGlobalOverlayController: @escaping (ViewController, Any?) -> Void, callPeer: @escaping (PeerId) -> Void, longTap: @escaping (ChatControllerInteractionLongTapAction, Message?) -> Void, openCheckoutOrReceipt: @escaping (MessageId) -> Void, openSearch: @escaping () -> Void, setupReply: @escaping (MessageId) -> Void, canSetupReply: @escaping (Message) -> Bool, navigateToFirstDateMessage: @escaping(Int32) ->Void, requestRedeliveryOfFailedMessages: @escaping (MessageId) -> Void, addContact: @escaping (String) -> Void, rateCall: @escaping (Message, CallId) -> Void, requestSelectMessagePollOption: @escaping (MessageId, Data) -> Void, openAppStorePage: @escaping () -> Void, displayMessageTooltip: @escaping (MessageId, String, ASDisplayNode?, CGRect?) -> Void, seekToTimecode: @escaping (Message, Double, Bool) -> Void, requestMessageUpdate: @escaping (MessageId) -> Void, cancelInteractiveKeyboardGestures: @escaping () -> Void, automaticMediaDownloadSettings: MediaAutoDownloadSettings, pollActionState: ChatInterfacePollActionState, stickerSettings: ChatInterfaceStickerSettings) {
|
||||||
self.openMessage = openMessage
|
self.openMessage = openMessage
|
||||||
self.openPeer = openPeer
|
self.openPeer = openPeer
|
||||||
self.openPeerMention = openPeerMention
|
self.openPeerMention = openPeerMention
|
||||||
@ -154,6 +171,7 @@ public final class ChatControllerInteraction {
|
|||||||
self.automaticMediaDownloadSettings = automaticMediaDownloadSettings
|
self.automaticMediaDownloadSettings = automaticMediaDownloadSettings
|
||||||
|
|
||||||
self.pollActionState = pollActionState
|
self.pollActionState = pollActionState
|
||||||
|
self.stickerSettings = stickerSettings
|
||||||
}
|
}
|
||||||
|
|
||||||
static var `default`: ChatControllerInteraction {
|
static var `default`: ChatControllerInteraction {
|
||||||
@ -175,6 +193,6 @@ public final class ChatControllerInteraction {
|
|||||||
}, requestMessageUpdate: { _ in
|
}, requestMessageUpdate: { _ in
|
||||||
}, cancelInteractiveKeyboardGestures: {
|
}, cancelInteractiveKeyboardGestures: {
|
||||||
}, automaticMediaDownloadSettings: MediaAutoDownloadSettings.defaultSettings,
|
}, automaticMediaDownloadSettings: MediaAutoDownloadSettings.defaultSettings,
|
||||||
pollActionState: ChatInterfacePollActionState())
|
pollActionState: ChatInterfacePollActionState(), stickerSettings: ChatInterfaceStickerSettings(loopAnimatedStickers: false))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1497,6 +1497,14 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate {
|
|||||||
self.historyNode.prefetchManager.updateAutoDownloadSettings(settings)
|
self.historyNode.prefetchManager.updateAutoDownloadSettings(settings)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func updateStickerSettings(_ settings: ChatInterfaceStickerSettings) {
|
||||||
|
self.historyNode.forEachItemNode { itemNode in
|
||||||
|
if let itemNode = itemNode as? ChatMessageItemView {
|
||||||
|
itemNode.updateStickerSettings()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var isInputViewFocused: Bool {
|
var isInputViewFocused: Bool {
|
||||||
if let inputPanelNode = self.inputPanelNode as? ChatTextInputPanelNode {
|
if let inputPanelNode = self.inputPanelNode as? ChatTextInputPanelNode {
|
||||||
return inputPanelNode.isFocused
|
return inputPanelNode.isFocused
|
||||||
|
|||||||
@ -145,7 +145,6 @@ final class ChatMediaInputStickerGridItem: GridItem {
|
|||||||
let node = ChatMediaInputStickerGridItemNode()
|
let node = ChatMediaInputStickerGridItemNode()
|
||||||
node.interfaceInteraction = self.interfaceInteraction
|
node.interfaceInteraction = self.interfaceInteraction
|
||||||
node.inputNodeInteraction = self.inputNodeInteraction
|
node.inputNodeInteraction = self.inputNodeInteraction
|
||||||
node.setup(account: self.account, stickerItem: self.stickerItem)
|
|
||||||
node.selected = self.selected
|
node.selected = self.selected
|
||||||
return node
|
return node
|
||||||
}
|
}
|
||||||
@ -157,7 +156,6 @@ final class ChatMediaInputStickerGridItem: GridItem {
|
|||||||
}
|
}
|
||||||
node.interfaceInteraction = self.interfaceInteraction
|
node.interfaceInteraction = self.interfaceInteraction
|
||||||
node.inputNodeInteraction = self.inputNodeInteraction
|
node.inputNodeInteraction = self.inputNodeInteraction
|
||||||
node.setup(account: self.account, stickerItem: self.stickerItem)
|
|
||||||
node.selected = self.selected
|
node.selected = self.selected
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -209,11 +207,6 @@ final class ChatMediaInputStickerGridItemNode: GridItemNode {
|
|||||||
self.imageNode.view.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(self.imageNodeTap(_:))))
|
self.imageNode.view.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(self.imageNodeTap(_:))))
|
||||||
}
|
}
|
||||||
|
|
||||||
func setup(account: Account, stickerItem: StickerPackItem) {
|
|
||||||
//self.updateSelectionState(animated: false)
|
|
||||||
//self.updateHiddenMedia()
|
|
||||||
}
|
|
||||||
|
|
||||||
override func updateLayout(item: GridItem, size: CGSize, isVisible: Bool, synchronousLoads: Bool) {
|
override func updateLayout(item: GridItem, size: CGSize, isVisible: Bool, synchronousLoads: Bool) {
|
||||||
guard let item = item as? ChatMediaInputStickerGridItem else {
|
guard let item = item as? ChatMediaInputStickerGridItem else {
|
||||||
return
|
return
|
||||||
@ -232,13 +225,7 @@ final class ChatMediaInputStickerGridItemNode: GridItemNode {
|
|||||||
self.addSubnode(animationNode)
|
self.addSubnode(animationNode)
|
||||||
}
|
}
|
||||||
self.imageNode.setSignal(chatMessageAnimatedSticker(postbox: item.account.postbox, file: item.stickerItem.file, small: false, size: CGSize(width: 160.0, height: 160.0)))
|
self.imageNode.setSignal(chatMessageAnimatedSticker(postbox: item.account.postbox, file: item.stickerItem.file, small: false, size: CGSize(width: 160.0, height: 160.0)))
|
||||||
if self.isPlaying {
|
self.updateVisibility()
|
||||||
self.didSetUpAnimationNode = true
|
|
||||||
self.animationNode?.setup(account: item.account, resource: item.stickerItem.file.resource, width: 160, height: 160, mode: .cached)
|
|
||||||
} else {
|
|
||||||
self.didSetUpAnimationNode = false
|
|
||||||
}
|
|
||||||
self.animationNode?.visibility = self.isPlaying
|
|
||||||
self.stickerFetchedDisposable.set(freeMediaFileResourceInteractiveFetched(account: item.account, fileReference: stickerPackFileReference(item.stickerItem.file), resource: item.stickerItem.file.resource).start())
|
self.stickerFetchedDisposable.set(freeMediaFileResourceInteractiveFetched(account: item.account, fileReference: stickerPackFileReference(item.stickerItem.file), resource: item.stickerItem.file.resource).start())
|
||||||
} else {
|
} else {
|
||||||
if let animationNode = self.animationNode {
|
if let animationNode = self.animationNode {
|
||||||
@ -297,7 +284,10 @@ final class ChatMediaInputStickerGridItemNode: GridItemNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func updateVisibility() {
|
func updateVisibility() {
|
||||||
let isPlaying = self.isPanelVisible && self.isVisibleInGrid
|
guard let item = self.item else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
let isPlaying = self.isPanelVisible && self.isVisibleInGrid && (item.interfaceInteraction?.stickerSettings.loopAnimatedStickers ?? true)
|
||||||
if self.isPlaying != isPlaying {
|
if self.isPlaying != isPlaying {
|
||||||
self.isPlaying = isPlaying
|
self.isPlaying = isPlaying
|
||||||
self.animationNode?.visibility = isPlaying
|
self.animationNode?.visibility = isPlaying
|
||||||
|
|||||||
@ -103,7 +103,7 @@ final class ChatMediaInputStickerPackItemNode: ListViewItemNode {
|
|||||||
|
|
||||||
override var visibility: ListViewItemNodeVisibility {
|
override var visibility: ListViewItemNodeVisibility {
|
||||||
didSet {
|
didSet {
|
||||||
self.visibilityStatus = self.visibility != .none
|
self.visibilityStatus = self.visibility != .none && false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -190,7 +190,7 @@ final class ChatMediaInputStickerPackItemNode: ListViewItemNode {
|
|||||||
animatedStickerNode.transform = CATransform3DMakeRotation(CGFloat.pi / 2.0, 0.0, 0.0, 1.0)
|
animatedStickerNode.transform = CATransform3DMakeRotation(CGFloat.pi / 2.0, 0.0, 0.0, 1.0)
|
||||||
self.addSubnode(animatedStickerNode)
|
self.addSubnode(animatedStickerNode)
|
||||||
animatedStickerNode.setup(account: account, resource: resource, width: 80, height: 80, mode: .cached)
|
animatedStickerNode.setup(account: account, resource: resource, width: 80, height: 80, mode: .cached)
|
||||||
animatedStickerNode.visibility = self.visibilityStatus
|
animatedStickerNode.visibility = self.visibilityStatus && false
|
||||||
}
|
}
|
||||||
if let animatedStickerNode = self.animatedStickerNode {
|
if let animatedStickerNode = self.animatedStickerNode {
|
||||||
animatedStickerNode.frame = CGRect(origin: CGPoint(x: floor((boundingSize.width - imageSize.width) / 2.0) + verticalOffset, y: floor((boundingSize.height - imageSize.height) / 2.0)), size: imageSize)
|
animatedStickerNode.frame = CGRect(origin: CGPoint(x: floor((boundingSize.width - imageSize.width) / 2.0) + verticalOffset, y: floor((boundingSize.height - imageSize.height) / 2.0)), size: imageSize)
|
||||||
|
|||||||
@ -17,6 +17,7 @@ class ChatMessageAnimatedStickerItemNode: ChatMessageItemView {
|
|||||||
let imageNode: TransformImageNode
|
let imageNode: TransformImageNode
|
||||||
private let animationNode: AnimatedStickerNode
|
private let animationNode: AnimatedStickerNode
|
||||||
private var didSetUpAnimationNode = false
|
private var didSetUpAnimationNode = false
|
||||||
|
private var isPlaying = false
|
||||||
|
|
||||||
private var swipeToReplyNode: ChatMessageSwipeToReplyNode?
|
private var swipeToReplyNode: ChatMessageSwipeToReplyNode?
|
||||||
private var swipeToReplyFeedback: HapticFeedback?
|
private var swipeToReplyFeedback: HapticFeedback?
|
||||||
@ -91,7 +92,6 @@ class ChatMessageAnimatedStickerItemNode: ChatMessageItemView {
|
|||||||
self.view.addGestureRecognizer(replyRecognizer)
|
self.view.addGestureRecognizer(replyRecognizer)
|
||||||
}
|
}
|
||||||
|
|
||||||
private var visibilityPromise = ValuePromise<Bool>(false, ignoreRepeated: true)
|
|
||||||
override var visibility: ListViewItemNodeVisibility {
|
override var visibility: ListViewItemNodeVisibility {
|
||||||
didSet {
|
didSet {
|
||||||
let wasVisible = oldValue != .none
|
let wasVisible = oldValue != .none
|
||||||
@ -106,21 +106,7 @@ class ChatMessageAnimatedStickerItemNode: ChatMessageItemView {
|
|||||||
private var visibilityStatus: Bool = false {
|
private var visibilityStatus: Bool = false {
|
||||||
didSet {
|
didSet {
|
||||||
if self.visibilityStatus != oldValue {
|
if self.visibilityStatus != oldValue {
|
||||||
if self.visibilityStatus {
|
self.updateVisibility()
|
||||||
self.animationNode.visibility = true
|
|
||||||
self.visibilityPromise.set(true)
|
|
||||||
if let item = self.item, !self.didSetUpAnimationNode {
|
|
||||||
for media in item.message.media {
|
|
||||||
if let telegramFile = media as? TelegramMediaFile {
|
|
||||||
self.didSetUpAnimationNode = true
|
|
||||||
self.animationNode.setup(account: item.context.account, resource: telegramFile.resource, width: 384, height: 384, mode: .cached)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
self.animationNode.visibility = false
|
|
||||||
self.visibilityPromise.set(false)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -133,7 +119,8 @@ class ChatMessageAnimatedStickerItemNode: ChatMessageItemView {
|
|||||||
if self.telegramFile?.id != telegramFile.id {
|
if self.telegramFile?.id != telegramFile.id {
|
||||||
self.telegramFile = telegramFile
|
self.telegramFile = telegramFile
|
||||||
self.imageNode.setSignal(chatMessageAnimatedSticker(postbox: item.context.account.postbox, file: telegramFile, small: false, size: CGSize(width: 384.0, height: 384.0), thumbnail: false))
|
self.imageNode.setSignal(chatMessageAnimatedSticker(postbox: item.context.account.postbox, file: telegramFile, small: false, size: CGSize(width: 384.0, height: 384.0), thumbnail: false))
|
||||||
if self.visibilityStatus {
|
self.updateVisibility()
|
||||||
|
if self.visibilityStatus && false {
|
||||||
self.didSetUpAnimationNode = true
|
self.didSetUpAnimationNode = true
|
||||||
self.animationNode.setup(account: item.context.account, resource: telegramFile.resource, width: 384, height: 384, mode: .cached)
|
self.animationNode.setup(account: item.context.account, resource: telegramFile.resource, width: 384, height: 384, mode: .cached)
|
||||||
}
|
}
|
||||||
@ -144,6 +131,31 @@ class ChatMessageAnimatedStickerItemNode: ChatMessageItemView {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func updateVisibility() {
|
||||||
|
guard let item = self.item else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
let isPlaying = self.visibilityStatus && item.controllerInteraction.stickerSettings.loopAnimatedStickers
|
||||||
|
if self.isPlaying != isPlaying {
|
||||||
|
self.isPlaying = isPlaying
|
||||||
|
self.animationNode.visibility = isPlaying
|
||||||
|
if let item = self.item, isPlaying, !self.didSetUpAnimationNode {
|
||||||
|
self.didSetUpAnimationNode = true
|
||||||
|
for media in item.message.media {
|
||||||
|
if let telegramFile = media as? TelegramMediaFile {
|
||||||
|
self.animationNode.setup(account: item.context.account, resource: telegramFile.resource, width: 384, height: 384, mode: .cached)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override func updateStickerSettings() {
|
||||||
|
self.updateVisibility()
|
||||||
|
}
|
||||||
|
|
||||||
override func asyncLayout() -> (_ item: ChatMessageItem, _ params: ListViewItemLayoutParams, _ mergedTop: ChatMessageMerge, _ mergedBottom: ChatMessageMerge, _ dateHeaderAtBottom: Bool) -> (ListViewItemNodeLayout, (ListViewItemUpdateAnimation, Bool) -> Void) {
|
override func asyncLayout() -> (_ item: ChatMessageItem, _ params: ListViewItemLayoutParams, _ mergedTop: ChatMessageMerge, _ mergedBottom: ChatMessageMerge, _ dateHeaderAtBottom: Bool) -> (ListViewItemNodeLayout, (ListViewItemUpdateAnimation, Bool) -> Void) {
|
||||||
let displaySize = CGSize(width: 184.0, height: 184.0)
|
let displaySize = CGSize(width: 184.0, height: 184.0)
|
||||||
let telegramFile = self.telegramFile
|
let telegramFile = self.telegramFile
|
||||||
|
|||||||
@ -2191,7 +2191,6 @@ class ChatMessageBubbleItemNode: ChatMessageItemView {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
override func playMediaWithSound() -> ((Double?) -> Void, Bool, Bool, Bool, ASDisplayNode?)? {
|
override func playMediaWithSound() -> ((Double?) -> Void, Bool, Bool, Bool, ASDisplayNode?)? {
|
||||||
for contentNode in self.contentNodes {
|
for contentNode in self.contentNodes {
|
||||||
if let playMediaWithSound = contentNode.playMediaWithSound() {
|
if let playMediaWithSound = contentNode.playMediaWithSound() {
|
||||||
|
|||||||
@ -698,6 +698,9 @@ public class ChatMessageItemView: ListViewItemNode {
|
|||||||
func updateAutomaticMediaDownloadSettings() {
|
func updateAutomaticMediaDownloadSettings() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func updateStickerSettings() {
|
||||||
|
}
|
||||||
|
|
||||||
func playMediaWithSound() -> ((Double?) -> Void, Bool, Bool, Bool, ASDisplayNode?)? {
|
func playMediaWithSound() -> ((Double?) -> Void, Bool, Bool, Bool, ASDisplayNode?)? {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,6 +5,7 @@ import SwiftSignalKit
|
|||||||
import Postbox
|
import Postbox
|
||||||
import TelegramCore
|
import TelegramCore
|
||||||
import TelegramPresentationData
|
import TelegramPresentationData
|
||||||
|
import TelegramUIPreferences
|
||||||
|
|
||||||
private final class FeaturedStickerPacksControllerArguments {
|
private final class FeaturedStickerPacksControllerArguments {
|
||||||
let account: Account
|
let account: Account
|
||||||
@ -46,7 +47,7 @@ private enum FeaturedStickerPacksEntryId: Hashable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private enum FeaturedStickerPacksEntry: ItemListNodeEntry {
|
private enum FeaturedStickerPacksEntry: ItemListNodeEntry {
|
||||||
case pack(Int32, PresentationTheme, PresentationStrings, StickerPackCollectionInfo, Bool, StickerPackItem?, String, Bool)
|
case pack(Int32, PresentationTheme, PresentationStrings, StickerPackCollectionInfo, Bool, StickerPackItem?, String, Bool, Bool)
|
||||||
|
|
||||||
var section: ItemListSectionId {
|
var section: ItemListSectionId {
|
||||||
switch self {
|
switch self {
|
||||||
@ -57,15 +58,15 @@ private enum FeaturedStickerPacksEntry: ItemListNodeEntry {
|
|||||||
|
|
||||||
var stableId: FeaturedStickerPacksEntryId {
|
var stableId: FeaturedStickerPacksEntryId {
|
||||||
switch self {
|
switch self {
|
||||||
case let .pack(_, _, _, info, _, _, _, _):
|
case let .pack(_, _, _, info, _, _, _, _, _):
|
||||||
return .pack(info.id)
|
return .pack(info.id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static func ==(lhs: FeaturedStickerPacksEntry, rhs: FeaturedStickerPacksEntry) -> Bool {
|
static func ==(lhs: FeaturedStickerPacksEntry, rhs: FeaturedStickerPacksEntry) -> Bool {
|
||||||
switch lhs {
|
switch lhs {
|
||||||
case let .pack(lhsIndex, lhsTheme, lhsStrings, lhsInfo, lhsUnread, lhsTopItem, lhsCount, lhsInstalled):
|
case let .pack(lhsIndex, lhsTheme, lhsStrings, lhsInfo, lhsUnread, lhsTopItem, lhsCount, lhsPlayAnimatedStickers, lhsInstalled):
|
||||||
if case let .pack(rhsIndex, rhsTheme, rhsStrings, rhsInfo, rhsUnread, rhsTopItem, rhsCount, rhsInstalled) = rhs {
|
if case let .pack(rhsIndex, rhsTheme, rhsStrings, rhsInfo, rhsUnread, rhsTopItem, rhsCount, rhsPlayAnimatedStickers, rhsInstalled) = rhs {
|
||||||
if lhsIndex != rhsIndex {
|
if lhsIndex != rhsIndex {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@ -87,6 +88,9 @@ private enum FeaturedStickerPacksEntry: ItemListNodeEntry {
|
|||||||
if lhsCount != rhsCount {
|
if lhsCount != rhsCount {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
if lhsPlayAnimatedStickers != rhsPlayAnimatedStickers {
|
||||||
|
return false
|
||||||
|
}
|
||||||
if lhsInstalled != rhsInstalled {
|
if lhsInstalled != rhsInstalled {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@ -99,9 +103,9 @@ private enum FeaturedStickerPacksEntry: ItemListNodeEntry {
|
|||||||
|
|
||||||
static func <(lhs: FeaturedStickerPacksEntry, rhs: FeaturedStickerPacksEntry) -> Bool {
|
static func <(lhs: FeaturedStickerPacksEntry, rhs: FeaturedStickerPacksEntry) -> Bool {
|
||||||
switch lhs {
|
switch lhs {
|
||||||
case let .pack(lhsIndex, _, _, _, _, _, _, _):
|
case let .pack(lhsIndex, _, _, _, _, _, _, _, _):
|
||||||
switch rhs {
|
switch rhs {
|
||||||
case let .pack(rhsIndex, _, _, _, _, _, _, _):
|
case let .pack(rhsIndex, _, _, _, _, _, _, _, _):
|
||||||
return lhsIndex < rhsIndex
|
return lhsIndex < rhsIndex
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -109,8 +113,8 @@ private enum FeaturedStickerPacksEntry: ItemListNodeEntry {
|
|||||||
|
|
||||||
func item(_ arguments: FeaturedStickerPacksControllerArguments) -> ListViewItem {
|
func item(_ arguments: FeaturedStickerPacksControllerArguments) -> ListViewItem {
|
||||||
switch self {
|
switch self {
|
||||||
case let .pack(_, theme, strings, info, unread, topItem, count, installed):
|
case let .pack(_, theme, strings, info, unread, topItem, count, playAnimatedStickers, installed):
|
||||||
return ItemListStickerPackItem(theme: theme, strings: strings, account: arguments.account, packInfo: info, itemCount: count, topItem: topItem, unread: unread, control: .installation(installed: installed), editing: ItemListStickerPackItemEditing(editable: false, editing: false, revealed: false, reorderable: false), enabled: true, sectionId: self.section, action: {
|
return ItemListStickerPackItem(theme: theme, strings: strings, account: arguments.account, packInfo: info, itemCount: count, topItem: topItem, unread: unread, control: .installation(installed: installed), editing: ItemListStickerPackItemEditing(editable: false, editing: false, revealed: false, reorderable: false), enabled: true, playAnimatedStickers: playAnimatedStickers, sectionId: self.section, action: {
|
||||||
arguments.openStickerPack(info)
|
arguments.openStickerPack(info)
|
||||||
}, setPackIdWithRevealedOptions: { _, _ in
|
}, setPackIdWithRevealedOptions: { _, _ in
|
||||||
}, addPack: {
|
}, addPack: {
|
||||||
@ -130,7 +134,7 @@ private struct FeaturedStickerPacksControllerState: Equatable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private func featuredStickerPacksControllerEntries(presentationData: PresentationData, state: FeaturedStickerPacksControllerState, view: CombinedView, featured: [FeaturedStickerPackItem], unreadPacks: [ItemCollectionId: Bool]) -> [FeaturedStickerPacksEntry] {
|
private func featuredStickerPacksControllerEntries(presentationData: PresentationData, state: FeaturedStickerPacksControllerState, view: CombinedView, featured: [FeaturedStickerPackItem], unreadPacks: [ItemCollectionId: Bool], stickerSettings: StickerSettings) -> [FeaturedStickerPacksEntry] {
|
||||||
var entries: [FeaturedStickerPacksEntry] = []
|
var entries: [FeaturedStickerPacksEntry] = []
|
||||||
|
|
||||||
if let stickerPacksView = view.views[.itemCollectionInfos(namespaces: [Namespaces.ItemCollection.CloudStickerPacks])] as? ItemCollectionInfosView, !featured.isEmpty {
|
if let stickerPacksView = view.views[.itemCollectionInfos(namespaces: [Namespaces.ItemCollection.CloudStickerPacks])] as? ItemCollectionInfosView, !featured.isEmpty {
|
||||||
@ -145,7 +149,7 @@ private func featuredStickerPacksControllerEntries(presentationData: Presentatio
|
|||||||
if let value = unreadPacks[item.info.id] {
|
if let value = unreadPacks[item.info.id] {
|
||||||
unread = value
|
unread = value
|
||||||
}
|
}
|
||||||
entries.append(.pack(index, presentationData.theme, presentationData.strings, item.info, unread, item.topItems.first, presentationData.strings.StickerPack_StickerCount(item.info.count), installedPacks.contains(item.info.id)))
|
entries.append(.pack(index, presentationData.theme, presentationData.strings, item.info, unread, item.topItems.first, presentationData.strings.StickerPack_StickerCount(item.info.count), stickerSettings.loopAnimatedStickers, installedPacks.contains(item.info.id)))
|
||||||
index += 1
|
index += 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -195,9 +199,14 @@ public func featuredStickerPacksController(context: AccountContext) -> ViewContr
|
|||||||
var previousPackCount: Int?
|
var previousPackCount: Int?
|
||||||
var initialUnreadPacks: [ItemCollectionId: Bool] = [:]
|
var initialUnreadPacks: [ItemCollectionId: Bool] = [:]
|
||||||
|
|
||||||
let signal = combineLatest(context.sharedContext.presentationData, statePromise.get() |> deliverOnMainQueue, stickerPacks.get() |> deliverOnMainQueue, featured.get() |> deliverOnMainQueue)
|
let signal = combineLatest(context.sharedContext.presentationData, statePromise.get() |> deliverOnMainQueue, stickerPacks.get() |> deliverOnMainQueue, featured.get() |> deliverOnMainQueue, context.sharedContext.accountManager.sharedData(keys: [ApplicationSpecificSharedDataKeys.stickerSettings]) |> deliverOnMainQueue)
|
||||||
|> deliverOnMainQueue
|
|> deliverOnMainQueue
|
||||||
|> map { presentationData, state, view, featured -> (ItemListControllerState, (ItemListNodeState<FeaturedStickerPacksEntry>, FeaturedStickerPacksEntry.ItemGenerationArguments)) in
|
|> map { presentationData, state, view, featured, sharedData -> (ItemListControllerState, (ItemListNodeState<FeaturedStickerPacksEntry>, FeaturedStickerPacksEntry.ItemGenerationArguments)) in
|
||||||
|
var stickerSettings = StickerSettings.defaultSettings
|
||||||
|
if let value = sharedData.entries[ApplicationSpecificSharedDataKeys.stickerSettings] as? StickerSettings {
|
||||||
|
stickerSettings = value
|
||||||
|
}
|
||||||
|
|
||||||
let packCount: Int? = featured.count
|
let packCount: Int? = featured.count
|
||||||
|
|
||||||
for item in featured {
|
for item in featured {
|
||||||
@ -212,7 +221,7 @@ public func featuredStickerPacksController(context: AccountContext) -> ViewContr
|
|||||||
|
|
||||||
let controllerState = ItemListControllerState(theme: presentationData.theme, title: .text(presentationData.strings.FeaturedStickerPacks_Title), leftNavigationButton: nil, rightNavigationButton: rightNavigationButton, backNavigationButton: ItemListBackButton(title: presentationData.strings.Common_Back), animateChanges: true)
|
let controllerState = ItemListControllerState(theme: presentationData.theme, title: .text(presentationData.strings.FeaturedStickerPacks_Title), leftNavigationButton: nil, rightNavigationButton: rightNavigationButton, backNavigationButton: ItemListBackButton(title: presentationData.strings.Common_Back), animateChanges: true)
|
||||||
|
|
||||||
let listState = ItemListNodeState(entries: featuredStickerPacksControllerEntries(presentationData: presentationData, state: state, view: view, featured: featured, unreadPacks: initialUnreadPacks), style: .blocks, animateChanges: false)
|
let listState = ItemListNodeState(entries: featuredStickerPacksControllerEntries(presentationData: presentationData, state: state, view: view, featured: featured, unreadPacks: initialUnreadPacks, stickerSettings: stickerSettings), style: .blocks, animateChanges: false)
|
||||||
return (controllerState, (listState, arguments))
|
return (controllerState, (listState, arguments))
|
||||||
} |> afterDisposed {
|
} |> afterDisposed {
|
||||||
actionsDisposable.dispose()
|
actionsDisposable.dispose()
|
||||||
@ -226,7 +235,7 @@ public func featuredStickerPacksController(context: AccountContext) -> ViewContr
|
|||||||
var unreadIds: [ItemCollectionId] = []
|
var unreadIds: [ItemCollectionId] = []
|
||||||
for entry in entries {
|
for entry in entries {
|
||||||
switch entry {
|
switch entry {
|
||||||
case let .pack(_, _, _, info, unread, _, _, _):
|
case let .pack(_, _, _, info, unread, _, _, _, _):
|
||||||
if unread && !alreadyReadIds.contains(info.id) {
|
if unread && !alreadyReadIds.contains(info.id) {
|
||||||
unreadIds.append(info.id)
|
unreadIds.append(info.id)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,6 +5,7 @@ import SwiftSignalKit
|
|||||||
import Postbox
|
import Postbox
|
||||||
import TelegramCore
|
import TelegramCore
|
||||||
import TelegramPresentationData
|
import TelegramPresentationData
|
||||||
|
import TelegramUIPreferences
|
||||||
|
|
||||||
private final class GroupStickerPackSetupControllerArguments {
|
private final class GroupStickerPackSetupControllerArguments {
|
||||||
let account: Account
|
let account: Account
|
||||||
@ -64,7 +65,7 @@ private enum GroupStickerPackEntry: ItemListNodeEntry {
|
|||||||
case currentPack(Int32, PresentationTheme, PresentationStrings, GroupStickerPackCurrentItemContent)
|
case currentPack(Int32, PresentationTheme, PresentationStrings, GroupStickerPackCurrentItemContent)
|
||||||
case searchInfo(PresentationTheme, String)
|
case searchInfo(PresentationTheme, String)
|
||||||
case packsTitle(PresentationTheme, String)
|
case packsTitle(PresentationTheme, String)
|
||||||
case pack(Int32, PresentationTheme, PresentationStrings, StickerPackCollectionInfo, StickerPackItem?, String, Bool)
|
case pack(Int32, PresentationTheme, PresentationStrings, StickerPackCollectionInfo, StickerPackItem?, String, Bool, Bool)
|
||||||
|
|
||||||
var section: ItemListSectionId {
|
var section: ItemListSectionId {
|
||||||
switch self {
|
switch self {
|
||||||
@ -85,7 +86,7 @@ private enum GroupStickerPackEntry: ItemListNodeEntry {
|
|||||||
return .index(2)
|
return .index(2)
|
||||||
case .packsTitle:
|
case .packsTitle:
|
||||||
return .index(3)
|
return .index(3)
|
||||||
case let .pack(_, _, _, info, _, _, _):
|
case let .pack(_, _, _, info, _, _, _, _):
|
||||||
return .pack(info.id)
|
return .pack(info.id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -128,8 +129,8 @@ private enum GroupStickerPackEntry: ItemListNodeEntry {
|
|||||||
} else {
|
} else {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
case let .pack(lhsIndex, lhsTheme, lhsStrings, lhsInfo, lhsTopItem, lhsCount, lhsSelected):
|
case let .pack(lhsIndex, lhsTheme, lhsStrings, lhsInfo, lhsTopItem, lhsCount, lhsPlayAnimatedStickers, lhsSelected):
|
||||||
if case let .pack(rhsIndex, rhsTheme, rhsStrings, rhsInfo, rhsTopItem, rhsCount, rhsSelected) = rhs {
|
if case let .pack(rhsIndex, rhsTheme, rhsStrings, rhsInfo, rhsTopItem, rhsCount, rhsPlayAnimatedStickers, rhsSelected) = rhs {
|
||||||
if lhsIndex != rhsIndex {
|
if lhsIndex != rhsIndex {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@ -148,6 +149,9 @@ private enum GroupStickerPackEntry: ItemListNodeEntry {
|
|||||||
if lhsCount != rhsCount {
|
if lhsCount != rhsCount {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
if lhsPlayAnimatedStickers != rhsPlayAnimatedStickers {
|
||||||
|
return false
|
||||||
|
}
|
||||||
if lhsSelected != rhsSelected {
|
if lhsSelected != rhsSelected {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@ -188,9 +192,9 @@ private enum GroupStickerPackEntry: ItemListNodeEntry {
|
|||||||
default:
|
default:
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
case let .pack(lhsIndex, _, _, _, _, _, _):
|
case let .pack(lhsIndex, _, _, _, _, _, _, _):
|
||||||
switch rhs {
|
switch rhs {
|
||||||
case let .pack(rhsIndex, _, _, _, _, _, _):
|
case let .pack(rhsIndex, _, _, _, _, _, _, _):
|
||||||
return lhsIndex < rhsIndex
|
return lhsIndex < rhsIndex
|
||||||
default:
|
default:
|
||||||
return false
|
return false
|
||||||
@ -216,8 +220,8 @@ private enum GroupStickerPackEntry: ItemListNodeEntry {
|
|||||||
return ItemListTextItem(theme: theme, text: .plain(text), sectionId: self.section, linkAction: nil)
|
return ItemListTextItem(theme: theme, text: .plain(text), sectionId: self.section, linkAction: nil)
|
||||||
case let .packsTitle(theme, text):
|
case let .packsTitle(theme, text):
|
||||||
return ItemListSectionHeaderItem(theme: theme, text: text, sectionId: self.section)
|
return ItemListSectionHeaderItem(theme: theme, text: text, sectionId: self.section)
|
||||||
case let .pack(_, theme, strings, info, topItem, count, selected):
|
case let .pack(_, theme, strings, info, topItem, count, playAnimatedStickers, selected):
|
||||||
return ItemListStickerPackItem(theme: theme, strings: strings, account: arguments.account, packInfo: info, itemCount: count, topItem: topItem, unread: false, control: selected ? .selection : .none, editing: ItemListStickerPackItemEditing(editable: false, editing: false, revealed: false, reorderable: false), enabled: true, sectionId: self.section, action: {
|
return ItemListStickerPackItem(theme: theme, strings: strings, account: arguments.account, packInfo: info, itemCount: count, topItem: topItem, unread: false, control: selected ? .selection : .none, editing: ItemListStickerPackItemEditing(editable: false, editing: false, revealed: false, reorderable: false), enabled: true, playAnimatedStickers: playAnimatedStickers, sectionId: self.section, action: {
|
||||||
if selected {
|
if selected {
|
||||||
arguments.openStickerPack(info)
|
arguments.openStickerPack(info)
|
||||||
} else {
|
} else {
|
||||||
@ -258,7 +262,7 @@ private struct GroupStickerPackSetupControllerState: Equatable {
|
|||||||
var isSaving: Bool
|
var isSaving: Bool
|
||||||
}
|
}
|
||||||
|
|
||||||
private func groupStickerPackSetupControllerEntries(presentationData: PresentationData, searchText: String, view: CombinedView, initialData: InitialStickerPackData?, searchState: GroupStickerPackSearchState) -> [GroupStickerPackEntry] {
|
private func groupStickerPackSetupControllerEntries(presentationData: PresentationData, searchText: String, view: CombinedView, initialData: InitialStickerPackData?, searchState: GroupStickerPackSearchState, stickerSettings: StickerSettings) -> [GroupStickerPackEntry] {
|
||||||
if initialData == nil {
|
if initialData == nil {
|
||||||
return []
|
return []
|
||||||
}
|
}
|
||||||
@ -288,7 +292,7 @@ private func groupStickerPackSetupControllerEntries(presentationData: Presentati
|
|||||||
if case let .found(found) = searchState {
|
if case let .found(found) = searchState {
|
||||||
selected = found.info.id == info.id
|
selected = found.info.id == info.id
|
||||||
}
|
}
|
||||||
entries.append(.pack(index, presentationData.theme, presentationData.strings, info, entry.firstItem as? StickerPackItem, presentationData.strings.StickerPack_StickerCount(info.count == 0 ? entry.count : info.count), selected))
|
entries.append(.pack(index, presentationData.theme, presentationData.strings, info, entry.firstItem as? StickerPackItem, presentationData.strings.StickerPack_StickerCount(info.count == 0 ? entry.count : info.count), stickerSettings.loopAnimatedStickers, selected))
|
||||||
index += 1
|
index += 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -400,8 +404,13 @@ public func groupStickerPackSetupController(context: AccountContext, peerId: Pee
|
|||||||
|
|
||||||
let previousHadData = Atomic<Bool>(value: false)
|
let previousHadData = Atomic<Bool>(value: false)
|
||||||
|
|
||||||
let signal = combineLatest(context.sharedContext.presentationData, statePromise.get() |> deliverOnMainQueue, initialData.get() |> deliverOnMainQueue, stickerPacks.get() |> deliverOnMainQueue, searchState.get() |> deliverOnMainQueue)
|
let signal = combineLatest(context.sharedContext.presentationData, statePromise.get() |> deliverOnMainQueue, initialData.get() |> deliverOnMainQueue, stickerPacks.get() |> deliverOnMainQueue, searchState.get() |> deliverOnMainQueue, context.sharedContext.accountManager.sharedData(keys: [ApplicationSpecificSharedDataKeys.stickerSettings]) |> deliverOnMainQueue)
|
||||||
|> map { presentationData, state, initialData, view, searchState -> (ItemListControllerState, (ItemListNodeState<GroupStickerPackEntry>, GroupStickerPackEntry.ItemGenerationArguments)) in
|
|> map { presentationData, state, initialData, view, searchState, sharedData -> (ItemListControllerState, (ItemListNodeState<GroupStickerPackEntry>, GroupStickerPackEntry.ItemGenerationArguments)) in
|
||||||
|
var stickerSettings = StickerSettings.defaultSettings
|
||||||
|
if let value = sharedData.entries[ApplicationSpecificSharedDataKeys.stickerSettings] as? StickerSettings {
|
||||||
|
stickerSettings = value
|
||||||
|
}
|
||||||
|
|
||||||
let leftNavigationButton = ItemListNavigationButton(content: .text(presentationData.strings.Common_Cancel), style: .regular, enabled: true, action: {
|
let leftNavigationButton = ItemListNavigationButton(content: .text(presentationData.strings.Common_Cancel), style: .regular, enabled: true, action: {
|
||||||
dismissImpl?()
|
dismissImpl?()
|
||||||
})
|
})
|
||||||
@ -456,7 +465,7 @@ public func groupStickerPackSetupController(context: AccountContext, peerId: Pee
|
|||||||
emptyStateItem = ItemListLoadingIndicatorEmptyStateItem(theme: presentationData.theme)
|
emptyStateItem = ItemListLoadingIndicatorEmptyStateItem(theme: presentationData.theme)
|
||||||
}
|
}
|
||||||
|
|
||||||
let listState = ItemListNodeState(entries: groupStickerPackSetupControllerEntries(presentationData: presentationData, searchText: searchState.0, view: view, initialData: initialData, searchState: searchState.1), style: .blocks, emptyStateItem: emptyStateItem, animateChanges: hasData && hadData)
|
let listState = ItemListNodeState(entries: groupStickerPackSetupControllerEntries(presentationData: presentationData, searchText: searchState.0, view: view, initialData: initialData, searchState: searchState.1, stickerSettings: stickerSettings), style: .blocks, emptyStateItem: emptyStateItem, animateChanges: hasData && hadData)
|
||||||
return (controllerState, (listState, arguments))
|
return (controllerState, (listState, arguments))
|
||||||
} |> afterDisposed {
|
} |> afterDisposed {
|
||||||
actionsDisposable.dispose()
|
actionsDisposable.dispose()
|
||||||
|
|||||||
@ -18,8 +18,9 @@ private final class InstalledStickerPacksControllerArguments {
|
|||||||
let openFeatured: () -> Void
|
let openFeatured: () -> Void
|
||||||
let openArchived: ([ArchivedStickerPackItem]?) -> Void
|
let openArchived: ([ArchivedStickerPackItem]?) -> Void
|
||||||
let openSuggestOptions: () -> Void
|
let openSuggestOptions: () -> Void
|
||||||
|
let toggleAnimatedStickers: (Bool) -> Void
|
||||||
|
|
||||||
init(account: Account, openStickerPack: @escaping (StickerPackCollectionInfo) -> Void, setPackIdWithRevealedOptions: @escaping (ItemCollectionId?, ItemCollectionId?) -> Void, removePack: @escaping (ArchivedStickerPackItem) -> Void, openStickersBot: @escaping () -> Void, openMasks: @escaping () -> Void, openFeatured: @escaping () -> Void, openArchived: @escaping ([ArchivedStickerPackItem]?) -> Void, openSuggestOptions: @escaping () -> Void) {
|
init(account: Account, openStickerPack: @escaping (StickerPackCollectionInfo) -> Void, setPackIdWithRevealedOptions: @escaping (ItemCollectionId?, ItemCollectionId?) -> Void, removePack: @escaping (ArchivedStickerPackItem) -> Void, openStickersBot: @escaping () -> Void, openMasks: @escaping () -> Void, openFeatured: @escaping () -> Void, openArchived: @escaping ([ArchivedStickerPackItem]?) -> Void, openSuggestOptions: @escaping () -> Void, toggleAnimatedStickers: @escaping (Bool) -> Void) {
|
||||||
self.account = account
|
self.account = account
|
||||||
self.openStickerPack = openStickerPack
|
self.openStickerPack = openStickerPack
|
||||||
self.setPackIdWithRevealedOptions = setPackIdWithRevealedOptions
|
self.setPackIdWithRevealedOptions = setPackIdWithRevealedOptions
|
||||||
@ -29,6 +30,7 @@ private final class InstalledStickerPacksControllerArguments {
|
|||||||
self.openFeatured = openFeatured
|
self.openFeatured = openFeatured
|
||||||
self.openArchived = openArchived
|
self.openArchived = openArchived
|
||||||
self.openSuggestOptions = openSuggestOptions
|
self.openSuggestOptions = openSuggestOptions
|
||||||
|
self.toggleAnimatedStickers = toggleAnimatedStickers
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -85,13 +87,15 @@ private enum InstalledStickerPacksEntry: ItemListNodeEntry {
|
|||||||
case trending(PresentationTheme, String, Int32)
|
case trending(PresentationTheme, String, Int32)
|
||||||
case archived(PresentationTheme, String, Int32, [ArchivedStickerPackItem]?)
|
case archived(PresentationTheme, String, Int32, [ArchivedStickerPackItem]?)
|
||||||
case masks(PresentationTheme, String)
|
case masks(PresentationTheme, String)
|
||||||
|
case animatedStickers(PresentationTheme, String, Bool)
|
||||||
|
case animatedStickersInfo(PresentationTheme, String)
|
||||||
case packsTitle(PresentationTheme, String)
|
case packsTitle(PresentationTheme, String)
|
||||||
case pack(Int32, PresentationTheme, PresentationStrings, StickerPackCollectionInfo, StickerPackItem?, String, Bool, ItemListStickerPackItemEditing)
|
case pack(Int32, PresentationTheme, PresentationStrings, StickerPackCollectionInfo, StickerPackItem?, String, Bool, Bool, ItemListStickerPackItemEditing)
|
||||||
case packsInfo(PresentationTheme, String)
|
case packsInfo(PresentationTheme, String)
|
||||||
|
|
||||||
var section: ItemListSectionId {
|
var section: ItemListSectionId {
|
||||||
switch self {
|
switch self {
|
||||||
case .suggestOptions, .trending, .masks, .archived:
|
case .suggestOptions, .trending, .masks, .archived, .animatedStickers, .animatedStickersInfo:
|
||||||
return InstalledStickerPacksSection.service.rawValue
|
return InstalledStickerPacksSection.service.rawValue
|
||||||
case .packsTitle, .pack, .packsInfo:
|
case .packsTitle, .pack, .packsInfo:
|
||||||
return InstalledStickerPacksSection.stickers.rawValue
|
return InstalledStickerPacksSection.stickers.rawValue
|
||||||
@ -108,12 +112,16 @@ private enum InstalledStickerPacksEntry: ItemListNodeEntry {
|
|||||||
return .index(2)
|
return .index(2)
|
||||||
case .masks:
|
case .masks:
|
||||||
return .index(3)
|
return .index(3)
|
||||||
case .packsTitle:
|
case .animatedStickers:
|
||||||
return .index(4)
|
return .index(4)
|
||||||
case let .pack(_, _, _, info, _, _, _, _):
|
case .animatedStickersInfo:
|
||||||
|
return .index(5)
|
||||||
|
case .packsTitle:
|
||||||
|
return .index(6)
|
||||||
|
case let .pack(_, _, _, info, _, _, _, _, _):
|
||||||
return .pack(info.id)
|
return .pack(info.id)
|
||||||
case .packsInfo:
|
case .packsInfo:
|
||||||
return .index(5)
|
return .index(7)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -143,14 +151,26 @@ private enum InstalledStickerPacksEntry: ItemListNodeEntry {
|
|||||||
} else {
|
} else {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
case let .animatedStickers(lhsTheme, lhsText, lhsValue):
|
||||||
|
if case let .animatedStickers(rhsTheme, rhsText, rhsValue) = rhs, lhsTheme === rhsTheme, lhsText == rhsText, lhsValue == rhsValue {
|
||||||
|
return true
|
||||||
|
} else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
case let .animatedStickersInfo(lhsTheme, lhsText):
|
||||||
|
if case let .animatedStickersInfo(rhsTheme, rhsText) = rhs, lhsTheme === rhsTheme, lhsText == rhsText {
|
||||||
|
return true
|
||||||
|
} else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
case let .packsTitle(lhsTheme, lhsText):
|
case let .packsTitle(lhsTheme, lhsText):
|
||||||
if case let .packsTitle(rhsTheme, rhsText) = rhs, lhsTheme === rhsTheme, lhsText == rhsText {
|
if case let .packsTitle(rhsTheme, rhsText) = rhs, lhsTheme === rhsTheme, lhsText == rhsText {
|
||||||
return true
|
return true
|
||||||
} else {
|
} else {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
case let .pack(lhsIndex, lhsTheme, lhsStrings, lhsInfo, lhsTopItem, lhsCount, lhsEnabled, lhsEditing):
|
case let .pack(lhsIndex, lhsTheme, lhsStrings, lhsInfo, lhsTopItem, lhsCount, lhsAnimatedStickers, lhsEnabled, lhsEditing):
|
||||||
if case let .pack(rhsIndex, rhsTheme, rhsStrings, rhsInfo, rhsTopItem, rhsCount, rhsEnabled, rhsEditing) = rhs {
|
if case let .pack(rhsIndex, rhsTheme, rhsStrings, rhsInfo, rhsTopItem, rhsCount, rhsAnimatedStickers, rhsEnabled, rhsEditing) = rhs {
|
||||||
if lhsIndex != rhsIndex {
|
if lhsIndex != rhsIndex {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@ -169,6 +189,9 @@ private enum InstalledStickerPacksEntry: ItemListNodeEntry {
|
|||||||
if lhsCount != rhsCount {
|
if lhsCount != rhsCount {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
if lhsAnimatedStickers != rhsAnimatedStickers {
|
||||||
|
return false
|
||||||
|
}
|
||||||
if lhsEnabled != rhsEnabled {
|
if lhsEnabled != rhsEnabled {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@ -218,16 +241,30 @@ private enum InstalledStickerPacksEntry: ItemListNodeEntry {
|
|||||||
default:
|
default:
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
case .packsTitle:
|
case .animatedStickers:
|
||||||
switch rhs {
|
switch rhs {
|
||||||
case .suggestOptions, .trending, .masks, .archived, .packsTitle:
|
case .suggestOptions, .trending, .archived, .masks, .animatedStickers:
|
||||||
return false
|
return false
|
||||||
default:
|
default:
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
case let .pack(lhsIndex, _, _, _, _, _, _, _):
|
case .animatedStickersInfo:
|
||||||
switch rhs {
|
switch rhs {
|
||||||
case let .pack(rhsIndex, _, _, _, _, _, _, _):
|
case .suggestOptions, .trending, .archived, .masks, .animatedStickers, .animatedStickersInfo:
|
||||||
|
return false
|
||||||
|
default:
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
case .packsTitle:
|
||||||
|
switch rhs {
|
||||||
|
case .suggestOptions, .trending, .masks, .archived, .animatedStickers, .animatedStickersInfo, .packsTitle:
|
||||||
|
return false
|
||||||
|
default:
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
case let .pack(lhsIndex, _, _, _, _, _, _, _, _):
|
||||||
|
switch rhs {
|
||||||
|
case let .pack(rhsIndex, _, _, _, _, _, _, _, _):
|
||||||
return lhsIndex < rhsIndex
|
return lhsIndex < rhsIndex
|
||||||
case .packsInfo:
|
case .packsInfo:
|
||||||
return true
|
return true
|
||||||
@ -262,10 +299,16 @@ private enum InstalledStickerPacksEntry: ItemListNodeEntry {
|
|||||||
return ItemListDisclosureItem(theme: theme, title: text, label: count == 0 ? "" : "\(count)", sectionId: self.section, style: .blocks, action: {
|
return ItemListDisclosureItem(theme: theme, title: text, label: count == 0 ? "" : "\(count)", sectionId: self.section, style: .blocks, action: {
|
||||||
arguments.openArchived(archived)
|
arguments.openArchived(archived)
|
||||||
})
|
})
|
||||||
|
case let .animatedStickers(theme, text, value):
|
||||||
|
return ItemListSwitchItem(theme: theme, title: text, value: value, sectionId: self.section, style: .blocks, updated: { value in
|
||||||
|
arguments.toggleAnimatedStickers(value)
|
||||||
|
})
|
||||||
|
case let .animatedStickersInfo(theme, text):
|
||||||
|
return ItemListTextItem(theme: theme, text: .plain(text), sectionId: self.section)
|
||||||
case let .packsTitle(theme, text):
|
case let .packsTitle(theme, text):
|
||||||
return ItemListSectionHeaderItem(theme: theme, text: text, sectionId: self.section)
|
return ItemListSectionHeaderItem(theme: theme, text: text, sectionId: self.section)
|
||||||
case let .pack(_, theme, strings, info, topItem, count, enabled, editing):
|
case let .pack(_, theme, strings, info, topItem, count, animatedStickers, enabled, editing):
|
||||||
return ItemListStickerPackItem(theme: theme, strings: strings, account: arguments.account, packInfo: info, itemCount: count, topItem: topItem, unread: false, control: .none, editing: editing, enabled: enabled, sectionId: self.section, action: {
|
return ItemListStickerPackItem(theme: theme, strings: strings, account: arguments.account, packInfo: info, itemCount: count, topItem: topItem, unread: false, control: .none, editing: editing, enabled: enabled, playAnimatedStickers: animatedStickers, sectionId: self.section, action: {
|
||||||
arguments.openStickerPack(info)
|
arguments.openStickerPack(info)
|
||||||
}, setPackIdWithRevealedOptions: { current, previous in
|
}, setPackIdWithRevealedOptions: { current, previous in
|
||||||
arguments.setPackIdWithRevealedOptions(current, previous)
|
arguments.setPackIdWithRevealedOptions(current, previous)
|
||||||
@ -353,6 +396,10 @@ private func installedStickerPacksControllerEntries(presentationData: Presentati
|
|||||||
entries.append(.archived(presentationData.theme, presentationData.strings.StickerPacksSettings_ArchivedPacks, Int32(archived.count), archived))
|
entries.append(.archived(presentationData.theme, presentationData.strings.StickerPacksSettings_ArchivedPacks, Int32(archived.count), archived))
|
||||||
}
|
}
|
||||||
entries.append(.masks(presentationData.theme, presentationData.strings.MaskStickerSettings_Title))
|
entries.append(.masks(presentationData.theme, presentationData.strings.MaskStickerSettings_Title))
|
||||||
|
|
||||||
|
entries.append(.animatedStickers(presentationData.theme, presentationData.strings.StickerPacksSettings_AnimatedStickers, stickerSettings.loopAnimatedStickers))
|
||||||
|
entries.append(.animatedStickersInfo(presentationData.theme, presentationData.strings.StickerPacksSettings_AnimatedStickersInfo))
|
||||||
|
|
||||||
entries.append(.packsTitle(presentationData.theme, presentationData.strings.StickerPacksSettings_StickerPacksSection))
|
entries.append(.packsTitle(presentationData.theme, presentationData.strings.StickerPacksSettings_StickerPacksSection))
|
||||||
case .masks:
|
case .masks:
|
||||||
if let archived = archived, !archived.isEmpty {
|
if let archived = archived, !archived.isEmpty {
|
||||||
@ -365,7 +412,7 @@ private func installedStickerPacksControllerEntries(presentationData: Presentati
|
|||||||
var index: Int32 = 0
|
var index: Int32 = 0
|
||||||
for entry in packsEntries {
|
for entry in packsEntries {
|
||||||
if let info = entry.info as? StickerPackCollectionInfo {
|
if let info = entry.info as? StickerPackCollectionInfo {
|
||||||
entries.append(.pack(index, presentationData.theme, presentationData.strings, info, entry.firstItem as? StickerPackItem, presentationData.strings.StickerPack_StickerCount(info.count == 0 ? entry.count : info.count), true, ItemListStickerPackItemEditing(editable: true, editing: state.editing, revealed: state.packIdWithRevealedOptions == entry.id, reorderable: true)))
|
entries.append(.pack(index, presentationData.theme, presentationData.strings, info, entry.firstItem as? StickerPackItem, presentationData.strings.StickerPack_StickerCount(info.count == 0 ? entry.count : info.count), stickerSettings.loopAnimatedStickers, true, ItemListStickerPackItemEditing(editable: true, editing: state.editing, revealed: state.packIdWithRevealedOptions == entry.id, reorderable: true)))
|
||||||
index += 1
|
index += 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -505,18 +552,10 @@ public func installedStickerPacksController(context: AccountContext, mode: Insta
|
|||||||
ActionSheetItemGroup(items: [ActionSheetButtonItem(title: presentationData.strings.Common_Cancel, action: { dismissAction() })])
|
ActionSheetItemGroup(items: [ActionSheetButtonItem(title: presentationData.strings.Common_Cancel, action: { dismissAction() })])
|
||||||
])
|
])
|
||||||
presentControllerImpl?(controller, ViewControllerPresentationArguments(presentationAnimation: .modalSheet))
|
presentControllerImpl?(controller, ViewControllerPresentationArguments(presentationAnimation: .modalSheet))
|
||||||
/*
|
}, toggleAnimatedStickers: { value in
|
||||||
let suggestString: String
|
let _ = updateStickerSettingsInteractively(accountManager: context.sharedContext.accountManager, { current in
|
||||||
switch stickerSettings.emojiStickerSuggestionMode {
|
return current.withUpdatedLoopAnimatedStickers(value)
|
||||||
case .none:
|
}).start()
|
||||||
suggestString = presentationData.strings.Stickers_SuggestNone
|
|
||||||
case .all:
|
|
||||||
|
|
||||||
case .installed:
|
|
||||||
suggestString = presentationData.strings.Stickers_SuggestAdded
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
})
|
})
|
||||||
let stickerPacks = Promise<CombinedView>()
|
let stickerPacks = Promise<CombinedView>()
|
||||||
stickerPacks.set(context.account.postbox.combinedView(keys: [.itemCollectionInfos(namespaces: [namespaceForMode(mode)])]))
|
stickerPacks.set(context.account.postbox.combinedView(keys: [.itemCollectionInfos(namespaces: [namespaceForMode(mode)])]))
|
||||||
@ -532,9 +571,7 @@ public func installedStickerPacksController(context: AccountContext, mode: Insta
|
|||||||
archivedPromise.set(.single(nil) |> then(archivedStickerPacks(account: context.account, namespace: .masks) |> map(Optional.init)))
|
archivedPromise.set(.single(nil) |> then(archivedStickerPacks(account: context.account, namespace: .masks) |> map(Optional.init)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
var previousPackCount: Int?
|
var previousPackCount: Int?
|
||||||
|
|
||||||
let signal = combineLatest(queue: .mainQueue(), context.sharedContext.presentationData, statePromise.get(), stickerPacks.get(), combineLatest(queue: .mainQueue(), featured.get(), archivedPromise.get()), context.sharedContext.accountManager.sharedData(keys: [ApplicationSpecificSharedDataKeys.stickerSettings]))
|
let signal = combineLatest(queue: .mainQueue(), context.sharedContext.presentationData, statePromise.get(), stickerPacks.get(), combineLatest(queue: .mainQueue(), featured.get(), archivedPromise.get()), context.sharedContext.accountManager.sharedData(keys: [ApplicationSpecificSharedDataKeys.stickerSettings]))
|
||||||
|> deliverOnMainQueue
|
|> deliverOnMainQueue
|
||||||
|> map { presentationData, state, view, featuredAndArchived, sharedData -> (ItemListControllerState, (ItemListNodeState<InstalledStickerPacksEntry>, InstalledStickerPacksEntry.ItemGenerationArguments)) in
|
|> map { presentationData, state, view, featuredAndArchived, sharedData -> (ItemListControllerState, (ItemListNodeState<InstalledStickerPacksEntry>, InstalledStickerPacksEntry.ItemGenerationArguments)) in
|
||||||
@ -549,12 +586,6 @@ public func installedStickerPacksController(context: AccountContext, mode: Insta
|
|||||||
}
|
}
|
||||||
|
|
||||||
let leftNavigationButton: ItemListNavigationButton? = nil
|
let leftNavigationButton: ItemListNavigationButton? = nil
|
||||||
/*if case .modal = mode {
|
|
||||||
leftNavigationButton = ItemListNavigationButton(content: .text(presentationData.strings.Common_Cancel), style: .regular, enabled: true, action: {
|
|
||||||
dismissImpl?()
|
|
||||||
})
|
|
||||||
}*/
|
|
||||||
|
|
||||||
var rightNavigationButton: ItemListNavigationButton?
|
var rightNavigationButton: ItemListNavigationButton?
|
||||||
if let packCount = packCount, packCount != 0 {
|
if let packCount = packCount, packCount != 0 {
|
||||||
if case .modal = mode {
|
if case .modal = mode {
|
||||||
@ -603,7 +634,7 @@ public func installedStickerPacksController(context: AccountContext, mode: Insta
|
|||||||
|
|
||||||
controller.reorderEntry = { fromIndex, toIndex, entries in
|
controller.reorderEntry = { fromIndex, toIndex, entries in
|
||||||
let fromEntry = entries[fromIndex]
|
let fromEntry = entries[fromIndex]
|
||||||
guard case let .pack(_, _, _, fromPackInfo, _, _, _, _) = fromEntry else {
|
guard case let .pack(_, _, _, fromPackInfo, _, _, _, _, _) = fromEntry else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
var referenceId: ItemCollectionId?
|
var referenceId: ItemCollectionId?
|
||||||
@ -611,7 +642,7 @@ public func installedStickerPacksController(context: AccountContext, mode: Insta
|
|||||||
var afterAll = false
|
var afterAll = false
|
||||||
if toIndex < entries.count {
|
if toIndex < entries.count {
|
||||||
switch entries[toIndex] {
|
switch entries[toIndex] {
|
||||||
case let .pack(_, _, _, toPackInfo, _, _, _, _):
|
case let .pack(_, _, _, toPackInfo, _, _, _, _, _):
|
||||||
referenceId = toPackInfo.id
|
referenceId = toPackInfo.id
|
||||||
default:
|
default:
|
||||||
if entries[toIndex] < fromEntry {
|
if entries[toIndex] < fromEntry {
|
||||||
|
|||||||
@ -47,13 +47,14 @@ final class ItemListStickerPackItem: ListViewItem, ItemListItem {
|
|||||||
let control: ItemListStickerPackItemControl
|
let control: ItemListStickerPackItemControl
|
||||||
let editing: ItemListStickerPackItemEditing
|
let editing: ItemListStickerPackItemEditing
|
||||||
let enabled: Bool
|
let enabled: Bool
|
||||||
|
let playAnimatedStickers: Bool
|
||||||
let sectionId: ItemListSectionId
|
let sectionId: ItemListSectionId
|
||||||
let action: (() -> Void)?
|
let action: (() -> Void)?
|
||||||
let setPackIdWithRevealedOptions: (ItemCollectionId?, ItemCollectionId?) -> Void
|
let setPackIdWithRevealedOptions: (ItemCollectionId?, ItemCollectionId?) -> Void
|
||||||
let addPack: () -> Void
|
let addPack: () -> Void
|
||||||
let removePack: () -> Void
|
let removePack: () -> Void
|
||||||
|
|
||||||
init(theme: PresentationTheme, strings: PresentationStrings, account: Account, packInfo: StickerPackCollectionInfo, itemCount: String, topItem: StickerPackItem?, unread: Bool, control: ItemListStickerPackItemControl, editing: ItemListStickerPackItemEditing, enabled: Bool, sectionId: ItemListSectionId, action: (() -> Void)?, setPackIdWithRevealedOptions: @escaping (ItemCollectionId?, ItemCollectionId?) -> Void, addPack: @escaping () -> Void, removePack: @escaping () -> Void) {
|
init(theme: PresentationTheme, strings: PresentationStrings, account: Account, packInfo: StickerPackCollectionInfo, itemCount: String, topItem: StickerPackItem?, unread: Bool, control: ItemListStickerPackItemControl, editing: ItemListStickerPackItemEditing, enabled: Bool, playAnimatedStickers: Bool, sectionId: ItemListSectionId, action: (() -> Void)?, setPackIdWithRevealedOptions: @escaping (ItemCollectionId?, ItemCollectionId?) -> Void, addPack: @escaping () -> Void, removePack: @escaping () -> Void) {
|
||||||
self.theme = theme
|
self.theme = theme
|
||||||
self.strings = strings
|
self.strings = strings
|
||||||
self.account = account
|
self.account = account
|
||||||
@ -64,6 +65,7 @@ final class ItemListStickerPackItem: ListViewItem, ItemListItem {
|
|||||||
self.control = control
|
self.control = control
|
||||||
self.editing = editing
|
self.editing = editing
|
||||||
self.enabled = enabled
|
self.enabled = enabled
|
||||||
|
self.playAnimatedStickers = playAnimatedStickers
|
||||||
self.sectionId = sectionId
|
self.sectionId = sectionId
|
||||||
self.action = action
|
self.action = action
|
||||||
self.setPackIdWithRevealedOptions = setPackIdWithRevealedOptions
|
self.setPackIdWithRevealedOptions = setPackIdWithRevealedOptions
|
||||||
@ -162,7 +164,7 @@ class ItemListStickerPackItemNode: ItemListRevealOptionsItemNode {
|
|||||||
let isVisible = self.visibility != .none
|
let isVisible = self.visibility != .none
|
||||||
|
|
||||||
if wasVisible != isVisible {
|
if wasVisible != isVisible {
|
||||||
self.animationNode?.visibility = isVisible
|
self.animationNode?.visibility = isVisible && (self.layoutParams?.0.playAnimatedStickers ?? true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -558,8 +560,8 @@ class ItemListStickerPackItemNode: ItemListRevealOptionsItemNode {
|
|||||||
strongSelf.animationNode = animationNode
|
strongSelf.animationNode = animationNode
|
||||||
strongSelf.addSubnode(animationNode)
|
strongSelf.addSubnode(animationNode)
|
||||||
animationNode.setup(account: item.account, resource: resource, width: 80, height: 80, mode: .cached)
|
animationNode.setup(account: item.account, resource: resource, width: 80, height: 80, mode: .cached)
|
||||||
animationNode.visibility = strongSelf.visibility != .none
|
|
||||||
}
|
}
|
||||||
|
animationNode.visibility = strongSelf.visibility != .none && item.playAnimatedStickers
|
||||||
if let animationNode = strongSelf.animationNode {
|
if let animationNode = strongSelf.animationNode {
|
||||||
transition.updateFrame(node: animationNode, frame: imageFrame)
|
transition.updateFrame(node: animationNode, frame: imageFrame)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -101,7 +101,7 @@ final class OverlayPlayerControllerNode: ViewControllerTracingNode, UIGestureRec
|
|||||||
}, seekToTimecode: { _, _, _ in
|
}, seekToTimecode: { _, _, _ in
|
||||||
}, requestMessageUpdate: { _ in
|
}, requestMessageUpdate: { _ in
|
||||||
}, cancelInteractiveKeyboardGestures: {
|
}, cancelInteractiveKeyboardGestures: {
|
||||||
}, automaticMediaDownloadSettings: MediaAutoDownloadSettings.defaultSettings, pollActionState: ChatInterfacePollActionState())
|
}, automaticMediaDownloadSettings: MediaAutoDownloadSettings.defaultSettings, pollActionState: ChatInterfacePollActionState(), stickerSettings: ChatInterfaceStickerSettings(loopAnimatedStickers: false))
|
||||||
|
|
||||||
self.dimNode = ASDisplayNode()
|
self.dimNode = ASDisplayNode()
|
||||||
self.dimNode.backgroundColor = UIColor(white: 0.0, alpha: 0.5)
|
self.dimNode.backgroundColor = UIColor(white: 0.0, alpha: 0.5)
|
||||||
|
|||||||
@ -272,7 +272,7 @@ public class PeerMediaCollectionController: TelegramController {
|
|||||||
}, requestMessageUpdate: { _ in
|
}, requestMessageUpdate: { _ in
|
||||||
}, cancelInteractiveKeyboardGestures: {
|
}, cancelInteractiveKeyboardGestures: {
|
||||||
}, automaticMediaDownloadSettings: MediaAutoDownloadSettings.defaultSettings,
|
}, automaticMediaDownloadSettings: MediaAutoDownloadSettings.defaultSettings,
|
||||||
pollActionState: ChatInterfacePollActionState())
|
pollActionState: ChatInterfacePollActionState(), stickerSettings: ChatInterfaceStickerSettings(loopAnimatedStickers: false))
|
||||||
|
|
||||||
self.controllerInteraction = controllerInteraction
|
self.controllerInteraction = controllerInteraction
|
||||||
|
|
||||||
|
|||||||
@ -5,6 +5,7 @@ import AsyncDisplayKit
|
|||||||
import Postbox
|
import Postbox
|
||||||
import TelegramCore
|
import TelegramCore
|
||||||
import SwiftSignalKit
|
import SwiftSignalKit
|
||||||
|
import TelegramUIPreferences
|
||||||
|
|
||||||
enum StickerPackPreviewControllerMode {
|
enum StickerPackPreviewControllerMode {
|
||||||
case `default`
|
case `default`
|
||||||
@ -140,8 +141,13 @@ final class StickerPackPreviewController: ViewController {
|
|||||||
}
|
}
|
||||||
let account = self.context.account
|
let account = self.context.account
|
||||||
self.displayNodeDidLoad()
|
self.displayNodeDidLoad()
|
||||||
self.stickerPackDisposable.set((self.stickerPackContents.get()
|
self.stickerPackDisposable.set((combineLatest(self.stickerPackContents.get(), self.context.sharedContext.accountManager.sharedData(keys: [ApplicationSpecificSharedDataKeys.stickerSettings]) |> take(1))
|
||||||
|> mapToSignal { next -> Signal<LoadedStickerPack, NoError> in
|
|> mapToSignal { next, sharedData -> Signal<(LoadedStickerPack, StickerSettings), NoError> in
|
||||||
|
var stickerSettings = StickerSettings.defaultSettings
|
||||||
|
if let value = sharedData.entries[ApplicationSpecificSharedDataKeys.stickerSettings] as? StickerSettings {
|
||||||
|
stickerSettings = value
|
||||||
|
}
|
||||||
|
|
||||||
switch next {
|
switch next {
|
||||||
case let .result(_, items, _):
|
case let .result(_, items, _):
|
||||||
var preloadSignals: [Signal<Bool, NoError>] = []
|
var preloadSignals: [Signal<Bool, NoError>] = []
|
||||||
@ -172,26 +178,26 @@ final class StickerPackPreviewController: ViewController {
|
|||||||
return !values.contains(false)
|
return !values.contains(false)
|
||||||
}
|
}
|
||||||
|> distinctUntilChanged
|
|> distinctUntilChanged
|
||||||
|> mapToSignal { loaded -> Signal<LoadedStickerPack, NoError> in
|
|> mapToSignal { loaded -> Signal<(LoadedStickerPack, StickerSettings), NoError> in
|
||||||
if !loaded {
|
if !loaded {
|
||||||
return .single(.fetching)
|
return .single((.fetching, stickerSettings))
|
||||||
} else {
|
} else {
|
||||||
return .single(next)
|
return .single((next, stickerSettings))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
return .single(next)
|
return .single((next, stickerSettings))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|> deliverOnMainQueue).start(next: { [weak self] next in
|
|> deliverOnMainQueue).start(next: { [weak self] next in
|
||||||
if let strongSelf = self {
|
if let strongSelf = self {
|
||||||
if case .none = next {
|
if case .none = next.0 {
|
||||||
let presentationData = strongSelf.context.sharedContext.currentPresentationData.with { $0 }
|
let presentationData = strongSelf.context.sharedContext.currentPresentationData.with { $0 }
|
||||||
strongSelf.present(textAlertController(context: strongSelf.context, title: nil, text: presentationData.strings.StickerPack_ErrorNotFound, actions: [TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_OK, action: {})]), in: .window(.root))
|
strongSelf.present(textAlertController(context: strongSelf.context, title: nil, text: presentationData.strings.StickerPack_ErrorNotFound, actions: [TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_OK, action: {})]), in: .window(.root))
|
||||||
strongSelf.dismiss()
|
strongSelf.dismiss()
|
||||||
} else {
|
} else {
|
||||||
strongSelf.controllerNode.updateStickerPack(next)
|
strongSelf.controllerNode.updateStickerPack(next.0, stickerSettings: next.1)
|
||||||
strongSelf.stickerPackContentsValue = next
|
strongSelf.stickerPackContentsValue = next.0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
|
|||||||
@ -6,6 +6,7 @@ import SwiftSignalKit
|
|||||||
import Postbox
|
import Postbox
|
||||||
import TelegramCore
|
import TelegramCore
|
||||||
import TelegramPresentationData
|
import TelegramPresentationData
|
||||||
|
import TelegramUIPreferences
|
||||||
|
|
||||||
private struct StickerPackPreviewGridEntry: Comparable, Identifiable {
|
private struct StickerPackPreviewGridEntry: Comparable, Identifiable {
|
||||||
let index: Int
|
let index: Int
|
||||||
@ -75,6 +76,7 @@ final class StickerPackPreviewControllerNode: ViewControllerTracingNode, UIScrol
|
|||||||
private var stickerPack: LoadedStickerPack?
|
private var stickerPack: LoadedStickerPack?
|
||||||
private var stickerPackUpdated = false
|
private var stickerPackUpdated = false
|
||||||
private var stickerPackInitiallyInstalled : Bool?
|
private var stickerPackInitiallyInstalled : Bool?
|
||||||
|
private var stickerSettings: StickerSettings?
|
||||||
|
|
||||||
private var currentItems: [StickerPackPreviewGridEntry] = []
|
private var currentItems: [StickerPackPreviewGridEntry] = []
|
||||||
|
|
||||||
@ -131,13 +133,7 @@ final class StickerPackPreviewControllerNode: ViewControllerTracingNode, UIScrol
|
|||||||
|
|
||||||
super.init()
|
super.init()
|
||||||
|
|
||||||
self.interaction = StickerPackPreviewInteraction(sendSticker: { [weak self] item in
|
self.interaction = StickerPackPreviewInteraction(playAnimatedStickers: false)
|
||||||
if let strongSelf = self, let sendSticker = strongSelf.sendSticker {
|
|
||||||
/*if sendSticker(item.file) {
|
|
||||||
strongSelf.cancel?()
|
|
||||||
}*/
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
self.backgroundColor = nil
|
self.backgroundColor = nil
|
||||||
self.isOpaque = false
|
self.isOpaque = false
|
||||||
@ -510,16 +506,16 @@ final class StickerPackPreviewControllerNode: ViewControllerTracingNode, UIScrol
|
|||||||
} else {
|
} else {
|
||||||
dismissOnAction = true
|
dismissOnAction = true
|
||||||
}
|
}
|
||||||
if let stickerPack = self.stickerPack {
|
if let stickerPack = self.stickerPack, let stickerSettings = self.stickerSettings {
|
||||||
switch stickerPack {
|
switch stickerPack {
|
||||||
case let .result(info, items, installed):
|
case let .result(info, items, installed):
|
||||||
if installed {
|
if installed {
|
||||||
let _ = removeStickerPackInteractively(postbox: self.context.account.postbox, id: info.id, option: .delete).start()
|
let _ = removeStickerPackInteractively(postbox: self.context.account.postbox, id: info.id, option: .delete).start()
|
||||||
updateStickerPack(.result(info: info, items: items, installed: false))
|
self.updateStickerPack(.result(info: info, items: items, installed: false), stickerSettings: stickerSettings)
|
||||||
} else {
|
} else {
|
||||||
let _ = addStickerPackInteractively(postbox: self.context.account.postbox, info: info, items: items).start()
|
let _ = addStickerPackInteractively(postbox: self.context.account.postbox, info: info, items: items).start()
|
||||||
if !dismissOnAction {
|
if !dismissOnAction {
|
||||||
updateStickerPack(.result(info: info, items: items, installed: true))
|
self.updateStickerPack(.result(info: info, items: items, installed: true), stickerSettings: stickerSettings)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if dismissOnAction {
|
if dismissOnAction {
|
||||||
@ -566,9 +562,13 @@ final class StickerPackPreviewControllerNode: ViewControllerTracingNode, UIScrol
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func updateStickerPack(_ stickerPack: LoadedStickerPack) {
|
func updateStickerPack(_ stickerPack: LoadedStickerPack, stickerSettings: StickerSettings) {
|
||||||
self.stickerPack = stickerPack
|
self.stickerPack = stickerPack
|
||||||
|
self.stickerSettings = stickerSettings
|
||||||
self.stickerPackUpdated = true
|
self.stickerPackUpdated = true
|
||||||
|
|
||||||
|
self.interaction.playAnimatedStickers = stickerSettings.loopAnimatedStickers
|
||||||
|
|
||||||
if let _ = self.containerLayout {
|
if let _ = self.containerLayout {
|
||||||
self.dequeueUpdateStickerPack()
|
self.dequeueUpdateStickerPack()
|
||||||
}
|
}
|
||||||
|
|||||||
@ -8,11 +8,10 @@ import Postbox
|
|||||||
|
|
||||||
final class StickerPackPreviewInteraction {
|
final class StickerPackPreviewInteraction {
|
||||||
var previewedItem: StickerPreviewPeekItem?
|
var previewedItem: StickerPreviewPeekItem?
|
||||||
|
var playAnimatedStickers: Bool
|
||||||
|
|
||||||
let sendSticker: (StickerPackItem) -> Void
|
init(playAnimatedStickers: Bool) {
|
||||||
|
self.playAnimatedStickers = playAnimatedStickers
|
||||||
init(sendSticker: @escaping (StickerPackItem) -> Void) {
|
|
||||||
self.sendSticker = sendSticker
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -53,12 +52,10 @@ final class StickerPackPreviewGridItemNode: GridItemNode {
|
|||||||
|
|
||||||
override var isVisibleInGrid: Bool {
|
override var isVisibleInGrid: Bool {
|
||||||
didSet {
|
didSet {
|
||||||
self.animationNode?.visibility = self.isVisibleInGrid
|
self.animationNode?.visibility = self.isVisibleInGrid && self.interaction?.playAnimatedStickers ?? true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private let textNode: ASTextNode
|
|
||||||
|
|
||||||
private var currentIsPreviewing = false
|
private var currentIsPreviewing = false
|
||||||
|
|
||||||
private let stickerFetchedDisposable = MetaDisposable()
|
private let stickerFetchedDisposable = MetaDisposable()
|
||||||
@ -74,16 +71,10 @@ final class StickerPackPreviewGridItemNode: GridItemNode {
|
|||||||
override init() {
|
override init() {
|
||||||
self.imageNode = TransformImageNode()
|
self.imageNode = TransformImageNode()
|
||||||
self.imageNode.isLayerBacked = !smartInvertColorsEnabled()
|
self.imageNode.isLayerBacked = !smartInvertColorsEnabled()
|
||||||
//self.imageNode.alphaTransitionOnFirstUpdate = true
|
|
||||||
|
|
||||||
self.textNode = ASTextNode()
|
|
||||||
self.textNode.isUserInteractionEnabled = false
|
|
||||||
self.textNode.displaysAsynchronously = true
|
|
||||||
|
|
||||||
super.init()
|
super.init()
|
||||||
|
|
||||||
self.addSubnode(self.imageNode)
|
self.addSubnode(self.imageNode)
|
||||||
//self.addSubnode(self.textNode)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
deinit {
|
deinit {
|
||||||
@ -100,14 +91,6 @@ final class StickerPackPreviewGridItemNode: GridItemNode {
|
|||||||
self.interaction = interaction
|
self.interaction = interaction
|
||||||
|
|
||||||
if self.currentState == nil || self.currentState!.0 !== account || self.currentState!.1 != stickerItem {
|
if self.currentState == nil || self.currentState!.0 !== account || self.currentState!.1 != stickerItem {
|
||||||
var text = ""
|
|
||||||
for attribute in stickerItem.file.attributes {
|
|
||||||
if case let .Sticker(displayText, _, _) = attribute {
|
|
||||||
text = displayText
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
self.textNode.attributedText = NSAttributedString(string: text, font: textFont, textColor: .black, paragraphAlignment: .right)
|
|
||||||
if let dimensions = stickerItem.file.dimensions {
|
if let dimensions = stickerItem.file.dimensions {
|
||||||
if stickerItem.file.isAnimatedSticker {
|
if stickerItem.file.isAnimatedSticker {
|
||||||
self.imageNode.setSignal(chatMessageAnimatedSticker(postbox: account.postbox, file: stickerItem.file, small: false, size: CGSize(width: 160.0, height: 160.0)))
|
self.imageNode.setSignal(chatMessageAnimatedSticker(postbox: account.postbox, file: stickerItem.file, small: false, size: CGSize(width: 160.0, height: 160.0)))
|
||||||
@ -121,7 +104,7 @@ final class StickerPackPreviewGridItemNode: GridItemNode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.animationNode?.setup(account: account, resource: stickerItem.file.resource, width: 160, height: 160, mode: .cached)
|
self.animationNode?.setup(account: account, resource: stickerItem.file.resource, width: 160, height: 160, mode: .cached)
|
||||||
self.animationNode?.visibility = self.isVisibleInGrid
|
self.animationNode?.visibility = self.isVisibleInGrid && self.interaction?.playAnimatedStickers ?? true
|
||||||
self.stickerFetchedDisposable.set(freeMediaFileResourceInteractiveFetched(account: account, fileReference: stickerPackFileReference(stickerItem.file), resource: stickerItem.file.resource).start())
|
self.stickerFetchedDisposable.set(freeMediaFileResourceInteractiveFetched(account: account, fileReference: stickerPackFileReference(stickerItem.file), resource: stickerItem.file.resource).start())
|
||||||
} else {
|
} else {
|
||||||
if let animationNode = self.animationNode {
|
if let animationNode = self.animationNode {
|
||||||
@ -157,9 +140,6 @@ final class StickerPackPreviewGridItemNode: GridItemNode {
|
|||||||
animationNode.frame = CGRect(origin: CGPoint(x: floor((bounds.size.width - imageSize.width) / 2.0), y: (bounds.size.height - imageSize.height) / 2.0), size: imageSize)
|
animationNode.frame = CGRect(origin: CGPoint(x: floor((bounds.size.width - imageSize.width) / 2.0), y: (bounds.size.height - imageSize.height) / 2.0), size: imageSize)
|
||||||
animationNode.updateLayout(size: imageSize)
|
animationNode.updateLayout(size: imageSize)
|
||||||
}
|
}
|
||||||
let boundingFrame = CGRect(origin: CGPoint(x: floor((bounds.size.width - boundingSize.width) / 2.0), y: (bounds.size.height - boundingSize.height) / 2.0), size: boundingSize)
|
|
||||||
let textSize = CGSize(width: 32.0, height: 24.0)
|
|
||||||
self.textNode.frame = CGRect(origin: CGPoint(x: boundingFrame.maxX - 1.0 - textSize.width, y: boundingFrame.height + 10.0 - textSize.height), size: textSize)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -169,7 +149,7 @@ final class StickerPackPreviewGridItemNode: GridItemNode {
|
|||||||
|
|
||||||
@objc func imageNodeTap(_ recognizer: UITapGestureRecognizer) {
|
@objc func imageNodeTap(_ recognizer: UITapGestureRecognizer) {
|
||||||
if let interaction = self.interaction, let (_, item, _) = self.currentState, case .ended = recognizer.state {
|
if let interaction = self.interaction, let (_, item, _) = self.currentState, case .ended = recognizer.state {
|
||||||
interaction.sendSticker(item)
|
//interaction.sendSticker(item)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -10,21 +10,25 @@ public enum EmojiStickerSuggestionMode: Int32 {
|
|||||||
|
|
||||||
public struct StickerSettings: PreferencesEntry, Equatable {
|
public struct StickerSettings: PreferencesEntry, Equatable {
|
||||||
public var emojiStickerSuggestionMode: EmojiStickerSuggestionMode
|
public var emojiStickerSuggestionMode: EmojiStickerSuggestionMode
|
||||||
|
public var loopAnimatedStickers: Bool
|
||||||
|
|
||||||
public static var defaultSettings: StickerSettings {
|
public static var defaultSettings: StickerSettings {
|
||||||
return StickerSettings(emojiStickerSuggestionMode: .all)
|
return StickerSettings(emojiStickerSuggestionMode: .all, loopAnimatedStickers: true)
|
||||||
}
|
}
|
||||||
|
|
||||||
init(emojiStickerSuggestionMode: EmojiStickerSuggestionMode) {
|
init(emojiStickerSuggestionMode: EmojiStickerSuggestionMode, loopAnimatedStickers: Bool) {
|
||||||
self.emojiStickerSuggestionMode = emojiStickerSuggestionMode
|
self.emojiStickerSuggestionMode = emojiStickerSuggestionMode
|
||||||
|
self.loopAnimatedStickers = loopAnimatedStickers
|
||||||
}
|
}
|
||||||
|
|
||||||
public init(decoder: PostboxDecoder) {
|
public init(decoder: PostboxDecoder) {
|
||||||
self.emojiStickerSuggestionMode = EmojiStickerSuggestionMode(rawValue: decoder.decodeInt32ForKey("emojiStickerSuggestionMode", orElse: 0))!
|
self.emojiStickerSuggestionMode = EmojiStickerSuggestionMode(rawValue: decoder.decodeInt32ForKey("emojiStickerSuggestionMode", orElse: 0))!
|
||||||
|
self.loopAnimatedStickers = decoder.decodeBoolForKey("loopAnimatedStickers", orElse: true)
|
||||||
}
|
}
|
||||||
|
|
||||||
public func encode(_ encoder: PostboxEncoder) {
|
public func encode(_ encoder: PostboxEncoder) {
|
||||||
encoder.encodeInt32(self.emojiStickerSuggestionMode.rawValue, forKey: "emojiStickerSuggestionMode")
|
encoder.encodeInt32(self.emojiStickerSuggestionMode.rawValue, forKey: "emojiStickerSuggestionMode")
|
||||||
|
encoder.encodeBool(self.loopAnimatedStickers, forKey: "loopAnimatedStickers")
|
||||||
}
|
}
|
||||||
|
|
||||||
public func isEqual(to: PreferencesEntry) -> Bool {
|
public func isEqual(to: PreferencesEntry) -> Bool {
|
||||||
@ -36,11 +40,15 @@ public struct StickerSettings: PreferencesEntry, Equatable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static func ==(lhs: StickerSettings, rhs: StickerSettings) -> Bool {
|
public static func ==(lhs: StickerSettings, rhs: StickerSettings) -> Bool {
|
||||||
return lhs.emojiStickerSuggestionMode == rhs.emojiStickerSuggestionMode
|
return lhs.emojiStickerSuggestionMode == rhs.emojiStickerSuggestionMode && lhs.loopAnimatedStickers == rhs.loopAnimatedStickers
|
||||||
}
|
}
|
||||||
|
|
||||||
public func withUpdatedEmojiStickerSuggestionMode(_ emojiStickerSuggestionMode: EmojiStickerSuggestionMode) -> StickerSettings {
|
public func withUpdatedEmojiStickerSuggestionMode(_ emojiStickerSuggestionMode: EmojiStickerSuggestionMode) -> StickerSettings {
|
||||||
return StickerSettings(emojiStickerSuggestionMode: emojiStickerSuggestionMode)
|
return StickerSettings(emojiStickerSuggestionMode: emojiStickerSuggestionMode, loopAnimatedStickers: self.loopAnimatedStickers)
|
||||||
|
}
|
||||||
|
|
||||||
|
public func withUpdatedLoopAnimatedStickers(_ loopAnimatedStickers: Bool) -> StickerSettings {
|
||||||
|
return StickerSettings(emojiStickerSuggestionMode: self.emojiStickerSuggestionMode, loopAnimatedStickers: loopAnimatedStickers)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user