mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
Display chat import errors
This commit is contained in:
parent
dbfe4dc9d9
commit
48230cd964
@ -17,6 +17,12 @@ import ConfettiEffect
|
||||
import TelegramUniversalVideoContent
|
||||
|
||||
public final class ChatImportActivityScreen: ViewController {
|
||||
private enum State {
|
||||
case progress(CGFloat)
|
||||
case error
|
||||
case done
|
||||
}
|
||||
|
||||
private final class Node: ViewControllerTracingNode {
|
||||
private weak var controller: ChatImportActivityScreen?
|
||||
|
||||
@ -37,9 +43,8 @@ public final class ChatImportActivityScreen: ViewController {
|
||||
|
||||
private var validLayout: (ContainerViewLayout, CGFloat)?
|
||||
|
||||
private var totalProgress: CGFloat = 0.0
|
||||
private let totalBytes: Int
|
||||
private var isDone: Bool = false
|
||||
private var state: State = .progress(0.0)
|
||||
|
||||
private var videoNode: UniversalVideoNode?
|
||||
private var feedback: HapticFeedback?
|
||||
@ -160,7 +165,12 @@ public final class ChatImportActivityScreen: ViewController {
|
||||
}
|
||||
|
||||
@objc private func statusButtonPressed() {
|
||||
self.controller?.cancel()
|
||||
switch self.state {
|
||||
case .done, .progress:
|
||||
self.controller?.cancel()
|
||||
case .error:
|
||||
self.controller?.beginImport()
|
||||
}
|
||||
}
|
||||
|
||||
func containerLayoutUpdated(_ layout: ContainerViewLayout, navigationHeight: CGFloat, transition: ContainedViewLayoutTransition) {
|
||||
@ -176,20 +186,39 @@ public final class ChatImportActivityScreen: ViewController {
|
||||
let progressStatusSpacing: CGFloat = 14.0
|
||||
let statusButtonSpacing: CGFloat = 19.0
|
||||
|
||||
self.radialStatusText.attributedText = NSAttributedString(string: "\(Int(self.totalProgress * 100.0))%", font: Font.with(size: 42.0, design: .round, weight: .semibold), textColor: self.presentationData.theme.list.itemPrimaryTextColor)
|
||||
let effectiveProgress: CGFloat
|
||||
switch state {
|
||||
case let .progress(value):
|
||||
effectiveProgress = value
|
||||
case .error:
|
||||
effectiveProgress = 0.0
|
||||
case .done:
|
||||
effectiveProgress = 1.0
|
||||
}
|
||||
|
||||
self.radialStatusText.attributedText = NSAttributedString(string: "\(Int(effectiveProgress * 100.0))%", font: Font.with(size: 42.0, design: .round, weight: .semibold), textColor: self.presentationData.theme.list.itemPrimaryTextColor)
|
||||
let radialStatusTextSize = self.radialStatusText.updateLayout(CGSize(width: 200.0, height: .greatestFiniteMagnitude))
|
||||
|
||||
self.progressText.attributedText = NSAttributedString(string: "\(dataSizeString(Int(self.totalProgress * CGFloat(self.totalBytes)))) of \(dataSizeString(Int(1.0 * CGFloat(self.totalBytes))))", font: Font.semibold(17.0), textColor: self.presentationData.theme.list.itemPrimaryTextColor)
|
||||
self.progressText.attributedText = NSAttributedString(string: "\(dataSizeString(Int(effectiveProgress * CGFloat(self.totalBytes)))) of \(dataSizeString(Int(1.0 * CGFloat(self.totalBytes))))", font: Font.semibold(17.0), textColor: self.presentationData.theme.list.itemPrimaryTextColor)
|
||||
let progressTextSize = self.progressText.updateLayout(CGSize(width: layout.size.width - 16.0 * 2.0, height: .greatestFiniteMagnitude))
|
||||
|
||||
self.statusButtonText.attributedText = NSAttributedString(string: "Done", font: Font.semibold(17.0), textColor: self.presentationData.theme.list.itemAccentColor)
|
||||
switch self.state {
|
||||
case .progress, .done:
|
||||
self.statusButtonText.attributedText = NSAttributedString(string: "Done", font: Font.semibold(17.0), textColor: self.presentationData.theme.list.itemAccentColor)
|
||||
case .error:
|
||||
self.statusButtonText.attributedText = NSAttributedString(string: "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))
|
||||
|
||||
if !self.isDone {
|
||||
switch self.state {
|
||||
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)
|
||||
} else {
|
||||
case .error:
|
||||
self.statusText.attributedText = NSAttributedString(string: "An error occurred.", font: Font.regular(17.0), textColor: self.presentationData.theme.list.itemDestructiveColor)
|
||||
case .done:
|
||||
self.statusText.attributedText = NSAttributedString(string: "This chat has been imported\nsuccessfully.", 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 contentHeight: CGFloat
|
||||
@ -220,35 +249,49 @@ public final class ChatImportActivityScreen: ViewController {
|
||||
|
||||
self.progressText.frame = CGRect(origin: CGPoint(x: floor((layout.size.width - progressTextSize.width) / 2.0), y: self.radialStatus.frame.maxY + maxProgressTextSpacing), size: progressTextSize)
|
||||
|
||||
if self.isDone {
|
||||
self.statusText.frame = CGRect(origin: CGPoint(x: floor((layout.size.width - statusTextSize.width) / 2.0), y: self.progressText.frame.minY), size: statusTextSize)
|
||||
} else {
|
||||
if case .progress = self.state {
|
||||
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.statusButton.isHidden = true
|
||||
self.progressText.isHidden = false
|
||||
} 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 = false
|
||||
self.statusButton.isHidden = false
|
||||
self.progressText.isHidden = true
|
||||
}
|
||||
|
||||
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.statusButton.frame = statusButtonTextFrame.insetBy(dx: -10.0, dy: -10.0)
|
||||
|
||||
self.statusButtonText.isHidden = !self.isDone
|
||||
self.statusButton.isHidden = !self.isDone
|
||||
self.progressText.isHidden = self.isDone
|
||||
|
||||
if isFirstLayout {
|
||||
self.updateProgress(totalProgress: self.totalProgress, isDone: self.isDone, animated: false)
|
||||
self.updateState(state: self.state, animated: false)
|
||||
}
|
||||
}
|
||||
|
||||
func updateProgress(totalProgress: CGFloat, isDone: Bool, animated: Bool) {
|
||||
self.totalProgress = totalProgress
|
||||
let wasDone = self.isDone
|
||||
self.isDone = isDone
|
||||
func updateState(state: State, animated: Bool) {
|
||||
var wasDone = false
|
||||
if case .done = self.state {
|
||||
wasDone = true
|
||||
}
|
||||
self.state = state
|
||||
|
||||
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.02, self.totalProgress), cancelEnabled: false, animateRotation: false), animated: animated, synchronous: true, completion: {})
|
||||
if isDone {
|
||||
self.radialCheck.transitionToState(.progress(color: .clear, lineWidth: 6.0, value: self.totalProgress, cancelEnabled: false, animateRotation: false), animated: false, synchronous: true, completion: {})
|
||||
|
||||
let effectiveProgress: CGFloat
|
||||
switch state {
|
||||
case let .progress(value):
|
||||
effectiveProgress = value
|
||||
case .error:
|
||||
effectiveProgress = 0.0
|
||||
case .done:
|
||||
effectiveProgress = 1.0
|
||||
}
|
||||
self.radialStatus.transitionToState(.progress(color: self.presentationData.theme.list.itemAccentColor, lineWidth: 6.0, value: max(0.01, effectiveProgress), cancelEnabled: false, animateRotation: false), animated: animated, synchronous: true, completion: {})
|
||||
if case .done = state {
|
||||
self.radialCheck.transitionToState(.progress(color: .clear, lineWidth: 6.0, value: 1.0, cancelEnabled: false, animateRotation: false), animated: false, synchronous: true, completion: {})
|
||||
self.radialCheck.transitionToState(.check(self.presentationData.theme.list.itemAccentColor), animated: animated, synchronous: true, completion: {})
|
||||
self.radialStatus.layer.animateScale(from: 1.0, to: 1.05, duration: 0.07, delay: 0.0, timingFunction: CAMediaTimingFunctionName.linear.rawValue, removeOnCompletion: false, additive: false, completion: { [weak self] _ in
|
||||
guard let strongSelf = self else {
|
||||
@ -293,7 +336,7 @@ public final class ChatImportActivityScreen: ViewController {
|
||||
private let context: AccountContext
|
||||
private var presentationData: PresentationData
|
||||
fileprivate let cancel: () -> Void
|
||||
private let peerId: PeerId
|
||||
private var peerId: PeerId
|
||||
private let archive: Archive
|
||||
private let mainEntry: TempBoxFile
|
||||
private let mainEntrySize: Int
|
||||
@ -388,6 +431,12 @@ public final class ChatImportActivityScreen: ViewController {
|
||||
case generic
|
||||
}
|
||||
|
||||
for (key, value) in self.pendingEntries {
|
||||
self.pendingEntries[key] = (value.0, 0.0)
|
||||
}
|
||||
|
||||
self.controllerNode.updateState(state: .progress(0.0), animated: true)
|
||||
|
||||
let context = self.context
|
||||
let archive = self.archive
|
||||
let mainEntry = self.mainEntry
|
||||
@ -404,7 +453,11 @@ public final class ChatImportActivityScreen: ViewController {
|
||||
}
|
||||
|
||||
self.disposable.set((resolvedPeerId
|
||||
|> mapToSignal { peerId -> Signal<ChatHistoryImport.Session, ImportError> in
|
||||
|> mapToSignal { [weak self] peerId -> Signal<ChatHistoryImport.Session, ImportError> in
|
||||
Queue.mainQueue().async {
|
||||
self?.peerId = peerId
|
||||
}
|
||||
|
||||
return ChatHistoryImport.initSession(account: context.account, peerId: peerId, file: mainEntry, mediaCount: Int32(otherEntries.count))
|
||||
|> mapError { _ -> ImportError in
|
||||
return .generic
|
||||
@ -477,17 +530,17 @@ public final class ChatImportActivityScreen: ViewController {
|
||||
if !strongSelf.otherEntries.isEmpty {
|
||||
totalProgress = CGFloat(totalDoneBytes) / CGFloat(strongSelf.totalBytes)
|
||||
}
|
||||
strongSelf.controllerNode.updateProgress(totalProgress: totalProgress, isDone: false, animated: true)
|
||||
strongSelf.controllerNode.updateState(state: .progress(totalProgress), animated: true)
|
||||
}, error: { [weak self] _ in
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
strongSelf.controllerNode.updateProgress(totalProgress: 0.0, isDone: false, animated: true)
|
||||
strongSelf.controllerNode.updateState(state: .error, animated: true)
|
||||
}, completed: { [weak self] in
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
strongSelf.controllerNode.updateProgress(totalProgress: 1.0, isDone: true, animated: true)
|
||||
strongSelf.controllerNode.updateState(state: .done, animated: true)
|
||||
|
||||
if let application = UIApplication.value(forKeyPath: #keyPath(UIApplication.shared)) as? UIApplication {
|
||||
application.isIdleTimerDisabled = false
|
||||
|
Loading…
x
Reference in New Issue
Block a user