Merge branch 'master' of gitlab.com:peter-iakovlev/TelegramUI

This commit is contained in:
Ilya Laktyushin 2019-01-15 20:03:12 +04:00
commit c9631285bf
17 changed files with 851 additions and 701 deletions

View File

@ -122,6 +122,7 @@
09FE756D2153F5F900A3120F /* CallRouteActionSheetItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09FE756C2153F5F900A3120F /* CallRouteActionSheetItem.swift */; };
9F06830921A404AB001D8EDB /* NotificationExceptionControllerNode.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F06830821A404AB001D8EDB /* NotificationExceptionControllerNode.swift */; };
9F06830B21A404C4001D8EDB /* NotificationExcetionSettingsController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F06830A21A404C4001D8EDB /* NotificationExcetionSettingsController.swift */; };
D000CABA21EE130D0011B15D /* MapResourceToAvatarSizes.swift in Sources */ = {isa = PBXBuildFile; fileRef = D000CAB921EE130D0011B15D /* MapResourceToAvatarSizes.swift */; };
D005808B21CAB8F000CB7CD3 /* VoipDerivedState.swift in Sources */ = {isa = PBXBuildFile; fileRef = D005808A21CAB8F000CB7CD3 /* VoipDerivedState.swift */; };
D00580A021DCF0A200CB7CD3 /* WallpaperListPreviewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D005809F21DCF0A200CB7CD3 /* WallpaperListPreviewController.swift */; };
D00580A221DCF0B700CB7CD3 /* WallpaperListPreviewControllerNode.swift in Sources */ = {isa = PBXBuildFile; fileRef = D00580A121DCF0B700CB7CD3 /* WallpaperListPreviewControllerNode.swift */; };
@ -1248,6 +1249,7 @@
09FE756C2153F5F900A3120F /* CallRouteActionSheetItem.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CallRouteActionSheetItem.swift; sourceTree = "<group>"; };
9F06830821A404AB001D8EDB /* NotificationExceptionControllerNode.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NotificationExceptionControllerNode.swift; sourceTree = "<group>"; };
9F06830A21A404C4001D8EDB /* NotificationExcetionSettingsController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NotificationExcetionSettingsController.swift; sourceTree = "<group>"; };
D000CAB921EE130D0011B15D /* MapResourceToAvatarSizes.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MapResourceToAvatarSizes.swift; sourceTree = "<group>"; };
D00219051DDD1C9E00BE708A /* ImageContainingNode.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ImageContainingNode.swift; sourceTree = "<group>"; };
D002A0D01E9B99F500A81812 /* SoftwareVideoSource.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SoftwareVideoSource.swift; sourceTree = "<group>"; };
D002A0D21E9BBE6700A81812 /* MultiplexedSoftwareVideoSourceManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MultiplexedSoftwareVideoSourceManager.swift; sourceTree = "<group>"; };
@ -4739,6 +4741,7 @@
09F664CD21EBB3A100AB7E26 /* ImageBlur.swift */,
099529B321D3E5D800805E13 /* CheckDiskSpace.swift */,
09DD5D4F21ECC3C400D7007A /* SuppressContactsWarning.swift */,
D000CAB921EE130D0011B15D /* MapResourceToAvatarSizes.swift */,
);
name = Utils;
sourceTree = "<group>";
@ -5457,6 +5460,7 @@
D0B2F76E2052B59F00D3BFB9 /* InviteContactsController.swift in Sources */,
D0EC6D591EB9F58800EBF1C3 /* ChatMessageThrottledProcessingManager.swift in Sources */,
D0BFAE4620AB04FB00793CF2 /* ChatRestrictedInputPanelNode.swift in Sources */,
D000CABA21EE130D0011B15D /* MapResourceToAvatarSizes.swift in Sources */,
D06E0F8E1F79ABFB003CF3DD /* ChatLoadingNode.swift in Sources */,
D0EC6D5A1EB9F58800EBF1C3 /* ListMessageItem.swift in Sources */,
D0EC6D5B1EB9F58800EBF1C3 /* ListMessageNode.swift in Sources */,

View File

@ -614,7 +614,9 @@ public func channelInfoController(account: Account, peerId: PeerId) -> ViewContr
updateState {
$0.withUpdatedUpdatingAvatar(.image(representation, true))
}
updateAvatarDisposable.set((updatePeerPhoto(postbox: account.postbox, network: account.network, stateManager: account.stateManager, accountPeerId: account.peerId, peerId: peerId, photo: uploadedPeerPhoto(postbox: account.postbox, network: account.network, resource: resource)) |> deliverOnMainQueue).start(next: { result in
updateAvatarDisposable.set((updatePeerPhoto(postbox: account.postbox, network: account.network, stateManager: account.stateManager, accountPeerId: account.peerId, peerId: peerId, photo: uploadedPeerPhoto(postbox: account.postbox, network: account.network, resource: resource), mapResourceToAvatarSizes: { resource, representations in
return mapResourceToAvatarSizes(postbox: account.postbox, resource: resource, representations: representations)
}) |> deliverOnMainQueue).start(next: { result in
switch result {
case .complete:
updateState {
@ -650,7 +652,9 @@ public func channelInfoController(account: Account, peerId: PeerId) -> ViewContr
return $0.withUpdatedUpdatingAvatar(.none)
}
}
updateAvatarDisposable.set((updatePeerPhoto(postbox: account.postbox, network: account.network, stateManager: account.stateManager, accountPeerId: account.peerId, peerId: peerId, photo: nil) |> deliverOnMainQueue).start(next: { result in
updateAvatarDisposable.set((updatePeerPhoto(postbox: account.postbox, network: account.network, stateManager: account.stateManager, accountPeerId: account.peerId, peerId: peerId, photo: nil, mapResourceToAvatarSizes: { resource, representations in
return mapResourceToAvatarSizes(postbox: account.postbox, resource: resource, representations: representations)
}) |> deliverOnMainQueue).start(next: { result in
switch result {
case .complete:
updateState {

View File

@ -54,11 +54,12 @@ class ChatListControllerNode: ASDisplayNode {
self.backgroundColor = presentationData.theme.chatList.backgroundColor
self.addSubnode(self.chatListNode)
self.chatListNode.isEmptyUpdated = { [weak self] isEmpty in
self.chatListNode.isEmptyUpdated = { [weak self] isEmptyState in
guard let strongSelf = self else {
return
}
if isEmpty {
switch isEmptyState {
case let .empty(isLoading):
if strongSelf.chatListEmptyNode == nil {
let chatListEmptyNode = ChatListEmptyNode(theme: strongSelf.presentationData.theme, strings: strongSelf.presentationData.strings)
strongSelf.chatListEmptyNode = chatListEmptyNode
@ -67,7 +68,8 @@ class ChatListControllerNode: ASDisplayNode {
strongSelf.containerLayoutUpdated(layout, navigationBarHeight: navigationHeight, transition: .immediate)
}
}
} else if let chatListEmptyNode = strongSelf.chatListEmptyNode {
case .notEmpty:
if let chatListEmptyNode = strongSelf.chatListEmptyNode {
strongSelf.chatListEmptyNode = nil
chatListEmptyNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2, removeOnCompletion: false, completion: { [weak chatListEmptyNode] _ in
chatListEmptyNode?.removeFromSupernode()
@ -75,6 +77,7 @@ class ChatListControllerNode: ASDisplayNode {
}
}
}
}
override func didLoad() {
super.didLoad()

View File

@ -281,6 +281,11 @@ enum ChatListNodeScrollPosition {
case top
}
enum ChatListNodeEmtpyState: Equatable {
case notEmpty
case empty(isLoading: Bool)
}
final class ChatListNode: ListView {
private let controlsHistoryPreload: Bool
private let account: Account
@ -346,8 +351,8 @@ final class ChatListNode: ListView {
}
}
var isEmptyUpdated: ((Bool) -> Void)?
private var wasEmpty: Bool?
var isEmptyUpdated: ((ChatListNodeEmtpyState) -> Void)?
private var currentIsEmptyState: ChatListNodeEmtpyState?
private let currentRemovingPeerId = Atomic<PeerId?>(value: nil)
func setCurrentRemovingPeerId(_ peerId: PeerId?) {
@ -469,7 +474,8 @@ final class ChatListNode: ListView {
let chatListNodeViewTransition = combineLatest(savedMessagesPeer, chatListViewUpdate, self.statePromise.get()) |> mapToQueue { (savedMessagesPeer, update, state) -> Signal<ChatListNodeListViewTransition, NoError> in
let entries = chatListNodeEntriesForView(update.view, state: state, savedMessagesPeer: savedMessagesPeer, mode: mode).filter { entry in
let (rawEntries, isLoading) = chatListNodeEntriesForView(update.view, state: state, savedMessagesPeer: savedMessagesPeer, mode: mode)
let entries = rawEntries.filter { entry in
switch entry {
case let .PeerEntry(_, _, _, _, _, _, peer, _, _, _, _, _, _):
switch mode {
@ -507,7 +513,7 @@ final class ChatListNode: ListView {
}
}
let processedView = ChatListNodeView(originalView: update.view, filteredEntries: entries)
let processedView = ChatListNodeView(originalView: update.view, filteredEntries: entries, isLoading: isLoading)
let previousView = previousView.swap(processedView)
let previousState = previousState.swap(state)
@ -520,6 +526,8 @@ final class ChatListNode: ListView {
if case .HoleEntry = previous.filteredEntries[0] {
previousWasEmptyOrSingleHole = true
}
} else if previous.filteredEntries.isEmpty && previous.isLoading {
previousWasEmptyOrSingleHole = true
}
} else {
previousWasEmptyOrSingleHole = true
@ -991,10 +999,17 @@ final class ChatListNode: ListView {
strongSelf._ready.set(true)
}
let isEmpty = transition.chatListView.filteredEntries.isEmpty
if strongSelf.wasEmpty != isEmpty {
strongSelf.wasEmpty = isEmpty
strongSelf.isEmptyUpdated?(isEmpty)
let isEmptyState: ChatListNodeEmtpyState
if transition.chatListView.isLoading {
isEmptyState = .empty(isLoading: true)
} else if transition.chatListView.filteredEntries.isEmpty {
isEmptyState = .empty(isLoading: false)
} else {
isEmptyState = .notEmpty
}
if strongSelf.currentIsEmptyState != isEmptyState {
strongSelf.currentIsEmptyState = isEmptyState
strongSelf.isEmptyUpdated?(isEmptyState)
}
completion()

View File

@ -197,7 +197,7 @@ private func offsetPinnedIndex(_ index: ChatListIndex, offset: UInt16) -> ChatLi
}
}
func chatListNodeEntriesForView(_ view: ChatListView, state: ChatListNodeState, savedMessagesPeer: Peer?, mode: ChatListNodeMode) -> [ChatListNodeEntry] {
func chatListNodeEntriesForView(_ view: ChatListView, state: ChatListNodeState, savedMessagesPeer: Peer?, mode: ChatListNodeMode) -> (entries: [ChatListNodeEntry], loading: Bool) {
var result: [ChatListNodeEntry] = []
var pinnedIndexOffset: UInt16 = 0
if view.laterIndex == nil && savedMessagesPeer == nil {
@ -249,12 +249,10 @@ func chatListNodeEntriesForView(_ view: ChatListView, state: ChatListNodeState,
}
}
// if result.count == 1, case .HoleEntry = result[0] {
if result.count >= 1, case .HoleEntry = result[result.count - 1] {
return []
return ([], true)
} else if result.count == 1, case .HoleEntry = result[0] {
return []
return ([], true)
}
return result
return (result, false)
}

View File

@ -7,6 +7,7 @@ import Display
struct ChatListNodeView {
let originalView: ChatListView
let filteredEntries: [ChatListNodeEntry]
let isLoading: Bool
}
enum ChatListNodeViewTransitionReason {

View File

@ -4,6 +4,78 @@ import Display
import TelegramCore
import Postbox
private struct PercentCounterItem: Comparable {
var index: Int = 0
var percent: Int = 0
var remainder: Int = 0
static func <(lhs: PercentCounterItem, rhs: PercentCounterItem) -> Bool {
if lhs.remainder > rhs.remainder {
return true
} else if lhs.remainder < rhs.remainder {
return false
}
return lhs.percent < rhs.percent
}
}
private func adjustPercentCount(_ items: [PercentCounterItem], left: Int) -> [PercentCounterItem] {
var left = left
var items = items.sorted(by: <)
var i:Int = 0
while i != items.count {
let item = items[i]
var j = i + 1
loop: while j != items.count {
if items[j].percent != item.percent || items[j].remainder != item.remainder {
break loop
}
j += 1
}
let equal = j - i
if equal <= left {
left -= equal
while i != j {
items[i].percent += 1
i += 1
}
} else {
i = j
}
}
return items
}
private func countNicePercent(votes: [Int], total: Int) -> [Int] {
var result:[Int] = []
var items:[PercentCounterItem] = []
for _ in votes {
result.append(0)
items.append(PercentCounterItem())
}
let count = votes.count
var left:Int = 100
for i in 0 ..< votes.count {
let votes = votes[i]
items[i].index = i
items[i].percent = Int((Float(votes) * 100) / Float(total))
items[i].remainder = (votes * 100) - (items[i].percent * total)
left -= items[i].percent
}
if left > 0 && left <= count {
items = adjustPercentCount(items, left: left)
}
for item in items {
result[item.index] = item.percent
}
return result
}
private final class ChatMessagePollOptionRadioNodeParameters: NSObject {
let staticColor: UIColor
let animatedColor: UIColor
@ -205,31 +277,30 @@ private final class ChatMessagePollOptionRadioNode: ASDisplayNode {
private let percentageFont = Font.bold(14.5)
private func generatePercentageImage(presentationData: ChatPresentationData, incoming: Bool, value: CGFloat) -> UIImage {
private func generatePercentageImage(presentationData: ChatPresentationData, incoming: Bool, value: Int) -> UIImage {
return generateImage(CGSize(width: 42.0, height: 20.0), rotatedContext: { size, context in
UIGraphicsPushContext(context)
context.clear(CGRect(origin: CGPoint(), size: size))
let percents = Int(round(value * 100.0))
let string = NSAttributedString(string: "\(percents)%", font: percentageFont, textColor: incoming ? presentationData.theme.theme.chat.bubble.incomingPrimaryTextColor : presentationData.theme.theme.chat.bubble.outgoingPrimaryTextColor, paragraphAlignment: .right)
let string = NSAttributedString(string: "\(value)%", font: percentageFont, textColor: incoming ? presentationData.theme.theme.chat.bubble.incomingPrimaryTextColor : presentationData.theme.theme.chat.bubble.outgoingPrimaryTextColor, paragraphAlignment: .right)
string.draw(in: CGRect(origin: CGPoint(x: 0.0, y: 2.0), size: size))
UIGraphicsPopContext()
})!
}
private func generatePercentageAnimationImages(presentationData: ChatPresentationData, incoming: Bool, from fromValue: CGFloat, to toValue: CGFloat, duration: Double) -> [UIImage] {
private func generatePercentageAnimationImages(presentationData: ChatPresentationData, incoming: Bool, from fromValue: Int, to toValue: Int, duration: Double) -> [UIImage] {
let minimumFrameDuration = 1.0 / 40.0
let numberOfFrames = max(1, Int(duration / minimumFrameDuration))
var images: [UIImage] = []
for i in 0 ..< numberOfFrames {
let t = CGFloat(i) / CGFloat(numberOfFrames)
images.append(generatePercentageImage(presentationData: presentationData, incoming: incoming, value: (1.0 - t) * fromValue + t * toValue))
images.append(generatePercentageImage(presentationData: presentationData, incoming: incoming, value: Int((1.0 - t) * CGFloat(fromValue) + t * CGFloat(toValue))))
}
return images
}
private struct ChatMessagePollOptionResult: Equatable {
let normalized: CGFloat
let absolute: CGFloat
let percent: Int
}
private final class ChatMessagePollOptionNode: ASDisplayNode {
@ -312,7 +383,7 @@ private final class ChatMessagePollOptionNode: ASDisplayNode {
var updatedPercentageImage: UIImage?
if currentResult != optionResult {
updatedPercentageImage = generatePercentageImage(presentationData: presentationData, incoming: incoming, value: optionResult?.absolute ?? 0.0)
updatedPercentageImage = generatePercentageImage(presentationData: presentationData, incoming: incoming, value: optionResult?.percent ?? 0)
}
return (titleLayout.size.width + leftInset + rightInset, { width in
@ -374,9 +445,9 @@ private final class ChatMessagePollOptionNode: ASDisplayNode {
}
if let image = node.percentageImage {
node.percentageNode.frame = CGRect(origin: CGPoint(x: leftInset - 7.0 - image.size.width, y: 12.0), size: image.size)
if animated && previousResult?.absolute != optionResult?.absolute {
if animated && previousResult?.percent != optionResult?.percent {
let percentageDuration = 0.27
let images = generatePercentageAnimationImages(presentationData: presentationData, incoming: incoming, from: previousResult?.absolute ?? 0.0, to: optionResult?.absolute ?? 0.0, duration: percentageDuration)
let images = generatePercentageAnimationImages(presentationData: presentationData, incoming: incoming, from: previousResult?.percent ?? 0, to: optionResult?.percent ?? 0, duration: percentageDuration)
if !images.isEmpty {
let animation = CAKeyframeAnimation(keyPath: "contents")
animation.values = images.map { $0.cgImage! }
@ -635,6 +706,13 @@ class ChatMessagePollBubbleContentNode: ChatMessageBubbleContentNode {
}
}
var optionVoterCounts: [Int]
if totalVoterCount != 0 {
optionVoterCounts = countNicePercent(votes: (0 ..< poll.options.count).map({ Int(optionVoterCount[$0] ?? 0) }), total: Int(totalVoterCount))
} else {
optionVoterCounts = Array(repeating: 0, count: poll.options.count)
}
for i in 0 ..< poll.options.count {
let option = poll.options[i]
@ -647,12 +725,12 @@ class ChatMessagePollBubbleContentNode: ChatMessageBubbleContentNode {
var optionResult: ChatMessagePollOptionResult?
if let count = optionVoterCount[i] {
if maxOptionVoterCount != 0 && totalVoterCount != 0 {
optionResult = ChatMessagePollOptionResult(normalized: CGFloat(count) / CGFloat(maxOptionVoterCount), absolute: CGFloat(count) / CGFloat(totalVoterCount))
optionResult = ChatMessagePollOptionResult(normalized: CGFloat(count) / CGFloat(maxOptionVoterCount), percent: optionVoterCounts[i])
} else if poll.isClosed {
optionResult = ChatMessagePollOptionResult(normalized: 0, absolute: 0)
optionResult = ChatMessagePollOptionResult(normalized: 0, percent: 0)
}
} else if poll.isClosed {
optionResult = ChatMessagePollOptionResult(normalized: 0, absolute: 0)
optionResult = ChatMessagePollOptionResult(normalized: 0, percent: 0)
}
let result = makeLayout(item.account.peerId, item.presentationData, item.message, option, optionResult, constrainedSize.width - layoutConstants.bubble.borderInset * 2.0)
boundingSize.width = max(boundingSize.width, result.minimumWidth + layoutConstants.bubble.borderInset * 2.0)

View File

@ -247,7 +247,9 @@ public func createChannelController(account: Account) -> ViewController {
return $0.avatar
}
if let _ = updatingAvatar {
let _ = updatePeerPhoto(postbox: account.postbox, network: account.network, stateManager: account.stateManager, accountPeerId: account.peerId, peerId: peerId, photo: uploadedAvatar.get()).start()
let _ = updatePeerPhoto(postbox: account.postbox, network: account.network, stateManager: account.stateManager, accountPeerId: account.peerId, peerId: peerId, photo: uploadedAvatar.get(), mapResourceToAvatarSizes: { resource, representations in
return mapResourceToAvatarSizes(postbox: account.postbox, resource: resource, representations: representations)
}).start()
}
let controller = channelVisibilityController(account: account, peerId: peerId, mode: .initialSetup, upgradedToSupergroup: { _, f in f() })

View File

@ -255,7 +255,9 @@ public func createGroupController(account: Account, peerIds: [PeerId]) -> ViewCo
return current
}
endEditingImpl?()
actionsDisposable.add((createGroup(account: account, title: title, peerIds: peerIds) |> deliverOnMainQueue |> afterDisposed {
actionsDisposable.add((createGroup(account: account, title: title, peerIds: peerIds)
|> deliverOnMainQueue
|> afterDisposed {
Queue.mainQueue().async {
updateState { current in
var current = current
@ -269,7 +271,9 @@ public func createGroupController(account: Account, peerIds: [PeerId]) -> ViewCo
return $0.avatar
}
if let _ = updatingAvatar {
let _ = updatePeerPhoto(postbox: account.postbox, network: account.network, stateManager: account.stateManager, accountPeerId: account.peerId, peerId: peerId, photo: uploadedAvatar.get()).start()
let _ = updatePeerPhoto(postbox: account.postbox, network: account.network, stateManager: account.stateManager, accountPeerId: account.peerId, peerId: peerId, photo: uploadedAvatar.get(), mapResourceToAvatarSizes: { resource, representations in
return mapResourceToAvatarSizes(postbox: account.postbox, resource: resource, representations: representations)
}).start()
}
let controller = ChatController(account: account, chatLocation: .peer(peerId))
replaceControllerImpl?(controller)
@ -368,7 +372,8 @@ public func createGroupController(account: Account, peerIds: [PeerId]) -> ViewCo
let listState = ItemListNodeState(entries: createGroupEntries(presentationData: presentationData, state: state, peerIds: peerIds, view: view), style: .blocks, focusItemTag: CreateGroupEntryTag.info)
return (controllerState, (listState, arguments))
} |> afterDisposed {
}
|> afterDisposed {
actionsDisposable.dispose()
}

View File

@ -449,7 +449,9 @@ func editSettingsController(account: Account, currentName: ItemListAvatarAndName
updateState {
$0.withUpdatedUpdatingAvatar(.image(representation, true))
}
updateAvatarDisposable.set((updateAccountPhoto(account: account, resource: resource) |> deliverOnMainQueue).start(next: { result in
updateAvatarDisposable.set((updateAccountPhoto(account: account, resource: resource, mapResourceToAvatarSizes: { resource, representations in
return mapResourceToAvatarSizes(postbox: account.postbox, resource: resource, representations: representations)
}) |> deliverOnMainQueue).start(next: { result in
switch result {
case .complete:
updateState {
@ -485,7 +487,9 @@ func editSettingsController(account: Account, currentName: ItemListAvatarAndName
return $0.withUpdatedUpdatingAvatar(.none)
}
}
updateAvatarDisposable.set((updateAccountPhoto(account: account, resource: nil) |> deliverOnMainQueue).start(next: { result in
updateAvatarDisposable.set((updateAccountPhoto(account: account, resource: nil, mapResourceToAvatarSizes: { resource, representations in
return mapResourceToAvatarSizes(postbox: account.postbox, resource: resource, representations: representations)
}) |> deliverOnMainQueue).start(next: { result in
switch result {
case .complete:
updateState {

View File

@ -1279,7 +1279,9 @@ public func groupInfoController(account: Account, peerId originalPeerId: PeerId,
updateState {
$0.withUpdatedUpdatingAvatar(.image(representation, true))
}
updateAvatarDisposable.set((updatePeerPhoto(postbox: account.postbox, network: account.network, stateManager: account.stateManager, accountPeerId: account.peerId, peerId: peerView.peerId, photo: uploadedPeerPhoto(postbox: account.postbox, network: account.network, resource: resource)) |> deliverOnMainQueue).start(next: { result in
updateAvatarDisposable.set((updatePeerPhoto(postbox: account.postbox, network: account.network, stateManager: account.stateManager, accountPeerId: account.peerId, peerId: peerView.peerId, photo: uploadedPeerPhoto(postbox: account.postbox, network: account.network, resource: resource), mapResourceToAvatarSizes: { resource, representations in
return mapResourceToAvatarSizes(postbox: account.postbox, resource: resource, representations: representations)
}) |> deliverOnMainQueue).start(next: { result in
switch result {
case .complete:
updateState {
@ -1315,7 +1317,9 @@ public func groupInfoController(account: Account, peerId originalPeerId: PeerId,
return $0.withUpdatedUpdatingAvatar(.none)
}
}
updateAvatarDisposable.set((updatePeerPhoto(postbox: account.postbox, network: account.network, stateManager: account.stateManager, accountPeerId: account.peerId, peerId: peerView.peerId, photo: nil) |> deliverOnMainQueue).start(next: { result in
updateAvatarDisposable.set((updatePeerPhoto(postbox: account.postbox, network: account.network, stateManager: account.stateManager, accountPeerId: account.peerId, peerId: peerView.peerId, photo: nil, mapResourceToAvatarSizes: { resource, representations in
return mapResourceToAvatarSizes(postbox: account.postbox, resource: resource, representations: representations)
}) |> deliverOnMainQueue).start(next: { result in
switch result {
case .complete:
updateState {

View File

@ -95,13 +95,17 @@ private struct GroupPreHistorySetupState: Equatable {
var applyingSetting: Bool = false
}
private func groupPreHistorySetupEntries(presentationData: PresentationData, defaultValue: Bool, state: GroupPreHistorySetupState) -> [GroupPreHistorySetupEntry] {
private func groupPreHistorySetupEntries(isSupergroup: Bool, presentationData: PresentationData, defaultValue: Bool, state: GroupPreHistorySetupState) -> [GroupPreHistorySetupEntry] {
var entries: [GroupPreHistorySetupEntry] = []
let value = state.changedValue ?? defaultValue
entries.append(.header(presentationData.theme, presentationData.strings.Group_Setup_HistoryHeader))
entries.append(.visible(presentationData.theme, presentationData.strings.Group_Setup_HistoryVisible, value))
entries.append(.hidden(presentationData.theme, presentationData.strings.Group_Setup_HistoryHidden, !value))
if isSupergroup {
entries.append(.info(presentationData.theme, value ? presentationData.strings.Group_Setup_HistoryVisibleHelp : presentationData.strings.Group_Setup_HistoryHiddenHelp))
} else {
entries.append(.info(presentationData.theme, value ? presentationData.strings.Group_Setup_HistoryVisibleHelp : presentationData.strings.Group_Setup_BasicHistoryHiddenHelp))
}
return entries
}
@ -186,7 +190,7 @@ public func groupPreHistorySetupController(account: Account, peerId: PeerId, upg
}
let controllerState = ItemListControllerState(theme: presentationData.theme, title: .text(presentationData.strings.Group_Setup_HistoryTitle), leftNavigationButton: leftNavigationButton, rightNavigationButton: rightNavigationButton, backNavigationButton: ItemListBackButton(title: presentationData.strings.Common_Back))
let listState = ItemListNodeState(entries: groupPreHistorySetupEntries(presentationData: presentationData, defaultValue: defaultValue, state: state), style: .blocks)
let listState = ItemListNodeState(entries: groupPreHistorySetupEntries(isSupergroup: peerId.namespace == Namespaces.Peer.CloudChannel, presentationData: presentationData, defaultValue: defaultValue, state: state), style: .blocks)
return (controllerState, (listState, arguments))
}

View File

@ -0,0 +1,23 @@
import Foundation
import UIKit
import SwiftSignalKit
import Postbox
import TelegramCore
import Display
func mapResourceToAvatarSizes(postbox: Postbox, resource: MediaResource, representations: [TelegramMediaImageRepresentation]) -> Signal<[Int: Data], NoError> {
return postbox.mediaBox.resourceData(resource)
|> take(1)
|> map { data -> [Int: Data] in
guard data.complete, let image = UIImage(contentsOfFile: data.path) else {
return [:]
}
var result: [Int: Data] = [:]
for i in 0 ..< representations.count {
if let scaledImage = generateScaledImage(image: image, size: representations[i].dimensions, scale: 1.0), let scaledData = UIImageJPEGRepresentation(scaledImage, 0.8) {
result[i] = scaledData
}
}
return result
}
}

File diff suppressed because it is too large Load Diff

View File

@ -647,7 +647,9 @@ public func settingsController(account: Account, accountManager: AccountManager)
updateState {
$0.withUpdatedUpdatingAvatar(.image(representation, true))
}
updateAvatarDisposable.set((updateAccountPhoto(account: account, resource: resource) |> deliverOnMainQueue).start(next: { result in
updateAvatarDisposable.set((updateAccountPhoto(account: account, resource: resource, mapResourceToAvatarSizes: { resource, representations in
return mapResourceToAvatarSizes(postbox: account.postbox, resource: resource, representations: representations)
}) |> deliverOnMainQueue).start(next: { result in
switch result {
case .complete:
updateState {
@ -683,7 +685,9 @@ public func settingsController(account: Account, accountManager: AccountManager)
return $0.withUpdatedUpdatingAvatar(.none)
}
}
updateAvatarDisposable.set((updateAccountPhoto(account: account, resource: nil) |> deliverOnMainQueue).start(next: { result in
updateAvatarDisposable.set((updateAccountPhoto(account: account, resource: nil, mapResourceToAvatarSizes: { resource, representations in
return mapResourceToAvatarSizes(postbox: account.postbox, resource: resource, representations: representations)
}) |> deliverOnMainQueue).start(next: { result in
switch result {
case .complete:
updateState {

View File

@ -100,8 +100,8 @@ final class SettingsThemeWallpaperNode: ASDisplayNode {
convertedRepresentations.append(ImageRepresentationWithReference(representation: representation, reference: .standalone(resource: representation.resource)))
}
let dimensions = file.file.dimensions ?? CGSize(width: 100.0, height: 100.0)
//convertedRepresentations.append(ImageRepresentationWithReference(representation: .init(dimensions: dimensions, resource: file.file.resource), reference: .standalone(resource: file.file.resource)))
self.imageNode.setSignal(chatAvatarGalleryPhoto(account: account, representations: convertedRepresentations, autoFetchFullSize: true))
convertedRepresentations.append(ImageRepresentationWithReference(representation: .init(dimensions: dimensions, resource: file.file.resource), reference: .standalone(resource: file.file.resource)))
self.imageNode.setSignal(chatAvatarGalleryPhoto(account: account, fileReference: .standalone(media: file.file), representations: convertedRepresentations, autoFetchFullSize: true))
let apply = self.imageNode.asyncLayout()(TransformImageArguments(corners: ImageCorners(), imageSize: dimensions.aspectFilled(size), boundingSize: size, intrinsicInsets: UIEdgeInsets()))
apply()
}
@ -122,7 +122,7 @@ final class SettingsThemeWallpaperNode: ASDisplayNode {
}
let dimensions = file.file.dimensions ?? CGSize(width: 100.0, height: 100.0)
convertedRepresentations.append(ImageRepresentationWithReference(representation: .init(dimensions: dimensions, resource: file.file.resource), reference: .standalone(resource: file.file.resource)))
self.imageNode.setSignal(chatAvatarGalleryPhoto(account: account, representations: convertedRepresentations, autoFetchFullSize: true))
self.imageNode.setSignal(chatAvatarGalleryPhoto(account: account, fileReference: .standalone(media: file.file), representations: convertedRepresentations, autoFetchFullSize: true))
let apply = self.imageNode.asyncLayout()(TransformImageArguments(corners: ImageCorners(), imageSize: dimensions.aspectFilled(size), boundingSize: size, intrinsicInsets: UIEdgeInsets()))
apply()
}