diff --git a/CookSmart/CookSmart.xcodeproj/project.pbxproj b/CookSmart/CookSmart.xcodeproj/project.pbxproj index f09889a..80f7753 100644 --- a/CookSmart/CookSmart.xcodeproj/project.pbxproj +++ b/CookSmart/CookSmart.xcodeproj/project.pbxproj @@ -12,6 +12,7 @@ 396E363F24396D5900C2815B /* UnitPickerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 396E363E24396D5900C2815B /* UnitPickerView.swift */; }; 396E3643243976A000C2815B /* GradientView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 396E3642243976A000C2815B /* GradientView.swift */; }; 396E3647243A3BDC00C2815B /* UnitPickerDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 396E3646243A3BDC00C2815B /* UnitPickerDelegate.swift */; }; + 39C3CE2524426BE600359EDF /* ConversionViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 39C3CE2424426BE600359EDF /* ConversionViewController.swift */; }; 39C3CE582442775E00359EDF /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 39C3CE562442775E00359EDF /* AppDelegate.swift */; }; 39C3CE5A2442776D00359EDF /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 39C3CE592442776D00359EDF /* SceneDelegate.swift */; }; 39C3CE642442A1C000359EDF /* EditIngredientViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 39C3CE632442A1C000359EDF /* EditIngredientViewController.swift */; }; @@ -41,8 +42,6 @@ 931AF96818C2B8AF0018AA8B /* WeightUnits.plist in Resources */ = {isa = PBXBuildFile; fileRef = 931AF96718C2B8AF0018AA8B /* WeightUnits.plist */; }; 931AF96A18C2B9C90018AA8B /* VolumeUnits.plist in Resources */ = {isa = PBXBuildFile; fileRef = 931AF96918C2B9C90018AA8B /* VolumeUnits.plist */; }; 931AF96D18C2BAE50018AA8B /* CSUnitCollection.m in Sources */ = {isa = PBXBuildFile; fileRef = 931AF96C18C2BAE50018AA8B /* CSUnitCollection.m */; }; - 9358BD6E1891CAAA00A99D51 /* CSConversionVC.m in Sources */ = {isa = PBXBuildFile; fileRef = 9358BD6C1891CAAA00A99D51 /* CSConversionVC.m */; }; - 9358BD6F1891CAAA00A99D51 /* CSConversionVC.xib in Resources */ = {isa = PBXBuildFile; fileRef = 9358BD6D1891CAAA00A99D51 /* CSConversionVC.xib */; }; 936809701891059700655B89 /* CSIngredientListVC.m in Sources */ = {isa = PBXBuildFile; fileRef = 9368096F1891059700655B89 /* CSIngredientListVC.m */; }; 93D09934189766080014DB3E /* CSUnit.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D09933189766080014DB3E /* CSUnit.m */; }; 93F6CCA818AED6050045400D /* CSScaleVC.m in Sources */ = {isa = PBXBuildFile; fileRef = 93F6CCA618AED6050045400D /* CSScaleVC.m */; }; @@ -93,6 +92,7 @@ 396E363E24396D5900C2815B /* UnitPickerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UnitPickerView.swift; sourceTree = ""; }; 396E3642243976A000C2815B /* GradientView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GradientView.swift; sourceTree = ""; }; 396E3646243A3BDC00C2815B /* UnitPickerDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UnitPickerDelegate.swift; sourceTree = ""; }; + 39C3CE2424426BE600359EDF /* ConversionViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConversionViewController.swift; sourceTree = ""; }; 39C3CE562442775E00359EDF /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 39C3CE592442776D00359EDF /* SceneDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = ""; }; 39C3CE632442A1C000359EDF /* EditIngredientViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EditIngredientViewController.swift; sourceTree = ""; }; @@ -138,9 +138,6 @@ 931AF96918C2B9C90018AA8B /* VolumeUnits.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = VolumeUnits.plist; sourceTree = ""; }; 931AF96B18C2BAE50018AA8B /* CSUnitCollection.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CSUnitCollection.h; sourceTree = ""; }; 931AF96C18C2BAE50018AA8B /* CSUnitCollection.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CSUnitCollection.m; sourceTree = ""; }; - 9358BD6B1891CAAA00A99D51 /* CSConversionVC.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CSConversionVC.h; sourceTree = ""; }; - 9358BD6C1891CAAA00A99D51 /* CSConversionVC.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CSConversionVC.m; sourceTree = ""; }; - 9358BD6D1891CAAA00A99D51 /* CSConversionVC.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = CSConversionVC.xib; sourceTree = ""; }; 9368096E1891059700655B89 /* CSIngredientListVC.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CSIngredientListVC.h; sourceTree = ""; }; 9368096F1891059700655B89 /* CSIngredientListVC.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CSIngredientListVC.m; sourceTree = ""; }; 93D09932189766080014DB3E /* CSUnit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CSUnit.h; sourceTree = ""; }; @@ -201,6 +198,14 @@ path = Core; sourceTree = ""; }; + 39C3CE2224426AF700359EDF /* Conversion */ = { + isa = PBXGroup; + children = ( + 39C3CE2424426BE600359EDF /* ConversionViewController.swift */, + ); + path = Conversion; + sourceTree = ""; + }; 39C3CE612442A1A300359EDF /* Edit Ingredient */ = { isa = PBXGroup; children = ( @@ -352,12 +357,10 @@ 39C3CE7F244BE1B100359EDF /* Scale View */, 39C3CE562442775E00359EDF /* AppDelegate.swift */, 39C3CE592442776D00359EDF /* SceneDelegate.swift */, + 39C3CE2224426AF700359EDF /* Conversion */, 392D8642242FD0CA002064D6 /* Core */, 39C3CE612442A1A300359EDF /* Edit Ingredient */, 80433B351BB2731B006B7A85 /* Launch Screen.storyboard */, - 9358BD6B1891CAAA00A99D51 /* CSConversionVC.h */, - 9358BD6C1891CAAA00A99D51 /* CSConversionVC.m */, - 9358BD6D1891CAAA00A99D51 /* CSConversionVC.xib */, 8000355C18B3CBF50032BF91 /* Scales */, 80592C0218924AEA0082D4E1 /* Model */, 807C0B681BB3DD04007D2C03 /* Ingredient List UI */, @@ -502,7 +505,6 @@ buildActionMask = 2147483647; files = ( 931AF96818C2B8AF0018AA8B /* WeightUnits.plist in Resources */, - 9358BD6F1891CAAA00A99D51 /* CSConversionVC.xib in Resources */, 931AF96A18C2B9C90018AA8B /* VolumeUnits.plist in Resources */, B7BCA29B180524A800CF7588 /* InfoPlist.strings in Resources */, B7BCA2C01805284A00CF7588 /* Ingredients.plist in Resources */, @@ -617,7 +619,6 @@ 77479AF924303D86000CFB0E /* Fonts.swift in Sources */, 80592C1718939E030082D4E1 /* CSGradientView.m in Sources */, 39C3CE642442A1C000359EDF /* EditIngredientViewController.swift in Sources */, - 9358BD6E1891CAAA00A99D51 /* CSConversionVC.m in Sources */, 80592C0518924B010082D4E1 /* CSIngredients.m in Sources */, 77F41932243950CB0055053E /* ScaleScrollView.swift in Sources */, 39C3CE82244BE22100359EDF /* ScalesView.swift in Sources */, @@ -628,6 +629,7 @@ 93D09934189766080014DB3E /* CSUnit.m in Sources */, 773C97E5244BF0BF00208351 /* StyledView.swift in Sources */, 80433B2E1BB26C1A006B7A85 /* CSRecentsIngredientGroup.m in Sources */, + 39C3CE2524426BE600359EDF /* ConversionViewController.swift in Sources */, 396E3643243976A000C2815B /* GradientView.swift in Sources */, 396E363D2439684E00C2815B /* CenterLineView.swift in Sources */, 936809701891059700655B89 /* CSIngredientListVC.m in Sources */, diff --git a/CookSmart/CookSmart/CSConversionVC.h b/CookSmart/CookSmart/CSConversionVC.h deleted file mode 100644 index ac0d54a..0000000 --- a/CookSmart/CookSmart/CSConversionVC.h +++ /dev/null @@ -1,20 +0,0 @@ -// -// CSConversionVC.h -// CookSmart -// -// Created by Olga Galchenko on 1/23/14. -// Copyright (c) 2014 Olga Galchenko. All rights reserved. -// - -#import -#import "CSIngredientListVC.h" -#import "CSScaleView.h" -#import "CSScaleVC.h" - -@class CSIngredientGroup; - -@interface CSConversionVC : UIViewController - -- (id)initWithIngredientGroupIndex:(NSUInteger)ingredientGroupIndex ingredientIndex:(NSUInteger)ingredientIndex; - -@end diff --git a/CookSmart/CookSmart/CSConversionVC.m b/CookSmart/CookSmart/CSConversionVC.m deleted file mode 100644 index 5e21a19..0000000 --- a/CookSmart/CookSmart/CSConversionVC.m +++ /dev/null @@ -1,274 +0,0 @@ -// -// CSConversionVC.m -// CookSmart -// -// Created by Olga Galchenko on 1/23/14. -// Copyright (c) 2014 Olga Galchenko. All rights reserved. -// - -#import "CSConversionVC.h" -#import "CSIngredients.h" -#import "CSIngredientListVC.h" -#import "CSIngredientGroup.h" -#import "CSIngredient.h" -#import "CSScaleView.h" -#import "CSUnit.h" -#import "CSUnitCollection.h" -#import "CSScaleVC.h" -#import "cake-Swift.h" - -#define CHOOSE_UNITS_TEXT @"Choose Units" - -@interface CSConversionVC () - -@property (nonatomic, readwrite, assign) NSUInteger ingredientIndex; -@property (weak, nonatomic) IBOutlet UIScrollView *ingredientPickerScrollView; - -@property (strong, nonatomic) IBOutlet CSScaleVC* scaleVC; - -@end - -@implementation CSConversionVC - -- (id)initWithIngredientGroupIndex:(NSUInteger)ingredientGroupIndex ingredientIndex:(NSUInteger)ingredientIndex -{ - self = [super initWithNibName:@"CSConversionVC" bundle:nil]; - if (self) - { - self.ingredientIndex = [[CSIngredients sharedInstance] flattenedIngredientIndexForGroupIndex:ingredientGroupIndex ingredientIndex:ingredientIndex]; - - [[NSNotificationCenter defaultCenter] addObserver:self - selector:@selector(ingredientDeleted:) - name:INGREDIENT_DELETE_NOTIFICATION_NAME - object:nil]; - } - return self; -} - -- (void)dealloc -{ - [[NSNotificationCenter defaultCenter] removeObserver:self]; -} - -#pragma mark - View Lifecycle Management - -- (void)viewDidLoad -{ - [super viewDidLoad]; - - [self addChildViewController:self.scaleVC]; - [self.view addSubview:self.scaleVC.view]; - self.scaleVC.view.translatesAutoresizingMaskIntoConstraints = NO; - self.scaleVC.delegate = self; - NSLayoutConstraint* bottom = [NSLayoutConstraint constraintWithItem:self.scaleVC.view - attribute:NSLayoutAttributeBottom - relatedBy:NSLayoutRelationEqual - toItem:self.view - attribute:NSLayoutAttributeBottom - multiplier:1.0 - constant:0]; - NSLayoutConstraint* left = [NSLayoutConstraint constraintWithItem:self.scaleVC.view - attribute:NSLayoutAttributeLeft - relatedBy:NSLayoutRelationEqual - toItem:self.view - attribute:NSLayoutAttributeLeft - multiplier:1.0 - constant:0]; - NSLayoutConstraint* right = [NSLayoutConstraint constraintWithItem:self.scaleVC.view - attribute:NSLayoutAttributeRight - relatedBy:NSLayoutRelationEqual - toItem:self.view - attribute:NSLayoutAttributeRight - multiplier:1.0 - constant:0]; - NSLayoutConstraint* top = [NSLayoutConstraint constraintWithItem:self.scaleVC.view - attribute:NSLayoutAttributeTop - relatedBy:NSLayoutRelationEqual - toItem:self.ingredientPickerScrollView - attribute:NSLayoutAttributeBottom - multiplier:1.0 - constant:10]; - [self.view addConstraints:@[bottom, left, right, top]]; - self.ingredientPickerScrollView.scrollsToTop = NO; - self.ingredientPickerScrollView.showsHorizontalScrollIndicator = NO; - self.ingredientPickerScrollView.showsVerticalScrollIndicator = NO; -} - -- (void)viewDidAppear:(BOOL)animated -{ - [super viewDidAppear:animated]; - // When we first appear, always select the very first ingredient – the one most recently selected. - [self selectIngredientAtIndex:self.ingredientIndex]; - logViewChange(@"conversion", [self.scaleVC analyticsAttributes]); -} - -- (void)viewDidDisappear:(BOOL)animated -{ - [super viewDidDisappear:animated]; - [self markCurrentIngredientAccess]; -} - -- (void)markCurrentIngredientAccess -{ - if (self.isViewLoaded && self.view.window != nil) { - CSIngredient *ingredient = [[CSIngredients sharedInstance] ingredientAtFlattenedIngredientIndex:self.ingredientIndex]; - [ingredient markAccess]; - } -} - -#pragma mark - Ingredient Picker - -- (NSString *)nameForIngredientAtXOrigin:(CGFloat)xOrigin -{ - NSUInteger indexOfIngredient = (NSUInteger) (xOrigin/self.ingredientPickerScrollView.bounds.size.width); - NSString *nameOfIngredient = nil; - if (indexOfIngredient < [[CSIngredients sharedInstance] flattenedCountOfIngredients]) - { - nameOfIngredient = [[[CSIngredients sharedInstance] ingredientAtFlattenedIngredientIndex:indexOfIngredient] name]; - } - return nameOfIngredient; -} - -- (void)refreshIngredientNameUI -{ - self.ingredientPickerScrollView.contentSize = CGSizeMake(self.ingredientPickerScrollView.bounds.size.width*[[CSIngredients sharedInstance] flattenedCountOfIngredients], - self.ingredientPickerScrollView.bounds.size.height); - for (UIView *subview in self.ingredientPickerScrollView.subviews) - { - [subview removeFromSuperview]; - } - CGFloat initialXOffset = self.ingredientPickerScrollView.bounds.size.width*self.ingredientIndex; - for (CGFloat xOrigin = initialXOffset; xOrigin <= initialXOffset + 2*self.ingredientPickerScrollView.bounds.size.width; xOrigin += self.ingredientPickerScrollView.bounds.size.width) - { - UIButton *ingredientButton = [UIButton buttonWithType:UIButtonTypeSystem]; - ingredientButton.frame = CGRectMake(xOrigin, 0, self.ingredientPickerScrollView.bounds.size.width, self.ingredientPickerScrollView.bounds.size.height); - [ingredientButton setTitle:[self nameForIngredientAtXOrigin:xOrigin] forState:UIControlStateNormal]; - ingredientButton.titleLabel.font = [UIFont fontWithName:@"AvenirNext-Medium" size:MAJOR_BUTTON_FONT_SIZE]; - [ingredientButton setTitleColor:RED_LINE_COLOR forState:UIControlStateNormal]; - [ingredientButton setTitleColor:[UIColor blackColor] forState:UIControlStateDisabled]; - [ingredientButton addTarget:self action:@selector(handleIngredientTap:) forControlEvents:UIControlEventTouchUpInside]; - [self.ingredientPickerScrollView addSubview:ingredientButton]; - } - self.ingredientPickerScrollView.contentOffset = CGPointMake(initialXOffset, 0); -} - -- (void)handleIngredientTap:(id)sender -{ - CSIngredientListVC* ingrListVC = [[CSIngredientListVC alloc] initWithDelegate:self]; - UINavigationController* nav = [[UINavigationController alloc] initWithRootViewController:ingrListVC]; - nav.modalPresentationStyle = UIModalPresentationOverFullScreen; - [self presentViewController:nav animated:YES completion:nil]; -} - -- (void)scrollViewDidScroll:(UIScrollView *)scrollView -{ - CSAssert(scrollView == self.ingredientPickerScrollView, @"conversion_vc_wrong_scrollview_delegate", - @"CSConversionVC doesn't expect to be delegate of a scrollview other than its ingredientPickerScrollView"); - CGFloat minVisibleX = self.ingredientPickerScrollView.contentOffset.x; - CGFloat maxVisibleX = minVisibleX + self.ingredientPickerScrollView.bounds.size.width; - NSUInteger numSubviews = self.ingredientPickerScrollView.subviews.count; - CGFloat contentSize = self.ingredientPickerScrollView.contentSize.width; - for (UIButton *button in self.ingredientPickerScrollView.subviews) - { - if (button.frame.origin.x + button.bounds.size.width < minVisibleX && - button.frame.origin.x + (numSubviews + 1)*button.bounds.size.width <= contentSize && - button.frame.origin.x + numSubviews*button.bounds.size.width) - { - button.frame = CGRectMake(button.frame.origin.x + numSubviews*button.bounds.size.width, 0, button.frame.size.width, button.frame.size.height); - [button setTitle:[self nameForIngredientAtXOrigin:button.frame.origin.x] forState:UIControlStateNormal]; - } - if (button.frame.origin.x > maxVisibleX && - button.frame.origin.x - numSubviews*button.bounds.size.width >= 0 && - button.frame.origin.x + (1 - numSubviews)*button.bounds.size.width >= minVisibleX) - { - button.frame = CGRectMake(button.frame.origin.x - numSubviews*button.bounds.size.width, 0, button.frame.size.width, button.frame.size.height); - [button setTitle:[self nameForIngredientAtXOrigin:button.frame.origin.x] forState:UIControlStateNormal]; - } - } - - CGFloat distanceToSnap = remainder(self.ingredientPickerScrollView.contentOffset.x, self.ingredientPickerScrollView.bounds.size.width); - CGFloat distanceToMiddle = (self.ingredientPickerScrollView.bounds.size.width/2) - fabs(distanceToSnap); - CGFloat scaleViewAlpha = distanceToMiddle/(self.ingredientPickerScrollView.bounds.size.width/2); - [self.scaleVC setScalesAlpha:scaleViewAlpha]; - - NSUInteger projectedIndex = (int)round(self.ingredientPickerScrollView.contentOffset.x/self.ingredientPickerScrollView.bounds.size.width); - projectedIndex = MIN(MAX(0, projectedIndex), self.ingredientPickerScrollView.contentSize.width/self.ingredientPickerScrollView.bounds.size.width - 1); - if (projectedIndex != self.ingredientIndex) - { - self.ingredientIndex = projectedIndex; - [self refreshScalesWithCurrentIngredient]; - [self markCurrentIngredientAccess]; - logUserAction(@"ingredient_switch", [self.scaleVC analyticsAttributes]); - } -} - -#pragma mark - CSIngredientListVCDelegate - -- (void)ingredientListVC:(CSIngredientListVC *)listVC selectedIngredientGroup:(NSUInteger)ingredientGroupIndex ingredientIndex:(NSUInteger)index -{ - CSIngredientGroup *ingredientGroup = [[CSIngredients sharedInstance] ingredientGroupAtIndex:ingredientGroupIndex]; - CSIngredient *ingredient = [ingredientGroup ingredientAtIndex:index]; - logUserAction(@"ingredient_select", @{ - @"ingredient_group_name" : ingredientGroup.name, - @"ingredient_name" : ingredient.name, - @"ingredient_density" : [NSNumber numberWithFloat:ingredient.density], - }); - [self selectIngredientAtIndex:[[CSIngredients sharedInstance] flattenedIngredientIndexForGroupIndex:ingredientGroupIndex ingredientIndex:index]]; -} - -- (void)selectIngredientAtIndex:(NSUInteger)ingredientIndex -{ - self.ingredientIndex = ingredientIndex; - [self refreshIngredientNameUI]; - [self refreshScalesWithCurrentIngredient]; - [self markCurrentIngredientAccess]; -} - -- (void)refreshScalesWithCurrentIngredient -{ - self.scaleVC.ingredient = [[CSIngredients sharedInstance] ingredientAtFlattenedIngredientIndex:self.ingredientIndex]; -} - -#pragma mark - Notifications - -- (void)ingredientDeleted:(NSNotification *)notification -{ - // When an ingredient is deleted, our index into the ingredient group might change. - // In the future we might want to put a better solution for this, but for now, we'll - // just select the very first ingredient of the very first ingredient group and be done - // with it. - [self selectIngredientAtIndex:0]; -} - -#pragma mark - scaleVC delegate methods - -- (void)scaleVCDidBeginChangingUnits:(CSScaleVC*)scaleVC -{ - [self iterateOverIngredientButtons:^(UIButton *ingredientButton) { - ingredientButton.enabled = NO; - [ingredientButton setTitle:CHOOSE_UNITS_TEXT forState:UIControlStateNormal]; - }]; - [self.ingredientPickerScrollView setScrollEnabled:NO]; -} - -- (void)scaleVCDidFinishChangingUnits:(CSScaleVC *)scaleVC -{ - [self iterateOverIngredientButtons:^(UIButton *ingredientButton) { - ingredientButton.enabled = YES; - [ingredientButton setTitle:[self nameForIngredientAtXOrigin:ingredientButton.frame.origin.x] forState:UIControlStateNormal]; - }]; - [self.ingredientPickerScrollView setScrollEnabled:YES]; -} - -- (void)iterateOverIngredientButtons:(void (^)(UIButton *))work -{ - for (UIButton *ingredientButton in self.ingredientPickerScrollView.subviews) - { - if ([ingredientButton isKindOfClass:[UIButton class]]) - { - work(ingredientButton); - } - } -} - -@end diff --git a/CookSmart/CookSmart/CSConversionVC.xib b/CookSmart/CookSmart/CSConversionVC.xib deleted file mode 100644 index 7b0b092..0000000 --- a/CookSmart/CookSmart/CSConversionVC.xib +++ /dev/null @@ -1,46 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/CookSmart/CookSmart/Conversion/ConversionViewController.swift b/CookSmart/CookSmart/Conversion/ConversionViewController.swift new file mode 100644 index 0000000..284f3fd --- /dev/null +++ b/CookSmart/CookSmart/Conversion/ConversionViewController.swift @@ -0,0 +1,114 @@ +// +// ConversionViewController.swift +// cake +// +// Created by Alex King on 4/11/20. +// Copyright © 2020 Olga Galchenko. All rights reserved. +// + +import Foundation +import UIKit + +class ConversionViewController: UIViewController { + private enum Constants { + static let ingredientButtonHeight: CGFloat = 75 + } + + private var ingredientIndex: UInt = 0 + + public init() { + super.init(nibName: nil, bundle: nil) + } + + @available(*, unavailable) + required init?(coder: NSCoder) { + assertionFailure("init(coder:) has not been implemented") + return nil + } + + private let ingredientButton: UIButton = { + let button = UIButton(type: .system) + button.setTitleColor(Color.redLineColor, for: .normal) + button.titleLabel?.font = AvenirFont.medium.of(size: 17) + button.translatesAutoresizingMaskIntoConstraints = false + button.addTarget(self, action: #selector(ingredientButtonPressed), for: .touchUpInside) + return button + }() + + private lazy var scaleViewController = ScaleViewController(ingredient: currentIngredient!, shouldSyncScales: true) + + private var currentIngredient: CSIngredient? { + CSIngredients.sharedInstance()?.ingredient(atFlattenedIngredientIndex: ingredientIndex) + } + + override func viewDidLoad() { + super.viewDidLoad() + setupViews() + selectIngredientAtCurrentIndex() + + _ = NotificationCenter.default.addObserver(forName: NSNotification.Name(INGREDIENT_DELETE_NOTIFICATION_NAME), + object: nil, + queue: nil) { [weak self] _ in + self?.ingredientIndex = 0 + self?.selectIngredientAtCurrentIndex() + } + } + + override func viewDidAppear(_ animated: Bool) { + super.viewDidAppear(animated) + selectIngredientAtCurrentIndex() + } + + override func viewDidDisappear(_ animated: Bool) { + super.viewDidDisappear(animated) + markIngredientAccess() + } + + private func setupViews() { + view.backgroundColor = Color.background + + view.addSubview(ingredientButton) + ingredientButton.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor).isActive = true + ingredientButton.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true + ingredientButton.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true + ingredientButton.heightAnchor.constraint(equalToConstant: Constants.ingredientButtonHeight).isActive = true + + addChild(scaleViewController) + view.addSubview(scaleViewController.view) + scaleViewController.view.translatesAutoresizingMaskIntoConstraints = false + + scaleViewController.view.topAnchor.constraint(equalTo: ingredientButton.bottomAnchor).isActive = true + scaleViewController.view.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true + scaleViewController.view.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true + scaleViewController.view.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true + } + + private func selectIngredientAtCurrentIndex() { + guard let ingredient = CSIngredients.sharedInstance()?.ingredient(atFlattenedIngredientIndex: ingredientIndex) else { + return + } + ingredientButton.setTitle(ingredient.name, for: .normal) + scaleViewController.ingredient = ingredient + markIngredientAccess() + } + + private func markIngredientAccess() { + currentIngredient?.markAccess() + } + + @objc + private func ingredientButtonPressed() { + guard let ingredientListVC = CSIngredientListVC(delegate: self) else { + return + } + let ingredientListNav = UINavigationController(rootViewController: ingredientListVC) + present(ingredientListNav, animated: true) + } +} + +extension ConversionViewController: CSIngredientListVCDelegate { + func ingredientListVC(_ listVC: CSIngredientListVC!, selectedIngredientGroup ingredientGroupIndex: UInt, ingredientIndex index: UInt) { + ingredientIndex = CSIngredients.sharedInstance()?.flattenedIngredientIndex(forGroupIndex: ingredientGroupIndex, ingredientIndex: index) ?? 0 + selectIngredientAtCurrentIndex() + } +} diff --git a/CookSmart/CookSmart/Core/Colors.swift b/CookSmart/CookSmart/Core/Colors.swift index 479dfd9..178c8a5 100644 --- a/CookSmart/CookSmart/Core/Colors.swift +++ b/CookSmart/CookSmart/Core/Colors.swift @@ -9,17 +9,17 @@ import UIKit enum Color { - static let redLineColor = Color.color( + static let redLineColor = Color.dynamicColor( light: UIColor(red: 187.0 / 255.0, green: 1.0 / 255.0, blue: 3.0 / 255.0, alpha: 1.0), dark: UIColor(red: 187.0 / 255.0, green: 1.0 / 255.0, blue: 3.0 / 255.0, alpha: 1.0) ) - static let background = Color.color( + static let background = Color.dynamicColor( light: UIColor(red: 245.0 / 255.0, green: 245.0 / 255.0, blue: 245.0 / 255.0, alpha: 1.0), dark: UIColor(red: 10.0 / 255.0, green: 10.0 / 255.0, blue: 10.0 / 255.0, alpha: 1.0) ) - private static func color(light: UIColor, dark: UIColor) -> UIColor { + private static func dynamicColor(light: UIColor, dark: UIColor) -> UIColor { UIColor { traitCollection in switch traitCollection.userInterfaceStyle { case .dark: return dark diff --git a/CookSmart/CookSmart/SceneDelegate.swift b/CookSmart/CookSmart/SceneDelegate.swift index 0687251..ae9cd98 100644 --- a/CookSmart/CookSmart/SceneDelegate.swift +++ b/CookSmart/CookSmart/SceneDelegate.swift @@ -19,7 +19,9 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate { // Use a UIHostingController as window root view controller. if let windowScene = scene as? UIWindowScene { let window = UIWindow(windowScene: windowScene) - window.rootViewController = CSConversionVC(ingredientGroupIndex: 0, ingredientIndex: 0) + + window.rootViewController = ConversionViewController() + self.window = window window.makeKeyAndVisible() } diff --git a/CookSmart/CookSmart/cake-Bridging-Header.h b/CookSmart/CookSmart/cake-Bridging-Header.h index 042f261..7e89c1f 100644 --- a/CookSmart/CookSmart/cake-Bridging-Header.h +++ b/CookSmart/CookSmart/cake-Bridging-Header.h @@ -6,8 +6,8 @@ #import "CSUnit.h" #import "CSUnitCollection.h" -#import "CSConversionVC.h" #import "CSScaleVC.h" #import "CSIngredient.h" #import "CSIngredients.h" #import "CSIngredientListVC.h" +#import "CSScaleView.h"