Apply design feedback from Myles.

This commit is contained in:
Matthew Chen 2019-02-21 09:53:49 -05:00
parent 93e09be18e
commit 9402e088b2
12 changed files with 152 additions and 38 deletions

View File

@ -164,6 +164,7 @@
3496957421A301A100DCFE74 /* OWSBackupAPI.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3496956B21A301A100DCFE74 /* OWSBackupAPI.swift */; };
349EA07C2162AEA800F7B17F /* OWS111UDAttributesMigration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 349EA07B2162AEA700F7B17F /* OWS111UDAttributesMigration.swift */; };
349ED990221B0194008045B0 /* Onboarding2FAViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 349ED98F221B0194008045B0 /* Onboarding2FAViewController.swift */; };
349ED992221EE80D008045B0 /* AppPreferences.swift in Sources */ = {isa = PBXBuildFile; fileRef = 349ED991221EE80D008045B0 /* AppPreferences.swift */; };
34A4C61E221613D00042EF2E /* OnboardingVerificationViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34A4C61D221613D00042EF2E /* OnboardingVerificationViewController.swift */; };
34A4C62022175C5C0042EF2E /* OnboardingProfileViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34A4C61F22175C5C0042EF2E /* OnboardingProfileViewController.swift */; };
34A6C28021E503E700B5B12E /* OWSImagePickerController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34A6C27F21E503E600B5B12E /* OWSImagePickerController.swift */; };
@ -843,6 +844,7 @@
3496956D21A301A100DCFE74 /* OWSBackupIO.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OWSBackupIO.h; sourceTree = "<group>"; };
349EA07B2162AEA700F7B17F /* OWS111UDAttributesMigration.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OWS111UDAttributesMigration.swift; sourceTree = "<group>"; };
349ED98F221B0194008045B0 /* Onboarding2FAViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Onboarding2FAViewController.swift; sourceTree = "<group>"; };
349ED991221EE80D008045B0 /* AppPreferences.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppPreferences.swift; sourceTree = "<group>"; };
34A4C61D221613D00042EF2E /* OnboardingVerificationViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OnboardingVerificationViewController.swift; sourceTree = "<group>"; };
34A4C61F22175C5C0042EF2E /* OnboardingProfileViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OnboardingProfileViewController.swift; sourceTree = "<group>"; };
34A6C27F21E503E600B5B12E /* OWSImagePickerController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OWSImagePickerController.swift; sourceTree = "<group>"; };
@ -1568,6 +1570,7 @@
34480B471FD0A60200BC14EF /* utils */ = {
isa = PBXGroup;
children = (
349ED991221EE80D008045B0 /* AppPreferences.swift */,
452EC6E0205FF5DC000E787C /* Bench.swift */,
4C948FF62146EB4800349F0D /* BlockListCache.swift */,
343D3D991E9283F100165CA4 /* BlockListUIUtils.h */,
@ -3423,6 +3426,7 @@
34612A071FD7238600532771 /* OWSSyncManager.m in Sources */,
450C801220AD1D5B00F3A091 /* UIDevice+featureSupport.swift in Sources */,
451F8A471FD715BA005CB9DA /* OWSAvatarBuilder.m in Sources */,
349ED992221EE80D008045B0 /* AppPreferences.swift in Sources */,
34AC09E7211B39B100997B47 /* MessageApprovalViewController.swift in Sources */,
34480B591FD0A7A400BC14EF /* OWSScrubbingLogFormatter.m in Sources */,
34AC09F0211B39B100997B47 /* AttachmentApprovalViewController.swift in Sources */,

View File

@ -433,7 +433,7 @@ static NSString *const kSealedSenderInfoURL = @"https://signal.org/blog/sealed-s
- (void)didToggleLinkPreviewsEnabled:(UISwitch *)sender
{
OWSLogInfo(@"toggled to: %@", (sender.isOn ? @"ON" : @"OFF"));
[SSKPreferences setAreLinkPreviewsEnabledWithValue:sender.isOn];
SSKPreferences.areLinkPreviewsEnabled = sender.isOn;
}
- (void)show2FASettings

View File

@ -345,7 +345,10 @@ typedef NS_ENUM(NSInteger, HomeViewControllerSection) {
[self createFirstConversationCueView];
[self.view addSubview:self.firstConversationCueView];
[self.firstConversationCueView autoPinToTopLayoutGuideOfViewController:self withInset:0.f];
[self.firstConversationCueView autoPinEdgeToSuperviewEdge:ALEdgeTrailing withInset:10];
// This inset bakes in assumptions about UINavigationBar layout, but I'm not sure
// there's a better way to do it, since it isn't safe to use iOS auto layout with
// UINavigationBar contents.
[self.firstConversationCueView autoPinEdgeToSuperviewEdge:ALEdgeTrailing withInset:6.f];
[self.firstConversationCueView autoPinEdgeToSuperviewEdge:ALEdgeLeading
withInset:10
relation:NSLayoutRelationGreaterThanOrEqual];
@ -410,9 +413,9 @@ typedef NS_ENUM(NSInteger, HomeViewControllerSection) {
label.lineBreakMode = NSLineBreakByWordWrapping;
OWSLayerView *layerView = [OWSLayerView new];
layerView.layoutMargins = UIEdgeInsetsMake(11 + kTailHeight, 16, 7, 16);
layerView.layoutMargins = UIEdgeInsetsMake(11 + kTailHeight, 16, 11, 16);
CAShapeLayer *shapeLayer = [CAShapeLayer new];
shapeLayer.fillColor = [OWSConversationColor ows_wintergreenColor].CGColor;
shapeLayer.fillColor = UIColor.ows_signalBlueColor.CGColor;
[layerView.layer addSublayer:shapeLayer];
layerView.layoutCallback = ^(UIView *view) {
UIBezierPath *bezierPath = [UIBezierPath new];
@ -443,10 +446,24 @@ typedef NS_ENUM(NSInteger, HomeViewControllerSection) {
[layerView addSubview:label];
[label ows_autoPinToSuperviewMargins];
layerView.userInteractionEnabled = YES;
[layerView
addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self
action:@selector(firstConversationCueWasTapped:)]];
self.firstConversationCueView = layerView;
self.firstConversationLabel = label;
}
- (void)firstConversationCueWasTapped:(UITapGestureRecognizer *)gestureRecognizer
{
OWSLogInfo(@"");
AppPreferences.hasDimissedFirstConversationCue = YES;
[self updateViewState];
}
- (void)updateFirstConversationLabel
{
NSArray<SignalAccount *> *signalAccounts = self.contactsManager.signalAccounts;
@ -1453,7 +1470,7 @@ typedef NS_ENUM(NSInteger, HomeViewControllerSection) {
[self updateReminderViews];
}
#pragma mark Database delegates
#pragma mark - Database delegates
- (YapDatabaseConnection *)uiDatabaseConnection
{
@ -1614,10 +1631,7 @@ typedef NS_ENUM(NSInteger, HomeViewControllerSection) {
- (void)updateViewState
{
NSUInteger inboxCount = self.numberOfInboxThreads;
NSUInteger archiveCount = self.numberOfArchivedThreads;
if (self.homeViewMode == HomeViewMode_Inbox && inboxCount == 0 && archiveCount == 0) {
if (self.shouldShowFirstConversationCue) {
[_tableView setHidden:YES];
[self.emptyInboxView setHidden:NO];
[self.firstConversationCueView setHidden:NO];
@ -1629,6 +1643,13 @@ typedef NS_ENUM(NSInteger, HomeViewControllerSection) {
}
}
- (BOOL)shouldShowFirstConversationCue
{
return (self.homeViewMode == HomeViewMode_Inbox && self.numberOfInboxThreads == 0
&& self.numberOfArchivedThreads == 0 && !AppPreferences.hasDimissedFirstConversationCue
&& !SSKPreferences.hasSavedThread);
}
// We want to delay asking for a review until an opportune time.
// If the user has *just* launched Signal they intend to do something, we don't want to interrupt them.
// If the user hasn't sent a message, we don't want to ask them for a review yet.

View File

@ -32,17 +32,14 @@ public class OnboardingPermissionsViewController: OnboardingBaseViewController {
comment: "Label for the 'not now' button in the 'onboarding permissions' view."),
selector: #selector(notNowPressed))
let topSpacer = UIView.vStretchingSpacer()
let bottomSpacer = UIView.vStretchingSpacer()
let stackView = UIStackView(arrangedSubviews: [
titleLabel,
UIView.spacer(withHeight: 20),
explanationLabel,
topSpacer,
giveAccessButton,
UIView.spacer(withHeight: 12),
UIView.vStretchingSpacer(),
notNowButton,
bottomSpacer
UIView.spacer(withHeight: 12),
giveAccessButton
])
stackView.axis = .vertical
stackView.alignment = .fill
@ -52,9 +49,6 @@ public class OnboardingPermissionsViewController: OnboardingBaseViewController {
stackView.autoPinWidthToSuperview()
stackView.autoPin(toTopLayoutGuideOf: self, withInset: 0)
stackView.autoPin(toBottomLayoutGuideOf: self, withInset: 0)
// Ensure whitespace is balanced, so inputs are vertically centered.
topSpacer.autoMatch(.height, to: .height, of: bottomSpacer)
}
// MARK: Request Access

View File

@ -100,9 +100,8 @@ public class OnboardingProfileViewController: OnboardingBaseViewController {
profileRow,
UIView.spacer(withHeight: 25),
explanationLabel,
UIView.spacer(withHeight: 20),
nextButton,
bottomSpacer
bottomSpacer,
nextButton
])
stackView.axis = .vertical
stackView.alignment = .fill

View File

@ -0,0 +1,37 @@
//
// Copyright (c) 2019 Open Whisper Systems. All rights reserved.
//
import Foundation
@objc
public class AppPreferences: NSObject {
// Never instantiate this class.
private override init() {}
private static let collection = "AppPreferences"
// MARK: -
private static let hasDimissedFirstConversationCueKey = "hasDimissedFirstConversationCue"
@objc
public static var hasDimissedFirstConversationCue: Bool {
get {
return getBool(key: hasDimissedFirstConversationCueKey)
}
set {
setBool(newValue, key: hasDimissedFirstConversationCueKey)
}
}
// MARK: -
private class func getBool(key: String, defaultValue: Bool = false) -> Bool {
return OWSPrimaryStorage.dbReadConnection().bool(forKey: key, inCollection: collection, defaultValue: defaultValue)
}
private class func setBool(_ value: Bool, key: String) {
OWSPrimaryStorage.dbReadWriteConnection().setBool(value, forKey: key, inCollection: collection)
}
}

View File

@ -151,6 +151,13 @@ ConversationColorName const kConversationColorName_Default = ConversationColorNa
return self;
}
- (void)saveWithTransaction:(YapDatabaseReadWriteTransaction *)transaction
{
[super saveWithTransaction:transaction];
[SSKPreferences setHasSavedThreadWithValue:YES transaction:transaction];
}
- (void)removeWithTransaction:(YapDatabaseReadWriteTransaction *)transaction
{
[self removeAllThreadInteractionsWithTransaction:transaction];

View File

@ -195,7 +195,7 @@ public class OWSLinkPreview: MTLModel {
guard OWSLinkPreview.featureEnabled else {
throw LinkPreviewError.noPreview
}
guard SSKPreferences.areLinkPreviewsEnabled() else {
guard SSKPreferences.areLinkPreviewsEnabled else {
throw LinkPreviewError.noPreview
}
let imageAttachmentId = OWSLinkPreview.saveAttachmentIfPossible(inputFilePath: info.imageFilePath,
@ -445,7 +445,7 @@ public class OWSLinkPreview: MTLModel {
return nil
}
guard SSKPreferences.areLinkPreviewsEnabled() else {
guard SSKPreferences.areLinkPreviewsEnabled else {
return nil
}
@ -497,7 +497,7 @@ public class OWSLinkPreview: MTLModel {
guard OWSLinkPreview.featureEnabled else {
return []
}
guard SSKPreferences.areLinkPreviewsEnabled() else {
guard SSKPreferences.areLinkPreviewsEnabled else {
return []
}
@ -546,7 +546,7 @@ public class OWSLinkPreview: MTLModel {
guard OWSLinkPreview.featureEnabled else {
return
}
guard SSKPreferences.areLinkPreviewsEnabled() else {
guard SSKPreferences.areLinkPreviewsEnabled else {
return
}
@ -565,7 +565,7 @@ public class OWSLinkPreview: MTLModel {
guard OWSLinkPreview.featureEnabled else {
return Promise(error: LinkPreviewError.featureDisabled)
}
guard SSKPreferences.areLinkPreviewsEnabled() else {
guard SSKPreferences.areLinkPreviewsEnabled else {
return Promise(error: LinkPreviewError.featureDisabled)
}
guard let previewUrl = previewUrl else {

View File

@ -1,5 +1,5 @@
//
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
// Copyright (c) 2019 Open Whisper Systems. All rights reserved.
//
#import "YapDatabaseConnection+OWS.h"
@ -137,6 +137,12 @@ NS_ASSUME_NONNULL_BEGIN
OWSAssertDebug(key.length > 0);
OWSAssertDebug(collection.length > 0);
NSNumber *_Nullable oldValue = [self objectForKey:key inCollection:collection ofExpectedType:[NSNumber class]];
if (oldValue && [@(value) isEqual:oldValue]) {
// Skip redundant writes.
return;
}
[self setObject:@(value) forKey:key inCollection:collection];
}

View File

@ -1,5 +1,5 @@
//
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
// Copyright (c) 2019 Open Whisper Systems. All rights reserved.
//
#import <YapDatabase/YapDatabaseTransaction.h>
@ -36,6 +36,7 @@ NS_ASSUME_NONNULL_BEGIN
- (void)restoreSnapshotOfCollection:(NSString *)collection snapshotFilePath:(NSString *)snapshotFilePath;
#endif
- (void)setBool:(BOOL)value forKey:(NSString *)key inCollection:(NSString *)collection;
- (void)setDate:(NSDate *)value forKey:(NSString *)key inCollection:(NSString *)collection;
@end

View File

@ -1,5 +1,5 @@
//
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
// Copyright (c) 2019 Open Whisper Systems. All rights reserved.
//
#import "YapDatabaseTransaction+OWS.h"
@ -149,6 +149,20 @@ NS_ASSUME_NONNULL_BEGIN
}
#endif
- (void)setBool:(BOOL)value forKey:(NSString *)key inCollection:(NSString *)collection
{
OWSAssertDebug(key.length > 0);
OWSAssertDebug(collection.length > 0);
NSNumber *_Nullable oldValue = [self objectForKey:key inCollection:collection ofExpectedType:[NSNumber class]];
if (oldValue && [@(value) isEqual:oldValue]) {
// Skip redundant writes.
return;
}
[self setObject:@(value) forKey:key inCollection:collection];
}
- (void)setDate:(NSDate *)value forKey:(NSString *)key inCollection:(NSString *)collection
{
[self setObject:@(value.timeIntervalSince1970) forKey:key inCollection:collection];

View File

@ -10,20 +10,51 @@ public class SSKPreferences: NSObject {
private override init() {}
private static let collection = "SSKPreferences"
// MARK: -
private static let areLinkPreviewsEnabledKey = "areLinkPreviewsEnabled"
@objc
public class func areLinkPreviewsEnabled() -> Bool {
return OWSPrimaryStorage.dbReadConnection().bool(forKey: areLinkPreviewsEnabledKey,
inCollection: collection,
defaultValue: true)
public static var areLinkPreviewsEnabled: Bool {
get {
return getBool(key: areLinkPreviewsEnabledKey, defaultValue: true)
}
set {
setBool(newValue, key: areLinkPreviewsEnabledKey)
SSKEnvironment.shared.syncManager.sendConfigurationSyncMessage()
}
}
// MARK: -
private static let hasSavedThreadKey = "hasSavedThread"
@objc
public static var hasSavedThread: Bool {
get {
return getBool(key: hasSavedThreadKey)
}
set {
setBool(newValue, key: hasSavedThreadKey)
}
}
@objc
public class func setAreLinkPreviewsEnabled(value: Bool) {
OWSPrimaryStorage.dbReadWriteConnection().setBool(value,
forKey: areLinkPreviewsEnabledKey,
inCollection: collection)
SSKEnvironment.shared.syncManager.sendConfigurationSyncMessage()
public class func setHasSavedThread(value: Bool, transaction: YapDatabaseReadWriteTransaction) {
transaction.setBool(value,
forKey: areLinkPreviewsEnabledKey,
inCollection: collection)
}
// MARK: -
private class func getBool(key: String, defaultValue: Bool = false) -> Bool {
return OWSPrimaryStorage.dbReadConnection().bool(forKey: key, inCollection: collection, defaultValue: defaultValue)
}
private class func setBool(_ value: Bool, key: String) {
OWSPrimaryStorage.dbReadWriteConnection().setBool(value, forKey: key, inCollection: collection)
}
}