mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-11-07 09:20:08 +00:00
Various UI fixes
This commit is contained in:
parent
81c409e93e
commit
b5b7128583
@ -5242,3 +5242,5 @@ Any member of this group will be able to see messages in the channel.";
|
|||||||
"StickerPackActionInfo.RemovedText" = "%@ is no longer in your stickers.";
|
"StickerPackActionInfo.RemovedText" = "%@ is no longer in your stickers.";
|
||||||
|
|
||||||
"Conversation.ContextMenuCancelEditing" = "Cancel Editing";
|
"Conversation.ContextMenuCancelEditing" = "Cancel Editing";
|
||||||
|
|
||||||
|
"Map.NoPlacesNearby" = "There are no known places nearby.\nTry a different location.";
|
||||||
|
|||||||
@ -304,6 +304,7 @@ class CallListCallItemNode: ItemListRevealOptionsItemNode {
|
|||||||
let titleFont = Font.regular(item.presentationData.fontSize.itemListBaseFontSize)
|
let titleFont = Font.regular(item.presentationData.fontSize.itemListBaseFontSize)
|
||||||
let statusFont = Font.regular(floor(item.presentationData.fontSize.itemListBaseFontSize * 14.0 / 17.0))
|
let statusFont = Font.regular(floor(item.presentationData.fontSize.itemListBaseFontSize * 14.0 / 17.0))
|
||||||
let dateFont = Font.regular(floor(item.presentationData.fontSize.itemListBaseFontSize * 15.0 / 17.0))
|
let dateFont = Font.regular(floor(item.presentationData.fontSize.itemListBaseFontSize * 15.0 / 17.0))
|
||||||
|
let avatarDiameter = min(40.0, floor(item.presentationData.fontSize.itemListBaseFontSize * 40.0 / 17.0))
|
||||||
|
|
||||||
let editingOffset: CGFloat
|
let editingOffset: CGFloat
|
||||||
var editableControlSizeAndApply: (CGFloat, (CGFloat) -> ItemListEditableControlNode)?
|
var editableControlSizeAndApply: (CGFloat, (CGFloat) -> ItemListEditableControlNode)?
|
||||||
@ -315,7 +316,7 @@ class CallListCallItemNode: ItemListRevealOptionsItemNode {
|
|||||||
editingOffset = 0.0
|
editingOffset = 0.0
|
||||||
}
|
}
|
||||||
|
|
||||||
var leftInset: CGFloat = 86.0 + params.leftInset
|
var leftInset: CGFloat = 46.0 + avatarDiameter + params.leftInset
|
||||||
let rightInset: CGFloat = 13.0 + params.rightInset
|
let rightInset: CGFloat = 13.0 + params.rightInset
|
||||||
var infoIconRightInset: CGFloat = rightInset - 1.0
|
var infoIconRightInset: CGFloat = rightInset - 1.0
|
||||||
|
|
||||||
@ -548,7 +549,7 @@ class CallListCallItemNode: ItemListRevealOptionsItemNode {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
transition.updateFrameAdditive(node: strongSelf.avatarNode, frame: CGRect(origin: CGPoint(x: revealOffset + leftInset - 52.0, y: floor((contentSize.height - 40.0) / 2.0)), size: CGSize(width: 40.0, height: 40.0)))
|
transition.updateFrameAdditive(node: strongSelf.avatarNode, frame: CGRect(origin: CGPoint(x: revealOffset + leftInset - 52.0, y: floor((contentSize.height - avatarDiameter) / 2.0)), size: CGSize(width: avatarDiameter, height: avatarDiameter)))
|
||||||
|
|
||||||
let _ = titleApply()
|
let _ = titleApply()
|
||||||
transition.updateFrameAdditive(node: strongSelf.titleNode, frame: CGRect(origin: CGPoint(x: revealOffset + leftInset, y: verticalInset), size: titleLayout.size))
|
transition.updateFrameAdditive(node: strongSelf.titleNode, frame: CGRect(origin: CGPoint(x: revealOffset + leftInset, y: verticalInset), size: titleLayout.size))
|
||||||
|
|||||||
@ -107,6 +107,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController,
|
|||||||
private let hideNetworkActivityStatus: Bool
|
private let hideNetworkActivityStatus: Bool
|
||||||
|
|
||||||
public let groupId: PeerGroupId
|
public let groupId: PeerGroupId
|
||||||
|
public let previewing: Bool
|
||||||
|
|
||||||
let openMessageFromSearchDisposable: MetaDisposable = MetaDisposable()
|
let openMessageFromSearchDisposable: MetaDisposable = MetaDisposable()
|
||||||
|
|
||||||
@ -150,6 +151,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController,
|
|||||||
self.hideNetworkActivityStatus = hideNetworkActivityStatus
|
self.hideNetworkActivityStatus = hideNetworkActivityStatus
|
||||||
|
|
||||||
self.groupId = groupId
|
self.groupId = groupId
|
||||||
|
self.previewing = previewing
|
||||||
|
|
||||||
self.presentationData = (context.sharedContext.currentPresentationData.with { $0 })
|
self.presentationData = (context.sharedContext.currentPresentationData.with { $0 })
|
||||||
self.presentationDataValue.set(.single(self.presentationData))
|
self.presentationDataValue.set(.single(self.presentationData))
|
||||||
@ -369,11 +371,13 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController,
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
self.searchContentNode = NavigationBarSearchContentNode(theme: self.presentationData.theme, placeholder: self.presentationData.strings.DialogList_SearchLabel, activate: { [weak self] in
|
if !previewing {
|
||||||
self?.activateSearch()
|
self.searchContentNode = NavigationBarSearchContentNode(theme: self.presentationData.theme, placeholder: self.presentationData.strings.DialogList_SearchLabel, activate: { [weak self] in
|
||||||
})
|
self?.activateSearch()
|
||||||
self.searchContentNode?.updateExpansionProgress(0.0)
|
})
|
||||||
self.navigationBar?.setContentNode(self.searchContentNode, animated: false)
|
self.searchContentNode?.updateExpansionProgress(0.0)
|
||||||
|
self.navigationBar?.setContentNode(self.searchContentNode, animated: false)
|
||||||
|
}
|
||||||
|
|
||||||
if enableDebugActions {
|
if enableDebugActions {
|
||||||
self.tabBarItemDebugTapAction = {
|
self.tabBarItemDebugTapAction = {
|
||||||
@ -443,7 +447,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController,
|
|||||||
}
|
}
|
||||||
|
|
||||||
override public func loadDisplayNode() {
|
override public func loadDisplayNode() {
|
||||||
self.displayNode = ChatListControllerNode(context: self.context, groupId: self.groupId, controlsHistoryPreload: self.controlsHistoryPreload, presentationData: self.presentationData, controller: self)
|
self.displayNode = ChatListControllerNode(context: self.context, groupId: self.groupId, previewing: self.previewing, controlsHistoryPreload: self.controlsHistoryPreload, presentationData: self.presentationData, controller: self)
|
||||||
|
|
||||||
self.chatListDisplayNode.navigationBar = self.navigationBar
|
self.chatListDisplayNode.navigationBar = self.navigationBar
|
||||||
|
|
||||||
|
|||||||
@ -72,12 +72,12 @@ final class ChatListControllerNode: ASDisplayNode {
|
|||||||
|
|
||||||
let debugListView = ListView()
|
let debugListView = ListView()
|
||||||
|
|
||||||
init(context: AccountContext, groupId: PeerGroupId, controlsHistoryPreload: Bool, presentationData: PresentationData, controller: ChatListControllerImpl) {
|
init(context: AccountContext, groupId: PeerGroupId, previewing: Bool, controlsHistoryPreload: Bool, presentationData: PresentationData, controller: ChatListControllerImpl) {
|
||||||
self.context = context
|
self.context = context
|
||||||
self.groupId = groupId
|
self.groupId = groupId
|
||||||
self.presentationData = presentationData
|
self.presentationData = presentationData
|
||||||
|
|
||||||
self.chatListNode = ChatListNode(context: context, groupId: groupId, controlsHistoryPreload: controlsHistoryPreload, mode: .chatList, theme: presentationData.theme, fontSize: presentationData.fontSize, strings: presentationData.strings, dateTimeFormat: presentationData.dateTimeFormat, nameSortOrder: presentationData.nameSortOrder, nameDisplayOrder: presentationData.nameDisplayOrder, disableAnimations: presentationData.disableAnimations)
|
self.chatListNode = ChatListNode(context: context, groupId: groupId, previewing: previewing, controlsHistoryPreload: controlsHistoryPreload, mode: .chatList, theme: presentationData.theme, fontSize: presentationData.fontSize, strings: presentationData.strings, dateTimeFormat: presentationData.dateTimeFormat, nameSortOrder: presentationData.nameSortOrder, nameDisplayOrder: presentationData.nameDisplayOrder, disableAnimations: presentationData.disableAnimations)
|
||||||
|
|
||||||
self.controller = controller
|
self.controller = controller
|
||||||
|
|
||||||
|
|||||||
@ -1183,6 +1183,17 @@ public final class ChatListSearchContainerNode: SearchDisplayControllerContentNo
|
|||||||
self.dimNode.backgroundColor = self.filter.contains(.excludeRecent) ? UIColor.black.withAlphaComponent(0.5) : theme.chatList.backgroundColor
|
self.dimNode.backgroundColor = self.filter.contains(.excludeRecent) ? UIColor.black.withAlphaComponent(0.5) : theme.chatList.backgroundColor
|
||||||
self.recentListNode.verticalScrollIndicatorColor = theme.list.scrollIndicatorColor
|
self.recentListNode.verticalScrollIndicatorColor = theme.list.scrollIndicatorColor
|
||||||
self.listNode.verticalScrollIndicatorColor = theme.list.scrollIndicatorColor
|
self.listNode.verticalScrollIndicatorColor = theme.list.scrollIndicatorColor
|
||||||
|
|
||||||
|
self.listNode.forEachItemHeaderNode({ itemHeaderNode in
|
||||||
|
if let itemHeaderNode = itemHeaderNode as? ChatListSearchItemHeaderNode {
|
||||||
|
itemHeaderNode.updateTheme(theme: theme)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
self.recentListNode.forEachItemHeaderNode({ itemHeaderNode in
|
||||||
|
if let itemHeaderNode = itemHeaderNode as? ChatListSearchItemHeaderNode {
|
||||||
|
itemHeaderNode.updateTheme(theme: theme)
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
private func updateState(_ f: (ChatListSearchContainerNodeState) -> ChatListSearchContainerNodeState) {
|
private func updateState(_ f: (ChatListSearchContainerNodeState) -> ChatListSearchContainerNodeState) {
|
||||||
|
|||||||
@ -379,7 +379,7 @@ public final class ChatListNode: ListView {
|
|||||||
|
|
||||||
private var hapticFeedback: HapticFeedback?
|
private var hapticFeedback: HapticFeedback?
|
||||||
|
|
||||||
public init(context: AccountContext, groupId: PeerGroupId, controlsHistoryPreload: Bool, mode: ChatListNodeMode, theme: PresentationTheme, fontSize: PresentationFontSize, strings: PresentationStrings, dateTimeFormat: PresentationDateTimeFormat, nameSortOrder: PresentationPersonNameOrder, nameDisplayOrder: PresentationPersonNameOrder, disableAnimations: Bool) {
|
public init(context: AccountContext, groupId: PeerGroupId, previewing: Bool, controlsHistoryPreload: Bool, mode: ChatListNodeMode, theme: PresentationTheme, fontSize: PresentationFontSize, strings: PresentationStrings, dateTimeFormat: PresentationDateTimeFormat, nameSortOrder: PresentationPersonNameOrder, nameDisplayOrder: PresentationPersonNameOrder, disableAnimations: Bool) {
|
||||||
self.context = context
|
self.context = context
|
||||||
self.groupId = groupId
|
self.groupId = groupId
|
||||||
self.controlsHistoryPreload = controlsHistoryPreload
|
self.controlsHistoryPreload = controlsHistoryPreload
|
||||||
@ -708,7 +708,7 @@ public final class ChatListNode: ListView {
|
|||||||
searchMode = true
|
searchMode = true
|
||||||
}
|
}
|
||||||
|
|
||||||
return preparedChatListNodeViewTransition(from: previousView, to: processedView, reason: reason, disableAnimations: disableAnimations, account: context.account, scrollPosition: updatedScrollPosition, searchMode: searchMode)
|
return preparedChatListNodeViewTransition(from: previousView, to: processedView, reason: reason, previewing: previewing, disableAnimations: disableAnimations, account: context.account, scrollPosition: updatedScrollPosition, searchMode: searchMode)
|
||||||
|> map({ mappedChatListNodeViewListTransition(context: context, nodeInteraction: nodeInteraction, peerGroupId: groupId, mode: mode, transition: $0) })
|
|> map({ mappedChatListNodeViewListTransition(context: context, nodeInteraction: nodeInteraction, peerGroupId: groupId, mode: mode, transition: $0) })
|
||||||
|> runOn(prepareOnMainQueue ? Queue.mainQueue() : viewProcessingQueue)
|
|> runOn(prepareOnMainQueue ? Queue.mainQueue() : viewProcessingQueue)
|
||||||
}
|
}
|
||||||
@ -1262,8 +1262,7 @@ public final class ChatListNode: ListView {
|
|||||||
if view.laterIndex == nil {
|
if view.laterIndex == nil {
|
||||||
self.transaction(deleteIndices: [], insertIndicesAndItems: [], updateIndicesAndItems: [], options: [.Synchronous], scrollToItem: ListViewScrollToItem(index: 0, position: .top(0.0), animated: true, curve: .Default(duration: nil), directionHint: .Up), updateSizeAndInsets: nil, stationaryItemRange: nil, updateOpaqueState: nil, completion: { _ in })
|
self.transaction(deleteIndices: [], insertIndicesAndItems: [], updateIndicesAndItems: [], options: [.Synchronous], scrollToItem: ListViewScrollToItem(index: 0, position: .top(0.0), animated: true, curve: .Default(duration: nil), directionHint: .Up), updateSizeAndInsets: nil, stationaryItemRange: nil, updateOpaqueState: nil, completion: { _ in })
|
||||||
} else {
|
} else {
|
||||||
let location: ChatListNodeLocation = .scroll(index: .absoluteUpperBound, sourceIndex: .absoluteLowerBound
|
let location: ChatListNodeLocation = .scroll(index: .absoluteUpperBound, sourceIndex: .absoluteLowerBound, scrollPosition: .top(0.0), animated: true)
|
||||||
, scrollPosition: .top(0.0), animated: true)
|
|
||||||
self.setChatListLocation(location)
|
self.setChatListLocation(location)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@ -48,7 +48,7 @@ enum ChatListNodeViewScrollPosition {
|
|||||||
case index(index: ChatListIndex, position: ListViewScrollPosition, directionHint: ListViewScrollToItemDirectionHint, animated: Bool)
|
case index(index: ChatListIndex, position: ListViewScrollPosition, directionHint: ListViewScrollToItemDirectionHint, animated: Bool)
|
||||||
}
|
}
|
||||||
|
|
||||||
func preparedChatListNodeViewTransition(from fromView: ChatListNodeView?, to toView: ChatListNodeView, reason: ChatListNodeViewTransitionReason, disableAnimations: Bool, account: Account, scrollPosition: ChatListNodeViewScrollPosition?, searchMode: Bool) -> Signal<ChatListNodeViewTransition, NoError> {
|
func preparedChatListNodeViewTransition(from fromView: ChatListNodeView?, to toView: ChatListNodeView, reason: ChatListNodeViewTransitionReason, previewing: Bool, disableAnimations: Bool, account: Account, scrollPosition: ChatListNodeViewScrollPosition?, searchMode: Bool) -> Signal<ChatListNodeViewTransition, NoError> {
|
||||||
return Signal { subscriber in
|
return Signal { subscriber in
|
||||||
let (deleteIndices, indicesAndItems, updateIndices) = mergeListsStableWithUpdates(leftList: fromView?.filteredEntries ?? [], rightList: toView.filteredEntries)
|
let (deleteIndices, indicesAndItems, updateIndices) = mergeListsStableWithUpdates(leftList: fromView?.filteredEntries ?? [], rightList: toView.filteredEntries)
|
||||||
|
|
||||||
@ -174,7 +174,7 @@ func preparedChatListNodeViewTransition(from fromView: ChatListNodeView?, to toV
|
|||||||
fromEmptyView = true
|
fromEmptyView = true
|
||||||
}
|
}
|
||||||
|
|
||||||
if !searchMode && fromEmptyView && scrollToItem == nil && toView.filteredEntries.count >= 1 {
|
if !previewing && !searchMode && fromEmptyView && scrollToItem == nil && toView.filteredEntries.count >= 1 {
|
||||||
scrollToItem = ListViewScrollToItem(index: 0, position: .top(-navigationBarSearchContentHeight), animated: false, curve: .Default(duration: 0.0), directionHint: .Up)
|
scrollToItem = ListViewScrollToItem(index: 0, position: .top(-navigationBarSearchContentHeight), animated: false, curve: .Default(duration: 0.0), directionHint: .Up)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -420,11 +420,11 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode {
|
|||||||
} else {
|
} else {
|
||||||
let throttledSignal = videoNode.status
|
let throttledSignal = videoNode.status
|
||||||
|> mapToThrottled { next -> Signal<MediaPlayerStatus?, NoError> in
|
|> mapToThrottled { next -> Signal<MediaPlayerStatus?, NoError> in
|
||||||
return .single(next) |> then(.complete() |> delay(4.0, queue: Queue.concurrentDefaultQueue()))
|
return .single(next) |> then(.complete() |> delay(2.0, queue: Queue.concurrentDefaultQueue()))
|
||||||
}
|
}
|
||||||
|
|
||||||
self.mediaPlaybackStateDisposable.set(throttledSignal.start(next: { status in
|
self.mediaPlaybackStateDisposable.set(throttledSignal.start(next: { status in
|
||||||
if let status = status, status.duration > 60.0 * 20.0 {
|
if let status = status, status.duration >= 60.0 * 20.0 {
|
||||||
var timestamp: Double?
|
var timestamp: Double?
|
||||||
if status.timestamp > 5.0 && status.timestamp < status.duration - 5.0 {
|
if status.timestamp > 5.0 && status.timestamp < status.duration - 5.0 {
|
||||||
timestamp = status.timestamp
|
timestamp = status.timestamp
|
||||||
|
|||||||
@ -257,6 +257,9 @@
|
|||||||
{
|
{
|
||||||
if (![[[LegacyComponentsGlobals provider] accessChecker] checkCameraAuthorizationStatusForIntent:TGCameraAccessIntentDefault alertDismissCompletion:nil])
|
if (![[[LegacyComponentsGlobals provider] accessChecker] checkCameraAuthorizationStatusForIntent:TGCameraAccessIntentDefault alertDismissCompletion:nil])
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if ([_context currentlyInSplitView])
|
||||||
|
return;
|
||||||
|
|
||||||
if ([TGCameraController useLegacyCamera])
|
if ([TGCameraController useLegacyCamera])
|
||||||
{
|
{
|
||||||
|
|||||||
@ -111,8 +111,12 @@ public func legacyAttachmentMenu(context: AccountContext, peer: Peer, editMediaO
|
|||||||
carouselItemView = carouselItem
|
carouselItemView = carouselItem
|
||||||
carouselItem.suggestionContext = legacySuggestionContext(context: context, peerId: peer.id)
|
carouselItem.suggestionContext = legacySuggestionContext(context: context, peerId: peer.id)
|
||||||
carouselItem.recipientName = peer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder)
|
carouselItem.recipientName = peer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder)
|
||||||
carouselItem.cameraPressed = { [weak controller] cameraView in
|
carouselItem.cameraPressed = { [weak controller, weak parentController] cameraView in
|
||||||
if let controller = controller {
|
if let controller = controller {
|
||||||
|
if let parentController = parentController, parentController.context.currentlyInSplitView() {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
DeviceAccess.authorizeAccess(to: .camera, presentationData: context.sharedContext.currentPresentationData.with { $0 }, present: context.sharedContext.presentGlobalController, openSettings: context.sharedContext.applicationBindings.openSettings, { value in
|
DeviceAccess.authorizeAccess(to: .camera, presentationData: context.sharedContext.currentPresentationData.with { $0 }, present: context.sharedContext.presentGlobalController, openSettings: context.sharedContext.applicationBindings.openSettings, { value in
|
||||||
if value {
|
if value {
|
||||||
openCamera(cameraView, controller)
|
openCamera(cameraView, controller)
|
||||||
|
|||||||
@ -22,6 +22,7 @@ private struct LocationPickerTransaction {
|
|||||||
let insertions: [ListViewInsertItem]
|
let insertions: [ListViewInsertItem]
|
||||||
let updates: [ListViewUpdateItem]
|
let updates: [ListViewUpdateItem]
|
||||||
let isLoading: Bool
|
let isLoading: Bool
|
||||||
|
let isEmpty: Bool
|
||||||
let crossFade: Bool
|
let crossFade: Bool
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -166,14 +167,14 @@ private enum LocationPickerEntry: Comparable, Identifiable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private func preparedTransition(from fromEntries: [LocationPickerEntry], to toEntries: [LocationPickerEntry], isLoading: Bool, crossFade: Bool, account: Account, presentationData: PresentationData, interaction: LocationPickerInteraction?) -> LocationPickerTransaction {
|
private func preparedTransition(from fromEntries: [LocationPickerEntry], to toEntries: [LocationPickerEntry], isLoading: Bool, isEmpty: Bool, crossFade: Bool, account: Account, presentationData: PresentationData, interaction: LocationPickerInteraction?) -> LocationPickerTransaction {
|
||||||
let (deleteIndices, indicesAndItems, updateIndices) = mergeListsStableWithUpdates(leftList: fromEntries, rightList: toEntries)
|
let (deleteIndices, indicesAndItems, updateIndices) = mergeListsStableWithUpdates(leftList: fromEntries, rightList: toEntries)
|
||||||
|
|
||||||
let deletions = deleteIndices.map { ListViewDeleteItem(index: $0, directionHint: nil) }
|
let deletions = deleteIndices.map { ListViewDeleteItem(index: $0, directionHint: nil) }
|
||||||
let insertions = indicesAndItems.map { ListViewInsertItem(index: $0.0, previousIndex: $0.2, item: $0.1.item(account: account, presentationData: presentationData, interaction: interaction), directionHint: nil) }
|
let insertions = indicesAndItems.map { ListViewInsertItem(index: $0.0, previousIndex: $0.2, item: $0.1.item(account: account, presentationData: presentationData, interaction: interaction), directionHint: nil) }
|
||||||
let updates = updateIndices.map { ListViewUpdateItem(index: $0.0, previousIndex: $0.2, item: $0.1.item(account: account, presentationData: presentationData, interaction: interaction), directionHint: nil) }
|
let updates = updateIndices.map { ListViewUpdateItem(index: $0.0, previousIndex: $0.2, item: $0.1.item(account: account, presentationData: presentationData, interaction: interaction), directionHint: nil) }
|
||||||
|
|
||||||
return LocationPickerTransaction(deletions: deletions, insertions: insertions, updates: updates, isLoading: isLoading, crossFade: crossFade)
|
return LocationPickerTransaction(deletions: deletions, insertions: insertions, updates: updates, isLoading: isLoading, isEmpty: isEmpty, crossFade: crossFade)
|
||||||
}
|
}
|
||||||
|
|
||||||
enum LocationPickerLocation: Equatable {
|
enum LocationPickerLocation: Equatable {
|
||||||
@ -246,6 +247,7 @@ final class LocationPickerControllerNode: ViewControllerTracingNode {
|
|||||||
private let interaction: LocationPickerInteraction
|
private let interaction: LocationPickerInteraction
|
||||||
|
|
||||||
private let listNode: ListView
|
private let listNode: ListView
|
||||||
|
private let emptyResultsTextNode: ImmediateTextNode
|
||||||
private let headerNode: LocationMapHeaderNode
|
private let headerNode: LocationMapHeaderNode
|
||||||
private let activityIndicator: ActivityIndicator
|
private let activityIndicator: ActivityIndicator
|
||||||
private let shadeNode: ASDisplayNode
|
private let shadeNode: ASDisplayNode
|
||||||
@ -281,6 +283,11 @@ final class LocationPickerControllerNode: ViewControllerTracingNode {
|
|||||||
self.listNode.verticalScrollIndicatorColor = UIColor(white: 0.0, alpha: 0.3)
|
self.listNode.verticalScrollIndicatorColor = UIColor(white: 0.0, alpha: 0.3)
|
||||||
self.listNode.verticalScrollIndicatorFollowsOverscroll = true
|
self.listNode.verticalScrollIndicatorFollowsOverscroll = true
|
||||||
|
|
||||||
|
self.emptyResultsTextNode = ImmediateTextNode()
|
||||||
|
self.emptyResultsTextNode.maximumNumberOfLines = 0
|
||||||
|
self.emptyResultsTextNode.textAlignment = .center
|
||||||
|
self.emptyResultsTextNode.isHidden = true
|
||||||
|
|
||||||
self.headerNode = LocationMapHeaderNode(presentationData: presentationData, toggleMapModeSelection: interaction.toggleMapModeSelection, goToUserLocation: interaction.goToUserLocation, showPlacesInThisArea: interaction.showPlacesInThisArea)
|
self.headerNode = LocationMapHeaderNode(presentationData: presentationData, toggleMapModeSelection: interaction.toggleMapModeSelection, goToUserLocation: interaction.goToUserLocation, showPlacesInThisArea: interaction.showPlacesInThisArea)
|
||||||
self.headerNode.mapNode.isRotateEnabled = false
|
self.headerNode.mapNode.isRotateEnabled = false
|
||||||
|
|
||||||
@ -302,6 +309,7 @@ final class LocationPickerControllerNode: ViewControllerTracingNode {
|
|||||||
self.addSubnode(self.headerNode)
|
self.addSubnode(self.headerNode)
|
||||||
self.addSubnode(self.optionsNode)
|
self.addSubnode(self.optionsNode)
|
||||||
self.listNode.addSubnode(self.activityIndicator)
|
self.listNode.addSubnode(self.activityIndicator)
|
||||||
|
self.listNode.addSubnode(self.emptyResultsTextNode)
|
||||||
self.shadeNode.addSubnode(self.innerShadeNode)
|
self.shadeNode.addSubnode(self.innerShadeNode)
|
||||||
self.addSubnode(self.shadeNode)
|
self.addSubnode(self.shadeNode)
|
||||||
|
|
||||||
@ -506,7 +514,7 @@ final class LocationPickerControllerNode: ViewControllerTracingNode {
|
|||||||
crossFade = true
|
crossFade = true
|
||||||
}
|
}
|
||||||
|
|
||||||
let transition = preparedTransition(from: previousEntries ?? [], to: entries, isLoading: displayedVenues == nil, crossFade: crossFade, account: context.account, presentationData: presentationData, interaction: strongSelf.interaction)
|
let transition = preparedTransition(from: previousEntries ?? [], to: entries, isLoading: displayedVenues == nil, isEmpty: displayedVenues?.isEmpty ?? false, crossFade: crossFade, account: context.account, presentationData: presentationData, interaction: strongSelf.interaction)
|
||||||
strongSelf.enqueueTransition(transition)
|
strongSelf.enqueueTransition(transition)
|
||||||
|
|
||||||
var displayingPlacesButton = false
|
var displayingPlacesButton = false
|
||||||
@ -725,6 +733,11 @@ final class LocationPickerControllerNode: ViewControllerTracingNode {
|
|||||||
self.listNode.transaction(deleteIndices: transition.deletions, insertIndicesAndItems: transition.insertions, updateIndicesAndItems: transition.updates, options: options, updateSizeAndInsets: nil, updateOpaqueState: nil, completion: { [weak self] _ in
|
self.listNode.transaction(deleteIndices: transition.deletions, insertIndicesAndItems: transition.insertions, updateIndicesAndItems: transition.updates, options: options, updateSizeAndInsets: nil, updateOpaqueState: nil, completion: { [weak self] _ in
|
||||||
if let strongSelf = self {
|
if let strongSelf = self {
|
||||||
strongSelf.activityIndicator.isHidden = !transition.isLoading
|
strongSelf.activityIndicator.isHidden = !transition.isLoading
|
||||||
|
strongSelf.emptyResultsTextNode.isHidden = transition.isLoading || !transition.isEmpty
|
||||||
|
|
||||||
|
strongSelf.emptyResultsTextNode.attributedText = NSAttributedString(string: strongSelf.presentationData.strings.Map_NoPlacesNearby, font: Font.regular(15.0), textColor: strongSelf.presentationData.theme.list.freeTextColor)
|
||||||
|
|
||||||
|
strongSelf.layoutActivityIndicator(transition: .immediate)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -779,6 +792,10 @@ final class LocationPickerControllerNode: ViewControllerTracingNode {
|
|||||||
let indicatorSize = self.activityIndicator.measure(CGSize(width: 100.0, height: 100.0))
|
let indicatorSize = self.activityIndicator.measure(CGSize(width: 100.0, height: 100.0))
|
||||||
let actionsInset: CGFloat = 148.0
|
let actionsInset: CGFloat = 148.0
|
||||||
transition.updateFrame(node: self.activityIndicator, frame: CGRect(origin: CGPoint(x: floor((layout.size.width - indicatorSize.width) / 2.0), y: headerHeight + actionsInset + floor((layout.size.height - headerHeight - actionsInset - indicatorSize.height - layout.intrinsicInsets.bottom) / 2.0)), size: indicatorSize))
|
transition.updateFrame(node: self.activityIndicator, frame: CGRect(origin: CGPoint(x: floor((layout.size.width - indicatorSize.width) / 2.0), y: headerHeight + actionsInset + floor((layout.size.height - headerHeight - actionsInset - indicatorSize.height - layout.intrinsicInsets.bottom) / 2.0)), size: indicatorSize))
|
||||||
|
|
||||||
|
let padding: CGFloat = 16.0
|
||||||
|
let emptyTextSize = self.emptyResultsTextNode.updateLayout(CGSize(width: layout.size.width - layout.safeInsets.left - layout.safeInsets.right - padding * 2.0, height: CGFloat.greatestFiniteMagnitude))
|
||||||
|
transition.updateFrame(node: self.emptyResultsTextNode, frame: CGRect(origin: CGPoint(x: floor((layout.size.width - emptyTextSize.width) / 2.0), y: headerHeight + actionsInset + floor((layout.size.height - headerHeight - actionsInset - emptyTextSize.height - layout.intrinsicInsets.bottom) / 2.0)), size: emptyTextSize))
|
||||||
}
|
}
|
||||||
|
|
||||||
func containerLayoutUpdated(_ layout: ContainerViewLayout, navigationHeight: CGFloat, transition: ContainedViewLayoutTransition) {
|
func containerLayoutUpdated(_ layout: ContainerViewLayout, navigationHeight: CGFloat, transition: ContainedViewLayoutTransition) {
|
||||||
|
|||||||
@ -68,6 +68,9 @@ private final class MediaPlayerTimeTextNodeParameters: NSObject {
|
|||||||
public final class MediaPlayerTimeTextNode: ASDisplayNode {
|
public final class MediaPlayerTimeTextNode: ASDisplayNode {
|
||||||
public var alignment: NSTextAlignment = .left
|
public var alignment: NSTextAlignment = .left
|
||||||
public var mode: MediaPlayerTimeTextNodeMode = .normal
|
public var mode: MediaPlayerTimeTextNodeMode = .normal
|
||||||
|
|
||||||
|
public var keepPreviousValueOnEmptyState = false
|
||||||
|
|
||||||
public var textColor: UIColor {
|
public var textColor: UIColor {
|
||||||
didSet {
|
didSet {
|
||||||
self.updateTimestamp()
|
self.updateTimestamp()
|
||||||
@ -151,6 +154,10 @@ public final class MediaPlayerTimeTextNode: ASDisplayNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func updateTimestamp() {
|
func updateTimestamp() {
|
||||||
|
if ((self.statusValue?.duration ?? 0.0) < 0.1) && self.state.seconds != nil && self.keepPreviousValueOnEmptyState {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
if let statusValue = self.statusValue, Double(0.0).isLess(than: statusValue.duration) {
|
if let statusValue = self.statusValue, Double(0.0).isLess(than: statusValue.duration) {
|
||||||
let timestampSeconds: Double
|
let timestampSeconds: Double
|
||||||
if !statusValue.generationTimestamp.isZero {
|
if !statusValue.generationTimestamp.isZero {
|
||||||
|
|||||||
@ -353,7 +353,7 @@ private func stringForSelectiveSettings(strings: PresentationStrings, settings:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private func privacyAndSecurityControllerEntries(presentationData: PresentationData, state: PrivacyAndSecurityControllerState, privacySettings: AccountPrivacySettings?, accessChallengeData: PostboxAccessChallengeData, blockedPeerCount: Int?, activeWebsitesCount: Int, twoStepAuthData: TwoStepVerificationAccessConfiguration?) -> [PrivacyAndSecurityEntry] {
|
private func privacyAndSecurityControllerEntries(presentationData: PresentationData, state: PrivacyAndSecurityControllerState, privacySettings: AccountPrivacySettings?, accessChallengeData: PostboxAccessChallengeData, blockedPeerCount: Int?, activeWebsitesCount: Int, hasTwoStepAuth: Bool?, twoStepAuthData: TwoStepVerificationAccessConfiguration?) -> [PrivacyAndSecurityEntry] {
|
||||||
var entries: [PrivacyAndSecurityEntry] = []
|
var entries: [PrivacyAndSecurityEntry] = []
|
||||||
|
|
||||||
entries.append(.blockedPeers(presentationData.theme, presentationData.strings.Settings_BlockedUsers, blockedPeerCount == nil ? "" : (blockedPeerCount == 0 ? presentationData.strings.PrivacySettings_BlockedPeersEmpty : "\(blockedPeerCount!)")))
|
entries.append(.blockedPeers(presentationData.theme, presentationData.strings.Settings_BlockedUsers, blockedPeerCount == nil ? "" : (blockedPeerCount == 0 ? presentationData.strings.PrivacySettings_BlockedPeersEmpty : "\(blockedPeerCount!)")))
|
||||||
@ -380,13 +380,8 @@ private func privacyAndSecurityControllerEntries(presentationData: PresentationD
|
|||||||
entries.append(.passcode(presentationData.theme, presentationData.strings.PrivacySettings_Passcode, false, passcodeValue))
|
entries.append(.passcode(presentationData.theme, presentationData.strings.PrivacySettings_Passcode, false, passcodeValue))
|
||||||
}
|
}
|
||||||
var twoStepAuthString = ""
|
var twoStepAuthString = ""
|
||||||
if let twoStepAuthData = twoStepAuthData {
|
if let hasTwoStepAuth = hasTwoStepAuth {
|
||||||
switch twoStepAuthData {
|
twoStepAuthString = hasTwoStepAuth ? presentationData.strings.PrivacySettings_PasscodeOn : presentationData.strings.PrivacySettings_PasscodeOff
|
||||||
case .set:
|
|
||||||
twoStepAuthString = presentationData.strings.PrivacySettings_PasscodeOn
|
|
||||||
case .notSet:
|
|
||||||
twoStepAuthString = presentationData.strings.PrivacySettings_PasscodeOff
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
entries.append(.twoStepVerification(presentationData.theme, presentationData.strings.PrivacySettings_TwoStepAuth, twoStepAuthString, twoStepAuthData))
|
entries.append(.twoStepVerification(presentationData.theme, presentationData.strings.PrivacySettings_TwoStepAuth, twoStepAuthString, twoStepAuthData))
|
||||||
|
|
||||||
@ -429,7 +424,7 @@ private func privacyAndSecurityControllerEntries(presentationData: PresentationD
|
|||||||
return entries
|
return entries
|
||||||
}
|
}
|
||||||
|
|
||||||
public func privacyAndSecurityController(context: AccountContext, initialSettings: AccountPrivacySettings? = nil, updatedSettings: ((AccountPrivacySettings?) -> Void)? = nil, focusOnItemTag: PrivacyAndSecurityEntryTag? = nil, activeSessionsContext: ActiveSessionsContext? = nil, webSessionsContext: WebSessionsContext? = nil, blockedPeersContext: BlockedPeersContext? = nil) -> ViewController {
|
public func privacyAndSecurityController(context: AccountContext, initialSettings: AccountPrivacySettings? = nil, updatedSettings: ((AccountPrivacySettings?) -> Void)? = nil, updatedBlockedPeers: ((BlockedPeersContext?) -> Void)? = nil, updatedHasTwoStepAuth: ((Bool) -> Void)? = nil, focusOnItemTag: PrivacyAndSecurityEntryTag? = nil, activeSessionsContext: ActiveSessionsContext? = nil, webSessionsContext: WebSessionsContext? = nil, blockedPeersContext: BlockedPeersContext? = nil, hasTwoStepAuth: Bool? = nil) -> ViewController {
|
||||||
let statePromise = ValuePromise(PrivacyAndSecurityControllerState(), ignoreRepeated: true)
|
let statePromise = ValuePromise(PrivacyAndSecurityControllerState(), ignoreRepeated: true)
|
||||||
let stateValue = Atomic(value: PrivacyAndSecurityControllerState())
|
let stateValue = Atomic(value: PrivacyAndSecurityControllerState())
|
||||||
let updateState: ((PrivacyAndSecurityControllerState) -> PrivacyAndSecurityControllerState) -> Void = { f in
|
let updateState: ((PrivacyAndSecurityControllerState) -> PrivacyAndSecurityControllerState) -> Void = { f in
|
||||||
@ -450,17 +445,40 @@ public func privacyAndSecurityController(context: AccountContext, initialSetting
|
|||||||
|
|
||||||
let privacySettingsPromise = Promise<AccountPrivacySettings?>()
|
let privacySettingsPromise = Promise<AccountPrivacySettings?>()
|
||||||
privacySettingsPromise.set(.single(initialSettings) |> then(requestAccountPrivacySettings(account: context.account) |> map(Optional.init)))
|
privacySettingsPromise.set(.single(initialSettings) |> then(requestAccountPrivacySettings(account: context.account) |> map(Optional.init)))
|
||||||
|
|
||||||
let blockedPeersContext = blockedPeersContext ?? BlockedPeersContext(account: context.account)
|
let blockedPeersContext = blockedPeersContext ?? BlockedPeersContext(account: context.account)
|
||||||
let activeSessionsContext = activeSessionsContext ?? ActiveSessionsContext(account: context.account)
|
let activeSessionsContext = activeSessionsContext ?? ActiveSessionsContext(account: context.account)
|
||||||
let webSessionsContext = webSessionsContext ?? WebSessionsContext(account: context.account)
|
let webSessionsContext = webSessionsContext ?? WebSessionsContext(account: context.account)
|
||||||
|
|
||||||
|
let blockedPeersState = Promise<BlockedPeersContextState>()
|
||||||
|
blockedPeersState.set(blockedPeersContext.state)
|
||||||
|
|
||||||
webSessionsContext.loadMore()
|
webSessionsContext.loadMore()
|
||||||
|
|
||||||
let updateTwoStepAuthDisposable = MetaDisposable()
|
let updateTwoStepAuthDisposable = MetaDisposable()
|
||||||
actionsDisposable.add(updateTwoStepAuthDisposable)
|
actionsDisposable.add(updateTwoStepAuthDisposable)
|
||||||
|
|
||||||
let twoStepAuthDataValue = Promise<TwoStepVerificationAccessConfiguration?>(nil)
|
let twoStepAuthDataValue = Promise<TwoStepVerificationAccessConfiguration?>(nil)
|
||||||
|
let hasTwoStepAuthDataValue = twoStepAuthDataValue.get()
|
||||||
|
|> map { data -> Bool? in
|
||||||
|
if let data = data {
|
||||||
|
if case .set = data {
|
||||||
|
return true
|
||||||
|
} else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let twoStepAuth = Promise<Bool?>()
|
||||||
|
if let hasTwoStepAuth = hasTwoStepAuth {
|
||||||
|
twoStepAuth.set(.single(hasTwoStepAuth) |> then(hasTwoStepAuthDataValue))
|
||||||
|
} else {
|
||||||
|
twoStepAuth.set(hasTwoStepAuthDataValue)
|
||||||
|
}
|
||||||
|
|
||||||
let updateHasTwoStepAuth: () -> Void = {
|
let updateHasTwoStepAuth: () -> Void = {
|
||||||
let signal = twoStepVerificationConfiguration(account: context.account)
|
let signal = twoStepVerificationConfiguration(account: context.account)
|
||||||
|> map { value -> TwoStepVerificationAccessConfiguration? in
|
|> map { value -> TwoStepVerificationAccessConfiguration? in
|
||||||
@ -744,8 +762,13 @@ public func privacyAndSecurityController(context: AccountContext, initialSetting
|
|||||||
updatedSettings?(settings)
|
updatedSettings?(settings)
|
||||||
}))
|
}))
|
||||||
|
|
||||||
let signal = combineLatest(queue: .mainQueue(), context.sharedContext.presentationData, statePromise.get(), privacySettingsPromise.get(), context.sharedContext.accountManager.noticeEntry(key: ApplicationSpecificNotice.secretChatLinkPreviewsKey()), context.sharedContext.accountManager.sharedData(keys: [ApplicationSpecificSharedDataKeys.contactSynchronizationSettings]), recentPeers(account: context.account), blockedPeersContext.state, webSessionsContext.state, context.sharedContext.accountManager.accessChallengeData(), twoStepAuthDataValue.get())
|
actionsDisposable.add((blockedPeersState.get()
|
||||||
|> map { presentationData, state, privacySettings, noticeView, sharedData, recentPeers, blockedPeersState, activeWebsitesState, accessChallengeData, twoStepAuthData -> (ItemListControllerState, (ItemListNodeState, Any)) in
|
|> deliverOnMainQueue).start(next: { _ in
|
||||||
|
updatedBlockedPeers?(blockedPeersContext)
|
||||||
|
}))
|
||||||
|
|
||||||
|
let signal = combineLatest(queue: .mainQueue(), context.sharedContext.presentationData, statePromise.get(), privacySettingsPromise.get(), context.sharedContext.accountManager.noticeEntry(key: ApplicationSpecificNotice.secretChatLinkPreviewsKey()), context.sharedContext.accountManager.sharedData(keys: [ApplicationSpecificSharedDataKeys.contactSynchronizationSettings]), recentPeers(account: context.account), blockedPeersState.get(), webSessionsContext.state, context.sharedContext.accountManager.accessChallengeData(), combineLatest(twoStepAuth.get(), twoStepAuthDataValue.get()))
|
||||||
|
|> map { presentationData, state, privacySettings, noticeView, sharedData, recentPeers, blockedPeersState, activeWebsitesState, accessChallengeData, twoStepAuth -> (ItemListControllerState, (ItemListNodeState, Any)) in
|
||||||
var rightNavigationButton: ItemListNavigationButton?
|
var rightNavigationButton: ItemListNavigationButton?
|
||||||
if privacySettings == nil || state.updatingAccountTimeoutValue != nil {
|
if privacySettings == nil || state.updatingAccountTimeoutValue != nil {
|
||||||
rightNavigationButton = ItemListNavigationButton(content: .none, style: .activity, enabled: true, action: {})
|
rightNavigationButton = ItemListNavigationButton(content: .none, style: .activity, enabled: true, action: {})
|
||||||
@ -753,7 +776,7 @@ public func privacyAndSecurityController(context: AccountContext, initialSetting
|
|||||||
|
|
||||||
let controllerState = ItemListControllerState(presentationData: ItemListPresentationData(presentationData), title: .text(presentationData.strings.PrivacySettings_Title), leftNavigationButton: nil, rightNavigationButton: rightNavigationButton, backNavigationButton: ItemListBackButton(title: presentationData.strings.Common_Back), animateChanges: false)
|
let controllerState = ItemListControllerState(presentationData: ItemListPresentationData(presentationData), title: .text(presentationData.strings.PrivacySettings_Title), leftNavigationButton: nil, rightNavigationButton: rightNavigationButton, backNavigationButton: ItemListBackButton(title: presentationData.strings.Common_Back), animateChanges: false)
|
||||||
|
|
||||||
let listState = ItemListNodeState(presentationData: ItemListPresentationData(presentationData), entries: privacyAndSecurityControllerEntries(presentationData: presentationData, state: state, privacySettings: privacySettings, accessChallengeData: accessChallengeData.data, blockedPeerCount: blockedPeersState.totalCount, activeWebsitesCount: activeWebsitesState.sessions.count, twoStepAuthData: twoStepAuthData), style: .blocks, ensureVisibleItemTag: focusOnItemTag, animateChanges: false)
|
let listState = ItemListNodeState(presentationData: ItemListPresentationData(presentationData), entries: privacyAndSecurityControllerEntries(presentationData: presentationData, state: state, privacySettings: privacySettings, accessChallengeData: accessChallengeData.data, blockedPeerCount: blockedPeersState.totalCount, activeWebsitesCount: activeWebsitesState.sessions.count, hasTwoStepAuth: twoStepAuth.0, twoStepAuthData: twoStepAuth.1), style: .blocks, ensureVisibleItemTag: focusOnItemTag, animateChanges: false)
|
||||||
|
|
||||||
return (controllerState, (listState, arguments))
|
return (controllerState, (listState, arguments))
|
||||||
}
|
}
|
||||||
|
|||||||
@ -875,6 +875,9 @@ public func settingsController(context: AccountContext, accountManager: AccountM
|
|||||||
let activeSessionsContextAndCount = Promise<(ActiveSessionsContext, Int, WebSessionsContext)>()
|
let activeSessionsContextAndCount = Promise<(ActiveSessionsContext, Int, WebSessionsContext)>()
|
||||||
activeSessionsContextAndCount.set(activeSessionsContextAndCountSignal)
|
activeSessionsContextAndCount.set(activeSessionsContextAndCountSignal)
|
||||||
|
|
||||||
|
let blockedPeers = Promise<BlockedPeersContext?>(nil)
|
||||||
|
let hasTwoStepAuthPromise = Promise<Bool?>(nil)
|
||||||
|
|
||||||
let arguments = SettingsItemArguments(sharedContext: context.sharedContext, avatarAndNameInfoContext: avatarAndNameInfoContext, avatarTapAction: {
|
let arguments = SettingsItemArguments(sharedContext: context.sharedContext, avatarAndNameInfoContext: avatarAndNameInfoContext, avatarTapAction: {
|
||||||
var updating = false
|
var updating = false
|
||||||
updateState {
|
updateState {
|
||||||
@ -932,12 +935,17 @@ public func settingsController(context: AccountContext, accountManager: AccountM
|
|||||||
let _ = (contextValue.get()
|
let _ = (contextValue.get()
|
||||||
|> deliverOnMainQueue
|
|> deliverOnMainQueue
|
||||||
|> take(1)).start(next: { context in
|
|> take(1)).start(next: { context in
|
||||||
let _ = (activeSessionsContextAndCount.get()
|
let _ = (combineLatest(activeSessionsContextAndCount.get(), blockedPeers.get(), hasTwoStepAuthPromise.get())
|
||||||
|> deliverOnMainQueue
|
|> deliverOnMainQueue
|
||||||
|> take(1)).start(next: { activeSessionsContext, _, webSessionsContext in
|
|> take(1)).start(next: { sessions, blockedPeersContext, hasTwoStepAuth in
|
||||||
|
let (activeSessionsContext, _, webSessionsContext) = sessions
|
||||||
pushControllerImpl?(privacyAndSecurityController(context: context, initialSettings: privacySettingsValue, updatedSettings: { settings in
|
pushControllerImpl?(privacyAndSecurityController(context: context, initialSettings: privacySettingsValue, updatedSettings: { settings in
|
||||||
privacySettings.set(.single(settings))
|
privacySettings.set(.single(settings))
|
||||||
}, activeSessionsContext: activeSessionsContext, webSessionsContext: webSessionsContext))
|
}, updatedBlockedPeers: { blockedPeersContext in
|
||||||
|
blockedPeers.set(.single(blockedPeersContext))
|
||||||
|
}, updatedHasTwoStepAuth: { hasTwoStepAuthValue in
|
||||||
|
hasTwoStepAuthPromise.set(.single(hasTwoStepAuthValue))
|
||||||
|
}, activeSessionsContext: activeSessionsContext, webSessionsContext: webSessionsContext, blockedPeersContext: blockedPeersContext))
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}, openDataAndStorage: {
|
}, openDataAndStorage: {
|
||||||
|
|||||||
@ -260,10 +260,6 @@ final class ThemeAccentColorController: ViewController {
|
|||||||
if case let .result(resultTheme) = next {
|
if case let .result(resultTheme) = next {
|
||||||
let _ = applyTheme(accountManager: context.sharedContext.accountManager, account: context.account, theme: resultTheme).start()
|
let _ = applyTheme(accountManager: context.sharedContext.accountManager, account: context.account, theme: resultTheme).start()
|
||||||
return updatePresentationThemeSettingsInteractively(accountManager: context.sharedContext.accountManager, { current in
|
return updatePresentationThemeSettingsInteractively(accountManager: context.sharedContext.accountManager, { current in
|
||||||
// if let resource = resultTheme.file?.resource, let data = themeData {
|
|
||||||
// context.sharedContext.accountManager.mediaBox.storeResourceData(resource.id, data: data, synchronous: true)
|
|
||||||
// }
|
|
||||||
|
|
||||||
let themeReference: PresentationThemeReference = .cloud(PresentationCloudTheme(theme: resultTheme, resolvedWallpaper: wallpaper))
|
let themeReference: PresentationThemeReference = .cloud(PresentationCloudTheme(theme: resultTheme, resolvedWallpaper: wallpaper))
|
||||||
|
|
||||||
var updatedTheme = current.theme
|
var updatedTheme = current.theme
|
||||||
@ -293,10 +289,6 @@ final class ThemeAccentColorController: ViewController {
|
|||||||
if case let .result(resultTheme) = next {
|
if case let .result(resultTheme) = next {
|
||||||
let _ = applyTheme(accountManager: context.sharedContext.accountManager, account: context.account, theme: resultTheme).start()
|
let _ = applyTheme(accountManager: context.sharedContext.accountManager, account: context.account, theme: resultTheme).start()
|
||||||
return updatePresentationThemeSettingsInteractively(accountManager: context.sharedContext.accountManager, { current in
|
return updatePresentationThemeSettingsInteractively(accountManager: context.sharedContext.accountManager, { current in
|
||||||
// if let resource = resultTheme.file?.resource, let data = themeData {
|
|
||||||
// context.sharedContext.accountManager.mediaBox.storeResourceData(resource.id, data: data, synchronous: true)
|
|
||||||
// }
|
|
||||||
|
|
||||||
let themeReference: PresentationThemeReference = .cloud(PresentationCloudTheme(theme: resultTheme, resolvedWallpaper: wallpaper))
|
let themeReference: PresentationThemeReference = .cloud(PresentationCloudTheme(theme: resultTheme, resolvedWallpaper: wallpaper))
|
||||||
|
|
||||||
var updatedTheme = current.theme
|
var updatedTheme = current.theme
|
||||||
|
|||||||
@ -12,7 +12,7 @@ var dayClassicColorPresets: [PresentationThemeAccentColor] = [
|
|||||||
PresentationThemeAccentColor(index: 102, baseColor: .preset, accentColor: 0xffff5fa9, bubbleColors: (0xfffff4d7, nil), wallpaper: patternWallpaper(slug: "51nnTjx8mFIBAAAAaFGJsMIvWkk", topColor: 0xfff6b594, bottomColor: 0xffebf6cd, intensity: 46, rotation: 45)),
|
PresentationThemeAccentColor(index: 102, baseColor: .preset, accentColor: 0xffff5fa9, bubbleColors: (0xfffff4d7, nil), wallpaper: patternWallpaper(slug: "51nnTjx8mFIBAAAAaFGJsMIvWkk", topColor: 0xfff6b594, bottomColor: 0xffebf6cd, intensity: 46, rotation: 45)),
|
||||||
PresentationThemeAccentColor(index: 104, baseColor: .preset, accentColor: 0xff5a9e29, bubbleColors: (0xfffff8df, 0xffdcf8c6), wallpaper: patternWallpaper(slug: "R3j69wKskFIBAAAAoUdXWCKMzCM", topColor: 0xffede6dd, bottomColor: 0xffffd59e, intensity: 50, rotation: nil)),
|
PresentationThemeAccentColor(index: 104, baseColor: .preset, accentColor: 0xff5a9e29, bubbleColors: (0xfffff8df, 0xffdcf8c6), wallpaper: patternWallpaper(slug: "R3j69wKskFIBAAAAoUdXWCKMzCM", topColor: 0xffede6dd, bottomColor: 0xffffd59e, intensity: 50, rotation: nil)),
|
||||||
PresentationThemeAccentColor(index: 101, baseColor: .preset, accentColor: 0xff7e5fe5, bubbleColors: (0xfff5e2ff, nil), wallpaper: patternWallpaper(slug: "nQcFYJe1mFIBAAAAcI95wtIK0fk", topColor: 0xfffcccf4, bottomColor: 0xffae85f0, intensity: 54, rotation: nil)),
|
PresentationThemeAccentColor(index: 101, baseColor: .preset, accentColor: 0xff7e5fe5, bubbleColors: (0xfff5e2ff, nil), wallpaper: patternWallpaper(slug: "nQcFYJe1mFIBAAAAcI95wtIK0fk", topColor: 0xfffcccf4, bottomColor: 0xffae85f0, intensity: 54, rotation: nil)),
|
||||||
PresentationThemeAccentColor(index: 107, baseColor: .preset, accentColor: 0xff2cb9ed, bubbleColors: (0xffadf7b5, 0xfffcff8b), wallpaper: patternWallpaper(slug: "nQcFYJe1mFIBAAAAcI95wtIK0fk", topColor: 0xff1a2d1a, bottomColor: 0xff5f6f54, intensity: 50, rotation: 225)),
|
PresentationThemeAccentColor(index: 107, baseColor: .preset, accentColor: 0xff2cb9ed, bubbleColors: (0xffadf7b5, 0xfffcff8b), wallpaper: patternWallpaper(slug: "CJNyxPMgSVAEAAAAvW9sMwc51cw", topColor: 0xff1a2d1a, bottomColor: 0xff5f6f54, intensity: 50, rotation: 225)),
|
||||||
PresentationThemeAccentColor(index: 103, baseColor: .preset, accentColor: 0xff199972, bubbleColors: (0xfffffec7, nil), wallpaper: patternWallpaper(slug: "fqv01SQemVIBAAAApND8LDRUhRU", topColor: 0xffc1e7cb, bottomColor: nil, intensity: 50, rotation: nil)),
|
PresentationThemeAccentColor(index: 103, baseColor: .preset, accentColor: 0xff199972, bubbleColors: (0xfffffec7, nil), wallpaper: patternWallpaper(slug: "fqv01SQemVIBAAAApND8LDRUhRU", topColor: 0xffc1e7cb, bottomColor: nil, intensity: 50, rotation: nil)),
|
||||||
PresentationThemeAccentColor(index: 105, baseColor: .preset, accentColor: 0x0ff09eee, bubbleColors: (0xff94fff9, 0xffccffc7), wallpaper: patternWallpaper(slug: "p-pXcflrmFIBAAAAvXYQk-mCwZU", topColor: 0xffffbca6, bottomColor: 0xffff63bd, intensity: 57, rotation: 225))
|
PresentationThemeAccentColor(index: 105, baseColor: .preset, accentColor: 0x0ff09eee, bubbleColors: (0xff94fff9, 0xffccffc7), wallpaper: patternWallpaper(slug: "p-pXcflrmFIBAAAAvXYQk-mCwZU", topColor: 0xffffbca6, bottomColor: 0xffff63bd, intensity: 57, rotation: 225))
|
||||||
]
|
]
|
||||||
|
|||||||
@ -19,15 +19,15 @@ private enum ThemeSettingsColorEntryId: Hashable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private enum ThemeSettingsColorEntry: Comparable, Identifiable {
|
private enum ThemeSettingsColorEntry: Comparable, Identifiable {
|
||||||
case color(Int, PresentationThemeReference, PresentationThemeAccentColor?, Bool)
|
case color(Int, PresentationTheme, PresentationThemeReference, PresentationThemeAccentColor?, Bool)
|
||||||
case theme(Int, PresentationThemeReference, PresentationThemeReference, Bool)
|
case theme(Int, PresentationTheme, PresentationThemeReference, PresentationThemeReference, Bool)
|
||||||
case picker
|
case picker
|
||||||
|
|
||||||
var stableId: ThemeSettingsColorEntryId {
|
var stableId: ThemeSettingsColorEntryId {
|
||||||
switch self {
|
switch self {
|
||||||
case let .color(index, themeReference, accentColor, _):
|
case let .color(index, _, themeReference, accentColor, _):
|
||||||
return .color(themeReference.index &+ Int64(accentColor?.index ?? 0))
|
return .color(themeReference.index &+ Int64(accentColor?.index ?? 0))
|
||||||
case let .theme(_, _, theme, _):
|
case let .theme(_, _, _, theme, _):
|
||||||
return .theme(theme.index)
|
return .theme(theme.index)
|
||||||
case .picker:
|
case .picker:
|
||||||
return .picker
|
return .picker
|
||||||
@ -36,14 +36,14 @@ private enum ThemeSettingsColorEntry: Comparable, Identifiable {
|
|||||||
|
|
||||||
static func ==(lhs: ThemeSettingsColorEntry, rhs: ThemeSettingsColorEntry) -> Bool {
|
static func ==(lhs: ThemeSettingsColorEntry, rhs: ThemeSettingsColorEntry) -> Bool {
|
||||||
switch lhs {
|
switch lhs {
|
||||||
case let .color(lhsIndex, lhsThemeReference, lhsAccentColor, lhsSelected):
|
case let .color(lhsIndex, lhsCurrentTheme, lhsThemeReference, lhsAccentColor, lhsSelected):
|
||||||
if case let .color(rhsIndex, rhsThemeReference, rhsAccentColor, rhsSelected) = rhs, lhsIndex == rhsIndex, lhsThemeReference.index == rhsThemeReference.index, lhsAccentColor == rhsAccentColor, lhsSelected == rhsSelected {
|
if case let .color(rhsIndex, rhsCurrentTheme, rhsThemeReference, rhsAccentColor, rhsSelected) = rhs, lhsIndex == rhsIndex, lhsCurrentTheme === rhsCurrentTheme, lhsThemeReference.index == rhsThemeReference.index, lhsAccentColor == rhsAccentColor, lhsSelected == rhsSelected {
|
||||||
return true
|
return true
|
||||||
} else {
|
} else {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
case let .theme(lhsIndex, lhsBaseThemeReference, lhsTheme, lhsSelected):
|
case let .theme(lhsIndex, lhsCurrentTheme, lhsBaseThemeReference, lhsTheme, lhsSelected):
|
||||||
if case let .theme(rhsIndex, rhsBaseThemeReference, rhsTheme, rhsSelected) = rhs, lhsIndex == rhsIndex, lhsBaseThemeReference.index == rhsBaseThemeReference.index, lhsTheme == rhsTheme, lhsSelected == rhsSelected {
|
if case let .theme(rhsIndex, rhsCurrentTheme, rhsBaseThemeReference, rhsTheme, rhsSelected) = rhs, lhsIndex == rhsIndex, lhsCurrentTheme === rhsCurrentTheme, lhsBaseThemeReference.index == rhsBaseThemeReference.index, lhsTheme == rhsTheme, lhsSelected == rhsSelected {
|
||||||
return true
|
return true
|
||||||
} else {
|
} else {
|
||||||
return false
|
return false
|
||||||
@ -61,11 +61,11 @@ private enum ThemeSettingsColorEntry: Comparable, Identifiable {
|
|||||||
switch lhs {
|
switch lhs {
|
||||||
case .picker:
|
case .picker:
|
||||||
return true
|
return true
|
||||||
case let .color(lhsIndex, _, _, _), let .theme(lhsIndex, _, _, _):
|
case let .color(lhsIndex, _, _, _, _), let .theme(lhsIndex, _, _, _, _):
|
||||||
switch rhs {
|
switch rhs {
|
||||||
case let .color(rhsIndex, _, _, _):
|
case let .color(rhsIndex, _, _, _, _):
|
||||||
return lhsIndex < rhsIndex
|
return lhsIndex < rhsIndex
|
||||||
case let .theme(rhsIndex, _, _, _):
|
case let .theme(rhsIndex, _, _, _, _):
|
||||||
return lhsIndex < rhsIndex
|
return lhsIndex < rhsIndex
|
||||||
case .picker:
|
case .picker:
|
||||||
return false
|
return false
|
||||||
@ -75,10 +75,10 @@ private enum ThemeSettingsColorEntry: Comparable, Identifiable {
|
|||||||
|
|
||||||
func item(action: @escaping (ThemeSettingsColorOption?, Bool) -> Void, contextAction: ((ThemeSettingsColorOption?, Bool, ASDisplayNode, ContextGesture?) -> Void)?, openColorPicker: @escaping (Bool) -> Void) -> ListViewItem {
|
func item(action: @escaping (ThemeSettingsColorOption?, Bool) -> Void, contextAction: ((ThemeSettingsColorOption?, Bool, ASDisplayNode, ContextGesture?) -> Void)?, openColorPicker: @escaping (Bool) -> Void) -> ListViewItem {
|
||||||
switch self {
|
switch self {
|
||||||
case let .color(_, themeReference, accentColor, selected):
|
case let .color(_, currentTheme, themeReference, accentColor, selected):
|
||||||
return ThemeSettingsAccentColorIconItem(themeReference: themeReference, color: accentColor.flatMap { .accentColor($0) }, selected: selected, action: action, contextAction: contextAction)
|
return ThemeSettingsAccentColorIconItem(themeReference: themeReference, theme: currentTheme, color: accentColor.flatMap { .accentColor($0) }, selected: selected, action: action, contextAction: contextAction)
|
||||||
case let .theme(_, baseThemeReference, theme, selected):
|
case let .theme(_, currentTheme, baseThemeReference, theme, selected):
|
||||||
return ThemeSettingsAccentColorIconItem(themeReference: baseThemeReference, color: .theme(theme), selected: selected, action: action, contextAction: contextAction)
|
return ThemeSettingsAccentColorIconItem(themeReference: baseThemeReference, theme: currentTheme, color: .theme(theme), selected: selected, action: action, contextAction: contextAction)
|
||||||
case .picker:
|
case .picker:
|
||||||
return ThemeSettingsAccentColorPickerItem(action: openColorPicker)
|
return ThemeSettingsAccentColorPickerItem(action: openColorPicker)
|
||||||
}
|
}
|
||||||
@ -165,13 +165,15 @@ enum ThemeSettingsColorOption: Equatable {
|
|||||||
|
|
||||||
private class ThemeSettingsAccentColorIconItem: ListViewItem {
|
private class ThemeSettingsAccentColorIconItem: ListViewItem {
|
||||||
let themeReference: PresentationThemeReference
|
let themeReference: PresentationThemeReference
|
||||||
|
let theme: PresentationTheme
|
||||||
let color: ThemeSettingsColorOption?
|
let color: ThemeSettingsColorOption?
|
||||||
let selected: Bool
|
let selected: Bool
|
||||||
let action: (ThemeSettingsColorOption?, Bool) -> Void
|
let action: (ThemeSettingsColorOption?, Bool) -> Void
|
||||||
let contextAction: ((ThemeSettingsColorOption?, Bool, ASDisplayNode, ContextGesture?) -> Void)?
|
let contextAction: ((ThemeSettingsColorOption?, Bool, ASDisplayNode, ContextGesture?) -> Void)?
|
||||||
|
|
||||||
public init(themeReference: PresentationThemeReference, color: ThemeSettingsColorOption?, selected: Bool, action: @escaping (ThemeSettingsColorOption?, Bool) -> Void, contextAction: ((ThemeSettingsColorOption?, Bool, ASDisplayNode, ContextGesture?) -> Void)?) {
|
public init(themeReference: PresentationThemeReference, theme: PresentationTheme, color: ThemeSettingsColorOption?, selected: Bool, action: @escaping (ThemeSettingsColorOption?, Bool) -> Void, contextAction: ((ThemeSettingsColorOption?, Bool, ASDisplayNode, ContextGesture?) -> Void)?) {
|
||||||
self.themeReference = themeReference
|
self.themeReference = themeReference
|
||||||
|
self.theme = theme
|
||||||
self.color = color
|
self.color = color
|
||||||
self.selected = selected
|
self.selected = selected
|
||||||
self.action = action
|
self.action = action
|
||||||
@ -369,13 +371,13 @@ private final class ThemeSettingsAccentColorIconItemNode : ListViewItemNode {
|
|||||||
strokeColor = fillColor
|
strokeColor = fillColor
|
||||||
}
|
}
|
||||||
|
|
||||||
// if strokeColor.distance(to: theme.list.itemBlocksBackgroundColor) < 200 {
|
if let color = strokeColor, color.distance(to: item.theme.list.itemBlocksBackgroundColor) < 200 {
|
||||||
// if strokeColor.distance(to: UIColor.white) < 200 {
|
if color.distance(to: UIColor.white) < 200 {
|
||||||
// strokeColor = UIColor(rgb: 0x999999)
|
strokeColor = UIColor(rgb: 0x999999)
|
||||||
// } else {
|
} else {
|
||||||
// strokeColor = theme.list.controlSecondaryColor
|
strokeColor = item.theme.list.controlSecondaryColor
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
|
|
||||||
var topColor: UIColor?
|
var topColor: UIColor?
|
||||||
var bottomColor: UIColor?
|
var bottomColor: UIColor?
|
||||||
@ -874,7 +876,7 @@ class ThemeSettingsAccentColorItemNode: ListViewItemNode, ItemListItemNode {
|
|||||||
switch color {
|
switch color {
|
||||||
case .default:
|
case .default:
|
||||||
let selected = item.currentColor == nil
|
let selected = item.currentColor == nil
|
||||||
entries.append(.color(index, item.generalThemeReference, nil, selected))
|
entries.append(.color(index, item.theme, item.generalThemeReference, nil, selected))
|
||||||
case let .color(color):
|
case let .color(color):
|
||||||
var selected = false
|
var selected = false
|
||||||
if let currentColor = item.currentColor, case let .accentColor(accentColor) = currentColor {
|
if let currentColor = item.currentColor, case let .accentColor(accentColor) = currentColor {
|
||||||
@ -888,22 +890,22 @@ class ThemeSettingsAccentColorItemNode: ListViewItemNode, ItemListItemNode {
|
|||||||
}
|
}
|
||||||
switch accentColor {
|
switch accentColor {
|
||||||
case let .accentColor(color):
|
case let .accentColor(color):
|
||||||
entries.append(.color(index, item.generalThemeReference, color, selected))
|
entries.append(.color(index, item.theme, item.generalThemeReference, color, selected))
|
||||||
case let .theme(theme):
|
case let .theme(theme):
|
||||||
entries.append(.theme(index, item.generalThemeReference, theme, selected))
|
entries.append(.theme(index, item.theme, item.generalThemeReference, theme, selected))
|
||||||
}
|
}
|
||||||
case let .preset(color), let .custom(color):
|
case let .preset(color), let .custom(color):
|
||||||
var selected = false
|
var selected = false
|
||||||
if let currentColor = item.currentColor {
|
if let currentColor = item.currentColor {
|
||||||
selected = currentColor.index == Int64(color.index)
|
selected = currentColor.index == Int64(color.index)
|
||||||
}
|
}
|
||||||
entries.append(.color(index, item.themeReference, color, selected))
|
entries.append(.color(index, item.theme, item.themeReference, color, selected))
|
||||||
case let .theme(theme):
|
case let .theme(theme):
|
||||||
var selected = false
|
var selected = false
|
||||||
if let currentColor = item.currentColor {
|
if let currentColor = item.currentColor {
|
||||||
selected = currentColor.index == theme.index
|
selected = currentColor.index == theme.index
|
||||||
}
|
}
|
||||||
entries.append(.theme(index, item.generalThemeReference, theme, selected))
|
entries.append(.theme(index, item.theme, item.generalThemeReference, theme, selected))
|
||||||
}
|
}
|
||||||
index += 1
|
index += 1
|
||||||
}
|
}
|
||||||
|
|||||||
@ -143,7 +143,7 @@ class ThemeSettingsChatPreviewItemNode: ListViewItemNode {
|
|||||||
return { item, params, neighbors in
|
return { item, params, neighbors in
|
||||||
var updatedBackgroundSignal: Signal<(UIImage?, Bool)?, NoError>?
|
var updatedBackgroundSignal: Signal<(UIImage?, Bool)?, NoError>?
|
||||||
if currentItem?.wallpaper != item.wallpaper {
|
if currentItem?.wallpaper != item.wallpaper {
|
||||||
updatedBackgroundSignal = chatControllerBackgroundImageSignal(wallpaper: item.wallpaper, mediaBox: item.context.account.postbox.mediaBox)
|
updatedBackgroundSignal = chatControllerBackgroundImageSignal(wallpaper: item.wallpaper, mediaBox: item.context.sharedContext.accountManager.mediaBox)
|
||||||
}
|
}
|
||||||
|
|
||||||
let insets: UIEdgeInsets
|
let insets: UIEdgeInsets
|
||||||
|
|||||||
@ -1208,8 +1208,13 @@ public func themeSettingsController(context: AccountContext, focusOnItemTag: The
|
|||||||
|
|
||||||
let _ = (context.account.postbox.mediaBox.cachedResourceRepresentation(resource, representation: representation, complete: false, fetch: true)
|
let _ = (context.account.postbox.mediaBox.cachedResourceRepresentation(resource, representation: representation, complete: false, fetch: true)
|
||||||
|> filter({ $0.complete })).start(next: { data in
|
|> filter({ $0.complete })).start(next: { data in
|
||||||
if data.complete, let path = context.account.postbox.mediaBox.completedResourcePath(resource), let maybeData = try? Data(contentsOf: URL(fileURLWithPath: path), options: .mappedRead) {
|
if data.complete, let path = context.account.postbox.mediaBox.completedResourcePath(resource) {
|
||||||
context.sharedContext.accountManager.mediaBox.storeResourceData(resource.id, data: maybeData, synchronous: true)
|
if let maybeData = try? Data(contentsOf: URL(fileURLWithPath: path), options: .mappedRead) {
|
||||||
|
context.sharedContext.accountManager.mediaBox.storeResourceData(resource.id, data: maybeData, synchronous: true)
|
||||||
|
}
|
||||||
|
if let maybeData = try? Data(contentsOf: URL(fileURLWithPath: data.path), options: .mappedRead) {
|
||||||
|
context.sharedContext.accountManager.mediaBox.storeCachedResourceRepresentation(resource, representation: representation, data: maybeData)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
return .single(wallpaper)
|
return .single(wallpaper)
|
||||||
@ -1263,12 +1268,6 @@ public func themeSettingsController(context: AccountContext, focusOnItemTag: The
|
|||||||
} else {
|
} else {
|
||||||
themeSpecificChatWallpapers[index] = presetWallpaper
|
themeSpecificChatWallpapers[index] = presetWallpaper
|
||||||
}
|
}
|
||||||
// if let wallpaper = current.themeSpecificChatWallpapers[coloredThemeIndex(reference: currentTheme, accentColor: accentColor)], wallpaper.isColorOrGradient || wallpaper.isPattern || wallpaper.isBuiltin {
|
|
||||||
// themeSpecificChatWallpapers[currentTheme.index] = nil
|
|
||||||
// if let accentColor = accentColor {
|
|
||||||
// themeSpecificChatWallpapers[coloredThemeIndex(reference: currentTheme, accentColor: accentColor)] = nil
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return PresentationThemeSettings(theme: updatedTheme, themeSpecificAccentColors: themeSpecificAccentColors, themeSpecificChatWallpapers: themeSpecificChatWallpapers, useSystemFont: current.useSystemFont, fontSize: current.fontSize, automaticThemeSwitchSetting: updatedAutomaticThemeSwitchSetting, largeEmoji: current.largeEmoji, disableAnimations: current.disableAnimations)
|
return PresentationThemeSettings(theme: updatedTheme, themeSpecificAccentColors: themeSpecificAccentColors, themeSpecificChatWallpapers: themeSpecificChatWallpapers, useSystemFont: current.useSystemFont, fontSize: current.fontSize, automaticThemeSwitchSetting: updatedAutomaticThemeSwitchSetting, largeEmoji: current.largeEmoji, disableAnimations: current.disableAnimations)
|
||||||
|
|||||||
@ -637,7 +637,7 @@ final class WallpaperGalleryItemNode: GalleryItemNode {
|
|||||||
|
|
||||||
@objc private func togglePattern() {
|
@objc private func togglePattern() {
|
||||||
let value = !self.patternButtonNode.isSelected
|
let value = !self.patternButtonNode.isSelected
|
||||||
self.patternButtonNode.setSelected(value, animated: true)
|
self.patternButtonNode.setSelected(value, animated: false)
|
||||||
|
|
||||||
self.requestPatternPanel?(value)
|
self.requestPatternPanel?(value)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -8,10 +8,166 @@ import SyncCore
|
|||||||
import TelegramPresentationData
|
import TelegramPresentationData
|
||||||
import LegacyComponents
|
import LegacyComponents
|
||||||
import AccountContext
|
import AccountContext
|
||||||
|
import MergeLists
|
||||||
|
|
||||||
private let itemSize = CGSize(width: 88.0, height: 88.0)
|
private let itemSize = CGSize(width: 88.0, height: 88.0)
|
||||||
private let inset: CGFloat = 12.0
|
private let inset: CGFloat = 12.0
|
||||||
|
|
||||||
|
|
||||||
|
private struct WallpaperPatternEntry: Comparable, Identifiable {
|
||||||
|
let index: Int
|
||||||
|
let wallpaper: TelegramWallpaper
|
||||||
|
let selected: Bool
|
||||||
|
|
||||||
|
var stableId: Int64 {
|
||||||
|
if case let .file(file) = self.wallpaper {
|
||||||
|
return file.id
|
||||||
|
} else {
|
||||||
|
return Int64(self.index)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static func ==(lhs: WallpaperPatternEntry, rhs: WallpaperPatternEntry) -> Bool {
|
||||||
|
if lhs.index != rhs.index {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if lhs.wallpaper != rhs.wallpaper {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
static func <(lhs: WallpaperPatternEntry, rhs: WallpaperPatternEntry) -> Bool {
|
||||||
|
return lhs.index < rhs.index
|
||||||
|
}
|
||||||
|
|
||||||
|
func item(context: AccountContext, action: @escaping (TelegramWallpaper) -> Void) -> ListViewItem {
|
||||||
|
return WallpaperPatternItem(context: context, wallpaper: self.wallpaper, selected: self.selected, action: action)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class WallpaperPatternItem: ListViewItem {
|
||||||
|
let context: AccountContext
|
||||||
|
let wallpaper: TelegramWallpaper
|
||||||
|
let selected: Bool
|
||||||
|
let action: (TelegramWallpaper) -> Void
|
||||||
|
|
||||||
|
public init(context: AccountContext, wallpaper: TelegramWallpaper, selected: Bool, action: @escaping (TelegramWallpaper) -> Void) {
|
||||||
|
self.context = context
|
||||||
|
self.wallpaper = wallpaper
|
||||||
|
self.selected = selected
|
||||||
|
self.action = action
|
||||||
|
}
|
||||||
|
|
||||||
|
public func nodeConfiguredForParams(async: @escaping (@escaping () -> Void) -> Void, params: ListViewItemLayoutParams, synchronousLoads: Bool, previousItem: ListViewItem?, nextItem: ListViewItem?, completion: @escaping (ListViewItemNode, @escaping () -> (Signal<Void, NoError>?, (ListViewItemApply) -> Void)) -> Void) {
|
||||||
|
async {
|
||||||
|
let node = WallpaperPatternItemNode()
|
||||||
|
let (nodeLayout, apply) = node.asyncLayout()(self, params)
|
||||||
|
node.insets = nodeLayout.insets
|
||||||
|
node.contentSize = nodeLayout.contentSize
|
||||||
|
|
||||||
|
Queue.mainQueue().async {
|
||||||
|
completion(node, {
|
||||||
|
return (nil, { _ in
|
||||||
|
apply(false)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public func updateNode(async: @escaping (@escaping () -> Void) -> Void, node: @escaping () -> ListViewItemNode, params: ListViewItemLayoutParams, previousItem: ListViewItem?, nextItem: ListViewItem?, animation: ListViewItemUpdateAnimation, completion: @escaping (ListViewItemNodeLayout, @escaping (ListViewItemApply) -> Void) -> Void) {
|
||||||
|
Queue.mainQueue().async {
|
||||||
|
assert(node() is WallpaperPatternItemNode)
|
||||||
|
if let nodeValue = node() as? WallpaperPatternItemNode {
|
||||||
|
let layout = nodeValue.asyncLayout()
|
||||||
|
async {
|
||||||
|
let (nodeLayout, apply) = layout(self, params)
|
||||||
|
Queue.mainQueue().async {
|
||||||
|
completion(nodeLayout, { _ in
|
||||||
|
apply(animation.isAnimated)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public var selectable = true
|
||||||
|
public func selected(listView: ListView) {
|
||||||
|
self.action(self.wallpaper)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private final class WallpaperPatternItemNode : ListViewItemNode {
|
||||||
|
private let wallpaperNode: SettingsThemeWallpaperNode
|
||||||
|
|
||||||
|
var item: WallpaperPatternItem?
|
||||||
|
|
||||||
|
init() {
|
||||||
|
self.wallpaperNode = SettingsThemeWallpaperNode()
|
||||||
|
|
||||||
|
super.init(layerBacked: false, dynamicBounce: false, rotated: false, seeThrough: false)
|
||||||
|
|
||||||
|
self.addSubnode(self.wallpaperNode)
|
||||||
|
}
|
||||||
|
|
||||||
|
override func didLoad() {
|
||||||
|
super.didLoad()
|
||||||
|
|
||||||
|
self.layer.sublayerTransform = CATransform3DMakeRotation(CGFloat.pi / 2.0, 0.0, 0.0, 1.0)
|
||||||
|
}
|
||||||
|
|
||||||
|
func asyncLayout() -> (WallpaperPatternItem, ListViewItemLayoutParams) -> (ListViewItemNodeLayout, (Bool) -> Void) {
|
||||||
|
let currentItem = self.item
|
||||||
|
|
||||||
|
return { [weak self] item, params in
|
||||||
|
var updatedWallpaper = false
|
||||||
|
var updatedSelected = false
|
||||||
|
|
||||||
|
if currentItem?.wallpaper != item.wallpaper {
|
||||||
|
updatedWallpaper = true
|
||||||
|
}
|
||||||
|
if currentItem?.selected != item.selected {
|
||||||
|
updatedSelected = true
|
||||||
|
}
|
||||||
|
|
||||||
|
let itemLayout = ListViewItemNodeLayout(contentSize: CGSize(width: 112.0, height: 112.0), insets: UIEdgeInsets())
|
||||||
|
return (itemLayout, { animated in
|
||||||
|
if let strongSelf = self {
|
||||||
|
strongSelf.item = item
|
||||||
|
strongSelf.wallpaperNode.frame = CGRect(x: 0.0, y: 12.0, width: itemSize.width, height: itemSize.height)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override func animateInsertion(_ currentTimestamp: Double, duration: Double, short: Bool) {
|
||||||
|
super.animateInsertion(currentTimestamp, duration: duration, short: short)
|
||||||
|
|
||||||
|
self.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2)
|
||||||
|
}
|
||||||
|
|
||||||
|
override func animateRemoved(_ currentTimestamp: Double, duration: Double) {
|
||||||
|
super.animateRemoved(currentTimestamp, duration: duration)
|
||||||
|
|
||||||
|
self.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2, removeOnCompletion: false)
|
||||||
|
}
|
||||||
|
|
||||||
|
override func animateAdded(_ currentTimestamp: Double, duration: Double) {
|
||||||
|
super.animateAdded(currentTimestamp, duration: duration)
|
||||||
|
|
||||||
|
self.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
final class WallpaperPatternPanelNode: ASDisplayNode {
|
final class WallpaperPatternPanelNode: ASDisplayNode {
|
||||||
private let context: AccountContext
|
private let context: AccountContext
|
||||||
private var theme: PresentationTheme
|
private var theme: PresentationTheme
|
||||||
|
|||||||
@ -152,16 +152,18 @@ public func customizeDefaultDayTheme(theme: PresentationTheme, editing: Bool, ti
|
|||||||
outgoingSelectionBaseColor = outgoingControlColor
|
outgoingSelectionBaseColor = outgoingControlColor
|
||||||
outgoingCheckColor = outgoingAccent
|
outgoingCheckColor = outgoingAccent
|
||||||
} else {
|
} else {
|
||||||
outgoingAccentTextColor = outgoingBubbleFillColor?.withMultiplied(hue: 1.302 * hueFactor, saturation: 4.554 * saturationFactor, brightness: 0.655)
|
let outgoingBubbleMixedColor = lightnessColor
|
||||||
|
|
||||||
|
outgoingAccentTextColor = outgoingBubbleMixedColor.withMultiplied(hue: 1.302 * hueFactor, saturation: 4.554 * saturationFactor, brightness: 0.655)
|
||||||
outgoingLinkTextColor = UIColor(rgb: 0x004bad)
|
outgoingLinkTextColor = UIColor(rgb: 0x004bad)
|
||||||
outgoingScamColor = UIColor(rgb: 0xff3b30)
|
outgoingScamColor = UIColor(rgb: 0xff3b30)
|
||||||
outgoingControlColor = outgoingBubbleFillColor?.withMultiplied(hue: 1.283 * hueFactor, saturation: 3.176, brightness: 0.765)
|
outgoingControlColor = outgoingBubbleMixedColor.withMultiplied(hue: 1.283 * hueFactor, saturation: 3.176, brightness: 0.765)
|
||||||
outgoingInactiveControlColor = outgoingBubbleFillColor?.withMultiplied(hue: 1.207 * hueFactor, saturation: 1.721, brightness: 0.851)
|
outgoingInactiveControlColor = outgoingBubbleMixedColor.withMultiplied(hue: 1.207 * hueFactor, saturation: 1.721, brightness: 0.851)
|
||||||
outgoingFileTitleColor = outgoingBubbleFillColor?.withMultiplied(hue: 1.285 * hueFactor, saturation: 2.946, brightness: 0.667)
|
outgoingFileTitleColor = outgoingBubbleMixedColor.withMultiplied(hue: 1.285 * hueFactor, saturation: 2.946, brightness: 0.667)
|
||||||
outgoingPollsProgressColor = outgoingBubbleFillColor?.withMultiplied(hue: 1.283 * hueFactor, saturation: 3.176, brightness: 0.765)
|
outgoingPollsProgressColor = outgoingBubbleMixedColor.withMultiplied(hue: 1.283 * hueFactor, saturation: 3.176, brightness: 0.765)
|
||||||
outgoingSelectionColor = outgoingBubbleFillColor?.withMultiplied(hue: 1.013 * hueFactor, saturation: 1.292, brightness: 0.871)
|
outgoingSelectionColor = outgoingBubbleMixedColor.withMultiplied(hue: 1.013 * hueFactor, saturation: 1.292, brightness: 0.871)
|
||||||
outgoingSelectionBaseColor = outgoingControlColor
|
outgoingSelectionBaseColor = outgoingControlColor
|
||||||
outgoingCheckColor = outgoingBubbleFillColor?.withMultiplied(hue: 1.344 * hueFactor, saturation: 4.554 * saturationFactor, brightness: 0.549).withAlphaComponent(0.8)
|
outgoingCheckColor = outgoingBubbleMixedColor.withMultiplied(hue: 1.344 * hueFactor, saturation: 4.554 * saturationFactor, brightness: 0.549).withAlphaComponent(0.8)
|
||||||
}
|
}
|
||||||
outgoingPendingActivityColor = outgoingCheckColor
|
outgoingPendingActivityColor = outgoingCheckColor
|
||||||
|
|
||||||
@ -232,6 +234,7 @@ public func customizeDefaultDayTheme(theme: PresentationTheme, editing: Bool, ti
|
|||||||
bar: accentColor
|
bar: accentColor
|
||||||
),
|
),
|
||||||
actionButtonsFillColor: serviceBackgroundColor.flatMap { chat.message.incoming.actionButtonsFillColor.withUpdated(withWallpaper: $0) },
|
actionButtonsFillColor: serviceBackgroundColor.flatMap { chat.message.incoming.actionButtonsFillColor.withUpdated(withWallpaper: $0) },
|
||||||
|
actionButtonsStrokeColor: day ? chat.message.incoming.actionButtonsStrokeColor.withUpdated(withoutWallpaper: accentColor) : nil,
|
||||||
actionButtonsTextColor: day ? chat.message.incoming.actionButtonsTextColor.withUpdated(withoutWallpaper: accentColor) : nil,
|
actionButtonsTextColor: day ? chat.message.incoming.actionButtonsTextColor.withUpdated(withoutWallpaper: accentColor) : nil,
|
||||||
textSelectionColor: accentColor?.withAlphaComponent(0.2),
|
textSelectionColor: accentColor?.withAlphaComponent(0.2),
|
||||||
textSelectionKnobColor: accentColor
|
textSelectionKnobColor: accentColor
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@ -54,7 +54,7 @@ extension TelegramWallpaper: Codable {
|
|||||||
blur = true
|
blur = true
|
||||||
}
|
}
|
||||||
|
|
||||||
if components.count >= 2 && components.count <= 5 && components[0].count == 6 && !optionKeys.contains(components[0]) && components[1].count == 6 && !optionKeys.contains(components[1]), let topColor = UIColor(hexString: components[0]), let bottomColor = UIColor(hexString: components[1]) {
|
if components.count >= 2 && components.count <= 5 && [6, 8].contains(components[0].count) && !optionKeys.contains(components[0]) && [6, 8].contains(components[1].count) && !optionKeys.contains(components[1]), let topColor = UIColor(hexString: components[0]), let bottomColor = UIColor(hexString: components[1]) {
|
||||||
|
|
||||||
var rotation: Int32?
|
var rotation: Int32?
|
||||||
if components.count > 2, components[2].count <= 3, let value = Int32(components[2]) {
|
if components.count > 2, components[2].count <= 3, let value = Int32(components[2]) {
|
||||||
|
|||||||
@ -73,7 +73,8 @@ final class ChatButtonKeyboardInputNode: ChatInputNode {
|
|||||||
override func updateLayout(width: CGFloat, leftInset: CGFloat, rightInset: CGFloat, bottomInset: CGFloat, standardInputHeight: CGFloat, inputHeight: CGFloat, maximumHeight: CGFloat, inputPanelHeight: CGFloat, transition: ContainedViewLayoutTransition, interfaceState: ChatPresentationInterfaceState, deviceMetrics: DeviceMetrics, isVisible: Bool) -> (CGFloat, CGFloat) {
|
override func updateLayout(width: CGFloat, leftInset: CGFloat, rightInset: CGFloat, bottomInset: CGFloat, standardInputHeight: CGFloat, inputHeight: CGFloat, maximumHeight: CGFloat, inputPanelHeight: CGFloat, transition: ContainedViewLayoutTransition, interfaceState: ChatPresentationInterfaceState, deviceMetrics: DeviceMetrics, isVisible: Bool) -> (CGFloat, CGFloat) {
|
||||||
transition.updateFrame(node: self.separatorNode, frame: CGRect(origin: CGPoint(), size: CGSize(width: width, height: UIScreenPixel)))
|
transition.updateFrame(node: self.separatorNode, frame: CGRect(origin: CGPoint(), size: CGSize(width: width, height: UIScreenPixel)))
|
||||||
|
|
||||||
if self.theme !== interfaceState.theme {
|
let updatedTheme = self.theme !== interfaceState.theme
|
||||||
|
if updatedTheme {
|
||||||
self.theme = interfaceState.theme
|
self.theme = interfaceState.theme
|
||||||
|
|
||||||
self.separatorNode.backgroundColor = interfaceState.theme.chat.inputButtonPanel.panelSeparatorColor
|
self.separatorNode.backgroundColor = interfaceState.theme.chat.inputButtonPanel.panelSeparatorColor
|
||||||
@ -128,7 +129,7 @@ final class ChatButtonKeyboardInputNode: ChatInputNode {
|
|||||||
self.buttonNodes.append(buttonNode)
|
self.buttonNodes.append(buttonNode)
|
||||||
}
|
}
|
||||||
buttonIndex += 1
|
buttonIndex += 1
|
||||||
if buttonNode.button != button {
|
if buttonNode.button != button || updatedTheme {
|
||||||
buttonNode.button = button
|
buttonNode.button = button
|
||||||
buttonNode.setAttributedTitle(NSAttributedString(string: button.title, font: Font.regular(16.0), textColor: interfaceState.theme.chat.inputButtonPanel.buttonTextColor, paragraphAlignment: .center), for: [])
|
buttonNode.setAttributedTitle(NSAttributedString(string: button.title, font: Font.regular(16.0), textColor: interfaceState.theme.chat.inputButtonPanel.buttonTextColor, paragraphAlignment: .center), for: [])
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1625,8 +1625,14 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||||||
strongSelf.presentScheduleTimePicker(completion: { [weak self] time in
|
strongSelf.presentScheduleTimePicker(completion: { [weak self] time in
|
||||||
if let strongSelf = self {
|
if let strongSelf = self {
|
||||||
strongSelf.chatDisplayNode.sendCurrentMessage(scheduleTime: time, completion: { [weak self] in
|
strongSelf.chatDisplayNode.sendCurrentMessage(scheduleTime: time, completion: { [weak self] in
|
||||||
if let strongSelf = self, !strongSelf.presentationInterfaceState.isScheduledMessages && time != scheduleWhenOnlineTimestamp {
|
if let strongSelf = self {
|
||||||
strongSelf.openScheduledMessages()
|
strongSelf.updateChatPresentationInterfaceState(animated: true, interactive: false, {
|
||||||
|
$0.updatedInterfaceState { $0.withUpdatedReplyMessageId(nil).withUpdatedComposeInputState(ChatTextInputState(inputText: NSAttributedString(string: ""))) }
|
||||||
|
})
|
||||||
|
|
||||||
|
if !strongSelf.presentationInterfaceState.isScheduledMessages && time != scheduleWhenOnlineTimestamp {
|
||||||
|
strongSelf.openScheduledMessages()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2261,9 +2261,9 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate {
|
|||||||
textInputPanelNode.text = ""
|
textInputPanelNode.text = ""
|
||||||
strongSelf.requestUpdateChatInterfaceState(false, true, { $0.withUpdatedReplyMessageId(nil).withUpdatedForwardMessageIds(nil).withUpdatedComposeDisableUrlPreview(nil) })
|
strongSelf.requestUpdateChatInterfaceState(false, true, { $0.withUpdatedReplyMessageId(nil).withUpdatedForwardMessageIds(nil).withUpdatedComposeDisableUrlPreview(nil) })
|
||||||
strongSelf.ignoreUpdateHeight = false
|
strongSelf.ignoreUpdateHeight = false
|
||||||
completion()
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
completion()
|
||||||
|
|
||||||
if let forwardMessageIds = self.chatPresentationInterfaceState.interfaceState.forwardMessageIds {
|
if let forwardMessageIds = self.chatPresentationInterfaceState.interfaceState.forwardMessageIds {
|
||||||
for id in forwardMessageIds {
|
for id in forwardMessageIds {
|
||||||
|
|||||||
@ -142,9 +142,8 @@ final class ChatMessageNotificationItemNode: NotificationItemNode {
|
|||||||
} else {
|
} else {
|
||||||
isScheduled = true
|
isScheduled = true
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
self.avatarNode.setPeer(context: item.context, theme: presentationData.theme, peer: peer, overrideImage: peer.id == item.context.account.peerId ? .savedMessagesIcon : nil, emptyColor: presentationData.theme.list.mediaPlaceholderColor)
|
|
||||||
}
|
}
|
||||||
|
self.avatarNode.setPeer(context: item.context, theme: presentationData.theme, peer: peer, overrideImage: peer.id == item.context.account.peerId ? .savedMessagesIcon : nil, emptyColor: presentationData.theme.list.mediaPlaceholderColor)
|
||||||
}
|
}
|
||||||
|
|
||||||
var titleIcon: UIImage?
|
var titleIcon: UIImage?
|
||||||
@ -308,9 +307,6 @@ final class ChatMessageNotificationItemNode: NotificationItemNode {
|
|||||||
|
|
||||||
if isReminder {
|
if isReminder {
|
||||||
title = presentationData.strings.ScheduledMessages_ReminderNotification
|
title = presentationData.strings.ScheduledMessages_ReminderNotification
|
||||||
if let firstMessage = item.messages.first, let peer = messageMainPeer(firstMessage) {
|
|
||||||
self.avatarNode.setPeer(context: item.context, theme: presentationData.theme, peer: peer, overrideImage: .savedMessagesIcon, emptyColor: presentationData.theme.list.mediaPlaceholderColor)
|
|
||||||
}
|
|
||||||
} else if isScheduled, let currentTitle = title {
|
} else if isScheduled, let currentTitle = title {
|
||||||
title = "📅 \(currentTitle)"
|
title = "📅 \(currentTitle)"
|
||||||
}
|
}
|
||||||
|
|||||||
@ -12,6 +12,7 @@ import MergeLists
|
|||||||
import ChatListUI
|
import ChatListUI
|
||||||
import AccountContext
|
import AccountContext
|
||||||
import ContextUI
|
import ContextUI
|
||||||
|
import ChatListSearchItemHeader
|
||||||
|
|
||||||
private enum ChatListSearchEntryStableId: Hashable {
|
private enum ChatListSearchEntryStableId: Hashable {
|
||||||
case messageId(MessageId)
|
case messageId(MessageId)
|
||||||
@ -292,6 +293,12 @@ class ChatSearchResultsControllerNode: ViewControllerTracingNode, UIScrollViewDe
|
|||||||
let previousTheme = self.presentationData.theme
|
let previousTheme = self.presentationData.theme
|
||||||
self.presentationData = presentationData
|
self.presentationData = presentationData
|
||||||
self.presentationDataPromise.set(.single(ChatListPresentationData(theme: self.presentationData.theme, fontSize: self.presentationData.fontSize, strings: self.presentationData.strings, dateTimeFormat: self.presentationData.dateTimeFormat, nameSortOrder: self.presentationData.nameSortOrder, nameDisplayOrder: self.presentationData.nameDisplayOrder, disableAnimations: self.presentationData.disableAnimations)))
|
self.presentationDataPromise.set(.single(ChatListPresentationData(theme: self.presentationData.theme, fontSize: self.presentationData.fontSize, strings: self.presentationData.strings, dateTimeFormat: self.presentationData.dateTimeFormat, nameSortOrder: self.presentationData.nameSortOrder, nameDisplayOrder: self.presentationData.nameDisplayOrder, disableAnimations: self.presentationData.disableAnimations)))
|
||||||
|
|
||||||
|
self.listNode.forEachItemHeaderNode({ itemHeaderNode in
|
||||||
|
if let itemHeaderNode = itemHeaderNode as? ChatListSearchItemHeaderNode {
|
||||||
|
itemHeaderNode.updateTheme(theme: presentationData.theme)
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
private func enqueueTransition(_ transition: ChatListSearchContainerTransition, firstTime: Bool) {
|
private func enqueueTransition(_ transition: ChatListSearchContainerTransition, firstTime: Bool) {
|
||||||
|
|||||||
@ -395,11 +395,11 @@ public final class MediaManagerImpl: NSObject, MediaManager {
|
|||||||
|
|
||||||
let throttledSignal = self.globalMediaPlayerState
|
let throttledSignal = self.globalMediaPlayerState
|
||||||
|> mapToThrottled { next -> Signal<(Account, SharedMediaPlayerItemPlaybackStateOrLoading, MediaManagerPlayerType)?, NoError> in
|
|> mapToThrottled { next -> Signal<(Account, SharedMediaPlayerItemPlaybackStateOrLoading, MediaManagerPlayerType)?, NoError> in
|
||||||
return .single(next) |> then(.complete() |> delay(4.0, queue: Queue.concurrentDefaultQueue()))
|
return .single(next) |> then(.complete() |> delay(2.0, queue: Queue.concurrentDefaultQueue()))
|
||||||
}
|
}
|
||||||
|
|
||||||
self.mediaPlaybackStateDisposable.set(throttledSignal.start(next: { accountStateAndType in
|
self.mediaPlaybackStateDisposable.set(throttledSignal.start(next: { accountStateAndType in
|
||||||
if let (account, stateOrLoading, type) = accountStateAndType, type == .music, case let .state(state) = stateOrLoading, state.status.duration > 60.0 * 20.0, case .playing = state.status.status {
|
if let (account, stateOrLoading, type) = accountStateAndType, type == .music, case let .state(state) = stateOrLoading, state.status.duration >= 60.0 * 20.0, case .playing = state.status.status {
|
||||||
if let item = state.item as? MessageMediaPlaylistItem {
|
if let item = state.item as? MessageMediaPlaylistItem {
|
||||||
var storedState: MediaPlaybackStoredState?
|
var storedState: MediaPlaybackStoredState?
|
||||||
if state.status.timestamp > 5.0 && state.status.timestamp < state.status.duration - 5.0 {
|
if state.status.timestamp > 5.0 && state.status.timestamp < state.status.duration - 5.0 {
|
||||||
|
|||||||
@ -173,10 +173,12 @@ final class OverlayPlayerControlsNode: ASDisplayNode {
|
|||||||
self.scrubberNode = MediaPlayerScrubbingNode(content: .standard(lineHeight: 3.0, lineCap: .round, scrubberHandle: .circle, backgroundColor: presentationData.theme.list.controlSecondaryColor, foregroundColor: presentationData.theme.list.itemAccentColor, bufferingColor: presentationData.theme.list.itemAccentColor.withAlphaComponent(0.4)))
|
self.scrubberNode = MediaPlayerScrubbingNode(content: .standard(lineHeight: 3.0, lineCap: .round, scrubberHandle: .circle, backgroundColor: presentationData.theme.list.controlSecondaryColor, foregroundColor: presentationData.theme.list.itemAccentColor, bufferingColor: presentationData.theme.list.itemAccentColor.withAlphaComponent(0.4)))
|
||||||
self.leftDurationLabel = MediaPlayerTimeTextNode(textColor: presentationData.theme.list.itemSecondaryTextColor)
|
self.leftDurationLabel = MediaPlayerTimeTextNode(textColor: presentationData.theme.list.itemSecondaryTextColor)
|
||||||
self.leftDurationLabel.displaysAsynchronously = false
|
self.leftDurationLabel.displaysAsynchronously = false
|
||||||
|
self.leftDurationLabel.keepPreviousValueOnEmptyState = true
|
||||||
self.rightDurationLabel = MediaPlayerTimeTextNode(textColor: presentationData.theme.list.itemSecondaryTextColor)
|
self.rightDurationLabel = MediaPlayerTimeTextNode(textColor: presentationData.theme.list.itemSecondaryTextColor)
|
||||||
self.rightDurationLabel.displaysAsynchronously = false
|
self.rightDurationLabel.displaysAsynchronously = false
|
||||||
self.rightDurationLabel.mode = .reversed
|
self.rightDurationLabel.mode = .reversed
|
||||||
self.rightDurationLabel.alignment = .right
|
self.rightDurationLabel.alignment = .right
|
||||||
|
self.rightDurationLabel.keepPreviousValueOnEmptyState = true
|
||||||
|
|
||||||
self.rateButton = HighlightableButtonNode()
|
self.rateButton = HighlightableButtonNode()
|
||||||
self.rateButton.hitTestSlop = UIEdgeInsets(top: -8.0, left: -4.0, bottom: -8.0, right: -4.0)
|
self.rateButton.hitTestSlop = UIEdgeInsets(top: -8.0, left: -4.0, bottom: -8.0, right: -4.0)
|
||||||
|
|||||||
@ -85,7 +85,7 @@ final class PeerSelectionControllerNode: ASDisplayNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
self.chatListNode = ChatListNode(context: context, groupId: .root, controlsHistoryPreload: false, mode: .peers(filter: filter), theme: presentationData.theme, fontSize: presentationData.fontSize, strings: presentationData.strings, dateTimeFormat: presentationData.dateTimeFormat, nameSortOrder: presentationData.nameSortOrder, nameDisplayOrder: presentationData.nameDisplayOrder, disableAnimations: presentationData.disableAnimations)
|
self.chatListNode = ChatListNode(context: context, groupId: .root, previewing: false, controlsHistoryPreload: false, mode: .peers(filter: filter), theme: presentationData.theme, fontSize: presentationData.fontSize, strings: presentationData.strings, dateTimeFormat: presentationData.dateTimeFormat, nameSortOrder: presentationData.nameSortOrder, nameDisplayOrder: presentationData.nameDisplayOrder, disableAnimations: presentationData.disableAnimations)
|
||||||
|
|
||||||
super.init()
|
super.init()
|
||||||
|
|
||||||
|
|||||||
Binary file not shown.
@ -1125,7 +1125,7 @@ public func themeIconImage(account: Account, accountManager: AccountManager, the
|
|||||||
case .night:
|
case .night:
|
||||||
topBackgroundColor = UIColor(rgb: 0x000000)
|
topBackgroundColor = UIColor(rgb: 0x000000)
|
||||||
incomingColor = UIColor(rgb: 0x1f1f1f)
|
incomingColor = UIColor(rgb: 0x1f1f1f)
|
||||||
if accentColor == nil {
|
if accentColor == nil || accentColor?.rgb == 0xffffff {
|
||||||
accentColor = UIColor(rgb: 0x313131)
|
accentColor = UIColor(rgb: 0x313131)
|
||||||
}
|
}
|
||||||
outgoingColor = bubbleColors ?? (accentColor!, accentColor!)
|
outgoingColor = bubbleColors ?? (accentColor!, accentColor!)
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user