diff --git a/Sources/AppDelegate.swift b/Sources/AppDelegate.swift index d6972f0..2beb07c 100644 --- a/Sources/AppDelegate.swift +++ b/Sources/AppDelegate.swift @@ -8,6 +8,7 @@ import Cocoa import SwiftSoup import Then +import LaunchAtLogin @main class AppDelegate: NSObject, NSApplicationDelegate { @@ -50,7 +51,7 @@ class AppDelegate: NSObject, NSApplicationDelegate { $0.keyEquivalent = "" $0.tag = 4 } - + private let quitMenuItem = NSMenuItem().then { $0.title = Localized.quit $0.action = #selector(onQuitClick) @@ -59,18 +60,25 @@ class AppDelegate: NSObject, NSApplicationDelegate { } private let friendMenuItem = NSMenuItem().then { - $0.title = Localized.change_friend_username + $0.title = Localized.changeFriendUsername $0.action = #selector(onChangeFriendUsernameClick) $0.tag = 6 $0.keyEquivalent = "f" } private let RemoveFriendMenuItem = NSMenuItem().then { - $0.title = Localized.remove_friend_username + $0.title = Localized.removeFriendUsername $0.action = #selector(onRemoveFriendUsernameClick) $0.tag = 6 $0.keyEquivalent = "d" } + + private let settingMenuItem = NSMenuItem().then { + $0.title = Localized.setting + $0.action = #selector(onSettingClick) + $0.keyEquivalent = "s" + $0.tag = 7 + } func applicationDidFinishLaunching(_: Notification) { @@ -104,6 +112,7 @@ class AppDelegate: NSObject, NSApplicationDelegate { menu.addItem(.separator()) menu.addItem(refreshMenuItem) menu.addItem(changeUserMenuItem) + menu.addItem(settingMenuItem) menu.addItem(quitMenuItem) statusItem = NSStatusBar.system.statusItem(withLength: NSStatusItem.variableLength) @@ -122,11 +131,24 @@ class AppDelegate: NSObject, NSApplicationDelegate { let userMenuItemTitle = Localized.hello.replacingOccurrences(of: "${username}", with: username).replacingOccurrences(of: "${withFriend}", with: withFriend) userMenuItem.attributedTitle = NSAttributedString(string: userMenuItemTitle) - let friendMenuItemTitle = self.friendUsername.isEmpty ? Localized.set_friend_username : Localized.change_friend_username + let friendMenuItemTitle = self.friendUsername.isEmpty ? Localized.setFriendUsername : Localized.changeFriendUsername friendMenuItem.title = friendMenuItemTitle RemoveFriendMenuItem.isHidden = self.friendUsername.isEmpty } + + private func showSettingAlert() { + let alert = NSAlert() + + alert.messageText = Localized.settingTitle + let button = NSButton(checkboxWithTitle: Localized.autoLaunch, target: nil, action: #selector(setupLauchToggle)) + button.state = LaunchAtLogin.isEnabled ? .on : .off + alert.accessoryView = button + + if alert.runModal() == .alertFirstButtonReturn { + return + } + } private func showChangeUsernameAlert() { let alert = NSAlert() @@ -220,6 +242,14 @@ class AppDelegate: NSObject, NSApplicationDelegate { let url = URL(string: "https://github.com/techinpark/Jandi")! NSWorkspace.shared.open(url) } + + @objc func onSettingClick() { + showSettingAlert() + } + + @objc func setupLauchToggle() { + LaunchAtLogin.isEnabled.toggle() + } private func changeUsername(withUsername username: String) { diff --git a/Sources/Consts/Localized.swift b/Sources/Consts/Localized.swift index b814198..01068d2 100644 --- a/Sources/Consts/Localized.swift +++ b/Sources/Consts/Localized.swift @@ -13,19 +13,24 @@ enum Localized { static let withFriend = NSLocalizedString("with_friend", comment: "\nwith @${username}") static let refresh = NSLocalizedString("refresh", comment: "refresh") static let changeUsername = NSLocalizedString("change_username", comment: "Change username") - static let change_friend_username = NSLocalizedString("change_friend_username", comment: "Change friend username") - static let set_friend_username = NSLocalizedString("set_friend_username", comment: "Set friend username") - static let remove_friend_username = NSLocalizedString("remove_friend_username", comment: "Remove friend username") + static let changeFriendUsername = NSLocalizedString("change_friend_username", comment: "Change friend username") + static let setFriendUsername = NSLocalizedString("set_friend_username", comment: "Set friend username") + static let removeFriendUsername = NSLocalizedString("remove_friend_username", comment: "Remove friend username") static let help = NSLocalizedString("help", comment: "help") static let textFieldPlaceholder = NSLocalizedString("textfield_placeholder", comment: "Github username") static let setUsernameDescription = NSLocalizedString("username_description", comment: "Set username") static let changeUsernameDescription = NSLocalizedString("change_username_description", comment: "Change username") + static let autoLaunch = NSLocalizedString("auto_launch", comment: "Automatically start Jandi at login") static let information = NSLocalizedString("information", comment: "Enter your GitHub username. We’ll fetch the number of contributions.") static let friend_information = NSLocalizedString("friend_information", comment: "Enter your friend GitHub username. We'll fetch the number of contributions.") - static let streak_first_stage = NSLocalizedString("streak_first_stage", comment: "streak stage 1") - static let streak_second_stage = NSLocalizedString("streak_second_stage", comment: "streak stage 2") - static let streak_third_stage = NSLocalizedString("streak_third_stage", comment: "streak stage 3") - static let streak_fourth_stage = NSLocalizedString("streak_fourth_stage", comment: "streak stage 4") + static let setting = NSLocalizedString("setting", comment: "Preferences") + static let settingTitle = NSLocalizedString("setting_title", comment: "Preferences Title") + + static let streakFristStage = NSLocalizedString("streak_first_stage", comment: "streak stage 1") + static let streakSecondStage = NSLocalizedString("streak_second_stage", comment: "streak stage 2") + static let streakThirdStage = NSLocalizedString("streak_third_stage", comment: "streak stage 3") + static let streakForthStage = NSLocalizedString("streak_fourth_stage", comment: "streak stage 4") + static let ok = NSLocalizedString("ok", comment: "Okay") static let cancel = NSLocalizedString("cancel", comment: "cancel") static let error = NSLocalizedString("error", comment: "error") diff --git a/Sources/Extensions/Int+Extensions.swift b/Sources/Extensions/Int+Extensions.swift index afd65a8..82dac7f 100644 --- a/Sources/Extensions/Int+Extensions.swift +++ b/Sources/Extensions/Int+Extensions.swift @@ -24,13 +24,13 @@ extension Int { func getStreaks() -> String { switch self { case 0: - return Localized.streak_first_stage + return Localized.streakFristStage case 1 ..< 4: - return Localized.streak_second_stage + return Localized.streakSecondStage case 4 ..< 10: - return Localized.streak_third_stage.replacingOccurrences(of: "${day}", with: self.description) + return Localized.streakThirdStage.replacingOccurrences(of: "${day}", with: self.description) default: - return Localized.streak_fourth_stage.replacingOccurrences(of: "${day}", with: self.description) + return Localized.streakForthStage.replacingOccurrences(of: "${day}", with: self.description) } } } diff --git a/Supporting FIles/en.lproj/Localizable.strings b/Supporting FIles/en.lproj/Localizable.strings index ee4d118..f229768 100644 --- a/Supporting FIles/en.lproj/Localizable.strings +++ b/Supporting FIles/en.lproj/Localizable.strings @@ -9,11 +9,12 @@ "wellcome_user_message" = "πŸ‘‹ Hello, @${username} ${withFriend}"; "with_friend" = "\nwith @${username}"; "refresh" = "⏳ Refresh"; -"change_username" = "βš™οΈ Change username"; +"change_username" = "πŸͺ„ Change username"; "change_friend_username" = "🀝 Change Friend username"; "set_friend_username" = "🀝 Set Friend username"; "remove_friend_username" = "πŸ™‹β€β™‚οΈ Remove Friend username"; "help" = "πŸ› Bug Report"; +"auto_launch" = "Automatically start Jandi at login"; "textfield_placeholder" = "GitHub username"; "username_description" = "Set username"; "change_username_description" = "Change username"; @@ -23,6 +24,8 @@ "streak_second_stage" = "🌱 I planted my first Jandi today."; "streak_third_stage" = "🌿 It has been ${day} days since the Jandi sprouts."; "streak_fourth_stage" = "🌳 It's been ${day} days since the Jandi has grown well."; +"setting" = "βš™οΈ Preferences"; +"setting_title" = "App Preferences"; "ok" = "Okay"; "cancel" = "Cancel"; "error" = "⚠️ Error"; diff --git a/Supporting FIles/ko.lproj/Localizable.strings b/Supporting FIles/ko.lproj/Localizable.strings index e664c08..a5d845a 100644 --- a/Supporting FIles/ko.lproj/Localizable.strings +++ b/Supporting FIles/ko.lproj/Localizable.strings @@ -9,11 +9,12 @@ "wellcome_user_message" = "πŸ‘‹ μ•ˆλ…•, @${username} ${withFriend}"; "with_friend" = "\n @${username}와 ν•¨κ»˜"; "refresh" = "⏳ μƒˆλ‘œκ³ μΉ¨"; -"change_username" = "βš™οΈ 아이디 λ³€κ²½"; +"change_username" = "πŸͺ„ 아이디 λ³€κ²½"; "change_friend_username" = "🀝 친ꡬ 아이디 λ³€κ²½"; "set_friend_username" = "🀝 친ꡬ 아이디 μ„€μ •"; "remove_friend_username" = "πŸ™‹β€β™‚οΈ 친ꡬ 아이디 제거"; "help" = "πŸ› 버그 μ œλ³΄ν•˜κΈ°"; +"auto_launch" = "μž¬μ‹œμž‘μ‹œ μžλ™ μ‹€ν–‰"; "textfield_placeholder" = "Github 아이디"; "username_description" = "아이디λ₯Ό μž…λ ₯ν•΄μ£Όμ„Έμš”"; "change_username_description" = "아이디λ₯Ό λ³€κ²½ν•©λ‹ˆλ‹€"; @@ -23,6 +24,8 @@ "streak_second_stage" = "🌱 였늘 처음으둜 μž”λ””λ₯Ό μ‹¬μ—ˆμ–΄μš”."; "streak_third_stage" = "🌿 μž”λ””μ— 싹이 튼 지 ${day}일이 λ˜μ—ˆμ–΄μš”."; "streak_fourth_stage" = "🌳 μž”λ””κ°€ 무럭무럭 μžλž€μ§€ ${day}일이 λ˜μ—ˆμ–΄μš”."; +"setting" = "βš™οΈ μ„€μ •"; +"setting_title" = "ν™˜κ²½μ„€μ •"; "ok" = "확인"; "cancel" = "μ·¨μ†Œ"; "error" = "⚠️ 였λ₯˜"; diff --git a/jandi.xcodeproj/project.pbxproj b/jandi.xcodeproj/project.pbxproj index 1b5b5d4..6abfbad 100644 --- a/jandi.xcodeproj/project.pbxproj +++ b/jandi.xcodeproj/project.pbxproj @@ -20,6 +20,7 @@ ED18259525C40ACC00FCD100 /* Then in Frameworks */ = {isa = PBXBuildFile; productRef = ED18259425C40ACC00FCD100 /* Then */; }; ED18259C25C4420A00FCD100 /* Int+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED18259B25C4420A00FCD100 /* Int+Extensions.swift */; }; ED1825A025C4422D00FCD100 /* Date+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED18259F25C4422D00FCD100 /* Date+Extensions.swift */; }; + ED33D3CC25F3805400C18DE9 /* LaunchAtLogin in Frameworks */ = {isa = PBXBuildFile; productRef = ED33D3CB25F3805400C18DE9 /* LaunchAtLogin */; }; ED3FF1F225E3EEAA008CBD34 /* ContributeData.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED3FF1F125E3EEA1008CBD34 /* ContributeData.swift */; }; ED8F6FE425C461320099D861 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = ED8F6FE625C461320099D861 /* Localizable.strings */; }; /* End PBXBuildFile section */ @@ -51,6 +52,7 @@ buildActionMask = 2147483647; files = ( ED18259125C4098C00FCD100 /* SwiftSoup in Frameworks */, + ED33D3CC25F3805400C18DE9 /* LaunchAtLogin in Frameworks */, ED18259525C40ACC00FCD100 /* Then in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; @@ -137,6 +139,7 @@ buildPhases = ( ED18257725C4096400FCD100 /* Sources */, ED18257825C4096400FCD100 /* Frameworks */, + ED33D3CE25F3808B00C18DE9 /* LaunchAtLogin */, ED18257925C4096400FCD100 /* Resources */, ); buildRules = ( @@ -147,6 +150,7 @@ packageProductDependencies = ( ED18259025C4098C00FCD100 /* SwiftSoup */, ED18259425C40ACC00FCD100 /* Then */, + ED33D3CB25F3805400C18DE9 /* LaunchAtLogin */, ); productName = jandi; productReference = ED18257B25C4096400FCD100 /* jandi.app */; @@ -179,6 +183,7 @@ packageReferences = ( ED18258F25C4098C00FCD100 /* XCRemoteSwiftPackageReference "SwiftSoup" */, ED18259325C40ACC00FCD100 /* XCRemoteSwiftPackageReference "Then" */, + ED33D3CA25F3805400C18DE9 /* XCRemoteSwiftPackageReference "LaunchAtLogin" */, ); productRefGroup = ED18257C25C4096400FCD100 /* Products */; projectDirPath = ""; @@ -202,6 +207,27 @@ }; /* End PBXResourcesBuildPhase section */ +/* Begin PBXShellScriptBuildPhase section */ + ED33D3CE25F3808B00C18DE9 /* LaunchAtLogin */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + ); + name = LaunchAtLogin; + outputFileListPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "# Type a script or drag a script file from your workspace to insert its path.\n\"${BUILT_PRODUCTS_DIR}/LaunchAtLogin_LaunchAtLogin.bundle/Contents/Resources/copy-helper-swiftpm.sh\"\n"; + }; +/* End PBXShellScriptBuildPhase section */ + /* Begin PBXSourcesBuildPhase section */ ED18257725C4096400FCD100 /* Sources */ = { isa = PBXSourcesBuildPhase; @@ -369,7 +395,7 @@ CODE_SIGN_ENTITLEMENTS = "$(SRCROOT)/Sources/jandi.entitlements"; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 10; + CURRENT_PROJECT_VERSION = 12; DEVELOPMENT_TEAM = U6GQL8JQMT; ENABLE_HARDENED_RUNTIME = YES; INFOPLIST_FILE = "$(SRCROOT)/Sources/Info.plist"; @@ -378,7 +404,7 @@ "@executable_path/../Frameworks", ); MACOSX_DEPLOYMENT_TARGET = 10.12; - MARKETING_VERSION = 1.5; + MARKETING_VERSION = 1.7; PRODUCT_BUNDLE_IDENTIFIER = com.tmsae.jandi; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_VERSION = 5.0; @@ -394,7 +420,7 @@ CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 10; + CURRENT_PROJECT_VERSION = 12; DEVELOPMENT_TEAM = U6GQL8JQMT; ENABLE_HARDENED_RUNTIME = YES; INFOPLIST_FILE = "$(SRCROOT)/Sources/Info.plist"; @@ -403,7 +429,7 @@ "@executable_path/../Frameworks", ); MACOSX_DEPLOYMENT_TARGET = 10.12; - MARKETING_VERSION = 1.5; + MARKETING_VERSION = 1.7; PRODUCT_BUNDLE_IDENTIFIER = com.tmsae.jandi; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_VERSION = 5.0; @@ -450,6 +476,14 @@ minimumVersion = 2.7.0; }; }; + ED33D3CA25F3805400C18DE9 /* XCRemoteSwiftPackageReference "LaunchAtLogin" */ = { + isa = XCRemoteSwiftPackageReference; + repositoryURL = "https://github.com/sindresorhus/LaunchAtLogin"; + requirement = { + kind = upToNextMajorVersion; + minimumVersion = 4.0.0; + }; + }; /* End XCRemoteSwiftPackageReference section */ /* Begin XCSwiftPackageProductDependency section */ @@ -463,6 +497,11 @@ package = ED18259325C40ACC00FCD100 /* XCRemoteSwiftPackageReference "Then" */; productName = Then; }; + ED33D3CB25F3805400C18DE9 /* LaunchAtLogin */ = { + isa = XCSwiftPackageProductDependency; + package = ED33D3CA25F3805400C18DE9 /* XCRemoteSwiftPackageReference "LaunchAtLogin" */; + productName = LaunchAtLogin; + }; /* End XCSwiftPackageProductDependency section */ }; rootObject = ED18257325C4096400FCD100 /* Project object */; diff --git a/jandi.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/jandi.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index e09b9a1..cf11814 100644 --- a/jandi.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/jandi.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -1,6 +1,15 @@ { "object": { "pins": [ + { + "package": "LaunchAtLogin", + "repositoryURL": "https://github.com/sindresorhus/LaunchAtLogin", + "state": { + "branch": null, + "revision": "0f39982b9d6993eef253b81219d3c39ba1e680f3", + "version": "4.0.0" + } + }, { "package": "SwiftSoup", "repositoryURL": "https://github.com/scinfu/SwiftSoup",