mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
Merge branch 'master' of gitlab.com:peter-iakovlev/telegram-ios
This commit is contained in:
commit
752a21d486
@ -21,6 +21,7 @@ swift_library(
|
||||
"//submodules/RadialStatusNode:RadialStatusNode",
|
||||
"//submodules/AnimatedStickerNode:AnimatedStickerNode",
|
||||
"//submodules/ChatHistoryImportTasks:ChatHistoryImportTasks",
|
||||
"//submodules/MimeTypes:MimeTypes",
|
||||
],
|
||||
visibility = [
|
||||
"//visibility:public",
|
||||
|
@ -12,6 +12,7 @@ import RadialStatusNode
|
||||
import AnimatedStickerNode
|
||||
import AppBundle
|
||||
import ZIPFoundation
|
||||
import MimeTypes
|
||||
|
||||
public final class ChatImportActivityScreen: ViewController {
|
||||
private final class Node: ViewControllerTracingNode {
|
||||
@ -191,7 +192,7 @@ public final class ChatImportActivityScreen: ViewController {
|
||||
|
||||
if let (layout, navigationHeight) = self.validLayout {
|
||||
self.containerLayoutUpdated(layout, navigationHeight: navigationHeight, transition: .immediate)
|
||||
self.radialStatus.transitionToState(.progress(color: self.presentationData.theme.list.itemAccentColor, lineWidth: 6.0, value: max(0.09, self.totalProgress), cancelEnabled: false), animated: animated, synchronous: true, completion: {})
|
||||
self.radialStatus.transitionToState(.progress(color: self.presentationData.theme.list.itemAccentColor, lineWidth: 6.0, value: max(0.02, self.totalProgress), cancelEnabled: false), animated: animated, synchronous: true, completion: {})
|
||||
if isDone {
|
||||
self.radialCheck.transitionToState(.progress(color: .clear, lineWidth: 6.0, value: self.totalProgress, cancelEnabled: false), animated: false, synchronous: true, completion: {})
|
||||
self.radialCheck.transitionToState(.check(self.presentationData.theme.list.itemAccentColor), animated: animated, synchronous: true, completion: {})
|
||||
@ -362,7 +363,15 @@ public final class ChatImportActivityScreen: ViewController {
|
||||
}
|
||||
let uploadedMedia = unpackedFile
|
||||
|> mapToSignal { tempFile -> Signal<(String, Float), ImportError> in
|
||||
return ChatHistoryImport.uploadMedia(account: context.account, session: session, file: tempFile, fileName: fileName, type: mediaType)
|
||||
var mimeTypeValue = "application/binary"
|
||||
let fileExtension = (tempFile.path as NSString).pathExtension
|
||||
if !fileExtension.isEmpty {
|
||||
if let value = TGMimeTypeMap.mimeType(forExtension: fileExtension.lowercased()) {
|
||||
mimeTypeValue = value
|
||||
}
|
||||
}
|
||||
|
||||
return ChatHistoryImport.uploadMedia(account: context.account, session: session, file: tempFile, fileName: fileName, mimeType: mimeTypeValue, type: mediaType)
|
||||
|> mapError { _ -> ImportError in
|
||||
return .generic
|
||||
}
|
||||
|
@ -1351,6 +1351,9 @@ open class NavigationController: UINavigationController, ContainableController,
|
||||
}
|
||||
|
||||
override open func dismiss(animated flag: Bool, completion: (() -> Void)? = nil) {
|
||||
if let presentingViewController = self.presentingViewController {
|
||||
presentingViewController.dismiss(animated: false, completion: nil)
|
||||
}
|
||||
if let controller = self.presentedViewController {
|
||||
if flag {
|
||||
UIView.animate(withDuration: 0.3, delay: 0.0, options: UIView.AnimationOptions(rawValue: 7 << 16), animations: {
|
||||
|
@ -460,7 +460,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
|
||||
dict[649453030] = { return Api.messages.MessageEditData.parse_messageEditData($0) }
|
||||
dict[-886477832] = { return Api.LabeledPrice.parse_labeledPrice($0) }
|
||||
dict[-438840932] = { return Api.messages.ChatFull.parse_chatFull($0) }
|
||||
dict[-1919636670] = { return Api.messages.HistoryImportParsed.parse_historyImportParsed($0) }
|
||||
dict[1578088377] = { return Api.messages.HistoryImportParsed.parse_historyImportParsed($0) }
|
||||
dict[-618540889] = { return Api.InputSecureValue.parse_inputSecureValue($0) }
|
||||
dict[-170029155] = { return Api.messages.DiscussionMessage.parse_discussionMessage($0) }
|
||||
dict[1722786150] = { return Api.help.DeepLinkInfo.parse_deepLinkInfoEmpty($0) }
|
||||
|
@ -985,10 +985,10 @@ public struct messages {
|
||||
switch self {
|
||||
case .historyImportParsed(let flags, let title):
|
||||
if boxed {
|
||||
buffer.appendInt32(-1919636670)
|
||||
buffer.appendInt32(1578088377)
|
||||
}
|
||||
serializeInt32(flags, buffer: buffer, boxed: false)
|
||||
if Int(flags) & Int(1 << 1) != 0 {serializeString(title!, buffer: buffer, boxed: false)}
|
||||
if Int(flags) & Int(1 << 2) != 0 {serializeString(title!, buffer: buffer, boxed: false)}
|
||||
break
|
||||
}
|
||||
}
|
||||
@ -1004,9 +1004,9 @@ public struct messages {
|
||||
var _1: Int32?
|
||||
_1 = reader.readInt32()
|
||||
var _2: String?
|
||||
if Int(_1!) & Int(1 << 1) != 0 {_2 = parseString(reader) }
|
||||
if Int(_1!) & Int(1 << 2) != 0 {_2 = parseString(reader) }
|
||||
let _c1 = _1 != nil
|
||||
let _c2 = (Int(_1!) & Int(1 << 1) == 0) || _2 != nil
|
||||
let _c2 = (Int(_1!) & Int(1 << 2) == 0) || _2 != nil
|
||||
if _c1 && _c2 {
|
||||
return Api.messages.HistoryImportParsed.historyImportParsed(flags: _1!, title: _2)
|
||||
}
|
||||
|
@ -19,6 +19,7 @@ public enum ChatHistoryImport {
|
||||
public enum ParsedInfo {
|
||||
case privateChat(title: String?)
|
||||
case group(title: String?)
|
||||
case unknown(title: String?)
|
||||
}
|
||||
|
||||
public enum GetInfoError {
|
||||
@ -39,7 +40,7 @@ public enum ChatHistoryImport {
|
||||
} else if (flags & (1 << 1)) != 0 {
|
||||
return .single(.group(title: title))
|
||||
} else {
|
||||
return .fail(.parseError)
|
||||
return .single(.unknown(title: title))
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -92,7 +93,7 @@ public enum ChatHistoryImport {
|
||||
case generic
|
||||
}
|
||||
|
||||
public static func uploadMedia(account: Account, session: Session, file: TempBoxFile, fileName: String, type: MediaType) -> Signal<Float, UploadMediaError> {
|
||||
public static func uploadMedia(account: Account, session: Session, file: TempBoxFile, fileName: String, mimeType: String, type: MediaType) -> Signal<Float, UploadMediaError> {
|
||||
return multipartUpload(network: account.network, postbox: account.postbox, source: .tempFile(file), encrypt: false, tag: nil, hintFileSize: nil, hintFileIsLarge: false)
|
||||
|> mapError { _ -> UploadMediaError in
|
||||
return .generic
|
||||
@ -107,18 +108,18 @@ public enum ChatHistoryImport {
|
||||
case .file, .video, .sticker, .voice:
|
||||
var attributes: [Api.DocumentAttribute] = []
|
||||
attributes.append(.documentAttributeFilename(fileName: fileName))
|
||||
var mimeType = "application/octet-stream"
|
||||
var resolvedMimeType = mimeType
|
||||
switch type {
|
||||
case .video:
|
||||
mimeType = "video/mp4"
|
||||
resolvedMimeType = "video/mp4"
|
||||
case .sticker:
|
||||
mimeType = "image/webp"
|
||||
resolvedMimeType = "image/webp"
|
||||
case .voice:
|
||||
mimeType = "audio/ogg"
|
||||
resolvedMimeType = "audio/ogg"
|
||||
default:
|
||||
break
|
||||
}
|
||||
inputMedia = .inputMediaUploadedDocument(flags: 0, file: inputFile, thumb: nil, mimeType: mimeType, attributes: attributes, stickers: nil, ttlSeconds: nil)
|
||||
inputMedia = .inputMediaUploadedDocument(flags: 0, file: inputFile, thumb: nil, mimeType: resolvedMimeType, attributes: attributes, stickers: nil, ttlSeconds: nil)
|
||||
}
|
||||
case let .progress(value):
|
||||
return .single(value)
|
||||
|
@ -85,6 +85,8 @@ public class ShareRootControllerImpl {
|
||||
private var observer1: AnyObject?
|
||||
private var observer2: AnyObject?
|
||||
|
||||
private weak var navigationController: NavigationController?
|
||||
|
||||
public init(initializationData: ShareRootControllerInitializationData, getExtensionContext: @escaping () -> NSExtensionContext?) {
|
||||
self.initializationData = initializationData
|
||||
self.getExtensionContext = getExtensionContext
|
||||
@ -374,6 +376,9 @@ public class ShareRootControllerImpl {
|
||||
if let currentShareController = strongSelf.currentShareController {
|
||||
currentShareController.dismiss()
|
||||
}
|
||||
if let navigationController = strongSelf.navigationController {
|
||||
navigationController.dismiss(animated: false)
|
||||
}
|
||||
strongSelf.currentShareController = shareController
|
||||
strongSelf.mainWindow?.present(shareController, on: .root)
|
||||
}
|
||||
@ -491,6 +496,7 @@ public class ShareRootControllerImpl {
|
||||
|
||||
let presentationData = internalContext.sharedContext.currentPresentationData.with { $0 }
|
||||
let navigationController = NavigationController(mode: .single, theme: NavigationControllerTheme(presentationTheme: presentationData.theme))
|
||||
strongSelf.navigationController = navigationController
|
||||
navigationController.viewControllers = [TempController(context: context)]
|
||||
strongSelf.mainWindow?.present(navigationController, on: .root)
|
||||
|
||||
@ -677,6 +683,161 @@ public class ShareRootControllerImpl {
|
||||
})
|
||||
}
|
||||
|
||||
navigationController.viewControllers = [controller]
|
||||
strongSelf.mainWindow?.present(navigationController, on: .root)
|
||||
case let .unknown(peerTitle):
|
||||
//TODO:localize
|
||||
var attemptSelectionImpl: ((Peer) -> 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
|
||||
attemptSelectionImpl?(peer)
|
||||
}, createNewGroup: {
|
||||
createNewGroupImpl?()
|
||||
}, pretendPresentedInModal: true))
|
||||
|
||||
controller.customDismiss = {
|
||||
self?.getExtensionContext()?.completeRequest(returningItems: nil, completionHandler: nil)
|
||||
}
|
||||
|
||||
controller.peerSelected = { peer in
|
||||
attemptSelectionImpl?(peer)
|
||||
}
|
||||
|
||||
controller.navigationPresentation = .default
|
||||
|
||||
let beginWithPeer: (PeerId) -> Void = { peerId in
|
||||
navigationController.view.endEditing(true)
|
||||
navigationController.pushViewController(ChatImportActivityScreen(context: context, cancel: {
|
||||
self?.getExtensionContext()?.completeRequest(returningItems: nil, completionHandler: nil)
|
||||
}, peerId: peerId, archive: archive, mainEntry: mainFile, otherEntries: otherEntries))
|
||||
}
|
||||
|
||||
attemptSelectionImpl = { [weak controller] peer in
|
||||
controller?.inProgress = true
|
||||
let _ = (ChatHistoryImport.checkPeerImport(account: context.account, peerId: peer.id)
|
||||
|> deliverOnMainQueue).start(error: { error in
|
||||
controller?.inProgress = false
|
||||
|
||||
let presentationData = internalContext.sharedContext.currentPresentationData.with { $0 }
|
||||
let errorText: String
|
||||
switch error {
|
||||
case .generic:
|
||||
errorText = presentationData.strings.Login_UnknownError
|
||||
case .userIsNotMutualContact:
|
||||
errorText = "You can only import messages into private chats with users who added you in their contact list."
|
||||
}
|
||||
let controller = standardTextAlertController(theme: AlertControllerTheme(presentationData: presentationData), title: nil, text: errorText, actions: [TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_OK, action: {
|
||||
})])
|
||||
strongSelf.mainWindow?.present(controller, on: .root)
|
||||
}, completed: {
|
||||
controller?.inProgress = false
|
||||
|
||||
let presentationData = internalContext.sharedContext.currentPresentationData.with { $0 }
|
||||
|
||||
var errorText: String?
|
||||
if let channel = peer as? TelegramChannel {
|
||||
if channel.flags.contains(.isCreator) || channel.adminRights != nil {
|
||||
} else {
|
||||
errorText = "You need to be an admin of the group to import messages into it."
|
||||
}
|
||||
} else if let group = peer as? TelegramGroup {
|
||||
switch group.role {
|
||||
case .creator:
|
||||
break
|
||||
default:
|
||||
errorText = "You need to be an admin of the group to import messages into it."
|
||||
}
|
||||
} else if let _ = peer as? TelegramUser {
|
||||
} else {
|
||||
errorText = "You can't import history into this group."
|
||||
}
|
||||
|
||||
if let errorText = errorText {
|
||||
let presentationData = internalContext.sharedContext.currentPresentationData.with { $0 }
|
||||
let controller = standardTextAlertController(theme: AlertControllerTheme(presentationData: presentationData), title: nil, text: errorText, actions: [TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_OK, action: {
|
||||
})])
|
||||
strongSelf.mainWindow?.present(controller, on: .root)
|
||||
} else {
|
||||
let presentationData = internalContext.sharedContext.currentPresentationData.with { $0 }
|
||||
if let user = peer as? TelegramUser {
|
||||
let text: String
|
||||
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))**?"
|
||||
} else {
|
||||
text = "Are you sure you want to import messages into the chat with **\(peer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder))**?"
|
||||
}
|
||||
let controller = standardTextAlertController(theme: AlertControllerTheme(presentationData: presentationData), title: "Import Messages", text: text, actions: [TextAlertAction(type: .genericAction, title: presentationData.strings.Common_Cancel, action: {
|
||||
}), TextAlertAction(type: .defaultAction, title: "Import", action: {
|
||||
beginWithPeer(peer.id)
|
||||
})], parseMarkdown: true)
|
||||
strongSelf.mainWindow?.present(controller, on: .root)
|
||||
} else {
|
||||
let text: String
|
||||
if let groupTitle = peerTitle {
|
||||
text = "Are you sure you want to import messages from **\(groupTitle)** into **\(peer.debugDisplayTitle)**?"
|
||||
} else {
|
||||
text = "Are you sure you want to import messages into **\(peer.debugDisplayTitle)**?"
|
||||
}
|
||||
let controller = standardTextAlertController(theme: AlertControllerTheme(presentationData: presentationData), title: "Import Messages", text: text, actions: [TextAlertAction(type: .genericAction, title: presentationData.strings.Common_Cancel, action: {
|
||||
}), TextAlertAction(type: .defaultAction, title: "Import", action: {
|
||||
beginWithPeer(peer.id)
|
||||
})], parseMarkdown: true)
|
||||
strongSelf.mainWindow?.present(controller, on: .root)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
createNewGroupImpl = {
|
||||
let presentationData = internalContext.sharedContext.currentPresentationData.with { $0 }
|
||||
let resolvedGroupTitle: String
|
||||
if let groupTitle = peerTitle {
|
||||
resolvedGroupTitle = groupTitle
|
||||
} else {
|
||||
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: {
|
||||
var signal: Signal<PeerId?, NoError> = createSupergroup(account: context.account, title: resolvedGroupTitle, description: nil, isForHistoryImport: true)
|
||||
|> map(Optional.init)
|
||||
|> `catch` { _ -> Signal<PeerId?, NoError> in
|
||||
return .single(nil)
|
||||
}
|
||||
|
||||
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||
let progressSignal = Signal<Never, NoError> { subscriber in
|
||||
let controller = OverlayStatusController(theme: presentationData.theme, type: .loading(cancelled: nil))
|
||||
if let strongSelf = self {
|
||||
strongSelf.mainWindow?.present(controller, on: .root)
|
||||
}
|
||||
return ActionDisposable { [weak controller] in
|
||||
Queue.mainQueue().async() {
|
||||
controller?.dismiss()
|
||||
}
|
||||
}
|
||||
}
|
||||
|> runOn(Queue.mainQueue())
|
||||
|> delay(0.15, queue: Queue.mainQueue())
|
||||
let progressDisposable = progressSignal.start()
|
||||
|
||||
signal = signal
|
||||
|> afterDisposed {
|
||||
Queue.mainQueue().async {
|
||||
progressDisposable.dispose()
|
||||
}
|
||||
}
|
||||
let _ = (signal
|
||||
|> deliverOnMainQueue).start(next: { peerId in
|
||||
if let peerId = peerId {
|
||||
beginWithPeer(peerId)
|
||||
} else {
|
||||
//TODO:localize
|
||||
}
|
||||
})
|
||||
}), TextAlertAction(type: .genericAction, title: presentationData.strings.Common_Cancel, action: {
|
||||
})], parseMarkdown: true)
|
||||
strongSelf.mainWindow?.present(controller, on: .root)
|
||||
}
|
||||
|
||||
navigationController.viewControllers = [controller]
|
||||
strongSelf.mainWindow?.present(navigationController, on: .root)
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user