[themes] [ios] Added theme manager.

This commit is contained in:
Ilya Grechuhin 2017-01-31 10:30:07 +03:00 committed by Sergey Yershov
parent fac8c7e18b
commit 4ed9fbc45a
13 changed files with 124 additions and 135 deletions

View file

@ -7,6 +7,7 @@
#import "3party/Alohalytics/src/alohalytics_objc.h"
#import "AppInfo.h"
#import "MWMController.h"
#import "MWMFrameworkHelper.h"
#import "MWMKeyboard.h"
#import "MWMLocationManager.h"

View file

@ -47,11 +47,7 @@ typedef NS_ENUM(NSUInteger, MWMRoutingPlaneMode) {
- (void)enableDownloadIndicator;
- (void)showMap;
+ (void)startMapStyleChecker;
+ (void)stopMapStyleChecker;
- (void)showAlertIfRequired;
+ (void)resetToDefaultMapStyle;
+ (void)changeMapStyleIfNedeed;
- (void)setMapStyle:(MapStyle)mapStyle;

View file

@ -24,12 +24,12 @@
#import "MWMTextToSpeech.h"
#import "MapViewController.h"
#import "Statistics.h"
#import "SwiftBridge.h"
#import "3party/Alohalytics/src/alohalytics_objc.h"
#include <sys/xattr.h>
#include "base/sunrise_sunset.hpp"
#include "indexer/osm_editor.hpp"
#include "map/gps_tracker.hpp"
#include "platform/http_thread_apple.h"
@ -291,88 +291,6 @@ using namespace osm_auth_ios;
[self updateApplicationIconBadgeNumber];
}
+ (void)determineMapStyle
{
auto & f = GetFramework();
if ([MWMSettings theme] == MWMThemeAuto)
{
f.SetMapStyle(MapStyleClear);
[UIColor setNightMode:NO];
}
else
{
[UIColor setNightMode:f.GetMapStyle() == MapStyleDark];
}
}
+ (void)startMapStyleChecker
{
if ([MWMSettings theme] != MWMThemeAuto)
return;
MapsAppDelegate.theApp.mapStyleSwitchTimer =
[NSTimer scheduledTimerWithTimeInterval:(30 * 60)
target:self
selector:@selector(changeMapStyleIfNedeed)
userInfo:nil
repeats:YES];
}
+ (void)stopMapStyleChecker { [MapsAppDelegate.theApp.mapStyleSwitchTimer invalidate]; }
+ (void)resetToDefaultMapStyle
{
MapsAppDelegate * app = MapsAppDelegate.theApp;
auto & f = GetFramework();
auto style = f.GetMapStyle();
if (style == MapStyleClear)
return;
f.SetMapStyle(MapStyleClear);
[UIColor setNightMode:NO];
[static_cast<id<MWMController>>(app.mapViewController.navigationController.topViewController)
mwm_refreshUI];
[self stopMapStyleChecker];
}
+ (void)changeMapStyleIfNedeed
{
if ([MWMSettings theme] != MWMThemeAuto)
return;
auto & f = GetFramework();
CLLocation * lastLocation = [MWMLocationManager lastLocation];
if (!lastLocation || !f.IsRoutingActive())
return;
CLLocationCoordinate2D const coord = lastLocation.coordinate;
dispatch_async(dispatch_get_main_queue(), [coord] {
auto & f = GetFramework();
MapsAppDelegate * app = MapsAppDelegate.theApp;
auto const dayTime = GetDayTime(static_cast<time_t>(NSDate.date.timeIntervalSince1970),
coord.latitude, coord.longitude);
id<MWMController> vc = static_cast<id<MWMController>>(
app.mapViewController.navigationController.topViewController);
auto style = f.GetMapStyle();
switch (dayTime)
{
case DayTimeType::Day:
case DayTimeType::PolarDay:
if (style != MapStyleClear)
{
f.SetMapStyle(MapStyleClear);
[UIColor setNightMode:NO];
[vc mwm_refreshUI];
}
break;
case DayTimeType::Night:
case DayTimeType::PolarNight:
if (style != MapStyleDark)
{
f.SetMapStyle(MapStyleDark);
[UIColor setNightMode:YES];
[vc mwm_refreshUI];
}
break;
}
});
}
- (BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
@ -394,7 +312,7 @@ using namespace osm_auth_ios;
[HttpThread setDownloadIndicatorProtocol:self];
InitLocalizedStrings();
[[self class] determineMapStyle];
[MWMThemeManager invalidate];
GetFramework().EnterForeground();

View file

@ -1,6 +1,7 @@
typedef void (^TMWMVoidBlock)();
typedef void (^MWMStringBlock)(NSString *);
typedef NS_ENUM(NSUInteger, MWMDayTime) { MWMDayTimeDay, MWMDayTimeNight };
typedef NS_ENUM(NSUInteger, MWMUnits) { MWMUnitsMetric, MWMUnitsImperial };
@ -10,3 +11,5 @@ typedef NS_ENUM(NSUInteger, MWMRouterType) {
MWMRouterTypeBicycle,
MWMRouterTypeTaxi
};
typedef NS_ENUM(NSUInteger, MWMTheme) { MWMThemeDay, MWMThemeNight, MWMThemeAuto };

View file

@ -1,7 +1,13 @@
#import "MWMTypes.h"
@interface MWMFrameworkHelper : NSObject
+ (void)zoomToCurrentPosition;
+ (void)setVisibleViewport:(CGRect)rect;
+ (void)setTheme:(MWMTheme)theme;
+ (MWMDayTime)daytime;
@end

View file

@ -5,6 +5,8 @@
#include "Framework.h"
#include "base/sunrise_sunset.hpp"
@implementation MWMFrameworkHelper
+ (void)zoomToCurrentPosition
@ -27,4 +29,39 @@
GetFramework().SetVisibleViewport(m2::RectD(x0, y0, x1, y1));
}
+ (void)setTheme:(MWMTheme)theme
{
auto & f = GetFramework();
auto style = f.GetMapStyle();
MapStyle newStyle = MapStyleClear;
switch (theme)
{
case MWMThemeDay: break;
case MWMThemeNight: newStyle = MapStyleDark; break;
case MWMThemeAuto: NSAssert(NO, @"Invalid theme");
}
if (style != newStyle)
f.SetMapStyle(newStyle);
}
+ (MWMDayTime)daytime
{
CLLocation * lastLocation = [MWMLocationManager lastLocation];
if (!lastLocation)
{
NSAssert(false, @"Last location is not available");
return MWMDayTimeDay;
}
auto const coord = lastLocation.coordinate;
auto const timeUtc = static_cast<time_t>(NSDate.date.timeIntervalSince1970);
auto const dayTime = GetDayTime(timeUtc, coord.latitude, coord.longitude);
switch (dayTime)
{
case DayTimeType::Day:
case DayTimeType::PolarDay: return MWMDayTimeDay;
case DayTimeType::Night:
case DayTimeType::PolarNight: return MWMDayTimeNight;
}
}
@end

View file

@ -10,6 +10,7 @@ typedef void (^MWMImageHeightBlock)(UIImage *, NSString *);
+ (BOOL)isTaxi;
+ (void)startRouting;
+ (void)stopRouting;
+ (BOOL)isRoutingActive;
@property(nonatomic, readonly) MWMRoutePoint * startPoint;
@property(nonatomic, readonly) MWMRoutePoint * finishPoint;

View file

@ -18,6 +18,7 @@
#import "MapViewController.h"
#import "MapsAppDelegate.h"
#import "Statistics.h"
#import "SwiftBridge.h"
#import "UIImage+RGBAData.h"
#include "Framework.h"
@ -96,6 +97,7 @@ bool isMarkerPoint(MWMRoutePoint * point) { return point.isValid && !point.isMyP
[MWMNavigationDashboardManager manager].taxiDataSource = nil;
}
+ (BOOL)isRoutingActive { return GetFramework().IsRoutingActive(); }
- (instancetype)initRouter
{
self = [super init];
@ -221,8 +223,7 @@ bool isMarkerPoint(MWMRoutePoint * point) { return point.isValid && !point.isMyP
MapsAppDelegate * app = [MapsAppDelegate theApp];
app.routingPlaneMode = MWMRoutingPlaneModeNone;
[MWMRouterSavedState store];
[MapsAppDelegate changeMapStyleIfNedeed];
[MapsAppDelegate startMapStyleChecker];
[MWMThemeManager setAutoUpdates:YES];
}
else
{
@ -271,8 +272,7 @@ bool isMarkerPoint(MWMRoutePoint * point) { return point.isValid && !point.isMyP
MapsAppDelegate * app = [MapsAppDelegate theApp];
app.routingPlaneMode = MWMRoutingPlaneModeNone;
[MWMRouterSavedState remove];
if ([MWMSettings theme] == MWMThemeAuto)
[MapsAppDelegate resetToDefaultMapStyle];
[MWMThemeManager setAutoUpdates:NO];
[app showAlertIfRequired];
}

View file

@ -1,7 +1,9 @@
#import "MWMSettings.h"
#import "MWMCoreUnits.h"
#import "MWMFrameworkHelper.h"
#import "MWMMapViewControlsManager.h"
#import "MapsAppDelegate.h"
#import "SwiftBridge.h"
#import "3party/Alohalytics/src/alohalytics_objc.h"
@ -19,7 +21,9 @@ char const * kCompassCalibrationEnabledKey = "CompassCalibrationEnabled";
char const * kRoutingDisclaimerApprovedKey = "IsDisclaimerApproved";
char const * kStatisticsEnabledSettingsKey = "StatisticsEnabled";
// TODO(igrechuhin): Remove outdated kUDAutoNightModeOff
NSString * const kUDAutoNightModeOff = @"AutoNightModeOff";
NSString * const kThemeMode = @"ThemeMode";
NSString * const kSpotlightLocaleLanguageId = @"SpotlightLocaleLanguageId";
} // namespace
@ -122,11 +126,10 @@ NSString * const kSpotlightLocaleLanguageId = @"SpotlightLocaleLanguageId";
+ (MWMTheme)theme
{
if (![[NSUserDefaults standardUserDefaults] boolForKey:kUDAutoNightModeOff])
auto ud = [NSUserDefaults standardUserDefaults];
if (![ud boolForKey:kUDAutoNightModeOff])
return MWMThemeAuto;
if (GetFramework().GetMapStyle() == MapStyleDark)
return MWMThemeNight;
return MWMThemeDay;
return static_cast<MWMTheme>([ud integerForKey:kThemeMode]);
}
+ (void)setTheme:(MWMTheme)theme
@ -134,27 +137,10 @@ NSString * const kSpotlightLocaleLanguageId = @"SpotlightLocaleLanguageId";
if ([self theme] == theme)
return;
auto ud = [NSUserDefaults standardUserDefaults];
auto & f = GetFramework();
switch (theme)
{
case MWMThemeDay:
[ud setBool:YES forKey:kUDAutoNightModeOff];
f.SetMapStyle(MapStyleClear);
[UIColor setNightMode:NO];
break;
case MWMThemeNight:
[ud setBool:YES forKey:kUDAutoNightModeOff];
f.SetMapStyle(MapStyleDark);
[UIColor setNightMode:YES];
break;
case MWMThemeAuto:
[ud setBool:NO forKey:kUDAutoNightModeOff];
f.SetMapStyle(MapStyleClear);
[UIColor setNightMode:NO];
[MapsAppDelegate stopMapStyleChecker];
[MapsAppDelegate changeMapStyleIfNedeed];
break;
}
[ud setInteger:theme forKey:kThemeMode];
BOOL const autoOff = theme != MWMThemeAuto;
[ud setBool:autoOff forKey:kUDAutoNightModeOff];
[MWMThemeManager invalidate];
}
+ (BOOL)routingDisclaimerApproved

View file

@ -193,9 +193,9 @@
34570A3B1B13222600E6D4FD /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 34570A3A1B13222600E6D4FD /* libz.dylib */; settings = {ATTRIBUTES = (Required, ); }; };
34570A3D1B13223000E6D4FD /* libsqlite3.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 34570A3C1B13223000E6D4FD /* libsqlite3.dylib */; settings = {ATTRIBUTES = (Required, ); }; };
34570A3F1B13225500E6D4FD /* Accounts.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 34570A3E1B13225500E6D4FD /* Accounts.framework */; settings = {ATTRIBUTES = (Required, ); }; };
34574A621E3B5B620061E839 /* Theme.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34574A611E3B5B620061E839 /* Theme.swift */; };
34574A631E3B5B620061E839 /* Theme.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34574A611E3B5B620061E839 /* Theme.swift */; };
34574A641E3B5B620061E839 /* Theme.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34574A611E3B5B620061E839 /* Theme.swift */; };
34574A661E3B85F80061E839 /* ThemeManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34574A651E3B85F80061E839 /* ThemeManager.swift */; };
34574A671E3B85F80061E839 /* ThemeManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34574A651E3B85F80061E839 /* ThemeManager.swift */; };
34574A681E3B85F80061E839 /* ThemeManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34574A651E3B85F80061E839 /* ThemeManager.swift */; };
3462258E1DDC5DBA001E8752 /* MWMSearchNoResultsAlert.mm in Sources */ = {isa = PBXBuildFile; fileRef = 3462258D1DDC5DBA001E8752 /* MWMSearchNoResultsAlert.mm */; };
3462258F1DDC5DBA001E8752 /* MWMSearchNoResultsAlert.mm in Sources */ = {isa = PBXBuildFile; fileRef = 3462258D1DDC5DBA001E8752 /* MWMSearchNoResultsAlert.mm */; };
346225911DDC5FBA001E8752 /* MWMSearchNoResultsAlert.xib in Resources */ = {isa = PBXBuildFile; fileRef = 346225901DDC5FBA001E8752 /* MWMSearchNoResultsAlert.xib */; };
@ -1523,7 +1523,7 @@
34570A3A1B13222600E6D4FD /* libz.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libz.dylib; path = usr/lib/libz.dylib; sourceTree = SDKROOT; };
34570A3C1B13223000E6D4FD /* libsqlite3.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libsqlite3.dylib; path = usr/lib/libsqlite3.dylib; sourceTree = SDKROOT; };
34570A3E1B13225500E6D4FD /* Accounts.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Accounts.framework; path = System/Library/Frameworks/Accounts.framework; sourceTree = SDKROOT; };
34574A611E3B5B620061E839 /* Theme.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Theme.swift; sourceTree = "<group>"; };
34574A651E3B85F80061E839 /* ThemeManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ThemeManager.swift; sourceTree = "<group>"; };
3462258C1DDC5DB9001E8752 /* MWMSearchNoResultsAlert.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MWMSearchNoResultsAlert.h; sourceTree = "<group>"; };
3462258D1DDC5DBA001E8752 /* MWMSearchNoResultsAlert.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MWMSearchNoResultsAlert.mm; sourceTree = "<group>"; };
346225901DDC5FBA001E8752 /* MWMSearchNoResultsAlert.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = MWMSearchNoResultsAlert.xib; sourceTree = "<group>"; };
@ -2736,7 +2736,7 @@
34574A601E3B5B2A0061E839 /* Appearance */ = {
isa = PBXGroup;
children = (
34574A611E3B5B620061E839 /* Theme.swift */,
34574A651E3B85F80061E839 /* ThemeManager.swift */,
);
path = Appearance;
sourceTree = "<group>";
@ -4783,6 +4783,7 @@
F6E2FE4E1E097BA00083EBEC /* MWMActionBarButton.mm in Sources */,
34BF0CC61C31304A00D097EB /* MWMAuthorizationCommon.mm in Sources */,
349D1CE31E3F836900A878FD /* UIViewController+Hierarchy.swift in Sources */,
34574A661E3B85F80061E839 /* ThemeManager.swift in Sources */,
340475521E081A4600C92850 /* MWMCustomFacebookEvents.mm in Sources */,
F6E2FD761E097BA00083EBEC /* MWMMapDownloaderDataSource.mm in Sources */,
F64F4B741B4A45FD0081A24A /* MWMDownloaderDialogHeader.mm in Sources */,
@ -4873,7 +4874,6 @@
F6E2FEC31E097BA00083EBEC /* MWMSearchFilterPresentationController.mm in Sources */,
340475731E081A4600C92850 /* MWMStorage.mm in Sources */,
F6E2FD851E097BA00083EBEC /* MWMBaseMapDownloaderViewController.mm in Sources */,
34574A621E3B5B620061E839 /* Theme.swift in Sources */,
34ABA6241C2D551900FE1BEC /* MWMInputValidatorFactory.mm in Sources */,
34943BBA1E2626B200B14F84 /* WelcomePageController.swift in Sources */,
F6E2FEE11E097BA00083EBEC /* MWMSearchManager.mm in Sources */,
@ -5043,6 +5043,7 @@
F6E2FE4F1E097BA00083EBEC /* MWMActionBarButton.mm in Sources */,
340475531E081A4600C92850 /* MWMCustomFacebookEvents.mm in Sources */,
349D1CE41E3F836900A878FD /* UIViewController+Hierarchy.swift in Sources */,
34574A671E3B85F80061E839 /* ThemeManager.swift in Sources */,
34BF0CC71C31304A00D097EB /* MWMAuthorizationCommon.mm in Sources */,
F6E2FD771E097BA00083EBEC /* MWMMapDownloaderDataSource.mm in Sources */,
6741A9E01BF340DE002C974C /* MWMDownloaderDialogHeader.mm in Sources */,
@ -5133,7 +5134,6 @@
F6E2FEC41E097BA00083EBEC /* MWMSearchFilterPresentationController.mm in Sources */,
34ABA6251C2D551900FE1BEC /* MWMInputValidatorFactory.mm in Sources */,
F6E2FD861E097BA00083EBEC /* MWMBaseMapDownloaderViewController.mm in Sources */,
34574A631E3B5B620061E839 /* Theme.swift in Sources */,
F6E2FEE21E097BA00083EBEC /* MWMSearchManager.mm in Sources */,
F6E2FE221E097BA00083EBEC /* MWMOpeningHoursEditorViewController.mm in Sources */,
34943BBB1E2626B200B14F84 /* WelcomePageController.swift in Sources */,
@ -5303,6 +5303,7 @@
F6E2FD721E097BA00083EBEC /* MWMMapDownloaderTableViewCell.mm in Sources */,
F6E2FE501E097BA00083EBEC /* MWMActionBarButton.mm in Sources */,
349D1CE51E3F836900A878FD /* UIViewController+Hierarchy.swift in Sources */,
34574A681E3B85F80061E839 /* ThemeManager.swift in Sources */,
849CF6DC1DE842290024A8A5 /* MWMRoutePreview.mm in Sources */,
F6E2FD781E097BA00083EBEC /* MWMMapDownloaderDataSource.mm in Sources */,
849CF6DE1DE842290024A8A5 /* MWMRoutePointLayout.mm in Sources */,
@ -5393,7 +5394,6 @@
F6E2FEC51E097BA00083EBEC /* MWMSearchFilterPresentationController.mm in Sources */,
F6E2FD871E097BA00083EBEC /* MWMBaseMapDownloaderViewController.mm in Sources */,
F6E2FEE31E097BA00083EBEC /* MWMSearchManager.mm in Sources */,
34574A641E3B5B620061E839 /* Theme.swift in Sources */,
34943BBC1E2626B200B14F84 /* WelcomePageController.swift in Sources */,
F6E2FE231E097BA00083EBEC /* MWMOpeningHoursEditorViewController.mm in Sources */,
34D3AFE31E376F7E004100F9 /* UITableView+Updates.swift in Sources */,

View file

@ -1,7 +0,0 @@
@objc(MWMTheme)
enum Theme: Int {
case day
case night
case auto
}

View file

@ -0,0 +1,51 @@
@objc(MWMThemeManager)
final class ThemeManager: NSObject {
private static let autoUpdatesInterval: TimeInterval = 30 * 60;
private static let instance = ThemeManager()
private weak var timer: Timer?
private override init() { super.init() }
private func update(theme: MWMTheme) {
let actualTheme = { theme -> MWMTheme in
guard theme == .auto else { return theme }
guard MWMRouter.isRoutingActive() else { return .day }
switch MWMFrameworkHelper.daytime() {
case .day: return .day
case .night: return .night
}
}(theme)
MWMFrameworkHelper.setTheme(actualTheme)
let nightMode = UIColor.isNightMode()
var newNightMode = false
switch actualTheme {
case .day: break
case .night: newNightMode = true
case .auto: assert(false)
}
if nightMode != newNightMode {
UIColor.setNightMode(newNightMode)
(UIViewController.topViewController() as! MWMController).mwm_refreshUI()
}
}
static func invalidate() {
instance.update(theme: MWMSettings.theme())
}
static var autoUpdates: Bool {
get {
return instance.timer != nil
}
set {
if newValue {
instance.timer = Timer.scheduledTimer(timeInterval: autoUpdatesInterval, target: self, selector: #selector(invalidate), userInfo: nil, repeats: true)
} else {
instance.timer?.invalidate()
}
invalidate()
}
}
}

View file

@ -37,7 +37,6 @@
if ([_selectedCell isEqual:cell])
return;
BOOL const isNightMode = [UIColor isNightMode];
_selectedCell = cell;
NSString * statValue = nil;
if ([cell isEqual:self.on])
@ -55,8 +54,6 @@
[MWMSettings setTheme:MWMThemeAuto];
statValue = kStatValue;
}
if (isNightMode != [UIColor isNightMode])
[self mwm_refreshUI];
[Statistics logEvent:kStatNightMode withParameters:@{kStatValue : statValue}];
}