Merge pull request #130 from loki-project/ui

Various UI Improvements
pull/132/head
gmbnt 5 years ago committed by GitHub
commit e2b40028d0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -573,6 +573,8 @@
B82B408E239DC00D00A248E7 /* DisplayNameVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = B82B408D239DC00D00A248E7 /* DisplayNameVC.swift */; }; B82B408E239DC00D00A248E7 /* DisplayNameVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = B82B408D239DC00D00A248E7 /* DisplayNameVC.swift */; };
B82B4090239DD75000A248E7 /* RestoreVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = B82B408F239DD75000A248E7 /* RestoreVC.swift */; }; B82B4090239DD75000A248E7 /* RestoreVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = B82B408F239DD75000A248E7 /* RestoreVC.swift */; };
B82B4094239DF15900A248E7 /* ConversationTitleView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B82B4093239DF15900A248E7 /* ConversationTitleView.swift */; }; B82B4094239DF15900A248E7 /* ConversationTitleView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B82B4093239DF15900A248E7 /* ConversationTitleView.swift */; };
B83F2B86240C7B8F000A54AB /* NewConversationButtonSet.swift in Sources */ = {isa = PBXBuildFile; fileRef = B83F2B85240C7B8F000A54AB /* NewConversationButtonSet.swift */; };
B83F2B88240CB75A000A54AB /* UIImage+Scaling.swift in Sources */ = {isa = PBXBuildFile; fileRef = B83F2B87240CB75A000A54AB /* UIImage+Scaling.swift */; };
B846365B22B7418B00AF1514 /* Identicon+ObjC.swift in Sources */ = {isa = PBXBuildFile; fileRef = B846365A22B7418B00AF1514 /* Identicon+ObjC.swift */; }; B846365B22B7418B00AF1514 /* Identicon+ObjC.swift in Sources */ = {isa = PBXBuildFile; fileRef = B846365A22B7418B00AF1514 /* Identicon+ObjC.swift */; };
B84664F5235022F30083A1CD /* MentionUtilities.swift in Sources */ = {isa = PBXBuildFile; fileRef = B84664F4235022F30083A1CD /* MentionUtilities.swift */; }; B84664F5235022F30083A1CD /* MentionUtilities.swift in Sources */ = {isa = PBXBuildFile; fileRef = B84664F4235022F30083A1CD /* MentionUtilities.swift */; };
B847570323D5698100759540 /* LokiPushNotificationManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = B847570223D5698100759540 /* LokiPushNotificationManager.swift */; }; B847570323D5698100759540 /* LokiPushNotificationManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = B847570223D5698100759540 /* LokiPushNotificationManager.swift */; };
@ -587,7 +589,6 @@
B8544E3523D5201400299F14 /* UIView+Constraints.swift in Sources */ = {isa = PBXBuildFile; fileRef = B885D5F52334A32100EE0D8E /* UIView+Constraints.swift */; }; B8544E3523D5201400299F14 /* UIView+Constraints.swift in Sources */ = {isa = PBXBuildFile; fileRef = B885D5F52334A32100EE0D8E /* UIView+Constraints.swift */; };
B86BD08423399ACF000F5AE3 /* Modal.swift in Sources */ = {isa = PBXBuildFile; fileRef = B86BD08323399ACF000F5AE3 /* Modal.swift */; }; B86BD08423399ACF000F5AE3 /* Modal.swift in Sources */ = {isa = PBXBuildFile; fileRef = B86BD08323399ACF000F5AE3 /* Modal.swift */; };
B86BD08623399CEF000F5AE3 /* SeedModal.swift in Sources */ = {isa = PBXBuildFile; fileRef = B86BD08523399CEF000F5AE3 /* SeedModal.swift */; }; B86BD08623399CEF000F5AE3 /* SeedModal.swift in Sources */ = {isa = PBXBuildFile; fileRef = B86BD08523399CEF000F5AE3 /* SeedModal.swift */; };
B8783E9C23EB8DDE00404FB8 /* GeneralUtilities.swift in Sources */ = {isa = PBXBuildFile; fileRef = B8783E9B23EB8DDE00404FB8 /* GeneralUtilities.swift */; };
B8783E9E23EB948D00404FB8 /* UILabel+Interaction.swift in Sources */ = {isa = PBXBuildFile; fileRef = B8783E9D23EB948D00404FB8 /* UILabel+Interaction.swift */; }; B8783E9E23EB948D00404FB8 /* UILabel+Interaction.swift in Sources */ = {isa = PBXBuildFile; fileRef = B8783E9D23EB948D00404FB8 /* UILabel+Interaction.swift */; };
B885D5F4233491AB00EE0D8E /* DeviceLinkingModal.swift in Sources */ = {isa = PBXBuildFile; fileRef = B885D5F3233491AB00EE0D8E /* DeviceLinkingModal.swift */; }; B885D5F4233491AB00EE0D8E /* DeviceLinkingModal.swift in Sources */ = {isa = PBXBuildFile; fileRef = B885D5F3233491AB00EE0D8E /* DeviceLinkingModal.swift */; };
B886B4A72398B23E00211ABE /* QRCodeVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = B886B4A62398B23E00211ABE /* QRCodeVC.swift */; }; B886B4A72398B23E00211ABE /* QRCodeVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = B886B4A62398B23E00211ABE /* QRCodeVC.swift */; };
@ -1416,6 +1417,8 @@
B82B408D239DC00D00A248E7 /* DisplayNameVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DisplayNameVC.swift; sourceTree = "<group>"; }; B82B408D239DC00D00A248E7 /* DisplayNameVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DisplayNameVC.swift; sourceTree = "<group>"; };
B82B408F239DD75000A248E7 /* RestoreVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RestoreVC.swift; sourceTree = "<group>"; }; B82B408F239DD75000A248E7 /* RestoreVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RestoreVC.swift; sourceTree = "<group>"; };
B82B4093239DF15900A248E7 /* ConversationTitleView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConversationTitleView.swift; sourceTree = "<group>"; }; B82B4093239DF15900A248E7 /* ConversationTitleView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConversationTitleView.swift; sourceTree = "<group>"; };
B83F2B85240C7B8F000A54AB /* NewConversationButtonSet.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NewConversationButtonSet.swift; sourceTree = "<group>"; };
B83F2B87240CB75A000A54AB /* UIImage+Scaling.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIImage+Scaling.swift"; sourceTree = "<group>"; };
B846365A22B7418B00AF1514 /* Identicon+ObjC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Identicon+ObjC.swift"; sourceTree = "<group>"; }; B846365A22B7418B00AF1514 /* Identicon+ObjC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Identicon+ObjC.swift"; sourceTree = "<group>"; };
B84664F4235022F30083A1CD /* MentionUtilities.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MentionUtilities.swift; sourceTree = "<group>"; }; B84664F4235022F30083A1CD /* MentionUtilities.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MentionUtilities.swift; sourceTree = "<group>"; };
B847570023D568EB00759540 /* SignalServiceKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = SignalServiceKit.framework; sourceTree = BUILT_PRODUCTS_DIR; }; B847570023D568EB00759540 /* SignalServiceKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = SignalServiceKit.framework; sourceTree = BUILT_PRODUCTS_DIR; };
@ -1429,7 +1432,6 @@
B8544E3223D50E4900299F14 /* AppearanceUtilities.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppearanceUtilities.swift; sourceTree = "<group>"; }; B8544E3223D50E4900299F14 /* AppearanceUtilities.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppearanceUtilities.swift; sourceTree = "<group>"; };
B86BD08323399ACF000F5AE3 /* Modal.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Modal.swift; sourceTree = "<group>"; }; B86BD08323399ACF000F5AE3 /* Modal.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Modal.swift; sourceTree = "<group>"; };
B86BD08523399CEF000F5AE3 /* SeedModal.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SeedModal.swift; sourceTree = "<group>"; }; B86BD08523399CEF000F5AE3 /* SeedModal.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SeedModal.swift; sourceTree = "<group>"; };
B8783E9B23EB8DDE00404FB8 /* GeneralUtilities.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GeneralUtilities.swift; sourceTree = "<group>"; };
B8783E9D23EB948D00404FB8 /* UILabel+Interaction.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UILabel+Interaction.swift"; sourceTree = "<group>"; }; B8783E9D23EB948D00404FB8 /* UILabel+Interaction.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UILabel+Interaction.swift"; sourceTree = "<group>"; };
B885D5F3233491AB00EE0D8E /* DeviceLinkingModal.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeviceLinkingModal.swift; sourceTree = "<group>"; }; B885D5F3233491AB00EE0D8E /* DeviceLinkingModal.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeviceLinkingModal.swift; sourceTree = "<group>"; };
B885D5F52334A32100EE0D8E /* UIView+Constraints.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIView+Constraints.swift"; sourceTree = "<group>"; }; B885D5F52334A32100EE0D8E /* UIView+Constraints.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIView+Constraints.swift"; sourceTree = "<group>"; };
@ -2786,6 +2788,7 @@
B8162F0422892C5F00D46544 /* FriendRequestViewDelegate.swift */, B8162F0422892C5F00D46544 /* FriendRequestViewDelegate.swift */,
B8B26C8E234D629C004ED98C /* MentionCandidateSelectionView.swift */, B8B26C8E234D629C004ED98C /* MentionCandidateSelectionView.swift */,
B8B26C90234D8CBD004ED98C /* MentionCandidateSelectionViewDelegate.swift */, B8B26C90234D8CBD004ED98C /* MentionCandidateSelectionViewDelegate.swift */,
B83F2B85240C7B8F000A54AB /* NewConversationButtonSet.swift */,
B8BB82B02390C37000BA5194 /* SearchBar.swift */, B8BB82B02390C37000BA5194 /* SearchBar.swift */,
B85357BE23A1AE0800AAF6CD /* SeedReminderView.swift */, B85357BE23A1AE0800AAF6CD /* SeedReminderView.swift */,
B85357C023A1B81900AAF6CD /* SeedReminderViewDelegate.swift */, B85357C023A1B81900AAF6CD /* SeedReminderViewDelegate.swift */,
@ -2802,11 +2805,11 @@
children = ( children = (
B8544E3223D50E4900299F14 /* AppearanceUtilities.swift */, B8544E3223D50E4900299F14 /* AppearanceUtilities.swift */,
B8544E3023D16CA500299F14 /* DeviceUtilities.swift */, B8544E3023D16CA500299F14 /* DeviceUtilities.swift */,
B8783E9B23EB8DDE00404FB8 /* GeneralUtilities.swift */,
B847570223D5698100759540 /* LokiPushNotificationManager.swift */, B847570223D5698100759540 /* LokiPushNotificationManager.swift */,
B84664F4235022F30083A1CD /* MentionUtilities.swift */, B84664F4235022F30083A1CD /* MentionUtilities.swift */,
B886B4A82398BA1500211ABE /* QRCode.swift */, B886B4A82398BA1500211ABE /* QRCode.swift */,
B8783E9D23EB948D00404FB8 /* UILabel+Interaction.swift */, B8783E9D23EB948D00404FB8 /* UILabel+Interaction.swift */,
B83F2B87240CB75A000A54AB /* UIImage+Scaling.swift */,
); );
path = Utilities; path = Utilities;
sourceTree = "<group>"; sourceTree = "<group>";
@ -3846,6 +3849,7 @@
340FC8B8204DAC8D007AEB0F /* AddToGroupViewController.m in Sources */, 340FC8B8204DAC8D007AEB0F /* AddToGroupViewController.m in Sources */,
341F2C0F1F2B8AE700D07D6B /* DebugUIMisc.m in Sources */, 341F2C0F1F2B8AE700D07D6B /* DebugUIMisc.m in Sources */,
B893063F2383961A005EAA8E /* ScanQRCodeWrapperVC.swift in Sources */, B893063F2383961A005EAA8E /* ScanQRCodeWrapperVC.swift in Sources */,
B83F2B86240C7B8F000A54AB /* NewConversationButtonSet.swift in Sources */,
340FC8AF204DAC8D007AEB0F /* OWSLinkDeviceViewController.m in Sources */, 340FC8AF204DAC8D007AEB0F /* OWSLinkDeviceViewController.m in Sources */,
34E3EF0D1EFC235B007F6822 /* DebugUIDiskUsage.m in Sources */, 34E3EF0D1EFC235B007F6822 /* DebugUIDiskUsage.m in Sources */,
454A84042059C787008B8C75 /* MediaTileViewController.swift in Sources */, 454A84042059C787008B8C75 /* MediaTileViewController.swift in Sources */,
@ -3883,6 +3887,7 @@
B885D5F4233491AB00EE0D8E /* DeviceLinkingModal.swift in Sources */, B885D5F4233491AB00EE0D8E /* DeviceLinkingModal.swift in Sources */,
45DF5DF21DDB843F00C936C7 /* CompareSafetyNumbersActivity.swift in Sources */, 45DF5DF21DDB843F00C936C7 /* CompareSafetyNumbersActivity.swift in Sources */,
451166C01FD86B98000739BA /* AccountManager.swift in Sources */, 451166C01FD86B98000739BA /* AccountManager.swift in Sources */,
B83F2B88240CB75A000A54AB /* UIImage+Scaling.swift in Sources */,
3430FE181F7751D4000EC51B /* GiphyAPI.swift in Sources */, 3430FE181F7751D4000EC51B /* GiphyAPI.swift in Sources */,
4C2F454F214C00E1004871FF /* AvatarTableViewCell.swift in Sources */, 4C2F454F214C00E1004871FF /* AvatarTableViewCell.swift in Sources */,
346E9D5421B040B700562252 /* RegistrationController.swift in Sources */, 346E9D5421B040B700562252 /* RegistrationController.swift in Sources */,
@ -3900,7 +3905,6 @@
3403B95D20EA9527001A1F44 /* OWSContactShareButtonsView.m in Sources */, 3403B95D20EA9527001A1F44 /* OWSContactShareButtonsView.m in Sources */,
34B0796D1FCF46B100E248C2 /* MainAppContext.m in Sources */, 34B0796D1FCF46B100E248C2 /* MainAppContext.m in Sources */,
34E3EF101EFC2684007F6822 /* DebugUIPage.m in Sources */, 34E3EF101EFC2684007F6822 /* DebugUIPage.m in Sources */,
B8783E9C23EB8DDE00404FB8 /* GeneralUtilities.swift in Sources */,
B80C6B572384A56D00FDBC8B /* DeviceLinksVC.swift in Sources */, B80C6B572384A56D00FDBC8B /* DeviceLinksVC.swift in Sources */,
34A8B3512190A40E00218A25 /* MediaAlbumCellView.swift in Sources */, 34A8B3512190A40E00218A25 /* MediaAlbumCellView.swift in Sources */,
34D1F0AE1F867BFC0066283D /* OWSMessageCell.m in Sources */, 34D1F0AE1F867BFC0066283D /* OWSMessageCell.m in Sources */,

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

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

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

@ -5,7 +5,7 @@
<key>BuildDetails</key> <key>BuildDetails</key>
<dict> <dict>
<key>CarthageVersion</key> <key>CarthageVersion</key>
<string>0.33.0</string> <string>0.34.0</string>
<key>OSXVersion</key> <key>OSXVersion</key>
<string>10.15.3</string> <string>10.15.3</string>
<key>WebRTCCommit</key> <key>WebRTCCommit</key>

@ -884,7 +884,7 @@ static NSTimeInterval launchStartedAt;
return; return;
} }
[SignalApp.sharedApp.homeViewController createPrivateChat]; [SignalApp.sharedApp.homeViewController createNewPrivateChat];
completionHandler(YES); completionHandler(YES);
}]; }];

@ -63,7 +63,7 @@ final class Button : UIButton {
layer.borderColor = borderColor.cgColor layer.borderColor = borderColor.cgColor
layer.borderWidth = Values.borderThickness layer.borderWidth = Values.borderThickness
let fontSize = (size == .small) ? Values.smallFontSize : Values.mediumFontSize let fontSize = (size == .small) ? Values.smallFontSize : Values.mediumFontSize
titleLabel!.font = Fonts.spaceMono(ofSize: fontSize) titleLabel!.font = .boldSystemFont(ofSize: fontSize)
setTitleColor(textColor, for: UIControl.State.normal) setTitleColor(textColor, for: UIControl.State.normal)
} }
} }

@ -42,7 +42,9 @@ final class ConversationCell : UITableViewCell {
private lazy var statusIndicatorView: UIImageView = { private lazy var statusIndicatorView: UIImageView = {
let result = UIImageView() let result = UIImageView()
result.contentMode = .center result.contentMode = .scaleAspectFit
result.layer.cornerRadius = Values.conversationCellStatusIndicatorSize / 2
result.layer.masksToBounds = true
return result return result
}() }()
@ -167,6 +169,7 @@ final class ConversationCell : UITableViewCell {
typingIndicatorView.isHidden = true typingIndicatorView.isHidden = true
typingIndicatorView.stopAnimation() typingIndicatorView.stopAnimation()
} }
statusIndicatorView.backgroundColor = nil
let lastMessage = threadViewModel.lastMessageForInbox let lastMessage = threadViewModel.lastMessageForInbox
if let lastMessage = lastMessage as? TSOutgoingMessage { if let lastMessage = lastMessage as? TSOutgoingMessage {
let image: UIImage let image: UIImage
@ -174,7 +177,9 @@ final class ConversationCell : UITableViewCell {
switch status { switch status {
case .calculatingPoW, .uploading, .sending: image = #imageLiteral(resourceName: "CircleDotDotDot") case .calculatingPoW, .uploading, .sending: image = #imageLiteral(resourceName: "CircleDotDotDot")
case .sent, .skipped, .delivered: image = #imageLiteral(resourceName: "CircleCheck") case .sent, .skipped, .delivered: image = #imageLiteral(resourceName: "CircleCheck")
case .read: image = #imageLiteral(resourceName: "FilledCircleCheck") case .read:
statusIndicatorView.backgroundColor = .white
image = #imageLiteral(resourceName: "FilledCircleCheck")
case .failed: image = #imageLiteral(resourceName: "message_status_failed").asTintedImage(color: Colors.text)! case .failed: image = #imageLiteral(resourceName: "message_status_failed").asTintedImage(color: Colors.text)!
} }
statusIndicatorView.image = image statusIndicatorView.image = image

@ -0,0 +1,310 @@
final class NewConversationButtonSet : UIView {
private var isUserDragging = false
private var horizontalButtonConstraints: [NewConversationButton:NSLayoutConstraint] = [:]
private var verticalButtonConstraints: [NewConversationButton:NSLayoutConstraint] = [:]
private var expandedButton: NewConversationButton?
var delegate: NewConversationButtonSetDelegate?
// MARK: Settings
private let spacing = Values.largeSpacing
private let iconSize = CGFloat(24)
private let maxDragDistance = CGFloat(56)
private let dragMargin = CGFloat(16)
// MARK: Components
private lazy var mainButton = NewConversationButton(isMainButton: true, icon: #imageLiteral(resourceName: "Plus").scaled(to: CGSize(width: iconSize, height: iconSize)))
private lazy var createNewPrivateChatButton = NewConversationButton(isMainButton: false, icon: #imageLiteral(resourceName: "Message").scaled(to: CGSize(width: iconSize, height: iconSize)))
private lazy var createNewClosedGroupButton = NewConversationButton(isMainButton: false, icon: #imageLiteral(resourceName: "Group").scaled(to: CGSize(width: iconSize, height: iconSize)))
private lazy var joinOpenGroupButton = NewConversationButton(isMainButton: false, icon: #imageLiteral(resourceName: "Globe").scaled(to: CGSize(width: iconSize, height: iconSize)))
// MARK: Initialization
override init(frame: CGRect) {
super.init(frame: frame)
setUpViewHierarchy()
}
required init?(coder: NSCoder) {
super.init(coder: coder)
setUpViewHierarchy()
}
private func setUpViewHierarchy() {
let inset = (Values.newConversationButtonExpandedSize - Values.newConversationButtonCollapsedSize) / 2
addSubview(joinOpenGroupButton)
horizontalButtonConstraints[joinOpenGroupButton] = joinOpenGroupButton.pin(.left, to: .left, of: self, withInset: inset)
verticalButtonConstraints[joinOpenGroupButton] = joinOpenGroupButton.pin(.bottom, to: .bottom, of: self, withInset: -inset)
addSubview(createNewPrivateChatButton)
createNewPrivateChatButton.center(.horizontal, in: self)
verticalButtonConstraints[createNewPrivateChatButton] = createNewPrivateChatButton.pin(.top, to: .top, of: self, withInset: inset)
addSubview(createNewClosedGroupButton)
horizontalButtonConstraints[createNewClosedGroupButton] = createNewClosedGroupButton.pin(.right, to: .right, of: self, withInset: -inset)
verticalButtonConstraints[createNewClosedGroupButton] = createNewClosedGroupButton.pin(.bottom, to: .bottom, of: self, withInset: -inset)
addSubview(mainButton)
mainButton.center(.horizontal, in: self)
mainButton.pin(.bottom, to: .bottom, of: self)
let width = 3 * Values.newConversationButtonExpandedSize + 2 * spacing
set(.width, to: width)
let height = 2 * Values.newConversationButtonExpandedSize + spacing
set(.height, to: height)
collapse(withAnimation: false)
isUserInteractionEnabled = true
let mainButtonTapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(handleMainButtonTapped))
mainButton.addGestureRecognizer(mainButtonTapGestureRecognizer)
let joinOpenGroupButtonTapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(handleJoinOpenGroupButtonTapped))
joinOpenGroupButton.addGestureRecognizer(joinOpenGroupButtonTapGestureRecognizer)
let createNewPrivateChatButtonTapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(handleCreateNewPrivateChatButtonTapped))
createNewPrivateChatButton.addGestureRecognizer(createNewPrivateChatButtonTapGestureRecognizer)
let createNewClosedGroupButtonTapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(handleCreateNewClosedGroupButtonTapped))
createNewClosedGroupButton.addGestureRecognizer(createNewClosedGroupButtonTapGestureRecognizer)
}
// MARK: Interaction
@objc private func handleMainButtonTapped() { expand(isUserDragging: false) }
@objc private func handleJoinOpenGroupButtonTapped() { delegate?.joinOpenGroup() }
@objc private func handleCreateNewPrivateChatButtonTapped() { delegate?.createNewPrivateChat() }
@objc private func handleCreateNewClosedGroupButtonTapped() { delegate?.createNewClosedGroup() }
private func expand(isUserDragging: Bool) {
let buttons = [ joinOpenGroupButton, createNewPrivateChatButton, createNewClosedGroupButton ]
UIView.animate(withDuration: 0.25, animations: {
buttons.forEach { $0.alpha = 1 }
let inset = (Values.newConversationButtonExpandedSize - Values.newConversationButtonCollapsedSize) / 2
let size = Values.newConversationButtonCollapsedSize
self.joinOpenGroupButton.frame = CGRect(origin: CGPoint(x: inset, y: self.height() - size - inset), size: CGSize(width: size, height: size))
self.createNewPrivateChatButton.frame = CGRect(center: CGPoint(x: self.bounds.center.x, y: inset + size / 2), size: CGSize(width: size, height: size))
self.createNewClosedGroupButton.frame = CGRect(origin: CGPoint(x: self.width() - size - inset, y: self.height() - size - inset), size: CGSize(width: size, height: size))
}, completion: { _ in
self.isUserDragging = isUserDragging
})
}
private func collapse(withAnimation isAnimated: Bool) {
isUserDragging = false
let buttons = [ joinOpenGroupButton, createNewPrivateChatButton, createNewClosedGroupButton ]
UIView.animate(withDuration: isAnimated ? 0.25 : 0) {
buttons.forEach { button in
button.alpha = 0
let size = Values.newConversationButtonCollapsedSize
button.frame = CGRect(center: self.mainButton.center, size: CGSize(width: size, height: size))
}
}
}
private func reset() {
let mainButtonLocationInSelfCoordinates = CGPoint(x: width() / 2, y: height() - Values.newConversationButtonExpandedSize / 2)
let mainButtonSize = mainButton.frame.size
UIView.animate(withDuration: 0.25) {
self.mainButton.frame = CGRect(center: mainButtonLocationInSelfCoordinates, size: mainButtonSize)
self.mainButton.alpha = 1
}
if let expandedButton = expandedButton { collapse(expandedButton) }
expandedButton = nil
Timer.scheduledTimer(withTimeInterval: 0.25, repeats: false) { _ in
self.collapse(withAnimation: true)
}
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
guard let touch = touches.first, mainButton.contains(touch), !isUserDragging else { return }
UIImpactFeedbackGenerator(style: .medium).impactOccurred()
expand(isUserDragging: true)
}
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
guard let touch = touches.first, isUserDragging else { return }
let mainButtonSize = mainButton.frame.size
let mainButtonLocationInSelfCoordinates = CGPoint(x: width() / 2, y: height() - Values.newConversationButtonExpandedSize / 2)
let touchLocationInSelfCoordinates = touch.location(in: self)
mainButton.frame = CGRect(center: touchLocationInSelfCoordinates, size: mainButtonSize)
mainButton.alpha = 1 - (touchLocationInSelfCoordinates.distance(to: mainButtonLocationInSelfCoordinates) / maxDragDistance)
let buttons = [ joinOpenGroupButton, createNewPrivateChatButton, createNewClosedGroupButton ]
let buttonToExpand = buttons.first { button in
var hasUserDraggedBeyondButton = false
if button == joinOpenGroupButton && touch.isLeft(of: joinOpenGroupButton, with: dragMargin) { hasUserDraggedBeyondButton = true }
if button == createNewPrivateChatButton && touch.isAbove(createNewPrivateChatButton, with: dragMargin) { hasUserDraggedBeyondButton = true }
if button == createNewClosedGroupButton && touch.isRight(of: createNewClosedGroupButton, with: dragMargin) { hasUserDraggedBeyondButton = true }
return button.contains(touch) || hasUserDraggedBeyondButton
}
if let buttonToExpand = buttonToExpand {
guard buttonToExpand != expandedButton else { return }
if let expandedButton = expandedButton { collapse(expandedButton) }
expand(buttonToExpand)
expandedButton = buttonToExpand
} else {
if let expandedButton = expandedButton { collapse(expandedButton) }
expandedButton = nil
}
}
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
guard let touch = touches.first, isUserDragging else { return }
if joinOpenGroupButton.contains(touch) || touch.isLeft(of: joinOpenGroupButton, with: dragMargin) { delegate?.joinOpenGroup() }
else if createNewPrivateChatButton.contains(touch) || touch.isAbove(createNewPrivateChatButton, with: dragMargin) { delegate?.createNewPrivateChat() }
else if createNewClosedGroupButton.contains(touch) || touch.isRight(of: createNewClosedGroupButton, with: dragMargin) { delegate?.createNewClosedGroup() }
reset()
}
override func touchesCancelled(_ touches: Set<UITouch>, with event: UIEvent?) {
guard isUserDragging else { return }
reset()
}
private func expand(_ button: NewConversationButton) {
if let horizontalConstraint = horizontalButtonConstraints[button] { horizontalConstraint.constant = 0 }
if let verticalConstraint = verticalButtonConstraints[button] { verticalConstraint.constant = 0 }
let size = Values.newConversationButtonExpandedSize
let frame = CGRect(center: button.center, size: CGSize(width: size, height: size))
button.widthConstraint.constant = size
button.heightConstraint.constant = size
UIView.animate(withDuration: 0.25) {
self.layoutIfNeeded()
button.frame = frame
button.layer.cornerRadius = size / 2
button.addGlow(ofSize: size)
button.backgroundColor = Colors.accent
}
}
private func collapse(_ button: NewConversationButton) {
let inset = (Values.newConversationButtonExpandedSize - Values.newConversationButtonCollapsedSize) / 2
if joinOpenGroupButton == expandedButton {
horizontalButtonConstraints[joinOpenGroupButton]!.constant = inset
verticalButtonConstraints[joinOpenGroupButton]!.constant = -inset
} else if createNewPrivateChatButton == expandedButton {
verticalButtonConstraints[createNewPrivateChatButton]!.constant = inset
} else if createNewClosedGroupButton == expandedButton {
horizontalButtonConstraints[createNewClosedGroupButton]!.constant = -inset
verticalButtonConstraints[createNewClosedGroupButton]!.constant = -inset
}
let size = Values.newConversationButtonCollapsedSize
let frame = CGRect(center: button.center, size: CGSize(width: size, height: size))
button.widthConstraint.constant = size
button.heightConstraint.constant = size
UIView.animate(withDuration: 0.25) {
self.layoutIfNeeded()
button.frame = frame
button.layer.cornerRadius = size / 2
button.removeGlow()
button.backgroundColor = Colors.newConversationButtonCollapsedBackground
}
}
override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
if !bounds.contains(point), isUserDragging { collapse(withAnimation: true) }
return super.hitTest(point, with: event)
}
}
// MARK: Delegate
protocol NewConversationButtonSetDelegate {
func joinOpenGroup()
func createNewPrivateChat()
func createNewClosedGroup()
}
// MARK: Button
private final class NewConversationButton : UIImageView {
private let isMainButton: Bool
private let icon: UIImage
var widthConstraint: NSLayoutConstraint!
var heightConstraint: NSLayoutConstraint!
// Initialization
init(isMainButton: Bool, icon: UIImage) {
self.isMainButton = isMainButton
self.icon = icon
super.init(frame: CGRect.zero)
setUpViewHierarchy()
}
override init(frame: CGRect) {
preconditionFailure("Use init(isMainButton:) instead.")
}
required init?(coder: NSCoder) {
preconditionFailure("Use init(isMainButton:) instead.")
}
private func setUpViewHierarchy() {
backgroundColor = isMainButton ? Colors.accent : Colors.newConversationButtonCollapsedBackground
let size = isMainButton ? Values.newConversationButtonExpandedSize : Values.newConversationButtonCollapsedSize
layer.cornerRadius = size / 2
if isMainButton { addGlow(ofSize: size) }
layer.masksToBounds = false
image = icon
contentMode = .center
widthConstraint = set(.width, to: size)
heightConstraint = set(.height, to: size)
}
// General
func addGlow(ofSize size: CGFloat) {
layer.shadowPath = UIBezierPath(ovalIn: CGRect(origin: CGPoint(x: 0, y: 0), size: CGSize(width: size, height: size))).cgPath
layer.shadowColor = Colors.newConversationButtonShadow.cgColor
layer.shadowOffset = CGSize(width: 0, height: 0.8)
layer.shadowOpacity = 1
layer.shadowRadius = 6
}
func removeGlow() {
layer.shadowPath = nil
layer.shadowColor = nil
layer.shadowOffset = CGSize.zero
layer.shadowOpacity = 0
layer.shadowRadius = 0
}
}
// MARK: Convenience
private extension UIView {
func contains(_ touch: UITouch) -> Bool {
return bounds.contains(touch.location(in: self))
}
}
private extension UITouch {
func isLeft(of view: UIView, with margin: CGFloat = 0) -> Bool {
return isContainedVertically(in: view, with: margin) && location(in: view).x < view.bounds.minX
}
func isAbove(_ view: UIView, with margin: CGFloat = 0) -> Bool {
return isContainedHorizontally(in: view, with: margin) && location(in: view).y < view.bounds.minY
}
func isRight(of view: UIView, with margin: CGFloat = 0) -> Bool {
return isContainedVertically(in: view, with: margin) && location(in: view).x > view.bounds.maxX
}
func isBelow(_ view: UIView, with margin: CGFloat = 0) -> Bool {
return isContainedHorizontally(in: view, with: margin) && location(in: view).y > view.bounds.maxY
}
private func isContainedHorizontally(in view: UIView, with margin: CGFloat = 0) -> Bool {
return ((view.bounds.minX - margin)...(view.bounds.maxX + margin)) ~= location(in: view).x
}
private func isContainedVertically(in view: UIView, with margin: CGFloat = 0) -> Bool {
return ((view.bounds.minY - margin)...(view.bounds.maxY + margin)) ~= location(in: view).y
}
}
private extension CGPoint {
func distance(to otherPoint: CGPoint) -> CGFloat {
return sqrt(pow(self.x - otherPoint.x, 2) + pow(self.y - otherPoint.y, 2))
}
}
private extension CGRect {
init(center: CGPoint, size: CGSize) {
let originX = center.x - size.width / 2
let originY = center.y - size.height / 2
let origin = CGPoint(x: originX, y: originY)
self.init(origin: origin, size: size)
}
}

@ -35,4 +35,5 @@ final class Colors : NSObject {
@objc static let composeViewTextFieldBackground = UIColor(hex: 0x141414) @objc static let composeViewTextFieldBackground = UIColor(hex: 0x141414)
@objc static let receivedMessageBackground = UIColor(hex: 0x222325) @objc static let receivedMessageBackground = UIColor(hex: 0x222325)
@objc static let sentMessageBackground = UIColor(hex: 0x3F4146) @objc static let sentMessageBackground = UIColor(hex: 0x3F4146)
@objc static let newConversationButtonCollapsedBackground = UIColor(hex: 0x1F1F1F)
} }

@ -26,5 +26,6 @@ final class Gradient : NSObject {
@objc(LKGradients) @objc(LKGradients)
final class Gradients : NSObject { final class Gradients : NSObject {
@objc static let defaultLokiBackground = Gradient(start: UIColor(hex: 0x171717), end: UIColor(hex:0x121212)) @objc static let defaultLokiBackground = Gradient(start: UIColor(hex: 0x171717), end: UIColor(hex: 0x121212))
@objc static let transparentToBlack75 = Gradient(start: UIColor(red: 0, green: 0, blue: 0, alpha: 0), end: UIColor(red: 0, green: 0, blue: 0, alpha: 0.75))
} }

@ -30,7 +30,8 @@ final class Values : NSObject {
@objc static let borderThickness = CGFloat(1) @objc static let borderThickness = CGFloat(1)
@objc static let conversationCellStatusIndicatorSize = CGFloat(14) @objc static let conversationCellStatusIndicatorSize = CGFloat(14)
@objc static let searchBarHeight = CGFloat(36) @objc static let searchBarHeight = CGFloat(36)
@objc static let newConversationButtonSize = CGFloat(45) @objc static let newConversationButtonCollapsedSize = CGFloat(48)
@objc static let newConversationButtonExpandedSize = CGFloat(60)
@objc static let textFieldHeight = isSmallScreen ? CGFloat(48) : CGFloat(80) @objc static let textFieldHeight = isSmallScreen ? CGFloat(48) : CGFloat(80)
@objc static let textFieldCornerRadius = CGFloat(8) @objc static let textFieldCornerRadius = CGFloat(8)
@objc static let separatorLabelHeight = CGFloat(24) @objc static let separatorLabelHeight = CGFloat(24)

@ -1,29 +0,0 @@
@objc(LKGeneralUtilities)
final class GeneralUtilities : NSObject {
private override init() { }
@objc static func getSessionPublicChatNotice() -> String {
return """
Welcome to the Session public chat! In order for this forum to be a fun environment, full of robust and constructive discussion and inclusive of everyone, please read and follow the rules below.
1. Please Keep Talk Relevant to Topic and Add Value to the Discussion.
(No Referral Links, Spamming, Off Topic Discussion)
2. You don't have to love everyone, but be civil.
(No Baiting, Excessively Partisan Arguments, Threats, and so on. Use common sense.)
3. Do not be a shill.
Comparison and criticism is reasonable, but blatant shilling of anything you work for, work on, or own is not.
4. Don't post explicit content - be it excessively offensive language, sexual, or violent. Any form of bigotry including racism, sexism, transphobia, homophobia, ableism, fatphobia, classism will NOT be tolerated.
If you break these rules, youll be warned by an admin. If your behaviour doesnt improve, you will be removed from the public chat. Admins reserve the right to remove anyone violating these rules.
We want to keep this group a pleasant and supportive space for everyone.
If you experience any anti-social behaviour or have an issue with these rules, please contact an admin.
"""
}
}

@ -0,0 +1,17 @@
extension UIImage {
func scaled(to size: CGSize) -> UIImage {
var rect = CGRect.zero
let aspectRatio = min(size.width / self.size.width, size.height / self.size.height)
rect.size.width = self.size.width * aspectRatio
rect.size.height = self.size.height * aspectRatio
rect.origin.x = (size.width - rect.size.width) / 2
rect.origin.y = (size.height - rect.size.height) / 2
UIGraphicsBeginImageContextWithOptions(size, false, 0)
draw(in: rect)
let result = UIGraphicsGetImageFromCurrentImageContext()!
UIGraphicsEndImageContext()
return result
}
}

@ -24,7 +24,7 @@ final class DeviceLinksVC : UIViewController, UITableViewDataSource, UITableView
explanationLabel.lineBreakMode = .byWordWrapping explanationLabel.lineBreakMode = .byWordWrapping
explanationLabel.textAlignment = .center explanationLabel.textAlignment = .center
explanationLabel.text = NSLocalizedString("You haven't linked any devices yet", comment: "") explanationLabel.text = NSLocalizedString("You haven't linked any devices yet", comment: "")
let linkNewDeviceButton = Button(style: .prominentOutline, size: .medium) let linkNewDeviceButton = Button(style: .prominentOutline, size: .large)
linkNewDeviceButton.setTitle(NSLocalizedString("Link a Device", comment: ""), for: UIControl.State.normal) linkNewDeviceButton.setTitle(NSLocalizedString("Link a Device", comment: ""), for: UIControl.State.normal)
linkNewDeviceButton.addTarget(self, action: #selector(linkNewDevice), for: UIControl.Event.touchUpInside) linkNewDeviceButton.addTarget(self, action: #selector(linkNewDevice), for: UIControl.Event.touchUpInside)
linkNewDeviceButton.set(.width, to: 160) linkNewDeviceButton.set(.width, to: 160)

@ -1,5 +1,5 @@
final class HomeVC : UIViewController, UITableViewDataSource, UITableViewDelegate, UIScrollViewDelegate, UIViewControllerPreviewingDelegate, SeedReminderViewDelegate { final class HomeVC : UIViewController, UITableViewDataSource, UITableViewDelegate, UIScrollViewDelegate, UIViewControllerPreviewingDelegate, NewConversationButtonSetDelegate, SeedReminderViewDelegate {
private var threadViewModelCache: [String:ThreadViewModel] = [:] private var threadViewModelCache: [String:ThreadViewModel] = [:]
private var isObservingDatabase = true private var isObservingDatabase = true
private var isViewVisible = false { didSet { updateIsObservingDatabase() } } private var isViewVisible = false { didSet { updateIsObservingDatabase() } }
@ -45,23 +45,17 @@ final class HomeVC : UIViewController, UITableViewDataSource, UITableViewDelegat
return result return result
}() }()
private lazy var newConversationButton: UIButton = { private lazy var newConversationButtonSet: NewConversationButtonSet = {
let result = UIButton() let result = NewConversationButtonSet()
result.setTitle("+", for: UIControl.State.normal) result.delegate = self
result.titleLabel!.font = .systemFont(ofSize: 35) return result
result.setTitleColor(UIColor(hex: 0x121212), for: UIControl.State.normal) }()
result.titleEdgeInsets = UIEdgeInsets(top: 0, left: 1, bottom: 4, right: 0) // Slight adjustment to make the plus exactly centered
result.backgroundColor = Colors.accent private lazy var fadeView: UIView = {
let size = Values.newConversationButtonSize let result = UIView()
result.layer.cornerRadius = size / 2 let gradient = Gradients.transparentToBlack75
result.layer.shadowPath = UIBezierPath(ovalIn: CGRect(origin: CGPoint(x: 0, y: 0), size: CGSize(width: size, height: size))).cgPath result.setGradient(gradient)
result.layer.shadowColor = Colors.newConversationButtonShadow.cgColor result.isUserInteractionEnabled = false
result.layer.shadowOffset = CGSize(width: 0, height: 0.8)
result.layer.shadowOpacity = 1
result.layer.shadowRadius = 6
result.layer.masksToBounds = false
result.set(.width, to: size)
result.set(.height, to: size)
return result return result
}() }()
@ -109,15 +103,16 @@ final class HomeVC : UIViewController, UITableViewDataSource, UITableViewDelegat
} }
tableView.pin(.trailing, to: .trailing, of: view) tableView.pin(.trailing, to: .trailing, of: view)
tableView.pin(.bottom, to: .bottom, of: view) tableView.pin(.bottom, to: .bottom, of: view)
view.addSubview(fadeView)
fadeView.pin(to: view)
// Set up search bar // Set up search bar
// tableView.tableHeaderView = searchBar // tableView.tableHeaderView = searchBar
// searchBar.sizeToFit() // searchBar.sizeToFit()
// tableView.contentOffset = CGPoint(x: 0, y: searchBar.frame.height) // tableView.contentOffset = CGPoint(x: 0, y: searchBar.frame.height)
// Set up new conversation button // Set up new conversation button set
newConversationButton.addTarget(self, action: #selector(createPrivateChat), for: UIControl.Event.touchUpInside) view.addSubview(newConversationButtonSet)
view.addSubview(newConversationButton) newConversationButtonSet.center(.horizontal, in: view)
newConversationButton.center(.horizontal, in: view) newConversationButtonSet.pin(.bottom, to: .bottom, of: view, withInset: -Values.newConversationButtonBottomOffset) // Negative due to how the constraint is set up
newConversationButton.pin(.bottom, to: .bottom, of: view, withInset: -Values.newConversationButtonBottomOffset) // Negative due to how the constraint is set up
// Set up previewing // Set up previewing
if (traitCollection.forceTouchCapability == .available) { if (traitCollection.forceTouchCapability == .available) {
registerForPreviewing(with: self, sourceView: tableView) registerForPreviewing(with: self, sourceView: tableView)
@ -261,17 +256,6 @@ final class HomeVC : UIViewController, UITableViewDataSource, UITableViewDelegat
let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(openSettings)) let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(openSettings))
profilePictureView.addGestureRecognizer(tapGestureRecognizer) profilePictureView.addGestureRecognizer(tapGestureRecognizer)
navigationItem.leftBarButtonItem = UIBarButtonItem(customView: profilePictureView) navigationItem.leftBarButtonItem = UIBarButtonItem(customView: profilePictureView)
let newClosedGroupButton = UIButton(type: .custom)
newClosedGroupButton.setImage(#imageLiteral(resourceName: "btnGroup--white"), for: UIControl.State.normal)
newClosedGroupButton.addTarget(self, action: #selector(createClosedGroup), for: UIControl.Event.touchUpInside)
newClosedGroupButton.tintColor = Colors.text
let joinPublicChatButton = UIButton(type: .custom)
joinPublicChatButton.setImage(#imageLiteral(resourceName: "Globe"), for: UIControl.State.normal)
joinPublicChatButton.addTarget(self, action: #selector(joinPublicChat), for: UIControl.Event.touchUpInside)
joinPublicChatButton.tintColor = Colors.text
let buttonStackView = UIStackView(arrangedSubviews: [ newClosedGroupButton, joinPublicChatButton ])
buttonStackView.axis = .horizontal
navigationItem.rightBarButtonItem = UIBarButtonItem(customView: buttonStackView)
} }
// MARK: Interaction // MARK: Interaction
@ -371,21 +355,21 @@ final class HomeVC : UIViewController, UITableViewDataSource, UITableViewDelegat
present(navigationController, animated: true, completion: nil) present(navigationController, animated: true, completion: nil)
} }
@objc private func joinPublicChat() { @objc func joinOpenGroup() {
let joinPublicChatVC = JoinPublicChatVC() let joinPublicChatVC = JoinPublicChatVC()
let navigationController = OWSNavigationController(rootViewController: joinPublicChatVC) let navigationController = OWSNavigationController(rootViewController: joinPublicChatVC)
present(navigationController, animated: true, completion: nil) present(navigationController, animated: true, completion: nil)
} }
@objc private func createClosedGroup() { @objc func createNewPrivateChat() {
let newClosedGroupVC = NewClosedGroupVC() let newPrivateChatVC = NewPrivateChatVC()
let navigationController = OWSNavigationController(rootViewController: newClosedGroupVC) let navigationController = OWSNavigationController(rootViewController: newPrivateChatVC)
present(navigationController, animated: true, completion: nil) present(navigationController, animated: true, completion: nil)
} }
@objc func createPrivateChat() { @objc func createNewClosedGroup() {
let newPrivateChatVC = NewPrivateChatVC() let newClosedGroupVC = NewClosedGroupVC()
let navigationController = OWSNavigationController(rootViewController: newPrivateChatVC) let navigationController = OWSNavigationController(rootViewController: newClosedGroupVC)
present(navigationController, animated: true, completion: nil) present(navigationController, animated: true, completion: nil)
} }

@ -65,7 +65,8 @@ final class NewClosedGroupVC : UIViewController, UITableViewDataSource, UITableV
let titleLabel = UILabel() let titleLabel = UILabel()
titleLabel.text = NSLocalizedString("New Closed Group", comment: "") titleLabel.text = NSLocalizedString("New Closed Group", comment: "")
titleLabel.textColor = Colors.text titleLabel.textColor = Colors.text
titleLabel.font = .boldSystemFont(ofSize: Values.veryLargeFontSize) let titleLabelFontSize = isSmallScreen ? Values.largeFontSize : Values.veryLargeFontSize
titleLabel.font = .boldSystemFont(ofSize: titleLabelFontSize)
navigationItem.titleView = titleLabel navigationItem.titleView = titleLabel
// Set up content // Set up content
if !contacts.isEmpty { if !contacts.isEmpty {
@ -104,9 +105,9 @@ final class NewClosedGroupVC : UIViewController, UITableViewDataSource, UITableV
explanationLabel.lineBreakMode = .byWordWrapping explanationLabel.lineBreakMode = .byWordWrapping
explanationLabel.textAlignment = .center explanationLabel.textAlignment = .center
explanationLabel.text = NSLocalizedString("You don't have any contacts yet", comment: "") explanationLabel.text = NSLocalizedString("You don't have any contacts yet", comment: "")
let createNewPrivateChatButton = Button(style: .prominentOutline, size: .medium) let createNewPrivateChatButton = Button(style: .prominentOutline, size: .large)
createNewPrivateChatButton.setTitle(NSLocalizedString("Start a Session", comment: ""), for: UIControl.State.normal) createNewPrivateChatButton.setTitle(NSLocalizedString("Start a Session", comment: ""), for: UIControl.State.normal)
createNewPrivateChatButton.addTarget(self, action: #selector(createPrivateChat), for: UIControl.Event.touchUpInside) createNewPrivateChatButton.addTarget(self, action: #selector(createNewPrivateChat), for: UIControl.Event.touchUpInside)
createNewPrivateChatButton.set(.width, to: 160) createNewPrivateChatButton.set(.width, to: 160)
let stackView = UIStackView(arrangedSubviews: [ explanationLabel, createNewPrivateChatButton ]) let stackView = UIStackView(arrangedSubviews: [ explanationLabel, createNewPrivateChatButton ])
stackView.axis = .vertical stackView.axis = .vertical
@ -200,9 +201,9 @@ final class NewClosedGroupVC : UIViewController, UITableViewDataSource, UITableV
} }
} }
@objc private func createPrivateChat() { @objc private func createNewPrivateChat() {
presentingViewController?.dismiss(animated: true, completion: nil) presentingViewController?.dismiss(animated: true, completion: nil)
SignalApp.shared().homeViewController!.createPrivateChat() SignalApp.shared().homeViewController!.createNewPrivateChat()
} }
} }

@ -71,7 +71,8 @@ final class SeedVC : UIViewController {
let navigationBarTitleLabel = UILabel() let navigationBarTitleLabel = UILabel()
navigationBarTitleLabel.text = NSLocalizedString("Your Recovery Phrase", comment: "") navigationBarTitleLabel.text = NSLocalizedString("Your Recovery Phrase", comment: "")
navigationBarTitleLabel.textColor = Colors.text navigationBarTitleLabel.textColor = Colors.text
navigationBarTitleLabel.font = .boldSystemFont(ofSize: Values.veryLargeFontSize) let titleLabelFontSize = isSmallScreen ? Values.largeFontSize : Values.veryLargeFontSize
navigationBarTitleLabel.font = .boldSystemFont(ofSize: titleLabelFontSize)
navigationItem.titleView = navigationBarTitleLabel navigationItem.titleView = navigationBarTitleLabel
// Set up navigation bar buttons // Set up navigation bar buttons
let closeButton = UIBarButtonItem(image: #imageLiteral(resourceName: "X"), style: .plain, target: self, action: #selector(close)) let closeButton = UIBarButtonItem(image: #imageLiteral(resourceName: "X"), style: .plain, target: self, action: #selector(close))
@ -145,7 +146,7 @@ final class SeedVC : UIViewController {
let mainStackView = UIStackView(arrangedSubviews: [ topSpacer, topStackViewContainer, bottomSpacer, copyButtonContainer ]) let mainStackView = UIStackView(arrangedSubviews: [ topSpacer, topStackViewContainer, bottomSpacer, copyButtonContainer ])
mainStackView.axis = .vertical mainStackView.axis = .vertical
mainStackView.alignment = .fill mainStackView.alignment = .fill
mainStackView.layoutMargins = UIEdgeInsets(top: 0, leading: 0, bottom: isSmallScreen ? Values.smallSpacing : Values.mediumSpacing, trailing: 0) mainStackView.layoutMargins = UIEdgeInsets(top: 0, leading: 0, bottom: Values.mediumSpacing, trailing: 0)
mainStackView.isLayoutMarginsRelativeArrangement = true mainStackView.isLayoutMarginsRelativeArrangement = true
view.addSubview(mainStackView) view.addSubview(mainStackView)
mainStackView.pin(.leading, to: .leading, of: view) mainStackView.pin(.leading, to: .leading, of: view)

@ -1440,14 +1440,6 @@ typedef enum : NSUInteger {
[self updateInputToolbarLayout]; [self updateInputToolbarLayout];
[self ensureScrollDownButton]; [self ensureScrollDownButton];
NSUserDefaults *userDefaults = NSUserDefaults.standardUserDefaults;
if ([@"Session Public Chat" isEqual:self.thread.name] && ![userDefaults boolForKey:@"hasSeenSessionPublicChatNotice"]) {
UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"The Rules" message:[LKGeneralUtilities getSessionPublicChatNotice] preferredStyle:UIAlertControllerStyleAlert];
[alert addAction:[UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:nil]];
[self presentViewController:alert animated:YES completion:nil];
[userDefaults setBool:YES forKey:@"hasSeenSessionPublicChatNotice"];
}
} }
// `viewWillDisappear` is called whenever the view *starts* to disappear, // `viewWillDisappear` is called whenever the view *starts* to disappear,

Loading…
Cancel
Save