Merge branch 'dev'

This commit is contained in:
Ryan Zhao 2021-12-17 11:16:35 +11:00
commit c72fbc3acf
20 changed files with 130 additions and 47 deletions

View File

@ -5049,7 +5049,7 @@
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
CODE_SIGN_STYLE = Automatic;
COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 312;
CURRENT_PROJECT_VERSION = 316;
DEBUG_INFORMATION_FORMAT = dwarf;
DEVELOPMENT_TEAM = SUQ8J2PCT7;
FRAMEWORK_SEARCH_PATHS = "$(inherited)";
@ -5074,7 +5074,7 @@
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
MARKETING_VERSION = 1.11.19;
MARKETING_VERSION = 1.11.20;
MTL_ENABLE_DEBUG_INFO = YES;
PRODUCT_BUNDLE_IDENTIFIER = "com.loki-project.loki-messenger.ShareExtension";
PRODUCT_NAME = "$(TARGET_NAME)";
@ -5122,7 +5122,7 @@
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
CODE_SIGN_STYLE = Automatic;
COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 312;
CURRENT_PROJECT_VERSION = 316;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
DEVELOPMENT_TEAM = SUQ8J2PCT7;
ENABLE_NS_ASSERTIONS = NO;
@ -5152,7 +5152,7 @@
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
MARKETING_VERSION = 1.11.19;
MARKETING_VERSION = 1.11.20;
MTL_ENABLE_DEBUG_INFO = NO;
PRODUCT_BUNDLE_IDENTIFIER = "com.loki-project.loki-messenger.ShareExtension";
PRODUCT_NAME = "$(TARGET_NAME)";
@ -5188,7 +5188,7 @@
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
CODE_SIGN_STYLE = Automatic;
COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 312;
CURRENT_PROJECT_VERSION = 316;
DEBUG_INFORMATION_FORMAT = dwarf;
DEVELOPMENT_TEAM = SUQ8J2PCT7;
FRAMEWORK_SEARCH_PATHS = "$(inherited)";
@ -5211,7 +5211,7 @@
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
MARKETING_VERSION = 1.11.19;
MARKETING_VERSION = 1.11.20;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = "com.loki-project.loki-messenger.NotificationServiceExtension";
@ -5262,7 +5262,7 @@
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
CODE_SIGN_STYLE = Automatic;
COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 312;
CURRENT_PROJECT_VERSION = 316;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
DEVELOPMENT_TEAM = SUQ8J2PCT7;
ENABLE_NS_ASSERTIONS = NO;
@ -5290,7 +5290,7 @@
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
MARKETING_VERSION = 1.11.19;
MARKETING_VERSION = 1.11.20;
MTL_ENABLE_DEBUG_INFO = NO;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = "com.loki-project.loki-messenger.NotificationServiceExtension";
@ -6198,7 +6198,7 @@
CODE_SIGN_ENTITLEMENTS = Session/Meta/Signal.entitlements;
CODE_SIGN_IDENTITY = "iPhone Developer";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
CURRENT_PROJECT_VERSION = 312;
CURRENT_PROJECT_VERSION = 316;
DEVELOPMENT_TEAM = SUQ8J2PCT7;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
@ -6237,7 +6237,7 @@
"$(SRCROOT)",
);
LLVM_LTO = NO;
MARKETING_VERSION = 1.11.19;
MARKETING_VERSION = 1.11.20;
OTHER_LDFLAGS = "$(inherited)";
OTHER_SWIFT_FLAGS = "$(inherited) \"-D\" \"COCOAPODS\" \"-DDEBUG\"";
PRODUCT_BUNDLE_IDENTIFIER = "com.loki-project.loki-messenger";
@ -6269,7 +6269,7 @@
CODE_SIGN_ENTITLEMENTS = Session/Meta/Signal.entitlements;
CODE_SIGN_IDENTITY = "iPhone Developer";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
CURRENT_PROJECT_VERSION = 312;
CURRENT_PROJECT_VERSION = 316;
DEVELOPMENT_TEAM = SUQ8J2PCT7;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
@ -6308,7 +6308,7 @@
"$(SRCROOT)",
);
LLVM_LTO = NO;
MARKETING_VERSION = 1.11.19;
MARKETING_VERSION = 1.11.20;
OTHER_LDFLAGS = "$(inherited)";
PRODUCT_BUNDLE_IDENTIFIER = "com.loki-project.loki-messenger";
PRODUCT_NAME = Session;

View File

@ -56,7 +56,9 @@ extension ContextMenuVC {
if isReplyingAllowed() { result.append(Action.reply(viewItem, delegate)) }
result.append(Action.copy(viewItem, delegate))
let isGroup = viewItem.isGroupThread
if isGroup && viewItem.interaction is TSIncomingMessage { result.append(Action.copySessionID(viewItem, delegate)) }
if let message = viewItem.interaction as? TSIncomingMessage, isGroup, !message.isOpenGroupMessage {
result.append(Action.copySessionID(viewItem, delegate))
}
if !isGroup || viewItem.userCanDeleteGroupMessage { result.append(Action.delete(viewItem, delegate)) }
if isGroup && viewItem.interaction is TSIncomingMessage && viewItem.userHasModerationPermission {
result.append(Action.ban(viewItem, delegate))
@ -69,7 +71,9 @@ extension ContextMenuVC {
if viewItem.canCopyMedia() { result.append(Action.copy(viewItem, delegate)) }
if viewItem.canSaveMedia() { result.append(Action.save(viewItem, delegate)) }
let isGroup = viewItem.isGroupThread
if isGroup && viewItem.interaction is TSIncomingMessage { result.append(Action.copySessionID(viewItem, delegate)) }
if let message = viewItem.interaction as? TSIncomingMessage, isGroup, !message.isOpenGroupMessage {
result.append(Action.copySessionID(viewItem, delegate))
}
if !isGroup || viewItem.userCanDeleteGroupMessage { result.append(Action.delete(viewItem, delegate)) }
if isGroup && viewItem.interaction is TSIncomingMessage && viewItem.userHasModerationPermission {
result.append(Action.ban(viewItem, delegate))

View File

@ -49,6 +49,16 @@ extension ConversationVC : InputViewDelegate, MessageCellDelegate, ContextMenuAc
}
// MARK: Attachments
func didPasteImageFromPasteboard(_ image: UIImage) {
guard let imageData = image.jpegData(compressionQuality: 1.0) else { return }
let dataSource = DataSourceValue.dataSource(with: imageData, utiType: kUTTypeJPEG as String)
let attachment = SignalAttachment.attachment(dataSource: dataSource, dataUTI: kUTTypeJPEG as String, imageQuality: .medium)
let approvalVC = AttachmentApprovalViewController.wrappedInNavController(attachments: [ attachment ], approvalDelegate: self)
approvalVC.modalPresentationStyle = .fullScreen
self.present(approvalVC, animated: true, completion: nil)
}
func sendMediaNavDidCancel(_ sendMediaNavigationController: SendMediaNavigationController) {
dismiss(animated: true, completion: nil)
}

View File

@ -37,6 +37,22 @@ public final class InputTextView : UITextView, UITextViewDelegate {
public required init?(coder: NSCoder) {
preconditionFailure("Use init(delegate:) instead.")
}
public override func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool {
if action == #selector(paste(_:)) {
if let _ = UIPasteboard.general.image {
return true
}
}
return super.canPerformAction(action, withSender: sender)
}
public override func paste(_ sender: Any?) {
if let image = UIPasteboard.general.image {
snDelegate?.didPasteImageFromPasteboard(self, image: image)
}
super.paste(sender)
}
private func setUpViewHierarchy() {
showsHorizontalScrollIndicator = false
@ -80,4 +96,5 @@ protocol InputTextViewDelegate : AnyObject {
func inputTextViewDidChangeSize(_ inputTextView: InputTextView)
func inputTextViewDidChangeContent(_ inputTextView: InputTextView)
func didPasteImageFromPasteboard(_ inputTextView: InputTextView, image: UIImage)
}

View File

@ -143,6 +143,10 @@ final class InputView : UIView, InputViewButtonDelegate, InputTextViewDelegate,
autoGenerateLinkPreviewIfPossible()
delegate?.inputTextViewDidChangeContent(inputTextView)
}
func didPasteImageFromPasteboard(_ inputTextView: InputTextView, image: UIImage) {
delegate?.didPasteImageFromPasteboard(image)
}
// We want to show either a link preview or a quote draft, but never both at the same time. When trying to
// generate a link preview, wait until we're sure that we'll be able to build a link preview from the given
@ -351,4 +355,5 @@ protocol InputViewDelegate : AnyObject, ExpandingAttachmentsButtonDelegate, Voic
func handleQuoteViewCancelButtonTapped()
func inputTextViewDidChangeContent(_ inputTextView: InputTextView)
func handleMentionSelected(_ mention: Mention, from view: MentionSelectionView)
func didPasteImageFromPasteboard(_ image: UIImage)
}

View File

@ -4,8 +4,7 @@ final class DocumentView : UIView {
private let textColor: UIColor
// MARK: Settings
private static let iconSize: CGFloat = 24
private static let iconImageViewSize: CGFloat = 40
private static let iconImageViewSize: CGSize = CGSize(width: 31, height: 40)
// MARK: Lifecycle
init(viewItem: ConversationViewItem, textColor: UIColor) {
@ -26,26 +25,33 @@ final class DocumentView : UIView {
private func setUpViewHierarchy() {
guard let attachment = viewItem.attachmentStream ?? viewItem.attachmentPointer else { return }
// Image view
let iconSize = DocumentView.iconSize
let icon = UIImage(named: "actionsheet_document_black")?.withTint(textColor)?.resizedImage(to: CGSize(width: iconSize, height: iconSize))
let icon = UIImage(named: "File")?.withTint(textColor)
let imageView = UIImageView(image: icon)
imageView.contentMode = .center
let iconImageViewSize = DocumentView.iconImageViewSize
imageView.set(.width, to: iconImageViewSize)
imageView.set(.height, to: iconImageViewSize)
imageView.set(.width, to: iconImageViewSize.width)
imageView.set(.height, to: iconImageViewSize.height)
// Body label
let titleLabel = UILabel()
titleLabel.lineBreakMode = .byTruncatingTail
titleLabel.text = attachment.sourceFilename ?? "File"
titleLabel.textColor = textColor
titleLabel.font = .systemFont(ofSize: Values.mediumFontSize)
titleLabel.font = .systemFont(ofSize: Values.smallFontSize, weight: .light)
// Size label
let sizeLabel = UILabel()
sizeLabel.lineBreakMode = .byTruncatingTail
sizeLabel.text = OWSFormat.formatFileSize(UInt(attachment.byteCount))
sizeLabel.textColor = textColor
sizeLabel.font = .systemFont(ofSize: Values.verySmallFontSize)
// Label stack view
let labelStackView = UIStackView(arrangedSubviews: [ titleLabel, sizeLabel ])
labelStackView.axis = .vertical
// Stack view
let stackView = UIStackView(arrangedSubviews: [ imageView, titleLabel ])
let stackView = UIStackView(arrangedSubviews: [ imageView, labelStackView ])
stackView.axis = .horizontal
stackView.spacing = Values.verySmallSpacing
stackView.alignment = .center
stackView.isLayoutMarginsRelativeArrangement = true
stackView.layoutMargins = UIEdgeInsets(top: 0, leading: 0, bottom: 0, trailing: 12)
addSubview(stackView)
stackView.pin(to: self, withInset: Values.smallSpacing)
stackView.pin(to: self)
}
}

View File

@ -362,7 +362,6 @@ final class VisibleMessageCell : MessageCell, LinkPreviewViewDelegate {
let maxMessageWidth = VisibleMessageCell.getMaxWidth(for: viewItem)
let albumView = MediaAlbumView(mediaCache: cache, items: viewItem.mediaAlbumItems!, isOutgoing: isOutgoing, maxMessageWidth: maxMessageWidth)
self.albumView = albumView
snContentView.addSubview(albumView)
let size = getSize(for: viewItem)
albumView.set(.width, to: size.width)
albumView.set(.height, to: size.height)
@ -398,9 +397,25 @@ final class VisibleMessageCell : MessageCell, LinkPreviewViewDelegate {
Storage.shared.getContact(with: thread.contactSessionID())?.isTrusted != true {
showMediaPlaceholder()
} else {
let inset: CGFloat = 12
let maxWidth = VisibleMessageCell.getMaxWidth(for: viewItem) - 2 * inset
// Stack view
let stackView = UIStackView(arrangedSubviews: [])
stackView.axis = .vertical
stackView.spacing = Values.smallSpacing
// Document view
let documentView = DocumentView(viewItem: viewItem, textColor: bodyLabelTextColor)
snContentView.addSubview(documentView)
documentView.pin(to: snContentView)
stackView.addArrangedSubview(documentView)
// Body text view
if let message = viewItem.interaction as? TSMessage, let body = message.body, body.count > 0,
let delegate = delegate { // delegate should always be set at this point
let bodyTextView = VisibleMessageCell.getBodyTextView(for: viewItem, with: maxWidth, textColor: bodyLabelTextColor, searchText: delegate.lastSearchedText, delegate: self)
self.bodyTextView = bodyTextView
stackView.addArrangedSubview(bodyTextView)
}
// Constraints
snContentView.addSubview(stackView)
stackView.pin(to: snContentView, withInset: inset)
}
case .deletedMessage:
let deletedMessageView = DeletedMessageView(viewItem: viewItem, textColor: bodyLabelTextColor)
@ -468,6 +483,7 @@ final class VisibleMessageCell : MessageCell, LinkPreviewViewDelegate {
let location = gestureRecognizer.location(in: self)
if profilePictureView.frame.contains(location) && VisibleMessageCell.shouldShowProfilePicture(for: viewItem) {
guard let message = viewItem.interaction as? TSIncomingMessage else { return }
guard !message.isOpenGroupMessage else { return } // Do not show user details to prevent spam
delegate?.showUserDetails(for: message.authorId)
} else if replyButton.frame.contains(location) {
UIImpactFeedbackGenerator(style: .heavy).impactOccurred()

View File

@ -1025,8 +1025,11 @@ CGFloat kIconViewLength = 24;
- (void)saveName
{
if (![self.thread isKindOfClass:TSContactThread.class]) { return; }
SNContact *contact = [LKStorage.shared getContactWithSessionID:((TSContactThread *)self.thread).contactSessionID];
if (contact == nil) { return; }
NSString *sessionID = ((TSContactThread *)self.thread).contactSessionID;
SNContact *contact = [LKStorage.shared getContactWithSessionID:sessionID];
if (contact == nil) {
contact = [[SNContact alloc] initWithSessionID:sessionID];
}
NSString *text = [self.displayNameTextField.text stringByTrimmingCharactersInSet:NSCharacterSet.whitespaceAndNewlineCharacterSet];
contact.nickname = text.length > 0 ? text : nil;
[LKStorage writeWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {

View File

@ -42,7 +42,7 @@ import SignalUtilitiesKit
//
// TODO: We could make this a parameter.
var dstSizePixels: CGSize {
return CGSize(width: 210, height: 210)
return CGSize(width: 640, height: 640)
}
var dstAspectRatio: CGFloat {
return dstSizePixels.width / dstSizePixels.height

View File

@ -257,7 +257,7 @@ NS_ASSUME_NONNULL_BEGIN
self.videoProgressBar = videoProgressBar;
[self.view addSubview:videoProgressBar];
[videoProgressBar autoPinWidthToSuperview];
[videoProgressBar autoPinEdge:ALEdgeTop toEdge:ALEdgeTop ofView:self.view withOffset:0.0f];
[videoProgressBar autoPinEdgeToSuperviewSafeArea:ALEdgeTop];
CGFloat kVideoProgressBarHeight = 44;
[videoProgressBar autoSetDimension:ALDimensionHeight toSize:kVideoProgressBarHeight];

View File

@ -531,9 +531,6 @@ static NSTimeInterval launchStartedAt;
// enables this feature
[self.disappearingMessagesJob startIfNecessary];
// For non-legacy users, read receipts are on by default.
[self.readReceiptManager setAreReadReceiptsEnabled:YES];
[self startPollerIfNeeded];
[self startClosedGroupPoller];
[self startOpenGroupPollersIfNeeded];

View File

@ -0,0 +1,12 @@
{
"images" : [
{
"filename" : "doc.pdf",
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

Binary file not shown.

View File

@ -0,0 +1,12 @@
{
"images" : [
{
"filename" : "doc_large.pdf",
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

View File

@ -355,6 +355,10 @@ public final class MessageSender : NSObject {
// Start the disappearing messages timer if needed
OWSDisappearingMessagesJob.shared().startAnyExpiration(for: tsMessage, expirationStartedAt: NSDate.millisecondTimestamp(), transaction: transaction)
}
// Prevent the same ExpirationTimerUpdate to be handled twice
if let message = message as? ExpirationTimerUpdate {
Storage.shared.addReceivedMessageTimestamp(message.sentTimestamp!, using: transaction)
}
// Sync the message if:
// it's a visible message or an expiration timer update
// the destination was a contact
@ -362,11 +366,7 @@ public final class MessageSender : NSObject {
let userPublicKey = getUserHexEncodedPublicKey()
if case .contact(let publicKey) = destination, !isSyncMessage {
if let message = message as? VisibleMessage { message.syncTarget = publicKey }
if let message = message as? ExpirationTimerUpdate {
message.syncTarget = publicKey
// Prevent the same ExpirationTimerUpdate to be handled twice
Storage.shared.addReceivedMessageTimestamp(message.sentTimestamp!, using: transaction)
}
if let message = message as? ExpirationTimerUpdate { message.syncTarget = publicKey }
// FIXME: Make this a job
sendToSnodeDestination(.contact(publicKey: userPublicKey), message: message, using: transaction, isSyncMessage: true).retainUntilComplete()
}

View File

@ -63,7 +63,7 @@ public class TypingIndicatorsImpl : NSObject, TypingIndicators {
}
private func setup() {
_areTypingIndicatorsEnabled = OWSPrimaryStorage.shared().dbReadConnection.bool(forKey: kDatabaseKey_TypingIndicatorsEnabled, inCollection: kDatabaseCollection, defaultValue: true)
_areTypingIndicatorsEnabled = OWSPrimaryStorage.shared().dbReadConnection.bool(forKey: kDatabaseKey_TypingIndicatorsEnabled, inCollection: kDatabaseCollection, defaultValue: false)
}
// MARK: -

View File

@ -166,7 +166,7 @@ public class ImageEditorCanvasView: UIView {
// of code simplicity. We could modify the image layer's
// transform to handle the normalization, which would
// have perf benefits.
return srcImage
return srcImage.normalized()
}
// MARK: - Content

View File

@ -269,7 +269,8 @@ public class MediaMessageView: UIView, OWSAudioPlayerDelegate {
private func createGenericPreview() {
var subviews = [UIView]()
let imageView = createHeroImageView(imageName: "actionsheet_document_black")
let imageView = createHeroImageView(imageName: "FileLarge")
imageView.contentMode = .center
subviews.append(imageView)
let fileNameLabel = createFileNameLabel()

View File

@ -31,11 +31,11 @@ NS_ASSUME_NONNULL_BEGIN
const unsigned long kOneKilobyte = 1024;
const unsigned long kOneMegabyte = kOneKilobyte * kOneKilobyte;
if (fileSize > kOneMegabyte * 10) {
return [[formatter stringFromNumber:@((int)round(fileSize / (CGFloat)kOneMegabyte))]
if (fileSize > kOneMegabyte) {
return [[formatter stringFromNumber:@((double)lround(fileSize * 100 / (CGFloat)kOneMegabyte) / 100)]
stringByAppendingString:@" MB"];
} else if (fileSize > kOneKilobyte * 10) {
return [[formatter stringFromNumber:@((int)round(fileSize / (CGFloat)kOneKilobyte))]
} else if (fileSize > kOneKilobyte) {
return [[formatter stringFromNumber:@((double)lround(fileSize * 100 / (CGFloat)kOneKilobyte) / 100)]
stringByAppendingString:@" KB"];
} else {
return [NSString stringWithFormat:@"%lu Bytes", fileSize];