Skip to content

Commit

Permalink
Merge pull request #682 from hello/jimmy/states
Browse files Browse the repository at this point in the history
Sensor detail error + loading states + fixes + analytics
  • Loading branch information
jimmymlu authored Sep 23, 2016
2 parents 5e80956 + 2cdf0c4 commit 5f1711b
Show file tree
Hide file tree
Showing 26 changed files with 289 additions and 77 deletions.
16 changes: 16 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,21 @@
# Changelog

## 1.5.3.8

New:

* Added back analytics for room conditions + sensor
* Added analytics for Upgrade path
* Added error state in sensor detail view
* Added loading state in sensor detail view

Fixes:

* Fixed issue in upgrade path where voice tutorial is skipped if DFU is skipped
* Room conditions error card is no longer tappable
* Disable scrubbing in room conditions mini charts
* Welcome / intro message now will disappear right away after the 2nd appearance

## 1.5.3.7

New:
Expand Down
2 changes: 1 addition & 1 deletion Extensions/RoomConditions/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1.5.3.7</string>
<string>1.5.3.8</string>
<key>NSExtension</key>
<dict>
<key>NSExtensionMainStoryboard</key>
Expand Down
1 change: 1 addition & 0 deletions SleepModel/Base.lproj/Localizable.strings
Original file line number Diff line number Diff line change
Expand Up @@ -935,6 +935,7 @@
"sensor.section.scale.range.format" = "%.0f to %.0f";
"sensor.section.scale.range.no-min.format" = "0 to %.0f";
"sensor.section.scale.range.no-max.format" = "%.0f+";
"sensor.data.error" = "Unable to load data.";

// extension
"ext.room-conditions.no-data" = "no data available";
Expand Down
9 changes: 9 additions & 0 deletions SleepModel/Base.lproj/Main.storyboard
Original file line number Diff line number Diff line change
Expand Up @@ -2826,11 +2826,18 @@
<constraint firstAttribute="height" constant="1" id="TNR-lh-JtX"/>
</constraints>
</view>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Unable to load data." textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="pj8-bE-Ry7">
<rect key="frame" x="231" y="133" width="138" height="18"/>
<fontDescription key="fontDescription" type="system" pointSize="15"/>
<color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
<nil key="highlightedColor"/>
</label>
</subviews>
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
<constraints>
<constraint firstItem="vjd-ni-4e8" firstAttribute="trailing" secondItem="5aQ-kF-iug" secondAttribute="trailing" id="4GJ-dC-tvk"/>
<constraint firstItem="5aQ-kF-iug" firstAttribute="leading" secondItem="96I-UY-JZ5" secondAttribute="leading" constant="24" id="4iC-Ik-W4z"/>
<constraint firstItem="pj8-bE-Ry7" firstAttribute="centerX" secondItem="96I-UY-JZ5" secondAttribute="centerX" id="5lZ-0h-CzZ"/>
<constraint firstItem="5aQ-kF-iug" firstAttribute="top" secondItem="96I-UY-JZ5" secondAttribute="top" constant="14" id="A2B-Nf-btH"/>
<constraint firstItem="0jw-xb-L1N" firstAttribute="bottom" secondItem="XwZ-KU-whg" secondAttribute="top" constant="-3" id="BbI-gT-Flj"/>
<constraint firstItem="vjd-ni-4e8" firstAttribute="leading" secondItem="5aQ-kF-iug" secondAttribute="leading" id="GsV-Xg-vKW"/>
Expand All @@ -2845,6 +2852,7 @@
<connections>
<outlet property="botLimitLabel" destination="0jw-xb-L1N" id="xuy-og-rsO"/>
<outlet property="botLimitLine" destination="XwZ-KU-whg" id="y4E-e9-t1m"/>
<outlet property="noDataLabel" destination="pj8-bE-Ry7" id="VoQ-cB-q83"/>
<outlet property="topLimitLabel" destination="5aQ-kF-iug" id="5cO-S2-rcb"/>
<outlet property="topLimitLine" destination="vjd-ni-4e8" id="EIw-qe-hqY"/>
</connections>
Expand All @@ -2865,6 +2873,7 @@
<constraint firstAttribute="bottom" secondItem="96I-UY-JZ5" secondAttribute="bottom" id="YNI-AA-mZy"/>
<constraint firstAttribute="trailing" secondItem="xLD-V9-woc" secondAttribute="trailing" id="boE-r6-GwP"/>
<constraint firstItem="xLD-V9-woc" firstAttribute="leading" secondItem="WY3-eO-8e2" secondAttribute="leading" id="d9i-at-sVS"/>
<constraint firstItem="pj8-bE-Ry7" firstAttribute="centerY" secondItem="WY3-eO-8e2" secondAttribute="centerY" constant="10" id="gwA-3s-FkP"/>
<constraint firstItem="96I-UY-JZ5" firstAttribute="leading" secondItem="WY3-eO-8e2" secondAttribute="leading" id="tkk-Bi-Mpt"/>
<constraint firstItem="96I-UY-JZ5" firstAttribute="top" secondItem="WY3-eO-8e2" secondAttribute="top" id="wow-0p-jlG"/>
</constraints>
Expand Down
7 changes: 6 additions & 1 deletion SleepModel/HEMOnboardingController.m
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,12 @@ - (void)showMessageDialog:(NSString *)message

- (NSString*)onboardingAnalyticsEventNameFor:(NSString*)event {
NSString* reusedEvent = event;
if (![[HEMOnboardingService sharedService] hasFinishedOnboarding]) {
if ([self flow]) {
NSString* prefix = [[self flow] analyticsEventPrefix];
if (![event hasPrefix:prefix]) {
reusedEvent = [NSString stringWithFormat:@"%@ %@", prefix, event];
}
} else if (![[HEMOnboardingService sharedService] hasFinishedOnboarding]) {
if (![event hasPrefix:HEMAnalyticsEventOnboardingPrefix]) {
reusedEvent = [NSString stringWithFormat:@"%@ %@",
HEMAnalyticsEventOnboardingPrefix, event];
Expand Down
1 change: 1 addition & 0 deletions SleepModel/HEMOnboardingFlow.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,6 @@
- (BOOL)shouldCompleteFlowAfter:(UIViewController*)controller;
- (void)prepareNextController:(HEMOnboardingController*)controller
fromController:(UIViewController*)controller;
- (NSString*)analyticsEventPrefix;

@end
2 changes: 0 additions & 2 deletions SleepModel/HEMOnboardingService.m
Original file line number Diff line number Diff line change
Expand Up @@ -1001,8 +1001,6 @@ - (void)linkCurrentAccount:(HEMOnboardingErrorHandler)completion {
[[SENServiceDevice sharedService] loadDeviceInfo:nil];
}

[SENAnalytics track:HEMAnalyticsEventSensePaired];

if ([strongSelf tempSenseManager]) {
[strongSelf setCurrentSenseManager:[strongSelf tempSenseManager]];
[strongSelf setTempSenseManager:nil];
Expand Down
1 change: 1 addition & 0 deletions SleepModel/HEMPairPiillPresenter.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ NS_ASSUME_NONNULL_BEGIN
- (void)bindWithStatusLabel:(UILabel*)statusLabel;
- (void)bindWithNavigationItem:(UINavigationItem*)navItem;
- (void)bindWithContentContainerView:(UIView*)contentView;
- (void)trackEvent:(NSString*)event withProperties:(NSDictionary*)props;

@end

Expand Down
12 changes: 9 additions & 3 deletions SleepModel/HEMPairPiillPresenter.m
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,13 @@ - (void)bindWithNavigationItem:(UINavigationItem*)navItem {
[self setNavItem:navItem];
}

#pragma mark - Track Analytics Event

- (void)trackEvent:(NSString*)event withProperties:(NSDictionary*)props {
BOOL onboarding = ![[self onboardingService] hasFinishedOnboarding];
[SENAnalytics track:event properties:props onboarding:onboarding];
}

#pragma mark - Presenter events

- (void)didAppear {
Expand Down Expand Up @@ -218,8 +225,7 @@ - (void)startPairing {
[self setPairingAttempts:[self pairingAttempts] + 1];

if ([self pairingAttempts] > 1) {
BOOL onboarding = ![[self onboardingService] hasFinishedOnboarding];
[SENAnalytics track:HEMAnalyticsEventPairPillRetry properties:nil onboarding:onboarding];
[self trackEvent:HEMAnalyticsEventPairPillRetry withProperties:nil];
}

__weak typeof(self) weakSelf = self;
Expand Down Expand Up @@ -263,7 +269,7 @@ - (void)pairNow {
}
}];
} else {
[SENAnalytics track:HEMAnalyticsEventPillPaired];
[strongSelf trackEvent:HEMAnalyticsEventPillPaired withProperties:nil];
[strongSelf flashPairedState];
}
}];
Expand Down
1 change: 1 addition & 0 deletions SleepModel/HEMPairSensePresenter.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ NS_ASSUME_NONNULL_BEGIN
descriptionTopConstraint:(NSLayoutConstraint*)topConstraint;
- (void)bindWithIllustrationView:(nullable UIImageView*)illustrationView
andHeightConstraint:(NSLayoutConstraint*)heightConstraint;
- (void)trackEvent:(NSString*)event properties:(NSDictionary*)props;
- (void)help;
- (void)proceed;

Expand Down
8 changes: 8 additions & 0 deletions SleepModel/HEMPairSensePresenter.m
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,11 @@ - (void)bindWithIllustrationView:(__unused UIImageView*)illustrationView
}
}

- (void)trackEvent:(NSString*)event properties:(NSDictionary*)props {
BOOL onboarding = ![[self onbService] hasFinishedOnboarding];
[SENAnalytics track:event properties:props onboarding:onboarding];
}

#pragma mark - State Machine

- (void)executeNextStep {
Expand Down Expand Up @@ -261,6 +266,7 @@ - (void)issueSwapIntent {
__weak typeof(self) weakSelf = self;

DDLogVerbose(@"issuing swap intent");
[SENAnalytics track:HEMAnalyticsEventUpgradeSwapRequest];

NSString* activityMessage = NSLocalizedString(@"pairing.activity.linking-account", nil);
[self updateActivityText:activityMessage completion:nil];
Expand All @@ -269,6 +275,7 @@ - (void)issueSwapIntent {
[[self deviceService] issueSwapIntentFor:currentSense completion:^(NSError * error) {
__strong typeof(weakSelf) strongSelf = weakSelf;
if (!error) {
[SENAnalytics track:HEMAnalyticsEventUpgradeSwapped];
[strongSelf setCurrentState:HEMPairSenseStateIssuedSwapIntent];
[strongSelf executeNextStep];
} else {
Expand All @@ -290,6 +297,7 @@ - (void)linkAccount {
[[self onbService] linkCurrentAccount:^(NSError *error) {
__strong typeof(weakSelf) strongSelf = weakSelf;
if (!error) {
[strongSelf trackEvent:HEMAnalyticsEventSensePaired properties:nil];
[strongSelf setCurrentState:HEMPairSenseStateAccountLinked];
[strongSelf executeNextStep];
} else {
Expand Down
2 changes: 2 additions & 0 deletions SleepModel/HEMResetSensePresenter.m
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,8 @@ - (void)reset {
return [self later];
}

[SENAnalytics track:HEMAnalyticsEventUpgradeReset];

NSString* activityMessage = NSLocalizedString(@"settings.device.restoring-factory-settings", nil);
HEMActivityCoverView* activityView = [HEMActivityCoverView new];
[activityView showInView:[self activityContainerView] withText:activityMessage activity:YES completion:^{
Expand Down
15 changes: 12 additions & 3 deletions SleepModel/HEMRoomConditionsPresenter.m
Original file line number Diff line number Diff line change
Expand Up @@ -120,10 +120,15 @@ - (void)didAppear {

if ([self isIntroShowing]) {
[[self introService] incrementIntroViewsForType:HEMIntroTypeRoomConditions];
if (![[self introService] shouldIntroduceType:HEMIntroTypeRoomConditions]) {
[self reloadUI];
}
}

// let the polling update the UI
[self stopListeningForSensorStatusChanges];

[SENAnalytics track:kHEMAnalyticsEventCurrentConditions];
}

- (void)didDisappear {
Expand Down Expand Up @@ -500,9 +505,12 @@ - (void)scrollViewDidScroll:(UIScrollView *)scrollView {
}

- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath {
id sensorObj = [self groupedSensors][[indexPath row]];
if ([sensorObj isKindOfClass:[SENSensor class]]) {
[[self delegate] showSensor:sensorObj fromPresenter:self];
UICollectionViewCell* cell = [collectionView cellForItemAtIndexPath:indexPath];
if ([cell isKindOfClass:[HEMSensorCollectionViewCell class]]) {
id sensorObj = [self groupedSensors][[indexPath row]];
if ([sensorObj isKindOfClass:[SENSensor class]]) {
[[self delegate] showSensor:sensorObj fromPresenter:self];
}
}
}

Expand Down Expand Up @@ -590,6 +598,7 @@ - (void)configureSensorCell:(HEMSensorCollectionViewCell*)sensorCell forSensor:(

HEMSensorChartContainer* chartContainer = [sensorCell graphContainerView];
[chartContainer setChartView:chartView];
[chartContainer setScrubberEnable:NO];
[[chartContainer topLimitLabel] setText:[[self formatter] stringFromSensorValue:@(maxValue)]];
[[chartContainer botLimitLabel] setText:[[self formatter] stringFromSensorValue:@(minValue)]];

Expand Down
4 changes: 4 additions & 0 deletions SleepModel/HEMSensorChartContainer.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,12 @@
@property (weak, nonatomic) IBOutlet UILabel* botLimitLabel;
@property (weak, nonatomic) IBOutlet UIView* botLimitLine;

@property (weak, nonatomic) IBOutlet UILabel* noDataLabel;

@property (nonatomic, weak) id<HEMSensorChartScrubberDelegate> delegate;
@property (nonatomic, assign) BOOL scrubberEnable;

- (void)showLoadingActivity:(BOOL)loading;
- (void)setChartView:(ChartViewBase*)chartView;
- (ChartViewBase*)chartView;
- (void)setScrubberColor:(UIColor*)color;
Expand Down
60 changes: 57 additions & 3 deletions SleepModel/HEMSensorChartContainer.m
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,11 @@
//

#import "HEMSensorChartContainer.h"
#import "HEMActivityIndicatorView.h"
#import "HEMStyle.h"

static CGFloat const kHEMSensorChartWidth = 1.0f;
static CGFloat const kHEMSensorChartScrubStartDelay = 0.25f;
static CGFloat const kHEMSensorChartScrubStartDelay = 0.15f;
static CGFloat const kHEMSensorChartScrubberFadeDuration = 0.5f;
static CGFloat const kHEMSensorChartScrubberCircleSize = 8.0f;
static CGFloat const kHEMSensorChartScrubberInnerCircleSize = 4.0f;
Expand All @@ -21,16 +22,26 @@ @interface HEMSensorChartContainer() <UIGestureRecognizerDelegate>
@property (nonatomic, strong) UIView* scrubberCircle;
@property (nonatomic, weak) ChartViewBase* chartView;
@property (nonatomic, weak) UILongPressGestureRecognizer* scrubberGesture;
@property (nonatomic, weak) IBOutlet HEMActivityIndicatorView* activityView;

@end

@implementation HEMSensorChartContainer

- (void)awakeFromNib {
UIColor* lineColor = [[UIColor grey3] colorWithAlphaComponent:0.2f];
[[self topLimitLabel] setTextColor:[UIColor grey4]];
[[self botLimitLabel] setTextColor:[UIColor grey4]];
[[self topLimitLine] setBackgroundColor:[[UIColor grey3] colorWithAlphaComponent:0.2f]];
[[self botLimitLine] setBackgroundColor:[[UIColor grey3] colorWithAlphaComponent:0.2f]];
[[self topLimitLine] setBackgroundColor:lineColor];
[[self botLimitLine] setBackgroundColor:lineColor];

[[self noDataLabel] setFont:[UIFont body]];
[[self noDataLabel] setTextColor:[UIColor grey5]];
[[self noDataLabel] setUserInteractionEnabled:NO];
[[self noDataLabel] setHidden:YES];

[[self activityView] setHidden:YES];
[[self activityView] stop];

UILongPressGestureRecognizer* gesture = [UILongPressGestureRecognizer new];
[gesture addTarget:self action:@selector(startScrubbing:)];
Expand All @@ -40,6 +51,13 @@ - (void)awakeFromNib {
[self setScrubberGesture:gesture];
}

- (void)layoutSubviews {
[super layoutSubviews];
if ([self activityView]) {
[[self activityView] setCenter:[self center]];
}
}

- (UIView*)scrubberCircle {
if (!_scrubberCircle) {
CGRect circleFrame = CGRectZero;
Expand All @@ -65,6 +83,31 @@ - (UIView*)scrubberCircle {
return _scrubberCircle;
}

- (void)setScrubberEnable:(BOOL)scrubberEnable {
_scrubberEnable = scrubberEnable;
[[self scrubberGesture] setEnabled:scrubberEnable];
}

- (void)showLoadingActivity:(BOOL)loading {
if (loading && ![self activityView]) {
UIImage* loaderImage = [UIImage imageNamed:@"sensorLoaderGray"];
CGRect loaderFrame = CGRectZero;
loaderFrame.size = loaderImage.size;
HEMActivityIndicatorView* indicatorView
= [[HEMActivityIndicatorView alloc] initWithImage:loaderImage
andFrame:loaderFrame];
[self setActivityView:indicatorView];
[self addSubview:indicatorView];
}

[[self activityView] setHidden:!loading];
if (loading) {
[[self activityView] start];
} else {
[[self activityView] stop];
}
}

- (UIView*)scrubber {
if (!_scrubber) {
CGRect scrubberFrame = CGRectZero;
Expand All @@ -84,11 +127,22 @@ - (void)setScrubberColor:(UIColor*)color {
}

- (void)setChartView:(ChartViewBase*)chartView {
if (!chartView) {
if (_chartView) {
[_chartView removeFromSuperview];
_chartView = chartView;
}
[self setUserInteractionEnabled:NO];
return;
}

BOOL hasChartData = ![chartView isEmpty];
[[self topLimitLabel] setHidden:!hasChartData];
[[self botLimitLabel] setHidden:!hasChartData];

[self insertSubview:chartView atIndex:0];
[self setUserInteractionEnabled:YES];

_chartView = chartView;
}

Expand Down
Loading

0 comments on commit 5f1711b

Please sign in to comment.