├── .github └── images │ ├── preview.jpg │ └── preview2.jpg ├── Supporting Files ├── Assets.xcassets │ ├── Contents.json │ ├── AppIcon.appiconset │ │ ├── AppIcon-16.0x16.0@1x.png │ │ ├── AppIcon-16.0x16.0@2x.png │ │ ├── AppIcon-32.0x32.0@1x.png │ │ ├── AppIcon-32.0x32.0@2x.png │ │ ├── AppIcon-128.0x128.0@1x.png │ │ ├── AppIcon-128.0x128.0@2x.png │ │ ├── AppIcon-256.0x256.0@1x.png │ │ ├── AppIcon-256.0x256.0@2x.png │ │ ├── AppIcon-512.0x512.0@1x.png │ │ ├── AppIcon-512.0x512.0@2x.png │ │ └── Contents.json │ └── AccentColor.colorset │ │ └── Contents.json ├── upbitBar.entitlements ├── ko.lproj │ ├── Localizable.strings │ └── Main.strings ├── en.lproj │ └── Localizable.strings ├── Info.plist └── Base.lproj │ └── Main.storyboard ├── upbitBar.xcodeproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ ├── xcuserdata │ │ └── sung.xcuserdatad │ │ │ └── UserInterfaceState.xcuserstate │ └── xcshareddata │ │ ├── IDEWorkspaceChecks.plist │ │ └── swiftpm │ │ └── Package.resolved ├── xcuserdata │ ├── sung.xcuserdatad │ │ └── xcschemes │ │ │ └── xcschememanagement.plist │ └── fernando.xcuserdatad │ │ └── xcschemes │ │ └── xcschememanagement.plist └── project.pbxproj ├── Sources ├── Utils │ ├── Notifications.swift │ ├── UserInfo.swift │ ├── Attributes.swift │ └── Localized.swift ├── Models │ ├── Market.swift │ ├── CryptoAsset.swift │ ├── RefreshInterval.swift │ ├── Ticker.swift │ └── Cryptocurrency.swift ├── Constants │ └── Constants.swift ├── Networking │ ├── UPbitAPI.swift │ └── UpbitServices.swift ├── SettingViewController.swift └── AppDelegate.swift ├── LICENSE ├── README.md └── .gitignore /.github/images/preview.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/techinpark/upbitBar/HEAD/.github/images/preview.jpg -------------------------------------------------------------------------------- /.github/images/preview2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/techinpark/upbitBar/HEAD/.github/images/preview2.jpg -------------------------------------------------------------------------------- /Supporting Files/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /Supporting Files/Assets.xcassets/AppIcon.appiconset/AppIcon-16.0x16.0@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/techinpark/upbitBar/HEAD/Supporting Files/Assets.xcassets/AppIcon.appiconset/AppIcon-16.0x16.0@1x.png -------------------------------------------------------------------------------- /Supporting Files/Assets.xcassets/AppIcon.appiconset/AppIcon-16.0x16.0@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/techinpark/upbitBar/HEAD/Supporting Files/Assets.xcassets/AppIcon.appiconset/AppIcon-16.0x16.0@2x.png -------------------------------------------------------------------------------- /Supporting Files/Assets.xcassets/AppIcon.appiconset/AppIcon-32.0x32.0@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/techinpark/upbitBar/HEAD/Supporting Files/Assets.xcassets/AppIcon.appiconset/AppIcon-32.0x32.0@1x.png -------------------------------------------------------------------------------- /Supporting Files/Assets.xcassets/AppIcon.appiconset/AppIcon-32.0x32.0@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/techinpark/upbitBar/HEAD/Supporting Files/Assets.xcassets/AppIcon.appiconset/AppIcon-32.0x32.0@2x.png -------------------------------------------------------------------------------- /Supporting Files/Assets.xcassets/AppIcon.appiconset/AppIcon-128.0x128.0@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/techinpark/upbitBar/HEAD/Supporting Files/Assets.xcassets/AppIcon.appiconset/AppIcon-128.0x128.0@1x.png -------------------------------------------------------------------------------- /Supporting Files/Assets.xcassets/AppIcon.appiconset/AppIcon-128.0x128.0@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/techinpark/upbitBar/HEAD/Supporting Files/Assets.xcassets/AppIcon.appiconset/AppIcon-128.0x128.0@2x.png -------------------------------------------------------------------------------- /Supporting Files/Assets.xcassets/AppIcon.appiconset/AppIcon-256.0x256.0@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/techinpark/upbitBar/HEAD/Supporting Files/Assets.xcassets/AppIcon.appiconset/AppIcon-256.0x256.0@1x.png -------------------------------------------------------------------------------- /Supporting Files/Assets.xcassets/AppIcon.appiconset/AppIcon-256.0x256.0@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/techinpark/upbitBar/HEAD/Supporting Files/Assets.xcassets/AppIcon.appiconset/AppIcon-256.0x256.0@2x.png -------------------------------------------------------------------------------- /Supporting Files/Assets.xcassets/AppIcon.appiconset/AppIcon-512.0x512.0@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/techinpark/upbitBar/HEAD/Supporting Files/Assets.xcassets/AppIcon.appiconset/AppIcon-512.0x512.0@1x.png -------------------------------------------------------------------------------- /Supporting Files/Assets.xcassets/AppIcon.appiconset/AppIcon-512.0x512.0@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/techinpark/upbitBar/HEAD/Supporting Files/Assets.xcassets/AppIcon.appiconset/AppIcon-512.0x512.0@2x.png -------------------------------------------------------------------------------- /upbitBar.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Supporting Files/Assets.xcassets/AccentColor.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "idiom" : "universal" 5 | } 6 | ], 7 | "info" : { 8 | "author" : "xcode", 9 | "version" : 1 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /upbitBar.xcodeproj/project.xcworkspace/xcuserdata/sung.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/techinpark/upbitBar/HEAD/upbitBar.xcodeproj/project.xcworkspace/xcuserdata/sung.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /upbitBar.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Sources/Utils/Notifications.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Notifications.swift 3 | // upbitBar 4 | // 5 | // Created by Fernando on 2021/03/09. 6 | // 7 | 8 | import Foundation 9 | 10 | extension Notification.Name { 11 | static let neededTokenSetting = Notification.Name("neededTokenSetting") 12 | static let neededRefresh = Notification.Name("neededRefresh") 13 | } 14 | -------------------------------------------------------------------------------- /Sources/Models/Market.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Market.swift 3 | // upbitBar 4 | // 5 | // Created by SUNG on 2021/03/18. 6 | // 7 | 8 | import Foundation 9 | 10 | struct Market: Codable { 11 | let market, koreanName, englishName: String? 12 | 13 | enum CodingKeys: String, CodingKey { 14 | case market 15 | case koreanName = "korean_name" 16 | case englishName = "english_name" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Supporting Files/upbitBar.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.security.app-sandbox 6 | 7 | com.apple.security.files.user-selected.read-only 8 | 9 | com.apple.security.network.client 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /Sources/Constants/Constants.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Constants.swift 3 | // upbitBar 4 | // 5 | // Created by SUNG on 2021/03/18. 6 | // 7 | 8 | import Foundation 9 | 10 | enum Constants: String{ 11 | case bearer = "Bearer" 12 | case authorization = "Authorization" 13 | case notionURL = "https://www.notion.so/UpbitBar-6b9cc7ab41474a9eaa5e9c69addd59e3" 14 | } 15 | 16 | enum UpbitKey: String{ 17 | case accessKey 18 | case secretKey 19 | case refreshInterval 20 | } 21 | 22 | 23 | enum ServicesKey: String{ 24 | case accessKey = "access_key" 25 | case nonce 26 | case hs256 = "HS256" 27 | } 28 | -------------------------------------------------------------------------------- /Sources/Models/CryptoAsset.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CryptoAsset.swift 3 | // upbitBar 4 | // 5 | // Created by Fernando on 2021/03/08. 6 | // 7 | 8 | import Foundation 9 | 10 | // MARK: - CryptoAsset 11 | struct CryptoAsset: Codable { 12 | let currency: String 13 | let balance: String 14 | let locked: String 15 | let avgBuyPrice: String 16 | let avgBuyPriceModified: Bool 17 | let unitCurrency: String 18 | 19 | enum CodingKeys: String, CodingKey { 20 | case currency = "currency" 21 | case balance = "balance" 22 | case locked = "locked" 23 | case avgBuyPrice = "avg_buy_price" 24 | case avgBuyPriceModified = "avg_buy_price_modified" 25 | case unitCurrency = "unit_currency" 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Supporting Files/ko.lproj/Localizable.strings: -------------------------------------------------------------------------------- 1 | /* 2 | Localizable.strings 3 | upbitBar 4 | 5 | Created by Fernando on 2021/03/09. 6 | 7 | */ 8 | "app_refresh" = "♻️ 새로고침"; 9 | "app_setting" = "⚙️ 설정"; 10 | "app_quit" = "🚪 종료"; 11 | 12 | "setting_title" = "🎉 upbitBar 설정하기"; 13 | "setting_auto_launch" = "재시작시 자동 실행"; 14 | "access_token_title" = "Access key"; 15 | "secret_token_title" = "Secret key"; 16 | "refresh_time_title" = "갱신주기"; 17 | "setting_quit" = "닫기"; 18 | "setting_help_feedback" = "도움말 보기"; 19 | "setting_save" = "저장"; 20 | "setting_alert_title" = "알림"; 21 | "setting_alert_accesstoken_info" = "Access Token 값이 올바르지 않습니다 다시한번 확인해주세요 "; 22 | "setting_alert_refreshtoken_info" = "Refresh Token 값이 올바르지 않습니다 다시한번 확인해주세요 "; 23 | "ok" = "확인"; 24 | "one_minutes" = "1분"; 25 | "five_minutes" = "5분"; 26 | "ten_minutes" = "10분"; 27 | "fifteen_minutes" = "15분"; 28 | -------------------------------------------------------------------------------- /Supporting Files/en.lproj/Localizable.strings: -------------------------------------------------------------------------------- 1 | /* 2 | Localizable.strings 3 | upbitBar 4 | 5 | Created by Fernando on 2021/03/09. 6 | 7 | */ 8 | 9 | "app_refresh" = "♻️ Refresh"; 10 | "app_setting" = "⚙️ Preferences"; 11 | "app_quit" = "🚪 Quit"; 12 | 13 | "setting_title" = "Wellcome to upbitBar"; 14 | "setting_auto_launch" = "Automatically start at Login"; 15 | "access_token_title" = "Access key"; 16 | "secret_token_title" = "Secret key"; 17 | "refresh_time_title" = "Refresh Time"; 18 | "setting_quit" = "Quit"; 19 | "setting_help_feedback" = "Help & Feedback"; 20 | "setting_save" = "Save"; 21 | "setting_alert_title" = "Warning"; 22 | "setting_alert_accesstoken_info" = "Warning"; 23 | "setting_alert_refreshtoken_info" = ""; 24 | "ok" = "Okay"; 25 | "one_minutes" = "1 Minutes"; 26 | "five_minutes" = "5 Minutes"; 27 | "ten_minutes" = "10 Minutes"; 28 | "fifteen_minutes" = "15 Minutes"; 29 | -------------------------------------------------------------------------------- /Sources/Utils/UserInfo.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UserInfo.swift 3 | // upbitBar 4 | // 5 | // Created by Fernando on 2021/03/09. 6 | // 7 | 8 | import Foundation 9 | 10 | @propertyWrapper 11 | struct UserInfo { 12 | private let key: String 13 | private let defaultValue: T 14 | 15 | 16 | var wrappedValue: T { 17 | get { return UserDefaults.standard.object(forKey: key) as? T ?? defaultValue } 18 | set { UserDefaults.standard.set(newValue, forKey: key) } 19 | } 20 | 21 | init(key: String, defaultValue: T) { 22 | self.key = key 23 | self.defaultValue = defaultValue 24 | } 25 | } 26 | 27 | struct UPbitKeys { 28 | @UserInfo(key: UpbitKey.accessKey.rawValue, defaultValue: "") var accessToken: String 29 | @UserInfo(key: UpbitKey.secretKey.rawValue, defaultValue: "") var secretToken: String 30 | @UserInfo(key: UpbitKey.refreshInterval.rawValue, defaultValue: 1) var refershInterVal: Int 31 | } 32 | -------------------------------------------------------------------------------- /Sources/Models/RefreshInterval.swift: -------------------------------------------------------------------------------- 1 | // 2 | // RefreshInterval.swift 3 | // upbitBar 4 | // 5 | // Created by Fernando on 2021/03/09. 6 | // 7 | 8 | import Foundation 9 | 10 | enum RefreshInterval: Int { 11 | case one = 0 12 | case five = 1 13 | case ten = 2 14 | case fifteen = 3 15 | 16 | var title: String { 17 | switch self { 18 | case .one: return NSLocalizedString("one_minutes", comment: "1 minutes") 19 | case .five: return NSLocalizedString("five_minutes", comment: "5 minutes") 20 | case .ten: return NSLocalizedString("ten_minutes", comment: "10 minutes") 21 | case .fifteen: return NSLocalizedString("fifteen_minutes", comment: "15 minutes") 22 | } 23 | } 24 | 25 | var minutes: Int { 26 | switch self { 27 | case .one: return 1 28 | case .five: return 5 29 | case .ten: return 10 30 | case .fifteen: return 15 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /Sources/Utils/Attributes.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Attributes.swift 3 | // upbitBar 4 | // 5 | // Created by Fernando on 2021/03/10. 6 | // 7 | 8 | import Foundation 9 | import Cocoa 10 | 11 | enum Attributes { 12 | 13 | static var cryptoRedAttributes: [NSAttributedString.Key: Any] { 14 | return [.font : NSFont.systemFont(ofSize: 12.0, weight: .light), 15 | .foregroundColor : NSColor(red: 197/255.0, green: 39/255.0, blue: 68/255.0, alpha: 1) 16 | ] 17 | } 18 | 19 | static var cryptoBlueAttributes: [NSAttributedString.Key: Any] { 20 | return [.font : NSFont.systemFont(ofSize: 12.0, weight: .light), 21 | .foregroundColor : NSColor(red: 39/255.0, green: 139/255.0, blue: 197/255.0, alpha: 1) 22 | ] 23 | } 24 | 25 | static var cryptoNormalAttributes: [NSAttributedString.Key: Any] { 26 | return [.font : NSFont.systemFont(ofSize: 12.0, weight: .light), 27 | .foregroundColor : NSColor.white 28 | ] 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Sources/Networking/UPbitAPI.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UPbitAPI.swift 3 | // upbitBar 4 | // 5 | // Created by Fernando on 2021/03/08. 6 | // 7 | 8 | import Foundation 9 | 10 | enum UpbitAPI { 11 | 12 | /// 나의 자산을 조회합니다 13 | case balances 14 | 15 | /// 현재가를 조회합니다 16 | case ticker 17 | 18 | /// 업비트에서 거래 가능한 목록을 조회합니다 19 | case market 20 | } 21 | 22 | extension UpbitAPI { 23 | 24 | /// baseURL 을 지정합니다 25 | var baseURL: String { 26 | return "https://api.upbit.com" 27 | } 28 | 29 | /// API Version 30 | var version: String { 31 | return "v1" 32 | } 33 | 34 | /// endpoint를 지정합니다 35 | var endPoint: String { 36 | switch self { 37 | case .balances: 38 | return "/\(version)/accounts/" 39 | case .ticker: 40 | return "/\(version)/ticker/" 41 | case .market: 42 | return "/\(version)/market/" 43 | } 44 | } 45 | 46 | var targetURL: String { 47 | return baseURL + endPoint 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Fernando 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Supporting Files/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIconFile 10 | 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | $(PRODUCT_NAME) 17 | CFBundlePackageType 18 | $(PRODUCT_BUNDLE_PACKAGE_TYPE) 19 | CFBundleShortVersionString 20 | 1.2 21 | CFBundleVersion 22 | 4 23 | LSApplicationCategoryType 24 | public.app-category.utilities 25 | LSMinimumSystemVersion 26 | $(MACOSX_DEPLOYMENT_TARGET) 27 | LSUIElement 28 | 29 | NSMainStoryboardFile 30 | Main 31 | NSPrincipalClass 32 | NSApplication 33 | 34 | 35 | -------------------------------------------------------------------------------- /upbitBar.xcodeproj/xcuserdata/sung.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | QuickStart (Playground) 1.xcscheme 8 | 9 | isShown 10 | 11 | orderHint 12 | 6 13 | 14 | QuickStart (Playground) 2.xcscheme 15 | 16 | isShown 17 | 18 | orderHint 19 | 7 20 | 21 | QuickStart (Playground).xcscheme 22 | 23 | isShown 24 | 25 | orderHint 26 | 5 27 | 28 | SnapKitPlayground (Playground) 1.xcscheme 29 | 30 | isShown 31 | 32 | orderHint 33 | 3 34 | 35 | SnapKitPlayground (Playground) 2.xcscheme 36 | 37 | isShown 38 | 39 | orderHint 40 | 4 41 | 42 | SnapKitPlayground (Playground).xcscheme 43 | 44 | isShown 45 | 46 | orderHint 47 | 2 48 | 49 | upbitBar.xcscheme_^#shared#^_ 50 | 51 | orderHint 52 | 1 53 | 54 | 55 | 56 | 57 | -------------------------------------------------------------------------------- /Supporting Files/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "AppIcon-16.0x16.0@1x.png", 5 | "idiom" : "mac", 6 | "scale" : "1x", 7 | "size" : "16x16" 8 | }, 9 | { 10 | "filename" : "AppIcon-16.0x16.0@2x.png", 11 | "idiom" : "mac", 12 | "scale" : "2x", 13 | "size" : "16x16" 14 | }, 15 | { 16 | "filename" : "AppIcon-32.0x32.0@1x.png", 17 | "idiom" : "mac", 18 | "scale" : "1x", 19 | "size" : "32x32" 20 | }, 21 | { 22 | "filename" : "AppIcon-32.0x32.0@2x.png", 23 | "idiom" : "mac", 24 | "scale" : "2x", 25 | "size" : "32x32" 26 | }, 27 | { 28 | "filename" : "AppIcon-128.0x128.0@1x.png", 29 | "idiom" : "mac", 30 | "scale" : "1x", 31 | "size" : "128x128" 32 | }, 33 | { 34 | "filename" : "AppIcon-128.0x128.0@2x.png", 35 | "idiom" : "mac", 36 | "scale" : "2x", 37 | "size" : "128x128" 38 | }, 39 | { 40 | "filename" : "AppIcon-256.0x256.0@1x.png", 41 | "idiom" : "mac", 42 | "scale" : "1x", 43 | "size" : "256x256" 44 | }, 45 | { 46 | "filename" : "AppIcon-256.0x256.0@2x.png", 47 | "idiom" : "mac", 48 | "scale" : "2x", 49 | "size" : "256x256" 50 | }, 51 | { 52 | "filename" : "AppIcon-512.0x512.0@1x.png", 53 | "idiom" : "mac", 54 | "scale" : "1x", 55 | "size" : "512x512" 56 | }, 57 | { 58 | "filename" : "AppIcon-512.0x512.0@2x.png", 59 | "idiom" : "mac", 60 | "scale" : "2x", 61 | "size" : "512x512" 62 | } 63 | ], 64 | "info" : { 65 | "author" : "xcode", 66 | "version" : 1 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /Sources/Utils/Localized.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Localized.swift 3 | // upbitBar 4 | // 5 | // Created by Fernando on 2021/03/09. 6 | // 7 | 8 | import Foundation 9 | 10 | struct Localized { 11 | 12 | static let refresh = NSLocalizedString("app_refresh", comment: "♻️ Refresh") 13 | static let setting = NSLocalizedString("app_setting", comment: "⚙️ Preferences") 14 | static let quit = NSLocalizedString("app_quit", comment: "🚪 Quit") 15 | 16 | /// SettingViewController 17 | static let settingTitle = NSLocalizedString("setting_title", comment: "Wellcome to upbitBar") 18 | static let autoLaunch = NSLocalizedString("setting_auto_launch", comment: "Automatically start at Login") 19 | static let accessToken = NSLocalizedString("access_token_title", comment: "Access Key") 20 | static let secretToken = NSLocalizedString("secret_token_title", comment: "Secret Key") 21 | static let refreshTime = NSLocalizedString("refresh_time_title", comment: "Refresh Time") 22 | 23 | static let settingQuit = NSLocalizedString("setting_quit", comment: "Quit") 24 | static let settingHelpFeedback = NSLocalizedString(("setting_help_feedback"), comment: "Help & Feedback") 25 | static let settingSave = NSLocalizedString("setting_save", comment: "Save") 26 | 27 | static let settingAlertTitle = NSLocalizedString("setting_alert_title", comment: "Warning") 28 | static let settingAlertAccessTokenInfoText = NSLocalizedString("setting_alert_accesstoken_info", comment: "") 29 | static let settingAlertRefreshTokenInfoText = NSLocalizedString("setting_alert_refreshtoken_info", comment: "") 30 | static let ok = NSLocalizedString("ok", comment: "ok") 31 | 32 | static let oneMinutes = NSLocalizedString("one_minutes", comment: "1 minutes") 33 | static let fiveMinutes = NSLocalizedString("five_minutes", comment: "5 minutes") 34 | static let tenMinutes = NSLocalizedString("ten_minutes", comment: "10 minutes") 35 | static let fifteenMinues = NSLocalizedString("fifteen_minutes", comment: "15 minutes") 36 | } 37 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # upbitBar 2 | 3 | 4 | [![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg?style=flat)](https://github.com/techinpark/jandi/blob/main/LICENSE) 5 | [![Platform](https://img.shields.io/badge/platform-macOS-green.svg?style=flat)](https://github.com/techinpark/jandi) 6 | [![Swift 5.0](https://img.shields.io/badge/Swift-5.0-orange.svg?style=flat)](https://developer.apple.com/swift/) 7 | ![Twitter](https://img.shields.io/twitter/follow/techinpark.svg?style=social&label=Follow) 8 | 9 | 10 | ## 소개 🔍 11 | 12 | - 업비트 지갑 매번 스마트폰으로 확인하지 마시고 상태바에서 손쉽게 확인해보세요 💰 13 | - Swift 5.0 으로 작성되었습니다. 14 | 15 | ## 미리보기 👀 16 | 17 | - 설정을 하게되면 상태바에서 업비트 지갑의 잔액을 실시간으로 보실 수 있습니다. 18 | - 미리보기로 제공된 이미지는 예시입니다 19 | 20 | ![](./.github/images/preview2.jpg) 21 | 22 | 23 | ## 요구 사항 🪄 24 | 25 | - `UpbitBar` 프로젝트는 Swift 5.0 으로 작성되었습니다. 26 | - macOS 10.15 버전 이상에서 동작합니다. 27 | 28 | 29 | ## 사용한 라이브러리 📦 30 | 31 | - [Just](https://github.com/dduan/Just) 32 | - [JWTComponents](https://github.com/couchdeveloper/JWTComponents) 33 | - [LaunchAtLogin](https://github.com/sindresorhus/LaunchAtLogin) 34 | - [SnapKit](https://github.com/SnapKit/SnapKit) 35 | - [Then](https://github.com/devxoul/Then) 36 | 37 | ## 설치하기 🎉 38 | 39 | ### AppStore 40 | 41 | Download on the Mac App Store 42 | 43 | ## 이 프로젝트가 유용하셨나요 ? ❤️ 44 | 45 | 저의 프로젝트가 유용하셨다면 [stargazers](https://github.com/techinpark/Jandi/stargazers) 에 동참해주세요 ⭐ 46 | [팔로우](https://github.com/techinpark) 해주신다면 새로운 프로젝트를 더 빠르게 만나보실 수 있습니다 🤩 47 | 48 | ## Author 49 | - [techinpark](https://twitter.com/techinpark) 50 | 51 | ## 기여하기 🌱 52 | 모든 형태의 기여를 기다리고 있습니다 오타 수정, 기능 추가, 기능제안 모두 두팔벌려 환영합니다 🥳 53 | 54 | 55 | ## License 56 | `UpbitBar` is available under the MIT license. See the LICENSE file for more info. 57 | 58 | -------------------------------------------------------------------------------- /upbitBar.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved: -------------------------------------------------------------------------------- 1 | { 2 | "object": { 3 | "pins": [ 4 | { 5 | "package": "Just", 6 | "repositoryURL": "https://github.com/dduan/Just", 7 | "state": { 8 | "branch": null, 9 | "revision": "1824bf84cf52d11d69ae20cfb89f0ce5bffa5650", 10 | "version": "0.8.0" 11 | } 12 | }, 13 | { 14 | "package": "JWTComponents", 15 | "repositoryURL": "https://github.com/couchdeveloper/JWTComponents", 16 | "state": { 17 | "branch": null, 18 | "revision": "ddf78f2213f74c82ad0acbe2e6b08c74908d9dc0", 19 | "version": "0.4.0" 20 | } 21 | }, 22 | { 23 | "package": "LaunchAtLogin", 24 | "repositoryURL": "https://github.com/sindresorhus/LaunchAtLogin", 25 | "state": { 26 | "branch": null, 27 | "revision": "0f39982b9d6993eef253b81219d3c39ba1e680f3", 28 | "version": "4.0.0" 29 | } 30 | }, 31 | { 32 | "package": "SnapKit", 33 | "repositoryURL": "https://github.com/SnapKit/SnapKit", 34 | "state": { 35 | "branch": null, 36 | "revision": "d458564516e5676af9c70b4f4b2a9178294f1bc6", 37 | "version": "5.0.1" 38 | } 39 | }, 40 | { 41 | "package": "swift-crypto", 42 | "repositoryURL": "https://github.com/apple/swift-crypto.git", 43 | "state": { 44 | "branch": null, 45 | "revision": "0141f53dd525706c803b0c20aa8ad36f9ecd45e5", 46 | "version": "1.1.5" 47 | } 48 | }, 49 | { 50 | "package": "swift-log", 51 | "repositoryURL": "https://github.com/apple/swift-log", 52 | "state": { 53 | "branch": null, 54 | "revision": "5d66f7ba25daf4f94100e7022febf3c75e37a6c7", 55 | "version": "1.4.2" 56 | } 57 | }, 58 | { 59 | "package": "Then", 60 | "repositoryURL": "http://github.com/devxoul/then", 61 | "state": { 62 | "branch": null, 63 | "revision": "e421a7b3440a271834337694e6050133a3958bc7", 64 | "version": "2.7.0" 65 | } 66 | } 67 | ] 68 | }, 69 | "version": 1 70 | } 71 | -------------------------------------------------------------------------------- /upbitBar.xcodeproj/xcuserdata/fernando.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | QuickStart (Playground) 1.xcscheme 8 | 9 | isShown 10 | 11 | orderHint 12 | 2 13 | 14 | QuickStart (Playground) 2.xcscheme 15 | 16 | isShown 17 | 18 | orderHint 19 | 3 20 | 21 | QuickStart (Playground) 3.xcscheme 22 | 23 | isShown 24 | 25 | orderHint 26 | 11 27 | 28 | QuickStart (Playground) 4.xcscheme 29 | 30 | isShown 31 | 32 | orderHint 33 | 12 34 | 35 | QuickStart (Playground) 5.xcscheme 36 | 37 | isShown 38 | 39 | orderHint 40 | 13 41 | 42 | QuickStart (Playground).xcscheme 43 | 44 | isShown 45 | 46 | orderHint 47 | 1 48 | 49 | SnapKitPlayground (Playground) 1.xcscheme 50 | 51 | isShown 52 | 53 | orderHint 54 | 5 55 | 56 | SnapKitPlayground (Playground) 2.xcscheme 57 | 58 | isShown 59 | 60 | orderHint 61 | 6 62 | 63 | SnapKitPlayground (Playground) 3.xcscheme 64 | 65 | isShown 66 | 67 | orderHint 68 | 8 69 | 70 | SnapKitPlayground (Playground) 4.xcscheme 71 | 72 | isShown 73 | 74 | orderHint 75 | 9 76 | 77 | SnapKitPlayground (Playground) 5.xcscheme 78 | 79 | isShown 80 | 81 | orderHint 82 | 10 83 | 84 | SnapKitPlayground (Playground).xcscheme 85 | 86 | isShown 87 | 88 | orderHint 89 | 4 90 | 91 | upbitBar.xcscheme_^#shared#^_ 92 | 93 | orderHint 94 | 0 95 | 96 | 97 | 98 | 99 | -------------------------------------------------------------------------------- /Sources/Models/Ticker.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Ticker.swift 3 | // upbitBar 4 | // 5 | // Created by Fernando on 2021/03/08. 6 | // 7 | 8 | import Foundation 9 | 10 | // MARK: - Ticker 11 | 12 | /// Document URL 13 | /// https://docs.upbit.com/reference#ticker%ED%98%84%EC%9E%AC%EA%B0%80-%EB%82%B4%EC%97%AD 14 | 15 | struct Ticker: Codable { 16 | 17 | /// 종목구분코드 18 | let market: String 19 | /// 최근거래일자 (UTC) 20 | let tradeDate: String 21 | /// 최근 거래시각 (UTC) 22 | let tradeTime: String 23 | /// 최근 거래일자 (KST) 24 | let tradeDateKst: String 25 | /// 최근 거래시각 (KST) 26 | let tradeTimeKst: String 27 | /// 최근 거래시간 타임스탬프 28 | let tradeTimestamp: Double 29 | /// 시가 30 | let openingPrice: Double 31 | /// 고가 32 | let highPrice: Double 33 | /// 저가 34 | let lowPrice: Double 35 | /// 종가 36 | let tradePrice: Double 37 | /// 전일종가 38 | let prevClosingPrice: Double 39 | /// 변화 (EVENT: 보합, RISE: 상승, FALL: 하락) 40 | let change: String 41 | /// 변화액의 절대값 42 | let changePrice: Double 43 | /// 변화율의 절대값 44 | let changeRate: Double 45 | /// 부호가 있는 변화액 46 | let signedChangePrice: Double 47 | /// 부호가 있는 변화율 48 | let signedChangeRate: Double 49 | /// 가장최근 거래량 50 | let tradeVolume: Double 51 | /// 누적거래대금 (UTC 0시 기준) 52 | let accTradePrice: Double 53 | /// 24시간 누적 거래량 54 | let accTradePrice24H: Double 55 | /// 누적거래량 (UTC 0시 기준) 56 | let accTradeVolume: Double 57 | /// 24시간 누적 거래량 58 | let accTradeVolume24H: Double 59 | /// 52주 신고가 60 | let highest52_WeekPrice: Double 61 | /// 52주 신고가 달성일 62 | let highest52_WeekDate: String 63 | /// 52주 신저가 64 | let lowest52_WeekPrice: Double 65 | /// 52주 신저가 달성일 66 | let lowest52_WeekDate: String 67 | /// 타임스탬프 68 | let timestamp: UInt 69 | 70 | enum CodingKeys: String, CodingKey { 71 | case market = "market" 72 | case tradeDate = "trade_date" 73 | case tradeTime = "trade_time" 74 | case tradeDateKst = "trade_date_kst" 75 | case tradeTimeKst = "trade_time_kst" 76 | case tradeTimestamp = "trade_timestamp" 77 | case openingPrice = "opening_price" 78 | case highPrice = "high_price" 79 | case lowPrice = "low_price" 80 | case tradePrice = "trade_price" 81 | case prevClosingPrice = "prev_closing_price" 82 | case change = "change" 83 | case changePrice = "change_price" 84 | case changeRate = "change_rate" 85 | case signedChangePrice = "signed_change_price" 86 | case signedChangeRate = "signed_change_rate" 87 | case tradeVolume = "trade_volume" 88 | case accTradePrice = "acc_trade_price" 89 | case accTradePrice24H = "acc_trade_price_24h" 90 | case accTradeVolume = "acc_trade_volume" 91 | case accTradeVolume24H = "acc_trade_volume_24h" 92 | case highest52_WeekPrice = "highest_52_week_price" 93 | case highest52_WeekDate = "highest_52_week_date" 94 | case lowest52_WeekPrice = "lowest_52_week_price" 95 | case lowest52_WeekDate = "lowest_52_week_date" 96 | case timestamp = "timestamp" 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | # Created by https://www.toptal.com/developers/gitignore/api/swift,xcode,swiftpackagemanager 3 | # Edit at https://www.toptal.com/developers/gitignore?templates=swift,xcode,swiftpackagemanager 4 | 5 | ### Swift ### 6 | # Xcode 7 | # 8 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore 9 | 10 | ## User settings 11 | xcuserdata/ 12 | 13 | ## compatibility with Xcode 8 and earlier (ignoring not required starting Xcode 9) 14 | *.xcscmblueprint 15 | *.xccheckout 16 | 17 | ## compatibility with Xcode 3 and earlier (ignoring not required starting Xcode 4) 18 | build/ 19 | DerivedData/ 20 | *.moved-aside 21 | *.pbxuser 22 | !default.pbxuser 23 | *.mode1v3 24 | !default.mode1v3 25 | *.mode2v3 26 | !default.mode2v3 27 | *.perspectivev3 28 | !default.perspectivev3 29 | 30 | ## Obj-C/Swift specific 31 | *.hmap 32 | 33 | ## App packaging 34 | *.ipa 35 | *.dSYM.zip 36 | *.dSYM 37 | 38 | ## Playgrounds 39 | timeline.xctimeline 40 | playground.xcworkspace 41 | 42 | # Swift Package Manager 43 | # Add this line if you want to avoid checking in source code from Swift Package Manager dependencies. 44 | # Packages/ 45 | # Package.pins 46 | # Package.resolved 47 | # *.xcodeproj 48 | # Xcode automatically generates this directory with a .xcworkspacedata file and xcuserdata 49 | # hence it is not needed unless you have added a package configuration file to your project 50 | # .swiftpm 51 | 52 | .build/ 53 | 54 | # CocoaPods 55 | # We recommend against adding the Pods directory to your .gitignore. However 56 | # you should judge for yourself, the pros and cons are mentioned at: 57 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control 58 | # Pods/ 59 | # Add this line if you want to avoid checking in source code from the Xcode workspace 60 | # *.xcworkspace 61 | 62 | # Carthage 63 | # Add this line if you want to avoid checking in source code from Carthage dependencies. 64 | # Carthage/Checkouts 65 | 66 | Carthage/Build/ 67 | 68 | # Accio dependency management 69 | Dependencies/ 70 | .accio/ 71 | 72 | # fastlane 73 | # It is recommended to not store the screenshots in the git repo. 74 | # Instead, use fastlane to re-generate the screenshots whenever they are needed. 75 | # For more information about the recommended setup visit: 76 | # https://docs.fastlane.tools/best-practices/source-control/#source-control 77 | 78 | fastlane/report.xml 79 | fastlane/Preview.html 80 | fastlane/screenshots/**/*.png 81 | fastlane/test_output 82 | 83 | # Code Injection 84 | # After new code Injection tools there's a generated folder /iOSInjectionProject 85 | # https://github.com/johnno1962/injectionforxcode 86 | 87 | iOSInjectionProject/ 88 | 89 | ### SwiftPackageManager ### 90 | Packages 91 | xcuserdata 92 | *.xcodeproj 93 | 94 | 95 | ### Xcode ### 96 | # Xcode 97 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore 98 | 99 | 100 | 101 | 102 | ## Gcc Patch 103 | /*.gcno 104 | 105 | ### Xcode Patch ### 106 | *.xcodeproj/* 107 | !*.xcodeproj/project.pbxproj 108 | !*.xcodeproj/xcshareddata/ 109 | !*.xcworkspace/contents.xcworkspacedata 110 | **/xcshareddata/WorkspaceSettings.xcsettings 111 | 112 | # End of https://www.toptal.com/developers/gitignore/api/swift,xcode,swiftpackagemanager.DS_Store 113 | DerivedData 114 | -------------------------------------------------------------------------------- /Sources/Networking/UpbitServices.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UpbitServices.swift 3 | // upbitBar 4 | // 5 | // Created by Fernando on 2021/03/08. 6 | // 7 | 8 | import Foundation 9 | import JWTComponents 10 | import Just 11 | 12 | /// MARK: UpbitServices 13 | 14 | class UpbitServices { 15 | 16 | static let shared = UpbitServices() 17 | 18 | private let keys = UPbitKeys() 19 | 20 | /// JWT 토큰을 생성합니다 21 | func generateJWTToken() -> String? { 22 | 23 | var jwtc = JWTComponents() 24 | guard let secretKey = keys.secretToken.data(using: .utf8) else { return nil } 25 | let accessToken: String = keys.accessToken 26 | let nonce: String = UUID().uuidString 27 | 28 | do { 29 | try jwtc.setValue(accessToken, forClaim: ServicesKey.accessKey.rawValue) 30 | try jwtc.setValue(nonce, forClaim: ServicesKey.nonce.rawValue) 31 | try jwtc.setValue(ServicesKey.hs256.rawValue, forHeaderParameter: .alg) 32 | try jwtc.sign(withKey: secretKey) 33 | 34 | guard let bearer = jwtc.jwt else { return nil } 35 | return "Bearer \(bearer)" 36 | 37 | } catch { 38 | return nil 39 | } 40 | } 41 | 42 | /// 나의 자산을 조회합니다 43 | func getBalances() -> [CryptoAsset]? { 44 | guard let bearerToken = generateJWTToken() else { return nil } 45 | let targetURL = UpbitAPI.balances.targetURL 46 | let headers: [String: String] = [Constants.authorization.rawValue: bearerToken] 47 | let response = Just.get(targetURL, headers: headers) 48 | guard let jsonData = response.content else { return nil } 49 | 50 | do { 51 | return try JSONDecoder().decode([CryptoAsset].self, from: jsonData) 52 | } catch { 53 | NotificationCenter.default.post(name: .neededTokenSetting, object: nil) 54 | print(error) 55 | return nil 56 | } 57 | } 58 | 59 | /// 현재가를 조회합니다 60 | func getTicker(markets: String) -> [Ticker]? { 61 | guard let bearerToken = generateJWTToken() else { return nil } 62 | let targetURL = "\(UpbitAPI.ticker.targetURL)?markets=\(markets)" 63 | print(targetURL) 64 | 65 | let headers: [String: String] = [Constants.authorization.rawValue: bearerToken] 66 | let response = Just.get(targetURL, headers: headers) 67 | 68 | guard let jsonData = response.content else { return nil } 69 | do { 70 | return try JSONDecoder().decode([Ticker].self, from: jsonData) 71 | } catch { 72 | print("error: \(error.localizedDescription)") 73 | print("response: \(String(describing: String(data: jsonData, encoding: .utf8)))") 74 | return nil 75 | } 76 | } 77 | 78 | // 업비트에서 거래 가능한 코인을 조회합니다 79 | func getAllMarket() -> [Market]?{ 80 | let targetURL = "\(UpbitAPI.market.targetURL)all" 81 | let response = Just.get(targetURL) 82 | 83 | guard let jsonData = response.content else { return nil } 84 | do { 85 | return try JSONDecoder().decode([Market].self, from: jsonData) 86 | } catch { 87 | print("error: \(error.localizedDescription)") 88 | print("response: \(String(describing: String(data: jsonData, encoding: .utf8)))") 89 | return nil 90 | } 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /Sources/Models/Cryptocurrency.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Cryptocurrency.swift 3 | // upbitBar 4 | // 5 | // Created by Fernando on 2021/03/08. 6 | // 7 | 8 | import Foundation 9 | 10 | enum Cryptocurrency: String, Equatable { 11 | 12 | case BTC 13 | case ETH 14 | case XHR 15 | case XEM 16 | case EMC2 17 | case LBC 18 | case CHZ 19 | case BORA 20 | case PCI 21 | case ENJ 22 | case GRS 23 | case META 24 | case SRM 25 | case POWR 26 | case ONG 27 | case SAND 28 | case ADA 29 | case DOT 30 | case HUNT 31 | case CRO 32 | case DMT 33 | case UPP 34 | case EOS 35 | case ETC 36 | case ANKR 37 | case MANA 38 | case SXP 39 | case XLM 40 | case BCH 41 | case MLK 42 | case VET 43 | case GAS 44 | case OMG 45 | case STEEM 46 | case WAXP 47 | case BTT 48 | case DKA 49 | case NPXS 50 | case MTL 51 | case SOLVE 52 | case ICX 53 | case QTUM 54 | case BTG 55 | case MOC 56 | case CRE 57 | case TFUEL 58 | case TRX 59 | case HBAR 60 | case MFT 61 | case LTC 62 | case GLM 63 | case SSX 64 | case STRAX 65 | case XTZ 66 | case HIVE 67 | case TON 68 | case POLY 69 | case LINK 70 | case MVL 71 | case ONT 72 | case MED 73 | case BSV 74 | case SBD 75 | case QTCON 76 | case CVC 77 | case AQT 78 | case TT 79 | case IOST 80 | case PXL 81 | case CBK 82 | case DOGE 83 | case AHT 84 | case SNT 85 | case RFR 86 | case STPT 87 | case THETA 88 | case ZPX 89 | case BAT 90 | case ARK 91 | case ADX 92 | case AERGO 93 | case FCT2 94 | case NEO 95 | case MARO 96 | case STORJ 97 | case JST 98 | case SRN 99 | case ELF 100 | case MBL 101 | case HUM 102 | case LOOM 103 | case OBSR 104 | case ZIL 105 | case KAVA 106 | case ARDR 107 | case KMD 108 | case LAMB 109 | case TSHP 110 | case ATOM 111 | case STMX 112 | case LSK 113 | case BCHA 114 | case EDR 115 | case QKC 116 | case ORBS 117 | case SC 118 | case IGNIS 119 | case SPND 120 | case REP 121 | case IQ 122 | case WAVES 123 | case KNC 124 | case IOTA 125 | 126 | var name: String { 127 | switch self { 128 | 129 | case .BTC: return "비트코인" 130 | case .ETH: return "이더리움" 131 | case .XHR: return "리플" 132 | case .XEM: return "넴" 133 | case .EMC2: return "아인스타이늄" 134 | case .LBC: return "엘비와이크레딧" 135 | case .CHZ: return "칠리즈" 136 | case .BORA: return "보라" 137 | case .PCI: return "페이코인" 138 | case .ENJ: return "엔진코인" 139 | case .GRS: return "그로스톨코인" 140 | case .META: return "메타디움" 141 | case .SRM: return "세럼" 142 | case .POWR: return "파워렛저" 143 | case .ONG: return "온톨로지가스" 144 | case .SAND: return "샌드박스" 145 | case .ADA: return "에이다" 146 | case .DOT: return "폴카닷" 147 | case .HUNT: return "헌트" 148 | case .CRO: return "" 149 | case .DMT: return "" 150 | case .UPP: return "" 151 | case .EOS: return "이오스" 152 | case .ETC: return "" 153 | case .ANKR: return "" 154 | case .MANA: return "" 155 | case .SXP: return "" 156 | case .XLM: return "" 157 | case .BCH: return "" 158 | case .MLK: return "" 159 | case .VET: return "" 160 | case .GAS: return "" 161 | case .OMG: return "" 162 | case .STEEM: return "" 163 | case .WAXP: return "" 164 | case .BTT: return "" 165 | case .DKA: return "" 166 | case .NPXS: return "" 167 | case .MTL: return "" 168 | case .SOLVE: return "" 169 | case .ICX: return "" 170 | case .QTUM: return "" 171 | case .BTG: return "" 172 | case .MOC: return "" 173 | case .CRE: return "" 174 | case .TFUEL: return "" 175 | case .TRX: return "" 176 | case .HBAR: return "" 177 | case .MFT: return "" 178 | case .LTC: return "" 179 | case .GLM: return "" 180 | case .SSX: return "" 181 | case .STRAX: return "" 182 | case .XTZ: return "" 183 | case .HIVE: return "" 184 | case .TON: return "" 185 | case .POLY: return "" 186 | case .LINK: return "" 187 | case .MVL: return "" 188 | case .ONT: return "" 189 | case .MED: return "" 190 | case .BSV: return "" 191 | case .SBD: return "" 192 | case .QTCON: return "" 193 | case .CVC: return "" 194 | case .AQT: return "" 195 | case .TT: return "" 196 | case .IOST: return "" 197 | case .PXL: return "" 198 | case .CBK: return "" 199 | case .DOGE: return "" 200 | case .AHT: return "" 201 | case .SNT: return "" 202 | case .RFR: return "" 203 | case .STPT: return "" 204 | case .THETA: return "" 205 | case .ZPX: return "" 206 | case .BAT: return "" 207 | case .ARK: return "" 208 | case .ADX: return "" 209 | case .AERGO: return "" 210 | case .FCT2: return "" 211 | case .NEO: return "" 212 | case .MARO: return "" 213 | case .STORJ: return "" 214 | case .JST: return "" 215 | case .SRN: return "" 216 | case .ELF: return "" 217 | case .MBL: return "" 218 | case .HUM: return "" 219 | case .LOOM: return "" 220 | case .OBSR: return "" 221 | case .ZIL: return "" 222 | case .KAVA: return "" 223 | case .ARDR: return "" 224 | case .KMD: return "" 225 | case .LAMB: return "" 226 | case .TSHP: return "" 227 | case .ATOM: return "" 228 | case .STMX: return "" 229 | case .LSK: return "" 230 | case .BCHA: return "" 231 | case .EDR: return "" 232 | case .QKC: return "" 233 | case .ORBS: return "" 234 | case .SC: return "" 235 | case .IGNIS: return "" 236 | case .SPND: return "" 237 | case .REP: return "" 238 | case .IQ: return "" 239 | case .WAVES: return "" 240 | case .KNC: return "" 241 | case .IOTA: return "" 242 | } 243 | } 244 | } 245 | -------------------------------------------------------------------------------- /Sources/SettingViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SettingViewController.swift 3 | // upbitBar 4 | // 5 | // Created by Fernando on 2021/03/08. 6 | // 7 | 8 | import Cocoa 9 | import Then 10 | import SnapKit 11 | import LaunchAtLogin 12 | 13 | 14 | class SettingViewController: NSViewController { 15 | 16 | private struct Consts { 17 | 18 | static let viewRect = NSRect(x: 0, y: 0, width: 480, height: 240) 19 | static let accessTokenFieldFrame = NSRect(x: 0, y: 0, width: 300, height: 30) 20 | static let refreshTokenFieldFrame = NSRect(x: 0, y: 40, width: 300, height: 30) 21 | } 22 | 23 | private var keys = UPbitKeys() 24 | 25 | private let accessTokenField = NSTextField().then { 26 | $0.frame = Consts.accessTokenFieldFrame 27 | } 28 | 29 | private let secretTokenField = NSTextField().then { 30 | $0.frame = Consts.refreshTokenFieldFrame 31 | } 32 | 33 | private let accessTokenLabel = NSTextField().then { 34 | $0.stringValue = Localized.accessToken 35 | $0.isBezeled = false 36 | $0.isEditable = false 37 | $0.backgroundColor = .clear 38 | $0.sizeToFit() 39 | } 40 | 41 | private let refreshTokenLabel = NSTextField().then { 42 | $0.stringValue = Localized.secretToken 43 | $0.isBezeled = false 44 | $0.isEditable = false 45 | $0.backgroundColor = .clear 46 | $0.sizeToFit() 47 | } 48 | 49 | private let refreshTimeLabel = NSTextField().then { 50 | $0.stringValue = Localized.refreshTime 51 | $0.isBezeled = false 52 | $0.isEditable = false 53 | $0.backgroundColor = .clear 54 | $0.sizeToFit() 55 | } 56 | 57 | private let refreshTimeCheckbox = NSPopUpButton().then { 58 | $0.addItem(withTitle: Localized.oneMinutes) 59 | $0.addItem(withTitle: Localized.fiveMinutes) 60 | $0.addItem(withTitle: Localized.tenMinutes) 61 | $0.addItem(withTitle: Localized.fifteenMinues) 62 | } 63 | 64 | private let quitButton = NSButton().then { 65 | $0.title = Localized.settingQuit 66 | $0.action = #selector(onQuitTap) 67 | $0.bezelStyle = .rounded 68 | } 69 | 70 | private let helpButton = NSButton().then { 71 | $0.title = Localized.settingHelpFeedback 72 | $0.action = #selector(onHelpTap) 73 | $0.bezelStyle = .rounded 74 | } 75 | 76 | private let saveButton = NSButton().then { 77 | $0.title = Localized.settingSave 78 | $0.action = #selector(onSaveTap) 79 | $0.bezelStyle = .rounded 80 | $0.keyEquivalent = "\r" 81 | $0.highlight(true) 82 | } 83 | 84 | private let startAtLoginButton = NSButton(checkboxWithTitle: Localized.autoLaunch, target: nil, action: #selector(setupLaunchToggle)).then { 85 | $0.state = LaunchAtLogin.isEnabled ? .on : .off 86 | } 87 | 88 | 89 | override func loadView() { 90 | let rect = Consts.viewRect 91 | view = NSView(frame: rect) 92 | view.wantsLayer = true 93 | view.layer?.backgroundColor = NSColor.windowBackgroundColor.cgColor 94 | 95 | 96 | view.addSubview(accessTokenLabel) 97 | view.addSubview(accessTokenField) 98 | view.addSubview(refreshTokenLabel) 99 | view.addSubview(secretTokenField) 100 | view.addSubview(refreshTimeLabel) 101 | view.addSubview(refreshTimeCheckbox) 102 | view.addSubview(startAtLoginButton) 103 | view.addSubview(quitButton) 104 | view.addSubview(helpButton) 105 | view.addSubview(saveButton) 106 | 107 | 108 | 109 | setupDefaultValues() 110 | setupConstraints() 111 | } 112 | 113 | func setupConstraints() { 114 | 115 | accessTokenLabel.snp.makeConstraints { 116 | $0.top.equalToSuperview().offset(50) 117 | $0.left.equalToSuperview().offset(10) 118 | } 119 | 120 | accessTokenField.snp.makeConstraints { 121 | $0.centerY.equalTo(accessTokenLabel.snp.centerY) 122 | $0.left.equalTo(accessTokenLabel.snp.right).offset(30) 123 | } 124 | 125 | refreshTokenLabel.snp.makeConstraints { 126 | $0.top.equalTo(accessTokenLabel.snp.bottom).offset(20) 127 | $0.left.equalToSuperview().offset(10) 128 | } 129 | 130 | secretTokenField.snp.makeConstraints { 131 | $0.centerY.equalTo(refreshTokenLabel.snp.centerY) 132 | $0.left.equalTo(refreshTokenLabel.snp.right).offset(30) 133 | } 134 | 135 | 136 | refreshTimeLabel.snp.makeConstraints { 137 | $0.top.equalTo(secretTokenField.snp.bottom).offset(20) 138 | $0.left.equalToSuperview().offset(10) 139 | } 140 | 141 | refreshTimeCheckbox.snp.makeConstraints { 142 | $0.centerY.equalTo(refreshTimeLabel.snp.centerY) 143 | $0.left.equalTo(refreshTimeLabel.snp.right).offset(30) 144 | } 145 | 146 | startAtLoginButton.snp.makeConstraints { 147 | $0.top.equalTo(refreshTimeCheckbox.snp.bottom).offset(20) 148 | $0.left.equalToSuperview().offset(10) 149 | } 150 | 151 | quitButton.snp.makeConstraints { 152 | $0.bottom.equalToSuperview().offset(-20) 153 | $0.left.equalToSuperview().offset(20) 154 | $0.size.equalTo(CGSize(width: 100, height: 20)) 155 | } 156 | 157 | helpButton.snp.makeConstraints { 158 | $0.bottom.equalToSuperview().offset(-20) 159 | $0.left.equalTo(quitButton.snp.right).offset(20) 160 | $0.size.equalTo(CGSize(width: 120, height: 20)) 161 | } 162 | 163 | saveButton.snp.makeConstraints { 164 | $0.bottom.equalToSuperview().offset(-20) 165 | $0.right.equalToSuperview().offset(-20) 166 | $0.size.equalTo(CGSize(width: 100, height: 20)) 167 | } 168 | } 169 | 170 | // MARK: Private functions 171 | 172 | func setupDefaultValues() { 173 | accessTokenField.stringValue = keys.accessToken 174 | secretTokenField.stringValue = keys.secretToken 175 | 176 | if keys.refershInterVal == -1 { 177 | keys.refershInterVal = 1 178 | } 179 | 180 | refreshTimeCheckbox.selectItem(at: keys.refershInterVal) 181 | startAtLoginButton.state = LaunchAtLogin.isEnabled ? .off : .on 182 | } 183 | 184 | @objc func setupLaunchToggle() { 185 | LaunchAtLogin.isEnabled.toggle() 186 | } 187 | 188 | @objc func onQuitTap() { 189 | NSApp.stopModal() 190 | } 191 | 192 | @objc func onHelpTap() { 193 | let url = URL(string: Constants.notionURL.rawValue)! 194 | NSWorkspace.shared.open(url) 195 | } 196 | 197 | @objc func onSaveTap() { 198 | print("onSaveTap") 199 | 200 | let accessToken = accessTokenField.stringValue 201 | let refreshToken = secretTokenField.stringValue 202 | 203 | if accessToken.isEmpty || accessToken.count < 40{ 204 | 205 | let alert = NSAlert() 206 | alert.alertStyle = .warning 207 | alert.messageText = Localized.settingAlertTitle 208 | alert.informativeText = Localized.settingAlertAccessTokenInfoText 209 | alert.addButton(withTitle: Localized.ok) 210 | if alert.runModal() == .alertFirstButtonReturn { 211 | return 212 | } 213 | } else if refreshToken.isEmpty || refreshToken.count < 40 { 214 | 215 | let alert = NSAlert() 216 | alert.messageText = Localized.settingAlertTitle 217 | alert.informativeText = Localized.settingAlertRefreshTokenInfoText 218 | alert.addButton(withTitle: Localized.ok) 219 | if alert.runModal() == .alertFirstButtonReturn { 220 | return 221 | } 222 | } 223 | 224 | keys.accessToken = accessToken 225 | keys.secretToken = refreshToken 226 | keys.refershInterVal = refreshTimeCheckbox.indexOfSelectedItem 227 | 228 | NSApp.stopModal() 229 | NotificationCenter.default.post(name: .neededRefresh, object: nil) 230 | 231 | } 232 | 233 | } 234 | -------------------------------------------------------------------------------- /Sources/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // upbitBar 4 | // 5 | // Created by Fernando on 2021/03/07. 6 | // 7 | 8 | import Cocoa 9 | import Then 10 | 11 | @main 12 | class AppDelegate: NSObject, NSApplicationDelegate { 13 | 14 | 15 | private struct Consts { 16 | static let cryptoTags = 99 17 | } 18 | 19 | private var statusItem: NSStatusItem? 20 | private var refreshTimer: Timer? 21 | private var keys = UPbitKeys() 22 | 23 | private let menu = NSMenu().then { 24 | $0.title = "" 25 | } 26 | 27 | private let refreshMenuItem = NSMenuItem().then { 28 | $0.title = Localized.refresh 29 | $0.action = #selector(onRefreshTap) 30 | $0.tag = 1 31 | $0.keyEquivalent = "r" 32 | } 33 | 34 | private let settingMenuItem = NSMenuItem().then { 35 | $0.title = Localized.setting 36 | $0.action = #selector(onSettingTap) 37 | $0.tag = 2 38 | $0.keyEquivalent = "s" 39 | } 40 | 41 | private let quitMenuItem = NSMenuItem().then { 42 | $0.title = Localized.quit 43 | $0.action = #selector(onQuitTap) 44 | $0.tag = 3 45 | $0.keyEquivalent = "q" 46 | } 47 | 48 | private var settingWindow: NSWindow! 49 | 50 | func applicationDidFinishLaunching(_ aNotification: Notification) { 51 | // Insert code here to initialize your application 52 | NotificationCenter.default.addObserver(self, selector: #selector(onDidNeedTokenSetting(_:)), name: .neededTokenSetting, object: nil) 53 | NotificationCenter.default.addObserver(self, selector: #selector(onDidNeedRefresh(_:)), name: .neededRefresh, object: nil) 54 | 55 | setupUI() 56 | setupSettingWindow() 57 | getAllBalances() 58 | setupRefreshTimer() 59 | } 60 | 61 | func applicationWillTerminate(_ aNotification: Notification) { 62 | // Insert code here to tear down your application 63 | } 64 | 65 | func setupUI() { 66 | 67 | menu.addItem(.separator()) 68 | menu.addItem(refreshMenuItem) 69 | menu.addItem(settingMenuItem) 70 | menu.addItem(quitMenuItem) 71 | 72 | statusItem = NSStatusBar.system.statusItem(withLength: NSStatusItem.variableLength) 73 | statusItem?.menu = menu 74 | 75 | self.statusItem?.button?.title = "Loading ... " 76 | 77 | } 78 | 79 | private func setupSettingWindow() { 80 | let windowSize = NSSize(width: 480, height: 240) 81 | let screenSize = NSScreen.main?.frame.size ?? .zero 82 | let rect = NSMakeRect(screenSize.width/2 - windowSize.width/2, screenSize.height/2 - windowSize.height/2, windowSize.width, windowSize.height) 83 | settingWindow = NSWindow(contentRect: rect, styleMask: [.miniaturizable, .closable, .titled], backing: .buffered, defer: false) 84 | settingWindow.title = Localized.settingTitle 85 | settingWindow.contentViewController = SettingViewController() 86 | settingWindow.delegate = self 87 | } 88 | 89 | @objc func onDidNeedTokenSetting(_ notification: Notification) { 90 | self.showSettingAlert() 91 | } 92 | 93 | @objc func onDidNeedRefresh(_ notification: Notification) { 94 | self.refresh() 95 | } 96 | 97 | @objc func onRefreshTap() { 98 | self.refresh() 99 | } 100 | 101 | @objc func onSettingTap() { 102 | self.showSettingAlert() 103 | } 104 | 105 | @objc func onQuitTap() { 106 | NSApplication.shared.terminate(self) 107 | } 108 | 109 | @objc func onMenuItemTap() { 110 | //NSApplication.shared.terminate(self) 111 | print("menu") 112 | } 113 | 114 | // MARK: Private functions 115 | 116 | private func refresh() { 117 | invalidateRefreshTimer() 118 | removeAllItems() 119 | getAllBalances() 120 | setupRefreshTimer() 121 | } 122 | 123 | private func setupRefreshTimer() { 124 | 125 | let refreshInterval = RefreshInterval(rawValue: keys.refershInterVal) 126 | let timeInterval = refreshInterval?.minutes ?? 5 127 | 128 | refreshTimer = Timer.scheduledTimer(withTimeInterval: TimeInterval( timeInterval * 60), 129 | repeats: true, 130 | block: { [weak self] _ in 131 | guard let self = self else { return } 132 | self.refresh() 133 | }) 134 | } 135 | 136 | private func invalidateRefreshTimer() { 137 | refreshTimer?.invalidate() 138 | } 139 | 140 | private func showSettingAlert() { 141 | NSApp.runModal(for: settingWindow) 142 | NSApp.activate(ignoringOtherApps: true) 143 | settingWindow.orderOut(self) 144 | } 145 | 146 | private func removeAllItems() { 147 | _ = menu.items.map { 148 | if $0.tag == Consts.cryptoTags { 149 | self.menu.removeItem($0) 150 | } 151 | } 152 | } 153 | 154 | private func getAllBalances() { 155 | guard let balances = UpbitServices.shared.getBalances(), 156 | let allMarket = UpbitServices.shared.getAllMarket() else { return } 157 | 158 | let availableMarkets = allMarket.compactMap{ $0.market } 159 | let currency: [String] = balances 160 | .map { "\($0.unitCurrency)-\($0.currency)" } 161 | .filter{ market -> Bool in availableMarkets.filter{ $0 == market }.first != nil } 162 | 163 | var myCurrency: [String: Market] { 164 | var tempDict: [String: Market] = [:] 165 | for currencyItem in currency { 166 | tempDict[currencyItem] = allMarket.filter{ $0.market == currencyItem }.first 167 | } 168 | return tempDict 169 | } 170 | 171 | let markets = currency.joined(separator: ",") 172 | guard let tickers = UpbitServices.shared.getTicker(markets: markets) else { return } 173 | 174 | var totalBalances: [Double] = [] 175 | var avgTotalBalances: [Double] = [] 176 | 177 | for ticker in tickers { 178 | for balance in balances { 179 | let currentMarket = "\(balance.unitCurrency)-\(balance.currency)" 180 | if ticker.market == currentMarket { 181 | 182 | let totalAsset = Double(balance.balance) ?? 0 183 | let totalPrice = Double(ticker.tradePrice) * totalAsset 184 | let buyPrice = Double(balance.avgBuyPrice)! * totalAsset 185 | let percent = (Double(ticker.tradePrice) / Double(balance.avgBuyPrice)!-1.0) * 100 186 | 187 | var emoji = "-" 188 | var attributes = Attributes.cryptoNormalAttributes 189 | 190 | if totalPrice < buyPrice { 191 | emoji = "📉" 192 | attributes = Attributes.cryptoBlueAttributes 193 | } else if buyPrice < totalPrice { 194 | emoji = "📈" 195 | attributes = Attributes.cryptoRedAttributes 196 | } 197 | 198 | avgTotalBalances.append(buyPrice) 199 | totalBalances.append(totalPrice) 200 | 201 | let totalString = self.convertCurrency(prefix:"", money: round(totalPrice)) 202 | 203 | let currentCurrency = myCurrency[currentMarket] 204 | let currencyName = currentCurrency?.koreanName ?? currentCurrency?.englishName ?? "" 205 | 206 | let title: String = "\(emoji) \(currencyName)(\(balance.currency)) - \(totalString) (\(percent.rounded())%)" 207 | 208 | let menuItem = NSMenuItem().then { 209 | $0.isEnabled = true 210 | $0.tag = Consts.cryptoTags 211 | $0.action = #selector(onMenuItemTap) 212 | $0.attributedTitle = NSAttributedString(string: title, attributes: attributes) 213 | } 214 | 215 | self.menu.insertItem(menuItem, at: .zero) 216 | } 217 | } 218 | } 219 | 220 | let total = totalBalances.map { round($0) }.reduce(0, +) 221 | let avg = avgTotalBalances.map { round($0) }.reduce(0, +) 222 | var title = "" 223 | var totalAttributes = Attributes.cryptoNormalAttributes 224 | 225 | if avg < total { 226 | title = self.convertCurrency(prefix: "📈", money: total) 227 | totalAttributes = Attributes.cryptoRedAttributes 228 | } else if total < avg { 229 | title = self.convertCurrency(prefix: "📉", money: total) 230 | totalAttributes = Attributes.cryptoBlueAttributes 231 | } 232 | 233 | self.statusItem?.button?.attributedTitle = NSAttributedString(string: title, attributes: totalAttributes) 234 | } 235 | 236 | func convertCurrency(prefix: String, money: Double) -> String { 237 | 238 | let number = NSNumber(value: money) 239 | let numberFormatter = NumberFormatter() 240 | numberFormatter.numberStyle = .decimal 241 | 242 | let decimalString = numberFormatter.string(from: number)! 243 | 244 | return prefix.isEmpty ? "₩\(decimalString)" : "\(prefix) ₩\(decimalString)" 245 | } 246 | 247 | } 248 | 249 | 250 | 251 | extension AppDelegate: NSWindowDelegate { 252 | func windowWillClose(_ notification: Notification) { 253 | NSApp.stopModal() 254 | } 255 | } 256 | -------------------------------------------------------------------------------- /Supporting Files/ko.lproj/Main.strings: -------------------------------------------------------------------------------- 1 | 2 | /* Class = "NSMenuItem"; title = "Customize Toolbar…"; ObjectID = "1UK-8n-QPP"; */ 3 | "1UK-8n-QPP.title" = "Customize Toolbar…"; 4 | 5 | /* Class = "NSMenuItem"; title = "upbitBar"; ObjectID = "1Xt-HY-uBw"; */ 6 | "1Xt-HY-uBw.title" = "upbitBar"; 7 | 8 | /* Class = "NSMenu"; title = "Find"; ObjectID = "1b7-l0-nxx"; */ 9 | "1b7-l0-nxx.title" = "Find"; 10 | 11 | /* Class = "NSMenuItem"; title = "Lower"; ObjectID = "1tx-W0-xDw"; */ 12 | "1tx-W0-xDw.title" = "Lower"; 13 | 14 | /* Class = "NSMenuItem"; title = "Raise"; ObjectID = "2h7-ER-AoG"; */ 15 | "2h7-ER-AoG.title" = "Raise"; 16 | 17 | /* Class = "NSMenuItem"; title = "Transformations"; ObjectID = "2oI-Rn-ZJC"; */ 18 | "2oI-Rn-ZJC.title" = "Transformations"; 19 | 20 | /* Class = "NSMenu"; title = "Spelling"; ObjectID = "3IN-sU-3Bg"; */ 21 | "3IN-sU-3Bg.title" = "Spelling"; 22 | 23 | /* Class = "NSMenuItem"; title = "Use Default"; ObjectID = "3Om-Ey-2VK"; */ 24 | "3Om-Ey-2VK.title" = "Use Default"; 25 | 26 | /* Class = "NSMenu"; title = "Speech"; ObjectID = "3rS-ZA-NoH"; */ 27 | "3rS-ZA-NoH.title" = "Speech"; 28 | 29 | /* Class = "NSMenuItem"; title = "Tighten"; ObjectID = "46P-cB-AYj"; */ 30 | "46P-cB-AYj.title" = "Tighten"; 31 | 32 | /* Class = "NSMenuItem"; title = "Find"; ObjectID = "4EN-yA-p0u"; */ 33 | "4EN-yA-p0u.title" = "Find"; 34 | 35 | /* Class = "NSMenuItem"; title = "Enter Full Screen"; ObjectID = "4J7-dP-txa"; */ 36 | "4J7-dP-txa.title" = "Enter Full Screen"; 37 | 38 | /* Class = "NSMenuItem"; title = "Quit upbitBar"; ObjectID = "4sb-4s-VLi"; */ 39 | "4sb-4s-VLi.title" = "Quit upbitBar"; 40 | 41 | /* Class = "NSMenuItem"; title = "Edit"; ObjectID = "5QF-Oa-p0T"; */ 42 | "5QF-Oa-p0T.title" = "Edit"; 43 | 44 | /* Class = "NSMenuItem"; title = "Copy Style"; ObjectID = "5Vv-lz-BsD"; */ 45 | "5Vv-lz-BsD.title" = "Copy Style"; 46 | 47 | /* Class = "NSMenuItem"; title = "About upbitBar"; ObjectID = "5kV-Vb-QxS"; */ 48 | "5kV-Vb-QxS.title" = "About upbitBar"; 49 | 50 | /* Class = "NSMenuItem"; title = "Redo"; ObjectID = "6dh-zS-Vam"; */ 51 | "6dh-zS-Vam.title" = "Redo"; 52 | 53 | /* Class = "NSMenuItem"; title = "Correct Spelling Automatically"; ObjectID = "78Y-hA-62v"; */ 54 | "78Y-hA-62v.title" = "Correct Spelling Automatically"; 55 | 56 | /* Class = "NSMenu"; title = "Writing Direction"; ObjectID = "8mr-sm-Yjd"; */ 57 | "8mr-sm-Yjd.title" = "Writing Direction"; 58 | 59 | /* Class = "NSMenuItem"; title = "Substitutions"; ObjectID = "9ic-FL-obx"; */ 60 | "9ic-FL-obx.title" = "Substitutions"; 61 | 62 | /* Class = "NSMenuItem"; title = "Smart Copy/Paste"; ObjectID = "9yt-4B-nSM"; */ 63 | "9yt-4B-nSM.title" = "Smart Copy/Paste"; 64 | 65 | /* Class = "NSMenu"; title = "Main Menu"; ObjectID = "AYu-sK-qS6"; */ 66 | "AYu-sK-qS6.title" = "Main Menu"; 67 | 68 | /* Class = "NSMenuItem"; title = "Preferences…"; ObjectID = "BOF-NM-1cW"; */ 69 | "BOF-NM-1cW.title" = "Preferences…"; 70 | 71 | /* Class = "NSMenuItem"; title = "\tLeft to Right"; ObjectID = "BgM-ve-c93"; */ 72 | "BgM-ve-c93.title" = "\tLeft to Right"; 73 | 74 | /* Class = "NSMenuItem"; title = "Save As…"; ObjectID = "Bw7-FT-i3A"; */ 75 | "Bw7-FT-i3A.title" = "Save As…"; 76 | 77 | /* Class = "NSMenuItem"; title = "Close"; ObjectID = "DVo-aG-piG"; */ 78 | "DVo-aG-piG.title" = "Close"; 79 | 80 | /* Class = "NSMenuItem"; title = "Spelling and Grammar"; ObjectID = "Dv1-io-Yv7"; */ 81 | "Dv1-io-Yv7.title" = "Spelling and Grammar"; 82 | 83 | /* Class = "NSMenu"; title = "Help"; ObjectID = "F2S-fz-NVQ"; */ 84 | "F2S-fz-NVQ.title" = "Help"; 85 | 86 | /* Class = "NSMenuItem"; title = "upbitBar Help"; ObjectID = "FKE-Sm-Kum"; */ 87 | "FKE-Sm-Kum.title" = "upbitBar Help"; 88 | 89 | /* Class = "NSMenuItem"; title = "Text"; ObjectID = "Fal-I4-PZk"; */ 90 | "Fal-I4-PZk.title" = "Text"; 91 | 92 | /* Class = "NSMenu"; title = "Substitutions"; ObjectID = "FeM-D8-WVr"; */ 93 | "FeM-D8-WVr.title" = "Substitutions"; 94 | 95 | /* Class = "NSMenuItem"; title = "Bold"; ObjectID = "GB9-OM-e27"; */ 96 | "GB9-OM-e27.title" = "Bold"; 97 | 98 | /* Class = "NSMenu"; title = "Format"; ObjectID = "GEO-Iw-cKr"; */ 99 | "GEO-Iw-cKr.title" = "Format"; 100 | 101 | /* Class = "NSMenuItem"; title = "Use Default"; ObjectID = "GUa-eO-cwY"; */ 102 | "GUa-eO-cwY.title" = "Use Default"; 103 | 104 | /* Class = "NSMenuItem"; title = "Font"; ObjectID = "Gi5-1S-RQB"; */ 105 | "Gi5-1S-RQB.title" = "Font"; 106 | 107 | /* Class = "NSMenuItem"; title = "Writing Direction"; ObjectID = "H1b-Si-o9J"; */ 108 | "H1b-Si-o9J.title" = "Writing Direction"; 109 | 110 | /* Class = "NSMenuItem"; title = "View"; ObjectID = "H8h-7b-M4v"; */ 111 | "H8h-7b-M4v.title" = "View"; 112 | 113 | /* Class = "NSMenuItem"; title = "Text Replacement"; ObjectID = "HFQ-gK-NFA"; */ 114 | "HFQ-gK-NFA.title" = "Text Replacement"; 115 | 116 | /* Class = "NSMenuItem"; title = "Show Spelling and Grammar"; ObjectID = "HFo-cy-zxI"; */ 117 | "HFo-cy-zxI.title" = "Show Spelling and Grammar"; 118 | 119 | /* Class = "NSMenu"; title = "View"; ObjectID = "HyV-fh-RgO"; */ 120 | "HyV-fh-RgO.title" = "View"; 121 | 122 | /* Class = "NSMenuItem"; title = "Subscript"; ObjectID = "I0S-gh-46l"; */ 123 | "I0S-gh-46l.title" = "Subscript"; 124 | 125 | /* Class = "NSMenuItem"; title = "Open…"; ObjectID = "IAo-SY-fd9"; */ 126 | "IAo-SY-fd9.title" = "Open…"; 127 | 128 | /* Class = "NSMenuItem"; title = "Justify"; ObjectID = "J5U-5w-g23"; */ 129 | "J5U-5w-g23.title" = "Justify"; 130 | 131 | /* Class = "NSMenuItem"; title = "Use None"; ObjectID = "J7y-lM-qPV"; */ 132 | "J7y-lM-qPV.title" = "Use None"; 133 | 134 | /* Class = "NSMenuItem"; title = "Revert to Saved"; ObjectID = "KaW-ft-85H"; */ 135 | "KaW-ft-85H.title" = "Revert to Saved"; 136 | 137 | /* Class = "NSMenuItem"; title = "Show All"; ObjectID = "Kd2-mp-pUS"; */ 138 | "Kd2-mp-pUS.title" = "Show All"; 139 | 140 | /* Class = "NSMenuItem"; title = "Bring All to Front"; ObjectID = "LE2-aR-0XJ"; */ 141 | "LE2-aR-0XJ.title" = "Bring All to Front"; 142 | 143 | /* Class = "NSMenuItem"; title = "Paste Ruler"; ObjectID = "LVM-kO-fVI"; */ 144 | "LVM-kO-fVI.title" = "Paste Ruler"; 145 | 146 | /* Class = "NSMenuItem"; title = "\tLeft to Right"; ObjectID = "Lbh-J2-qVU"; */ 147 | "Lbh-J2-qVU.title" = "\tLeft to Right"; 148 | 149 | /* Class = "NSMenuItem"; title = "Copy Ruler"; ObjectID = "MkV-Pr-PK5"; */ 150 | "MkV-Pr-PK5.title" = "Copy Ruler"; 151 | 152 | /* Class = "NSMenuItem"; title = "Services"; ObjectID = "NMo-om-nkz"; */ 153 | "NMo-om-nkz.title" = "Services"; 154 | 155 | /* Class = "NSMenuItem"; title = "\tDefault"; ObjectID = "Nop-cj-93Q"; */ 156 | "Nop-cj-93Q.title" = "\tDefault"; 157 | 158 | /* Class = "NSMenuItem"; title = "Minimize"; ObjectID = "OY7-WF-poV"; */ 159 | "OY7-WF-poV.title" = "Minimize"; 160 | 161 | /* Class = "NSMenuItem"; title = "Baseline"; ObjectID = "OaQ-X3-Vso"; */ 162 | "OaQ-X3-Vso.title" = "Baseline"; 163 | 164 | /* Class = "NSMenuItem"; title = "Hide upbitBar"; ObjectID = "Olw-nP-bQN"; */ 165 | "Olw-nP-bQN.title" = "Hide upbitBar"; 166 | 167 | /* Class = "NSMenuItem"; title = "Find Previous"; ObjectID = "OwM-mh-QMV"; */ 168 | "OwM-mh-QMV.title" = "Find Previous"; 169 | 170 | /* Class = "NSMenuItem"; title = "Stop Speaking"; ObjectID = "Oyz-dy-DGm"; */ 171 | "Oyz-dy-DGm.title" = "Stop Speaking"; 172 | 173 | /* Class = "NSMenuItem"; title = "Bigger"; ObjectID = "Ptp-SP-VEL"; */ 174 | "Ptp-SP-VEL.title" = "Bigger"; 175 | 176 | /* Class = "NSMenuItem"; title = "Show Fonts"; ObjectID = "Q5e-8K-NDq"; */ 177 | "Q5e-8K-NDq.title" = "Show Fonts"; 178 | 179 | /* Class = "NSMenuItem"; title = "Zoom"; ObjectID = "R4o-n2-Eq4"; */ 180 | "R4o-n2-Eq4.title" = "Zoom"; 181 | 182 | /* Class = "NSMenuItem"; title = "\tRight to Left"; ObjectID = "RB4-Sm-HuC"; */ 183 | "RB4-Sm-HuC.title" = "\tRight to Left"; 184 | 185 | /* Class = "NSMenuItem"; title = "Superscript"; ObjectID = "Rqc-34-cIF"; */ 186 | "Rqc-34-cIF.title" = "Superscript"; 187 | 188 | /* Class = "NSMenuItem"; title = "Select All"; ObjectID = "Ruw-6m-B2m"; */ 189 | "Ruw-6m-B2m.title" = "Select All"; 190 | 191 | /* Class = "NSMenuItem"; title = "Jump to Selection"; ObjectID = "S0p-oC-mLd"; */ 192 | "S0p-oC-mLd.title" = "Jump to Selection"; 193 | 194 | /* Class = "NSMenu"; title = "Window"; ObjectID = "Td7-aD-5lo"; */ 195 | "Td7-aD-5lo.title" = "Window"; 196 | 197 | /* Class = "NSMenuItem"; title = "Capitalize"; ObjectID = "UEZ-Bs-lqG"; */ 198 | "UEZ-Bs-lqG.title" = "Capitalize"; 199 | 200 | /* Class = "NSMenuItem"; title = "Center"; ObjectID = "VIY-Ag-zcb"; */ 201 | "VIY-Ag-zcb.title" = "Center"; 202 | 203 | /* Class = "NSMenuItem"; title = "Hide Others"; ObjectID = "Vdr-fp-XzO"; */ 204 | "Vdr-fp-XzO.title" = "Hide Others"; 205 | 206 | /* Class = "NSMenuItem"; title = "Italic"; ObjectID = "Vjx-xi-njq"; */ 207 | "Vjx-xi-njq.title" = "Italic"; 208 | 209 | /* Class = "NSMenu"; title = "Edit"; ObjectID = "W48-6f-4Dl"; */ 210 | "W48-6f-4Dl.title" = "Edit"; 211 | 212 | /* Class = "NSMenuItem"; title = "Underline"; ObjectID = "WRG-CD-K1S"; */ 213 | "WRG-CD-K1S.title" = "Underline"; 214 | 215 | /* Class = "NSMenuItem"; title = "New"; ObjectID = "Was-JA-tGl"; */ 216 | "Was-JA-tGl.title" = "New"; 217 | 218 | /* Class = "NSMenuItem"; title = "Paste and Match Style"; ObjectID = "WeT-3V-zwk"; */ 219 | "WeT-3V-zwk.title" = "Paste and Match Style"; 220 | 221 | /* Class = "NSMenuItem"; title = "Find…"; ObjectID = "Xz5-n4-O0W"; */ 222 | "Xz5-n4-O0W.title" = "Find…"; 223 | 224 | /* Class = "NSMenuItem"; title = "Find and Replace…"; ObjectID = "YEy-JH-Tfz"; */ 225 | "YEy-JH-Tfz.title" = "Find and Replace…"; 226 | 227 | /* Class = "NSMenuItem"; title = "\tDefault"; ObjectID = "YGs-j5-SAR"; */ 228 | "YGs-j5-SAR.title" = "\tDefault"; 229 | 230 | /* Class = "NSMenuItem"; title = "Start Speaking"; ObjectID = "Ynk-f8-cLZ"; */ 231 | "Ynk-f8-cLZ.title" = "Start Speaking"; 232 | 233 | /* Class = "NSMenuItem"; title = "Align Left"; ObjectID = "ZM1-6Q-yy1"; */ 234 | "ZM1-6Q-yy1.title" = "Align Left"; 235 | 236 | /* Class = "NSMenuItem"; title = "Paragraph"; ObjectID = "ZvO-Gk-QUH"; */ 237 | "ZvO-Gk-QUH.title" = "Paragraph"; 238 | 239 | /* Class = "NSMenuItem"; title = "Print…"; ObjectID = "aTl-1u-JFS"; */ 240 | "aTl-1u-JFS.title" = "Print…"; 241 | 242 | /* Class = "NSMenuItem"; title = "Window"; ObjectID = "aUF-d1-5bR"; */ 243 | "aUF-d1-5bR.title" = "Window"; 244 | 245 | /* Class = "NSMenu"; title = "Font"; ObjectID = "aXa-aM-Jaq"; */ 246 | "aXa-aM-Jaq.title" = "Font"; 247 | 248 | /* Class = "NSMenuItem"; title = "Use Default"; ObjectID = "agt-UL-0e3"; */ 249 | "agt-UL-0e3.title" = "Use Default"; 250 | 251 | /* Class = "NSMenuItem"; title = "Show Colors"; ObjectID = "bgn-CT-cEk"; */ 252 | "bgn-CT-cEk.title" = "Show Colors"; 253 | 254 | /* Class = "NSMenu"; title = "File"; ObjectID = "bib-Uj-vzu"; */ 255 | "bib-Uj-vzu.title" = "File"; 256 | 257 | /* Class = "NSMenuItem"; title = "Use Selection for Find"; ObjectID = "buJ-ug-pKt"; */ 258 | "buJ-ug-pKt.title" = "Use Selection for Find"; 259 | 260 | /* Class = "NSMenu"; title = "Transformations"; ObjectID = "c8a-y6-VQd"; */ 261 | "c8a-y6-VQd.title" = "Transformations"; 262 | 263 | /* Class = "NSMenuItem"; title = "Use None"; ObjectID = "cDB-IK-hbR"; */ 264 | "cDB-IK-hbR.title" = "Use None"; 265 | 266 | /* Class = "NSMenuItem"; title = "Selection"; ObjectID = "cqv-fj-IhA"; */ 267 | "cqv-fj-IhA.title" = "Selection"; 268 | 269 | /* Class = "NSMenuItem"; title = "Smart Links"; ObjectID = "cwL-P1-jid"; */ 270 | "cwL-P1-jid.title" = "Smart Links"; 271 | 272 | /* Class = "NSMenuItem"; title = "Make Lower Case"; ObjectID = "d9M-CD-aMd"; */ 273 | "d9M-CD-aMd.title" = "Make Lower Case"; 274 | 275 | /* Class = "NSMenu"; title = "Text"; ObjectID = "d9c-me-L2H"; */ 276 | "d9c-me-L2H.title" = "Text"; 277 | 278 | /* Class = "NSMenuItem"; title = "File"; ObjectID = "dMs-cI-mzQ"; */ 279 | "dMs-cI-mzQ.title" = "File"; 280 | 281 | /* Class = "NSMenuItem"; title = "Undo"; ObjectID = "dRJ-4n-Yzg"; */ 282 | "dRJ-4n-Yzg.title" = "Undo"; 283 | 284 | /* Class = "NSMenuItem"; title = "Paste"; ObjectID = "gVA-U4-sdL"; */ 285 | "gVA-U4-sdL.title" = "Paste"; 286 | 287 | /* Class = "NSMenuItem"; title = "Smart Quotes"; ObjectID = "hQb-2v-fYv"; */ 288 | "hQb-2v-fYv.title" = "Smart Quotes"; 289 | 290 | /* Class = "NSMenuItem"; title = "Check Document Now"; ObjectID = "hz2-CU-CR7"; */ 291 | "hz2-CU-CR7.title" = "Check Document Now"; 292 | 293 | /* Class = "NSMenu"; title = "Services"; ObjectID = "hz9-B4-Xy5"; */ 294 | "hz9-B4-Xy5.title" = "Services"; 295 | 296 | /* Class = "NSMenuItem"; title = "Smaller"; ObjectID = "i1d-Er-qST"; */ 297 | "i1d-Er-qST.title" = "Smaller"; 298 | 299 | /* Class = "NSMenu"; title = "Baseline"; ObjectID = "ijk-EB-dga"; */ 300 | "ijk-EB-dga.title" = "Baseline"; 301 | 302 | /* Class = "NSMenuItem"; title = "Kern"; ObjectID = "jBQ-r6-VK2"; */ 303 | "jBQ-r6-VK2.title" = "Kern"; 304 | 305 | /* Class = "NSMenuItem"; title = "\tRight to Left"; ObjectID = "jFq-tB-4Kx"; */ 306 | "jFq-tB-4Kx.title" = "\tRight to Left"; 307 | 308 | /* Class = "NSMenuItem"; title = "Format"; ObjectID = "jxT-CU-nIS"; */ 309 | "jxT-CU-nIS.title" = "Format"; 310 | 311 | /* Class = "NSMenuItem"; title = "Show Sidebar"; ObjectID = "kIP-vf-haE"; */ 312 | "kIP-vf-haE.title" = "Show Sidebar"; 313 | 314 | /* Class = "NSMenuItem"; title = "Check Grammar With Spelling"; ObjectID = "mK6-2p-4JG"; */ 315 | "mK6-2p-4JG.title" = "Check Grammar With Spelling"; 316 | 317 | /* Class = "NSMenuItem"; title = "Ligatures"; ObjectID = "o6e-r0-MWq"; */ 318 | "o6e-r0-MWq.title" = "Ligatures"; 319 | 320 | /* Class = "NSMenu"; title = "Open Recent"; ObjectID = "oas-Oc-fiZ"; */ 321 | "oas-Oc-fiZ.title" = "Open Recent"; 322 | 323 | /* Class = "NSMenuItem"; title = "Loosen"; ObjectID = "ogc-rX-tC1"; */ 324 | "ogc-rX-tC1.title" = "Loosen"; 325 | 326 | /* Class = "NSMenuItem"; title = "Delete"; ObjectID = "pa3-QI-u2k"; */ 327 | "pa3-QI-u2k.title" = "Delete"; 328 | 329 | /* Class = "NSMenuItem"; title = "Save…"; ObjectID = "pxx-59-PXV"; */ 330 | "pxx-59-PXV.title" = "Save…"; 331 | 332 | /* Class = "NSMenuItem"; title = "Find Next"; ObjectID = "q09-fT-Sye"; */ 333 | "q09-fT-Sye.title" = "Find Next"; 334 | 335 | /* Class = "NSMenuItem"; title = "Page Setup…"; ObjectID = "qIS-W8-SiK"; */ 336 | "qIS-W8-SiK.title" = "Page Setup…"; 337 | 338 | /* Class = "NSMenuItem"; title = "Check Spelling While Typing"; ObjectID = "rbD-Rh-wIN"; */ 339 | "rbD-Rh-wIN.title" = "Check Spelling While Typing"; 340 | 341 | /* Class = "NSMenuItem"; title = "Smart Dashes"; ObjectID = "rgM-f4-ycn"; */ 342 | "rgM-f4-ycn.title" = "Smart Dashes"; 343 | 344 | /* Class = "NSMenuItem"; title = "Show Toolbar"; ObjectID = "snW-S8-Cw5"; */ 345 | "snW-S8-Cw5.title" = "Show Toolbar"; 346 | 347 | /* Class = "NSMenuItem"; title = "Data Detectors"; ObjectID = "tRr-pd-1PS"; */ 348 | "tRr-pd-1PS.title" = "Data Detectors"; 349 | 350 | /* Class = "NSMenuItem"; title = "Open Recent"; ObjectID = "tXI-mr-wws"; */ 351 | "tXI-mr-wws.title" = "Open Recent"; 352 | 353 | /* Class = "NSMenu"; title = "Kern"; ObjectID = "tlD-Oa-oAM"; */ 354 | "tlD-Oa-oAM.title" = "Kern"; 355 | 356 | /* Class = "NSMenu"; title = "upbitBar"; ObjectID = "uQy-DD-JDr"; */ 357 | "uQy-DD-JDr.title" = "upbitBar"; 358 | 359 | /* Class = "NSMenuItem"; title = "Cut"; ObjectID = "uRl-iY-unG"; */ 360 | "uRl-iY-unG.title" = "Cut"; 361 | 362 | /* Class = "NSMenuItem"; title = "Paste Style"; ObjectID = "vKC-jM-MkH"; */ 363 | "vKC-jM-MkH.title" = "Paste Style"; 364 | 365 | /* Class = "NSMenuItem"; title = "Show Ruler"; ObjectID = "vLm-3I-IUL"; */ 366 | "vLm-3I-IUL.title" = "Show Ruler"; 367 | 368 | /* Class = "NSMenuItem"; title = "Clear Menu"; ObjectID = "vNY-rz-j42"; */ 369 | "vNY-rz-j42.title" = "Clear Menu"; 370 | 371 | /* Class = "NSMenuItem"; title = "Make Upper Case"; ObjectID = "vmV-6d-7jI"; */ 372 | "vmV-6d-7jI.title" = "Make Upper Case"; 373 | 374 | /* Class = "NSMenu"; title = "Ligatures"; ObjectID = "w0m-vy-SC9"; */ 375 | "w0m-vy-SC9.title" = "Ligatures"; 376 | 377 | /* Class = "NSMenuItem"; title = "Align Right"; ObjectID = "wb2-vD-lq4"; */ 378 | "wb2-vD-lq4.title" = "Align Right"; 379 | 380 | /* Class = "NSMenuItem"; title = "Help"; ObjectID = "wpr-3q-Mcd"; */ 381 | "wpr-3q-Mcd.title" = "Help"; 382 | 383 | /* Class = "NSMenuItem"; title = "Copy"; ObjectID = "x3v-GG-iWU"; */ 384 | "x3v-GG-iWU.title" = "Copy"; 385 | 386 | /* Class = "NSMenuItem"; title = "Use All"; ObjectID = "xQD-1f-W4t"; */ 387 | "xQD-1f-W4t.title" = "Use All"; 388 | 389 | /* Class = "NSMenuItem"; title = "Speech"; ObjectID = "xrE-MZ-jX0"; */ 390 | "xrE-MZ-jX0.title" = "Speech"; 391 | 392 | /* Class = "NSMenuItem"; title = "Show Substitutions"; ObjectID = "z6F-FW-3nz"; */ 393 | "z6F-FW-3nz.title" = "Show Substitutions"; 394 | -------------------------------------------------------------------------------- /upbitBar.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 52; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | A7BC7B8626032E0000B2A6DB /* Constants.swift in Sources */ = {isa = PBXBuildFile; fileRef = A7BC7B8526032E0000B2A6DB /* Constants.swift */; }; 11 | A7BC7B8A26032E3000B2A6DB /* Market.swift in Sources */ = {isa = PBXBuildFile; fileRef = A7BC7B8926032E3000B2A6DB /* Market.swift */; }; 12 | ED3BF34625F7C67A00F05BB5 /* Attributes.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED3BF34525F7C67A00F05BB5 /* Attributes.swift */; }; 13 | ED6E757E25F51FE2006387CA /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED6E757D25F51FE2006387CA /* AppDelegate.swift */; }; 14 | ED6E758225F51FE3006387CA /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = ED6E758125F51FE3006387CA /* Assets.xcassets */; }; 15 | ED6E758525F51FE3006387CA /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = ED6E758325F51FE3006387CA /* Main.storyboard */; }; 16 | ED6E759025F5204B006387CA /* Just in Frameworks */ = {isa = PBXBuildFile; productRef = ED6E758F25F5204B006387CA /* Just */; }; 17 | ED6E759425F5224B006387CA /* JWTComponents in Frameworks */ = {isa = PBXBuildFile; productRef = ED6E759325F5224B006387CA /* JWTComponents */; }; 18 | ED6E759925F522EC006387CA /* Then in Frameworks */ = {isa = PBXBuildFile; productRef = ED6E759825F522EC006387CA /* Then */; }; 19 | ED6E759D25F52C45006387CA /* CryptoAsset.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED6E759C25F52C45006387CA /* CryptoAsset.swift */; }; 20 | ED6E75A225F52DE1006387CA /* UpbitServices.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED6E75A125F52DE1006387CA /* UpbitServices.swift */; }; 21 | ED6E75A725F53056006387CA /* Logging in Frameworks */ = {isa = PBXBuildFile; productRef = ED6E75A625F53056006387CA /* Logging */; }; 22 | ED6E75AA25F5325A006387CA /* Ticker.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED6E75A925F5325A006387CA /* Ticker.swift */; }; 23 | ED6E75AD25F54617006387CA /* Cryptocurrency.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED6E75AC25F54617006387CA /* Cryptocurrency.swift */; }; 24 | ED6E75B125F54B0E006387CA /* LaunchAtLogin in Frameworks */ = {isa = PBXBuildFile; productRef = ED6E75B025F54B0E006387CA /* LaunchAtLogin */; }; 25 | ED6E75B425F54B6C006387CA /* UpbitAPI.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED6E75B325F54B6C006387CA /* UpbitAPI.swift */; }; 26 | ED6E765625F648E8006387CA /* SettingViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED6E765525F648E8006387CA /* SettingViewController.swift */; }; 27 | ED6E765A25F64BC5006387CA /* SnapKit in Frameworks */ = {isa = PBXBuildFile; productRef = ED6E765925F64BC5006387CA /* SnapKit */; }; 28 | ED6E772125F67802006387CA /* UserInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED6E772025F67802006387CA /* UserInfo.swift */; }; 29 | ED6E772A25F6836E006387CA /* Notifications.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED6E772925F6836E006387CA /* Notifications.swift */; }; 30 | ED6E772D25F689E0006387CA /* RefreshInterval.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED6E772C25F689E0006387CA /* RefreshInterval.swift */; }; 31 | ED6E773425F68E8C006387CA /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = ED6E773625F68E8C006387CA /* Localizable.strings */; }; 32 | ED6E774125F68F14006387CA /* Localized.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED6E774025F68F14006387CA /* Localized.swift */; }; 33 | /* End PBXBuildFile section */ 34 | 35 | /* Begin PBXFileReference section */ 36 | A7BC7B8526032E0000B2A6DB /* Constants.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Constants.swift; sourceTree = ""; }; 37 | A7BC7B8926032E3000B2A6DB /* Market.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Market.swift; sourceTree = ""; }; 38 | ED3BF34525F7C67A00F05BB5 /* Attributes.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Attributes.swift; sourceTree = ""; }; 39 | ED6E757A25F51FE2006387CA /* upbitBar.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = upbitBar.app; sourceTree = BUILT_PRODUCTS_DIR; }; 40 | ED6E757D25F51FE2006387CA /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 41 | ED6E758125F51FE3006387CA /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 42 | ED6E758425F51FE3006387CA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 43 | ED6E758625F51FE3006387CA /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 44 | ED6E758725F51FE3006387CA /* upbitBar.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = upbitBar.entitlements; sourceTree = ""; }; 45 | ED6E759C25F52C45006387CA /* CryptoAsset.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CryptoAsset.swift; sourceTree = ""; }; 46 | ED6E75A125F52DE1006387CA /* UpbitServices.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UpbitServices.swift; sourceTree = ""; }; 47 | ED6E75A925F5325A006387CA /* Ticker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Ticker.swift; sourceTree = ""; }; 48 | ED6E75AC25F54617006387CA /* Cryptocurrency.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Cryptocurrency.swift; sourceTree = ""; }; 49 | ED6E75B325F54B6C006387CA /* UpbitAPI.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UpbitAPI.swift; sourceTree = ""; }; 50 | ED6E765525F648E8006387CA /* SettingViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingViewController.swift; sourceTree = ""; }; 51 | ED6E772025F67802006387CA /* UserInfo.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserInfo.swift; sourceTree = ""; }; 52 | ED6E772925F6836E006387CA /* Notifications.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Notifications.swift; sourceTree = ""; }; 53 | ED6E772C25F689E0006387CA /* RefreshInterval.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RefreshInterval.swift; sourceTree = ""; }; 54 | ED6E773525F68E8C006387CA /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/Localizable.strings; sourceTree = ""; }; 55 | ED6E773825F68EAB006387CA /* ko */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ko; path = ko.lproj/Main.strings; sourceTree = ""; }; 56 | ED6E773925F68EAB006387CA /* ko */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ko; path = ko.lproj/Localizable.strings; sourceTree = ""; }; 57 | ED6E774025F68F14006387CA /* Localized.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Localized.swift; sourceTree = ""; }; 58 | /* End PBXFileReference section */ 59 | 60 | /* Begin PBXFrameworksBuildPhase section */ 61 | ED6E757725F51FE2006387CA /* Frameworks */ = { 62 | isa = PBXFrameworksBuildPhase; 63 | buildActionMask = 2147483647; 64 | files = ( 65 | ED6E759425F5224B006387CA /* JWTComponents in Frameworks */, 66 | ED6E759925F522EC006387CA /* Then in Frameworks */, 67 | ED6E75A725F53056006387CA /* Logging in Frameworks */, 68 | ED6E765A25F64BC5006387CA /* SnapKit in Frameworks */, 69 | ED6E75B125F54B0E006387CA /* LaunchAtLogin in Frameworks */, 70 | ED6E759025F5204B006387CA /* Just in Frameworks */, 71 | ); 72 | runOnlyForDeploymentPostprocessing = 0; 73 | }; 74 | /* End PBXFrameworksBuildPhase section */ 75 | 76 | /* Begin PBXGroup section */ 77 | A7BC7B8426032DF800B2A6DB /* Constants */ = { 78 | isa = PBXGroup; 79 | children = ( 80 | A7BC7B8526032E0000B2A6DB /* Constants.swift */, 81 | ); 82 | path = Constants; 83 | sourceTree = ""; 84 | }; 85 | ED6E757125F51FE2006387CA = { 86 | isa = PBXGroup; 87 | children = ( 88 | ED6E772F25F68E25006387CA /* Supporting Files */, 89 | ED6E757C25F51FE2006387CA /* Sources */, 90 | ED6E757B25F51FE2006387CA /* Products */, 91 | ); 92 | sourceTree = ""; 93 | }; 94 | ED6E757B25F51FE2006387CA /* Products */ = { 95 | isa = PBXGroup; 96 | children = ( 97 | ED6E757A25F51FE2006387CA /* upbitBar.app */, 98 | ); 99 | name = Products; 100 | sourceTree = ""; 101 | }; 102 | ED6E757C25F51FE2006387CA /* Sources */ = { 103 | isa = PBXGroup; 104 | children = ( 105 | A7BC7B8426032DF800B2A6DB /* Constants */, 106 | ED6E771A25F677D5006387CA /* Utils */, 107 | ED6E75A025F52DCF006387CA /* Networking */, 108 | ED6E759B25F52BD1006387CA /* Models */, 109 | ED6E757D25F51FE2006387CA /* AppDelegate.swift */, 110 | ED6E765525F648E8006387CA /* SettingViewController.swift */, 111 | ); 112 | path = Sources; 113 | sourceTree = ""; 114 | }; 115 | ED6E759B25F52BD1006387CA /* Models */ = { 116 | isa = PBXGroup; 117 | children = ( 118 | ED6E759C25F52C45006387CA /* CryptoAsset.swift */, 119 | ED6E75A925F5325A006387CA /* Ticker.swift */, 120 | ED6E75AC25F54617006387CA /* Cryptocurrency.swift */, 121 | ED6E772C25F689E0006387CA /* RefreshInterval.swift */, 122 | A7BC7B8926032E3000B2A6DB /* Market.swift */, 123 | ); 124 | path = Models; 125 | sourceTree = ""; 126 | }; 127 | ED6E75A025F52DCF006387CA /* Networking */ = { 128 | isa = PBXGroup; 129 | children = ( 130 | ED6E75A125F52DE1006387CA /* UpbitServices.swift */, 131 | ED6E75B325F54B6C006387CA /* UpbitAPI.swift */, 132 | ); 133 | path = Networking; 134 | sourceTree = ""; 135 | }; 136 | ED6E771A25F677D5006387CA /* Utils */ = { 137 | isa = PBXGroup; 138 | children = ( 139 | ED6E772025F67802006387CA /* UserInfo.swift */, 140 | ED6E772925F6836E006387CA /* Notifications.swift */, 141 | ED6E774025F68F14006387CA /* Localized.swift */, 142 | ED3BF34525F7C67A00F05BB5 /* Attributes.swift */, 143 | ); 144 | path = Utils; 145 | sourceTree = ""; 146 | }; 147 | ED6E772F25F68E25006387CA /* Supporting Files */ = { 148 | isa = PBXGroup; 149 | children = ( 150 | ED6E758125F51FE3006387CA /* Assets.xcassets */, 151 | ED6E758325F51FE3006387CA /* Main.storyboard */, 152 | ED6E758625F51FE3006387CA /* Info.plist */, 153 | ED6E758725F51FE3006387CA /* upbitBar.entitlements */, 154 | ED6E773625F68E8C006387CA /* Localizable.strings */, 155 | ); 156 | path = "Supporting Files"; 157 | sourceTree = ""; 158 | }; 159 | /* End PBXGroup section */ 160 | 161 | /* Begin PBXNativeTarget section */ 162 | ED6E757925F51FE2006387CA /* upbitBar */ = { 163 | isa = PBXNativeTarget; 164 | buildConfigurationList = ED6E758A25F51FE4006387CA /* Build configuration list for PBXNativeTarget "upbitBar" */; 165 | buildPhases = ( 166 | ED6E757625F51FE2006387CA /* Sources */, 167 | ED3BF34D25F7F2F500F05BB5 /* LaunchAtLogin */, 168 | ED6E757725F51FE2006387CA /* Frameworks */, 169 | ED6E757825F51FE2006387CA /* Resources */, 170 | ); 171 | buildRules = ( 172 | ); 173 | dependencies = ( 174 | ); 175 | name = upbitBar; 176 | packageProductDependencies = ( 177 | ED6E758F25F5204B006387CA /* Just */, 178 | ED6E759325F5224B006387CA /* JWTComponents */, 179 | ED6E759825F522EC006387CA /* Then */, 180 | ED6E75A625F53056006387CA /* Logging */, 181 | ED6E75B025F54B0E006387CA /* LaunchAtLogin */, 182 | ED6E765925F64BC5006387CA /* SnapKit */, 183 | ); 184 | productName = upbitBar; 185 | productReference = ED6E757A25F51FE2006387CA /* upbitBar.app */; 186 | productType = "com.apple.product-type.application"; 187 | }; 188 | /* End PBXNativeTarget section */ 189 | 190 | /* Begin PBXProject section */ 191 | ED6E757225F51FE2006387CA /* Project object */ = { 192 | isa = PBXProject; 193 | attributes = { 194 | LastSwiftUpdateCheck = 1240; 195 | LastUpgradeCheck = 1240; 196 | TargetAttributes = { 197 | ED6E757925F51FE2006387CA = { 198 | CreatedOnToolsVersion = 12.4; 199 | }; 200 | }; 201 | }; 202 | buildConfigurationList = ED6E757525F51FE2006387CA /* Build configuration list for PBXProject "upbitBar" */; 203 | compatibilityVersion = "Xcode 9.3"; 204 | developmentRegion = en; 205 | hasScannedForEncodings = 0; 206 | knownRegions = ( 207 | en, 208 | Base, 209 | ko, 210 | ); 211 | mainGroup = ED6E757125F51FE2006387CA; 212 | packageReferences = ( 213 | ED6E758E25F5204B006387CA /* XCRemoteSwiftPackageReference "Just" */, 214 | ED6E759225F5224B006387CA /* XCRemoteSwiftPackageReference "JWTComponents" */, 215 | ED6E759725F522EC006387CA /* XCRemoteSwiftPackageReference "then" */, 216 | ED6E75A525F53056006387CA /* XCRemoteSwiftPackageReference "swift-log" */, 217 | ED6E75AF25F54B0E006387CA /* XCRemoteSwiftPackageReference "LaunchAtLogin" */, 218 | ED6E765825F64BC5006387CA /* XCRemoteSwiftPackageReference "SnapKit" */, 219 | ); 220 | productRefGroup = ED6E757B25F51FE2006387CA /* Products */; 221 | projectDirPath = ""; 222 | projectRoot = ""; 223 | targets = ( 224 | ED6E757925F51FE2006387CA /* upbitBar */, 225 | ); 226 | }; 227 | /* End PBXProject section */ 228 | 229 | /* Begin PBXResourcesBuildPhase section */ 230 | ED6E757825F51FE2006387CA /* Resources */ = { 231 | isa = PBXResourcesBuildPhase; 232 | buildActionMask = 2147483647; 233 | files = ( 234 | ED6E758225F51FE3006387CA /* Assets.xcassets in Resources */, 235 | ED6E773425F68E8C006387CA /* Localizable.strings in Resources */, 236 | ED6E758525F51FE3006387CA /* Main.storyboard in Resources */, 237 | ); 238 | runOnlyForDeploymentPostprocessing = 0; 239 | }; 240 | /* End PBXResourcesBuildPhase section */ 241 | 242 | /* Begin PBXShellScriptBuildPhase section */ 243 | ED3BF34D25F7F2F500F05BB5 /* LaunchAtLogin */ = { 244 | isa = PBXShellScriptBuildPhase; 245 | buildActionMask = 2147483647; 246 | files = ( 247 | ); 248 | inputFileListPaths = ( 249 | ); 250 | inputPaths = ( 251 | ); 252 | name = LaunchAtLogin; 253 | outputFileListPaths = ( 254 | ); 255 | outputPaths = ( 256 | ); 257 | runOnlyForDeploymentPostprocessing = 0; 258 | shellPath = /bin/sh; 259 | 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"; 260 | }; 261 | /* End PBXShellScriptBuildPhase section */ 262 | 263 | /* Begin PBXSourcesBuildPhase section */ 264 | ED6E757625F51FE2006387CA /* Sources */ = { 265 | isa = PBXSourcesBuildPhase; 266 | buildActionMask = 2147483647; 267 | files = ( 268 | ED6E759D25F52C45006387CA /* CryptoAsset.swift in Sources */, 269 | ED6E75AD25F54617006387CA /* Cryptocurrency.swift in Sources */, 270 | ED6E772D25F689E0006387CA /* RefreshInterval.swift in Sources */, 271 | ED6E765625F648E8006387CA /* SettingViewController.swift in Sources */, 272 | ED6E772A25F6836E006387CA /* Notifications.swift in Sources */, 273 | ED6E75AA25F5325A006387CA /* Ticker.swift in Sources */, 274 | ED6E75B425F54B6C006387CA /* UpbitAPI.swift in Sources */, 275 | A7BC7B8626032E0000B2A6DB /* Constants.swift in Sources */, 276 | ED6E75A225F52DE1006387CA /* UpbitServices.swift in Sources */, 277 | A7BC7B8A26032E3000B2A6DB /* Market.swift in Sources */, 278 | ED6E774125F68F14006387CA /* Localized.swift in Sources */, 279 | ED6E772125F67802006387CA /* UserInfo.swift in Sources */, 280 | ED3BF34625F7C67A00F05BB5 /* Attributes.swift in Sources */, 281 | ED6E757E25F51FE2006387CA /* AppDelegate.swift in Sources */, 282 | ); 283 | runOnlyForDeploymentPostprocessing = 0; 284 | }; 285 | /* End PBXSourcesBuildPhase section */ 286 | 287 | /* Begin PBXVariantGroup section */ 288 | ED6E758325F51FE3006387CA /* Main.storyboard */ = { 289 | isa = PBXVariantGroup; 290 | children = ( 291 | ED6E758425F51FE3006387CA /* Base */, 292 | ED6E773825F68EAB006387CA /* ko */, 293 | ); 294 | name = Main.storyboard; 295 | sourceTree = ""; 296 | }; 297 | ED6E773625F68E8C006387CA /* Localizable.strings */ = { 298 | isa = PBXVariantGroup; 299 | children = ( 300 | ED6E773525F68E8C006387CA /* en */, 301 | ED6E773925F68EAB006387CA /* ko */, 302 | ); 303 | name = Localizable.strings; 304 | sourceTree = ""; 305 | }; 306 | /* End PBXVariantGroup section */ 307 | 308 | /* Begin XCBuildConfiguration section */ 309 | ED6E758825F51FE3006387CA /* Debug */ = { 310 | isa = XCBuildConfiguration; 311 | buildSettings = { 312 | ALWAYS_SEARCH_USER_PATHS = NO; 313 | CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; 314 | CLANG_ANALYZER_NONNULL = YES; 315 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 316 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 317 | CLANG_CXX_LIBRARY = "libc++"; 318 | CLANG_ENABLE_MODULES = YES; 319 | CLANG_ENABLE_OBJC_ARC = YES; 320 | CLANG_ENABLE_OBJC_WEAK = YES; 321 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 322 | CLANG_WARN_BOOL_CONVERSION = YES; 323 | CLANG_WARN_COMMA = YES; 324 | CLANG_WARN_CONSTANT_CONVERSION = YES; 325 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 326 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 327 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 328 | CLANG_WARN_EMPTY_BODY = YES; 329 | CLANG_WARN_ENUM_CONVERSION = YES; 330 | CLANG_WARN_INFINITE_RECURSION = YES; 331 | CLANG_WARN_INT_CONVERSION = YES; 332 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 333 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 334 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 335 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 336 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; 337 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 338 | CLANG_WARN_STRICT_PROTOTYPES = YES; 339 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 340 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 341 | CLANG_WARN_UNREACHABLE_CODE = YES; 342 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 343 | COPY_PHASE_STRIP = NO; 344 | DEBUG_INFORMATION_FORMAT = dwarf; 345 | ENABLE_STRICT_OBJC_MSGSEND = YES; 346 | ENABLE_TESTABILITY = YES; 347 | GCC_C_LANGUAGE_STANDARD = gnu11; 348 | GCC_DYNAMIC_NO_PIC = NO; 349 | GCC_NO_COMMON_BLOCKS = YES; 350 | GCC_OPTIMIZATION_LEVEL = 0; 351 | GCC_PREPROCESSOR_DEFINITIONS = ( 352 | "DEBUG=1", 353 | "$(inherited)", 354 | ); 355 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 356 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 357 | GCC_WARN_UNDECLARED_SELECTOR = YES; 358 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 359 | GCC_WARN_UNUSED_FUNCTION = YES; 360 | GCC_WARN_UNUSED_VARIABLE = YES; 361 | MACOSX_DEPLOYMENT_TARGET = 11.1; 362 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; 363 | MTL_FAST_MATH = YES; 364 | ONLY_ACTIVE_ARCH = YES; 365 | SDKROOT = macosx; 366 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; 367 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 368 | }; 369 | name = Debug; 370 | }; 371 | ED6E758925F51FE3006387CA /* Release */ = { 372 | isa = XCBuildConfiguration; 373 | buildSettings = { 374 | ALWAYS_SEARCH_USER_PATHS = NO; 375 | CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; 376 | CLANG_ANALYZER_NONNULL = YES; 377 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 378 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 379 | CLANG_CXX_LIBRARY = "libc++"; 380 | CLANG_ENABLE_MODULES = YES; 381 | CLANG_ENABLE_OBJC_ARC = YES; 382 | CLANG_ENABLE_OBJC_WEAK = YES; 383 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 384 | CLANG_WARN_BOOL_CONVERSION = YES; 385 | CLANG_WARN_COMMA = YES; 386 | CLANG_WARN_CONSTANT_CONVERSION = YES; 387 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 388 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 389 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 390 | CLANG_WARN_EMPTY_BODY = YES; 391 | CLANG_WARN_ENUM_CONVERSION = YES; 392 | CLANG_WARN_INFINITE_RECURSION = YES; 393 | CLANG_WARN_INT_CONVERSION = YES; 394 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 395 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 396 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 397 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 398 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; 399 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 400 | CLANG_WARN_STRICT_PROTOTYPES = YES; 401 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 402 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 403 | CLANG_WARN_UNREACHABLE_CODE = YES; 404 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 405 | COPY_PHASE_STRIP = NO; 406 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 407 | ENABLE_NS_ASSERTIONS = NO; 408 | ENABLE_STRICT_OBJC_MSGSEND = YES; 409 | GCC_C_LANGUAGE_STANDARD = gnu11; 410 | GCC_NO_COMMON_BLOCKS = YES; 411 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 412 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 413 | GCC_WARN_UNDECLARED_SELECTOR = YES; 414 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 415 | GCC_WARN_UNUSED_FUNCTION = YES; 416 | GCC_WARN_UNUSED_VARIABLE = YES; 417 | MACOSX_DEPLOYMENT_TARGET = 11.1; 418 | MTL_ENABLE_DEBUG_INFO = NO; 419 | MTL_FAST_MATH = YES; 420 | SDKROOT = macosx; 421 | SWIFT_COMPILATION_MODE = wholemodule; 422 | SWIFT_OPTIMIZATION_LEVEL = "-O"; 423 | }; 424 | name = Release; 425 | }; 426 | ED6E758B25F51FE4006387CA /* Debug */ = { 427 | isa = XCBuildConfiguration; 428 | buildSettings = { 429 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 430 | ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; 431 | CODE_SIGN_ENTITLEMENTS = "Supporting Files/upbitBar.entitlements"; 432 | CODE_SIGN_IDENTITY = "-"; 433 | CODE_SIGN_STYLE = Automatic; 434 | COMBINE_HIDPI_IMAGES = YES; 435 | CURRENT_PROJECT_VERSION = 1; 436 | DEVELOPMENT_TEAM = U6GQL8JQMT; 437 | ENABLE_HARDENED_RUNTIME = YES; 438 | INFOPLIST_FILE = "Supporting Files/Info.plist"; 439 | LD_RUNPATH_SEARCH_PATHS = ( 440 | "$(inherited)", 441 | "@executable_path/../Frameworks", 442 | ); 443 | MACOSX_DEPLOYMENT_TARGET = 10.15; 444 | MARKETING_VERSION = 1.0; 445 | PRODUCT_BUNDLE_IDENTIFIER = com.tmsae.upbitbar; 446 | PRODUCT_NAME = "$(TARGET_NAME)"; 447 | SWIFT_VERSION = 5.0; 448 | }; 449 | name = Debug; 450 | }; 451 | ED6E758C25F51FE4006387CA /* Release */ = { 452 | isa = XCBuildConfiguration; 453 | buildSettings = { 454 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 455 | ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; 456 | CODE_SIGN_ENTITLEMENTS = "Supporting Files/upbitBar.entitlements"; 457 | CODE_SIGN_IDENTITY = "-"; 458 | CODE_SIGN_STYLE = Automatic; 459 | COMBINE_HIDPI_IMAGES = YES; 460 | CURRENT_PROJECT_VERSION = 1; 461 | DEVELOPMENT_TEAM = U6GQL8JQMT; 462 | ENABLE_HARDENED_RUNTIME = YES; 463 | INFOPLIST_FILE = "Supporting Files/Info.plist"; 464 | LD_RUNPATH_SEARCH_PATHS = ( 465 | "$(inherited)", 466 | "@executable_path/../Frameworks", 467 | ); 468 | MACOSX_DEPLOYMENT_TARGET = 10.15; 469 | MARKETING_VERSION = 1.0; 470 | PRODUCT_BUNDLE_IDENTIFIER = com.tmsae.upbitbar; 471 | PRODUCT_NAME = "$(TARGET_NAME)"; 472 | SWIFT_VERSION = 5.0; 473 | }; 474 | name = Release; 475 | }; 476 | /* End XCBuildConfiguration section */ 477 | 478 | /* Begin XCConfigurationList section */ 479 | ED6E757525F51FE2006387CA /* Build configuration list for PBXProject "upbitBar" */ = { 480 | isa = XCConfigurationList; 481 | buildConfigurations = ( 482 | ED6E758825F51FE3006387CA /* Debug */, 483 | ED6E758925F51FE3006387CA /* Release */, 484 | ); 485 | defaultConfigurationIsVisible = 0; 486 | defaultConfigurationName = Release; 487 | }; 488 | ED6E758A25F51FE4006387CA /* Build configuration list for PBXNativeTarget "upbitBar" */ = { 489 | isa = XCConfigurationList; 490 | buildConfigurations = ( 491 | ED6E758B25F51FE4006387CA /* Debug */, 492 | ED6E758C25F51FE4006387CA /* Release */, 493 | ); 494 | defaultConfigurationIsVisible = 0; 495 | defaultConfigurationName = Release; 496 | }; 497 | /* End XCConfigurationList section */ 498 | 499 | /* Begin XCRemoteSwiftPackageReference section */ 500 | ED6E758E25F5204B006387CA /* XCRemoteSwiftPackageReference "Just" */ = { 501 | isa = XCRemoteSwiftPackageReference; 502 | repositoryURL = "https://github.com/dduan/Just"; 503 | requirement = { 504 | kind = upToNextMajorVersion; 505 | minimumVersion = 0.8.0; 506 | }; 507 | }; 508 | ED6E759225F5224B006387CA /* XCRemoteSwiftPackageReference "JWTComponents" */ = { 509 | isa = XCRemoteSwiftPackageReference; 510 | repositoryURL = "https://github.com/couchdeveloper/JWTComponents"; 511 | requirement = { 512 | kind = upToNextMajorVersion; 513 | minimumVersion = 0.4.0; 514 | }; 515 | }; 516 | ED6E759725F522EC006387CA /* XCRemoteSwiftPackageReference "then" */ = { 517 | isa = XCRemoteSwiftPackageReference; 518 | repositoryURL = "http://github.com/devxoul/then"; 519 | requirement = { 520 | kind = upToNextMajorVersion; 521 | minimumVersion = 2.7.0; 522 | }; 523 | }; 524 | ED6E75A525F53056006387CA /* XCRemoteSwiftPackageReference "swift-log" */ = { 525 | isa = XCRemoteSwiftPackageReference; 526 | repositoryURL = "https://github.com/apple/swift-log"; 527 | requirement = { 528 | kind = upToNextMajorVersion; 529 | minimumVersion = 1.4.2; 530 | }; 531 | }; 532 | ED6E75AF25F54B0E006387CA /* XCRemoteSwiftPackageReference "LaunchAtLogin" */ = { 533 | isa = XCRemoteSwiftPackageReference; 534 | repositoryURL = "https://github.com/sindresorhus/LaunchAtLogin"; 535 | requirement = { 536 | kind = upToNextMajorVersion; 537 | minimumVersion = 4.0.0; 538 | }; 539 | }; 540 | ED6E765825F64BC5006387CA /* XCRemoteSwiftPackageReference "SnapKit" */ = { 541 | isa = XCRemoteSwiftPackageReference; 542 | repositoryURL = "https://github.com/SnapKit/SnapKit"; 543 | requirement = { 544 | kind = upToNextMajorVersion; 545 | minimumVersion = 5.0.1; 546 | }; 547 | }; 548 | /* End XCRemoteSwiftPackageReference section */ 549 | 550 | /* Begin XCSwiftPackageProductDependency section */ 551 | ED6E758F25F5204B006387CA /* Just */ = { 552 | isa = XCSwiftPackageProductDependency; 553 | package = ED6E758E25F5204B006387CA /* XCRemoteSwiftPackageReference "Just" */; 554 | productName = Just; 555 | }; 556 | ED6E759325F5224B006387CA /* JWTComponents */ = { 557 | isa = XCSwiftPackageProductDependency; 558 | package = ED6E759225F5224B006387CA /* XCRemoteSwiftPackageReference "JWTComponents" */; 559 | productName = JWTComponents; 560 | }; 561 | ED6E759825F522EC006387CA /* Then */ = { 562 | isa = XCSwiftPackageProductDependency; 563 | package = ED6E759725F522EC006387CA /* XCRemoteSwiftPackageReference "then" */; 564 | productName = Then; 565 | }; 566 | ED6E75A625F53056006387CA /* Logging */ = { 567 | isa = XCSwiftPackageProductDependency; 568 | package = ED6E75A525F53056006387CA /* XCRemoteSwiftPackageReference "swift-log" */; 569 | productName = Logging; 570 | }; 571 | ED6E75B025F54B0E006387CA /* LaunchAtLogin */ = { 572 | isa = XCSwiftPackageProductDependency; 573 | package = ED6E75AF25F54B0E006387CA /* XCRemoteSwiftPackageReference "LaunchAtLogin" */; 574 | productName = LaunchAtLogin; 575 | }; 576 | ED6E765925F64BC5006387CA /* SnapKit */ = { 577 | isa = XCSwiftPackageProductDependency; 578 | package = ED6E765825F64BC5006387CA /* XCRemoteSwiftPackageReference "SnapKit" */; 579 | productName = SnapKit; 580 | }; 581 | /* End XCSwiftPackageProductDependency section */ 582 | }; 583 | rootObject = ED6E757225F51FE2006387CA /* Project object */; 584 | } 585 | -------------------------------------------------------------------------------- /Supporting Files/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | 289 | 290 | 291 | 292 | 293 | 294 | 295 | 296 | 297 | 298 | 299 | 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | 309 | 310 | 311 | 312 | 313 | 314 | 315 | 316 | 317 | 318 | 319 | 320 | 321 | 322 | 323 | 324 | 325 | 326 | 327 | 328 | 329 | 330 | 331 | 332 | 333 | 334 | 335 | 336 | 337 | 338 | 339 | 340 | 341 | 342 | 343 | 344 | 345 | 346 | 347 | 348 | 349 | 350 | 351 | 352 | 353 | 354 | 355 | 356 | 357 | 358 | 359 | 360 | 361 | 362 | 363 | 364 | 365 | 366 | 367 | 368 | 369 | 370 | 371 | 372 | 373 | 374 | 375 | 376 | 377 | 378 | 379 | 380 | 381 | 382 | 383 | 384 | 385 | 386 | 387 | 388 | 389 | 390 | 391 | 392 | 393 | 394 | 395 | 396 | 397 | 398 | 399 | 400 | 401 | 402 | 403 | 404 | 405 | 406 | 407 | 408 | 409 | 410 | 411 | 412 | 413 | 414 | 415 | 416 | 417 | 418 | 419 | 420 | 421 | 422 | 423 | 424 | 425 | 426 | 427 | 428 | 429 | 430 | 431 | 432 | 433 | 434 | 435 | 436 | 437 | 438 | 439 | 440 | 441 | 442 | 443 | 444 | 445 | 446 | 447 | 448 | 449 | 450 | 451 | 452 | 453 | 454 | 455 | 456 | 457 | 458 | 459 | 460 | 461 | 462 | 463 | 464 | 465 | 466 | 467 | 468 | 469 | 470 | 471 | 472 | 473 | 474 | 475 | 476 | 477 | 478 | 479 | 480 | 481 | 482 | 483 | 484 | 485 | 486 | 487 | 488 | 489 | 490 | 491 | 492 | 493 | 494 | 495 | 496 | 497 | 498 | 499 | 500 | 501 | 502 | 503 | 504 | 505 | 506 | 507 | 508 | 509 | 510 | 511 | 512 | 513 | 514 | 515 | 516 | 517 | 518 | 519 | 520 | 521 | 522 | 523 | 524 | 525 | 526 | 527 | 528 | 529 | Default 530 | 531 | 532 | 533 | 534 | 535 | 536 | Left to Right 537 | 538 | 539 | 540 | 541 | 542 | 543 | Right to Left 544 | 545 | 546 | 547 | 548 | 549 | 550 | 551 | 552 | 553 | 554 | Default 555 | 556 | 557 | 558 | 559 | 560 | 561 | Left to Right 562 | 563 | 564 | 565 | 566 | 567 | 568 | Right to Left 569 | 570 | 571 | 572 | 573 | 574 | 575 | 576 | 577 | 578 | 579 | 580 | 581 | 582 | 583 | 584 | 585 | 586 | 587 | 588 | 589 | 590 | 591 | 592 | 593 | 594 | 595 | 596 | 597 | 598 | 599 | 600 | 601 | 602 | 603 | 604 | 605 | 606 | 607 | 608 | 609 | 610 | 611 | 612 | 613 | 614 | 615 | 616 | 617 | 618 | 619 | 620 | 621 | 622 | 623 | 624 | 625 | 626 | 627 | 628 | 629 | 630 | 631 | 632 | 633 | 634 | 635 | 636 | 637 | 638 | 639 | 640 | 641 | 642 | 643 | 644 | 645 | 646 | 647 | 648 | 649 | 650 | 651 | 652 | 653 | 654 | 655 | 656 | 657 | 658 | 659 | 660 | 661 | 662 | 663 | 664 | 665 | 666 | 667 | 668 | 669 | 670 | 671 | 672 | 673 | 674 | 675 | 676 | 677 | 678 | 679 | 680 | 681 | 682 | 683 | 684 | 685 | --------------------------------------------------------------------------------