Browse Source

Merge branch 'master' of https://github.com/n0shake/Clocker

pull/92/head
Abhishek 5 years ago
parent
commit
5ea804ff8f
  1. 10
      Clocker/AppDelegate.swift
  2. 41
      Clocker/Clocker.xcodeproj/project.pbxproj
  3. 6
      Clocker/Clocker/en.lproj/Localizable.strings
  4. 7
      Clocker/Clocker/hi.lproj/Localizable.strings
  5. 3
      Clocker/ClockerUITests/AboutUsTests.swift
  6. 24
      Clocker/ClockerUITests/FloatingWindowTests.swift
  7. 4
      Clocker/ClockerUITests/NetworkDisconnectionTests.swift
  8. 60
      Clocker/ClockerUITests/PreferencesTest.swift
  9. 2
      Clocker/Panel/Data Layer/CLTimezoneData.h
  10. 4
      Clocker/Panel/Data Layer/CLTimezoneData.m
  11. 2
      Clocker/Preferences/General/PreferencesViewController.swift

10
Clocker/AppDelegate.swift

@ -57,6 +57,16 @@ open class AppDelegate: NSObject, NSApplicationDelegate {
Fabric.with([Crashlytics.self])
checkIfRunFromApplicationsFolder()
#endif
logCurrentLanguagePreferences()
}
// Help us priortize our localization efforts
private func logCurrentLanguagePreferences() {
let annotations = [
"Language": Locale.preferredLanguages.first ?? "en-US",
]
Logger.log(object: annotations, for: "Locale")
}
public func applicationDockMenu(_: NSApplication) -> NSMenu? {

41
Clocker/Clocker.xcodeproj/project.pbxproj

@ -105,6 +105,7 @@
9A7547E51F184E3F004705EF /* ClockerHelper.app in Login Item Helper */ = {isa = PBXBuildFile; fileRef = 9A7547D01F184DC3004705EF /* ClockerHelper.app */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
9A7CDC1B22BEC2170035902D /* StartupManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9A7CDC1A22BEC2170035902D /* StartupManager.swift */; };
9A8605AE1BEC148400A810A4 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 9A8605AD1BEC148400A810A4 /* main.m */; };
9A8B256A232EFAD300204CAD /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 9A13BAEC1CA88A76007C6CBE /* Localizable.strings */; };
9A9E87621C1FEDB500A7A2DF /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9A9E87611C1FEDB500A7A2DF /* CFNetwork.framework */; };
9A9E876A1C1FEDDB00A7A2DF /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9A9E87691C1FEDDB00A7A2DF /* SystemConfiguration.framework */; };
9AB6F1562259CF3900A44663 /* CalendarViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9AB6F1552259CF3900A44663 /* CalendarViewController.swift */; };
@ -1038,6 +1039,7 @@
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
9A8B256A232EFAD300204CAD /* Localizable.strings in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -1332,6 +1334,12 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_OBJC_IMPLICIT_ATOMIC_PROPERTIES = NO;
CLANG_WARN_OBJC_INTERFACE_IVARS = NO;
CLANG_WARN_OBJC_MISSING_PROPERTY_SYNTHESIS = NO;
CLANG_WARN_SEMICOLON_BEFORE_METHOD_BODY = YES;
CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION = NO;
CODE_SIGN_ENTITLEMENTS = Clocker/Clocker.entitlements;
CODE_SIGN_IDENTITY = "-";
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "-";
@ -1348,8 +1356,15 @@
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = "Clocker/Clocker-Prefix.pch";
"GCC_PREPROCESSOR_DEFINITIONS[arch=*]" = "";
GCC_TREAT_IMPLICIT_FUNCTION_DECLARATIONS_AS_ERRORS = YES;
GCC_TREAT_INCOMPATIBLE_POINTER_TYPE_WARNINGS_AS_ERRORS = YES;
GCC_TREAT_WARNINGS_AS_ERRORS = YES;
GCC_WARN_ABOUT_DEPRECATED_FUNCTIONS = NO;
GCC_WARN_FOUR_CHARACTER_CONSTANTS = YES;
GCC_WARN_SHADOW = YES;
GCC_WARN_SIGN_COMPARE = YES;
GCC_WARN_STRICT_SELECTOR_MATCH = YES;
GCC_WARN_UNKNOWN_PRAGMAS = YES;
GCC_WARN_UNUSED_LABEL = YES;
GCC_WARN_UNUSED_PARAMETER = NO;
INFOPLIST_FILE = "Clocker/Clocker-Info.plist";
@ -1802,6 +1817,12 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_OBJC_IMPLICIT_ATOMIC_PROPERTIES = NO;
CLANG_WARN_OBJC_INTERFACE_IVARS = NO;
CLANG_WARN_OBJC_MISSING_PROPERTY_SYNTHESIS = NO;
CLANG_WARN_SEMICOLON_BEFORE_METHOD_BODY = YES;
CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION = NO;
CODE_SIGN_ENTITLEMENTS = Clocker/Clocker.entitlements;
CODE_SIGN_IDENTITY = "Mac Developer";
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "-";
@ -1819,8 +1840,15 @@
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = "Clocker/Clocker-Prefix.pch";
GCC_PREPROCESSOR_DEFINITIONS = DEBUG;
GCC_TREAT_IMPLICIT_FUNCTION_DECLARATIONS_AS_ERRORS = YES;
GCC_TREAT_INCOMPATIBLE_POINTER_TYPE_WARNINGS_AS_ERRORS = YES;
GCC_TREAT_WARNINGS_AS_ERRORS = YES;
GCC_WARN_ABOUT_DEPRECATED_FUNCTIONS = YES;
GCC_WARN_FOUR_CHARACTER_CONSTANTS = YES;
GCC_WARN_SHADOW = YES;
GCC_WARN_SIGN_COMPARE = YES;
GCC_WARN_STRICT_SELECTOR_MATCH = YES;
GCC_WARN_UNKNOWN_PRAGMAS = YES;
GCC_WARN_UNUSED_LABEL = YES;
GCC_WARN_UNUSED_PARAMETER = YES;
INFOPLIST_FILE = "Clocker/Clocker-Info.plist";
@ -1849,6 +1877,12 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_OBJC_IMPLICIT_ATOMIC_PROPERTIES = NO;
CLANG_WARN_OBJC_INTERFACE_IVARS = NO;
CLANG_WARN_OBJC_MISSING_PROPERTY_SYNTHESIS = NO;
CLANG_WARN_SEMICOLON_BEFORE_METHOD_BODY = YES;
CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION = NO;
CODE_SIGN_ENTITLEMENTS = Clocker/Clocker.entitlements;
CODE_SIGN_IDENTITY = "-";
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "-";
@ -1865,8 +1899,15 @@
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = "Clocker/Clocker-Prefix.pch";
"GCC_PREPROCESSOR_DEFINITIONS[arch=*]" = RELEASE;
GCC_TREAT_IMPLICIT_FUNCTION_DECLARATIONS_AS_ERRORS = YES;
GCC_TREAT_INCOMPATIBLE_POINTER_TYPE_WARNINGS_AS_ERRORS = YES;
GCC_TREAT_WARNINGS_AS_ERRORS = YES;
GCC_WARN_ABOUT_DEPRECATED_FUNCTIONS = YES;
GCC_WARN_FOUR_CHARACTER_CONSTANTS = YES;
GCC_WARN_SHADOW = YES;
GCC_WARN_SIGN_COMPARE = YES;
GCC_WARN_STRICT_SELECTOR_MATCH = YES;
GCC_WARN_UNKNOWN_PRAGMAS = YES;
GCC_WARN_UNUSED_LABEL = YES;
GCC_WARN_UNUSED_PARAMETER = NO;
INFOPLIST_FILE = "Clocker/Clocker-Info.plist";

6
Clocker/Clocker/en.lproj/Localizable.strings

@ -46,9 +46,9 @@
"Sort by Name" = "Sort by Name";
"Sort by Label" = "Sort by Label";
"Search Field Placeholder" = "Enter a city, state or country name";
"No Timezone Selected Error Message" = "Please select a timezone!";
"Max Timezones Selected Error Message" = "Maximum 100 timezones allowed!";
"Max Search Characters Error Message" = "Only 50 characters allowed!";
"No Timezone Selected" = "Please select a timezone!";
"Max Timezones Selected" = "Maximum 100 timezones allowed!";
"Max Search Characters" = "Only 50 characters allowed!";
"Add Button Title" = "Add";
"Close Button Title" = "Close";

7
Clocker/Clocker/hi.lproj/Localizable.strings

@ -6,6 +6,7 @@
*/
"CFBundleDisplayName" = "विव क समय";
"Thank you for helping make Clocker even better!" = "Thank you for helping make Clocker even better!";
"iRateMessageTitle" = "Rate %@";
"iRateAppMessage" = "If you enjoy using %@, would you mind taking a moment to rate it? It won’t take more than a minute. Thanks for your support!";
@ -46,8 +47,8 @@
"Sort by Name" = "नम दट कर";
"Sort by Label" = "लबल दट कर";
"Search Field Placeholder" = "Enter a city, state or country name";
"No Timezone Selected Error Message" = "Please select a timezone!";
"Max Timezones Selected Error Message" = "Maximum 100 timezones allowed!";
"Max Search Characters Error Message" = "Only 50 characters allowed!";
"No Timezone Selected" = "Please select a timezone!";
"Max Timezones Selected" = "Maximum 100 timezones allowed!";
"Max Search Characters" = "Only 50 characters allowed!";
"Add Button Title" = "ऐड ";
"Close Button Title" = "बद कर";

3
Clocker/ClockerUITests/AboutUsTests.swift

@ -32,7 +32,8 @@ class AboutUsTests: XCTestCase {
tapAboutTab()
let expectedVersion = "Clocker 1.6.15 (70)"
let appDisplayName = "CFBundleDisplayName".localizedString()
let expectedVersion = "\(appDisplayName) 1.6.15 (70)"
guard let presentVersion = app.windows["Clocker"].staticTexts["ClockerVersion"].value as? String else {
XCTFail("Present version not present")
return

24
Clocker/ClockerUITests/FloatingWindowTests.swift

@ -2,6 +2,16 @@
import XCTest
extension String {
func localizedString() -> String {
let bundle = Bundle(for: AboutUsTests.self)
let deviceLanguage = Locale.preferredLanguages.first
let localizationBundle = Bundle(path: bundle.path(forResource: deviceLanguage,
ofType: "lproj")!)
return NSLocalizedString(self, bundle: localizationBundle!, comment: "")
}
}
class FloatingWindowTests: XCTestCase {
var app: XCUIApplication!
@ -76,6 +86,18 @@ class FloatingWindowTests: XCTestCase {
let remindersCheckbox = app.checkBoxes["ReminderCheckbox"]
remindersCheckbox.click()
addUIInterruptionMonitor(withDescription: "Reminders Access") { (alert) -> Bool in
print("Interruption Handler called")
print(alert)
let alertButton = alert.buttons["OK"]
if alertButton.exists {
print("Okay button found")
alertButton.tap()
return true
}
return false
}
app.buttons["SaveButton"].click()
app.tapMenubarIcon()
@ -109,7 +131,7 @@ class FloatingWindowTests: XCTestCase {
}
app.buttons["FloatingPreferences"].click()
app.windows["Clocker"].toolbars.buttons["General"].click()
app.windows["Clocker"].toolbars.buttons["Preferences Tab".localizedString()].click()
let menubarDisplayQuery = app.tables.checkBoxes.matching(NSPredicate(format: "value == 1", ""))
let menubarDisplayQueryCount = menubarDisplayQuery.count

4
Clocker/ClockerUITests/NetworkDisconnectionTests.swift

@ -36,7 +36,7 @@ class NetworkDisconnectionTests: XCTestCase {
sleep(1)
XCTAssertTrue(app.sheets.staticTexts["ErrorPlaceholder"].exists)
app.sheets.buttons["Close"].click()
app.sheets.buttons["Close Button Title".localizedString()].click()
}
func testFetchingATimezone() {
@ -66,6 +66,6 @@ class NetworkDisconnectionTests: XCTestCase {
sleep(1)
XCTAssertTrue(app.sheets.staticTexts["ErrorPlaceholder"].exists)
app.sheets.buttons["Close"].click()
app.sheets.buttons["Close Button Title".localizedString()].click()
}
}

60
Clocker/ClockerUITests/PreferencesTest.swift

@ -63,9 +63,9 @@ class PreferencesTest: XCTestCase {
addAPlace(place: "San Francisco", to: app)
addAPlace(place: "Florida", to: app, shouldSleep: false) // Last elements don't need to sleep
XCTAssertTrue(app.windows["Clocker"].checkBoxes["Sort by Time Difference"].exists)
XCTAssertTrue(app.windows["Clocker"].checkBoxes["Sort by Time Difference".localizedString()].exists)
app.windows["Clocker"].checkBoxes["Sort by Time Difference"].click()
app.windows["Clocker"].checkBoxes["Sort by Time Difference".localizedString()].click()
var actualLabels: [String] = []
let newFormattedAddressQuery = app.windows["Clocker"].textFields
@ -78,7 +78,7 @@ class PreferencesTest: XCTestCase {
XCTAssertEqual(actualLabels, ["New Zealand", "Florida", "San Francisco"])
app.windows["Clocker"].checkBoxes["Sort by Time Difference"].click()
app.windows["Clocker"].checkBoxes["Sort by Time Difference".localizedString()].click()
var actualReversedLabels: [String] = []
let newReversedQuery = app.windows["Clocker"].textFields
@ -99,9 +99,9 @@ class PreferencesTest: XCTestCase {
app.tapMenubarIcon()
app.tables["mainTableView"].typeKey(",", modifierFlags: .command)
XCTAssertTrue(app.windows["Clocker"].checkBoxes["Sort by Time Difference"].exists)
XCTAssertTrue(app.windows["Clocker"].checkBoxes["Sort by Label"].exists)
XCTAssertTrue(app.windows["Clocker"].checkBoxes["Sort by Name"].exists)
XCTAssertTrue(app.windows["Clocker"].checkBoxes["Sort by Time Difference".localizedString()].exists)
XCTAssertTrue(app.windows["Clocker"].checkBoxes["Sort by Label".localizedString()].exists)
XCTAssertTrue(app.windows["Clocker"].checkBoxes["Sort by Name".localizedString()].exists)
var formattedAddress: [String] = []
@ -115,8 +115,8 @@ class PreferencesTest: XCTestCase {
formattedAddress.sort()
if let value = app.windows["Clocker"].checkBoxes["Sort by Name"].value as? Int, value == 0 {
app.windows["Clocker"].checkBoxes["Sort by Name"].click()
if let value = app.windows["Clocker"].checkBoxes["Sort by Name".localizedString()].value as? Int, value == 0 {
app.windows["Clocker"].checkBoxes["Sort by Name".localizedString()].click()
}
var newformattedAddress: [String] = []
@ -132,9 +132,9 @@ class PreferencesTest: XCTestCase {
app.windows["Clocker"].checkBoxes["SortButton"].click()
XCTAssertFalse(app.windows["Clocker"].checkBoxes["Sort by Time Difference"].exists)
XCTAssertFalse(app.windows["Clocker"].checkBoxes["Sort by Label"].exists)
XCTAssertFalse(app.windows["Clocker"].checkBoxes["Sort by Name"].exists)
XCTAssertFalse(app.windows["Clocker"].checkBoxes["Sort by Time Difference".localizedString()].exists)
XCTAssertFalse(app.windows["Clocker"].checkBoxes["Sort by Label".localizedString()].exists)
XCTAssertFalse(app.windows["Clocker"].checkBoxes["Sort by Name".localizedString()].exists)
}
func testSortingCitiesByCustomLabel() {
@ -144,8 +144,10 @@ class PreferencesTest: XCTestCase {
addAPlace(place: "Aurangabad", to: app)
addAPlace(place: "Zimbabwe", to: app)
addAPlace(place: "Portland", to: app, shouldSleep: false)
addAPlace(place: "Asia/Kolkata", to: app)
addAPlace(place: "Anywhere on Earth", to: app, shouldSleep: false)
XCTAssertTrue(app.windows["Clocker"].checkBoxes["Sort by Label"].exists)
XCTAssertTrue(app.windows["Clocker"].checkBoxes["Sort by Label".localizedString()].exists)
var expectedLabels: [String] = []
@ -159,8 +161,8 @@ class PreferencesTest: XCTestCase {
expectedLabels.sort()
if let value = app.windows["Clocker"].checkBoxes["Sort by Label"].value as? Int, value == 0 {
app.windows["Clocker"].checkBoxes["Sort by Label"].click()
if let value = app.windows["Clocker"].checkBoxes["Sort by Label".localizedString()].value as? Int, value == 0 {
app.windows["Clocker"].checkBoxes["Sort by Label".localizedString()].click()
}
var actualLabels: [String] = []
@ -176,7 +178,9 @@ class PreferencesTest: XCTestCase {
deleteAPlace(place: "Aurangabad", for: app)
deleteAPlace(place: "Zimbabwe", for: app)
deleteAPlace(place: "Portland", for: app, shouldSleep: false)
deleteAPlace(place: "Portland", for: app)
deleteAPlace(place: "Asia/Kolkata", for: app)
deleteAPlace(place: "Anywhere on Earth", for: app, shouldSleep: false)
}
func testSortingTimezonesByCustomLabel() {
@ -187,7 +191,7 @@ class PreferencesTest: XCTestCase {
addAPlace(place: "Asia/Kolkata", to: app)
addAPlace(place: "Anywhere on Earth", to: app, shouldSleep: false)
XCTAssertTrue(app.windows["Clocker"].checkBoxes["Sort by Label"].exists)
XCTAssertTrue(app.windows["Clocker"].checkBoxes["Sort by Label".localizedString()].exists)
var expectedLabels: [String] = []
@ -201,8 +205,8 @@ class PreferencesTest: XCTestCase {
expectedLabels.sort()
if let value = app.windows["Clocker"].checkBoxes["Sort by Label"].value as? Int, value == 0 {
app.windows["Clocker"].checkBoxes["Sort by Label"].click()
if let value = app.windows["Clocker"].checkBoxes["Sort by Label".localizedString()].value as? Int, value == 0 {
app.windows["Clocker"].checkBoxes["Sort by Label".localizedString()].click()
}
var actualLabels: [String] = []
@ -234,7 +238,7 @@ class PreferencesTest: XCTestCase {
sleep(2)
let maxCharacterCountPredicate = NSPredicate(format: "value like %@", "Only 50 characters allowed!")
let maxCharacterCountPredicate = NSPredicate(format: "value like %@", "Max Search Characters".localizedString())
let currentSheets = app.sheets.firstMatch.staticTexts
let maxCharacterQuery = currentSheets.matching(maxCharacterCountPredicate)
@ -419,10 +423,24 @@ extension XCTestCase {
}
func deleteAPlace(place: String, for app: XCUIApplication, shouldSleep: Bool = true) {
let userPrefferedLanguage = Locale.preferredLanguages.first ?? "en-US"
if !userPrefferedLanguage.lowercased().contains("en") {
// We're testing in a different user language. We can't do string matching here.
// Delete the last row
let rowCount = app.tables["TimezoneTableView"].tableRows.count
let rowToDelete = app.tables["TimezoneTableView"].tableRows.element(boundBy: rowCount - 1)
deleteAtRow(rowToDelete, for: app, shouldSleep: shouldSleep)
return
}
let matchPredicate = NSPredicate(format: "value contains %@", place)
let row = app.tables["TimezoneTableView"].textFields.matching(matchPredicate).firstMatch
row.click()
row.typeKey(XCUIKeyboardKey.delete, modifierFlags: XCUIElement.KeyModifierFlags())
deleteAtRow(row, for: app, shouldSleep: shouldSleep)
}
private func deleteAtRow(_ rowToDelete: XCUIElement, for _: XCUIApplication, shouldSleep: Bool) {
rowToDelete.click()
rowToDelete.typeKey(XCUIKeyboardKey.delete, modifierFlags: XCUIElement.KeyModifierFlags())
if shouldSleep {
sleep(2)
}

2
Clocker/Panel/Data Layer/CLTimezoneData.h

@ -39,7 +39,7 @@ typedef NS_ENUM(NSUInteger, CLTimezoneOverride) {
@property (assign, nonatomic, readonly) CLTimezoneOverride overrideFormat;
+ (instancetype)getCustomObject:(NSData *)encodedData;
- (instancetype)initWithDictionary:(NSDictionary *)dictionary;
- (instancetype)initWithTimezoneInfo:(NSDictionary *)dictionary;
- (void)setLabelForTimezone:(NSString *)customLabel;
- (void)setIDForTimezone:(NSString *)uniqueID;

4
Clocker/Panel/Data Layer/CLTimezoneData.m

@ -27,7 +27,7 @@
@implementation CLTimezoneData
-(instancetype)initWithDictionary:(NSDictionary *)dictionary
-(instancetype)initWithTimezoneInfo:(NSDictionary *)dictionary
{
self = [super init];
@ -72,7 +72,7 @@
{
if ([encodedData isKindOfClass:[NSDictionary class]])
{
CLTimezoneData *newObject = [[self alloc] initWithDictionary:(NSDictionary *)encodedData];
CLTimezoneData *newObject = [[self alloc] initWithTimezoneInfo:(NSDictionary *)encodedData];
return newObject;
}

2
Clocker/Preferences/General/PreferencesViewController.swift

@ -7,7 +7,7 @@ struct PreferencesConstants {
comment: "Message shown when the user taps on Add without selecting a timezone")
static let maxTimezonesErrorMessage = NSLocalizedString("Max Timezones Selected",
comment: "Max Timezones Error Message")
static let maxCharactersAllowed = NSLocalizedString("Max Search Characters Error Message",
static let maxCharactersAllowed = NSLocalizedString("Max Search Characters",
comment: "Max Character Count Allowed Error Message")
static let noInternetConnectivityError = "You're offline, maybe?"
static let tryAgainMessage = "Try again, maybe?"

Loading…
Cancel
Save