├── DeveloperExcuses ├── en.lproj │ └── InfoPlist.strings ├── thumbnail.png ├── thumbnail@2x.png ├── DeveloperExcuses-Prefix.pch ├── Extension │ ├── TimeInterval+FetchInterval.swift │ ├── String+Constants.swift │ ├── Date+FetchInterval.swift │ └── UserDefaults+LastLine.swift ├── DeveloperExcusesConfigureSheetWC.swift ├── DeveloperExcuses-Info.plist ├── DeveloperExcusesView.swift ├── View │ └── OnelinerView.swift └── DeveloperExcusesConfigureSheetWC.xib ├── Release ├── Screenshot.png └── DeveloperExcuses.saver.zip ├── DeveloperExcuses.xcodeproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ │ └── DeveloperExcuses.xccheckout └── project.pbxproj ├── .github └── FUNDING.yml ├── DeveloperExcusesDebug ├── AppDelegate.swift ├── Assets.xcassets │ └── AppIcon.appiconset │ │ └── Contents.json ├── Info.plist └── Main.storyboard ├── LICENSE.md ├── README.md └── .gitignore /DeveloperExcuses/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /Release/Screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kimar/DeveloperExcuses/HEAD/Release/Screenshot.png -------------------------------------------------------------------------------- /DeveloperExcuses/thumbnail.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kimar/DeveloperExcuses/HEAD/DeveloperExcuses/thumbnail.png -------------------------------------------------------------------------------- /DeveloperExcuses/thumbnail@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kimar/DeveloperExcuses/HEAD/DeveloperExcuses/thumbnail@2x.png -------------------------------------------------------------------------------- /Release/DeveloperExcuses.saver.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kimar/DeveloperExcuses/HEAD/Release/DeveloperExcuses.saver.zip -------------------------------------------------------------------------------- /DeveloperExcuses/DeveloperExcuses-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header for all source files of the 'DeveloperExcuses' target in the 'DeveloperExcuses' project 3 | // 4 | 5 | #ifdef __OBJC__ 6 | #import 7 | #endif 8 | -------------------------------------------------------------------------------- /DeveloperExcuses.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /DeveloperExcuses/Extension/TimeInterval+FetchInterval.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TimeInterval+FetchInterval.swift 3 | // OnelinerKit 4 | // 5 | // Created by Marcus Kida on 17.12.17. 6 | // Copyright © 2017 Marcus Kida. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | extension TimeInterval { 12 | static let minimumFetchInterval = 15.0 13 | } 14 | -------------------------------------------------------------------------------- /DeveloperExcuses/Extension/String+Constants.swift: -------------------------------------------------------------------------------- 1 | // 2 | // String+Constants.swift 3 | // OnelinerKit 4 | // 5 | // Created by Marcus Kida on 17.12.17. 6 | // Copyright © 2017 Marcus Kida. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | extension String { 12 | static let onelineFontSize = "onelineFontSize" 13 | static let lastOneline = "lastOneline" 14 | static let fetchQueue = "io.kida.OnelinerKit.fetchQueue" 15 | } 16 | -------------------------------------------------------------------------------- /DeveloperExcuses/Extension/Date+FetchInterval.swift: -------------------------------------------------------------------------------- 1 | // 2 | // NSDate+FetchInterval.swift 3 | // OnelinerKit 4 | // 5 | // Created by Marcus Kida on 17.12.17. 6 | // Copyright © 2017 Marcus Kida. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | extension Date { 12 | func isFetchDue(since: Date) -> Bool { 13 | return timeIntervalSinceReferenceDate > since.timeIntervalSinceReferenceDate + .minimumFetchInterval 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /DeveloperExcuses/Extension/UserDefaults+LastLine.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UserDefaults+LastLine.swift 3 | // OnelinerKit 4 | // 5 | // Created by Marcus Kida on 17.12.17. 6 | // Copyright © 2017 Marcus Kida. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | extension UserDefaults { 12 | static var lastOneline: String? { 13 | get { 14 | return UserDefaults.standard.string(forKey: .lastOneline) 15 | } 16 | set { 17 | UserDefaults.standard.set(newValue, forKey: .lastOneline) 18 | UserDefaults.standard.synchronize() 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /DeveloperExcuses/DeveloperExcusesConfigureSheetWC.swift: -------------------------------------------------------------------------------- 1 | import Cocoa 2 | import ScreenSaver 3 | 4 | class DeveloperExcusesConfigureSheetWC: NSWindowController { 5 | override func windowDidLoad() { 6 | super.windowDidLoad() 7 | } 8 | 9 | @IBAction func endSheet(_ sender: Any?) { 10 | if let window = window { 11 | window.sheetParent?.endSheet(window) 12 | } 13 | } 14 | 15 | @objc dynamic var fontSize: Double = UserDefaults.standard.double(forKey: .onelineFontSize) { 16 | didSet { 17 | UserDefaults.standard.set(fontSize, forKey: .onelineFontSize) 18 | UserDefaults.standard.synchronize() 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: kimar # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] 4 | patreon: # Replace with a single Patreon username 5 | open_collective: # Replace with a single Open Collective username 6 | ko_fi: # Replace with a single Ko-fi username 7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel 8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry 9 | liberapay: # Replace with a single Liberapay username 10 | issuehunt: # Replace with a single IssueHunt username 11 | otechie: # Replace with a single Otechie username 12 | custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] 13 | -------------------------------------------------------------------------------- /DeveloperExcusesDebug/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // DeveloperExcusesDebug 4 | // 5 | // Created by Marcus Kida on 08.06.17. 6 | // Copyright © 2017 Marcus Kida. All rights reserved. 7 | // 8 | 9 | import Cocoa 10 | 11 | @NSApplicationMain 12 | class AppDelegate: NSObject, NSApplicationDelegate { 13 | 14 | lazy var screenSaverView = DeveloperExcusesView(frame: .zero, isPreview: false) 15 | 16 | func applicationDidFinishLaunching(_ aNotification: Notification) { 17 | guard 18 | let window = NSApplication.shared.mainWindow, 19 | let screenSaverView = screenSaverView 20 | else { 21 | preconditionFailure() 22 | } 23 | screenSaverView.frame = window.contentView!.bounds; 24 | screenSaverView.autoresizingMask = [.height, .width] 25 | window.contentView!.addSubview(screenSaverView); 26 | } 27 | 28 | func applicationWillTerminate(_ aNotification: Notification) { 29 | // Insert code here to tear down your application 30 | } 31 | 32 | 33 | } 34 | 35 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2013 - 2017 Marcus Kida 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 | -------------------------------------------------------------------------------- /DeveloperExcuses/DeveloperExcuses-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | English 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIconFile 10 | thumbnail.png 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | ${PRODUCT_NAME} 17 | CFBundlePackageType 18 | BNDL 19 | CFBundleShortVersionString 20 | $(MARKETING_VERSION) 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | $(CURRENT_PROJECT_VERSION) 25 | NSHumanReadableCopyright 26 | Copyright © 2016 Marcus Kida. All rights reserved. 27 | NSPrincipalClass 28 | DeveloperExcuses.DeveloperExcusesView 29 | 30 | 31 | -------------------------------------------------------------------------------- /DeveloperExcusesDebug/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "mac", 5 | "size" : "16x16", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "mac", 10 | "size" : "16x16", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "mac", 15 | "size" : "32x32", 16 | "scale" : "1x" 17 | }, 18 | { 19 | "idiom" : "mac", 20 | "size" : "32x32", 21 | "scale" : "2x" 22 | }, 23 | { 24 | "idiom" : "mac", 25 | "size" : "128x128", 26 | "scale" : "1x" 27 | }, 28 | { 29 | "idiom" : "mac", 30 | "size" : "128x128", 31 | "scale" : "2x" 32 | }, 33 | { 34 | "idiom" : "mac", 35 | "size" : "256x256", 36 | "scale" : "1x" 37 | }, 38 | { 39 | "idiom" : "mac", 40 | "size" : "256x256", 41 | "scale" : "2x" 42 | }, 43 | { 44 | "idiom" : "mac", 45 | "size" : "512x512", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "mac", 50 | "size" : "512x512", 51 | "scale" : "2x" 52 | } 53 | ], 54 | "info" : { 55 | "version" : 1, 56 | "author" : "xcode" 57 | } 58 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # DeveloperExcuses.saver 2 | 3 | [![Twitter: @Kidmar](https://img.shields.io/badge/contact-@Kidmar-blue.svg?style=flat)](https://twitter.com/Kidmar) 4 | [![License](https://img.shields.io/badge/license-MIT-green.svg?style=flat)](https://github.com/kimar/DeveloperExcuses/blob/master/LICENSE.md) 5 | 6 | 7 | ## Proudly powered by [OnelinerKit](https://github.com/kimar/OnelinerKit). 8 | 9 | ![Screenshot](Release/Screenshot.png) 10 | 11 | Dead simple Screensaver which periodically shows a quote from [http://developerexcuses.com](http://developerexcuses.com), that's it. 12 | 13 | Not officially affiliated with [http://developerexcuses.com](http://developerexcuses.com) 14 | 15 | Grab the current [Release here](Release/DeveloperExcuses.saver.zip)! 16 | 17 | And feel free to fork and contribute ;-) 18 | 19 | ## Getting started 20 | 21 | Open up *DeveloperExcuses.xcodeproj* using Xcode and hit Cmd+B to build it. That's it. 22 | 23 | ## Contributing 24 | 25 | As this is only a side-project of mine, there's no roadmap or explicit commitment from my side to fix bugs or add features, however if you'd like to contribute to this project, please feel free to raise a [Pull Request](https://github.com/kimar/DeveloperExcuses/pulls). 26 | 27 | ## License 28 | 29 | See [LICENSE.md](LICENSE.md) 30 | -------------------------------------------------------------------------------- /DeveloperExcusesDebug/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 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 | APPL 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleVersion 22 | 1 23 | LSMinimumSystemVersion 24 | $(MACOSX_DEPLOYMENT_TARGET) 25 | NSHumanReadableCopyright 26 | Copyright © 2017 Marcus Kida. All rights reserved. 27 | NSMainStoryboardFile 28 | Main 29 | NSPrincipalClass 30 | NSApplication 31 | NSAppTransportSecurity 32 | 33 | NSAllowsArbitraryLoads 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /DeveloperExcuses/DeveloperExcusesView.swift: -------------------------------------------------------------------------------- 1 | import Cocoa 2 | import ScreenSaver 3 | 4 | private extension String { 5 | static let htmlRegex = "(.+)" 6 | } 7 | 8 | private extension URL { 9 | static let websiteUrl = URL(string: "http://developerexcuses.com")! 10 | } 11 | 12 | class DeveloperExcusesView: OnelinerView { 13 | override func fetchOneline(_ completion: @escaping (String) -> Void) { 14 | guard let data = try? Data(contentsOf: .websiteUrl), let string = String(data: data, encoding: .utf8) else { 15 | return 16 | } 17 | 18 | guard let regex = try? NSRegularExpression(pattern: .htmlRegex, options: NSRegularExpression.Options(rawValue: 0)) else { 19 | return 20 | } 21 | 22 | let quotes = regex.matches(in: string, options: NSRegularExpression.MatchingOptions(rawValue: 0), range: NSRange(location: 0, length: string.lengthOfBytes(using: .utf8))).map { result in 23 | return (string as NSString).substring(with: result.range(at: 1)) 24 | } 25 | 26 | completion(quotes.first!) 27 | } 28 | 29 | override var hasConfigureSheet: Bool { 30 | true 31 | } 32 | 33 | var configureSheetWC = DeveloperExcusesConfigureSheetWC(windowNibName: "DeveloperExcusesConfigureSheetWC") 34 | 35 | override var configureSheet: NSWindow? { 36 | configureSheetWC.window 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /DeveloperExcuses.xcodeproj/project.xcworkspace/xcshareddata/DeveloperExcuses.xccheckout: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDESourceControlProjectFavoriteDictionaryKey 6 | 7 | IDESourceControlProjectIdentifier 8 | 4CC4EB4B-918E-4C47-A3F7-8C18775BABD2 9 | IDESourceControlProjectName 10 | DeveloperExcuses 11 | IDESourceControlProjectOriginsDictionary 12 | 13 | 283B2FC7-2770-4804-852B-9FAAAD9A31FD 14 | ssh://github.com/kimar/DeveloperExcuses.git 15 | 16 | IDESourceControlProjectPath 17 | DeveloperExcuses.xcodeproj/project.xcworkspace 18 | IDESourceControlProjectRelativeInstallPathDictionary 19 | 20 | 283B2FC7-2770-4804-852B-9FAAAD9A31FD 21 | ../.. 22 | 23 | IDESourceControlProjectURL 24 | ssh://github.com/kimar/DeveloperExcuses.git 25 | IDESourceControlProjectVersion 26 | 110 27 | IDESourceControlProjectWCCIdentifier 28 | 283B2FC7-2770-4804-852B-9FAAAD9A31FD 29 | IDESourceControlProjectWCConfigurations 30 | 31 | 32 | IDESourceControlRepositoryExtensionIdentifierKey 33 | public.vcs.git 34 | IDESourceControlWCCIdentifierKey 35 | 283B2FC7-2770-4804-852B-9FAAAD9A31FD 36 | IDESourceControlWCCName 37 | DeveloperExcuses 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | # Created by https://www.gitignore.io/api/xcode,swift,macos,carthage 3 | 4 | ### Carthage ### 5 | # Carthage 6 | # 7 | # Add this line if you want to avoid checking in source code from Carthage dependencies. 8 | # Carthage/Checkouts 9 | 10 | Carthage/Build 11 | 12 | ### macOS ### 13 | *.DS_Store 14 | .AppleDouble 15 | .LSOverride 16 | 17 | # Icon must end with two \r 18 | Icon 19 | 20 | # Thumbnails 21 | ._* 22 | 23 | # Files that might appear in the root of a volume 24 | .DocumentRevisions-V100 25 | .fseventsd 26 | .Spotlight-V100 27 | .TemporaryItems 28 | .Trashes 29 | .VolumeIcon.icns 30 | .com.apple.timemachine.donotpresent 31 | 32 | # Directories potentially created on remote AFP share 33 | .AppleDB 34 | .AppleDesktop 35 | Network Trash Folder 36 | Temporary Items 37 | .apdisk 38 | 39 | ### Swift ### 40 | # Xcode 41 | # 42 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore 43 | 44 | ## Build generated 45 | build/ 46 | DerivedData/ 47 | 48 | ## Various settings 49 | *.pbxuser 50 | !default.pbxuser 51 | *.mode1v3 52 | !default.mode1v3 53 | *.mode2v3 54 | !default.mode2v3 55 | *.perspectivev3 56 | !default.perspectivev3 57 | xcuserdata/ 58 | 59 | ## Other 60 | *.moved-aside 61 | *.xccheckout 62 | *.xcscmblueprint 63 | 64 | ## Obj-C/Swift specific 65 | *.hmap 66 | *.ipa 67 | *.dSYM.zip 68 | *.dSYM 69 | 70 | ## Playgrounds 71 | timeline.xctimeline 72 | playground.xcworkspace 73 | 74 | # Swift Package Manager 75 | # 76 | # Add this line if you want to avoid checking in source code from Swift Package Manager dependencies. 77 | # Packages/ 78 | # Package.pins 79 | .build/ 80 | 81 | # CocoaPods - Refactored to standalone file 82 | 83 | # Carthage - Refactored to standalone file 84 | 85 | # fastlane 86 | # 87 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the 88 | # screenshots whenever they are needed. 89 | # For more information about the recommended setup visit: 90 | # https://docs.fastlane.tools/best-practices/source-control/#source-control 91 | 92 | fastlane/report.xml 93 | fastlane/Preview.html 94 | fastlane/screenshots 95 | fastlane/test_output 96 | 97 | ### Xcode ### 98 | # Xcode 99 | # 100 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore 101 | 102 | ## Build generated 103 | 104 | ## Various settings 105 | 106 | ## Other 107 | 108 | ### Xcode Patch ### 109 | *.xcodeproj/* 110 | !*.xcodeproj/project.pbxproj 111 | !*.xcodeproj/xcshareddata/ 112 | !*.xcworkspace/contents.xcworkspacedata 113 | /*.gcno 114 | 115 | # End of https://www.gitignore.io/api/xcode,swift,macos,carthage 116 | -------------------------------------------------------------------------------- /DeveloperExcuses/View/OnelinerView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // OnelinerView.swift 3 | // OnelinerKit 4 | // 5 | // Created by Marcus Kida on 17.12.17. 6 | // Copyright © 2017 Marcus Kida. All rights reserved. 7 | // 8 | 9 | import ScreenSaver 10 | 11 | open class OnelinerView: ScreenSaverView { 12 | private let fetchQueue = DispatchQueue(label: .fetchQueue) 13 | private let mainQueue = DispatchQueue.main 14 | 15 | private var label: NSTextField! 16 | private var fetchingDue = true 17 | private var lastFetchDate: Date? 18 | 19 | public var backgroundColor = NSColor.black 20 | public var textColor = NSColor.white 21 | 22 | convenience init() { 23 | self.init(frame: .zero, isPreview: false) 24 | label = makeLabel(false, bounds: frame) 25 | initialize() 26 | } 27 | 28 | override init!(frame: NSRect, isPreview: Bool) { 29 | super.init(frame: frame, isPreview: isPreview) 30 | label = makeLabel(isPreview, bounds: frame) 31 | initialize() 32 | } 33 | 34 | required public init?(coder: NSCoder) { 35 | super.init(coder: coder) 36 | label = makeLabel(isPreview, bounds: bounds) 37 | initialize() 38 | } 39 | 40 | override open var configureSheet: NSWindow? { 41 | return nil 42 | } 43 | 44 | override open var hasConfigureSheet: Bool { 45 | return false 46 | } 47 | 48 | override open func animateOneFrame() { 49 | fetchNext() 50 | } 51 | 52 | override open func draw(_ rect: NSRect) { 53 | super.draw(rect) 54 | 55 | var newFrame = label.frame 56 | newFrame.origin.x = 0 57 | newFrame.origin.y = rect.size.height / 2 58 | newFrame.size.width = rect.size.width 59 | newFrame.size.height = (label.stringValue as NSString).size(withAttributes: [NSAttributedString.Key.font: label.font!]).height 60 | label.frame = newFrame 61 | label.textColor = textColor 62 | 63 | backgroundColor.setFill() 64 | rect.fill() 65 | } 66 | 67 | open func fetchOneline(_ completion: @escaping (String) -> Void) { 68 | preconditionFailure("`fetchOneline` must be overridden") 69 | } 70 | 71 | open var onelineFontSize: Double { 72 | let size = UserDefaults.standard.double(forKey: .onelineFontSize) 73 | if size == 0 { 74 | let defaultSize = 24.0 75 | UserDefaults.standard.set(defaultSize, forKey: .onelineFontSize) 76 | UserDefaults.standard.synchronize() 77 | return defaultSize 78 | } else { 79 | return size 80 | } 81 | } 82 | 83 | private func makeLabel(_ isPreview: Bool, bounds: CGRect) -> NSTextField { 84 | let fontSize = CGFloat(onelineFontSize) 85 | let label = NSTextField(frame: bounds) 86 | label.autoresizingMask = NSView.AutoresizingMask.width 87 | label.alignment = .center 88 | label.stringValue = "Loading…" 89 | label.textColor = .white 90 | 91 | if #available(OSX 10.15, *) { 92 | label.font = NSFont.monospacedSystemFont(ofSize: fontSize, weight: .medium) 93 | } else { 94 | label.font = NSFont(name: "Courier", size: fontSize) 95 | } 96 | 97 | label.backgroundColor = .clear 98 | label.isEditable = false 99 | label.isBezeled = false 100 | return label 101 | } 102 | 103 | private func initialize() { 104 | animationTimeInterval = 0.5 105 | addSubview(label) 106 | restoreLast() 107 | scheduleNext() 108 | } 109 | 110 | private func restoreLast() { 111 | fetchingDue = true 112 | set(oneliner: UserDefaults.lastOneline) 113 | } 114 | 115 | private func set(oneliner: String?) { 116 | if let oneliner = oneliner { 117 | label.stringValue = oneliner 118 | UserDefaults.lastOneline = oneliner 119 | setNeedsDisplay(frame) 120 | } 121 | } 122 | 123 | private func scheduleNext() { 124 | mainQueue.asyncAfter(deadline: .now() + 1) { [weak self] in 125 | guard let 🕑 = self?.lastFetchDate else { 126 | self?.scheduleForFetch() 127 | return 128 | } 129 | guard Date().isFetchDue(since: 🕑) else { 130 | self?.scheduleNext() 131 | return 132 | } 133 | self?.scheduleForFetch() 134 | } 135 | } 136 | 137 | private func scheduleForFetch() { 138 | fetchingDue = true 139 | fetchNext() 140 | } 141 | 142 | private func fetchNext() { 143 | if !fetchingDue { 144 | return 145 | } 146 | fetchingDue = false 147 | fetchQueue.sync { [weak self] in 148 | self?.fetchOneline { oneline in 149 | self?.mainQueue.async { [weak self] in 150 | self?.lastFetchDate = Date() 151 | self?.scheduleNext() 152 | self?.set(oneliner: oneline) 153 | } 154 | } 155 | } 156 | } 157 | } 158 | -------------------------------------------------------------------------------- /DeveloperExcuses/DeveloperExcusesConfigureSheetWC.xib: -------------------------------------------------------------------------------- 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 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | -------------------------------------------------------------------------------- /DeveloperExcuses.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 076642F11EE92D6D00FE8619 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 076642F01EE92D6D00FE8619 /* AppDelegate.swift */; }; 11 | 076642F51EE92D6D00FE8619 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 076642F41EE92D6D00FE8619 /* Assets.xcassets */; }; 12 | 076642FD1EE92D9500FE8619 /* DeveloperExcusesView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 077BC2B01DA22D14007DE060 /* DeveloperExcusesView.swift */; }; 13 | 076643011EE92E8B00FE8619 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 076643001EE92E8B00FE8619 /* Main.storyboard */; }; 14 | 077BC2B11DA22D14007DE060 /* DeveloperExcusesView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 077BC2B01DA22D14007DE060 /* DeveloperExcusesView.swift */; }; 15 | 07B5E452218645D50005E36F /* OnelinerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 07B5E451218645D50005E36F /* OnelinerView.swift */; }; 16 | 07B5E459218645DF0005E36F /* String+Constants.swift in Sources */ = {isa = PBXBuildFile; fileRef = 07B5E454218645DF0005E36F /* String+Constants.swift */; }; 17 | 07B5E45B218645DF0005E36F /* UserDefaults+LastLine.swift in Sources */ = {isa = PBXBuildFile; fileRef = 07B5E456218645DF0005E36F /* UserDefaults+LastLine.swift */; }; 18 | 07B5E45C218645DF0005E36F /* Date+FetchInterval.swift in Sources */ = {isa = PBXBuildFile; fileRef = 07B5E457218645DF0005E36F /* Date+FetchInterval.swift */; }; 19 | 07B5E45D218645DF0005E36F /* TimeInterval+FetchInterval.swift in Sources */ = {isa = PBXBuildFile; fileRef = 07B5E458218645DF0005E36F /* TimeInterval+FetchInterval.swift */; }; 20 | 07F22F0623EEE67400F939BF /* OnelinerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 07B5E451218645D50005E36F /* OnelinerView.swift */; }; 21 | 07F22F0723EEE68000F939BF /* String+Constants.swift in Sources */ = {isa = PBXBuildFile; fileRef = 07B5E454218645DF0005E36F /* String+Constants.swift */; }; 22 | 07F22F0923EEE68000F939BF /* UserDefaults+LastLine.swift in Sources */ = {isa = PBXBuildFile; fileRef = 07B5E456218645DF0005E36F /* UserDefaults+LastLine.swift */; }; 23 | 07F22F0A23EEE68000F939BF /* Date+FetchInterval.swift in Sources */ = {isa = PBXBuildFile; fileRef = 07B5E457218645DF0005E36F /* Date+FetchInterval.swift */; }; 24 | 07F22F0B23EEE68000F939BF /* TimeInterval+FetchInterval.swift in Sources */ = {isa = PBXBuildFile; fileRef = 07B5E458218645DF0005E36F /* TimeInterval+FetchInterval.swift */; }; 25 | 2A9D0E6817DB87B300DBFFBD /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2A9D0E6717DB87B300DBFFBD /* Cocoa.framework */; }; 26 | 2A9D0E6A17DB87B300DBFFBD /* ScreenSaver.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2A9D0E6917DB87B300DBFFBD /* ScreenSaver.framework */; }; 27 | 2A9D0E7417DB87B300DBFFBD /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 2A9D0E7217DB87B300DBFFBD /* InfoPlist.strings */; }; 28 | 3C9050DD2440FD9200542954 /* DeveloperExcusesConfigureSheetWC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3C9050DB2440FD9100542954 /* DeveloperExcusesConfigureSheetWC.swift */; }; 29 | 3C9050DE2440FD9200542954 /* DeveloperExcusesConfigureSheetWC.xib in Resources */ = {isa = PBXBuildFile; fileRef = 3C9050DC2440FD9200542954 /* DeveloperExcusesConfigureSheetWC.xib */; }; 30 | 3C9050DF2440FE4B00542954 /* DeveloperExcusesConfigureSheetWC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3C9050DB2440FD9100542954 /* DeveloperExcusesConfigureSheetWC.swift */; }; 31 | 3C9050E02440FE4E00542954 /* DeveloperExcusesConfigureSheetWC.xib in Resources */ = {isa = PBXBuildFile; fileRef = 3C9050DC2440FD9200542954 /* DeveloperExcusesConfigureSheetWC.xib */; }; 32 | 8117802E1D80A79F00127177 /* thumbnail@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 8117802D1D80A79F00127177 /* thumbnail@2x.png */; }; 33 | 811780321D80B5DD00127177 /* thumbnail.png in Resources */ = {isa = PBXBuildFile; fileRef = 811780311D80B5DD00127177 /* thumbnail.png */; }; 34 | /* End PBXBuildFile section */ 35 | 36 | /* Begin PBXCopyFilesBuildPhase section */ 37 | 07A101791FE687A600F7A42F /* Embed Frameworks */ = { 38 | isa = PBXCopyFilesBuildPhase; 39 | buildActionMask = 2147483647; 40 | dstPath = ""; 41 | dstSubfolderSpec = 10; 42 | files = ( 43 | ); 44 | name = "Embed Frameworks"; 45 | runOnlyForDeploymentPostprocessing = 0; 46 | }; 47 | /* End PBXCopyFilesBuildPhase section */ 48 | 49 | /* Begin PBXFileReference section */ 50 | 072387FF1FE6884A00B1E0E2 /* OnelinerKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OnelinerKit.framework; path = Carthage/Build/Mac/OnelinerKit.framework; sourceTree = ""; }; 51 | 076642EE1EE92D6D00FE8619 /* DeveloperExcusesDebug.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = DeveloperExcusesDebug.app; sourceTree = BUILT_PRODUCTS_DIR; }; 52 | 076642F01EE92D6D00FE8619 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 53 | 076642F41EE92D6D00FE8619 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 54 | 076642F91EE92D6D00FE8619 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 55 | 076643001EE92E8B00FE8619 /* Main.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = Main.storyboard; sourceTree = ""; }; 56 | 077BC2B01DA22D14007DE060 /* DeveloperExcusesView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DeveloperExcusesView.swift; sourceTree = ""; }; 57 | 07B5E451218645D50005E36F /* OnelinerView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OnelinerView.swift; sourceTree = ""; }; 58 | 07B5E454218645DF0005E36F /* String+Constants.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "String+Constants.swift"; sourceTree = ""; }; 59 | 07B5E456218645DF0005E36F /* UserDefaults+LastLine.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UserDefaults+LastLine.swift"; sourceTree = ""; }; 60 | 07B5E457218645DF0005E36F /* Date+FetchInterval.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Date+FetchInterval.swift"; sourceTree = ""; }; 61 | 07B5E458218645DF0005E36F /* TimeInterval+FetchInterval.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "TimeInterval+FetchInterval.swift"; sourceTree = ""; }; 62 | 2A9D0E6417DB87B300DBFFBD /* DeveloperExcuses.saver */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = DeveloperExcuses.saver; sourceTree = BUILT_PRODUCTS_DIR; }; 63 | 2A9D0E6717DB87B300DBFFBD /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; }; 64 | 2A9D0E6917DB87B300DBFFBD /* ScreenSaver.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ScreenSaver.framework; path = System/Library/Frameworks/ScreenSaver.framework; sourceTree = SDKROOT; }; 65 | 2A9D0E6C17DB87B300DBFFBD /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = System/Library/Frameworks/AppKit.framework; sourceTree = SDKROOT; }; 66 | 2A9D0E6D17DB87B300DBFFBD /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = System/Library/Frameworks/CoreData.framework; sourceTree = SDKROOT; }; 67 | 2A9D0E6E17DB87B300DBFFBD /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 68 | 2A9D0E7117DB87B300DBFFBD /* DeveloperExcuses-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "DeveloperExcuses-Info.plist"; sourceTree = ""; }; 69 | 2A9D0E7317DB87B300DBFFBD /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; 70 | 2A9D0E7517DB87B300DBFFBD /* DeveloperExcuses-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "DeveloperExcuses-Prefix.pch"; sourceTree = ""; }; 71 | 3C9050DB2440FD9100542954 /* DeveloperExcusesConfigureSheetWC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeveloperExcusesConfigureSheetWC.swift; sourceTree = ""; }; 72 | 3C9050DC2440FD9200542954 /* DeveloperExcusesConfigureSheetWC.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = DeveloperExcusesConfigureSheetWC.xib; sourceTree = ""; }; 73 | 8117802D1D80A79F00127177 /* thumbnail@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "thumbnail@2x.png"; sourceTree = ""; }; 74 | 811780311D80B5DD00127177 /* thumbnail.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = thumbnail.png; sourceTree = ""; }; 75 | /* End PBXFileReference section */ 76 | 77 | /* Begin PBXFrameworksBuildPhase section */ 78 | 076642EB1EE92D6D00FE8619 /* Frameworks */ = { 79 | isa = PBXFrameworksBuildPhase; 80 | buildActionMask = 2147483647; 81 | files = ( 82 | ); 83 | runOnlyForDeploymentPostprocessing = 0; 84 | }; 85 | 2A9D0E5F17DB87B300DBFFBD /* Frameworks */ = { 86 | isa = PBXFrameworksBuildPhase; 87 | buildActionMask = 2147483647; 88 | files = ( 89 | 2A9D0E6817DB87B300DBFFBD /* Cocoa.framework in Frameworks */, 90 | 2A9D0E6A17DB87B300DBFFBD /* ScreenSaver.framework in Frameworks */, 91 | ); 92 | runOnlyForDeploymentPostprocessing = 0; 93 | }; 94 | /* End PBXFrameworksBuildPhase section */ 95 | 96 | /* Begin PBXGroup section */ 97 | 076642EF1EE92D6D00FE8619 /* DeveloperExcusesDebug */ = { 98 | isa = PBXGroup; 99 | children = ( 100 | 076643001EE92E8B00FE8619 /* Main.storyboard */, 101 | 076642F01EE92D6D00FE8619 /* AppDelegate.swift */, 102 | 076642F41EE92D6D00FE8619 /* Assets.xcassets */, 103 | 076642F91EE92D6D00FE8619 /* Info.plist */, 104 | ); 105 | path = DeveloperExcusesDebug; 106 | sourceTree = ""; 107 | }; 108 | 07B5E450218645D50005E36F /* View */ = { 109 | isa = PBXGroup; 110 | children = ( 111 | 07B5E451218645D50005E36F /* OnelinerView.swift */, 112 | ); 113 | path = View; 114 | sourceTree = ""; 115 | }; 116 | 07B5E453218645DF0005E36F /* Extension */ = { 117 | isa = PBXGroup; 118 | children = ( 119 | 07B5E454218645DF0005E36F /* String+Constants.swift */, 120 | 07B5E456218645DF0005E36F /* UserDefaults+LastLine.swift */, 121 | 07B5E457218645DF0005E36F /* Date+FetchInterval.swift */, 122 | 07B5E458218645DF0005E36F /* TimeInterval+FetchInterval.swift */, 123 | ); 124 | path = Extension; 125 | sourceTree = ""; 126 | }; 127 | 2A9D0E5917DB87B300DBFFBD = { 128 | isa = PBXGroup; 129 | children = ( 130 | 2A9D0E6F17DB87B300DBFFBD /* DeveloperExcuses */, 131 | 076642EF1EE92D6D00FE8619 /* DeveloperExcusesDebug */, 132 | 2A9D0E6617DB87B300DBFFBD /* Frameworks */, 133 | 2A9D0E6517DB87B300DBFFBD /* Products */, 134 | ); 135 | sourceTree = ""; 136 | }; 137 | 2A9D0E6517DB87B300DBFFBD /* Products */ = { 138 | isa = PBXGroup; 139 | children = ( 140 | 2A9D0E6417DB87B300DBFFBD /* DeveloperExcuses.saver */, 141 | 076642EE1EE92D6D00FE8619 /* DeveloperExcusesDebug.app */, 142 | ); 143 | name = Products; 144 | sourceTree = ""; 145 | }; 146 | 2A9D0E6617DB87B300DBFFBD /* Frameworks */ = { 147 | isa = PBXGroup; 148 | children = ( 149 | 072387FF1FE6884A00B1E0E2 /* OnelinerKit.framework */, 150 | 2A9D0E6717DB87B300DBFFBD /* Cocoa.framework */, 151 | 2A9D0E6917DB87B300DBFFBD /* ScreenSaver.framework */, 152 | 2A9D0E6B17DB87B300DBFFBD /* Other Frameworks */, 153 | ); 154 | name = Frameworks; 155 | sourceTree = ""; 156 | }; 157 | 2A9D0E6B17DB87B300DBFFBD /* Other Frameworks */ = { 158 | isa = PBXGroup; 159 | children = ( 160 | 2A9D0E6C17DB87B300DBFFBD /* AppKit.framework */, 161 | 2A9D0E6D17DB87B300DBFFBD /* CoreData.framework */, 162 | 2A9D0E6E17DB87B300DBFFBD /* Foundation.framework */, 163 | ); 164 | name = "Other Frameworks"; 165 | sourceTree = ""; 166 | }; 167 | 2A9D0E6F17DB87B300DBFFBD /* DeveloperExcuses */ = { 168 | isa = PBXGroup; 169 | children = ( 170 | 07B5E453218645DF0005E36F /* Extension */, 171 | 07B5E450218645D50005E36F /* View */, 172 | 077BC2B01DA22D14007DE060 /* DeveloperExcusesView.swift */, 173 | 3C9050DB2440FD9100542954 /* DeveloperExcusesConfigureSheetWC.swift */, 174 | 3C9050DC2440FD9200542954 /* DeveloperExcusesConfigureSheetWC.xib */, 175 | 2A9D0E7017DB87B300DBFFBD /* Supporting Files */, 176 | ); 177 | path = DeveloperExcuses; 178 | sourceTree = ""; 179 | }; 180 | 2A9D0E7017DB87B300DBFFBD /* Supporting Files */ = { 181 | isa = PBXGroup; 182 | children = ( 183 | 2A9D0E7117DB87B300DBFFBD /* DeveloperExcuses-Info.plist */, 184 | 2A9D0E7217DB87B300DBFFBD /* InfoPlist.strings */, 185 | 2A9D0E7517DB87B300DBFFBD /* DeveloperExcuses-Prefix.pch */, 186 | 811780311D80B5DD00127177 /* thumbnail.png */, 187 | 8117802D1D80A79F00127177 /* thumbnail@2x.png */, 188 | ); 189 | name = "Supporting Files"; 190 | sourceTree = ""; 191 | }; 192 | /* End PBXGroup section */ 193 | 194 | /* Begin PBXHeadersBuildPhase section */ 195 | 2A9D0E6017DB87B300DBFFBD /* Headers */ = { 196 | isa = PBXHeadersBuildPhase; 197 | buildActionMask = 2147483647; 198 | files = ( 199 | ); 200 | runOnlyForDeploymentPostprocessing = 0; 201 | }; 202 | /* End PBXHeadersBuildPhase section */ 203 | 204 | /* Begin PBXNativeTarget section */ 205 | 076642ED1EE92D6D00FE8619 /* DeveloperExcusesDebug */ = { 206 | isa = PBXNativeTarget; 207 | buildConfigurationList = 076642FC1EE92D6D00FE8619 /* Build configuration list for PBXNativeTarget "DeveloperExcusesDebug" */; 208 | buildPhases = ( 209 | 076642EA1EE92D6D00FE8619 /* Sources */, 210 | 076642EB1EE92D6D00FE8619 /* Frameworks */, 211 | 076642EC1EE92D6D00FE8619 /* Resources */, 212 | 07A101791FE687A600F7A42F /* Embed Frameworks */, 213 | ); 214 | buildRules = ( 215 | ); 216 | dependencies = ( 217 | ); 218 | name = DeveloperExcusesDebug; 219 | productName = DeveloperExcusesDebug; 220 | productReference = 076642EE1EE92D6D00FE8619 /* DeveloperExcusesDebug.app */; 221 | productType = "com.apple.product-type.application"; 222 | }; 223 | 2A9D0E6317DB87B300DBFFBD /* DeveloperExcuses */ = { 224 | isa = PBXNativeTarget; 225 | buildConfigurationList = 2A9D0E7B17DB87B300DBFFBD /* Build configuration list for PBXNativeTarget "DeveloperExcuses" */; 226 | buildPhases = ( 227 | 2A9D0E5E17DB87B300DBFFBD /* Sources */, 228 | 2A9D0E5F17DB87B300DBFFBD /* Frameworks */, 229 | 2A9D0E6017DB87B300DBFFBD /* Headers */, 230 | 2A9D0E6117DB87B300DBFFBD /* Resources */, 231 | 2A9D0E6217DB87B300DBFFBD /* Rez */, 232 | ); 233 | buildRules = ( 234 | ); 235 | dependencies = ( 236 | ); 237 | name = DeveloperExcuses; 238 | productName = DeveloperExcuses; 239 | productReference = 2A9D0E6417DB87B300DBFFBD /* DeveloperExcuses.saver */; 240 | productType = "com.apple.product-type.bundle"; 241 | }; 242 | /* End PBXNativeTarget section */ 243 | 244 | /* Begin PBXProject section */ 245 | 2A9D0E5A17DB87B300DBFFBD /* Project object */ = { 246 | isa = PBXProject; 247 | attributes = { 248 | LastSwiftUpdateCheck = 0830; 249 | LastUpgradeCheck = 1240; 250 | ORGANIZATIONNAME = "Marcus Kida"; 251 | TargetAttributes = { 252 | 076642ED1EE92D6D00FE8619 = { 253 | CreatedOnToolsVersion = 8.3.2; 254 | DevelopmentTeam = 857XYUU5FE; 255 | ProvisioningStyle = Automatic; 256 | }; 257 | 2A9D0E6317DB87B300DBFFBD = { 258 | DevelopmentTeam = 857XYUU5FE; 259 | LastSwiftMigration = 1240; 260 | }; 261 | }; 262 | }; 263 | buildConfigurationList = 2A9D0E5D17DB87B300DBFFBD /* Build configuration list for PBXProject "DeveloperExcuses" */; 264 | compatibilityVersion = "Xcode 3.2"; 265 | developmentRegion = en; 266 | hasScannedForEncodings = 0; 267 | knownRegions = ( 268 | en, 269 | ); 270 | mainGroup = 2A9D0E5917DB87B300DBFFBD; 271 | productRefGroup = 2A9D0E6517DB87B300DBFFBD /* Products */; 272 | projectDirPath = ""; 273 | projectRoot = ""; 274 | targets = ( 275 | 2A9D0E6317DB87B300DBFFBD /* DeveloperExcuses */, 276 | 076642ED1EE92D6D00FE8619 /* DeveloperExcusesDebug */, 277 | ); 278 | }; 279 | /* End PBXProject section */ 280 | 281 | /* Begin PBXResourcesBuildPhase section */ 282 | 076642EC1EE92D6D00FE8619 /* Resources */ = { 283 | isa = PBXResourcesBuildPhase; 284 | buildActionMask = 2147483647; 285 | files = ( 286 | 076642F51EE92D6D00FE8619 /* Assets.xcassets in Resources */, 287 | 076643011EE92E8B00FE8619 /* Main.storyboard in Resources */, 288 | 3C9050E02440FE4E00542954 /* DeveloperExcusesConfigureSheetWC.xib in Resources */, 289 | ); 290 | runOnlyForDeploymentPostprocessing = 0; 291 | }; 292 | 2A9D0E6117DB87B300DBFFBD /* Resources */ = { 293 | isa = PBXResourcesBuildPhase; 294 | buildActionMask = 2147483647; 295 | files = ( 296 | 3C9050DE2440FD9200542954 /* DeveloperExcusesConfigureSheetWC.xib in Resources */, 297 | 2A9D0E7417DB87B300DBFFBD /* InfoPlist.strings in Resources */, 298 | 8117802E1D80A79F00127177 /* thumbnail@2x.png in Resources */, 299 | 811780321D80B5DD00127177 /* thumbnail.png in Resources */, 300 | ); 301 | runOnlyForDeploymentPostprocessing = 0; 302 | }; 303 | /* End PBXResourcesBuildPhase section */ 304 | 305 | /* Begin PBXRezBuildPhase section */ 306 | 2A9D0E6217DB87B300DBFFBD /* Rez */ = { 307 | isa = PBXRezBuildPhase; 308 | buildActionMask = 2147483647; 309 | files = ( 310 | ); 311 | runOnlyForDeploymentPostprocessing = 0; 312 | }; 313 | /* End PBXRezBuildPhase section */ 314 | 315 | /* Begin PBXSourcesBuildPhase section */ 316 | 076642EA1EE92D6D00FE8619 /* Sources */ = { 317 | isa = PBXSourcesBuildPhase; 318 | buildActionMask = 2147483647; 319 | files = ( 320 | 07F22F0723EEE68000F939BF /* String+Constants.swift in Sources */, 321 | 07F22F0B23EEE68000F939BF /* TimeInterval+FetchInterval.swift in Sources */, 322 | 07F22F0923EEE68000F939BF /* UserDefaults+LastLine.swift in Sources */, 323 | 07F22F0A23EEE68000F939BF /* Date+FetchInterval.swift in Sources */, 324 | 3C9050DF2440FE4B00542954 /* DeveloperExcusesConfigureSheetWC.swift in Sources */, 325 | 076642FD1EE92D9500FE8619 /* DeveloperExcusesView.swift in Sources */, 326 | 076642F11EE92D6D00FE8619 /* AppDelegate.swift in Sources */, 327 | 07F22F0623EEE67400F939BF /* OnelinerView.swift in Sources */, 328 | ); 329 | runOnlyForDeploymentPostprocessing = 0; 330 | }; 331 | 2A9D0E5E17DB87B300DBFFBD /* Sources */ = { 332 | isa = PBXSourcesBuildPhase; 333 | buildActionMask = 2147483647; 334 | files = ( 335 | 07B5E452218645D50005E36F /* OnelinerView.swift in Sources */, 336 | 077BC2B11DA22D14007DE060 /* DeveloperExcusesView.swift in Sources */, 337 | 07B5E45B218645DF0005E36F /* UserDefaults+LastLine.swift in Sources */, 338 | 07B5E45C218645DF0005E36F /* Date+FetchInterval.swift in Sources */, 339 | 3C9050DD2440FD9200542954 /* DeveloperExcusesConfigureSheetWC.swift in Sources */, 340 | 07B5E459218645DF0005E36F /* String+Constants.swift in Sources */, 341 | 07B5E45D218645DF0005E36F /* TimeInterval+FetchInterval.swift in Sources */, 342 | ); 343 | runOnlyForDeploymentPostprocessing = 0; 344 | }; 345 | /* End PBXSourcesBuildPhase section */ 346 | 347 | /* Begin PBXVariantGroup section */ 348 | 2A9D0E7217DB87B300DBFFBD /* InfoPlist.strings */ = { 349 | isa = PBXVariantGroup; 350 | children = ( 351 | 2A9D0E7317DB87B300DBFFBD /* en */, 352 | ); 353 | name = InfoPlist.strings; 354 | sourceTree = ""; 355 | }; 356 | /* End PBXVariantGroup section */ 357 | 358 | /* Begin XCBuildConfiguration section */ 359 | 076642FA1EE92D6D00FE8619 /* Debug */ = { 360 | isa = XCBuildConfiguration; 361 | buildSettings = { 362 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 363 | CLANG_ANALYZER_NONNULL = YES; 364 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 365 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 366 | CLANG_CXX_LIBRARY = "libc++"; 367 | CLANG_ENABLE_MODULES = YES; 368 | CLANG_ENABLE_OBJC_ARC = YES; 369 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 370 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 371 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 372 | CODE_SIGN_IDENTITY = "-"; 373 | COMBINE_HIDPI_IMAGES = YES; 374 | DEBUG_INFORMATION_FORMAT = dwarf; 375 | DEVELOPMENT_TEAM = 857XYUU5FE; 376 | ENABLE_STRICT_OBJC_MSGSEND = YES; 377 | FRAMEWORK_SEARCH_PATHS = ( 378 | "$(inherited)", 379 | "$(PROJECT_DIR)/Carthage/Build/Mac", 380 | ); 381 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 382 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 383 | INFOPLIST_FILE = DeveloperExcusesDebug/Info.plist; 384 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; 385 | MACOSX_DEPLOYMENT_TARGET = 10.12; 386 | MTL_ENABLE_DEBUG_INFO = YES; 387 | PRODUCT_BUNDLE_IDENTIFIER = io.kida.DeveloperExcusesDebug; 388 | PRODUCT_NAME = "$(TARGET_NAME)"; 389 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; 390 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 391 | }; 392 | name = Debug; 393 | }; 394 | 076642FB1EE92D6D00FE8619 /* Release */ = { 395 | isa = XCBuildConfiguration; 396 | buildSettings = { 397 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 398 | CLANG_ANALYZER_NONNULL = YES; 399 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 400 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 401 | CLANG_CXX_LIBRARY = "libc++"; 402 | CLANG_ENABLE_MODULES = YES; 403 | CLANG_ENABLE_OBJC_ARC = YES; 404 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 405 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 406 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 407 | CODE_SIGN_IDENTITY = "-"; 408 | COMBINE_HIDPI_IMAGES = YES; 409 | COPY_PHASE_STRIP = NO; 410 | DEVELOPMENT_TEAM = 857XYUU5FE; 411 | ENABLE_NS_ASSERTIONS = NO; 412 | ENABLE_STRICT_OBJC_MSGSEND = YES; 413 | FRAMEWORK_SEARCH_PATHS = ( 414 | "$(inherited)", 415 | "$(PROJECT_DIR)/Carthage/Build/Mac", 416 | ); 417 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 418 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 419 | INFOPLIST_FILE = DeveloperExcusesDebug/Info.plist; 420 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; 421 | MACOSX_DEPLOYMENT_TARGET = 10.12; 422 | MTL_ENABLE_DEBUG_INFO = NO; 423 | PRODUCT_BUNDLE_IDENTIFIER = io.kida.DeveloperExcusesDebug; 424 | PRODUCT_NAME = "$(TARGET_NAME)"; 425 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; 426 | }; 427 | name = Release; 428 | }; 429 | 2A9D0E7917DB87B300DBFFBD /* Debug */ = { 430 | isa = XCBuildConfiguration; 431 | buildSettings = { 432 | ALWAYS_SEARCH_USER_PATHS = NO; 433 | CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; 434 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 435 | CLANG_WARN_BOOL_CONVERSION = YES; 436 | CLANG_WARN_COMMA = YES; 437 | CLANG_WARN_CONSTANT_CONVERSION = YES; 438 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 439 | CLANG_WARN_EMPTY_BODY = YES; 440 | CLANG_WARN_ENUM_CONVERSION = YES; 441 | CLANG_WARN_INFINITE_RECURSION = YES; 442 | CLANG_WARN_INT_CONVERSION = YES; 443 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 444 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 445 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 446 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; 447 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 448 | CLANG_WARN_STRICT_PROTOTYPES = YES; 449 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 450 | CLANG_WARN_UNREACHABLE_CODE = YES; 451 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 452 | COMBINE_HIDPI_IMAGES = YES; 453 | COPY_PHASE_STRIP = NO; 454 | ENABLE_STRICT_OBJC_MSGSEND = YES; 455 | ENABLE_TESTABILITY = YES; 456 | GCC_C_LANGUAGE_STANDARD = gnu99; 457 | GCC_DYNAMIC_NO_PIC = NO; 458 | GCC_NO_COMMON_BLOCKS = YES; 459 | GCC_OPTIMIZATION_LEVEL = 0; 460 | GCC_PREPROCESSOR_DEFINITIONS = ( 461 | "DEBUG=1", 462 | "$(inherited)", 463 | ); 464 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 465 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 466 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 467 | GCC_WARN_UNDECLARED_SELECTOR = YES; 468 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 469 | GCC_WARN_UNUSED_FUNCTION = YES; 470 | GCC_WARN_UNUSED_VARIABLE = YES; 471 | MACOSX_DEPLOYMENT_TARGET = 10.11; 472 | ONLY_ACTIVE_ARCH = YES; 473 | SDKROOT = macosx; 474 | SWIFT_INSTALL_OBJC_HEADER = NO; 475 | SWIFT_VERSION = 4.2; 476 | }; 477 | name = Debug; 478 | }; 479 | 2A9D0E7A17DB87B300DBFFBD /* Release */ = { 480 | isa = XCBuildConfiguration; 481 | buildSettings = { 482 | ALWAYS_SEARCH_USER_PATHS = NO; 483 | CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; 484 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 485 | CLANG_WARN_BOOL_CONVERSION = YES; 486 | CLANG_WARN_COMMA = YES; 487 | CLANG_WARN_CONSTANT_CONVERSION = YES; 488 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 489 | CLANG_WARN_EMPTY_BODY = YES; 490 | CLANG_WARN_ENUM_CONVERSION = YES; 491 | CLANG_WARN_INFINITE_RECURSION = YES; 492 | CLANG_WARN_INT_CONVERSION = YES; 493 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 494 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 495 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 496 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; 497 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 498 | CLANG_WARN_STRICT_PROTOTYPES = YES; 499 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 500 | CLANG_WARN_UNREACHABLE_CODE = YES; 501 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 502 | COMBINE_HIDPI_IMAGES = YES; 503 | COPY_PHASE_STRIP = YES; 504 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 505 | ENABLE_STRICT_OBJC_MSGSEND = YES; 506 | GCC_C_LANGUAGE_STANDARD = gnu99; 507 | GCC_NO_COMMON_BLOCKS = YES; 508 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 509 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 510 | GCC_WARN_UNDECLARED_SELECTOR = YES; 511 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 512 | GCC_WARN_UNUSED_FUNCTION = YES; 513 | GCC_WARN_UNUSED_VARIABLE = YES; 514 | MACOSX_DEPLOYMENT_TARGET = 10.11; 515 | SDKROOT = macosx; 516 | SWIFT_INSTALL_OBJC_HEADER = NO; 517 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; 518 | SWIFT_VERSION = 4.2; 519 | }; 520 | name = Release; 521 | }; 522 | 2A9D0E7C17DB87B300DBFFBD /* Debug */ = { 523 | isa = XCBuildConfiguration; 524 | buildSettings = { 525 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; 526 | CLANG_ENABLE_MODULES = YES; 527 | CLANG_ENABLE_OBJC_ARC = YES; 528 | CODE_SIGN_IDENTITY = "Mac Developer"; 529 | COMBINE_HIDPI_IMAGES = YES; 530 | CURRENT_PROJECT_VERSION = 2.1.4; 531 | DEVELOPMENT_TEAM = 857XYUU5FE; 532 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 533 | GCC_PREFIX_HEADER = "DeveloperExcuses/DeveloperExcuses-Prefix.pch"; 534 | INFOPLIST_FILE = "DeveloperExcuses/DeveloperExcuses-Info.plist"; 535 | INSTALL_PATH = "$(HOME)/Library/Screen Savers"; 536 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; 537 | MARKETING_VERSION = 2.1.4; 538 | PRODUCT_BUNDLE_IDENTIFIER = "com.marcuskida.${PRODUCT_NAME:rfc1034identifier}"; 539 | PRODUCT_NAME = "$(TARGET_NAME)"; 540 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 541 | SWIFT_VERSION = 5.0; 542 | WRAPPER_EXTENSION = saver; 543 | }; 544 | name = Debug; 545 | }; 546 | 2A9D0E7D17DB87B300DBFFBD /* Release */ = { 547 | isa = XCBuildConfiguration; 548 | buildSettings = { 549 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; 550 | CLANG_ENABLE_MODULES = YES; 551 | CLANG_ENABLE_OBJC_ARC = YES; 552 | CODE_SIGN_IDENTITY = "Mac Developer"; 553 | COMBINE_HIDPI_IMAGES = YES; 554 | CURRENT_PROJECT_VERSION = 2.1.4; 555 | DEVELOPMENT_TEAM = 857XYUU5FE; 556 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 557 | GCC_PREFIX_HEADER = "DeveloperExcuses/DeveloperExcuses-Prefix.pch"; 558 | INFOPLIST_FILE = "DeveloperExcuses/DeveloperExcuses-Info.plist"; 559 | INSTALL_PATH = "$(HOME)/Library/Screen Savers"; 560 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; 561 | MARKETING_VERSION = 2.1.4; 562 | PRODUCT_BUNDLE_IDENTIFIER = "com.marcuskida.${PRODUCT_NAME:rfc1034identifier}"; 563 | PRODUCT_NAME = "$(TARGET_NAME)"; 564 | SWIFT_VERSION = 5.0; 565 | WRAPPER_EXTENSION = saver; 566 | }; 567 | name = Release; 568 | }; 569 | /* End XCBuildConfiguration section */ 570 | 571 | /* Begin XCConfigurationList section */ 572 | 076642FC1EE92D6D00FE8619 /* Build configuration list for PBXNativeTarget "DeveloperExcusesDebug" */ = { 573 | isa = XCConfigurationList; 574 | buildConfigurations = ( 575 | 076642FA1EE92D6D00FE8619 /* Debug */, 576 | 076642FB1EE92D6D00FE8619 /* Release */, 577 | ); 578 | defaultConfigurationIsVisible = 0; 579 | defaultConfigurationName = Release; 580 | }; 581 | 2A9D0E5D17DB87B300DBFFBD /* Build configuration list for PBXProject "DeveloperExcuses" */ = { 582 | isa = XCConfigurationList; 583 | buildConfigurations = ( 584 | 2A9D0E7917DB87B300DBFFBD /* Debug */, 585 | 2A9D0E7A17DB87B300DBFFBD /* Release */, 586 | ); 587 | defaultConfigurationIsVisible = 0; 588 | defaultConfigurationName = Release; 589 | }; 590 | 2A9D0E7B17DB87B300DBFFBD /* Build configuration list for PBXNativeTarget "DeveloperExcuses" */ = { 591 | isa = XCConfigurationList; 592 | buildConfigurations = ( 593 | 2A9D0E7C17DB87B300DBFFBD /* Debug */, 594 | 2A9D0E7D17DB87B300DBFFBD /* Release */, 595 | ); 596 | defaultConfigurationIsVisible = 0; 597 | defaultConfigurationName = Release; 598 | }; 599 | /* End XCConfigurationList section */ 600 | }; 601 | rootObject = 2A9D0E5A17DB87B300DBFFBD /* Project object */; 602 | } 603 | -------------------------------------------------------------------------------- /DeveloperExcusesDebug/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 | Default 511 | 512 | 513 | 514 | 515 | 516 | 517 | Left to Right 518 | 519 | 520 | 521 | 522 | 523 | 524 | Right to Left 525 | 526 | 527 | 528 | 529 | 530 | 531 | 532 | 533 | 534 | 535 | Default 536 | 537 | 538 | 539 | 540 | 541 | 542 | Left to Right 543 | 544 | 545 | 546 | 547 | 548 | 549 | Right to Left 550 | 551 | 552 | 553 | 554 | 555 | 556 | 557 | 558 | 559 | 560 | 561 | 562 | 563 | 564 | 565 | 566 | 567 | 568 | 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 | 686 | 687 | 688 | 689 | 690 | 691 | 692 | 693 | 694 | 695 | 696 | 697 | 698 | 699 | --------------------------------------------------------------------------------