Fixed issues found during testing

Fixed an issue where the user config message wouldn't get sent correctly
Fixed an issue where the theme preference migration wasn't working properly
Fixed a crash which could occur in some cases when updating the theme
Fixed a crash which could occur when opening the new conversation screen with a contact with no name
Fixed a minor UI glitch with the 'sessionId' separator border
Fixed a minor UI issue where long author names in quotes could cause the message bubble to stretch incorrectly
Cleaned up some no-contact UI states
Updated the Atomic queue to have a 'userInteractive' priority so it can't be delayed by lower priority queues and block the main thread
pull/672/head
Morgan Pretty 2 years ago
parent 47083cca38
commit 58184d6d27

@ -161,25 +161,14 @@ final class NewClosedGroupVC: BaseVC, UITableViewDataSource, UITableViewDelegate
let explanationLabel: UILabel = UILabel()
explanationLabel.font = .systemFont(ofSize: Values.smallFontSize)
explanationLabel.text = "vc_create_closed_group_empty_state_message".localized()
explanationLabel.themeTextColor = .textPrimary
explanationLabel.themeTextColor = .textSecondary
explanationLabel.textAlignment = .center
explanationLabel.lineBreakMode = .byWordWrapping
explanationLabel.numberOfLines = 0
let createNewPrivateChatButton: SessionButton = SessionButton(style: .bordered, size: .medium)
createNewPrivateChatButton.setTitle("vc_create_closed_group_empty_state_button_title".localized(), for: .normal)
createNewPrivateChatButton.addTarget(self, action: #selector(createNewDM), for: .touchUpInside)
createNewPrivateChatButton.set(.width, to: 196)
let stackView: UIStackView = UIStackView(arrangedSubviews: [ explanationLabel, createNewPrivateChatButton ])
stackView.axis = .vertical
stackView.spacing = Values.mediumSpacing
stackView.alignment = .center
view.addSubview(stackView)
stackView.center(.horizontal, in: view)
let verticalCenteringConstraint = stackView.center(.vertical, in: view)
verticalCenteringConstraint.constant = -16 // Makes things appear centered visually
view.addSubview(explanationLabel)
explanationLabel.pin(.top, to: .top, of: view, withInset: Values.largeSpacing)
explanationLabel.center(.horizontal, in: view)
return
}
@ -348,12 +337,6 @@ final class NewClosedGroupVC: BaseVC, UITableViewDataSource, UITableViewDelegate
.retainUntilComplete()
}
}
@objc private func createNewDM() {
presentingViewController?.dismiss(animated: true, completion: nil)
SessionApp.homeViewController.wrappedValue?.createNewDM()
}
}
extension NewClosedGroupVC: UISearchBarDelegate {

@ -519,6 +519,7 @@ final class VisibleMessageCell: MessageCell, TappableLabelDelegate {
// Constraints
bubbleView.addSubview(stackView)
stackView.pin(to: bubbleView, withInset: inset)
stackView.widthAnchor.constraint(lessThanOrEqualToConstant: maxWidth).isActive = true
snContentView.addArrangedSubview(bubbleBackgroundView)
}

@ -185,7 +185,7 @@ final class HomeVC: BaseVC, UITableViewDataSource, UITableViewDelegate, SeedRemi
let createNewPrivateChatButton = SessionButton(style: .bordered, size: .large)
createNewPrivateChatButton.setTitle("vc_home_empty_state_button_title".localized(), for: .normal)
createNewPrivateChatButton.addTarget(self, action: #selector(createNewDM), for: .touchUpInside)
createNewPrivateChatButton.addTarget(self, action: #selector(createNewConversation), for: .touchUpInside)
createNewPrivateChatButton.set(.width, to: Values.iPadButtonWidth)
let result = UIStackView(arrangedSubviews: [ explanationLabel, createNewPrivateChatButton ])
@ -771,16 +771,6 @@ final class HomeVC: BaseVC, UITableViewDataSource, UITableViewDelegate, SeedRemi
present(navigationController, animated: true, completion: nil)
}
@objc func createNewDM() {
let newDMVC = NewDMVC(shouldShowBackButton: false)
let navigationController = StyledNavigationController(rootViewController: newDMVC)
if UIDevice.current.isIPad {
navigationController.modalPresentationStyle = .fullScreen
}
navigationController.modalPresentationCapturesStatusBarAppearance = true
present(navigationController, animated: true, completion: nil)
}
func createNewDMFromDeepLink(sessionId: String) {
let newDMVC = NewDMVC(sessionId: sessionId, shouldShowBackButton: false)
let navigationController = StyledNavigationController(rootViewController: newDMVC)

@ -50,8 +50,14 @@ final class NewConversationVC: BaseVC, ThemedNavigation, UITableViewDelegate, UI
private lazy var contactsTitleLabel: UILabel = {
let result: UILabel = UILabel()
result.font = .systemFont(ofSize: Values.mediumFontSize)
result.text = "Contacts"
result.themeTextColor = .textPrimary
result.text = (newConversationViewModel.sectionData.isEmpty ?
"vc_create_closed_group_empty_state_message".localized() :
"Contacts"
)
result.themeTextColor = (newConversationViewModel.sectionData.isEmpty ?
.textSecondary :
.textPrimary
)
return result
}()

@ -20,18 +20,21 @@ public class NewConversationViewModel {
let displayName = NSMutableString(string: profile.displayName())
CFStringTransform(displayName, nil, kCFStringTransformToLatin, false)
CFStringTransform(displayName, nil, kCFStringTransformStripDiacritics, false)
let section: String = displayName.substring(to: 1).capitalized.isSingleAlphabet ?
displayName.substring(to: 1).capitalized :
let initialCharacter: String = (displayName.length > 0 ? displayName.substring(to: 1) : "")
let section: String = initialCharacter.capitalized.isSingleAlphabet ?
initialCharacter.capitalized :
"#"
if groupedContacts[section] == nil {
groupedContacts[section] = SectionData(
sectionName: section,
contacts: [])
contacts: []
)
}
groupedContacts[section]?.contacts.append(profile)
}
sectionData = groupedContacts.values.sorted{ $0.sectionName < $1.sectionName }
sectionData = groupedContacts.values.sorted { $0.sectionName < $1.sectionName }
}
}

@ -481,7 +481,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
AppReadiness.runNowOrWhenAppDidBecomeReady {
guard Identity.userExists() else { return }
SessionApp.homeViewController.wrappedValue?.createNewDM()
SessionApp.homeViewController.wrappedValue?.createNewConversation()
completionHandler(true)
}
}

@ -193,9 +193,8 @@ extension MessageSender {
// fresh install due to the migrations getting run)
guard Identity.userExists(db) else { return Promise(error: StorageError.generic) }
let destination: Message.Destination = Message.Destination.contact(
publicKey: getUserHexEncodedPublicKey(db)
)
let publicKey: String = getUserHexEncodedPublicKey(db)
let destination: Message.Destination = Message.Destination.contact(publicKey: publicKey)
let configurationMessage = try ConfigurationMessage.getCurrent(db)
let (promise, seal) = Promise<Void>.pending()
@ -211,6 +210,7 @@ extension MessageSender {
db,
job: Job(
variant: .messageSend,
threadId: publicKey,
details: MessageSendJob.Details(
destination: destination,
message: configurationMessage

@ -7,6 +7,22 @@ public final class Separator: UIView {
// MARK: - Components
private let leftLine: UIView = {
let result: UIView = UIView()
result.themeBackgroundColor = .textSecondary
result.set(.height, to: Values.separatorThickness)
return result
}()
private let roundedLine: UIView = {
let result: UIView = UIView()
result.themeBorderColor = .textSecondary
result.layer.borderWidth = Values.separatorThickness
return result
}()
private lazy var titleLabel: UILabel = {
let result = UILabel()
result.font = .systemFont(ofSize: Values.smallFontSize)
@ -16,11 +32,10 @@ public final class Separator: UIView {
return result
}()
private lazy var lineLayer: CAShapeLayer = {
let result = CAShapeLayer()
result.lineWidth = Values.separatorThickness
result.themeStrokeColor = .textSecondary
result.themeFillColor = .clear
private let rightLine: UIView = {
let result: UIView = UIView()
result.themeBackgroundColor = .textSecondary
result.set(.height, to: Values.separatorThickness)
return result
}()
@ -47,40 +62,35 @@ public final class Separator: UIView {
private func setUpViewHierarchy(title: String?) {
titleLabel.text = title
addSubview(leftLine)
addSubview(roundedLine)
addSubview(rightLine)
addSubview(titleLabel)
titleLabel.center(.horizontal, in: self)
titleLabel.center(.vertical, in: self)
layer.insertSublayer(lineLayer, at: 0)
set(.height, to: Separator.height)
roundedLine.pin(.top, to: .top, of: self)
roundedLine.pin(.top, to: .top, of: titleLabel, withInset: -6)
roundedLine.pin(.leading, to: .leading, of: titleLabel, withInset: -10)
roundedLine.pin(.trailing, to: .trailing, of: titleLabel, withInset: 10)
roundedLine.pin(.bottom, to: .bottom, of: titleLabel, withInset: 6)
roundedLine.pin(.bottom, to: .bottom, of: self)
leftLine.pin(.leading, to: .leading, of: self)
leftLine.pin(.trailing, to: .leading, of: roundedLine)
leftLine.center(.vertical, in: self)
rightLine.pin(.leading, to: .trailing, of: roundedLine)
rightLine.pin(.trailing, to: .trailing, of: self)
rightLine.center(.vertical, in: self)
}
// MARK: - Updating
public override func layoutSubviews() {
super.layoutSubviews()
updateLineLayer()
roundedLine.layer.cornerRadius = (roundedLine.bounds.height / 2)
}
private func updateLineLayer() {
let w = bounds.width
let h = bounds.height
let path = UIBezierPath()
path.move(to: CGPoint(x: 0, y: h / 2))
let titleLabelFrame = titleLabel.frame.insetBy(dx: -10, dy: -6)
path.addLine(to: CGPoint(x: titleLabelFrame.origin.x, y: h / 2))
let oval = UIBezierPath(roundedRect: titleLabelFrame, cornerRadius: Separator.height / 2)
path.append(oval)
path.move(to: CGPoint(x: titleLabelFrame.origin.x + titleLabelFrame.width, y: h / 2))
path.addLine(to: CGPoint(x: w, y: h / 2))
path.close()
lineLayer.path = path.cgPath
}
// MARK: - Updating
public func update(title: String?) {
titleLabel.text = title

@ -13,21 +13,32 @@ enum _001_ThemePreferences: Migration {
static let minExpectedRunDuration: TimeInterval = 0.1
static func migrate(_ db: Database) throws {
// Determine if the user was matching the system setting
let isMatchingSystemSetting: Bool = UserDefaults.standard.dictionaryRepresentation()
// Determine if the user was matching the system setting (previously the absence of this value
// indicated that the app should match the system setting)
let isExistingUser: Bool = Identity.userExists(db)
let hadCustomLegacyThemeSetting: Bool = UserDefaults.standard.dictionaryRepresentation()
.keys
.contains("appMode")
// Set the default theme settings sccordingly
db[.themeMatchSystemDayNightCycle] = isMatchingSystemSetting
db[.theme] = (isMatchingSystemSetting ?
let matchSystemNightModeSetting: Bool = (isExistingUser && !hadCustomLegacyThemeSetting)
let targetTheme: Theme = (!hadCustomLegacyThemeSetting ?
Theme.classicDark :
(UserDefaults.standard.integer(forKey: "appMode") == 0 ?
Theme.classicLight :
Theme.classicDark
)
)
db[.themePrimaryColor] = Theme.PrimaryColor.green
let targetPrimaryColor: Theme.PrimaryColor = .green
// Save the settings
db[.themeMatchSystemDayNightCycle] = matchSystemNightModeSetting
db[.theme] = targetTheme
db[.themePrimaryColor] = targetPrimaryColor
// Looks like the ThemeManager will load it's default values before this migration gets run
// as a result we need to update the ThemeManage to ensure the correct theme is applied
ThemeManager.currentTheme = targetTheme
ThemeManager.primaryColor = targetPrimaryColor
ThemeManager.matchSystemNightModeSetting = matchSystemNightModeSetting
Storage.update(progress: 1, for: self, in: target) // In case this is the last migration
}

@ -85,7 +85,9 @@ public enum ThemeManager {
// Note: We need to set this to 'unspecified' to force the UI to properly update as the
// 'TraitObservingWindow' won't actually trigger the trait change otherwise
mainWindow?.overrideUserInterfaceStyle = .unspecified
DispatchQueue.main.async {
self.mainWindow?.overrideUserInterfaceStyle = .unspecified
}
}
}
@ -122,6 +124,10 @@ public enum ThemeManager {
}
public static func applyNavigationStyling() {
guard Thread.isMainThread else {
return DispatchQueue.main.async { applyNavigationStyling() }
}
let textPrimary: UIColor = (ThemeManager.currentTheme.color(for: .textPrimary) ?? .white)
// Set the `mainWindow.tintColor` for system screens to use the right colour for text
@ -244,6 +250,10 @@ public enum ThemeManager {
}
public static func applyWindowStyling() {
guard Thread.isMainThread else {
return DispatchQueue.main.async { applyWindowStyling() }
}
mainWindow?.overrideUserInterfaceStyle = {
guard !ThemeManager.matchSystemNightModeSetting else { return .unspecified }
@ -268,10 +278,7 @@ public enum ThemeManager {
private static func updateAllUI() {
guard Thread.isMainThread else {
DispatchQueue.main.async {
updateAllUI()
}
return
return DispatchQueue.main.async { updateAllUI() }
}
ThemeManager.uiRegistry.objectEnumerator()?.forEach { applier in

@ -12,7 +12,12 @@ import Foundation
/// a somewhat inconsistent interface between different `Atomic` wrappers
@propertyWrapper
public class Atomic<Value> {
private let queue: DispatchQueue = DispatchQueue(label: "io.oxen.\(UUID().uuidString)")
// Note: Using 'userInteractive' to ensure this can't be blockedby higher priority queues
// which could result in the main thread getting blocked
private let queue: DispatchQueue = DispatchQueue(
label: "io.oxen.\(UUID().uuidString)",
qos: .userInteractive
)
private var value: Value
/// In order to change the value you **must** use the `mutate` function

Loading…
Cancel
Save