Merge branch 'dev' into punycode-for-ons

pull/1061/head
Ryan ZHAO 2 months ago
commit 0707f30e9a

@ -1252,8 +1252,7 @@ extension ConversationVC:
body: .attributedText( body: .attributedText(
"urlOpenDescription" "urlOpenDescription"
.put(key: "url", value: url.absoluteString) .put(key: "url", value: url.absoluteString)
.localizedFormatted(baseFont: .systemFont(ofSize: Values.smallFontSize)), .localizedFormatted(baseFont: .systemFont(ofSize: Values.smallFontSize))
canScroll: true
), ),
confirmTitle: "open".localized(), confirmTitle: "open".localized(),
confirmStyle: .danger, confirmStyle: .danger,

File diff suppressed because it is too large Load Diff

@ -313,7 +313,6 @@ class DeveloperSettingsViewModel: SessionTableViewModel, NavigatableStateHolder,
sourcePath: FileManager.default.appSharedDataDirectoryPath, sourcePath: FileManager.default.appSharedDataDirectoryPath,
destinationPath: backupFile, destinationPath: backupFile,
filenamesToExclude: [ filenamesToExclude: [
".DS_Store",
"\(Storage.dbFileName)-wal", "\(Storage.dbFileName)-wal",
"\(Storage.dbFileName)-shm" "\(Storage.dbFileName)-shm"
], ],

@ -239,21 +239,21 @@ public class ConfirmationModal: Modal, UITextFieldDelegate {
case .none: case .none:
mainStackView.spacing = Values.smallSpacing mainStackView.spacing = Values.smallSpacing
case .text(let text, let canScroll): case .text(let text, let scrollMode):
mainStackView.spacing = Values.smallSpacing mainStackView.spacing = Values.smallSpacing
explanationLabel.text = text explanationLabel.text = text
explanationLabel.canScroll = canScroll explanationLabel.scrollMode = scrollMode
explanationLabel.isHidden = false explanationLabel.isHidden = false
case .attributedText(let attributedText, let canScroll): case .attributedText(let attributedText, let scrollMode):
mainStackView.spacing = Values.smallSpacing mainStackView.spacing = Values.smallSpacing
explanationLabel.attributedText = attributedText explanationLabel.attributedText = attributedText
explanationLabel.canScroll = canScroll explanationLabel.scrollMode = scrollMode
explanationLabel.isHidden = false explanationLabel.isHidden = false
case .input(let explanation, let placeholder, let value, let clearButton, let onTextChanged): case .input(let explanation, let placeholder, let value, let clearButton, let onTextChanged):
explanationLabel.attributedText = explanation explanationLabel.attributedText = explanation
explanationLabel.canScroll = false explanationLabel.scrollMode = .never
explanationLabel.isHidden = (explanation == nil) explanationLabel.isHidden = (explanation == nil)
textField.placeholder = placeholder textField.placeholder = placeholder
textField.text = (value ?? "") textField.text = (value ?? "")
@ -559,11 +559,11 @@ public extension ConfirmationModal.Info {
case none case none
case text( case text(
_ text: String, _ text: String,
canScroll: Bool = false scrollMode: ScrollableLabel.ScrollMode = .automatic
) )
case attributedText( case attributedText(
_ attributedText: NSAttributedString, _ attributedText: NSAttributedString,
canScroll: Bool = false scrollMode: ScrollableLabel.ScrollMode = .automatic
) )
case input( case input(
explanation: NSAttributedString?, explanation: NSAttributedString?,

@ -2,13 +2,18 @@
import UIKit import UIKit
class ScrollableLabel: UIView { public class ScrollableLabel: UIView {
public enum ScrollMode: Equatable, Hashable {
case never
case automatic
}
private var oldSize: CGSize = .zero private var oldSize: CGSize = .zero
private var layoutLoopCounter: Int = 0 private var layoutLoopCounter: Int = 0
var canScroll: Bool = false { var scrollMode: ScrollMode = .automatic {
didSet { didSet {
guard canScroll != oldValue else { return } guard scrollMode != oldValue else { return }
updateContentSizeIfNeeded() updateContentSizeIfNeeded()
} }
@ -104,7 +109,7 @@ class ScrollableLabel: UIView {
label.set(.width, to: .width, of: scrollView) label.set(.width, to: .width, of: scrollView)
} }
override func layoutSubviews() { public override func layoutSubviews() {
super.layoutSubviews() super.layoutSubviews()
guard frame.size != oldSize else { guard frame.size != oldSize else {
@ -128,7 +133,7 @@ class ScrollableLabel: UIView {
// then we need to fix the height of the scroll view to our desired maximum, other // then we need to fix the height of the scroll view to our desired maximum, other
let maxCalculatedHeight: CGFloat = (label.font.lineHeight * CGFloat(maxNumberOfLinesWhenScrolling)) let maxCalculatedHeight: CGFloat = (label.font.lineHeight * CGFloat(maxNumberOfLinesWhenScrolling))
switch (canScroll, maxCalculatedHeight <= scrollView.contentSize.height) { switch (scrollMode != .never, maxCalculatedHeight <= scrollView.contentSize.height) {
case (false, _), (true, false): case (false, _), (true, false):
scrollViewHeightAnchor.isActive = false scrollViewHeightAnchor.isActive = false
labelHeightAnchor.isActive = true labelHeightAnchor.isActive = true

@ -77,7 +77,7 @@ public class DirectoryArchiver {
// Stream-based directory traversal and compression // Stream-based directory traversal and compression
let enumerator: FileManager.DirectoryEnumerator? = FileManager.default.enumerator( let enumerator: FileManager.DirectoryEnumerator? = FileManager.default.enumerator(
at: sourceUrl, at: sourceUrl,
includingPropertiesForKeys: [.isRegularFileKey, .isDirectoryKey] includingPropertiesForKeys: [.isRegularFileKey, .isHiddenKey, .isDirectoryKey]
) )
let fileUrls: [URL] = (enumerator?.allObjects let fileUrls: [URL] = (enumerator?.allObjects
.compactMap { $0 as? URL } .compactMap { $0 as? URL }
@ -85,11 +85,14 @@ public class DirectoryArchiver {
guard !filenamesToExclude.contains(url.lastPathComponent) else { return false } guard !filenamesToExclude.contains(url.lastPathComponent) else { return false }
guard guard
let resourceValues = try? url.resourceValues( let resourceValues = try? url.resourceValues(
forKeys: [.isRegularFileKey, .isDirectoryKey] forKeys: [.isRegularFileKey, .isHiddenKey, .isDirectoryKey]
) )
else { return true } else { return true }
return (resourceValues.isRegularFile == true) return (
resourceValues.isRegularFile == true &&
resourceValues.isHidden != true
)
}) })
.defaulting(to: []) .defaulting(to: [])
var index: Int = 0 var index: Int = 0
@ -215,6 +218,7 @@ public class DirectoryArchiver {
var filePaths: [String] = [] var filePaths: [String] = []
var additionalFilePaths: [String] = [] var additionalFilePaths: [String] = []
var skippedFilePaths: [String] = []
var fileAmountProcessed: UInt64 = 0 var fileAmountProcessed: UInt64 = 0
progressChanged?(0, Int(expectedFileCount + expectedAdditionalFileCount), 0, encryptedFileSize) progressChanged?(0, Int(expectedFileCount + expectedAdditionalFileCount), 0, encryptedFileSize)
while inputStream.hasBytesAvailable { while inputStream.hasBytesAvailable {
@ -224,7 +228,7 @@ public class DirectoryArchiver {
) )
fileAmountProcessed += UInt64(blockSizeBytesRead) fileAmountProcessed += UInt64(blockSizeBytesRead)
progressChanged?( progressChanged?(
(filePaths.count + additionalFilePaths.count), (filePaths.count + skippedFilePaths.count + additionalFilePaths.count),
Int(expectedFileCount + expectedAdditionalFileCount), Int(expectedFileCount + expectedAdditionalFileCount),
fileAmountProcessed, fileAmountProcessed,
encryptedFileSize encryptedFileSize
@ -274,12 +278,30 @@ public class DirectoryArchiver {
) )
fileAmountProcessed += encryptedSize fileAmountProcessed += encryptedSize
progressChanged?( progressChanged?(
(filePaths.count + additionalFilePaths.count), (filePaths.count + skippedFilePaths.count + additionalFilePaths.count),
Int(expectedFileCount + expectedAdditionalFileCount), Int(expectedFileCount + expectedAdditionalFileCount),
fileAmountProcessed, fileAmountProcessed,
encryptedFileSize encryptedFileSize
) )
// If the file is a hidden file (shouldn't be possible anymore but old backups had this
// issue) then just skip the file - any hidden files are from Apple and seem to fail to
// decrypt causing the entire import to fail
guard !URL(fileURLWithPath: relativePath).lastPathComponent.starts(with: ".") else {
Log.warn(.cat, "Skipping hidden file to avoid breaking the import: \(relativePath)")
skippedFilePaths.append(fullPath)
// Update the progress
fileAmountProcessed += fileSize
progressChanged?(
(filePaths.count + skippedFilePaths.count + additionalFilePaths.count),
Int(expectedFileCount + expectedAdditionalFileCount),
fileAmountProcessed,
encryptedFileSize
)
continue
}
// Read and decrypt file content // Read and decrypt file content
guard let outputStream: OutputStream = OutputStream(toFileAtPath: fullPath, append: false) else { guard let outputStream: OutputStream = OutputStream(toFileAtPath: fullPath, append: false) else {
Log.error(.cat, "Failed to create output stream") Log.error(.cat, "Failed to create output stream")
@ -302,7 +324,7 @@ public class DirectoryArchiver {
// Update the progress // Update the progress
fileAmountProcessed += UInt64(chunkSizeBytesRead) + UInt64(encryptedSize) fileAmountProcessed += UInt64(chunkSizeBytesRead) + UInt64(encryptedSize)
progressChanged?( progressChanged?(
(filePaths.count + additionalFilePaths.count), (filePaths.count + skippedFilePaths.count + additionalFilePaths.count),
Int(expectedFileCount + expectedAdditionalFileCount), Int(expectedFileCount + expectedAdditionalFileCount),
fileAmountProcessed, fileAmountProcessed,
encryptedFileSize encryptedFileSize
@ -315,7 +337,7 @@ public class DirectoryArchiver {
case true: additionalFilePaths.append(fullPath) case true: additionalFilePaths.append(fullPath)
} }
progressChanged?( progressChanged?(
(filePaths.count + additionalFilePaths.count), (filePaths.count + skippedFilePaths.count + additionalFilePaths.count),
Int(expectedFileCount + expectedAdditionalFileCount), Int(expectedFileCount + expectedAdditionalFileCount),
fileAmountProcessed, fileAmountProcessed,
encryptedFileSize encryptedFileSize
@ -345,12 +367,12 @@ public class DirectoryArchiver {
throw ArchiveError.importedFileCountMismatch throw ArchiveError.importedFileCountMismatch
} }
guard guard
filePaths.count == expectedFileCount && (filePaths.count + skippedFilePaths.count) == expectedFileCount &&
additionalFilePaths.count == expectedAdditionalFileCount additionalFilePaths.count == expectedAdditionalFileCount
else { else {
switch ((filePaths.count == expectedFileCount), additionalFilePaths.count == expectedAdditionalFileCount) { switch (((filePaths.count + skippedFilePaths.count) == expectedFileCount), additionalFilePaths.count == expectedAdditionalFileCount) {
case (false, true): case (false, true):
Log.error(.cat, "The number of main files decrypted (\(filePaths.count)) didn't match the expected number of main files (\(expectedFileCount))") Log.error(.cat, "The number of main files decrypted (\(filePaths.count)) plus skipped files (\(skippedFilePaths.count)) didn't match the expected number of main files (\(expectedFileCount))")
case (true, false): case (true, false):
Log.error(.cat, "The number of additional files decrypted (\(additionalFilePaths.count)) didn't match the expected number of additional files (\(expectedAdditionalFileCount))") Log.error(.cat, "The number of additional files decrypted (\(additionalFilePaths.count)) didn't match the expected number of additional files (\(expectedAdditionalFileCount))")

Loading…
Cancel
Save