Finish up first version of redesign

This commit is contained in:
Niels Andriesse 2019-12-13 15:02:05 +11:00
parent 2ffdbbb031
commit 53a231a3bd
27 changed files with 216 additions and 128 deletions

View File

@ -2743,8 +2743,6 @@
B8BFFF392355426100102A27 /* Messaging */ = {
isa = PBXGroup;
children = (
B8162F0222891AD600D46544 /* FriendRequestView.swift */,
B8162F0422892C5F00D46544 /* FriendRequestViewDelegate.swift */,
24A830A12293CD0100F4CAC0 /* LokiP2PServer.swift */,
B825849F2315024B001B41CB /* LokiRSSFeedPoller.swift */,
);
@ -2769,6 +2767,8 @@
B8BB82AA238F669C00BA5194 /* ConversationCell.swift */,
B82B4093239DF15900A248E7 /* ConversationTitleView.swift */,
B82B40892399EC0600A248E7 /* FakeChatView.swift */,
B8162F0222891AD600D46544 /* FriendRequestView.swift */,
B8162F0422892C5F00D46544 /* FriendRequestViewDelegate.swift */,
B8B26C8E234D629C004ED98C /* MentionCandidateSelectionView.swift */,
B8B26C90234D8CBD004ED98C /* MentionCandidateSelectionViewDelegate.swift */,
B8BB82AC238F734800BA5194 /* ProfilePictureView.swift */,

Binary file not shown.

View File

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

View File

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

Binary file not shown.

View File

@ -8,10 +8,11 @@ final class FakeChatView : UIView {
}
private lazy var chatBubbles = [
getChatBubble(withText: NSLocalizedString("What is Loki Messenger? A completely decentralised private messaging application for all platforms.", comment: ""), wasSentByCurrentUser: true),
getChatBubble(withText: NSLocalizedString("So no metadata collection, or personally identifiable information? How does it work?", comment: ""), wasSentByCurrentUser: false),
getChatBubble(withText: NSLocalizedString("Through a combination of advanced blockchain techniques including onion routing through Lokinet's private servers.", comment: ""), wasSentByCurrentUser: true),
getChatBubble(withText: NSLocalizedString("Friends don't let friends use compromised messengers. You're welcome.", comment: ""), wasSentByCurrentUser: true)
getChatBubble(withText: NSLocalizedString("What's Loki Messenger?", comment: ""), wasSentByCurrentUser: true),
getChatBubble(withText: NSLocalizedString("It's a secure, decentralized cross-platform private messaging app", comment: ""), wasSentByCurrentUser: false),
getChatBubble(withText: NSLocalizedString("So it doesn't collect my personal information or my conversation metadata? How's it work?", comment: ""), wasSentByCurrentUser: true),
getChatBubble(withText: NSLocalizedString("Using a combination of advanced anonymous routing and end-to-end encryption technologies.", comment: ""), wasSentByCurrentUser: false),
getChatBubble(withText: NSLocalizedString("Friends don't let friends use compromised messengers. You're welcome.", comment: ""), wasSentByCurrentUser: false)
]
private lazy var scrollView: UIScrollView = {
@ -55,10 +56,10 @@ final class FakeChatView : UIView {
bubbleView.layer.shadowColor = UIColor.black.cgColor
bubbleView.layer.shadowRadius = 8
bubbleView.layer.shadowOpacity = 0.64
let backgroundColor = wasSentByCurrentUser ? Colors.accent : Colors.fakeChatBubbleBackground
let backgroundColor = wasSentByCurrentUser ? Colors.fakeChatBubbleBackground : Colors.accent
bubbleView.backgroundColor = backgroundColor
let label = UILabel()
let textColor = wasSentByCurrentUser ? Colors.fakeChatBubbleText : Colors.text
let textColor = wasSentByCurrentUser ? Colors.text : Colors.fakeChatBubbleText
label.textColor = textColor
label.font = .boldSystemFont(ofSize: Values.mediumFontSize)
label.numberOfLines = 0
@ -70,9 +71,9 @@ final class FakeChatView : UIView {
bubbleView.pin(.top, to: .top, of: result)
result.pin(.bottom, to: .bottom, of: bubbleView)
if wasSentByCurrentUser {
bubbleView.pin(.leading, to: .leading, of: result)
bubbleView.pin(.trailing, to: .trailing, of: result)
} else {
result.pin(.trailing, to: .trailing, of: bubbleView)
result.pin(.leading, to: .leading, of: bubbleView)
}
return result
}
@ -83,7 +84,7 @@ final class FakeChatView : UIView {
chatBubbles.forEach { $0.alpha = 0 }
Timer.scheduledTimer(withTimeInterval: Values.fakeChatStartDelay, repeats: false) { [weak self] _ in
self?.showChatBubble(at: 0)
Timer.scheduledTimer(withTimeInterval: delayBetweenMessages, repeats: false) { _ in
Timer.scheduledTimer(withTimeInterval: 1.5 * delayBetweenMessages, repeats: false) { _ in
self?.showChatBubble(at: 1)
Timer.scheduledTimer(withTimeInterval: 1.5 * delayBetweenMessages, repeats: false) { _ in
self?.showChatBubble(at: 2)
@ -91,12 +92,19 @@ final class FakeChatView : UIView {
guard let self = self else { return }
self.scrollView.contentOffset = CGPoint(x: 0, y: self.chatBubbles[0].height() + self.spacing)
}
Timer.scheduledTimer(withTimeInterval: delayBetweenMessages, repeats: false) { _ in
Timer.scheduledTimer(withTimeInterval: 1.5 * delayBetweenMessages, repeats: false) { _ in
self?.showChatBubble(at: 3)
UIView.animate(withDuration: animationDuration) {
guard let self = self else { return }
self.scrollView.contentOffset = CGPoint(x: 0, y: self.chatBubbles[0].height() + self.spacing + self.chatBubbles[1].height() + self.spacing)
}
Timer.scheduledTimer(withTimeInterval: delayBetweenMessages, repeats: false) { _ in
self?.showChatBubble(at: 4)
UIView.animate(withDuration: animationDuration) {
guard let self = self else { return }
self.scrollView.contentOffset = CGPoint(x: 0, y: self.chatBubbles[0].height() + self.spacing + self.chatBubbles[1].height() + self.spacing + self.chatBubbles[2].height() + self.spacing)
}
}
}
}
}

View File

@ -13,16 +13,22 @@ final class FriendRequestView : UIView {
enum Kind : String { case incoming, outgoing }
// MARK: Components
private lazy var topSpacer: UIView = {
private lazy var spacer1: UIView = {
let result = UIView()
result.autoSetDimension(.height, toSize: 12)
result.set(.height, to: 12)
return result
}()
private lazy var spacer2: UIView = {
let result = UIView()
result.set(.height, to: Values.mediumSpacing)
return result
}()
private lazy var label: UILabel = {
let result = UILabel()
result.textColor = Theme.secondaryColor
result.font = UIFont.ows_dynamicTypeSubheadlineClamped
result.textColor = Colors.text
result.font = .systemFont(ofSize: Values.smallFontSize)
result.numberOfLines = 0
result.textAlignment = .center
result.lineBreakMode = .byWordWrapping
@ -32,12 +38,10 @@ final class FriendRequestView : UIView {
private lazy var buttonStackView: UIStackView = {
let result = UIStackView()
result.axis = .horizontal
result.spacing = Values.mediumSpacing
result.distribution = .fillEqually
return result
}()
private lazy var buttonFont = UIFont.ows_dynamicTypeBodyClamped.ows_mediumWeight()
private lazy var buttonHeight = buttonFont.pointSize * 48 / 17
// MARK: Lifecycle
@objc init(message: TSMessage) {
@ -54,23 +58,36 @@ final class FriendRequestView : UIView {
let mainStackView = UIStackView()
mainStackView.axis = .vertical
mainStackView.distribution = .fill
mainStackView.addArrangedSubview(topSpacer)
mainStackView.layoutMargins = UIEdgeInsets(top: 0, left: Values.largeSpacing, bottom: 0, right: Values.largeSpacing)
mainStackView.isLayoutMarginsRelativeArrangement = true
mainStackView.addArrangedSubview(spacer1)
mainStackView.addArrangedSubview(label)
switch kind {
case .incoming:
mainStackView.addArrangedSubview(spacer2)
mainStackView.addArrangedSubview(buttonStackView)
let acceptButton = OWSFlatButton.button(title: NSLocalizedString("Accept", comment: ""), font: buttonFont, titleColor: .ows_materialBlue, backgroundColor: .white, target: self, selector: #selector(accept))
acceptButton.setBackgroundColors(upColor: .clear, downColor: .clear)
acceptButton.autoSetDimension(.height, toSize: buttonHeight)
buttonStackView.addArrangedSubview(acceptButton)
let declineButton = OWSFlatButton.button(title: NSLocalizedString("Decline", comment: ""), font: buttonFont, titleColor: .ows_destructiveRed, backgroundColor: .white, target: self, selector: #selector(decline))
declineButton.setBackgroundColors(upColor: .clear, downColor: .clear)
declineButton.autoSetDimension(.height, toSize: buttonHeight)
let declineButton = UIButton()
declineButton.set(.height, to: Values.mediumButtonHeight)
declineButton.layer.cornerRadius = Values.modalButtonCornerRadius
declineButton.backgroundColor = Colors.buttonBackground
declineButton.titleLabel!.font = .systemFont(ofSize: Values.smallFontSize)
declineButton.setTitleColor(Colors.text, for: UIControl.State.normal)
declineButton.setTitle(NSLocalizedString("Decline", comment: ""), for: UIControl.State.normal)
declineButton.addTarget(self, action: #selector(decline), for: UIControl.Event.touchUpInside)
buttonStackView.addArrangedSubview(declineButton)
let acceptButton = UIButton()
acceptButton.set(.height, to: Values.mediumButtonHeight)
acceptButton.layer.cornerRadius = Values.modalButtonCornerRadius
acceptButton.backgroundColor = Colors.accent
acceptButton.titleLabel!.font = .systemFont(ofSize: Values.smallFontSize)
acceptButton.setTitleColor(Colors.text, for: UIControl.State.normal)
acceptButton.setTitle(NSLocalizedString("Accept", comment: ""), for: UIControl.State.normal)
acceptButton.addTarget(self, action: #selector(accept), for: UIControl.Event.touchUpInside)
buttonStackView.addArrangedSubview(acceptButton)
case .outgoing: break
}
addSubview(mainStackView)
mainStackView.autoPin(toEdgesOf: self)
mainStackView.pin(to: self)
updateUI()
// Observe friend request status changes
NotificationCenter.default.addObserver(self, selector: #selector(handleFriendRequestStatusChangedNotification), name: .messageFriendRequestStatusChanged, object: nil)
@ -93,18 +110,19 @@ final class FriendRequestView : UIView {
case .incoming:
guard let message = message as? TSIncomingMessage else { preconditionFailure() }
buttonStackView.isHidden = message.friendRequestStatus != .pending
spacer2.isHidden = buttonStackView.isHidden
let format: String = {
switch (message.friendRequestStatus) {
case .none, .sendingOrFailed: preconditionFailure()
case .pending: return NSLocalizedString("%@ sent you a friend request", comment: "")
case .accepted: return NSLocalizedString("You've accepted %@'s friend request", comment: "")
case .declined: return NSLocalizedString("You've declined %@'s friend request", comment: "")
case .expired: return NSLocalizedString("%@'s friend request has expired", comment: "")
case .pending: return NSLocalizedString("%@ sent you a message request", comment: "")
case .accepted: return NSLocalizedString("You've accepted %@'s message request", comment: "")
case .declined: return NSLocalizedString("You've declined %@'s message request", comment: "")
case .expired: return NSLocalizedString("%@'s message request has expired", comment: "")
default: preconditionFailure()
}
}()
let contactID = message.authorId
let displayName = Environment.shared.contactsManager.profileName(forRecipientId: contactID) ?? contactID
let displayName = DisplayNameUtilities.getPrivateChatDisplayName(for: contactID) ?? contactID
label.text = String(format: format, displayName)
case .outgoing:
guard let message = message as? TSOutgoingMessage else { preconditionFailure() }
@ -112,20 +130,20 @@ final class FriendRequestView : UIView {
switch (message.friendRequestStatus) {
case .none: preconditionFailure()
case .sendingOrFailed: return nil
case .pending: return NSLocalizedString("You've sent %@ a friend request", comment: "")
case .accepted: return NSLocalizedString("%@ accepted your friend request", comment: "")
case .pending: return NSLocalizedString("You've sent %@ a message request", comment: "")
case .accepted: return NSLocalizedString("%@ accepted your message request", comment: "")
case .declined: preconditionFailure()
case .expired: return NSLocalizedString("Your friend request to %@ has expired", comment: "")
case .expired: return NSLocalizedString("Your message request to %@ has expired", comment: "")
default: preconditionFailure()
}
}()
if let format = format {
let contactID = message.thread.contactIdentifier()!
let displayName = Environment.shared.contactsManager.profileName(forRecipientId: contactID) ?? contactID
let displayName = DisplayNameUtilities.getPrivateChatDisplayName(for: contactID) ?? contactID
label.text = String(format: format, displayName)
}
label.isHidden = (format == nil)
topSpacer.isHidden = (label.isHidden)
spacer1.isHidden = (label.isHidden)
}
}
@ -144,14 +162,14 @@ final class FriendRequestView : UIView {
// MARK: Measuring
@objc static func calculateHeight(message: TSMessage, conversationStyle: ConversationStyle) -> CGFloat {
let width = conversationStyle.contentWidth
let width = conversationStyle.contentWidth - 2 * Values.largeSpacing
let dummyFriendRequestView = FriendRequestView(message: message)
let hasTopSpacer = !dummyFriendRequestView.topSpacer.isHidden
let hasTopSpacer = !dummyFriendRequestView.spacer1.isHidden
let topSpacing: CGFloat = hasTopSpacer ? 12 : 0
let hasLabel = !dummyFriendRequestView.label.isHidden
let labelHeight = hasLabel ? dummyFriendRequestView.label.sizeThatFits(CGSize(width: width, height: CGFloat.greatestFiniteMagnitude)).height : 0
let hasButtonStackView = dummyFriendRequestView.buttonStackView.superview != nil && !dummyFriendRequestView.buttonStackView.isHidden
let buttonHeight = hasButtonStackView ? dummyFriendRequestView.buttonHeight : 0
let buttonHeight = hasButtonStackView ? Values.mediumButtonHeight + Values.mediumSpacing : 0 // Values.mediumSpacing is the height of the spacer
let totalHeight = topSpacing + labelHeight + buttonHeight
return totalHeight.rounded(.up)
}

View File

@ -59,6 +59,6 @@ final class Values : NSObject {
// MARK: - Animation Values
@objc static let fakeChatStartDelay: TimeInterval = 2
@objc static let fakeChatAnimationDuration: TimeInterval = 0.4
@objc static let fakeChatDelay: TimeInterval = 2
@objc static let fakeChatDelay: TimeInterval = 2.5
@objc static let fakeChatMessagePopAnimationStartScale: CGFloat = 0.6
}

View File

@ -38,14 +38,14 @@ final class DisplayNameVC : UIViewController {
let titleLabel = UILabel()
titleLabel.textColor = Colors.text
titleLabel.font = .boldSystemFont(ofSize: Values.veryLargeFontSize)
titleLabel.text = NSLocalizedString("Pick your public display name", comment: "")
titleLabel.text = NSLocalizedString("Pick your display name", comment: "")
titleLabel.numberOfLines = 0
titleLabel.lineBreakMode = .byWordWrapping
// Set up explanation label
let explanationLabel = UILabel()
explanationLabel.textColor = Colors.text
explanationLabel.font = .systemFont(ofSize: Values.smallFontSize)
explanationLabel.text = "explanation explanation explanation explanation explanation explanation explanation explanation explanation explanation explanation explanation explanation explanation explanation explanation"
explanationLabel.text = "This is how others will be able to recognize you."
explanationLabel.numberOfLines = 0
explanationLabel.lineBreakMode = .byWordWrapping
// Set up spacers

View File

@ -36,7 +36,7 @@ final class LinkDeviceVC : UIViewController, UIPageViewControllerDataSource, UIP
}()
private lazy var scanQRCodeWrapperVC: ScanQRCodeWrapperVC = {
let message = NSLocalizedString("Link to your existing device by going into your in-app settings and clicking \"Linked Devices\".", comment: "")
let message = NSLocalizedString("Link to your existing account by going into your in-app settings and clicking \"Linked Devices\".", comment: "")
let result = ScanQRCodeWrapperVC(message: message)
result.delegate = self
return result
@ -156,7 +156,7 @@ private final class EnterPublicKeyVC : UIViewController {
let explanationLabel = UILabel()
explanationLabel.textColor = Colors.text
explanationLabel.font = .systemFont(ofSize: Values.smallFontSize)
explanationLabel.text = "explanation explanation explanation explanation explanation explanation explanation explanation explanation explanation explanation explanation explanation explanation explanation explanation"
explanationLabel.text = "Enter your account's public key to link your device."
explanationLabel.numberOfLines = 0
explanationLabel.lineBreakMode = .byWordWrapping
// Link button

View File

@ -16,7 +16,7 @@ final class RegisterVC : UIViewController {
private lazy var copyPublicKeyButton: Button = {
let result = Button(style: .prominentOutline, size: .large)
result.setTitle(NSLocalizedString("Copy Public Key", comment: ""), for: UIControl.State.normal)
result.setTitle(NSLocalizedString("Copy", comment: ""), for: UIControl.State.normal)
result.addTarget(self, action: #selector(copyPublicKey), for: UIControl.Event.touchUpInside)
return result
}()
@ -62,14 +62,14 @@ final class RegisterVC : UIViewController {
let titleLabel = UILabel()
titleLabel.textColor = Colors.text
titleLabel.font = .boldSystemFont(ofSize: Values.veryLargeFontSize)
titleLabel.text = NSLocalizedString("Say hello to your unique public key", comment: "")
titleLabel.text = NSLocalizedString("Say hello to your Loki Messenger ID", comment: "")
titleLabel.numberOfLines = 0
titleLabel.lineBreakMode = .byWordWrapping
// Set up explanation label
let explanationLabel = UILabel()
explanationLabel.textColor = Colors.text
explanationLabel.font = .systemFont(ofSize: Values.smallFontSize)
explanationLabel.text = "explanation explanation explanation explanation explanation explanation explanation explanation explanation explanation explanation explanation explanation explanation explanation explanation"
explanationLabel.text = NSLocalizedString("Your Loki Messenger ID is the unique address that people can use to contact you on Loki Messenger. With no connection to your real identity, your Loki Messenger ID is totally anonymous and private by design.", comment: "")
explanationLabel.numberOfLines = 0
explanationLabel.lineBreakMode = .byWordWrapping
// Set up public key label container
@ -138,7 +138,7 @@ final class RegisterVC : UIViewController {
@objc private func enableCopyButton() {
copyPublicKeyButton.isUserInteractionEnabled = true
UIView.transition(with: copyPublicKeyButton, duration: 0.25, options: .transitionCrossDissolve, animations: {
self.copyPublicKeyButton.setTitle(NSLocalizedString("Copy Public Key", comment: ""), for: UIControl.State.normal)
self.copyPublicKeyButton.setTitle(NSLocalizedString("Copy", comment: ""), for: UIControl.State.normal)
}, completion: nil)
}

View File

@ -61,7 +61,7 @@ final class RestoreVC : UIViewController {
let explanationLabel = UILabel()
explanationLabel.textColor = Colors.text
explanationLabel.font = .systemFont(ofSize: Values.smallFontSize)
explanationLabel.text = "explanation explanation explanation explanation explanation explanation explanation explanation explanation explanation explanation explanation explanation explanation explanation explanation"
explanationLabel.text = "Enter the seed that was given to you when you signed up to restore your account."
explanationLabel.numberOfLines = 0
explanationLabel.lineBreakMode = .byWordWrapping
// Set up legal label

View File

@ -30,7 +30,7 @@ final class SeedVCV2 : UIViewController {
let attributedTitle = NSMutableAttributedString(string: title)
attributedTitle.addAttribute(.foregroundColor, value: Colors.accent, range: (title as NSString).range(of: "90%"))
result.title = attributedTitle
result.subtitle = NSLocalizedString("Press the covered words to view your seed and secure your account", comment: "")
result.subtitle = NSLocalizedString("Press the redacted words to view your seed and secure your account", comment: "")
result.setProgress(0.9, animated: false)
return result
}()
@ -88,7 +88,7 @@ final class SeedVCV2 : UIViewController {
let explanationLabel = UILabel()
explanationLabel.textColor = Colors.text
explanationLabel.font = .systemFont(ofSize: Values.smallFontSize)
explanationLabel.text = NSLocalizedString("Think of this as the crypto-equivalent of a social security number. This allows whomever has it complete access to your personal information and crypto wallet.", comment: "")
explanationLabel.text = NSLocalizedString("Think of this as the crypto-equivalent of a social security number. This allows whomever has it complete access to your account.", comment: "")
explanationLabel.numberOfLines = 0
explanationLabel.lineBreakMode = .byWordWrapping
// Set up mnemonic label

View File

@ -32,7 +32,7 @@ struct MessageActionBuilder {
}
static func copyPublicKey(conversationViewItem: ConversationViewItem, delegate: MessageActionsDelegate) -> MenuAction {
return MenuAction(image: #imageLiteral(resourceName: "table_ic_add_to_existing_contact"),
return MenuAction(image: #imageLiteral(resourceName: "Key"),
title: NSLocalizedString("Copy Public Key", comment: ""),
subtitle: nil,
block: { [weak delegate] _ in delegate?.copyPublicKey(for: conversationViewItem) }

View File

@ -98,24 +98,19 @@ NS_ASSUME_NONNULL_BEGIN
- (void)setAudioIcon:(UIImage *)icon
{
OWSAssertDebug(icon.size.height == self.iconSize);
icon = [icon imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
icon = [icon resizedImageToSize:CGSizeMake(self.iconSize, self.iconSize)];
[_audioPlayPauseButton setImage:icon forState:UIControlStateNormal];
[_audioPlayPauseButton setImage:icon forState:UIControlStateDisabled];
_audioPlayPauseButton.imageView.tintColor = [UIColor ows_signalBlueColor];
_audioPlayPauseButton.backgroundColor = [UIColor colorWithWhite:1.f alpha:0.92f];
_audioPlayPauseButton.layer.cornerRadius = self.iconSize * 0.5f;
}
- (void)setAudioIconToPlay
{
[self setAudioIcon:[UIImage imageNamed:@"audio_play_black_48"]];
[self setAudioIcon:[UIImage imageNamed:@"CirclePlay"]];
}
- (void)setAudioIconToPause
{
[self setAudioIcon:[UIImage imageNamed:@"audio_pause_black_48"]];
[self setAudioIcon:[UIImage imageNamed:@"CirclePause"]];
}
- (void)updateAudioProgressView
@ -181,7 +176,7 @@ NS_ASSUME_NONNULL_BEGIN
+ (CGFloat)vMargin
{
return 5.f;
return 0.f;
}
- (CGFloat)vMargin
@ -205,7 +200,7 @@ NS_ASSUME_NONNULL_BEGIN
+ (CGFloat)iconSize
{
return kStandardAvatarSize;
return 72.f;
}
- (CGFloat)iconSize
@ -229,7 +224,12 @@ NS_ASSUME_NONNULL_BEGIN
_audioPlayPauseButton = [UIButton buttonWithType:UIButtonTypeCustom];
self.audioPlayPauseButton.enabled = NO;
[self addArrangedSubview:self.audioPlayPauseButton];
[self.audioPlayPauseButton setContentHuggingHigh];
self.audioPlayPauseButton.imageView.contentMode = UIViewContentModeCenter;
[self.audioPlayPauseButton autoSetDimension:ALDimensionWidth toSize:56.f];
[self.audioPlayPauseButton autoSetDimension:ALDimensionHeight toSize:56.f];
self.audioPlayPauseButton.imageView.clipsToBounds = NO;
self.audioPlayPauseButton.clipsToBounds = NO;
self.clipsToBounds = NO;
[self replaceIconWithDownloadProgressIfNecessary:self.audioPlayPauseButton];

View File

@ -1591,7 +1591,7 @@ typedef enum : NSUInteger {
isAttachmentButtonHidden = false;
}
[self.inputToolbar setUserInteractionEnabled:isEnabled];
NSString *placeholderText = isEnabled ? NSLocalizedString(@"Message", "") : NSLocalizedString(@"Pending Friend Request...", "");
NSString *placeholderText = isEnabled ? NSLocalizedString(@"Message", "") : NSLocalizedString(@"Pending message request", "");
[self.inputToolbar setPlaceholderText:placeholderText];
[self.inputToolbar setAttachmentButtonHidden:isAttachmentButtonHidden];
}

View File

@ -37,7 +37,7 @@ class GifPickerViewController: OWSViewController, UISearchBarDelegate, UICollect
let thread: TSThread
let messageSender: MessageSender
let searchBar: UISearchBar
let searchBar: SearchBar
let layout: GifPickerLayout
let collectionView: UICollectionView
var noResultsView: UILabel?
@ -64,7 +64,7 @@ class GifPickerViewController: OWSViewController, UISearchBarDelegate, UICollect
self.thread = thread
self.messageSender = messageSender
self.searchBar = OWSSearchBar()
self.searchBar = SearchBar()
self.layout = GifPickerLayout()
self.collectionView = UICollectionView(frame: CGRect.zero, collectionViewLayout: self.layout)
@ -148,9 +148,7 @@ class GifPickerViewController: OWSViewController, UISearchBarDelegate, UICollect
private func createViews() {
let backgroundColor = (Theme.isDarkThemeEnabled
? UIColor(white: 0.08, alpha: 1.0)
: Theme.backgroundColor)
let backgroundColor = Colors.navigationBarBackground
self.view.backgroundColor = backgroundColor
// Block UIKit from adjust insets of collection view which screws up
@ -159,8 +157,6 @@ class GifPickerViewController: OWSViewController, UISearchBarDelegate, UICollect
// Search
searchBar.delegate = self
searchBar.placeholder = NSLocalizedString("GIF_VIEW_SEARCH_PLACEHOLDER_TEXT",
comment: "Placeholder text for the search field in GIF view")
self.view.addSubview(searchBar)
searchBar.autoPinWidthToSuperview()
@ -179,7 +175,7 @@ class GifPickerViewController: OWSViewController, UISearchBarDelegate, UICollect
// for iPhoneX devices, extends the black background to the bottom edge of the view.
let bottomBannerContainer = UIView()
bottomBannerContainer.backgroundColor = UIColor.black
bottomBannerContainer.backgroundColor = Colors.navigationBarBackground
self.view.addSubview(bottomBannerContainer)
bottomBannerContainer.autoPinWidthToSuperview()
bottomBannerContainer.autoPinEdge(.top, to: .bottom, of: self.collectionView)
@ -216,12 +212,18 @@ class GifPickerViewController: OWSViewController, UISearchBarDelegate, UICollect
searchErrorView.isUserInteractionEnabled = true
searchErrorView.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(retryTapped)))
let activityIndicator = UIActivityIndicatorView(style: .gray)
let activityIndicator = UIActivityIndicatorView(style: .whiteLarge)
self.activityIndicator = activityIndicator
self.view.addSubview(activityIndicator)
activityIndicator.autoHCenterInSuperview()
activityIndicator.autoAlignAxis(.horizontal, toSameAxisOf: self.collectionView)
let navigationBar = navigationController!.navigationBar
navigationBar.setBackgroundImage(UIImage(), for: UIBarMetrics.default)
navigationBar.shadowImage = UIImage()
navigationBar.isTranslucent = false
navigationBar.barTintColor = Colors.navigationBarBackground
self.updateContents()
}

View File

@ -274,13 +274,13 @@ NS_ASSUME_NONNULL_BEGIN
[playVideoButton addTarget:self action:@selector(playVideo) forControlEvents:UIControlEventTouchUpInside];
UIImage *playImage = [UIImage imageNamed:@"play_button"];
UIImage *playImage = [UIImage imageNamed:@"CirclePlay"];
[playVideoButton setBackgroundImage:playImage forState:UIControlStateNormal];
playVideoButton.contentMode = UIViewContentModeScaleAspectFill;
[self.view addSubview:playVideoButton];
CGFloat playVideoButtonWidth = ScaleFromIPhone5(70);
CGFloat playVideoButtonWidth = 72.f;
[playVideoButton autoSetDimensionsToSize:CGSizeMake(playVideoButtonWidth, playVideoButtonWidth)];
[playVideoButton autoCenterInSuperview];
}

View File

@ -84,15 +84,30 @@ public class MediaTileViewController: UICollectionViewController, MediaGalleryDa
override public func viewDidLoad() {
super.viewDidLoad()
self.title = MediaStrings.allMedia
// Loki: Set gradient background
view.backgroundColor = .clear
let gradient = Gradients.defaultLokiBackground
view.setGradient(gradient)
// Loki: Set navigation bar background color
let navigationBar = navigationController!.navigationBar
navigationBar.setBackgroundImage(UIImage(), for: UIBarMetrics.default)
navigationBar.shadowImage = UIImage()
navigationBar.isTranslucent = false
navigationBar.barTintColor = Colors.navigationBarBackground
// Loki: Customize title
let titleLabel = UILabel()
titleLabel.text = MediaStrings.allMedia
titleLabel.textColor = Colors.text
titleLabel.font = .boldSystemFont(ofSize: Values.veryLargeFontSize)
navigationItem.titleView = titleLabel
guard let collectionView = self.collectionView else {
owsFailDebug("collectionView was unexpectedly nil")
return
}
collectionView.backgroundColor = Theme.darkThemeBackgroundColor
collectionView.backgroundColor = Colors.navigationBarBackground
collectionView.register(PhotoGridViewCell.self, forCellWithReuseIdentifier: PhotoGridViewCell.reuseIdentifier)
collectionView.register(MediaGallerySectionHeader.self, forSupplementaryViewOfKind: UICollectionView.elementKindSectionHeader, withReuseIdentifier: MediaGallerySectionHeader.reuseIdentifier)

View File

@ -404,23 +404,21 @@ class MenuActionView: UIButton {
}
let imageView = UIImageView(image: image)
if Theme.isDarkThemeEnabled {
imageView.tintColor = UIColor.ows_gray25
imageView.tintColor = Colors.text.withAlphaComponent(Values.unimportantElementOpacity)
}
let imageWidth: CGFloat = 24
imageView.autoSetDimensions(to: CGSize(width: imageWidth, height: imageWidth))
imageView.isUserInteractionEnabled = false
let titleLabel = UILabel()
titleLabel.font = UIFont.ows_dynamicTypeBody
titleLabel.textColor = Theme.primaryColor
titleLabel.font = .systemFont(ofSize: Values.mediumFontSize)
titleLabel.textColor = Colors.text
titleLabel.text = action.title
titleLabel.isUserInteractionEnabled = false
let subtitleLabel = UILabel()
subtitleLabel.font = UIFont.ows_dynamicTypeSubheadline
subtitleLabel.textColor = (Theme.isDarkThemeEnabled
? UIColor.ows_gray25
: Theme.secondaryColor)
subtitleLabel.font = .systemFont(ofSize: Values.smallFontSize)
subtitleLabel.textColor = Colors.text.withAlphaComponent(Values.unimportantElementOpacity)
subtitleLabel.text = action.subtitle
subtitleLabel.isUserInteractionEnabled = false
@ -445,15 +443,11 @@ class MenuActionView: UIButton {
}
private var defaultBackgroundColor: UIColor {
return (Theme.isDarkThemeEnabled
? UIColor.ows_gray75
: UIColor.white)
return Colors.cellBackground
}
private var highlightedBackgroundColor: UIColor {
return (Theme.isDarkThemeEnabled
? UIColor.ows_gray75
: UIColor.ows_gray05)
return Colors.cellSelected
}
override var isHighlighted: Bool {

View File

@ -99,8 +99,22 @@ class MessageDetailViewController: OWSViewController, MediaGalleryDataSourceDele
self.conversationStyle.viewWidth = view.width()
self.navigationItem.title = NSLocalizedString("MESSAGE_METADATA_VIEW_TITLE",
comment: "Title for the 'message metadata' view.")
// Loki: Set gradient background
view.backgroundColor = .clear
let gradient = Gradients.defaultLokiBackground
view.setGradient(gradient)
// Loki: Set navigation bar background color
let navigationBar = navigationController!.navigationBar
navigationBar.setBackgroundImage(UIImage(), for: UIBarMetrics.default)
navigationBar.shadowImage = UIImage()
navigationBar.isTranslucent = false
navigationBar.barTintColor = Colors.navigationBarBackground
// Loki: Customize title
let titleLabel = UILabel()
titleLabel.text = NSLocalizedString("MESSAGE_METADATA_VIEW_TITLE", comment: "Title for the 'message metadata' view.")
titleLabel.textColor = Colors.text
titleLabel.font = .boldSystemFont(ofSize: Values.veryLargeFontSize)
navigationItem.titleView = titleLabel
createViews()
@ -154,7 +168,7 @@ class MessageDetailViewController: OWSViewController, MediaGalleryDataSourceDele
// MARK: - Create Views
private func createViews() {
view.backgroundColor = Theme.backgroundColor
view.backgroundColor = .clear
let scrollView = UIScrollView()
self.scrollView = scrollView

View File

@ -59,23 +59,30 @@ class ImagePickerGridController: UICollectionViewController, PhotoLibraryDelegat
// ensure images at the end of the list can be scrolled above the bottom buttons
let bottomButtonInset = -1 * SendMediaNavigationController.bottomButtonsCenterOffset + SendMediaNavigationController.bottomButtonWidth / 2
collectionView.contentInset.bottom = bottomButtonInset + 8
view.backgroundColor = .ows_gray95
view.backgroundColor = Colors.navigationBarBackground
// The PhotoCaptureVC needs a shadow behind it's cancel button, so we use a custom icon.
// This VC has a visible navbar so doesn't need the shadow, but because the user can
// quickly toggle between the Capture and the Picker VC's, we use the same custom "X"
// icon here rather than the system "stop" icon so that the spacing matches exactly.
// Otherwise there's a noticable shift in the icon placement.
let cancelImage = UIImage(imageLiteralResourceName: "ic_x_with_shadow")
let cancelImage = UIImage(imageLiteralResourceName: "X")
let cancelButton = UIBarButtonItem(image: cancelImage, style: .plain, target: self, action: #selector(didPressCancel))
cancelButton.tintColor = .ows_gray05
cancelButton.tintColor = Colors.text
navigationItem.leftBarButtonItem = cancelButton
let titleView = TitleView()
titleView.delegate = self
titleView.text = photoCollection.localizedTitle()
// Loki: Set navigation bar background color
let navigationBar = navigationController!.navigationBar
navigationBar.setBackgroundImage(UIImage(), for: UIBarMetrics.default)
navigationBar.shadowImage = UIImage()
navigationBar.isTranslucent = false
navigationBar.barTintColor = Colors.navigationBarBackground
if #available(iOS 11, *) {
// do nothing
} else {
@ -86,7 +93,7 @@ class ImagePickerGridController: UICollectionViewController, PhotoLibraryDelegat
navigationItem.titleView = titleView
self.titleView = titleView
collectionView.backgroundColor = .ows_gray95
collectionView.backgroundColor = Colors.navigationBarBackground
let selectionPanGesture = DirectionalPanGestureRecognizer(direction: [.horizontal], target: self, action: #selector(didPanSelection))
selectionPanGesture.delegate = self
@ -244,7 +251,11 @@ class ImagePickerGridController: UICollectionViewController, PhotoLibraryDelegat
// MARK:
var lastPageYOffset: CGFloat {
return collectionView.contentSize.height - collectionView.frame.height
var yOffset = collectionView.contentSize.height - collectionView.frame.height + collectionView.contentInset.bottom
if #available(iOS 11.0, *) {
yOffset += view.safeAreaInsets.bottom
}
return yOffset
}
func scrollToBottom(animated: Bool) {
@ -581,7 +592,7 @@ class TitleView: UIView {
let stackView = UIStackView(arrangedSubviews: [label, iconView])
stackView.axis = .horizontal
stackView.alignment = .center
stackView.spacing = 5
stackView.spacing = 8
stackView.isUserInteractionEnabled = true
self.stackView = stackView
@ -591,10 +602,10 @@ class TitleView: UIView {
addSubview(stackView)
stackView.autoPinEdgesToSuperviewEdges()
label.textColor = .ows_gray05
label.font = UIFont.ows_dynamicTypeBody.ows_mediumWeight()
label.textColor = Colors.text
label.font = .boldSystemFont(ofSize: Values.mediumFontSize)
iconView.tintColor = .ows_gray05
iconView.tintColor = Colors.text
iconView.image = UIImage(named: "navbar_disclosure_down")?.withRenderingMode(.alwaysTemplate)
addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(titleTapped)))

View File

@ -34,8 +34,8 @@ class PhotoCollectionPickerController: OWSTableViewController, PhotoLibraryDeleg
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = Theme.darkThemeBackgroundColor
tableView.backgroundColor = Theme.darkThemeBackgroundColor
view.backgroundColor = Colors.navigationBarBackground
tableView.backgroundColor = Colors.navigationBarBackground
tableView.separatorColor = .clear
library.add(delegate: self)

View File

@ -343,7 +343,7 @@ const CGFloat kIconViewLength = 24;
OWSTableSection *mainSection = [OWSTableSection new];
mainSection.customHeaderView = [self mainSectionHeader];
mainSection.customHeaderHeight = self.isGroupThread ? @(153.f) : @(214.f);
mainSection.customHeaderHeight = self.isGroupThread ? @(147.f) : @(208.f);
/**
* Loki: Original code
@ -933,9 +933,9 @@ const CGFloat kIconViewLength = 24;
UILabel *titleView = [UILabel new];
titleView.textColor = LKColors.text;
titleView.font = [UIFont boldSystemFontOfSize:LKValues.veryLargeFontSize];
titleView.font = [UIFont boldSystemFontOfSize:LKValues.largeFontSize];
titleView.lineBreakMode = NSLineBreakByTruncatingTail;
titleView.text = self.threadName;
titleView.text = (self.threadName != nil && self.threadName.length > 0) ? self.threadName : @"Anonymous";
UIStackView *stackView = [[UIStackView alloc] initWithArrangedSubviews:@[ profilePictureView, titleView ]];
stackView.axis = UILayoutConstraintAxisVertical;

View File

@ -57,12 +57,12 @@ public class PhotoGridViewCell: UICollectionViewCell {
self.highlightedView = UIView()
highlightedView.alpha = 0.2
highlightedView.backgroundColor = Theme.darkThemePrimaryColor
highlightedView.backgroundColor = Colors.cellSelected
highlightedView.isHidden = true
self.selectedView = UIView()
selectedView.alpha = 0.3
selectedView.backgroundColor = Theme.darkThemeBackgroundColor
selectedView.backgroundColor = Colors.cellSelected
selectedView.isHidden = true
super.init(frame: frame)

View File

@ -2573,20 +2573,20 @@
"Calculating proof of work" = "Calculating proof of work";
"Failed to calculate proof of work." = "Failed to calculate proof of work.";
"Share Public Key" = "Share Public Key";
"%@ sent you a friend request" = "%@ sent you a friend request";
"%@ sent you a message request" = "%@ sent you a message request";
"Accept" = "Accept";
"Decline" = "Decline";
"Pending Friend Request..." = "Pending Friend Request...";
"Pending message request" = "Pending message request";
"New Message" = "New Message";
"Secure session reset in progress" = "Secure session reset in progress";
"Secure session reset done" = "Secure session reset done";
"Loki Messenger" = "Loki Messenger";
"You've sent %@ a friend request" = "You've sent %@ a friend request";
"You've declined %@'s friend request" = "You've declined %@'s friend request";
"You've accepted %@'s friend request" = "You've accepted %@'s friend request";
"%@ accepted your friend request" = "%@ accepted your friend request";
"%@'s friend request has expired" = "%@'s friend request has expired";
"Your friend request to %@ has expired" = "Your friend request to %@ has expired";
"You've sent %@ a message request" = "You've sent %@ a message request";
"You've declined %@'s message request" = "You've declined %@'s message request";
"You've accepted %@'s message request" = "You've accepted %@'s message request";
"%@ accepted your message request" = "%@ accepted your message request";
"%@'s message request has expired" = "%@'s message request has expired";
"Your message request to %@ has expired" = "Your message request to %@ has expired";
"Show Seed" = "Show Seed";
"Your Seed" = "Your Seed";
"Unlock Loki Messenger's screen using Touch ID, Face ID, or your iOS device passcode. You can still answer incoming calls and receive message notifications while Screen Lock is enabled. Loki Messenger's notification settings allow you to customize the information that is displayed." = "Unlock Loki Messenger's screen using Touch ID, Face ID, or your iOS device passcode. You can still answer incoming calls and receive message notifications while Screen Lock is enabled. Loki Messenger's notification settings allow you to customize the information that is displayed.";
@ -2725,16 +2725,17 @@
"Clear" = "Clear";
"Enter a display name" = "Enter a display name";
"Your Loki Messenger begins here..." = "Your Loki Messenger begins here...";
"What is Loki Messenger? A completely decentralised private messaging application for all platforms." = "What is Loki Messenger? A completely decentralised private messaging application for all platforms.";
"So no metadata collection, or personally identifiable information? How does it work?" = "So no metadata collection, or personally identifiable information? How does it work?";
"Through a combination of advanced blockchain techniques including onion routing through Lokinet's private servers." = "Through a combination of advanced blockchain techniques including onion routing through Lokinet's private servers.";
"What's Loki Messenger?" = "What's Loki Messenger?";
"It's a secure, decentralized cross-platform private messaging app" = "It's a secure, decentralized cross-platform private messaging app";
"So it doesn't collect my personal information or my conversation metadata? How's it work?" = "So it doesn't collect my personal information or my conversation metadata? How's it work?";
"Using a combination of advanced anonymous routing and end-to-end encryption technologies." = "Using a combination of advanced anonymous routing and end-to-end encryption technologies.";
"Friends don't let friends use compromised messengers. You're welcome." = "Friends don't let friends use compromised messengers. You're welcome.";
"Create Account" = "Create Account";
"Continue your Loki Messenger" = "Continue your Loki Messenger";
"Say hello to your unique public key" = "Say hello to your unique public key";
"Say hello to your Loki Messenger ID" = "Say hello to your Loki Messenger ID";
"Continue" = "Continue";
"Copy Public Key" = "Copy Public Key";
"Pick your public display name" = "Pick your public display name";
"Pick your display name" = "Pick your display name";
"Enter a display name" = "Enter a display name";
"Restore your account using your seed" = "Restore your account using your seed";
"Enter your seed" = "Enter your seed";
@ -2749,12 +2750,13 @@
"Continue" = "Continue";
"Your Seed" = "Your Seed";
"Meet your seed" = "Meet your seed";
"Think of this as the crypto-equivalent of a social security number. This allows whomever has it complete access to your personal information and crypto wallet." = "Think of this as the crypto-equivalent of a social security number. This allows whomever has it complete access to your personal information and crypto wallet.";
"Press the covered words to view your seed and secure your account" = "Press the covered words to view your seed and secure your account";
"Think of this as the crypto-equivalent of a social security number. This allows whomever has it complete access to your account." = "Think of this as the crypto-equivalent of a social security number. This allows whomever has it complete access to your account.";
"Press the redacted words to view your seed and secure your account" = "Press the redacted words to view your seed and secure your account";
"Hold to reveal" = "Hold to reveal";
"Make sure to store your seed in a safe place" = "Make sure to store your seed in a safe place";
"Link to an existing account" = "Link to an existing account";
"Enter your public key" = "Enter your public key";
"Link to your existing device by going into your in-app settings and clicking \"Linked Devices\"." = "Link to your existing device by going into your in-app settings and clicking \"Linked Devices\".";
"Link to your existing account by going into your in-app settings and clicking \"Linked Devices\"." = "Link to your existing account by going into your in-app settings and clicking \"Linked Devices\".";
"Create a new account on your other device and click \"Link to an existing account\" to start the linking process" = "Create a new account on your other device and click \"Link to an existing account\" to start the linking process";
"Group Settings" = "Group Settings";
"Your Loki Messenger ID is the unique address that people can use to contact you on Loki Messenger. With no connection to your real identity, your Loki Messenger ID is totally anonymous and private by design." = "Your Loki Messenger ID is the unique address that people can use to contact you on Loki Messenger. With no connection to your real identity, your Loki Messenger ID is totally anonymous and private by design.";