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

This commit is contained in:
Ilya Laktyushin 2021-01-25 13:27:58 +03:00
commit b920e3e2c9
10 changed files with 4201 additions and 4122 deletions

View File

@ -5932,3 +5932,29 @@ Sorry for the inconvenience.";
"Conversation.AudioRateTooltipSpeedUp" = "The audio will now play 2 times faster."; "Conversation.AudioRateTooltipSpeedUp" = "The audio will now play 2 times faster.";
"Conversation.AudioRateTooltipNormal" = "The audio will now play at normal speed."; "Conversation.AudioRateTooltipNormal" = "The audio will now play at normal speed.";
"ChatImport.Title" = "Import Chat";
"ChatImport.SelectionErrorNotAdmin" = "You need to be an admin of the group to import messages into it.";
"ChatImport.SelectionErrorGroupGeneric" = "You can't import history into this group.";
"ChatImport.SelectionConfirmationGroupWithTitle" = "Are you sure you want to import messages from **%1$@** into **%2$@**?";
"ChatImport.SelectionConfirmationGroupWithoutTitle" = "Are you sure you want to import messages into **%@**?";
"ChatImport.SelectionConfirmationAlertTitle" = "Import Messages";
"ChatImport.SelectionConfirmationAlertImportAction" = "Import";
"ChatImport.CreateGroupAlertTitle" = "Create Group and Import Messages";
"ChatImport.CreateGroupAlertText" = "Are you sure you want to create group **%@** and import messages from another messaging app?";
"ChatImport.CreateGroupAlertImportAction" = "Create and Import";
"ChatImport.UserErrorNotMutual" = "You can only import messages into private chats with users who added you in their contact list.";
"ChatImport.SelectionConfirmationUserWithTitle" = "Are you sure you want to import messages from **%1$@** into the chat with **%2$@**?";
"ChatImport.SelectionConfirmationUserWithoutTitle" = "Are you sure you want to import messages into the chat with **%@**?";
"PeerSelection.CreateNewGroup" = "Create a New Group";
"Message.ImportedDateFormat" = "%1$@, %2$@ Imported %3$@";
"ChatImportActivity.Title" = "Importing Chat";
"ChatImportActivity.OpenApp" = "Open Telegram";
"ChatImportActivity.Retry" = "Retry";
"ChatImportActivity.InProgress" = "Please keep this window open\nduring the import.";
"ChatImportActivity.ErrorNotAdmin" = "You need to be an admin.";
"ChatImportActivity.ErrorInvalidChatType" = "You can't import this history in this type of chat.";
"ChatImportActivity.ErrorGeneric" = "An error occurred.";
"ChatImportActivity.Success" = "This chat has been imported\nsuccessfully.";

View File

@ -24,6 +24,7 @@ swift_library(
"//submodules/MimeTypes:MimeTypes", "//submodules/MimeTypes:MimeTypes",
"//submodules/ConfettiEffect:ConfettiEffect", "//submodules/ConfettiEffect:ConfettiEffect",
"//submodules/TelegramUniversalVideoContent:TelegramUniversalVideoContent", "//submodules/TelegramUniversalVideoContent:TelegramUniversalVideoContent",
"//submodules/SolidRoundedButtonNode:SolidRoundedButtonNode",
], ],
visibility = [ visibility = [
"//visibility:public", "//visibility:public",

View File

@ -15,6 +15,7 @@ import ZIPFoundation
import MimeTypes import MimeTypes
import ConfettiEffect import ConfettiEffect
import TelegramUniversalVideoContent import TelegramUniversalVideoContent
import SolidRoundedButtonNode
public final class ChatImportActivityScreen: ViewController { public final class ChatImportActivityScreen: ViewController {
enum ImportError { enum ImportError {
@ -46,6 +47,7 @@ public final class ChatImportActivityScreen: ViewController {
private let statusButtonText: ImmediateTextNode private let statusButtonText: ImmediateTextNode
private let statusButton: HighlightableButtonNode private let statusButton: HighlightableButtonNode
private let doneButton: SolidRoundedButtonNode
private var validLayout: (ContainerViewLayout, CGFloat)? private var validLayout: (ContainerViewLayout, CGFloat)?
@ -100,6 +102,8 @@ public final class ChatImportActivityScreen: ViewController {
self.statusButton = HighlightableButtonNode() self.statusButton = HighlightableButtonNode()
self.doneButton = SolidRoundedButtonNode(title: self.presentationData.strings.ChatImportActivity_OpenApp, theme: SolidRoundedButtonTheme(backgroundColor: self.presentationData.theme.list.itemCheckColors.fillColor, foregroundColor: self.presentationData.theme.list.itemCheckColors.foregroundColor), height: 50.0, cornerRadius: 10.0, gloss: false)
super.init() super.init()
self.backgroundColor = self.presentationData.theme.list.plainBackgroundColor self.backgroundColor = self.presentationData.theme.list.plainBackgroundColor
@ -129,6 +133,7 @@ public final class ChatImportActivityScreen: ViewController {
self.addSubnode(self.statusText) self.addSubnode(self.statusText)
self.addSubnode(self.statusButtonText) self.addSubnode(self.statusButtonText)
self.addSubnode(self.statusButton) self.addSubnode(self.statusButton)
self.addSubnode(self.doneButton)
self.statusButton.addTarget(self, action: #selector(self.statusButtonPressed), forControlEvents: .touchUpInside) self.statusButton.addTarget(self, action: #selector(self.statusButtonPressed), forControlEvents: .touchUpInside)
self.statusButton.highligthedChanged = { [weak self] highlighted in self.statusButton.highligthedChanged = { [weak self] highlighted in
@ -167,6 +172,18 @@ public final class ChatImportActivityScreen: ViewController {
self.addSubnode(videoNode) self.addSubnode(videoNode)
videoNode.canAttachContent = true videoNode.canAttachContent = true
videoNode.play() videoNode.play()
self.doneButton.pressed = { [weak self] in
guard let strongSelf = self, let controller = strongSelf.controller else {
return
}
if let application = UIApplication.value(forKeyPath: #keyPath(UIApplication.shared)) as? UIApplication {
let selector = NSSelectorFromString("openURL:")
let url = URL(string: "tg://localpeer?id=\(controller.peerId.toInt64())")!
application.perform(selector, with: url)
}
}
} }
} }
@ -183,8 +200,6 @@ public final class ChatImportActivityScreen: ViewController {
let isFirstLayout = self.validLayout == nil let isFirstLayout = self.validLayout == nil
self.validLayout = (layout, navigationHeight) self.validLayout = (layout, navigationHeight)
//TODO:localize
let iconSize = CGSize(width: 170.0, height: 170.0) let iconSize = CGSize(width: 170.0, height: 170.0)
let radialStatusSize = CGSize(width: 186.0, height: 186.0) let radialStatusSize = CGSize(width: 186.0, height: 186.0)
let maxIconStatusSpacing: CGFloat = 62.0 let maxIconStatusSpacing: CGFloat = 62.0
@ -210,28 +225,28 @@ public final class ChatImportActivityScreen: ViewController {
switch self.state { switch self.state {
case .progress, .done: case .progress, .done:
self.statusButtonText.attributedText = NSAttributedString(string: "Done", font: Font.semibold(17.0), textColor: self.presentationData.theme.list.itemAccentColor) self.statusButtonText.attributedText = NSAttributedString(string: self.presentationData.strings.Common_Done, font: Font.semibold(17.0), textColor: self.presentationData.theme.list.itemAccentColor)
case .error: case .error:
self.statusButtonText.attributedText = NSAttributedString(string: "Retry", font: Font.semibold(17.0), textColor: self.presentationData.theme.list.itemAccentColor) self.statusButtonText.attributedText = NSAttributedString(string: self.presentationData.strings.ChatImportActivity_Retry, font: Font.semibold(17.0), textColor: self.presentationData.theme.list.itemAccentColor)
} }
let statusButtonTextSize = self.statusButtonText.updateLayout(CGSize(width: layout.size.width - 16.0 * 2.0, height: .greatestFiniteMagnitude)) let statusButtonTextSize = self.statusButtonText.updateLayout(CGSize(width: layout.size.width - 16.0 * 2.0, height: .greatestFiniteMagnitude))
switch self.state { switch self.state {
case .progress: case .progress:
self.statusText.attributedText = NSAttributedString(string: "Please keep this window open\nduring the import.", font: Font.regular(17.0), textColor: self.presentationData.theme.list.itemSecondaryTextColor) self.statusText.attributedText = NSAttributedString(string: self.presentationData.strings.ChatImportActivity_InProgress, font: Font.regular(17.0), textColor: self.presentationData.theme.list.itemSecondaryTextColor)
case let .error(error): case let .error(error):
let errorText: String let errorText: String
switch error { switch error {
case .chatAdminRequired: case .chatAdminRequired:
errorText = "You need to be an admin." errorText = self.presentationData.strings.ChatImportActivity_ErrorNotAdmin
case .invalidChatType: case .invalidChatType:
errorText = "You can't import this history in this type of chat." errorText = self.presentationData.strings.ChatImportActivity_ErrorGeneric
case .generic: case .generic:
errorText = "An error occurred." errorText = self.presentationData.strings.ChatImportActivity_ErrorInvalidChatType
} }
self.statusText.attributedText = NSAttributedString(string: errorText, font: Font.regular(17.0), textColor: self.presentationData.theme.list.itemDestructiveColor) self.statusText.attributedText = NSAttributedString(string: errorText, font: Font.regular(17.0), textColor: self.presentationData.theme.list.itemDestructiveColor)
case .done: case .done:
self.statusText.attributedText = NSAttributedString(string: "This chat has been imported\nsuccessfully.", font: Font.semibold(17.0), textColor: self.presentationData.theme.list.itemPrimaryTextColor) self.statusText.attributedText = NSAttributedString(string: self.presentationData.strings.ChatImportActivity_Success, font: Font.semibold(17.0), textColor: self.presentationData.theme.list.itemPrimaryTextColor)
} }
let statusTextSize = self.statusText.updateLayout(CGSize(width: layout.size.width - 16.0 * 2.0, height: .greatestFiniteMagnitude)) let statusTextSize = self.statusText.updateLayout(CGSize(width: layout.size.width - 16.0 * 2.0, height: .greatestFiniteMagnitude))
@ -240,7 +255,7 @@ public final class ChatImportActivityScreen: ViewController {
var hideIcon = false var hideIcon = false
if case .compact = layout.metrics.heightClass, layout.size.width > layout.size.height { if case .compact = layout.metrics.heightClass, layout.size.width > layout.size.height {
hideIcon = true hideIcon = true
contentHeight = radialStatusSize.height + maxProgressTextSpacing + progressTextSize.height + progressStatusSpacing + 100.0 contentHeight = radialStatusSize.height + maxProgressTextSpacing + progressTextSize.height + progressStatusSpacing + 140.0
} else { } else {
contentHeight = iconSize.height + maxIconStatusSpacing + radialStatusSize.height + maxProgressTextSpacing + progressTextSize.height + progressStatusSpacing + 100.0 contentHeight = iconSize.height + maxIconStatusSpacing + radialStatusSize.height + maxProgressTextSpacing + progressTextSize.height + progressStatusSpacing + 100.0
} }
@ -268,14 +283,30 @@ public final class ChatImportActivityScreen: ViewController {
self.statusText.frame = CGRect(origin: CGPoint(x: floor((layout.size.width - statusTextSize.width) / 2.0), y: self.progressText.frame.maxY + progressStatusSpacing), size: statusTextSize) self.statusText.frame = CGRect(origin: CGPoint(x: floor((layout.size.width - statusTextSize.width) / 2.0), y: self.progressText.frame.maxY + progressStatusSpacing), size: statusTextSize)
self.statusButtonText.isHidden = true self.statusButtonText.isHidden = true
self.statusButton.isHidden = true self.statusButton.isHidden = true
self.doneButton.isHidden = true
self.progressText.isHidden = false self.progressText.isHidden = false
} else { } else if case .error = self.state {
self.statusText.frame = CGRect(origin: CGPoint(x: floor((layout.size.width - statusTextSize.width) / 2.0), y: self.progressText.frame.minY), size: statusTextSize) self.statusText.frame = CGRect(origin: CGPoint(x: floor((layout.size.width - statusTextSize.width) / 2.0), y: self.progressText.frame.minY), size: statusTextSize)
self.statusButtonText.isHidden = false self.statusButtonText.isHidden = false
self.statusButton.isHidden = false self.statusButton.isHidden = false
self.doneButton.isHidden = true
self.progressText.isHidden = true
} else {
self.statusText.frame = CGRect(origin: CGPoint(x: floor((layout.size.width - statusTextSize.width) / 2.0), y: self.progressText.frame.minY), size: statusTextSize)
self.statusButtonText.isHidden = true
self.statusButton.isHidden = true
self.doneButton.isHidden = false
self.progressText.isHidden = true self.progressText.isHidden = true
} }
let buttonSideInset: CGFloat = 40.0
let buttonWidth = min(layout.size.width - buttonSideInset * 2.0, horizontalContainerFillingSizeForLayout(layout: layout, sideInset: buttonSideInset))
let buttonHeight = self.doneButton.updateLayout(width: buttonWidth, transition: .immediate)
let doneButtonFrame = CGRect(origin: CGPoint(x: floor((layout.size.width - buttonWidth) / 2.0), y: self.statusText.frame.maxY + statusButtonSpacing + 10.0), size: CGSize(width: buttonWidth, height: buttonHeight))
self.doneButton.frame = doneButtonFrame
let statusButtonTextFrame = CGRect(origin: CGPoint(x: floor((layout.size.width - statusButtonTextSize.width) / 2.0), y: self.statusText.frame.maxY + statusButtonSpacing), size: statusButtonTextSize) let statusButtonTextFrame = CGRect(origin: CGPoint(x: floor((layout.size.width - statusButtonTextSize.width) / 2.0), y: self.statusText.frame.maxY + statusButtonSpacing), size: statusButtonTextSize)
self.statusButtonText.frame = statusButtonTextFrame self.statusButtonText.frame = statusButtonTextFrame
self.statusButton.frame = statusButtonTextFrame.insetBy(dx: -10.0, dy: -10.0) self.statusButton.frame = statusButtonTextFrame.insetBy(dx: -10.0, dy: -10.0)
@ -351,7 +382,7 @@ public final class ChatImportActivityScreen: ViewController {
private let context: AccountContext private let context: AccountContext
private var presentationData: PresentationData private var presentationData: PresentationData
fileprivate let cancel: () -> Void fileprivate let cancel: () -> Void
private var peerId: PeerId fileprivate var peerId: PeerId
private let archive: Archive private let archive: Archive
private let mainEntry: TempBoxFile private let mainEntry: TempBoxFile
private let mainEntrySize: Int private let mainEntrySize: Int
@ -397,8 +428,7 @@ public final class ChatImportActivityScreen: ViewController {
super.init(navigationBarPresentationData: NavigationBarPresentationData(presentationData: self.presentationData, hideBackground: true, hideBadge: true)) super.init(navigationBarPresentationData: NavigationBarPresentationData(presentationData: self.presentationData, hideBackground: true, hideBadge: true))
//TODO:localize self.title = self.presentationData.strings.ChatImportActivity_Title
self.title = "Importing Chat"
self.navigationItem.setLeftBarButton(UIBarButtonItem(title: self.presentationData.strings.Common_Cancel, style: .plain, target: self, action: #selector(self.cancelPressed)), animated: false) self.navigationItem.setLeftBarButton(UIBarButtonItem(title: self.presentationData.strings.Common_Cancel, style: .plain, target: self, action: #selector(self.cancelPressed)), animated: false)

View File

@ -270,7 +270,7 @@ func fetchMessageHistoryHole(accountPeerId: PeerId, source: FetchMessageHistoryH
offsetId = start.id == Int32.max ? start.id : (start.id + 1) offsetId = start.id == Int32.max ? start.id : (start.id + 1)
addOffset = 0 addOffset = 0
maxId = start.id == Int32.max ? start.id : (start.id + 1) maxId = start.id == Int32.max ? start.id : (start.id + 1)
minId = end.id minId = end.id == 1 ? 0 : end.id
let rangeStartId = end.id let rangeStartId = end.id
let rangeEndId = min(start.id, Int32.max - 1) let rangeEndId = min(start.id, Int32.max - 1)

View File

@ -2968,6 +2968,8 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewItemNode
if item.effectiveAuthorId?.namespace == Namespaces.Peer.Empty { if item.effectiveAuthorId?.namespace == Namespaces.Peer.Empty {
item.controllerInteraction.displayMessageTooltip(item.content.firstMessage.id, item.presentationData.strings.Conversation_ForwardAuthorHiddenTooltip, self, avatarNode.frame) item.controllerInteraction.displayMessageTooltip(item.content.firstMessage.id, item.presentationData.strings.Conversation_ForwardAuthorHiddenTooltip, self, avatarNode.frame)
} else if let forwardInfo = item.content.firstMessage.forwardInfo, forwardInfo.flags.contains(.isImported), forwardInfo.author == nil {
item.controllerInteraction.displayImportedMessageTooltip(avatarNode)
} else { } else {
if item.message.id.peerId.isRepliesOrSavedMessages(accountPeerId: item.context.account.peerId), let channel = item.content.firstMessage.forwardInfo?.author as? TelegramChannel, channel.username == nil { if item.message.id.peerId.isRepliesOrSavedMessages(accountPeerId: item.context.account.peerId), let channel = item.content.firstMessage.forwardInfo?.author as? TelegramChannel, channel.username == nil {
if case let .broadcast(info) = channel.info, info.flags.contains(.hasDiscussionGroup) { if case let .broadcast(info) = channel.info, info.flags.contains(.hasDiscussionGroup) {

View File

@ -90,8 +90,7 @@ final class PeerSelectionControllerNode: ASDisplayNode {
var chatListcategories: [ChatListNodeAdditionalCategory] = [] var chatListcategories: [ChatListNodeAdditionalCategory] = []
if let _ = createNewGroup { if let _ = createNewGroup {
//TODO:localize chatListcategories.append(ChatListNodeAdditionalCategory(id: 0, icon: PresentationResourcesItemList.createGroupIcon(self.presentationData.theme), title: self.presentationData.strings.PeerSelection_CreateNewGroup, appearance: .action))
chatListcategories.append(ChatListNodeAdditionalCategory(id: 0, icon: PresentationResourcesItemList.createGroupIcon(self.presentationData.theme), title: "Create a New Group", appearance: .action))
} }
self.chatListNode = ChatListNode(context: context, groupId: .root, previewing: false, fillPreloadItems: false, mode: .peers(filter: filter, isSelecting: false, additionalCategories: chatListcategories, chatListFilters: nil), theme: self.presentationData.theme, fontSize: presentationData.listsFontSize, strings: presentationData.strings, dateTimeFormat: presentationData.dateTimeFormat, nameSortOrder: presentationData.nameSortOrder, nameDisplayOrder: presentationData.nameDisplayOrder, disableAnimations: presentationData.disableAnimations) self.chatListNode = ChatListNode(context: context, groupId: .root, previewing: false, fillPreloadItems: false, mode: .peers(filter: filter, isSelecting: false, additionalCategories: chatListcategories, chatListFilters: nil), theme: self.presentationData.theme, fontSize: presentationData.listsFontSize, strings: presentationData.strings, dateTimeFormat: presentationData.dateTimeFormat, nameSortOrder: presentationData.nameSortOrder, nameDisplayOrder: presentationData.nameDisplayOrder, disableAnimations: presentationData.disableAnimations)

View File

@ -387,12 +387,6 @@ public class ShareRootControllerImpl {
context.account.resetStateManagement() context.account.resetStateManagement()
} }
/*if let application = UIApplication.value(forKeyPath: #keyPath(UIApplication.shared)) as? UIApplication {
let selector = NSSelectorFromString("openURL:")
let url = URL(string: "tg://open")!
application.perform(selector, with: url)
}*/
if let strongSelf = self, let inputItems = strongSelf.getExtensionContext()?.inputItems, inputItems.count == 1, let item = inputItems[0] as? NSExtensionItem, let attachments = item.attachments { if let strongSelf = self, let inputItems = strongSelf.getExtensionContext()?.inputItems, inputItems.count == 1, let item = inputItems[0] as? NSExtensionItem, let attachments = item.attachments {
for attachment in attachments { for attachment in attachments {
if attachment.hasItemConformingToTypeIdentifier(kUTTypeFileURL as String) { if attachment.hasItemConformingToTypeIdentifier(kUTTypeFileURL as String) {
@ -505,8 +499,7 @@ public class ShareRootControllerImpl {
super.init(navigationBarPresentationData: NavigationBarPresentationData(presentationData: presentationData)) super.init(navigationBarPresentationData: NavigationBarPresentationData(presentationData: presentationData))
//TODO:localize self.title = presentationData.strings.ChatImport_Title
self.title = "Import Chat"
self.navigationItem.setLeftBarButton(UIBarButtonItem(title: presentationData.strings.Common_Cancel, style: .plain, target: self, action: #selector(self.cancelPressed)), animated: false) self.navigationItem.setLeftBarButton(UIBarButtonItem(title: presentationData.strings.Common_Cancel, style: .plain, target: self, action: #selector(self.cancelPressed)), animated: false)
} }
@ -542,10 +535,9 @@ public class ShareRootControllerImpl {
|> deliverOnMainQueue).start(next: { parseInfo in |> deliverOnMainQueue).start(next: { parseInfo in
switch parseInfo { switch parseInfo {
case let .group(groupTitle): case let .group(groupTitle):
//TODO:localize
var attemptSelectionImpl: ((Peer) -> Void)? var attemptSelectionImpl: ((Peer) -> Void)?
var createNewGroupImpl: (() -> Void)? var createNewGroupImpl: (() -> Void)?
let controller = context.sharedContext.makePeerSelectionController(PeerSelectionControllerParams(context: context, filter: [.onlyGroups, .onlyManageable, .excludeDisabled, .doNotSearchMessages], hasContactSelector: false, hasGlobalSearch: false, title: "Import Chat", attemptSelection: { peer in let controller = context.sharedContext.makePeerSelectionController(PeerSelectionControllerParams(context: context, filter: [.onlyGroups, .onlyManageable, .excludeDisabled, .doNotSearchMessages], hasContactSelector: false, hasGlobalSearch: false, title: presentationData.strings.ChatImport_Title, attemptSelection: { peer in
attemptSelectionImpl?(peer) attemptSelectionImpl?(peer)
}, createNewGroup: { }, createNewGroup: {
createNewGroupImpl?() createNewGroupImpl?()
@ -573,17 +565,17 @@ public class ShareRootControllerImpl {
if let channel = peer as? TelegramChannel { if let channel = peer as? TelegramChannel {
if channel.hasPermission(.changeInfo), (channel.flags.contains(.isCreator) || channel.adminRights != nil) { if channel.hasPermission(.changeInfo), (channel.flags.contains(.isCreator) || channel.adminRights != nil) {
} else { } else {
errorText = "You need to be an admin of the group to import messages into it." errorText = presentationData.strings.ChatImport_SelectionErrorNotAdmin
} }
} else if let group = peer as? TelegramGroup { } else if let group = peer as? TelegramGroup {
switch group.role { switch group.role {
case .creator: case .creator:
break break
default: default:
errorText = "You need to be an admin of the group to import messages into it." errorText = presentationData.strings.ChatImport_SelectionErrorNotAdmin
} }
} else { } else {
errorText = "You can't import history into this group." errorText = presentationData.strings.ChatImport_SelectionErrorGroupGeneric
} }
if let errorText = errorText { if let errorText = errorText {
@ -595,12 +587,12 @@ public class ShareRootControllerImpl {
let presentationData = internalContext.sharedContext.currentPresentationData.with { $0 } let presentationData = internalContext.sharedContext.currentPresentationData.with { $0 }
let text: String let text: String
if let groupTitle = groupTitle { if let groupTitle = groupTitle {
text = "Are you sure you want to import messages from **\(groupTitle)** into **\(peer.debugDisplayTitle)**?" text = presentationData.strings.ChatImport_SelectionConfirmationGroupWithTitle(groupTitle, peer.debugDisplayTitle).0
} else { } else {
text = "Are you sure you want to import messages into **\(peer.debugDisplayTitle)**?" text = presentationData.strings.ChatImport_SelectionConfirmationGroupWithoutTitle(peer.debugDisplayTitle).0
} }
let controller = standardTextAlertController(theme: AlertControllerTheme(presentationData: presentationData), title: "Import Messages", text: text, actions: [TextAlertAction(type: .genericAction, title: presentationData.strings.Common_Cancel, action: { let controller = standardTextAlertController(theme: AlertControllerTheme(presentationData: presentationData), title: presentationData.strings.ChatImport_SelectionConfirmationAlertTitle, text: text, actions: [TextAlertAction(type: .genericAction, title: presentationData.strings.Common_Cancel, action: {
}), TextAlertAction(type: .defaultAction, title: "Import", action: { }), TextAlertAction(type: .defaultAction, title: presentationData.strings.ChatImport_SelectionConfirmationAlertImportAction, action: {
beginWithPeer(peer.id) beginWithPeer(peer.id)
})], parseMarkdown: true) })], parseMarkdown: true)
strongSelf.mainWindow?.present(controller, on: .root) strongSelf.mainWindow?.present(controller, on: .root)
@ -615,7 +607,7 @@ public class ShareRootControllerImpl {
} else { } else {
resolvedGroupTitle = "Group" resolvedGroupTitle = "Group"
} }
let controller = standardTextAlertController(theme: AlertControllerTheme(presentationData: presentationData), title: "Create Group and Import Messages", text: "Are you sure you want to create group **\(resolvedGroupTitle)** and import messages from another messaging app?", actions: [TextAlertAction(type: .defaultAction, title: "Create and Import", action: { let controller = standardTextAlertController(theme: AlertControllerTheme(presentationData: presentationData), title: presentationData.strings.ChatImport_CreateGroupAlertTitle, text: presentationData.strings.ChatImport_CreateGroupAlertText(resolvedGroupTitle).0, actions: [TextAlertAction(type: .defaultAction, title: presentationData.strings.ChatImport_CreateGroupAlertImportAction, action: {
var signal: Signal<PeerId?, NoError> = createSupergroup(account: context.account, title: resolvedGroupTitle, description: nil, isForHistoryImport: true) var signal: Signal<PeerId?, NoError> = createSupergroup(account: context.account, title: resolvedGroupTitle, description: nil, isForHistoryImport: true)
|> map(Optional.init) |> map(Optional.init)
|> `catch` { _ -> Signal<PeerId?, NoError> in |> `catch` { _ -> Signal<PeerId?, NoError> in
@ -649,7 +641,6 @@ public class ShareRootControllerImpl {
if let peerId = peerId { if let peerId = peerId {
beginWithPeer(peerId) beginWithPeer(peerId)
} else { } else {
//TODO:localize
} }
}) })
}), TextAlertAction(type: .genericAction, title: presentationData.strings.Common_Cancel, action: { }), TextAlertAction(type: .genericAction, title: presentationData.strings.Common_Cancel, action: {
@ -661,9 +652,8 @@ public class ShareRootControllerImpl {
case let .privateChat(title): case let .privateChat(title):
let presentationData = internalContext.sharedContext.currentPresentationData.with { $0 } let presentationData = internalContext.sharedContext.currentPresentationData.with { $0 }
//TODO:localize
var attemptSelectionImpl: ((Peer) -> Void)? var attemptSelectionImpl: ((Peer) -> Void)?
let controller = context.sharedContext.makePeerSelectionController(PeerSelectionControllerParams(context: context, filter: [.onlyPrivateChats, .excludeDisabled, .doNotSearchMessages], hasChatListSelector: false, hasContactSelector: true, hasGlobalSearch: false, title: "Import Chat", attemptSelection: { peer in let controller = context.sharedContext.makePeerSelectionController(PeerSelectionControllerParams(context: context, filter: [.onlyPrivateChats, .excludeDisabled, .doNotSearchMessages], hasChatListSelector: false, hasContactSelector: true, hasGlobalSearch: false, title: presentationData.strings.ChatImport_Title, attemptSelection: { peer in
attemptSelectionImpl?(peer) attemptSelectionImpl?(peer)
}, pretendPresentedInModal: true)) }, pretendPresentedInModal: true))
@ -696,7 +686,7 @@ public class ShareRootControllerImpl {
case .generic: case .generic:
errorText = presentationData.strings.Login_UnknownError errorText = presentationData.strings.Login_UnknownError
case .userIsNotMutualContact: case .userIsNotMutualContact:
errorText = "You can only import messages into private chats with users who added you in their contact list." errorText = presentationData.strings.ChatImport_UserErrorNotMutual
} }
let controller = standardTextAlertController(theme: AlertControllerTheme(presentationData: presentationData), title: nil, text: errorText, actions: [TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_OK, action: { let controller = standardTextAlertController(theme: AlertControllerTheme(presentationData: presentationData), title: nil, text: errorText, actions: [TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_OK, action: {
})]) })])
@ -707,12 +697,12 @@ public class ShareRootControllerImpl {
let presentationData = internalContext.sharedContext.currentPresentationData.with { $0 } let presentationData = internalContext.sharedContext.currentPresentationData.with { $0 }
let text: String let text: String
if let title = title { if let title = title {
text = "Are you sure you want to import messages from **\(title)** into the chat with **\(peer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder))**?" text = presentationData.strings.ChatImport_SelectionConfirmationUserWithTitle(title, peer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder)).0
} else { } else {
text = "Are you sure you want to import messages into the chat with **\(peer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder))**?" text = presentationData.strings.ChatImport_SelectionConfirmationUserWithoutTitle(peer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder)).0
} }
let controller = standardTextAlertController(theme: AlertControllerTheme(presentationData: presentationData), title: "Import Messages", text: text, actions: [TextAlertAction(type: .genericAction, title: presentationData.strings.Common_Cancel, action: { let controller = standardTextAlertController(theme: AlertControllerTheme(presentationData: presentationData), title: presentationData.strings.ChatImport_SelectionConfirmationAlertTitle, text: text, actions: [TextAlertAction(type: .genericAction, title: presentationData.strings.Common_Cancel, action: {
}), TextAlertAction(type: .defaultAction, title: "Import", action: { }), TextAlertAction(type: .defaultAction, title: presentationData.strings.ChatImport_SelectionConfirmationAlertImportAction, action: {
beginWithPeer(peer.id) beginWithPeer(peer.id)
})], parseMarkdown: true) })], parseMarkdown: true)
strongSelf.mainWindow?.present(controller, on: .root) strongSelf.mainWindow?.present(controller, on: .root)
@ -721,10 +711,9 @@ public class ShareRootControllerImpl {
navigationController.viewControllers = [controller] navigationController.viewControllers = [controller]
case let .unknown(peerTitle): case let .unknown(peerTitle):
//TODO:localize
var attemptSelectionImpl: ((Peer) -> Void)? var attemptSelectionImpl: ((Peer) -> Void)?
var createNewGroupImpl: (() -> Void)? var createNewGroupImpl: (() -> Void)?
let controller = context.sharedContext.makePeerSelectionController(PeerSelectionControllerParams(context: context, filter: [.excludeDisabled, .doNotSearchMessages], hasContactSelector: true, hasGlobalSearch: false, title: "Import Chat", attemptSelection: { peer in let controller = context.sharedContext.makePeerSelectionController(PeerSelectionControllerParams(context: context, filter: [.excludeDisabled, .doNotSearchMessages], hasContactSelector: true, hasGlobalSearch: false, title: presentationData.strings.ChatImport_Title, attemptSelection: { peer in
attemptSelectionImpl?(peer) attemptSelectionImpl?(peer)
}, createNewGroup: { }, createNewGroup: {
createNewGroupImpl?() createNewGroupImpl?()
@ -759,7 +748,7 @@ public class ShareRootControllerImpl {
case .generic: case .generic:
errorText = presentationData.strings.Login_UnknownError errorText = presentationData.strings.Login_UnknownError
case .userIsNotMutualContact: case .userIsNotMutualContact:
errorText = "You can only import messages into private chats with users who added you in their contact list." errorText = presentationData.strings.ChatImport_UserErrorNotMutual
} }
let controller = standardTextAlertController(theme: AlertControllerTheme(presentationData: presentationData), title: nil, text: errorText, actions: [TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_OK, action: { let controller = standardTextAlertController(theme: AlertControllerTheme(presentationData: presentationData), title: nil, text: errorText, actions: [TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_OK, action: {
})]) })])
@ -773,18 +762,18 @@ public class ShareRootControllerImpl {
if let channel = peer as? TelegramChannel { if let channel = peer as? TelegramChannel {
if channel.hasPermission(.changeInfo), (channel.flags.contains(.isCreator) || channel.adminRights != nil) { if channel.hasPermission(.changeInfo), (channel.flags.contains(.isCreator) || channel.adminRights != nil) {
} else { } else {
errorText = "You need to be an admin of the group to import messages into it." errorText = presentationData.strings.ChatImport_SelectionErrorNotAdmin
} }
} else if let group = peer as? TelegramGroup { } else if let group = peer as? TelegramGroup {
switch group.role { switch group.role {
case .creator: case .creator:
break break
default: default:
errorText = "You need to be an admin of the group to import messages into it." errorText = presentationData.strings.ChatImport_SelectionErrorNotAdmin
} }
} else if let _ = peer as? TelegramUser { } else if let _ = peer as? TelegramUser {
} else { } else {
errorText = "You can't import history into this group." errorText = presentationData.strings.ChatImport_SelectionErrorGroupGeneric
} }
if let errorText = errorText { if let errorText = errorText {
@ -797,24 +786,24 @@ public class ShareRootControllerImpl {
if let user = peer as? TelegramUser { if let user = peer as? TelegramUser {
let text: String let text: String
if let title = peerTitle { if let title = peerTitle {
text = "Are you sure you want to import messages from **\(title)** into the chat with **\(peer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder))**?" text = presentationData.strings.ChatImport_SelectionConfirmationUserWithTitle(title, peer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder)).0
} else { } else {
text = "Are you sure you want to import messages into the chat with **\(peer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder))**?" text = presentationData.strings.ChatImport_SelectionConfirmationUserWithoutTitle(peer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder)).0
} }
let controller = standardTextAlertController(theme: AlertControllerTheme(presentationData: presentationData), title: "Import Messages", text: text, actions: [TextAlertAction(type: .genericAction, title: presentationData.strings.Common_Cancel, action: { let controller = standardTextAlertController(theme: AlertControllerTheme(presentationData: presentationData), title: presentationData.strings.ChatImport_SelectionConfirmationAlertTitle, text: text, actions: [TextAlertAction(type: .genericAction, title: presentationData.strings.Common_Cancel, action: {
}), TextAlertAction(type: .defaultAction, title: "Import", action: { }), TextAlertAction(type: .defaultAction, title: presentationData.strings.ChatImport_SelectionConfirmationAlertImportAction, action: {
beginWithPeer(peer.id) beginWithPeer(peer.id)
})], parseMarkdown: true) })], parseMarkdown: true)
strongSelf.mainWindow?.present(controller, on: .root) strongSelf.mainWindow?.present(controller, on: .root)
} else { } else {
let text: String let text: String
if let groupTitle = peerTitle { if let groupTitle = peerTitle {
text = "Are you sure you want to import messages from **\(groupTitle)** into **\(peer.debugDisplayTitle)**?" text = presentationData.strings.ChatImport_SelectionConfirmationGroupWithTitle(groupTitle, peer.debugDisplayTitle).0
} else { } else {
text = "Are you sure you want to import messages into **\(peer.debugDisplayTitle)**?" text = presentationData.strings.ChatImport_SelectionConfirmationGroupWithoutTitle(peer.debugDisplayTitle).0
} }
let controller = standardTextAlertController(theme: AlertControllerTheme(presentationData: presentationData), title: "Import Messages", text: text, actions: [TextAlertAction(type: .genericAction, title: presentationData.strings.Common_Cancel, action: { let controller = standardTextAlertController(theme: AlertControllerTheme(presentationData: presentationData), title: presentationData.strings.ChatImport_SelectionConfirmationAlertTitle, text: text, actions: [TextAlertAction(type: .genericAction, title: presentationData.strings.Common_Cancel, action: {
}), TextAlertAction(type: .defaultAction, title: "Import", action: { }), TextAlertAction(type: .defaultAction, title: presentationData.strings.ChatImport_SelectionConfirmationAlertImportAction, action: {
beginWithPeer(peer.id) beginWithPeer(peer.id)
})], parseMarkdown: true) })], parseMarkdown: true)
strongSelf.mainWindow?.present(controller, on: .root) strongSelf.mainWindow?.present(controller, on: .root)
@ -831,7 +820,7 @@ public class ShareRootControllerImpl {
} else { } else {
resolvedGroupTitle = "Group" resolvedGroupTitle = "Group"
} }
let controller = standardTextAlertController(theme: AlertControllerTheme(presentationData: presentationData), title: "Create Group and Import Messages", text: "Are you sure you want to create group **\(resolvedGroupTitle)** and import messages from another messaging app?", actions: [TextAlertAction(type: .defaultAction, title: "Create and Import", action: { let controller = standardTextAlertController(theme: AlertControllerTheme(presentationData: presentationData), title: presentationData.strings.ChatImport_CreateGroupAlertTitle, text: presentationData.strings.ChatImport_CreateGroupAlertText(resolvedGroupTitle).0, actions: [TextAlertAction(type: .defaultAction, title: presentationData.strings.ChatImport_CreateGroupAlertImportAction, action: {
var signal: Signal<PeerId?, NoError> = createSupergroup(account: context.account, title: resolvedGroupTitle, description: nil, isForHistoryImport: true) var signal: Signal<PeerId?, NoError> = createSupergroup(account: context.account, title: resolvedGroupTitle, description: nil, isForHistoryImport: true)
|> map(Optional.init) |> map(Optional.init)
|> `catch` { _ -> Signal<PeerId?, NoError> in |> `catch` { _ -> Signal<PeerId?, NoError> in
@ -865,7 +854,6 @@ public class ShareRootControllerImpl {
if let peerId = peerId { if let peerId = peerId {
beginWithPeer(peerId) beginWithPeer(peerId)
} else { } else {
//TODO:localize
} }
}) })
}), TextAlertAction(type: .genericAction, title: presentationData.strings.Common_Cancel, action: { }), TextAlertAction(type: .genericAction, title: presentationData.strings.Common_Cancel, action: {

View File

@ -42,9 +42,7 @@ func stringForMessageTimestampStatus(accountPeerId: PeerId, message: Message, da
} }
if let forwardInfo = message.forwardInfo, forwardInfo.flags.contains(.isImported) { if let forwardInfo = message.forwardInfo, forwardInfo.flags.contains(.isImported) {
//TODO:localize dateText = strings.Message_ImportedDateFormat(dateStringForDay(strings: strings, dateTimeFormat: dateTimeFormat, timestamp: forwardInfo.date), stringForMessageTimestamp(timestamp: forwardInfo.date, dateTimeFormat: dateTimeFormat), dateText).0
dateText = dateStringForDay(strings: strings, dateTimeFormat: dateTimeFormat, timestamp: forwardInfo.date) + ", " + stringForMessageTimestamp(timestamp: forwardInfo.date, dateTimeFormat: dateTimeFormat) + " Imported " + dateText
} }
var authorTitle: String? var authorTitle: String?