Merge commit '5fbe8c8ac59f993822eea89c3cd8950e8408cfe8'

This commit is contained in:
Ali 2021-03-22 21:45:07 +04:00
commit 2784521952
25 changed files with 3678 additions and 3584 deletions

View File

@ -6255,6 +6255,7 @@ Sorry for the inconvenience.";
"VoiceChat.YouCanNowSpeak" = "You can now speak";
"VoiceChat.YouCanNowSpeakIn" = "You can now speak in **%@**";
"VoiceChat.UserCanNowSpeak" = "**%@** can now speak";
"VoiceChat.MutedByAdmin" = "Muted by Admin";
"VoiceChat.MutedByAdminHelp" = "Tap if you want to speak";

View File

@ -20,16 +20,18 @@ public class ContactListActionItem: ListViewItem, ListViewItemWithHeader {
let icon: ContactListActionItemIcon
let highlight: ContactListActionItemHighlight
let clearHighlightAutomatically: Bool
let accessible: Bool
let action: () -> Void
public let header: ListViewItemHeader?
public init(presentationData: ItemListPresentationData, title: String, icon: ContactListActionItemIcon, highlight: ContactListActionItemHighlight = .cell, clearHighlightAutomatically: Bool = true, header: ListViewItemHeader?, action: @escaping () -> Void) {
public init(presentationData: ItemListPresentationData, title: String, icon: ContactListActionItemIcon, highlight: ContactListActionItemHighlight = .cell, clearHighlightAutomatically: Bool = true, accessible: Bool = true, header: ListViewItemHeader?, action: @escaping () -> Void) {
self.presentationData = presentationData
self.title = title
self.icon = icon
self.highlight = highlight
self.header = header
self.clearHighlightAutomatically = clearHighlightAutomatically
self.accessible = accessible
self.action = action
}
@ -205,6 +207,14 @@ class ContactListActionItemNode: ListViewItemNode {
strongSelf.iconNode.image = generateTintedImage(image: item.icon.image, color: item.presentationData.theme.list.itemAccentColor)
}
if item.accessible && strongSelf.activateArea.supernode == nil {
strongSelf.view.accessibilityElementsHidden = false
strongSelf.addSubnode(strongSelf.activateArea)
} else if !item.accessible && strongSelf.activateArea.supernode != nil {
strongSelf.view.accessibilityElementsHidden = true
strongSelf.activateArea.removeFromSupernode()
}
let _ = titleApply()
var titleOffset = leftInset

View File

@ -163,7 +163,7 @@ private enum ContactListNodeEntry: Comparable, Identifiable {
if case .presence = sortOrder {
text = strings.Contacts_SortedByPresence
}
return ContactListActionItem(presentationData: ItemListPresentationData(presentationData), title: text, icon: .inline(dropDownIcon, .right), highlight: .alpha, header: nil, action: {
return ContactListActionItem(presentationData: ItemListPresentationData(presentationData), title: text, icon: .inline(dropDownIcon, .right), highlight: .alpha, accessible: false, header: nil, action: {
interaction.openSortMenu()
})
case let .permissionInfo(_, title, text, suppressed):
@ -874,7 +874,7 @@ public final class ContactListNode: ASDisplayNode {
private var authorizationNode: PermissionContentNode
private let displayPermissionPlaceholder: Bool
public init(context: AccountContext, presentation: Signal<ContactListPresentation, NoError>, filters: [ContactListFilter] = [.excludeSelf], selectionState: ContactListNodeGroupSelectionState? = nil, displayPermissionPlaceholder: Bool = true, displaySortOptions: Bool = false, displayCallIcons: Bool = false, contextAction: ((Peer, ASDisplayNode, ContextGesture?) -> Void)? = nil, isSearch: Bool = false) {
public init(context: AccountContext, presentation: Signal<ContactListPresentation, NoError>, filters: [ContactListFilter] = [.excludeSelf], selectionState: ContactListNodeGroupSelectionState? = nil, displayPermissionPlaceholder: Bool = true, displaySortOptions: Bool = false, displayCallIcons: Bool = false, contextAction: ((Peer, ASDisplayNode, ContextGesture?) -> Void)? = nil, isSearch: Bool = false, multipleSelection: Bool = false) {
self.context = context
self.filters = filters
self.displayPermissionPlaceholder = displayPermissionPlaceholder
@ -951,7 +951,7 @@ public final class ContactListNode: ASDisplayNode {
self?.suppressPermissionWarning?()
}, openPeer: { [weak self] peer, action in
if let strongSelf = self {
if let _ = strongSelf.selectionStateValue {
if multipleSelection {
strongSelf.updateSelectionState({ state in
if let state = state {
var selectedPeerMap = state.selectedPeerMap

View File

@ -892,7 +892,11 @@ final class ChatItemGalleryFooterContentNode: GalleryFooterContentNode, UIScroll
if messages.count == 1 {
strongSelf.commitDeleteMessages(messages, ask: true)
} else {
let presentationData = strongSelf.context.sharedContext.currentPresentationData.with { $0 }
var presentationData = strongSelf.context.sharedContext.currentPresentationData.with { $0 }
if !presentationData.theme.overallDarkAppearance {
presentationData = presentationData.withUpdated(theme: defaultDarkColorPresentationTheme)
}
var generalMessageContentKind: MessageContentKind?
for message in messages {
let currentKind = messageContentKind(contentSettings: strongSelf.context.currentContentSettings.with { $0 }, message: message, strings: presentationData.strings, nameDisplayOrder: presentationData.nameDisplayOrder, accountPeerId: strongSelf.context.account.peerId)
@ -926,7 +930,8 @@ final class ChatItemGalleryFooterContentNode: GalleryFooterContentNode, UIScroll
}
}
let actionSheet = ActionSheetController(presentationData: presentationData.withUpdated(theme: defaultDarkColorPresentationTheme))
let actionSheet = ActionSheetController(presentationData: presentationData)
let items: [ActionSheetItem] = [
ActionSheetButtonItem(title: singleText, color: .destructive, action: { [weak actionSheet] in
actionSheet?.dismissAnimated()
@ -956,7 +961,11 @@ final class ChatItemGalleryFooterContentNode: GalleryFooterContentNode, UIScroll
private func commitDeleteMessages(_ messages: [Message], ask: Bool) {
self.messageContextDisposable.set((self.context.sharedContext.chatAvailableMessageActions(postbox: self.context.account.postbox, accountPeerId: self.context.account.peerId, messageIds: Set(messages.map { $0.id })) |> deliverOnMainQueue).start(next: { [weak self] actions in
if let strongSelf = self, let controllerInteration = strongSelf.controllerInteraction, !actions.options.isEmpty {
let actionSheet = ActionSheetController(presentationData: strongSelf.presentationData.withUpdated(theme: defaultDarkColorPresentationTheme))
var presentationData = strongSelf.presentationData
if !presentationData.theme.overallDarkAppearance {
presentationData = presentationData.withUpdated(theme: defaultDarkColorPresentationTheme)
}
let actionSheet = ActionSheetController(presentationData: presentationData)
var items: [ActionSheetItem] = []
var personalPeerName: String?
var isChannel = false
@ -1020,7 +1029,10 @@ final class ChatItemGalleryFooterContentNode: GalleryFooterContentNode, UIScroll
return transaction.getMessageGroup(currentMessage.id) ?? []
} |> deliverOnMainQueue).start(next: { [weak self] messages in
if let strongSelf = self, !messages.isEmpty {
let presentationData = strongSelf.context.sharedContext.currentPresentationData.with { $0 }
var presentationData = strongSelf.context.sharedContext.currentPresentationData.with { $0 }
if !presentationData.theme.overallDarkAppearance {
presentationData = presentationData.withUpdated(theme: defaultDarkColorPresentationTheme)
}
var generalMessageContentKind: MessageContentKind?
var beganContentKindScanning = false
var messageContentKinds = Set<MessageContentKindKey>()
@ -1097,7 +1109,7 @@ final class ChatItemGalleryFooterContentNode: GalleryFooterContentNode, UIScroll
}
}
}
let shareController = ShareController(context: strongSelf.context, subject: subject, preferredAction: preferredAction, forcedTheme: defaultDarkColorPresentationTheme)
let shareController = ShareController(context: strongSelf.context, subject: subject, preferredAction: preferredAction, forcedTheme: presentationData.theme.overallDarkAppearance ? nil : defaultDarkColorPresentationTheme)
shareController.completed = { [weak self] peerIds in
if let strongSelf = self {
let _ = (strongSelf.context.account.postbox.transaction { transaction -> [Peer] in
@ -1158,7 +1170,7 @@ final class ChatItemGalleryFooterContentNode: GalleryFooterContentNode, UIScroll
let shareAction: ([Message]) -> Void = { messages in
if let strongSelf = self {
let shareController = ShareController(context: strongSelf.context, subject: .messages(messages), preferredAction: preferredAction, forcedTheme: defaultDarkColorPresentationTheme)
let shareController = ShareController(context: strongSelf.context, subject: .messages(messages), preferredAction: preferredAction, forcedTheme: presentationData.theme.overallDarkAppearance ? nil : defaultDarkColorPresentationTheme)
shareController.completed = { [weak self] peerIds in
if let strongSelf = self {
let _ = (strongSelf.context.account.postbox.transaction { transaction -> [Peer] in
@ -1203,7 +1215,7 @@ final class ChatItemGalleryFooterContentNode: GalleryFooterContentNode, UIScroll
}
}
let actionSheet = ActionSheetController(presentationData: presentationData.withUpdated(theme: defaultDarkColorPresentationTheme))
let actionSheet = ActionSheetController(presentationData: presentationData)
let items: [ActionSheetItem] = [
ActionSheetButtonItem(title: singleText, color: .accent, action: { [weak actionSheet] in
actionSheet?.dismissAnimated()
@ -1227,7 +1239,10 @@ final class ChatItemGalleryFooterContentNode: GalleryFooterContentNode, UIScroll
}
})
} else if let (webPage, media) = self.currentWebPageAndMedia {
let presentationData = self.context.sharedContext.currentPresentationData.with { $0 }
var presentationData = self.context.sharedContext.currentPresentationData.with { $0 }
if !presentationData.theme.overallDarkAppearance {
presentationData = presentationData.withUpdated(theme: defaultDarkColorPresentationTheme)
}
var preferredAction = ShareControllerPreferredAction.default
var subject = ShareControllerSubject.media(.webPage(webPage: WebpageReference(webPage), media: media))
@ -1250,7 +1265,7 @@ final class ChatItemGalleryFooterContentNode: GalleryFooterContentNode, UIScroll
if availableOpenInOptions(context: self.context, item: item).count > 1 {
preferredAction = .custom(action: ShareControllerAction(title: presentationData.strings.Conversation_FileOpenIn, action: { [weak self] in
if let strongSelf = self {
let openInController = OpenInActionSheetController(context: strongSelf.context, forceTheme: defaultDarkColorPresentationTheme, item: item, additionalAction: nil, openUrl: { [weak self] url in
let openInController = OpenInActionSheetController(context: strongSelf.context, forceTheme: presentationData.theme.overallDarkAppearance ? nil : defaultDarkColorPresentationTheme, item: item, additionalAction: nil, openUrl: { [weak self] url in
if let strongSelf = self {
strongSelf.context.sharedContext.openExternalUrl(context: strongSelf.context, urlContext: .generic, url: url, forceExternal: true, presentationData: presentationData, navigationController: nil, dismissInput: {})
}
@ -1275,7 +1290,7 @@ final class ChatItemGalleryFooterContentNode: GalleryFooterContentNode, UIScroll
}
}
}
let shareController = ShareController(context: self.context, subject: subject, preferredAction: preferredAction, forcedTheme: defaultDarkColorPresentationTheme)
let shareController = ShareController(context: self.context, subject: subject, preferredAction: preferredAction, forcedTheme: presentationData.theme.overallDarkAppearance ? nil : defaultDarkColorPresentationTheme)
shareController.completed = { [weak self] peerIds in
if let strongSelf = self {
let _ = (strongSelf.context.account.postbox.transaction { transaction -> [Peer] in

View File

@ -665,7 +665,10 @@ public class GalleryController: ViewController, StandalonePresentableController
openActionOptionsImpl = { [weak self] action in
if let strongSelf = self {
let presentationData = strongSelf.presentationData
var presentationData = strongSelf.presentationData
if !presentationData.theme.overallDarkAppearance {
presentationData = presentationData.withUpdated(theme: defaultDarkColorPresentationTheme)
}
switch action {
case let .url(url, _):
var cleanUrl = url
@ -673,7 +676,7 @@ public class GalleryController: ViewController, StandalonePresentableController
let canOpenIn = availableOpenInOptions(context: strongSelf.context, item: .url(url: url)).count > 1
let mailtoString = "mailto:"
let telString = "tel:"
var openText = strongSelf.presentationData.strings.Conversation_LinkDialogOpen
var openText = presentationData.strings.Conversation_LinkDialogOpen
var phoneNumber: String?
var isEmail = false
@ -686,12 +689,12 @@ public class GalleryController: ViewController, StandalonePresentableController
canAddToReadingList = false
phoneNumber = String(cleanUrl[cleanUrl.index(cleanUrl.startIndex, offsetBy: telString.distance(from: telString.startIndex, to: telString.endIndex))...])
cleanUrl = phoneNumber!
openText = strongSelf.presentationData.strings.UserInfo_PhoneCall
openText = presentationData.strings.UserInfo_PhoneCall
isPhoneNumber = true
} else if canOpenIn {
openText = strongSelf.presentationData.strings.Conversation_FileOpenIn
openText = presentationData.strings.Conversation_FileOpenIn
}
let actionSheet = ActionSheetController(presentationData: strongSelf.presentationData.withUpdated(theme: defaultDarkColorPresentationTheme))
let actionSheet = ActionSheetController(presentationData: presentationData)
var items: [ActionSheetItem] = []
items.append(ActionSheetTextItem(title: cleanUrl))
@ -707,7 +710,7 @@ public class GalleryController: ViewController, StandalonePresentableController
}
}))
if let phoneNumber = phoneNumber {
items.append(ActionSheetButtonItem(title: strongSelf.presentationData.strings.Conversation_AddContact, color: .accent, action: { [weak actionSheet] in
items.append(ActionSheetButtonItem(title: presentationData.strings.Conversation_AddContact, color: .accent, action: { [weak actionSheet] in
actionSheet?.dismissAnimated()
if let strongSelf = self {
strongSelf.dismiss(forceAway: false)
@ -715,7 +718,7 @@ public class GalleryController: ViewController, StandalonePresentableController
}
}))
}
items.append(ActionSheetButtonItem(title: canAddToReadingList ? strongSelf.presentationData.strings.ShareMenu_CopyShareLink : strongSelf.presentationData.strings.Conversation_ContextMenuCopy, color: .accent, action: { [weak actionSheet, weak self] in
items.append(ActionSheetButtonItem(title: canAddToReadingList ? presentationData.strings.ShareMenu_CopyShareLink : presentationData.strings.Conversation_ContextMenuCopy, color: .accent, action: { [weak actionSheet, weak self] in
actionSheet?.dismissAnimated()
UIPasteboard.general.string = cleanUrl
@ -732,7 +735,7 @@ public class GalleryController: ViewController, StandalonePresentableController
self?.present(UndoOverlayController(presentationData: presentationData, content: content, elevatedLayout: false, animateInAsReplacement: false, action: { _ in return false }), in: .window(.root))
}))
if canAddToReadingList {
items.append(ActionSheetButtonItem(title: strongSelf.presentationData.strings.Conversation_AddToReadingList, color: .accent, action: { [weak actionSheet] in
items.append(ActionSheetButtonItem(title: presentationData.strings.Conversation_AddToReadingList, color: .accent, action: { [weak actionSheet] in
actionSheet?.dismissAnimated()
if let link = URL(string: url) {
let _ = try? SSReadingList.default()?.addItem(with: link, title: nil, previewText: nil)
@ -740,13 +743,13 @@ public class GalleryController: ViewController, StandalonePresentableController
}))
}
actionSheet.setItemGroups([ActionSheetItemGroup(items: items), ActionSheetItemGroup(items: [
ActionSheetButtonItem(title: strongSelf.presentationData.strings.Common_Cancel, color: .accent, font: .bold, action: { [weak actionSheet] in
ActionSheetButtonItem(title: presentationData.strings.Common_Cancel, color: .accent, font: .bold, action: { [weak actionSheet] in
actionSheet?.dismissAnimated()
})
])])
strongSelf.present(actionSheet, in: .window(.root))
case let .peerMention(peerId, mention):
let actionSheet = ActionSheetController(presentationData: strongSelf.presentationData.withUpdated(theme: defaultDarkColorPresentationTheme))
let actionSheet = ActionSheetController(presentationData: presentationData)
var items: [ActionSheetItem] = []
if !mention.isEmpty {
items.append(ActionSheetTextItem(title: mention))
@ -774,7 +777,7 @@ public class GalleryController: ViewController, StandalonePresentableController
])])
strongSelf.present(actionSheet, in: .window(.root))
case let .textMention(mention):
let actionSheet = ActionSheetController(presentationData: strongSelf.presentationData.withUpdated(theme: defaultDarkColorPresentationTheme))
let actionSheet = ActionSheetController(presentationData: presentationData)
actionSheet.setItemGroups([ActionSheetItemGroup(items: [
ActionSheetTextItem(title: mention),
ActionSheetButtonItem(title: strongSelf.presentationData.strings.Conversation_LinkDialogOpen, color: .accent, action: { [weak actionSheet] in
@ -798,7 +801,7 @@ public class GalleryController: ViewController, StandalonePresentableController
])])
strongSelf.present(actionSheet, in: .window(.root))
case let .botCommand(command):
let actionSheet = ActionSheetController(presentationData: strongSelf.presentationData.withUpdated(theme: defaultDarkColorPresentationTheme))
let actionSheet = ActionSheetController(presentationData: presentationData)
var items: [ActionSheetItem] = []
items.append(ActionSheetTextItem(title: command))
items.append(ActionSheetButtonItem(title: strongSelf.presentationData.strings.Conversation_LinkDialogCopy, color: .accent, action: { [weak actionSheet, weak self] in
@ -815,7 +818,7 @@ public class GalleryController: ViewController, StandalonePresentableController
])])
strongSelf.present(actionSheet, in: .window(.root))
case let .hashtag(peerName, hashtag):
let actionSheet = ActionSheetController(presentationData: strongSelf.presentationData.withUpdated(theme: defaultDarkColorPresentationTheme))
let actionSheet = ActionSheetController(presentationData: presentationData)
actionSheet.setItemGroups([ActionSheetItemGroup(items: [
ActionSheetTextItem(title: hashtag),
ActionSheetButtonItem(title: strongSelf.presentationData.strings.Conversation_LinkDialogOpen, color: .accent, action: { [weak actionSheet] in
@ -840,7 +843,7 @@ public class GalleryController: ViewController, StandalonePresentableController
])
strongSelf.present(actionSheet, in: .window(.root))
case let .timecode(timecode, text):
let actionSheet = ActionSheetController(presentationData: strongSelf.presentationData.withUpdated(theme: defaultDarkColorPresentationTheme))
let actionSheet = ActionSheetController(presentationData: presentationData)
actionSheet.setItemGroups([ActionSheetItemGroup(items: [
ActionSheetTextItem(title: text),
ActionSheetButtonItem(title: strongSelf.presentationData.strings.Conversation_LinkDialogOpen, color: .accent, action: { [weak actionSheet] in

View File

@ -478,7 +478,7 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode {
pictureInPictureNode.updateLayout(placeholderSize, transition: transition)
}
}
if dismiss {
self.dismiss()
}
@ -488,7 +488,6 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode {
private var previousPlaying: Bool?
private func setupControlsTimer() {
return
let timer = SwiftSignalKit.Timer(timeout: 3.0, repeat: false, completion: { [weak self] in
self?.updateControlsVisibility(false)
self?.controlsTimer = nil
@ -504,14 +503,7 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode {
if item.hideControls {
self.statusButtonNode.isHidden = true
}
let dimensions = item.content.dimensions
if dimensions.height > 0.0 {
if dimensions.width / dimensions.height < 1.33 {
self.overlayContentNode.isHidden = true
}
}
self.dismissOnOrientationChange = item.landscape
var hasLinkedStickers = false
@ -546,6 +538,13 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode {
forceEnablePiP = true
}
let dimensions = item.content.dimensions
if dimensions.height > 0.0 {
if dimensions.width / dimensions.height < 1.33 || isAnimated {
self.overlayContentNode.isHidden = true
}
}
if let videoNode = self.videoNode {
videoNode.canAttachContent = false
videoNode.removeFromSupernode()

View File

@ -282,9 +282,14 @@ public class InstantPageGalleryController: ViewController, StandalonePresentable
openLinkOptionsImpl = { [weak self] url in
if let strongSelf = self {
var presentationData = strongSelf.presentationData
if !presentationData.theme.overallDarkAppearance {
presentationData = presentationData.withUpdated(theme: defaultDarkColorPresentationTheme)
}
let canOpenIn = availableOpenInOptions(context: context, item: .url(url: url.url)).count > 1
let openText = canOpenIn ? strongSelf.presentationData.strings.Conversation_FileOpenIn : strongSelf.presentationData.strings.Conversation_LinkDialogOpen
let actionSheet = ActionSheetController(presentationData: strongSelf.presentationData.withUpdated(theme: defaultDarkColorPresentationTheme))
let actionSheet = ActionSheetController(presentationData: presentationData)
actionSheet.setItemGroups([ActionSheetItemGroup(items: [
ActionSheetTextItem(title: url.url),
ActionSheetButtonItem(title: openText, color: .accent, action: { [weak actionSheet] in

View File

@ -20,6 +20,7 @@ swift_library(
"//submodules/ShareController:ShareController",
"//submodules/SelectablePeerNode:SelectablePeerNode",
"//submodules/PeerInfoUI:PeerInfoUI",
"//submodules/UndoUI:UndoUI",
],
visibility = [
"//visibility:public",

View File

@ -11,6 +11,7 @@ import AccountContext
import AlertUI
import PresentationDataUtils
import PeerInfoUI
import UndoUI
public final class JoinLinkPreviewController: ViewController {
private var controllerNode: JoinLinkPreviewControllerNode {
@ -87,7 +88,8 @@ public final class JoinLinkPreviewController: ViewController {
strongSelf.navigateToPeer(peerId, ChatPeekTimeout(deadline: deadline, linkData: strongSelf.link))
strongSelf.dismiss()
case .invalidHash:
strongSelf.present(textAlertController(context: strongSelf.context, title: nil, text: strongSelf.presentationData.strings.InviteLinks_InviteLinkExpired, actions: [TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.Common_OK, action: {})]), in: .window(.root))
let presentationData = strongSelf.context.sharedContext.currentPresentationData.with { $0 }
strongSelf.present(UndoOverlayController(presentationData: presentationData, content: .linkRevoked(text: presentationData.strings.InviteLinks_InviteLinkExpired), elevatedLayout: true, animateInAsReplacement: true, action: { _ in return false }), in: .window(.root))
strongSelf.dismiss()
}
}

View File

@ -1028,13 +1028,19 @@ static void setViewFrame(UIView *view, CGRect frame)
_associatedPanel.frame = associatedPanelFrame;
}
UIEdgeInsets inputFieldInsets = [self _inputFieldInsets];
UIEdgeInsets visibleInputFieldInsets = [self _inputFieldInsets];
if (self.isFirstResponder) {
inputFieldInsets.right += 41.0;
visibleInputFieldInsets.right += 41.0;
}
UIEdgeInsets actualInputFieldInsets = [self _inputFieldInsets];
actualInputFieldInsets.right += 41.0;
CGFloat inputContainerHeight = [self heightForInputFieldHeight:self.isFirstResponder ? _inputField.frame.size.height : 0];
setViewFrame(_fieldBackground, CGRectMake(inputFieldInsets.left, inputFieldInsets.top, frame.size.width - inputFieldInsets.left - inputFieldInsets.right, inputContainerHeight - inputFieldInsets.top - inputFieldInsets.bottom));
CGRect fieldBackgroundFrame = CGRectMake(visibleInputFieldInsets.left, visibleInputFieldInsets.top, frame.size.width - visibleInputFieldInsets.left - visibleInputFieldInsets.right, inputContainerHeight - visibleInputFieldInsets.top - visibleInputFieldInsets.bottom);
CGRect actualFieldBackgroundFrame = CGRectMake(actualInputFieldInsets.left, actualInputFieldInsets.top, frame.size.width - actualInputFieldInsets.left - actualInputFieldInsets.right, inputContainerHeight - actualInputFieldInsets.top - actualInputFieldInsets.bottom);
setViewFrame(_fieldBackground, fieldBackgroundFrame);
UIEdgeInsets inputFieldInternalEdgeInsets = [self _inputFieldInternalEdgeInsets];
CGRect onelineFrame = _fieldBackground.frame;
@ -1049,7 +1055,7 @@ static void setViewFrame(UIView *view, CGRect frame)
placeholderFrame.origin.x = onelineFrame.origin.x;
setViewFrame(_placeholderLabel, placeholderFrame);
CGRect inputFieldClippingFrame = _fieldBackground.frame;
CGRect inputFieldClippingFrame = actualFieldBackgroundFrame;
setViewFrame(_inputFieldClippingContainer, inputFieldClippingFrame);
CGFloat inputFieldWidth = _inputFieldClippingContainer.frame.size.width - inputFieldInternalEdgeInsets.left - 36;

View File

@ -185,7 +185,7 @@ public final class ListMessageFileItemNode: ListMessageNode {
private let playbackStatusDisposable = MetaDisposable()
private let playbackStatus = Promise<MediaPlayerStatus>()
private var downloadStatusIconNode: DownloadIconNode
private var downloadStatusIconNode: ASImageNode
private var linearProgressNode: LinearProgressNode?
private var context: AccountContext?
@ -247,7 +247,10 @@ public final class ListMessageFileItemNode: ListMessageNode {
self.iconStatusNode = SemanticStatusNode(backgroundNodeColor: .clear, foregroundNodeColor: .white)
self.iconStatusNode.isUserInteractionEnabled = false
self.downloadStatusIconNode = DownloadIconNode()
self.downloadStatusIconNode = ASImageNode()
self.downloadStatusIconNode.isLayerBacked = true
self.downloadStatusIconNode.displaysAsynchronously = false
self.downloadStatusIconNode.displayWithoutProcessing = true
self.restrictionNode = ASDisplayNode()
self.restrictionNode.isHidden = true
@ -736,8 +739,6 @@ public final class ListMessageFileItemNode: ListMessageNode {
strongSelf.linearProgressNode?.updateTheme(theme: item.presentationData.theme.theme)
strongSelf.restrictionNode.backgroundColor = item.presentationData.theme.theme.list.itemBlocksBackgroundColor.withAlphaComponent(0.6)
strongSelf.downloadStatusIconNode.customColor = item.presentationData.theme.theme.list.itemAccentColor
}
if let (selectionWidth, selectionApply) = selectionNodeWidthAndApply {
@ -849,7 +850,7 @@ public final class ListMessageFileItemNode: ListMessageNode {
}))
}
transition.updateFrame(node: strongSelf.downloadStatusIconNode, frame: CGRect(origin: CGPoint(x: leftOffset + leftInset - 3.0, y: strongSelf.descriptionNode.frame.minY + floor((strongSelf.descriptionNode.frame.height - 18.0) / 2.0)), size: CGSize(width: 18.0, height: 18.0)))
transition.updateFrame(node: strongSelf.downloadStatusIconNode, frame: CGRect(origin: CGPoint(x: leftOffset + leftInset, y: strongSelf.descriptionNode.frame.minY + floor((strongSelf.descriptionNode.frame.height - 12.0) / 2.0)), size: CGSize(width: 12.0, height: 12.0)))
if let updatedFetchControls = updatedFetchControls {
let _ = strongSelf.fetchControls.swap(updatedFetchControls)
@ -873,7 +874,7 @@ public final class ListMessageFileItemNode: ListMessageNode {
}
private func updateStatus(transition: ContainedViewLayoutTransition) {
guard let item = self.item, let media = self.currentMedia, let fetchStatus = self.fetchStatus, let status = self.resourceStatus, let layoutParams = self.layoutParams, let contentSize = self.contentSizeValue else {
guard let item = self.item, let media = self.currentMedia, let _ = self.fetchStatus, let status = self.resourceStatus, let layoutParams = self.layoutParams, let contentSize = self.contentSizeValue else {
return
}
@ -1015,12 +1016,10 @@ public final class ListMessageFileItemNode: ListMessageNode {
transition.updateFrame(node: linearProgressNode, frame: progressFrame)
linearProgressNode.updateProgress(value: CGFloat(progress), completion: {})
var animated = true
if self.downloadStatusIconNode.supernode == nil {
animated = false
self.offsetContainerNode.addSubnode(self.downloadStatusIconNode)
}
self.downloadStatusIconNode.enqueueState(.pause, animated: animated)
self.downloadStatusIconNode.image = PresentationResourcesChat.sharedMediaFileDownloadPauseIcon(item.presentationData.theme.theme)
case .Local:
if let linearProgressNode = self.linearProgressNode {
self.linearProgressNode = nil
@ -1033,6 +1032,7 @@ public final class ListMessageFileItemNode: ListMessageNode {
if self.downloadStatusIconNode.supernode != nil {
self.downloadStatusIconNode.removeFromSupernode()
}
self.downloadStatusIconNode.image = nil
case .Remote:
if let linearProgressNode = self.linearProgressNode {
self.linearProgressNode = nil
@ -1040,12 +1040,10 @@ public final class ListMessageFileItemNode: ListMessageNode {
linearProgressNode?.removeFromSupernode()
})
}
var animated = true
if self.downloadStatusIconNode.supernode == nil {
animated = false
self.offsetContainerNode.addSubnode(self.downloadStatusIconNode)
}
self.downloadStatusIconNode.enqueueState(.download, animated: animated)
self.downloadStatusIconNode.image = PresentationResourcesChat.sharedMediaFileDownloadStartIcon(item.presentationData.theme.theme)
}
} else {
if let linearProgressNode = self.linearProgressNode {

View File

@ -104,6 +104,9 @@ public func fetchExternalMusicAlbumArtResource(account: Account, resource: Exter
let metaUrl = "https://itunes.apple.com/search?term=\(urlEncodedStringFromString("\(performer) \(resource.title)"))&entity=song&limit=4"
let title = resource.title.lowercased()
let isMix = title.contains("remix") || title.contains("mixed")
let fetchDisposable = MetaDisposable()
let disposable = fetchHttpResource(url: metaUrl).start(next: { result in
@ -120,7 +123,23 @@ public func fetchExternalMusicAlbumArtResource(account: Account, resource: Exter
return
}
guard let result = results.first as? [String: Any] else {
var matchingResult: Any?
for result in results {
if let result = result as? [String: Any] {
let title = ((result["trackCensoredName"] as? String) ?? (result["trackName"] as? String))?.lowercased() ?? ""
let resultIsMix = title.contains("remix") || title.contains("mixed")
if isMix == resultIsMix {
matchingResult = result
break
}
}
}
if matchingResult == nil {
matchingResult = results.first
}
guard let result = matchingResult as? [String: Any] else {
subscriber.putNext(.dataPart(resourceOffset: 0, data: Data(), range: 0 ..< 0, complete: true))
subscriber.putCompletion()
return

View File

@ -856,6 +856,8 @@ open class TelegramBaseController: ViewController, KeyShortcutResponder {
let context = self.context
let presentationData = self.context.sharedContext.currentPresentationData.with { $0 }
self.view.endEditing(true)
self.context.joinGroupCall(peerId: peerId, invite: invite, requestJoinAsPeerId: { completion in
let currentAccountPeer = context.account.postbox.loadedPeerWithId(context.account.peerId)
|> map { peer in
@ -898,7 +900,10 @@ open class TelegramBaseController: ViewController, KeyShortcutResponder {
var items: [ActionSheetItem] = []
var isGroup = false
for peer in peers {
if let peer = peer.peer as? TelegramChannel, case .group = peer.info {
if peer.peer is TelegramGroup {
isGroup = true
break
} else if let peer = peer.peer as? TelegramChannel, case .group = peer.info {
isGroup = true
break
}

View File

@ -1219,6 +1219,8 @@ public final class VoiceChatController: ViewController {
let _ = strongSelf.call.updateMuteState(peerId: peer.id, isMuted: false)
f(.default)
strongSelf.presentUndoOverlay(content: .voiceChatCanSpeak(text: presentationData.strings.VoiceChat_UserCanNowSpeak(entry.peer.displayTitle(strings: strongSelf.presentationData.strings, displayOrder: strongSelf.presentationData.nameDisplayOrder)).0), action: { _ in return true })
})))
} else {
items.append(.action(ContextMenuActionItem(text: strongSelf.presentationData.strings.VoiceChat_MutePeer, icon: { theme in
@ -1265,8 +1267,8 @@ public final class VoiceChatController: ViewController {
openTitle = strongSelf.presentationData.strings.VoiceChat_OpenChannel
openIcon = UIImage(bundleImageName: "Chat/Context Menu/Channels")
} else {
openTitle = strongSelf.presentationData.strings.VoiceChat_OpenChat
openIcon = UIImage(bundleImageName: "Chat/Context Menu/Message")
openTitle = strongSelf.presentationData.strings.Conversation_ContextMenuOpenProfile
openIcon = UIImage(bundleImageName: "Chat/Context Menu/Info")
}
items.append(.action(ContextMenuActionItem(text: openTitle, icon: { theme in
return generateTintedImage(image: openIcon, color: theme.actionSheet.primaryTextColor)
@ -1277,7 +1279,7 @@ public final class VoiceChatController: ViewController {
let context = strongSelf.context
strongSelf.controller?.dismiss(completion: {
Queue.mainQueue().justDispatch {
Queue.mainQueue().after(0.3) {
if peer.id.namespace == Namespaces.Peer.CloudUser {
let _ = (strongSelf.context.account.postbox.loadedPeerWithId(peer.id)
|> take(1)
@ -1959,7 +1961,10 @@ public final class VoiceChatController: ViewController {
var isGroup = false
for peer in peers {
if let peer = peer.peer as? TelegramChannel, case .group = peer.info {
if peer.peer is TelegramGroup {
isGroup = true
break
} else if let peer = peer.peer as? TelegramChannel, case .group = peer.info {
isGroup = true
break
}

View File

@ -14,6 +14,7 @@ import PresentationDataUtils
import PeerInfoUI
import ShareController
import AvatarNode
import UndoUI
public final class VoiceChatJoinScreen: ViewController {
private var controllerNode: Node {
@ -152,7 +153,8 @@ public final class VoiceChatJoinScreen: ViewController {
strongSelf.controllerNode.setPeer(call: activeCall, peer: peer, title: call.info.title, memberCount: call.info.participantCount)
}
} else {
strongSelf.present(textAlertController(context: strongSelf.context, title: nil, text: strongSelf.presentationData.strings.InviteLinks_InviteLinkExpired, actions: [TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.Common_OK, action: {})]), in: .window(.root))
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
strongSelf.present(UndoOverlayController(presentationData: presentationData, content: .linkRevoked(text: presentationData.strings.InviteLinks_InviteLinkExpired), elevatedLayout: true, animateInAsReplacement: true, action: { _ in return false }), in: .window(.root))
strongSelf.dismiss()
}
}

View File

@ -16,6 +16,7 @@ public struct PresentationDateTimeFormat: Equatable {
public let dateFormat: PresentationDateFormat
public let dateSeparator: String
public let dateSuffix: String
public let requiresFullYear: Bool
public let decimalSeparator: String
public let groupingSeparator: String
@ -24,15 +25,17 @@ public struct PresentationDateTimeFormat: Equatable {
self.dateFormat = .monthFirst
self.dateSeparator = "."
self.dateSuffix = ""
self.requiresFullYear = false
self.decimalSeparator = "."
self.groupingSeparator = "."
}
public init(timeFormat: PresentationTimeFormat, dateFormat: PresentationDateFormat, dateSeparator: String, dateSuffix: String, decimalSeparator: String, groupingSeparator: String) {
public init(timeFormat: PresentationTimeFormat, dateFormat: PresentationDateFormat, dateSeparator: String, dateSuffix: String, requiresFullYear: Bool, decimalSeparator: String, groupingSeparator: String) {
self.timeFormat = timeFormat
self.dateFormat = dateFormat
self.dateSeparator = dateSeparator
self.dateSuffix = dateSuffix
self.requiresFullYear = requiresFullYear
self.decimalSeparator = decimalSeparator
self.groupingSeparator = groupingSeparator
}
@ -157,12 +160,14 @@ private func currentDateTimeFormat() -> PresentationDateTimeFormat {
let dateFormat: PresentationDateFormat
var dateSeparator = "/"
var dateSuffix = ""
var requiresFullYear = false
if let dateString = DateFormatter.dateFormat(fromTemplate: "MdY", options: 0, locale: locale) {
for separator in [". ", ".", "/", "-", "/"] {
if dateString.contains(separator) {
if separator == ". " {
dateSuffix = "."
dateSeparator = "."
requiresFullYear = true
} else {
dateSeparator = separator
}
@ -180,7 +185,7 @@ private func currentDateTimeFormat() -> PresentationDateTimeFormat {
let decimalSeparator = locale.decimalSeparator ?? "."
let groupingSeparator = locale.groupingSeparator ?? ""
return PresentationDateTimeFormat(timeFormat: timeFormat, dateFormat: dateFormat, dateSeparator: dateSeparator, dateSuffix: dateSuffix, decimalSeparator: decimalSeparator, groupingSeparator: groupingSeparator)
return PresentationDateTimeFormat(timeFormat: timeFormat, dateFormat: dateFormat, dateSeparator: dateSeparator, dateSuffix: dateSuffix, requiresFullYear: requiresFullYear, decimalSeparator: decimalSeparator, groupingSeparator: groupingSeparator)
}
private func currentPersonNameSortOrder() -> PresentationPersonNameOrder {

View File

@ -54,11 +54,12 @@ public func stringForMediumDate(timestamp: Int32, strings: PresentationStrings,
let dateString: String
let separator = dateTimeFormat.dateSeparator
let suffix = dateTimeFormat.dateSuffix
let displayYear = dateTimeFormat.requiresFullYear ? year - 100 + 2000 : year - 100
switch dateTimeFormat.dateFormat {
case .monthFirst:
dateString = String(format: "%02d%@%02d%@%02d%@", month, separator, day, separator, year - 100, suffix)
dateString = String(format: "%02d%@%02d%@%02d%@", month, separator, day, separator, displayYear, suffix)
case .dayFirst:
dateString = String(format: "%02d%@%02d%@%02d%@", day, separator, month, separator, year - 100, suffix)
dateString = String(format: "%02d%@%02d%@%02d%@", day, separator, month, separator, displayYear, suffix)
}
let timeString = stringForShortTimestamp(hours: Int32(timeinfo.tm_hour), minutes: Int32(timeinfo.tm_min), dateTimeFormat: dateTimeFormat)

View File

@ -7,11 +7,12 @@ import TelegramPresentationData
public func stringForTimestamp(day: Int32, month: Int32, year: Int32, dateTimeFormat: PresentationDateTimeFormat) -> String {
let separator = dateTimeFormat.dateSeparator
let suffix = dateTimeFormat.dateSuffix
let displayYear = dateTimeFormat.requiresFullYear ? year - 100 + 2000 : year - 100
switch dateTimeFormat.dateFormat {
case .monthFirst:
return String(format: "%02d%@%02d%@%02d%@", month, separator, day, separator, year - 100, suffix)
return String(format: "%02d%@%02d%@%02d%@", month, separator, day, separator, displayYear, suffix)
case .dayFirst:
return String(format: "%02d%@%02d%@%02d%@", day, separator, month, separator, year - 100, suffix)
return String(format: "%02d%@%02d%@%02d%@", day, separator, month, separator, displayYear, suffix)
}
}

View File

@ -35,6 +35,7 @@ class ContactSelectionControllerImpl: ViewController, ContactSelectionController
private let options: [ContactListAdditionalOption]
private let displayDeviceContacts: Bool
private let displayCallIcons: Bool
private let multipleSelection: Bool
private var _ready = Promise<Bool>()
override var ready: Promise<Bool> {
@ -77,6 +78,7 @@ class ContactSelectionControllerImpl: ViewController, ContactSelectionController
self.displayDeviceContacts = params.displayDeviceContacts
self.displayCallIcons = params.displayCallIcons
self.confirmation = params.confirmation
self.multipleSelection = params.multipleSelection
self.presentationData = context.sharedContext.currentPresentationData.with { $0 }
@ -154,7 +156,7 @@ class ContactSelectionControllerImpl: ViewController, ContactSelectionController
}
override func loadDisplayNode() {
self.displayNode = ContactSelectionControllerNode(context: self.context, options: self.options, displayDeviceContacts: self.displayDeviceContacts, displayCallIcons: self.displayCallIcons)
self.displayNode = ContactSelectionControllerNode(context: self.context, options: self.options, displayDeviceContacts: self.displayDeviceContacts, displayCallIcons: self.displayCallIcons, multipleSelection: self.multipleSelection)
self._ready.set(self.contactsNode.contactListNode.ready)
self.contactsNode.navigationBar = self.navigationBar

View File

@ -47,13 +47,13 @@ final class ContactSelectionControllerNode: ASDisplayNode {
private var selectionState: ContactListNodeGroupSelectionState?
init(context: AccountContext, options: [ContactListAdditionalOption], displayDeviceContacts: Bool, displayCallIcons: Bool) {
init(context: AccountContext, options: [ContactListAdditionalOption], displayDeviceContacts: Bool, displayCallIcons: Bool, multipleSelection: Bool) {
self.context = context
self.presentationData = context.sharedContext.currentPresentationData.with { $0 }
self.displayDeviceContacts = displayDeviceContacts
self.displayCallIcons = displayCallIcons
self.contactListNode = ContactListNode(context: context, presentation: .single(.natural(options: options, includeChatList: false)), displayCallIcons: displayCallIcons)
self.contactListNode = ContactListNode(context: context, presentation: .single(.natural(options: options, includeChatList: false)), displayCallIcons: displayCallIcons, multipleSelection: multipleSelection)
self.dimNode = ASDisplayNode()

View File

@ -1284,7 +1284,7 @@ private func editingItems(data: PeerInfoScreenData?, context: AccountContext, pr
}
} else {
if cachedData.flags.contains(.canChangeUsername) {
items[.peerPublicSettings]!.append(PeerInfoScreenDisclosureItem(id: ItemUsername, label: .text(isPublic ? presentationData.strings.Channel_Setup_TypePublic : presentationData.strings.Channel_Setup_TypePrivate), text: presentationData.strings.GroupInfo_GroupType, icon: UIImage(bundleImageName: "Chat/Info/GroupTypeIcon"), action: {
items[.peerPublicSettings]!.append(PeerInfoScreenDisclosureItem(id: ItemUsername, label: .text(isPublic ? presentationData.strings.Group_Setup_TypePublic : presentationData.strings.Group_Setup_TypePrivate), text: presentationData.strings.GroupInfo_GroupType, icon: UIImage(bundleImageName: "Chat/Info/GroupTypeIcon"), action: {
interaction.editingOpenPublicLinkSetup()
}))
}
@ -4365,7 +4365,10 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD
var isGroup = false
for peer in peers {
if let peer = peer.peer as? TelegramChannel, case .group = peer.info {
if peer.peer is TelegramGroup {
isGroup = true
break
} else if let peer = peer.peer as? TelegramChannel, case .group = peer.info {
isGroup = true
break
}

View File

@ -549,13 +549,21 @@ public func resolveUrlImpl(context: AccountContext, peerId: PeerId?, url: String
url = "http://\(url)"
}
}
Logger.shared.log("UrlHandling", "Resolving url: \(url)")
if let urlValue = URL(string: url), let host = urlValue.host?.lowercased() {
Logger.shared.log("UrlHandling", "created URL object")
Logger.shared.log("UrlHandling", "known domains are: \n\(urlHandlingConfiguration.domains.joined(separator: "\n"))")
if urlHandlingConfiguration.domains.contains(host), var components = URLComponents(string: url) {
components.scheme = "https"
var queryItems = components.queryItems ?? []
queryItems.append(URLQueryItem(name: "autologin_token", value: urlHandlingConfiguration.token))
components.queryItems = queryItems
url = components.url?.absoluteString ?? url
Logger.shared.log("UrlHandling", "host is in known domains")
Logger.shared.log("UrlHandling", "token is \(urlHandlingConfiguration.token ?? "nil")")
Logger.shared.log("UrlHandling", "url with token is \(url)")
} else if !skipUrlAuth && urlHandlingConfiguration.urlAuthDomains.contains(host) {
return .single(.urlAuth(url))
}