├── .gitignore ├── LICENSE ├── QSKit ├── App │ ├── Base.lproj │ │ └── MainMenu.xib │ ├── Images.xcassets │ │ └── AppIcon.appiconset │ │ │ └── Contents.json │ ├── QSAppDelegate.h │ ├── QSAppDelegate.m │ ├── QSKit-Info.plist │ ├── QSKit-Prefix.pch │ ├── README │ ├── en.lproj │ │ ├── Credits.rtf │ │ └── InfoPlist.strings │ └── main.m ├── Classes │ ├── AppKit │ │ ├── NSColor+QSKit.h │ │ ├── NSColor+QSKit.m │ │ ├── NSView+QSKit.h │ │ └── NSView+QSKit.m │ ├── Foundation │ │ ├── NSArray+QSKit.h │ │ ├── NSArray+QSKit.m │ │ ├── NSAttributedString+QSKit.h │ │ ├── NSAttributedString+QSKit.m │ │ ├── NSData+QSKit.h │ │ ├── NSData+QSKit.m │ │ ├── NSDate+QSKit.h │ │ ├── NSDate+QSKit.m │ │ ├── NSDictionary+QSKit.h │ │ ├── NSDictionary+QSKit.m │ │ ├── NSMutableArray+QSKit.h │ │ ├── NSMutableArray+QSKit.m │ │ ├── NSMutableDictionary+QSKit.h │ │ ├── NSMutableDictionary+QSKit.m │ │ ├── NSMutableSet+QSKit.h │ │ ├── NSMutableSet+QSKit.m │ │ ├── NSNotificationCenter+QSKit.h │ │ ├── NSNotificationCenter+QSKit.m │ │ ├── NSObject+QSKit.h │ │ ├── NSObject+QSKit.m │ │ ├── NSString+QSKit.h │ │ ├── NSString+QSKit.m │ │ ├── NSTimer+QSKit.h │ │ ├── NSTimer+QSKit.m │ │ ├── NSURL+QSKit.h │ │ ├── NSURL+QSKit.m │ │ ├── NSURLRequest+QSKit.h │ │ ├── NSURLRequest+QSKit.m │ │ ├── QSDateParser.h │ │ └── QSDateParser.m │ ├── Images │ │ ├── NSImage+QSKit.h │ │ ├── NSImage+QSKit.m │ │ ├── QSImageRenderer.h │ │ ├── QSImageRenderer.m │ │ ├── QSScaling.h │ │ ├── QSScaling.m │ │ ├── UIImage+QSKit.h │ │ └── UIImage+QSKit.m │ ├── QSBlocks.h │ ├── QSConstants.h │ ├── QSConstants.m │ ├── QSMath.h │ ├── QSMath.m │ ├── QSNode.h │ ├── QSNode.m │ ├── QSPlatform.h │ ├── QSPlatform.m │ ├── SQLite │ │ ├── NSString+QSDatabase.h │ │ ├── NSString+QSDatabase.m │ │ ├── QSDatabaseQueue.h │ │ └── QSDatabaseQueue.m │ ├── UIKit │ │ ├── QSAssets.h │ │ ├── QSAssets.m │ │ ├── UIColor+QSKit.h │ │ ├── UIColor+QSKit.m │ │ ├── UIPanGestureRecognizer+QSKit.h │ │ ├── UIPanGestureRecognizer+QSKit.m │ │ ├── UIResponder+QSKit.h │ │ ├── UIResponder+QSKit.m │ │ ├── UIView+QSKit.h │ │ ├── UIView+QSKit.m │ │ ├── UIViewController+QSKit.h │ │ └── UIViewController+QSKit.m │ ├── Web │ │ ├── NSMutableURLRequest+QSKit.h │ │ ├── NSMutableURLRequest+QSKit.m │ │ ├── QSHTTPConditionalGetInfo.h │ │ ├── QSHTTPConditionalGetInfo.m │ │ ├── QSHTTPConstants.h │ │ ├── QSHTTPConstants.m │ │ ├── QSMimeTypes.h │ │ └── QSMimeTypes.m │ └── XML │ │ ├── QSOPMLFeed.h │ │ ├── QSOPMLFeed.m │ │ ├── QSOPMLFolder.h │ │ ├── QSOPMLFolder.m │ │ ├── QSOPMLParser.h │ │ ├── QSOPMLParser.m │ │ ├── QSOPMLParserFeedsOnly.h │ │ ├── QSOPMLParserFeedsOnly.m │ │ ├── QSSAXParser.h │ │ └── QSSAXParser.m ├── QSKit.xcodeproj │ ├── project.pbxproj │ └── project.xcworkspace │ │ └── contents.xcworkspacedata ├── QSKitTests │ ├── NSArrayTests.m │ ├── NSAttributedStringTests.m │ ├── NSColorTests.m │ ├── NSDataTests.m │ ├── NSDateTests.m │ ├── NSDictionaryTests.m │ ├── NSMutableArrayTests.m │ ├── NSMutableDictionaryTests.m │ ├── NSMutableSetTests.m │ ├── NSObjectTests.m │ ├── NSStringQSDatabaseTests.m │ ├── NSStringTests.m │ ├── NSURLTests.m │ ├── QSDateParserTests.m │ ├── QSKitTests-Info.plist │ ├── QSMathTests.m │ ├── QSOPMLTests.m │ ├── QSPlatformTests.m │ ├── QSSAXParserTests.m │ ├── TestFiles │ │ ├── appstore.png │ │ ├── background.jpg │ │ ├── qbranch.png │ │ ├── subscriptions.opml │ │ ├── subscriptions.plist │ │ └── test.gif │ ├── UIColorTests.m │ └── en.lproj │ │ └── InfoPlist.strings └── Resources │ └── Liberal-URL-Regex-Pattern ├── README.md ├── Vesper Tests ├── Resources │ └── Vesper-Notes.sqlite3 ├── VSAttachmentsTests.m ├── VSBinaryCacheTests.m ├── VSDataMigraterTests.m ├── VSJSONNoteTests.m ├── VSJSONTagsTests.m ├── VSMergeNotesTests.m ├── VSMergeTagsTests.m ├── Vesper Tests-Info.plist ├── Vesper Tests-Prefix.pch └── en.lproj │ └── InfoPlist.strings ├── Vesper.xcodeproj ├── project.pbxproj └── project.xcworkspace │ └── contents.xcworkspacedata └── Vesper ├── Classes ├── CheckmarkTableViewCell.h ├── CheckmarkTableViewCell.m ├── CreditsListView.h ├── CreditsListView.m ├── CreditsPosterView.h ├── CreditsPosterView.m ├── FMDatabase+Extras.h ├── FMDatabase+Extras.m ├── FMDatabase+QSKit.h ├── FMDatabase+QSKit.m ├── FMDatabase.h ├── FMDatabase.m ├── FMDatabaseAdditions.h ├── FMDatabaseAdditions.m ├── FMDatabasePool.h ├── FMDatabasePool.m ├── FMDatabaseQueue.h ├── FMDatabaseQueue.m ├── FMResultSet+RSExtras.h ├── FMResultSet+RSExtras.m ├── FMResultSet.h ├── FMResultSet.m ├── NSString+RSExtras.h ├── NSString+RSExtras.m ├── QSAPIObject.h ├── QSAPIObject.m ├── QSBlocks.m ├── QSDataModel.h ├── QSDataModel.m ├── QSDataObject.h ├── QSDataObjectDeleter.h ├── QSDataObjectDeleter.m ├── QSDataObjectDictionary.h ├── QSDataObjectDictionary.m ├── QSDataRowFetcher.h ├── QSDataRowFetcher.m ├── QSFetchRequest.h ├── QSFetchRequest.m ├── QSLookupTable.h ├── QSLookupTable.m ├── QSObjectSpecifier.h ├── QSObjectSpecifier.m ├── QSRelationship.h ├── QSRelationship.m ├── QSTable.h ├── QSTable.m ├── RSCoreDataUtilities.h ├── RSCoreDataUtilities.m ├── RSGeometry.h ├── RSGeometry.m ├── RSSQLiteDatabaseController.h ├── RSSQLiteDatabaseController.m ├── SFHFKeychainUtils.h ├── SFHFKeychainUtils.m ├── ServerAttachment.h ├── ServerAttachment.m ├── SidebarAnimationController.h ├── SidebarAnimationController.m ├── SidebarPresentationController.h ├── SidebarPresentationController.m ├── SidebarTransitioningDelegate.h ├── SidebarTransitioningDelegate.m ├── UIImage+ImageEffects.h ├── UIImage+ImageEffects.m ├── UIImageView+RSExtras.h ├── UIImageView+RSExtras.m ├── UITextView+RSExtras.h ├── UITextView+RSExtras.m ├── UIView+RSExtras.h ├── UIView+RSExtras.m ├── VSAPICall.h ├── VSAPICall.m ├── VSAPICaller.h ├── VSAPICaller.m ├── VSAPIResult.h ├── VSAPIResult.m ├── VSAccount.h ├── VSAccount.m ├── VSActivityPopover.h ├── VSActivityPopover.m ├── VSAppDelegate.h ├── VSAppDelegate.m ├── VSAppDelegateProtocol.h ├── VSArchiveIndicatorView.h ├── VSArchiveIndicatorView.m ├── VSAttachment.h ├── VSAttachment.m ├── VSAttachmentData.h ├── VSAttachmentData.m ├── VSAttachmentDataController.h ├── VSAttachmentDataController.m ├── VSAttachmentStorage.h ├── VSAttachmentStorage.m ├── VSAttachmentSyncData.h ├── VSAttachmentSyncData.m ├── VSBaseViewController.h ├── VSBaseViewController.m ├── VSBasicWebViewController.h ├── VSBasicWebViewController.m ├── VSBinaryCache.h ├── VSBinaryCache.m ├── VSBrowserBackgroundView.h ├── VSBrowserBackgroundView.m ├── VSBrowserLoadingView.h ├── VSBrowserLoadingView.m ├── VSBrowserPullToRefreshView.h ├── VSBrowserPullToRefreshView.m ├── VSBrowserToolbarView.h ├── VSBrowserToolbarView.m ├── VSBrowserViewController.h ├── VSBrowserViewController.m ├── VSCameraViewController.h ├── VSCameraViewController.m ├── VSCheckmarkAccessoryView.h ├── VSCheckmarkAccessoryView.m ├── VSConstants.h ├── VSConstants.m ├── VSCreditsViewController.h ├── VSCreditsViewController.m ├── VSDataController.h ├── VSDataController.m ├── VSDatabaseController.h ├── VSDatabaseController.m ├── VSDateManager.h ├── VSDateManager.m ├── VSDescriptionView.h ├── VSDescriptionView.m ├── VSDetailNavbarView.h ├── VSDetailNavbarView.m ├── VSDetailStatusView.h ├── VSDetailStatusView.m ├── VSDetailTextStorage.h ├── VSDetailTextStorage.m ├── VSDetailTextView.h ├── VSDetailTextView.m ├── VSDetailToSearchResultsAnimator.h ├── VSDetailToSearchResultsAnimator.m ├── VSDetailToTimelineAnimator.h ├── VSDetailToTimelineAnimator.m ├── VSDetailToolbar.h ├── VSDetailToolbar.m ├── VSDetailTransitionNavbarView.h ├── VSDetailTransitionNavbarView.m ├── VSDetailTransitionView.h ├── VSDetailTransitionView.m ├── VSDetailView.h ├── VSDetailView.m ├── VSDetailViewController.h ├── VSDetailViewController.m ├── VSEditableTagView.h ├── VSExportHeaderView.h ├── VSExportHeaderView.m ├── VSExportViewController.h ├── VSExportViewController.m ├── VSExporter.h ├── VSExporter.m ├── VSGhostTagButton.h ├── VSGhostTagButton.m ├── VSGroupedTableButtonViewCell.h ├── VSGroupedTableButtonViewCell.m ├── VSIconGridButton.h ├── VSIconGridButton.m ├── VSIconGridPopover.h ├── VSIconGridPopover.m ├── VSImagePickerController.h ├── VSImagePickerController.m ├── VSImageScrollView.h ├── VSImageScrollView.m ├── VSImageUtilities.h ├── VSImageUtilities.m ├── VSInputTextTableViewCell.h ├── VSInputTextTableViewCell.m ├── VSKeychain.h ├── VSKeychain.m ├── VSLabelSwitchTableViewCell.h ├── VSLabelSwitchTableViewCell.m ├── VSLinkButton.h ├── VSLinkButton.m ├── VSLinkButtonFooterView.h ├── VSLinkButtonFooterView.m ├── VSMainThreadQueue.h ├── VSMainThreadQueue.m ├── VSMenuButton.h ├── VSMenuButton.m ├── VSMenuItem.h ├── VSMenuItem.m ├── VSMenuPopover.h ├── VSMenuPopover.m ├── VSNavbarButton.h ├── VSNavbarButton.m ├── VSNavbarView.h ├── VSNavbarView.m ├── VSNoNotesView.h ├── VSNoNotesView.m ├── VSNote.h ├── VSNote.m ├── VSNoteTextRenderer.h ├── VSNoteTextRenderer.m ├── VSPictureNavbarView.h ├── VSPictureNavbarView.m ├── VSPictureViewController.h ├── VSPictureViewController.m ├── VSPopoverBackgroundView.h ├── VSPopoverBackgroundView.m ├── VSProgressCircleView.h ├── VSProgressCircleView.m ├── VSProgressView.h ├── VSProgressView.m ├── VSPullToRefreshView.h ├── VSPullToRefreshView.m ├── VSRootViewController.h ├── VSRootViewController.m ├── VSRootViewManager.h ├── VSRowHeightCache.h ├── VSRowHeightCache.m ├── VSSQLDataController.h ├── VSSQLDataController.m ├── VSSearchBarContainerView.h ├── VSSearchBarContainerView.m ├── VSSearchResultsToDetailAnimator.h ├── VSSearchResultsToDetailAnimator.m ├── VSSearchResultsViewController.h ├── VSSearchResultsViewController.m ├── VSSidebarArchiveStatusController.h ├── VSSidebarArchiveStatusController.m ├── VSSidebarTableViewCell.h ├── VSSidebarTableViewCell.m ├── VSSidebarTagsController.h ├── VSSidebarTagsController.m ├── VSSidebarUntaggedStatusController.h ├── VSSidebarUntaggedStatusController.m ├── VSSidebarView.h ├── VSSidebarView.m ├── VSSidebarViewController.h ├── VSSidebarViewController.m ├── VSSignInFooterView.h ├── VSSignInFooterView.m ├── VSSmokescreenView.h ├── VSSmokescreenView.m ├── VSStatusBarNotification.h ├── VSStatusBarNotification.m ├── VSStatusBarNotificationView.h ├── VSStatusBarNotificationView.m ├── VSSyncChangePasswordViewController.h ├── VSSyncChangePasswordViewController.m ├── VSSyncConstants.h ├── VSSyncConstants.m ├── VSSyncContainerViewController.h ├── VSSyncContainerViewController.m ├── VSSyncCreateAccountViewController.h ├── VSSyncCreateAccountViewController.m ├── VSSyncForgotPasswordViewController.h ├── VSSyncForgotPasswordViewController.m ├── VSSyncNoAccountHeaderView.h ├── VSSyncNoAccountHeaderView.m ├── VSSyncNoAccountViewController.h ├── VSSyncNoAccountViewController.m ├── VSSyncNote.h ├── VSSyncNote.m ├── VSSyncNoteMerger.h ├── VSSyncNoteMerger.m ├── VSSyncObject.h ├── VSSyncObject.m ├── VSSyncSettingsViewController.h ├── VSSyncSettingsViewController.m ├── VSSyncSignInViewController.h ├── VSSyncSignInViewController.m ├── VSSyncTagMerger.h ├── VSSyncTagMerger.m ├── VSSyncUI.h ├── VSSyncUI.m ├── VSSyncUtilities.h ├── VSSyncUtilities.m ├── VSTableViewDragController.h ├── VSTableViewDragController.m ├── VSTag.h ├── VSTag.m ├── VSTagButton.h ├── VSTagButton.m ├── VSTagDetailScrollView.h ├── VSTagDetailScrollView.m ├── VSTagPopover.h ├── VSTagPopover.m ├── VSTagPopoverButton.h ├── VSTagPopoverButton.m ├── VSTagProxy.h ├── VSTagProxy.m ├── VSTagSuggester.h ├── VSTagSuggester.m ├── VSTagSuggestionButton.h ├── VSTagSuggestionButton.m ├── VSTagSuggestionButtonsContainerView.h ├── VSTagSuggestionButtonsContainerView.m ├── VSTagSuggestionView.h ├── VSTagSuggestionView.m ├── VSTagTextFieldContainerView.h ├── VSTagTextFieldContainerView.m ├── VSTagsManager.h ├── VSTagsManager.m ├── VSTestDataImporter.h ├── VSTestDataImporter.m ├── VSTextRenderer.h ├── VSTextRenderer.m ├── VSTextRendererView.h ├── VSTextRendererView.m ├── VSTextView.h ├── VSTextView.m ├── VSTheme.h ├── VSTheme.m ├── VSThemeLoader.h ├── VSThemeLoader.m ├── VSThumbnail.h ├── VSThumbnail.m ├── VSThumbnailCache.h ├── VSThumbnailCache.m ├── VSThumbnailDatabase.h ├── VSThumbnailDatabase.m ├── VSThumbnailRenderer.h ├── VSThumbnailRenderer.m ├── VSThumbnailRotation.h ├── VSThumbnailRotation.m ├── VSTickMarksView.h ├── VSTickMarksView.m ├── VSTimelineCell.h ├── VSTimelineCell.m ├── VSTimelineCellButton.h ├── VSTimelineCellButton.m ├── VSTimelineCellButtonContainer.h ├── VSTimelineCellButtonContainer.m ├── VSTimelineContext.h ├── VSTimelineContext.m ├── VSTimelineNote.h ├── VSTimelineNote.m ├── VSTimelineNotesController.h ├── VSTimelineNotesController.m ├── VSTimelineSectionHeaderView.h ├── VSTimelineSectionHeaderView.m ├── VSTimelineTableView.h ├── VSTimelineTableView.m ├── VSTimelineToDetailAnimator.h ├── VSTimelineToDetailAnimator.m ├── VSTimelineViewController.h ├── VSTimelineViewController.m ├── VSTutorialDataImporter.h ├── VSTutorialDataImporter.m ├── VSTypographyFontSizeCell.h ├── VSTypographyFontSizeCell.m ├── VSTypographySettings.h ├── VSTypographySettings.m ├── VSTypographySmallCapsCell.h ├── VSTypographySmallCapsCell.m ├── VSTypographyTextWeightCell.h ├── VSTypographyTextWeightCell.m ├── VSTypographyViewController.h ├── VSTypographyViewController.m ├── VSUI.h ├── VSUI.m ├── VSV1DataExtracter.h ├── VSV1DataExtracter.m ├── VSV1Importer.h ├── VSV1Importer.m └── fmdb.m ├── Resources ├── CreateStatements2.sql ├── DB5.plist ├── DataModel2.plist ├── Default-1334h@2x.png ├── Default-2208h@3x.png ├── Default-568h@2x.png ├── Default-Landscape.png ├── Default-Landscape@2x.png ├── Default-Portrait.png ├── Default-Portrait@2x.png ├── Default.png ├── Default@2x.png ├── Icon-Small@2x.png ├── TutorialData.plist ├── WebViewError.html ├── account-checkmark@2x.png ├── account-x@2x.png ├── activity-camera@2x.png ├── activity-copy@2x.png ├── activity-delete@2x.png ├── activity-library@2x.png ├── activity-mail@2x.png ├── activity-messages@2x.png ├── activity-newest@2x.png ├── activity-pressed@2x.png ├── activity-print@2x.png ├── activity-remove@2x.png ├── activity-safari@2x.png ├── activity@2x.png ├── addbutton@2x.png ├── all-notes@2x.png ├── archive-full@2x.png ├── archive@2x.png ├── arrow-left@2x.png ├── arrow-right@2x.png ├── camera@2x.png ├── checkmark@2x.png ├── chevron@2x.png ├── cloud-error-status@2x.png ├── cloud-error@2x.png ├── cloud-logo@2x.png ├── cloud-off@2x.png ├── cloud@2x.png ├── credits-bubble@2x.png ├── credits-icon@2x.png ├── credits-names@2x.png ├── credits-remember@2x.png ├── credits-vesper@2x.png ├── export.png ├── export@2x.png ├── icon-ipad.png ├── icon-ipad@2x.png ├── icon@2x.png ├── keyboard@2x.png ├── listbutton@2x.png ├── navbar-backarrow-pressed@2x.png ├── navbar-backarrow@2x.png ├── navbar-button-pressed@2x.png ├── navbar-button@2x.png ├── noarchive@2x.png ├── nonotes@2x.png ├── refresh@2x.png ├── restore@2x.png ├── search-clear@2x.png ├── search-icon@2x.png ├── settings.png ├── settings@2x.png ├── spinner │ ├── spin0@2x.png │ ├── spin10@2x.png │ ├── spin11@2x.png │ ├── spin1@2x.png │ ├── spin2@2x.png │ ├── spin3@2x.png │ ├── spin4@2x.png │ ├── spin5@2x.png │ ├── spin6@2x.png │ ├── spin7@2x.png │ ├── spin8@2x.png │ └── spin9@2x.png ├── ssllock@2x.png ├── taglist-untagged@2x.png ├── taglist@2x.png ├── thanks@2x.png ├── trash@2x.png ├── tutorial.jpg ├── typography@2x.png ├── wallpaper@2x.png ├── webview-back@2x.png ├── webview-downarrow@2x.png └── webview-forward@2x.png ├── Vesper-Info.plist ├── Vesper-Prefix.pch ├── Vesper.entitlements ├── en.lproj └── InfoPlist.strings └── main.m /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2016 brentsimmons 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 | -------------------------------------------------------------------------------- /QSKit/App/Images.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 | } -------------------------------------------------------------------------------- /QSKit/App/QSAppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // QSAppDelegate.h 3 | // Q Branch Standard Kit 4 | // 5 | // Created by Brent Simmons on 10/30/13. 6 | // Copyright (c) 2013 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | @import Cocoa; 10 | 11 | 12 | /*Bogus app just so we can do testing. The testing system seems to want an app.*/ 13 | 14 | 15 | @interface QSAppDelegate : NSObject 16 | 17 | @property (nonatomic, assign) IBOutlet NSWindow *window; 18 | 19 | @end 20 | -------------------------------------------------------------------------------- /QSKit/App/QSAppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // QSAppDelegate.m 3 | // Q Branch Standard Kit 4 | // 5 | // Created by Brent Simmons on 10/30/13. 6 | // Copyright (c) 2013 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | #import "QSAppDelegate.h" 10 | 11 | @implementation QSAppDelegate 12 | 13 | - (void)applicationDidFinishLaunching:(NSNotification *)aNotification { 14 | 15 | #pragma unused(aNotification) 16 | 17 | // Insert code here to initialize your application 18 | } 19 | 20 | @end 21 | -------------------------------------------------------------------------------- /QSKit/App/QSKit-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIconFile 10 | 11 | CFBundleIdentifier 12 | co.qbranch.${PRODUCT_NAME:rfc1034identifier} 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | ${PRODUCT_NAME} 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 1 25 | LSMinimumSystemVersion 26 | ${MACOSX_DEPLOYMENT_TARGET} 27 | NSHumanReadableCopyright 28 | Copyright © 2013 Q Branch LLC. All rights reserved. 29 | NSMainNibFile 30 | MainMenu 31 | NSPrincipalClass 32 | NSApplication 33 | 34 | 35 | -------------------------------------------------------------------------------- /QSKit/App/QSKit-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header 3 | // 4 | // The contents of this file are implicitly included at the beginning of every source file. 5 | // 6 | 7 | @import Cocoa; 8 | -------------------------------------------------------------------------------- /QSKit/App/README: -------------------------------------------------------------------------------- 1 | This is just a bogus app. The testing system seems to want an app. -------------------------------------------------------------------------------- /QSKit/App/en.lproj/Credits.rtf: -------------------------------------------------------------------------------- 1 | {\rtf0\ansi{\fonttbl\f0\fswiss Helvetica;} 2 | {\colortbl;\red255\green255\blue255;} 3 | \paperw9840\paperh8400 4 | \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural 5 | 6 | \f0\b\fs24 \cf0 Engineering: 7 | \b0 \ 8 | Some people\ 9 | \ 10 | 11 | \b Human Interface Design: 12 | \b0 \ 13 | Some other people\ 14 | \ 15 | 16 | \b Testing: 17 | \b0 \ 18 | Hopefully not nobody\ 19 | \ 20 | 21 | \b Documentation: 22 | \b0 \ 23 | Whoever\ 24 | \ 25 | 26 | \b With special thanks to: 27 | \b0 \ 28 | Mom\ 29 | } 30 | -------------------------------------------------------------------------------- /QSKit/App/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /QSKit/App/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // Q Branch Standard Kit 4 | // 5 | // Created by Brent Simmons on 10/30/13. 6 | // Copyright (c) 2013 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | 10 | @import Cocoa; 11 | 12 | int main(int argc, const char * argv[]) 13 | { 14 | return NSApplicationMain(argc, argv); 15 | } 16 | -------------------------------------------------------------------------------- /QSKit/Classes/AppKit/NSColor+QSKit.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSColor+QSKit.h 3 | // Q Branch Standard Kit 4 | // 5 | // Created by Brent Simmons on 10/30/13. 6 | // Copyright (c) 2013 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | 10 | @import Cocoa; 11 | 12 | 13 | @interface NSColor (QSKit) 14 | 15 | 16 | + (NSColor *)qs_colorWithHexString:(NSString *)hexString; 17 | 18 | 19 | @end 20 | -------------------------------------------------------------------------------- /QSKit/Classes/AppKit/NSColor+QSKit.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSColor+QSKit.m 3 | // Q Branch Standard Kit 4 | // 5 | // Created by Brent Simmons on 10/30/13. 6 | // Copyright (c) 2013 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | #import "NSColor+QSKit.h" 10 | #import "NSString+QSKit.h" 11 | 12 | 13 | @implementation NSColor (QSKit) 14 | 15 | 16 | + (NSColor *)qs_colorWithHexString:(NSString *)hexString { 17 | 18 | QSRGBAComponents components = [hexString qs_rgbaComponents]; 19 | 20 | return [NSColor colorWithRed:components.red green:components.green blue:components.blue alpha:components.alpha]; 21 | } 22 | 23 | 24 | @end 25 | -------------------------------------------------------------------------------- /QSKit/Classes/AppKit/NSView+QSKit.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSView+QSKit.h 3 | // Q Branch Standard Kit 4 | // 5 | // Created by Brent Simmons on 10/30/13. 6 | // Copyright (c) 2013 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | 10 | @import Cocoa; 11 | 12 | 13 | @interface NSView (QSKit) 14 | 15 | 16 | /*Keeps subview at same size as receiver.*/ 17 | 18 | - (void)qs_addFullSizeConstraintsForSubview:(NSView *)view; 19 | 20 | - (void)qs_setFrameIfNotEqual:(NSRect)r; 21 | 22 | @end 23 | -------------------------------------------------------------------------------- /QSKit/Classes/AppKit/NSView+QSKit.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSView+QSKit.m 3 | // Q Branch Standard Kit 4 | // 5 | // Created by Brent Simmons on 10/30/13. 6 | // Copyright (c) 2013 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | #import "NSView+QSKit.h" 10 | 11 | 12 | @implementation NSView (QSKit) 13 | 14 | 15 | - (void)qs_addFullSizeConstraintsForSubview:(NSView *)view { 16 | 17 | NSDictionary *d = NSDictionaryOfVariableBindings(view); 18 | 19 | NSArray *constraints = [NSLayoutConstraint constraintsWithVisualFormat:@"|-0-[view]-0-|" options:0 metrics:nil views:d]; 20 | [self addConstraints:constraints]; 21 | constraints = [NSLayoutConstraint constraintsWithVisualFormat:@"V:|-0-[view]-0-|" options:0 metrics:nil views:d]; 22 | [self addConstraints:constraints]; 23 | } 24 | 25 | 26 | - (void)qs_setFrameIfNotEqual:(NSRect)r { 27 | 28 | if (!NSEqualRects(self.frame, r)) { 29 | self.frame = r; 30 | } 31 | } 32 | 33 | 34 | @end 35 | -------------------------------------------------------------------------------- /QSKit/Classes/Foundation/NSArray+QSKit.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSArray+QSKit.h 3 | // Q Branch Standard Kit 4 | // 5 | // Created by Brent Simmons on 10/31/13. 6 | // Copyright (c) 2013 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | 10 | @import Foundation; 11 | 12 | 13 | @interface NSArray (QSKit) 14 | 15 | 16 | /*Returns nil if out of bounds instead of throwing an exception.*/ 17 | 18 | - (id)qs_safeObjectAtIndex:(NSUInteger)anIndex; 19 | 20 | /*Does valueForKey:key. When value isEqual, returns YES.*/ 21 | 22 | - (id)qs_firstObjectWhereValueForKey:(NSString *)key equalsValue:(id)value; 23 | 24 | /*Gets the index from indexOfObjectPassingTest: and returns the object. 25 | Returns nil if not found.*/ 26 | 27 | - (id)qs_firstObjectPassingTest:(BOOL (^)(id obj, NSUInteger idx, BOOL *stop))predicate; 28 | 29 | 30 | typedef id (^QSMapBlock)(id obj); 31 | 32 | - (NSArray *)qs_map:(QSMapBlock)mapBlock; 33 | 34 | 35 | - (NSArray *)qs_arrayWithCopyOfEachObject; 36 | 37 | 38 | /*Does [valueForKey:key] on each object and uses that as the key in the dictionary.*/ 39 | 40 | - (NSDictionary *)qs_dictionaryUsingKey:(id)key; 41 | 42 | 43 | @end 44 | -------------------------------------------------------------------------------- /QSKit/Classes/Foundation/NSAttributedString+QSKit.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSAttributedString+QSKit.h 3 | // Q Branch Standard Kit 4 | // 5 | // Created by Brent Simmons on 10/31/13. 6 | // Copyright (c) 2013 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | 10 | @import Foundation; 11 | #import "QSPlatform.h" 12 | 13 | 14 | @interface NSAttributedString (QSKit) 15 | 16 | 17 | /*If kerning, adds NSKernAttributeName : [NSNull null] (which is the right way to turn on kerning, weirdly). Always Be Kerning. 18 | 19 | (Except that it breaks NSTextView's text pasteboard writing. So don't do it there.)*/ 20 | 21 | + (NSAttributedString *)qs_attributedStringWithText:(NSString *)text font:(QS_FONT *)font color:(QS_COLOR *)color kerning:(BOOL)kerning; 22 | 23 | 24 | @end 25 | -------------------------------------------------------------------------------- /QSKit/Classes/Foundation/NSAttributedString+QSKit.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSAttributedString+QSKit.m 3 | // Q Branch Standard Kit 4 | // 5 | // Created by Brent Simmons on 10/31/13. 6 | // Copyright (c) 2013 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | #import "NSAttributedString+QSKit.h" 10 | 11 | 12 | @implementation NSAttributedString (QSKit) 13 | 14 | 15 | + (NSAttributedString *)qs_attributedStringWithText:(NSString *)text font:(QS_FONT *)font color:(QS_COLOR *)color kerning:(BOOL)kerning { 16 | 17 | NSDictionary *attributes; 18 | 19 | if (kerning) { 20 | attributes = @{NSFontAttributeName : font, NSForegroundColorAttributeName : color, NSKernAttributeName : [NSNull null]}; 21 | } 22 | else { 23 | attributes = @{NSFontAttributeName : font, NSForegroundColorAttributeName : color}; 24 | } 25 | 26 | return [[self alloc] initWithString:text attributes:attributes]; 27 | } 28 | 29 | 30 | @end 31 | -------------------------------------------------------------------------------- /QSKit/Classes/Foundation/NSData+QSKit.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSData+QSKit.h 3 | // Q Branch Standard Kit 4 | // 5 | // Created by Brent Simmons on 10/25/13. 6 | // Copyright (c) 2013 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | @import Foundation; 10 | 11 | 12 | BOOL QSEqualBytes(const void *bytes1, const void *bytes2, size_t length); 13 | 14 | NSString *QSHexadecimalStringWithBytes(const unsigned char *bytes, NSUInteger numberOfBytes); 15 | 16 | 17 | @interface NSData (QSKit) 18 | 19 | 20 | - (NSData *)qs_md5Hash; 21 | 22 | - (BOOL)qs_dataIsPNG; 23 | - (BOOL)qs_dataIsGIF; 24 | - (BOOL)qs_dataIsJPEG; 25 | - (BOOL)qs_dataIsImage; 26 | 27 | - (BOOL)qs_dataBeginsWithBytes:(const void *)bytes length:(size_t)numberOfBytes; 28 | 29 | 30 | /*If bytes are deadbeef, then string is @"deadbeef". Returns nil for empty data.*/ 31 | 32 | - (NSString *)qs_hexadecimalString; 33 | 34 | 35 | @end 36 | -------------------------------------------------------------------------------- /QSKit/Classes/Foundation/NSDate+QSKit.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSDate+QSKit.h 3 | // Q Branch Standard Kit 4 | // 5 | // Created by Brent Simmons on 10/25/13. 6 | // Copyright (c) 2013 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | 10 | @import Foundation; 11 | 12 | 13 | @interface NSDate (QSKit) 14 | 15 | 16 | - (NSString *)qs_unixTimestampStringWithNoDecimal; 17 | 18 | - (NSString *)qs_iso8601DateString; 19 | 20 | 21 | /*Not intended for calendar-perfect use.*/ 22 | 23 | + (NSDate *)qs_dateWithNumberOfDaysInThePast:(NSUInteger)numberOfDays; 24 | 25 | @end 26 | -------------------------------------------------------------------------------- /QSKit/Classes/Foundation/NSDictionary+QSKit.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSDictionary+QSKit.h 3 | // Q Branch Standard Kit 4 | // 5 | // Created by Brent Simmons on 11/1/13. 6 | // Copyright (c) 2013 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | 10 | @import Foundation; 11 | 12 | 13 | @interface NSDictionary (QSKit) 14 | 15 | /*Keys that aren't strings are ignored. No coercion.*/ 16 | 17 | - (id)qs_objectForCaseInsensitiveKey:(NSString *)key; 18 | 19 | - (BOOL)qs_boolForKey:(NSString *)key; /*NO if doesn't exist.*/ 20 | 21 | 22 | @end 23 | -------------------------------------------------------------------------------- /QSKit/Classes/Foundation/NSDictionary+QSKit.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSDictionary+QSKit.m 3 | // Q Branch Standard Kit 4 | // 5 | // Created by Brent Simmons on 11/1/13. 6 | // Copyright (c) 2013 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | #import "NSDictionary+QSKit.h" 10 | 11 | 12 | @implementation NSDictionary (QSKit) 13 | 14 | 15 | - (id)qs_objectForCaseInsensitiveKey:(NSString *)key { 16 | 17 | id obj = self[key]; 18 | if (obj != nil) { 19 | return obj; 20 | } 21 | 22 | for (NSString *oneKey in [self allKeys]) { 23 | 24 | if ([oneKey isKindOfClass:[NSString class]] && [key caseInsensitiveCompare:oneKey] == NSOrderedSame) { 25 | return self[oneKey]; 26 | } 27 | } 28 | 29 | return nil; 30 | } 31 | 32 | 33 | - (BOOL)qs_boolForKey:(NSString *)key { 34 | 35 | id obj = self[key]; 36 | 37 | if ([obj respondsToSelector:@selector(boolValue)]) { 38 | return [obj boolValue]; 39 | } 40 | 41 | return NO; 42 | } 43 | 44 | 45 | @end 46 | -------------------------------------------------------------------------------- /QSKit/Classes/Foundation/NSMutableArray+QSKit.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSMutableArray+QSKit.h 3 | // Q Branch Standard Kit 4 | // 5 | // Created by Brent Simmons on 10/31/13. 6 | // Copyright (c) 2013 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | 10 | @import Foundation; 11 | 12 | 13 | @interface NSMutableArray (QSKit) 14 | 15 | 16 | /*Does nothing if obj == nil. No exception thrown.*/ 17 | 18 | - (void)qs_safeAddObject:(id)obj; 19 | 20 | 21 | @end 22 | -------------------------------------------------------------------------------- /QSKit/Classes/Foundation/NSMutableArray+QSKit.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSMutableArray+QSKit.m 3 | // Q Branch Standard Kit 4 | // 5 | // Created by Brent Simmons on 10/31/13. 6 | // Copyright (c) 2013 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | #import "NSMutableArray+QSKit.h" 10 | 11 | 12 | @implementation NSMutableArray (QSKit) 13 | 14 | 15 | - (void)qs_safeAddObject:(id)obj { 16 | if (obj != nil) { 17 | [self addObject:obj]; 18 | } 19 | } 20 | 21 | 22 | @end 23 | -------------------------------------------------------------------------------- /QSKit/Classes/Foundation/NSMutableDictionary+QSKit.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSMutableDictionary+QSKit.h 3 | // Q Branch Standard Kit 4 | // 5 | // Created by Brent Simmons on 10/31/13. 6 | // Copyright (c) 2013 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | 10 | @import Foundation; 11 | 12 | 13 | @interface NSMutableDictionary (QSKit) 14 | 15 | 16 | /*If obj or key are nil, does nothing. No exception thrown.*/ 17 | 18 | - (void)qs_safeSetObject:(id)obj forKey:(id)key; 19 | 20 | 21 | @end 22 | -------------------------------------------------------------------------------- /QSKit/Classes/Foundation/NSMutableDictionary+QSKit.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSMutableDictionary+QSKit.m 3 | // Q Branch Standard Kit 4 | // 5 | // Created by Brent Simmons on 10/31/13. 6 | // Copyright (c) 2013 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | #import "NSMutableDictionary+QSKit.h" 10 | 11 | 12 | @implementation NSMutableDictionary (QSKit) 13 | 14 | 15 | - (void)qs_safeSetObject:(id)obj forKey:(id)key { 16 | if (obj != nil & key != nil) { 17 | [self setObject:obj forKey:key]; 18 | } 19 | } 20 | 21 | 22 | @end 23 | -------------------------------------------------------------------------------- /QSKit/Classes/Foundation/NSMutableSet+QSKit.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSMutableSet+QSKit.h 3 | // Q Branch Standard Kit 4 | // 5 | // Created by Brent Simmons on 10/25/13. 6 | // Copyright (c) 2013 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | 10 | @import Foundation; 11 | 12 | 13 | @interface NSMutableSet (QSKit) 14 | 15 | 16 | /*Does nothing if obj == nil. No exception thrown.*/ 17 | 18 | - (void)qs_safeAddObject:(id)obj; 19 | 20 | 21 | @end 22 | -------------------------------------------------------------------------------- /QSKit/Classes/Foundation/NSMutableSet+QSKit.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSMutableSet+QSKit.m 3 | // Q Branch Standard Kit 4 | // 5 | // Created by Brent Simmons on 10/25/13. 6 | // Copyright (c) 2013 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | #import "NSMutableSet+QSKit.h" 10 | 11 | 12 | @implementation NSMutableSet (QSKit) 13 | 14 | 15 | - (void)qs_safeAddObject:(id)obj { 16 | if (obj != nil) { 17 | [self addObject:obj]; 18 | } 19 | } 20 | 21 | 22 | @end 23 | -------------------------------------------------------------------------------- /QSKit/Classes/Foundation/NSNotificationCenter+QSKit.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSNotificationCenter+QSKit.h 3 | // Q Branch Standard Kit 4 | // 5 | // Created by Brent Simmons on 10/20/13. 6 | // Copyright (c) 2013 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | @import Foundation; 10 | 11 | 12 | @interface NSNotificationCenter (QSKit) 13 | 14 | 15 | /*Posts immediately if already on the main thread.*/ 16 | 17 | - (void)qs_postNotificationNameOnMainThread:(NSString *)notificationName object:(id)obj userInfo:(NSDictionary *)userInfo; 18 | 19 | @end 20 | -------------------------------------------------------------------------------- /QSKit/Classes/Foundation/NSNotificationCenter+QSKit.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSNotificationCenter+QSKit.m 3 | // Q Branch Standard Kit 4 | // 5 | // Created by Brent Simmons on 10/20/13. 6 | // Copyright (c) 2013 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | #import "NSNotificationCenter+QSKit.h" 10 | 11 | 12 | @implementation NSNotificationCenter (QSKit) 13 | 14 | - (void)qs_postNotificationNameOnMainThread:(NSString *)notificationName object:(id)obj userInfo:(NSDictionary *)userInfo { 15 | 16 | if (![NSThread isMainThread]) { 17 | 18 | dispatch_async(dispatch_get_main_queue(), ^{ 19 | 20 | [self postNotificationName:notificationName object:obj userInfo:userInfo]; 21 | }); 22 | } 23 | 24 | else { 25 | [self postNotificationName:notificationName object:obj userInfo:userInfo]; 26 | } 27 | } 28 | 29 | @end 30 | 31 | -------------------------------------------------------------------------------- /QSKit/Classes/Foundation/NSObject+QSKit.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSObject+QSKit.h 3 | // Q Branch Standard Kit 4 | // 5 | // Created by Brent Simmons on 10/20/13. 6 | // Copyright (c) 2013 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | 10 | @import Foundation; 11 | 12 | 13 | BOOL QSIsEmpty(id obj); /*YES if nil or NSNull -- or length or count < 1*/ 14 | 15 | 16 | @interface NSObject (QSKit) 17 | 18 | 19 | /*Cancels any previous and does a new -performSelector:withObject:afterDelay:. Experimental.*/ 20 | 21 | - (void)qs_performSelectorCoalesced:(SEL)selector withObject:(id)obj afterDelay:(NSTimeInterval)delay; 22 | 23 | @end 24 | -------------------------------------------------------------------------------- /QSKit/Classes/Foundation/NSObject+QSKit.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSObject+QSKit.m 3 | // Q Branch Standard Kit 4 | // 5 | // Created by Brent Simmons on 10/20/13. 6 | // Copyright (c) 2013 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | #import "NSObject+QSKit.h" 10 | 11 | 12 | BOOL QSIsEmpty(id obj) { 13 | 14 | if (obj == nil || (id)obj == [NSNull null]) { 15 | return YES; 16 | } 17 | 18 | if ([obj respondsToSelector:@selector(count)]) { 19 | return [obj count] < 1; 20 | } 21 | 22 | if ([obj respondsToSelector:@selector(length)]) { 23 | return [obj length] < 1; 24 | } 25 | 26 | return NO; /*Shouldn't get here very often.*/ 27 | } 28 | 29 | 30 | @implementation NSObject (QSKit) 31 | 32 | - (void)qs_performSelectorCoalesced:(SEL)selector withObject:(id)obj afterDelay:(NSTimeInterval)delay { 33 | 34 | [NSObject cancelPreviousPerformRequestsWithTarget:self selector:selector object:obj]; 35 | [self performSelector:selector withObject:obj afterDelay:delay]; 36 | } 37 | 38 | 39 | @end 40 | 41 | -------------------------------------------------------------------------------- /QSKit/Classes/Foundation/NSTimer+QSKit.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSTimer+QSKit.h 3 | // Q Branch Standard Kit 4 | // 5 | // Created by Brent Simmons on 11/1/13. 6 | // Copyright (c) 2013 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | 10 | @import Foundation; 11 | 12 | 13 | @interface NSTimer (QSKit) 14 | 15 | 16 | - (void)qs_invalidateIfValid; 17 | 18 | 19 | @end 20 | -------------------------------------------------------------------------------- /QSKit/Classes/Foundation/NSTimer+QSKit.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSTimer+QSKit.m 3 | // Q Branch Standard Kit 4 | // 5 | // Created by Brent Simmons on 11/1/13. 6 | // Copyright (c) 2013 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | #import "NSTimer+QSKit.h" 10 | 11 | 12 | @implementation NSTimer (QSKit) 13 | 14 | 15 | - (void)qs_invalidateIfValid { 16 | 17 | if ([self isValid]) { 18 | [self invalidate]; 19 | } 20 | } 21 | 22 | @end 23 | -------------------------------------------------------------------------------- /QSKit/Classes/Foundation/NSURL+QSKit.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSURL+QSKit.h 3 | // Q Branch Standard Kit 4 | // 5 | // Created by Brent Simmons on 10/31/13. 6 | // Copyright (c) 2013 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | 10 | @import Foundation; 11 | 12 | 13 | @interface NSURL (QSKit) 14 | 15 | 16 | - (BOOL)qs_isHTTPSURL; 17 | - (BOOL)qs_isHTTPURL; 18 | - (BOOL)qs_isHTTPOrHTTPSURL; 19 | 20 | - (NSString *)qs_absoluteStringWithHTTPOrHTTPSPrefixRemoved; /*Case-insensitive. Removes http:// or https://.*/ 21 | 22 | 23 | /*Turns dictionary into ?x=y&a=b and appends it to URL. 24 | If the URL already has a query, and queryDictionary is not empty, 25 | the original query will be replaced. 26 | 27 | The query keys are sorted (case-insensitive).*/ 28 | 29 | - (NSURL *)qs_URLByAppendingQueryDictionary:(NSDictionary *)queryDictionary; 30 | 31 | 32 | @end 33 | -------------------------------------------------------------------------------- /QSKit/Classes/Foundation/NSURLRequest+QSKit.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSURLRequest+QSKit.h 3 | // Q Branch Standard Kit 4 | // 5 | // Created by Brent Simmons on 10/31/13. 6 | // Copyright (c) 2013 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | 10 | @import Foundation; 11 | 12 | 13 | @interface NSURLRequest (QSKit) 14 | 15 | 16 | - (NSURL *)qs_loadingURL; /*Experimental. Returns nil if scheme isn't http or https (about:blank, for instance).*/ 17 | 18 | @end 19 | -------------------------------------------------------------------------------- /QSKit/Classes/Foundation/NSURLRequest+QSKit.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSURLRequest+QSKit.m 3 | // Q Branch Standard Kit 4 | // 5 | // Created by Brent Simmons on 10/31/13. 6 | // Copyright (c) 2013 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | #import "NSURLRequest+QSKit.h" 10 | #import "NSURL+QSKit.h" 11 | #import "NSString+QSKit.h" 12 | 13 | 14 | @implementation NSURLRequest (QSKit) 15 | 16 | 17 | - (NSURL *)qs_loadingURL { 18 | 19 | NSURL *loadingURL = [self mainDocumentURL]; 20 | if (loadingURL == nil || ![loadingURL qs_isHTTPOrHTTPSURL]) { 21 | return nil; 22 | } 23 | 24 | NSString *absoluteString = [loadingURL absoluteString]; 25 | if (QSStringIsEmpty(absoluteString)) { 26 | return nil; 27 | } 28 | 29 | return loadingURL; 30 | } 31 | 32 | 33 | @end 34 | -------------------------------------------------------------------------------- /QSKit/Classes/Foundation/QSDateParser.h: -------------------------------------------------------------------------------- 1 | // 2 | // QSDateParser.h 3 | // Q Branch Standard Kit 4 | // 5 | // Created by Brent Simmons on 12/18/13. 6 | // Copyright (c) 2013 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | @import Foundation; 10 | 11 | /*The problem: you often know that a date will be in 8601 format (for instance), 12 | but you don't know its precise format, so NSDateFormatter isn't helpful. 13 | 14 | Common web dates -- RFC 822 and 8601 -- are handled here: 15 | the formats you find in JSON and XML feeds. 16 | 17 | Any of these may return nil. They may also return garbage, given bad input. 18 | */ 19 | 20 | 21 | NSDate *QSDateWithString(NSString *dateString); 22 | 23 | /*If you're using a SAX parser, you have the bytes and don't need to convert to a string first. 24 | It's faster and uses less memory. 25 | (Assumes bytes are UTF-8 or ASCII. If you're using the libxml SAX parser, this will work.)*/ 26 | 27 | NSDate *QSDateWithBytes(const char *bytes, NSUInteger numberOfBytes); 28 | -------------------------------------------------------------------------------- /QSKit/Classes/Images/NSImage+QSKit.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSImage+QSKit.h 3 | // Q Branch Standard Kit 4 | // 5 | // Created by Brent Simmons on 10/30/13. 6 | // Copyright (c) 2013 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | 10 | @import Cocoa; 11 | #import "QSBlocks.h" 12 | 13 | 14 | @interface NSImage (QSKit) 15 | 16 | /*Calls -initWithData in background queue. data and imageResultBlock must be non-nil.*/ 17 | 18 | + (void)qs_imageWithData:(NSData *)data imageResultBlock:(QSImageResultBlock)imageResultBlock; 19 | 20 | + (instancetype)imageWithContentsOfFile:(NSString *)f; 21 | 22 | @end 23 | -------------------------------------------------------------------------------- /QSKit/Classes/Images/NSImage+QSKit.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSImage+QSKit.m 3 | // Q Branch Standard Kit 4 | // 5 | // Created by Brent Simmons on 10/30/13. 6 | // Copyright (c) 2013 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | #import "NSImage+QSKit.h" 10 | 11 | 12 | @implementation NSImage (QSKit) 13 | 14 | 15 | + (void)qs_imageWithData:(NSData *)data imageResultBlock:(QSImageResultBlock)imageResultBlock { 16 | 17 | NSParameterAssert(data != nil); 18 | 19 | NSImage *image = [[NSImage alloc] initWithData:data]; 20 | 21 | QSCallBlockWithParameter(imageResultBlock, image); 22 | } 23 | 24 | 25 | + (instancetype)imageWithContentsOfFile:(NSString *)f { 26 | 27 | return [[self alloc] initWithContentsOfFile:f]; 28 | } 29 | 30 | @end 31 | -------------------------------------------------------------------------------- /QSKit/Classes/Images/QSImageRenderer.h: -------------------------------------------------------------------------------- 1 | // 2 | // QSImageRenderer.h 3 | // Q Branch Standard Kit 4 | // 5 | // Created by Brent Simmons on 10/23/13. 6 | // Copyright (c) 2013 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | 10 | @import Foundation; 11 | #if TARGET_OS_IPHONE 12 | @import UIKit; 13 | #else 14 | @import AppKit; 15 | #endif 16 | #import "QSPlatform.h" 17 | #import "QSBlocks.h" 18 | 19 | 20 | /*Used to render an image based on another image. (Thumbnails, for instance.) 21 | Thread-safe. Renders in a background queue. 22 | 23 | imageRenderBlock is responsible for dealing with graphics context; it returns the rendered image. 24 | 25 | imageResultBlock may be called on any thread. 26 | 27 | None of the parameters may be nil. 28 | */ 29 | 30 | 31 | @interface QSImageRenderer : NSObject 32 | 33 | - (instancetype)initWithRenderer:(QSImageRenderBlock)imageRenderBlock; 34 | 35 | - (void)renderImage:(QS_IMAGE *)originalImage imageResultBlock:(QSImageResultBlock)imageResultBlock; 36 | 37 | @end 38 | -------------------------------------------------------------------------------- /QSKit/Classes/Images/QSScaling.h: -------------------------------------------------------------------------------- 1 | // 2 | // QSScaling.h 3 | // Q Branch Standard Kit 4 | // 5 | // Created by Brent Simmons on 10/31/13. 6 | // Copyright (c) 2013 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | 10 | @import Foundation; 11 | 12 | 13 | CGSize QSScaledSizeForImageFittingSize(CGSize imageSize, CGSize constrainingSize); /*does a ceil on size.*/ 14 | 15 | CGFloat QSZoomScaleToFitSize(CGSize imageSize, CGSize constrainingSize); /*Aspect fit*/ 16 | CGFloat QSZoomScaleToFillSize(CGSize imageSize, CGSize constrainingSize); /*Aspect fill*/ 17 | -------------------------------------------------------------------------------- /QSKit/Classes/Images/UIImage+QSKit.h: -------------------------------------------------------------------------------- 1 | // 2 | // UIImage+QSKit.h 3 | // Q Branch Standard Kit 4 | // 5 | // Created by Brent Simmons on 10/23/13. 6 | // Copyright (c) 2013 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | 10 | @import UIKit; 11 | #import "QSBlocks.h" 12 | 13 | 14 | @interface UIImage (QSKit) 15 | 16 | 17 | /*Calls +imageWithData: in background queue. data and imageResultBlock must be non-nil.*/ 18 | 19 | + (void)qs_imageWithData:(NSData *)data imageResultBlock:(QSImageResultBlock)imageResultBlock; 20 | 21 | 22 | - (UIImage *)qs_imageTintedWithColor:(UIColor *)color; 23 | + (UIImage *)qs_imageNamed:(NSString *)imageName tintedWithColor:(UIColor *)color; 24 | 25 | 26 | @end 27 | -------------------------------------------------------------------------------- /QSKit/Classes/QSBlocks.h: -------------------------------------------------------------------------------- 1 | // 2 | // QSBlocks.h 3 | // Q Branch Standard Kit 4 | // 5 | // Created by Brent Simmons on 10/22/13. 6 | // Copyright (c) 2013 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | @import Foundation; 10 | #import "QSPlatform.h" 11 | 12 | 13 | typedef void (^QSVoidBlock)(void); 14 | 15 | typedef QSVoidBlock QSVoidCompletionBlock; 16 | 17 | typedef BOOL (^QSBoolBlock)(void); 18 | 19 | typedef void (^QSFetchResultsBlock)(NSArray *fetchedObjects); 20 | 21 | typedef void (^QSDataResultBlock)(NSData *d); 22 | 23 | typedef void (^QSObjectResultBlock)(id obj); 24 | 25 | typedef void (^QSBoolResultBlock)(BOOL flag); 26 | 27 | 28 | /*Images*/ 29 | 30 | typedef void (^QSImageResultBlock)(QS_IMAGE *image); 31 | 32 | typedef QS_IMAGE *(^QSImageRenderBlock)(QS_IMAGE *imageToRender); 33 | 34 | 35 | /*Calls on main thread. Ignores if nil.*/ 36 | 37 | void QSCallCompletionBlock(QSVoidCompletionBlock completion); 38 | 39 | void QSCallBlockWithParameter(QSObjectResultBlock block, id obj); 40 | 41 | void QSCallFetchResultsBlock(QSFetchResultsBlock fetchResultsBlock, NSArray *fetchedObjects); 42 | -------------------------------------------------------------------------------- /QSKit/Classes/QSConstants.h: -------------------------------------------------------------------------------- 1 | // 2 | // QSConstants.h 3 | // Q Branch Standard Kit 4 | // 5 | // Created by Brent Simmons on 10/21/13. 6 | // Copyright (c) 2013 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | @import Foundation; 10 | 11 | 12 | typedef NS_ENUM(NSUInteger, QSPosition) { 13 | QSPositionFirst, 14 | QSPositionMiddle, 15 | QSPositionLast, 16 | QSPositionOnly 17 | }; 18 | 19 | 20 | extern NSString *QSUniqueIDKey; //@"uniqueID" 21 | extern NSString *QSImageKey; //@"image" 22 | -------------------------------------------------------------------------------- /QSKit/Classes/QSConstants.m: -------------------------------------------------------------------------------- 1 | // 2 | // QSConstants.m 3 | // Q Branch Standard Kit 4 | // 5 | // Created by Brent Simmons on 10/21/13. 6 | // Copyright (c) 2013 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | #import "QSConstants.h" 10 | 11 | 12 | NSString *QSUniqueIDKey = @"uniqueID"; 13 | NSString *QSImageKey = @"image"; 14 | 15 | -------------------------------------------------------------------------------- /QSKit/Classes/QSMath.h: -------------------------------------------------------------------------------- 1 | // 2 | // QSMath.h 3 | // Q Branch Standard Kit 4 | // 5 | // Created by Brent Simmons on 10/31/13. 6 | // Copyright (c) 2013 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | 10 | @import Foundation; 11 | 12 | 13 | /*Does the right things with 32-bit/64-bit sizes.*/ 14 | 15 | CGFloat QSCeil(CGFloat f); 16 | CGFloat QSFloor(CGFloat f); 17 | CGFloat QSAbs(CGFloat f); 18 | 19 | -------------------------------------------------------------------------------- /QSKit/Classes/QSMath.m: -------------------------------------------------------------------------------- 1 | // 2 | // QSMath.m 3 | // Q Branch Standard Kit 4 | // 5 | // Created by Brent Simmons on 10/31/13. 6 | // Copyright (c) 2013 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | #import "QSMath.h" 10 | 11 | 12 | CGFloat QSCeil(CGFloat f) { 13 | 14 | #if __LP64__ 15 | return ceil(f); 16 | #else 17 | return ceilf(f); 18 | #endif 19 | } 20 | 21 | CGFloat QSAbs(CGFloat f) { 22 | 23 | #if __LP64__ 24 | return fabs(f); 25 | #else 26 | return fabsf(f); 27 | #endif 28 | } 29 | 30 | 31 | CGFloat QSFloor(CGFloat f) { 32 | 33 | #if __LP64__ 34 | return floor(f); 35 | #else 36 | return floorf(f); 37 | #endif 38 | } 39 | 40 | -------------------------------------------------------------------------------- /QSKit/Classes/QSPlatform.h: -------------------------------------------------------------------------------- 1 | // 2 | // QSPlatform.h 3 | // Q Branch Standard Kit 4 | // 5 | // Created by Brent Simmons on 10/23/13. 6 | // Copyright (c) 2013 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | 10 | @import Foundation; 11 | 12 | #if TARGET_OS_IPHONE 13 | 14 | @import UIKit; 15 | 16 | #define QS_IMAGE UIImage 17 | #define QS_COLOR UIColor 18 | #define QS_FONT UIFont 19 | #define QS_EDGE_INSETS UIEdgeInsets 20 | 21 | #define QSEdgeInsetsMake UIEdgeInsetsMake 22 | 23 | #else 24 | 25 | @import AppKit; 26 | 27 | #define QS_IMAGE NSImage 28 | #define QS_COLOR NSColor 29 | #define QS_FONT NSFont 30 | #define QS_EDGE_INSETS NSEdgeInsets 31 | 32 | #define QSEdgeInsetsMake NSEdgeInsetsMake 33 | 34 | #endif 35 | 36 | 37 | /*iOS: Documents/ directory. 38 | Mac: ~/Application Support/AppName/ 39 | 40 | If nil, gets appName from Info.plist -- @"CFBundleExecutable" key. 41 | It creates the folder and intermediate folders if necessary. 42 | (appName is ignored on iOS.) 43 | 44 | If something goes wrong it returns nil. The error is NSLogged. 45 | Panic, at that point, is strongly indicated.*/ 46 | 47 | NSString *QSDataFolder(NSString *appName); 48 | 49 | /*Path to file in folder specified by QSDataFolder. 50 | appName may be nil -- it's passed to QSDataFolder.*/ 51 | 52 | NSString *QSDataFile(NSString *appName, NSString *fileName); 53 | -------------------------------------------------------------------------------- /QSKit/Classes/QSPlatform.m: -------------------------------------------------------------------------------- 1 | // 2 | // QSPlatform.m 3 | // Q Branch Standard Kit 4 | // 5 | // Created by Brent Simmons on 10/23/13. 6 | // Copyright (c) 2013 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | 10 | #import "QSPlatform.h" 11 | 12 | 13 | NSString *QSDataFolder(NSString *appName) { 14 | 15 | #if TARGET_OS_IPHONE 16 | 17 | NSString *dataFolder = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0]; 18 | 19 | #else 20 | 21 | NSString *dataFolder = [NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSUserDomainMask, YES) objectAtIndex:0]; 22 | if (appName == nil) { 23 | appName = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleExecutable"]; 24 | } 25 | dataFolder = [dataFolder stringByAppendingPathComponent:appName]; 26 | 27 | #endif 28 | 29 | NSError *error = nil; 30 | 31 | if (![[NSFileManager defaultManager] createDirectoryAtPath:dataFolder withIntermediateDirectories:YES attributes:nil error:&error]) { 32 | NSLog(@"QSDataFolder error: %@", error); 33 | return nil; 34 | } 35 | 36 | return dataFolder; 37 | } 38 | 39 | 40 | NSString *QSDataFile(NSString *appName, NSString *fileName) { 41 | 42 | NSCParameterAssert(fileName != nil); 43 | 44 | NSString *dataFolder = QSDataFolder(appName); 45 | return [dataFolder stringByAppendingPathComponent:fileName]; 46 | } 47 | 48 | -------------------------------------------------------------------------------- /QSKit/Classes/SQLite/NSString+QSDatabase.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSString+QSDatabase.h 3 | // Q Branch Standard Kit 4 | // 5 | // Created by Brent Simmons on 10/23/13. 6 | // Copyright (c) 2013 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | @import Foundation; 10 | 11 | 12 | @interface NSString (QSDatabase) 13 | 14 | 15 | /*Returns @"(?, ?, ?)" -- where number of ? spots is specified by numberOfValues. 16 | numberOfValues should be greater than 0. Triggers an NSParameterAssert if not.*/ 17 | 18 | + (NSString *)qs_SQLValueListWithPlaceholders:(NSUInteger)numberOfValues; 19 | 20 | 21 | /*Returns @"(someColumn, anotherColumm, thirdColumn)" -- using passed-in keys. 22 | It's essential that you trust keys. They must not be user input. 23 | Triggers an NSParameterAssert if keys are empty.*/ 24 | 25 | + (NSString *)qs_SQLKeysListWithArray:(NSArray *)keys; 26 | 27 | 28 | /*Returns @"key1=?, key2=?" using passed-in keys. Keys must be trusted.*/ 29 | 30 | + (NSString *)qs_SQLKeyPlaceholderPairsWithKeys:(NSArray *)keys; 31 | 32 | 33 | @end 34 | -------------------------------------------------------------------------------- /QSKit/Classes/UIKit/QSAssets.h: -------------------------------------------------------------------------------- 1 | // 2 | // QSAssets.h 3 | // Q Branch Standard Kit 4 | // 5 | // Created by Brent Simmons on 10/31/13. 6 | // Copyright (c) 2013 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | 10 | @import Foundation; 11 | @import UIKit; 12 | @import AssetsLibrary; 13 | #import "QSBlocks.h" 14 | 15 | 16 | /*imageResultBlock will be called on main thread. Won't get called on error.*/ 17 | 18 | void QSAssetsMostRecentPhoto(QSImageResultBlock imageResultBlock); 19 | 20 | 21 | void QSSaveImageToAlbum(UIImage *image, NSString *albumName, ALAssetsLibraryAccessFailureBlock completionBlock); 22 | 23 | -------------------------------------------------------------------------------- /QSKit/Classes/UIKit/UIColor+QSKit.h: -------------------------------------------------------------------------------- 1 | // 2 | // UIColor+QSKit.h 3 | // Q Branch Standard Kit 4 | // 5 | // Created by Brent Simmons on 10/31/13. 6 | // Copyright (c) 2013 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | 10 | @import UIKit; 11 | 12 | 13 | @interface UIColor (QSKit) 14 | 15 | 16 | + (UIColor *)qs_colorWithHexString:(NSString *)hexString; 17 | 18 | 19 | @end 20 | -------------------------------------------------------------------------------- /QSKit/Classes/UIKit/UIColor+QSKit.m: -------------------------------------------------------------------------------- 1 | // 2 | // UIColor+QSKit.m 3 | // Q Branch Standard Kit 4 | // 5 | // Created by Brent Simmons on 10/31/13. 6 | // Copyright (c) 2013 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | #import "UIColor+QSKit.h" 10 | #import "NSString+QSKit.h" 11 | 12 | 13 | @implementation UIColor (QSKit) 14 | 15 | 16 | + (UIColor *)qs_colorWithHexString:(NSString *)hexString { 17 | 18 | QSRGBAComponents components = [hexString qs_rgbaComponents]; 19 | 20 | return [UIColor colorWithRed:components.red green:components.green blue:components.blue alpha:components.alpha]; 21 | } 22 | 23 | 24 | @end 25 | -------------------------------------------------------------------------------- /QSKit/Classes/UIKit/UIPanGestureRecognizer+QSKit.h: -------------------------------------------------------------------------------- 1 | // 2 | // UIPanGestureRecognizer+QSKit.h 3 | // Q Branch Standard Kit 4 | // 5 | // Created by Brent Simmons on 10/21/13. 6 | // Copyright (c) 2013 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | 10 | @import UIKit; 11 | 12 | 13 | @interface UIPanGestureRecognizer (QSKit) 14 | 15 | - (UIRectEdge)qs_leftOrRightDirectionInView:(UIView *)view commitThreshold:(CGFloat)commitThreshold commitVelocity:(CGFloat)commitVelocity; 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /QSKit/Classes/UIKit/UIPanGestureRecognizer+QSKit.m: -------------------------------------------------------------------------------- 1 | // 2 | // UIPanGestureRecognizer+QSKit.m 3 | // Q Branch Standard Kit 4 | // 5 | // Created by Brent Simmons on 10/21/13. 6 | // Copyright (c) 2013 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | #import "UIPanGestureRecognizer+QSKit.h" 10 | #import "QSConstants.h" 11 | #import "QSMath.h" 12 | 13 | 14 | @implementation UIPanGestureRecognizer (QSKit) 15 | 16 | 17 | - (UIRectEdge)qs_leftOrRightDirectionInView:(UIView *)view commitThreshold:(CGFloat)commitThreshold commitVelocity:(CGFloat)commitVelocity { 18 | 19 | CGPoint translation = [self translationInView:view]; 20 | CGFloat originX = translation.x; 21 | 22 | if (originX < commitThreshold) { 23 | return UIRectEdgeLeft; 24 | } 25 | 26 | CGFloat velocityX = [self velocityInView:view].x; 27 | BOOL velocityIsAboveCommitVelocity = QSAbs(velocityX) > commitVelocity; 28 | if (!velocityIsAboveCommitVelocity) { 29 | return UIRectEdgeRight; 30 | } 31 | 32 | if (velocityX < 0.0f) { 33 | return UIRectEdgeLeft; 34 | } 35 | 36 | return UIRectEdgeRight; 37 | } 38 | 39 | 40 | @end 41 | -------------------------------------------------------------------------------- /QSKit/Classes/UIKit/UIResponder+QSKit.h: -------------------------------------------------------------------------------- 1 | // 2 | // UIResponder+QSKit.h 3 | // Q Branch Standard Kit 4 | // 5 | // Created by Brent Simmons on 10/31/13. 6 | // Copyright (c) 2013 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | 10 | @import UIKit; 11 | 12 | 13 | @interface UIResponder (QSKit) 14 | 15 | 16 | /*Returns YES if it found a responder to call.*/ 17 | 18 | - (BOOL)qs_performSelectorViaResponderChain:(SEL)aSelector withObject:(id)anObject; 19 | 20 | @end 21 | -------------------------------------------------------------------------------- /QSKit/Classes/UIKit/UIResponder+QSKit.m: -------------------------------------------------------------------------------- 1 | // 2 | // UIResponder+QSKit.m 3 | // Q Branch Standard Kit 4 | // 5 | // Created by Brent Simmons on 10/31/13. 6 | // Copyright (c) 2013 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | 10 | #import "UIResponder+QSKit.h" 11 | 12 | 13 | @implementation UIResponder (QSKit) 14 | 15 | 16 | - (BOOL)qs_performSelectorViaResponderChain:(SEL)aSelector withObject:(id)anObject { 17 | UIResponder *nomad = self; 18 | while (nomad != nil) { 19 | if ([nomad respondsToSelector:aSelector]) { 20 | 21 | #pragma clang diagnostic push 22 | #pragma clang diagnostic ignored "-Warc-performSelector-leaks" 23 | [nomad performSelector:aSelector withObject:anObject]; 24 | #pragma clang diagnostic pop 25 | 26 | return YES; 27 | } 28 | nomad = [nomad nextResponder]; 29 | } 30 | return NO; 31 | } 32 | 33 | 34 | @end 35 | -------------------------------------------------------------------------------- /QSKit/Classes/UIKit/UIView+QSKit.h: -------------------------------------------------------------------------------- 1 | // 2 | // UIView+QSKit.h 3 | // Q Branch Standard Kit 4 | // 5 | // Created by Brent Simmons on 10/31/13. 6 | // Copyright (c) 2013 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | 10 | @import UIKit; 11 | 12 | 13 | @interface UIView (QSKit) 14 | 15 | 16 | - (UIView *)qs_firstSubviewOfClass:(Class)aClass; 17 | 18 | - (void)qs_setFrameIfNotEqual:(CGRect)rect; 19 | 20 | - (void)qs_addParallaxMotionEffectWithOffset:(CGSize)offset; 21 | 22 | - (void)qs_addFullSizeConstraintsForSubview:(UIView *)view; 23 | 24 | @end 25 | -------------------------------------------------------------------------------- /QSKit/Classes/UIKit/UIViewController+QSKit.h: -------------------------------------------------------------------------------- 1 | // 2 | // UIViewController+QSKit.h 3 | // Q Branch Standard Kit 4 | // 5 | // Created by Brent Simmons on 10/21/13. 6 | // Copyright (c) 2013 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | 10 | @import UIKit; 11 | 12 | 13 | @interface UIViewController (QSKit) 14 | 15 | - (BOOL)qs_hasChildViewController; 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /QSKit/Classes/UIKit/UIViewController+QSKit.m: -------------------------------------------------------------------------------- 1 | // 2 | // UIViewController+QSKit.m 3 | // Q Branch Standard Kit 4 | // 5 | // Created by Brent Simmons on 10/21/13. 6 | // Copyright (c) 2013 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | #import "UIViewController+QSKit.h" 10 | 11 | 12 | @implementation UIViewController (QSKit) 13 | 14 | 15 | - (BOOL)qs_hasChildViewController { 16 | return [self.childViewControllers count] > 0; 17 | } 18 | 19 | 20 | @end 21 | -------------------------------------------------------------------------------- /QSKit/Classes/Web/NSMutableURLRequest+QSKit.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSMutableURLRequest+QSKit.h 3 | // Q Branch Standard Kit 4 | // 5 | // Created by Brent Simmons on 11/6/13. 6 | // Copyright (c) 2013 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | 10 | @import Foundation; 11 | 12 | 13 | @interface NSMutableURLRequest (QSKit) 14 | 15 | 16 | - (void)qs_addBasicAuthorization:(NSString *)username password:(NSString *)password; /*Do this only with https.*/ 17 | 18 | 19 | @end 20 | -------------------------------------------------------------------------------- /QSKit/Classes/Web/NSMutableURLRequest+QSKit.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSMutableURLRequest+QSKit.m 3 | // Q Branch Standard Kit 4 | // 5 | // Created by Brent Simmons on 11/6/13. 6 | // Copyright (c) 2013 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | #import "NSMutableURLRequest+QSKit.h" 10 | #import "QSHTTPConstants.h" 11 | 12 | 13 | @implementation NSMutableURLRequest (QSKit) 14 | 15 | 16 | - (void)qs_addBasicAuthorization:(NSString *)username password:(NSString *)password { 17 | 18 | NSString *s = [NSString stringWithFormat:@"%@:%@", username, password]; 19 | NSData *d = [s dataUsingEncoding:NSUTF8StringEncoding]; 20 | NSString *base64EncodedString = [d base64EncodedStringWithOptions:0]; 21 | 22 | NSString *authorization = [NSString stringWithFormat:@"Basic %@", base64EncodedString]; 23 | [self setValue:authorization forHTTPHeaderField:QSHTTPRequestHeaderAuthorization]; 24 | } 25 | 26 | 27 | @end 28 | -------------------------------------------------------------------------------- /QSKit/Classes/Web/QSHTTPConditionalGetInfo.h: -------------------------------------------------------------------------------- 1 | // 2 | // QSHTTPConditionalGetInfo.h 3 | // Q Branch Standard Kit 4 | // 5 | // Created by Brent Simmons on 10/28/13. 6 | // Copyright (c) 2013 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | 10 | @import Foundation; 11 | 12 | 13 | /* http://fishbowl.pastiche.org/2002/10/21/http_conditional_get_for_rss_hackers/ */ 14 | 15 | 16 | @interface QSHTTPConditionalGetInfo : NSObject 17 | 18 | @property (nonatomic, strong) NSString *HTTPResponseLastModified; 19 | @property (nonatomic, strong) NSString *HTTPResponseETag; 20 | 21 | + (instancetype)conditionalGetInfoWithURLResponse:(NSHTTPURLResponse *)response; 22 | 23 | - (void)addRequestHeadersToURLRequest:(NSMutableURLRequest *)URLRequest; 24 | 25 | @end 26 | -------------------------------------------------------------------------------- /QSKit/Classes/Web/QSHTTPConditionalGetInfo.m: -------------------------------------------------------------------------------- 1 | // 2 | // QSHTTPConditionalGetInfo.m 3 | // Q Branch Standard Kit 4 | // 5 | // Created by Brent Simmons on 10/28/13. 6 | // Copyright (c) 2013 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | 10 | #import "QSHTTPConditionalGetInfo.h" 11 | #import "QSHTTPConstants.h" 12 | #import "NSObject+QSKit.h" 13 | 14 | 15 | @implementation QSHTTPConditionalGetInfo 16 | 17 | 18 | + (instancetype)conditionalGetInfoWithURLResponse:(NSHTTPURLResponse *)response { 19 | 20 | QSHTTPConditionalGetInfo *info = [self new]; 21 | 22 | info.HTTPResponseLastModified = [response allHeaderFields][QSHTTPResponseHeaderLastModified]; 23 | info.HTTPResponseETag = [response allHeaderFields][QSHTTPResponseHeaderEtag]; 24 | 25 | return info; 26 | } 27 | 28 | 29 | - (void)addRequestHeadersToURLRequest:(NSMutableURLRequest *)URLRequest { 30 | 31 | if (!QSIsEmpty(self.HTTPResponseLastModified)) { 32 | [URLRequest addValue:self.HTTPResponseLastModified forHTTPHeaderField:QSHTTPRequestHeaderIfModifiedSince]; 33 | } 34 | 35 | if (!QSIsEmpty(self.HTTPResponseETag)) { 36 | [URLRequest addValue:self.HTTPResponseETag forHTTPHeaderField:QSHTTPRequestHeaderIfNoneMatch]; 37 | } 38 | } 39 | 40 | @end 41 | -------------------------------------------------------------------------------- /QSKit/Classes/Web/QSHTTPConstants.m: -------------------------------------------------------------------------------- 1 | // 2 | // QSHTTPCodes.m 3 | // Q Branch Standard Kit 4 | // 5 | // Created by Brent Simmons on 10/25/13. 6 | // Copyright (c) 2013 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | #import "QSHTTPConstants.h" 10 | 11 | 12 | NSString *QSHTTPResponseHeaderLastModified = @"Last-Modified"; 13 | NSString *QSHTTPResponseHeaderEtag = @"ETag"; 14 | 15 | NSString *QSHTTPRequestHeaderIfModifiedSince = @"If-Modified-Since"; 16 | NSString *QSHTTPRequestHeaderIfNoneMatch = @"If-None-Match"; 17 | NSString *QSHTTPRequestHeaderUserAgent = @"User-Agent"; 18 | NSString *QSHTTPRequestHeaderAuthorization = @"Authorization"; 19 | NSString *QSHTTPRequestHeaderContentType = @"Content-Type"; 20 | 21 | NSString *QSPrefixHTTP = @"http://"; 22 | NSString *QSPrefixHTTPS = @"https://"; 23 | 24 | NSString *QSSchemeHTTP = @"http"; 25 | NSString *QSSchemeHTTPS = @"https"; 26 | 27 | NSString *QSHTTPMethodPost = @"POST"; 28 | NSString *QSHTTPMethodGet = @"GET"; 29 | NSString *QSHTTPMethodPut = @"PUT"; 30 | NSString *QSHTTPMethodDelete = @"DELETE"; 31 | 32 | NSString *QSHTTPContentTypeJSON = @"application/json"; 33 | 34 | -------------------------------------------------------------------------------- /QSKit/Classes/Web/QSMimeTypes.h: -------------------------------------------------------------------------------- 1 | // 2 | // QSMimeTypes.h 3 | // Q Branch Standard Kit 4 | // 5 | // Created by Brent Simmons on 10/25/13. 6 | // Copyright (c) 2013 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | 10 | @import Foundation; 11 | 12 | 13 | extern NSString *QSMimeTypePNG; // image/png 14 | extern NSString *QSMimeTypeJPEG; // image/jpeg 15 | extern NSString *QSMimeTypeGIF; // image/gif 16 | extern NSString *QSMimeTypeTIFF; // image/tiff 17 | 18 | NSString *QSMimeTypeForData(NSData *data); /*Will usually return nil. Recognizes a few image types.*/ 19 | NSString *QSMimeTypeForFile(NSString *path); /*Recognizes the same few image types QSMimeTypeForData recognizes.*/ 20 | 21 | BOOL QSMimeTypeIsImage(NSString *mimeType); 22 | BOOL QSMimeTypeIsTimeBasedMedia(NSString *mimeType); 23 | BOOL QSMimeTypeIsMedia(NSString *mimeType); /*Is image or time-based media (audio or video)*/ 24 | -------------------------------------------------------------------------------- /QSKit/Classes/XML/QSOPMLFeed.h: -------------------------------------------------------------------------------- 1 | // 2 | // QSOPMLFeed.h 3 | // Q Branch Standard Kit 4 | // 5 | // Created by Brent Simmons on 11/1/13. 6 | // Copyright (c) 2013 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | 10 | @import Foundation; 11 | 12 | 13 | @interface QSOPMLFeed : NSObject 14 | 15 | @property (nonatomic) NSString *title; 16 | @property (nonatomic) NSString *URL; 17 | @property (nonatomic) NSString *feedURL; 18 | 19 | 20 | + (instancetype)OPMLFeedWithXMLAttributes:(NSDictionary *)attributes; 21 | 22 | 23 | @end 24 | -------------------------------------------------------------------------------- /QSKit/Classes/XML/QSOPMLFolder.h: -------------------------------------------------------------------------------- 1 | // 2 | // QSOPMLFolder.h 3 | // Q Branch Standard Kit 4 | // 5 | // Created by Brent Simmons on 11/1/13. 6 | // Copyright (c) 2013 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | 10 | @import Foundation; 11 | 12 | 13 | @interface QSOPMLFolder : NSObject 14 | 15 | @property (nonatomic) NSString *title; 16 | 17 | + (instancetype)OPMLFolderWithXMLAttributes:(NSDictionary *)attributes; 18 | 19 | 20 | @end 21 | -------------------------------------------------------------------------------- /QSKit/Classes/XML/QSOPMLFolder.m: -------------------------------------------------------------------------------- 1 | // 2 | // QSOPMLFolder.m 3 | // Q Branch Standard Kit 4 | // 5 | // Created by Brent Simmons on 11/1/13. 6 | // Copyright (c) 2013 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | #import "QSOPMLFolder.h" 10 | #import "NSString+QSKit.h" 11 | #import "NSDictionary+QSKit.h" 12 | #import "NSMutableDictionary+QSKit.h" 13 | 14 | 15 | @implementation QSOPMLFolder 16 | 17 | 18 | #pragma mark - Class Methods 19 | 20 | + (instancetype)OPMLFolderWithXMLAttributes:(NSDictionary *)attributes { 21 | 22 | QSOPMLFolder *folder = [QSOPMLFolder new]; 23 | 24 | /*OPML doesn't always have properly-cased keys*/ 25 | 26 | NSString *title = [attributes qs_objectForCaseInsensitiveKey:@"title"]; 27 | if (QSStringIsEmpty(title)) { 28 | title = [attributes qs_objectForCaseInsensitiveKey:@"text"]; 29 | } 30 | 31 | folder.title = title; 32 | 33 | return folder; 34 | } 35 | 36 | 37 | #pragma mark - Debugging 38 | 39 | - (NSString *)description { 40 | 41 | NSString *s = [super description]; 42 | return [NSString stringWithFormat:@"%@ - %@", s, self.title]; 43 | } 44 | 45 | 46 | - (NSDictionary *)dictionaryRepresentation { 47 | 48 | NSMutableDictionary *d = [NSMutableDictionary new]; 49 | 50 | [d qs_safeSetObject:self.title forKey:@"title"]; 51 | 52 | return d; 53 | } 54 | 55 | 56 | @end 57 | -------------------------------------------------------------------------------- /QSKit/Classes/XML/QSOPMLParser.h: -------------------------------------------------------------------------------- 1 | // 2 | // QSOPMLParser.h 3 | // Q Branch Standard Kit 4 | // 5 | // Created by Brent Simmons on 11/1/13. 6 | // Copyright (c) 2013 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | 10 | @import Foundation; 11 | 12 | 13 | /*Creates a tree of QSNode. The representedObject for each node is either QSOPMLFolder or QSOPMLFeed.*/ 14 | 15 | @class QSNode; 16 | 17 | 18 | @interface QSOPMLParser : NSObject 19 | 20 | - (void)parseOPMLData:(NSData *)data; 21 | - (void)finishParsing; 22 | 23 | @property (nonatomic, readonly) QSNode *rootNode; 24 | 25 | @end 26 | -------------------------------------------------------------------------------- /QSKit/Classes/XML/QSOPMLParserFeedsOnly.h: -------------------------------------------------------------------------------- 1 | // 2 | // QSOPMLParserFeedsOnly.h 3 | // Q Branch Standard Kit 4 | // 5 | // Created by Brent Simmons on 11/1/13. 6 | // Copyright (c) 2013 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | 10 | @import Foundation; 11 | 12 | 13 | /*Parses OPML but gets just the feeds. Puts them into a flat array.*/ 14 | 15 | @interface QSOPMLParserFeedsOnly : NSObject 16 | 17 | 18 | - (void)parseOPMLData:(NSData *)data; 19 | - (void)finishParsing; 20 | 21 | @property (nonatomic, readonly) NSArray *feeds; /*QSOPMLFeed objects.*/ 22 | 23 | 24 | @end 25 | -------------------------------------------------------------------------------- /QSKit/QSKit.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /QSKit/QSKitTests/NSArrayTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSArrayTests.m 3 | // Q Branch Standard Kit 4 | // 5 | // Created by Brent Simmons on 10/31/13. 6 | // Copyright (c) 2013 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "NSArray+QSKit.h" 11 | 12 | 13 | @interface NSArrayTests : XCTestCase 14 | @end 15 | 16 | @implementation NSArrayTests 17 | 18 | 19 | - (void)testSafeObjectAtIndex { 20 | 21 | NSArray *testArray = @[@"first", @"second", @"third", @"fourth"]; 22 | 23 | XCTAssertNil([testArray qs_safeObjectAtIndex:4]); 24 | XCTAssertNotNil([testArray qs_safeObjectAtIndex:3]); 25 | XCTAssertNotNil([testArray qs_safeObjectAtIndex:0]); 26 | 27 | XCTAssertTrue([testArray qs_safeObjectAtIndex:3] == testArray[3]); 28 | 29 | testArray = @[]; 30 | 31 | XCTAssertNil([testArray qs_safeObjectAtIndex:0]); 32 | 33 | NSInteger anIndex = -1; 34 | XCTAssertNoThrow([testArray qs_safeObjectAtIndex:(NSUInteger)anIndex]); 35 | XCTAssertNil([testArray qs_safeObjectAtIndex:(NSUInteger)anIndex]); 36 | } 37 | 38 | @end 39 | -------------------------------------------------------------------------------- /QSKit/QSKitTests/NSAttributedStringTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSAttributedStringTests.m 3 | // Q Branch Standard Kit 4 | // 5 | // Created by Brent Simmons on 10/31/13. 6 | // Copyright (c) 2013 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "NSAttributedString+QSKit.h" 11 | 12 | 13 | @interface NSAttributedStringTests : XCTestCase 14 | @end 15 | 16 | 17 | @implementation NSAttributedStringTests 18 | 19 | 20 | - (void)testQSAttributedStringWithText { 21 | 22 | NSString *text = @"Animals were hiding behind the rocks, except the little fish."; 23 | NSFont *font = [NSFont systemFontOfSize:18.0f]; 24 | NSColor *color = [NSColor greenColor]; 25 | 26 | NSAttributedString *attributedString = [NSAttributedString qs_attributedStringWithText:text font:font color:color kerning:YES]; 27 | XCTAssertNotNil(attributedString); 28 | 29 | NSDictionary *attributes = [attributedString attributesAtIndex:0 effectiveRange:nil]; 30 | id kernAttribute = attributes[NSKernAttributeName]; 31 | XCTAssertEqual(kernAttribute, [NSNull null]); 32 | } 33 | 34 | @end 35 | -------------------------------------------------------------------------------- /QSKit/QSKitTests/NSDateTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSDateTests.m 3 | // Q Branch Standard Kit 4 | // 5 | // Created by Brent Simmons on 11/1/13. 6 | // Copyright (c) 2013 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "NSDate+QSKit.h" 11 | 12 | 13 | @interface NSDateTests : XCTestCase 14 | @end 15 | 16 | 17 | @implementation NSDateTests 18 | 19 | 20 | - (void)testQSDateWithNumberOfDaysInThePast { 21 | 22 | NSUInteger numberOfDays = 100; 23 | NSTimeInterval expectedTimeInterval = 60 * 60 * 24 * numberOfDays; 24 | NSDate *actualDate = [NSDate qs_dateWithNumberOfDaysInThePast:numberOfDays]; 25 | NSTimeInterval actualTimeInterval = [actualDate timeIntervalSinceNow]; 26 | 27 | XCTAssertEqualWithAccuracy(-expectedTimeInterval, actualTimeInterval, 60 * 60 * 2); 28 | } 29 | 30 | 31 | - (void)testQSUnixTimestampStringWithNoDecimal { 32 | 33 | NSDate *d = [NSDate dateWithTimeIntervalSince1970:1383339107]; 34 | NSString *s = [d qs_unixTimestampStringWithNoDecimal]; 35 | 36 | XCTAssertEqualObjects(s, @"1383339107"); 37 | 38 | d = [NSDate dateWithTimeIntervalSince1970:500]; 39 | s = [d qs_unixTimestampStringWithNoDecimal]; 40 | 41 | XCTAssertEqualObjects(s, @"500"); 42 | 43 | d = [NSDate dateWithTimeIntervalSince1970:2343349107]; 44 | s = [d qs_unixTimestampStringWithNoDecimal]; 45 | 46 | XCTAssertEqualObjects(s, @"2343349107"); 47 | 48 | } 49 | 50 | @end 51 | -------------------------------------------------------------------------------- /QSKit/QSKitTests/NSMutableArrayTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSMutableArrayTests.m 3 | // Q Branch Standard Kit 4 | // 5 | // Created by Brent Simmons on 10/31/13. 6 | // Copyright (c) 2013 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "NSMutableArray+QSKit.h" 11 | 12 | 13 | @interface NSMutableArrayTests : XCTestCase 14 | @end 15 | 16 | @implementation NSMutableArrayTests 17 | 18 | 19 | - (void)testQSSafeAddObject { 20 | 21 | NSMutableArray *s = [NSMutableArray new]; 22 | 23 | XCTAssertNoThrow([s qs_safeAddObject:nil]); 24 | 25 | NSString *foo = @"Foo"; 26 | XCTAssertNoThrow([s qs_safeAddObject:foo]); 27 | XCTAssertTrue([s containsObject:foo]); 28 | } 29 | 30 | @end 31 | -------------------------------------------------------------------------------- /QSKit/QSKitTests/NSMutableDictionaryTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSMutableDictionaryTests.m 3 | // Q Branch Standard Kit 4 | // 5 | // Created by Brent Simmons on 10/31/13. 6 | // Copyright (c) 2013 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "NSMutableDictionary+QSKit.h" 11 | 12 | 13 | @interface NSMutableDictionaryTests : XCTestCase 14 | @end 15 | 16 | 17 | @implementation NSMutableDictionaryTests 18 | 19 | 20 | - (void)testQSSafeSetObject { 21 | 22 | NSMutableDictionary *d = [NSMutableDictionary new]; 23 | 24 | XCTAssertNoThrow([d qs_safeSetObject:@"foo" forKey:nil]); 25 | XCTAssertNoThrow([d qs_safeSetObject:nil forKey:nil]); 26 | XCTAssertNoThrow([d qs_safeSetObject:nil forKey:@"bar"]); 27 | XCTAssertNoThrow([d qs_safeSetObject:@"foo" forKey:@"bar"]); 28 | XCTAssertNotNil(d[@"bar"]); 29 | } 30 | 31 | @end 32 | -------------------------------------------------------------------------------- /QSKit/QSKitTests/NSMutableSetTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSMutableSetTests.m 3 | // Q Branch Standard Kit 4 | // 5 | // Created by Brent Simmons on 10/31/13. 6 | // Copyright (c) 2013 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "NSMutableSet+QSKit.h" 11 | 12 | 13 | @interface NSMutableSetTests : XCTestCase 14 | @end 15 | 16 | 17 | @implementation NSMutableSetTests 18 | 19 | 20 | - (void)testQSSafeAddObject { 21 | 22 | NSMutableSet *s = [NSMutableSet new]; 23 | 24 | XCTAssertNoThrow([s qs_safeAddObject:nil]); 25 | 26 | NSString *foo = @"Foo"; 27 | XCTAssertNoThrow([s qs_safeAddObject:foo]); 28 | XCTAssertTrue([s containsObject:foo]); 29 | } 30 | 31 | @end 32 | -------------------------------------------------------------------------------- /QSKit/QSKitTests/NSStringQSDatabaseTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSStringQSDatabaseTests.m 3 | // Q Branch Standard Kit 4 | // 5 | // Created by Brent Simmons on 11/1/13. 6 | // Copyright (c) 2013 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "NSString+QSDatabase.h" 11 | 12 | 13 | @interface NSStringQSDatabaseTests : XCTestCase 14 | @end 15 | 16 | 17 | @implementation NSStringQSDatabaseTests 18 | 19 | 20 | - (void)testExample { 21 | 22 | XCTAssertThrows([NSString qs_SQLValueListWithPlaceholders:0]); 23 | 24 | XCTAssertNoThrow([NSString qs_SQLValueListWithPlaceholders:1]); 25 | XCTAssertNoThrow([NSString qs_SQLValueListWithPlaceholders:2]); 26 | XCTAssertNoThrow([NSString qs_SQLValueListWithPlaceholders:100]); 27 | 28 | XCTAssertEqualObjects([NSString qs_SQLValueListWithPlaceholders:1], @"(?)"); 29 | XCTAssertEqualObjects([NSString qs_SQLValueListWithPlaceholders:2], @"(?, ?)"); 30 | XCTAssertEqualObjects([NSString qs_SQLValueListWithPlaceholders:3], @"(?, ?, ?)"); 31 | XCTAssertEqualObjects([NSString qs_SQLValueListWithPlaceholders:10], @"(?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"); 32 | } 33 | 34 | @end 35 | -------------------------------------------------------------------------------- /QSKit/QSKitTests/QSKitTests-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | co.qbranch.${PRODUCT_NAME:rfc1034identifier} 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundlePackageType 14 | BNDL 15 | CFBundleShortVersionString 16 | 1.0 17 | CFBundleSignature 18 | ???? 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /QSKit/QSKitTests/QSOPMLTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // QSOPMLTests.m 3 | // Q Branch Standard Kit 4 | // 5 | // Created by Brent Simmons on 11/1/13. 6 | // Copyright (c) 2013 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "QSOPMLParser.h" 11 | #import "QSNode.h" 12 | 13 | 14 | @interface QSOPMLTests : XCTestCase 15 | @end 16 | 17 | 18 | @implementation QSOPMLTests 19 | 20 | 21 | - (void)testOPMLParser { 22 | 23 | NSString *f = [[NSBundle bundleForClass:[self class]] pathForResource:@"subscriptions" ofType:@"opml"]; 24 | NSData *d = [NSData dataWithContentsOfFile:f]; 25 | 26 | QSOPMLParser *parser = [QSOPMLParser new]; 27 | [parser parseOPMLData:d]; 28 | [parser finishParsing]; 29 | 30 | NSDictionary *parsedDictionary = [parser.rootNode dictionaryRepresentation]; 31 | 32 | NSString *plistPath = [[NSBundle bundleForClass:[self class]] pathForResource:@"subscriptions" ofType:@"plist"]; 33 | NSDictionary *expectedDictionary = [NSDictionary dictionaryWithContentsOfFile:plistPath]; 34 | 35 | XCTAssertEqualObjects(parsedDictionary, expectedDictionary); 36 | } 37 | 38 | 39 | @end 40 | -------------------------------------------------------------------------------- /QSKit/QSKitTests/QSPlatformTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // QSPlatformTests.m 3 | // Q Branch Standard Kit 4 | // 5 | // Created by Brent Simmons on 10/31/13. 6 | // Copyright (c) 2013 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "QSPlatform.h" 11 | 12 | 13 | @interface QSPlatformTests : XCTestCase 14 | @end 15 | 16 | 17 | @implementation QSPlatformTests 18 | 19 | 20 | - (void)testQSDataFolder { 21 | 22 | NSString *dataFolder = QSDataFolder(@"QSKit"); 23 | XCTAssertNotNil(dataFolder); 24 | 25 | #if !TARGET_OS_IPHONE 26 | XCTAssertTrue([dataFolder hasSuffix:@"/Library/Application Support/QSKit"]); 27 | #endif 28 | 29 | } 30 | 31 | @end 32 | -------------------------------------------------------------------------------- /QSKit/QSKitTests/TestFiles/appstore.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brentsimmons/Vesper/2b05a1ccd2629c1eb757620186823418ac68bee6/QSKit/QSKitTests/TestFiles/appstore.png -------------------------------------------------------------------------------- /QSKit/QSKitTests/TestFiles/background.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brentsimmons/Vesper/2b05a1ccd2629c1eb757620186823418ac68bee6/QSKit/QSKitTests/TestFiles/background.jpg -------------------------------------------------------------------------------- /QSKit/QSKitTests/TestFiles/qbranch.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brentsimmons/Vesper/2b05a1ccd2629c1eb757620186823418ac68bee6/QSKit/QSKitTests/TestFiles/qbranch.png -------------------------------------------------------------------------------- /QSKit/QSKitTests/TestFiles/test.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brentsimmons/Vesper/2b05a1ccd2629c1eb757620186823418ac68bee6/QSKit/QSKitTests/TestFiles/test.gif -------------------------------------------------------------------------------- /QSKit/QSKitTests/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Vesper 2 | 3 | Vesper is a note-taking app for iOS by Q Branch. 4 | 5 | This is presented as historical artifact rather than as living project. I don’t expect to make any further code changes. 6 | 7 | For more notes, see [Vesper Open Source #3: the iOS App](http://inessential.com/2016/12/21/vesper_open_source_3_the_ios_app). -------------------------------------------------------------------------------- /Vesper Tests/Resources/Vesper-Notes.sqlite3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brentsimmons/Vesper/2b05a1ccd2629c1eb757620186823418ac68bee6/Vesper Tests/Resources/Vesper-Notes.sqlite3 -------------------------------------------------------------------------------- /Vesper Tests/Vesper Tests-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | co.ranchero.${PRODUCT_NAME:rfc1034identifier} 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundlePackageType 14 | BNDL 15 | CFBundleShortVersionString 16 | 1.0 17 | CFBundleSignature 18 | ???? 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /Vesper Tests/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /Vesper.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Vesper/Classes/CheckmarkTableViewCell.h: -------------------------------------------------------------------------------- 1 | // 2 | // CheckmarkTableViewCell.h 3 | // Vesper 4 | // 5 | // Created by Brent Simmons on 9/19/14. 6 | // Copyright (c) 2014 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | 10 | @import UIKit; 11 | 12 | @interface CheckmarkTableViewCell : UITableViewCell 13 | 14 | 15 | - (instancetype)initWithLabel:(NSString *)label; 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /Vesper/Classes/CreditsListView.h: -------------------------------------------------------------------------------- 1 | // 2 | // CreditsListView.h 3 | // Vesper 4 | // 5 | // Created by Brent Simmons on 7/24/14. 6 | // Copyright (c) 2014 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface CreditsListView : UIView 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /Vesper/Classes/CreditsPosterView.h: -------------------------------------------------------------------------------- 1 | // 2 | // CreditsPosterView.h 3 | // Vesper 4 | // 5 | // Created by Brent Simmons on 7/23/14. 6 | // Copyright (c) 2014 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | @import UIKit; 10 | 11 | 12 | @interface CreditsPosterView : UIView 13 | 14 | @end 15 | -------------------------------------------------------------------------------- /Vesper/Classes/FMDatabase+Extras.h: -------------------------------------------------------------------------------- 1 | /* 2 | FMDatabase+Extras.h 3 | NetNewsWire 4 | 5 | Created by Brent Simmons on 5/30/06. 6 | Copyright 2006 Ranchero Software. All rights reserved. 7 | */ 8 | 9 | 10 | #import 11 | #import "FMDatabase.h" 12 | 13 | 14 | @interface FMDatabase (Extras) 15 | 16 | 17 | + (FMDatabase *)openDatabaseWithPath:(NSString *)f; 18 | 19 | 20 | @end 21 | 22 | -------------------------------------------------------------------------------- /Vesper/Classes/FMDatabase+Extras.m: -------------------------------------------------------------------------------- 1 | /* 2 | FMDatabase+Extras.m 3 | NetNewsWire 4 | 5 | Created by Brent Simmons on 5/30/06. 6 | Copyright 2006 Ranchero Software. All rights reserved. 7 | */ 8 | 9 | 10 | #import "FMDatabase+Extras.h" 11 | 12 | 13 | @implementation FMDatabase (Extras) 14 | 15 | 16 | + (FMDatabase *)openDatabaseWithPath:(NSString *)f { 17 | FMDatabase *fmdb = [self databaseWithPath:f]; 18 | if (!fmdb || ![fmdb open]) 19 | return nil; 20 | return fmdb; 21 | } 22 | 23 | 24 | @end 25 | 26 | -------------------------------------------------------------------------------- /Vesper/Classes/FMDatabaseAdditions.h: -------------------------------------------------------------------------------- 1 | // 2 | // FMDatabaseAdditions.h 3 | // fmkit 4 | // 5 | // Created by August Mueller on 10/30/05. 6 | // Copyright 2005 Flying Meat Inc.. All rights reserved. 7 | // 8 | 9 | #import 10 | @interface FMDatabase (FMDatabaseAdditions) 11 | 12 | 13 | - (int)intForQuery:(NSString*)objs, ...; 14 | - (long)longForQuery:(NSString*)objs, ...; 15 | - (BOOL)boolForQuery:(NSString*)objs, ...; 16 | - (double)doubleForQuery:(NSString*)objs, ...; 17 | - (NSString*)stringForQuery:(NSString*)objs, ...; 18 | - (NSData*)dataForQuery:(NSString*)objs, ...; 19 | - (NSDate*)dateForQuery:(NSString*)objs, ...; 20 | 21 | // Notice that there's no dataNoCopyForQuery:. 22 | // That would be a bad idea, because we close out the result set, and then what 23 | // happens to the data that we just didn't copy? Who knows, not I. 24 | 25 | 26 | - (BOOL)tableExists:(NSString*)tableName; 27 | - (FMResultSet*)getSchema; 28 | - (FMResultSet*)getTableSchema:(NSString*)tableName; 29 | 30 | - (BOOL)columnExists:(NSString*)columnName inTableWithName:(NSString*)tableName; 31 | 32 | - (BOOL)validateSQL:(NSString*)sql error:(NSError**)error; 33 | 34 | // deprecated - use columnExists:inTableWithName: instead. 35 | - (BOOL)columnExists:(NSString*)tableName columnName:(NSString*)columnName __attribute__ ((deprecated)); 36 | 37 | @end 38 | -------------------------------------------------------------------------------- /Vesper/Classes/FMDatabaseQueue.h: -------------------------------------------------------------------------------- 1 | // 2 | // FMDatabasePool.h 3 | // fmdb 4 | // 5 | // Created by August Mueller on 6/22/11. 6 | // Copyright 2011 Flying Meat Inc. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "sqlite3.h" 11 | 12 | @class FMDatabase; 13 | 14 | @interface FMDatabaseQueue : NSObject { 15 | NSString *_path; 16 | dispatch_queue_t _queue; 17 | FMDatabase *_db; 18 | } 19 | 20 | @property (atomic, retain) NSString *path; 21 | 22 | + (id)databaseQueueWithPath:(NSString*)aPath; 23 | - (id)initWithPath:(NSString*)aPath; 24 | - (void)close; 25 | 26 | - (void)inDatabase:(void (^)(FMDatabase *db))block; 27 | 28 | - (void)inTransaction:(void (^)(FMDatabase *db, BOOL *rollback))block; 29 | - (void)inDeferredTransaction:(void (^)(FMDatabase *db, BOOL *rollback))block; 30 | 31 | #if SQLITE_VERSION_NUMBER >= 3007000 32 | // NOTE: you can not nest these, since calling it will pull another database out of the pool and you'll get a deadlock. 33 | // If you need to nest, use FMDatabase's startSavePointWithName:error: instead. 34 | - (NSError*)inSavePoint:(void (^)(FMDatabase *db, BOOL *rollback))block; 35 | #endif 36 | 37 | @end 38 | 39 | -------------------------------------------------------------------------------- /Vesper/Classes/FMResultSet+RSExtras.h: -------------------------------------------------------------------------------- 1 | // 2 | // FMResultSet+RSExtras.h 3 | // Vesper 4 | // 5 | // Created by Brent Simmons on 2/19/13. 6 | // Copyright (c) 2013 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | #import "FMResultSet.h" 10 | 11 | 12 | @interface FMResultSet (RSExtras) 13 | 14 | @end 15 | -------------------------------------------------------------------------------- /Vesper/Classes/FMResultSet+RSExtras.m: -------------------------------------------------------------------------------- 1 | // 2 | // FMResultSet+RSExtras.m 3 | // Vesper 4 | // 5 | // Created by Brent Simmons on 2/19/13. 6 | // Copyright (c) 2013 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | #import "FMResultSet+RSExtras.h" 10 | 11 | 12 | @implementation FMResultSet (RSExtras) 13 | 14 | 15 | - (id)valueForKey:(NSString *)key { 16 | return [self objectForColumnName:key]; 17 | } 18 | 19 | 20 | @end 21 | -------------------------------------------------------------------------------- /Vesper/Classes/NSString+RSExtras.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSString+RSExtras.h 3 | // Vesper 4 | // 5 | // Created by Brent Simmons on 12/4/12. 6 | // Copyright (c) 2012 Ranchero Software. All rights reserved. 7 | // 8 | 9 | 10 | @import Foundation; 11 | 12 | 13 | @interface NSString (RSExtras) 14 | 15 | 16 | - (NSString *)rs_firstLine; /*Text until cr or lf.*/ 17 | - (NSUInteger)rs_indexOfCROrLF; 18 | 19 | - (BOOL)rs_hasNonWhitespaceAndNewlineCharacters; 20 | 21 | @end 22 | -------------------------------------------------------------------------------- /Vesper/Classes/NSString+RSExtras.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSString+RSExtras.m 3 | // Vesper 4 | // 5 | // Created by Brent Simmons on 12/4/12. 6 | // Copyright (c) 2012 Ranchero Software. All rights reserved. 7 | // 8 | 9 | #import "NSString+RSExtras.h" 10 | 11 | 12 | @implementation NSString (RSExtras) 13 | 14 | 15 | - (NSString *)rs_firstLine { 16 | 17 | NSScanner *scanner = [NSScanner scannerWithString:self]; 18 | [scanner setCharactersToBeSkipped:nil]; 19 | NSString *title = nil; 20 | [scanner scanUpToCharactersFromSet:[NSCharacterSet characterSetWithCharactersInString:@"\n\r"] intoString:&title]; 21 | return title; 22 | } 23 | 24 | 25 | - (BOOL)rs_hasNonWhitespaceAndNewlineCharacters { 26 | 27 | NSUInteger lengthOfText = [self length]; 28 | NSUInteger i = 0; 29 | 30 | for (i = 0; i < lengthOfText; i++) { 31 | unichar ch = [self characterAtIndex:i]; 32 | if (![[NSCharacterSet whitespaceAndNewlineCharacterSet] characterIsMember:ch]) 33 | return YES; 34 | } 35 | 36 | return NO; 37 | } 38 | 39 | 40 | - (NSUInteger)rs_indexOfCROrLF { 41 | 42 | NSRange rangeOfCR = [self rangeOfString:@"\r"]; 43 | NSRange rangeOfLF = [self rangeOfString:@"\n"]; 44 | 45 | if (rangeOfCR.length == 0 && rangeOfLF.length == 0) 46 | return NSNotFound; 47 | NSUInteger index = MIN(rangeOfCR.location, rangeOfLF.location); 48 | return index; 49 | } 50 | 51 | 52 | @end 53 | 54 | -------------------------------------------------------------------------------- /Vesper/Classes/QSAPIObject.h: -------------------------------------------------------------------------------- 1 | // 2 | // QSAPIObject.h 3 | // Vesper 4 | // 5 | // Created by Brent Simmons on 3/6/14. 6 | // Copyright (c) 2014 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | 10 | @import Foundation; 11 | 12 | 13 | /*JSON representations are NSDictionaries.*/ 14 | 15 | 16 | @protocol QSAPIObject 17 | 18 | @required 19 | 20 | 21 | /*Methods may return nil, but it's strongly discouraged. 22 | Methods may be called on any thread. The responsibility for thread 23 | safety is handled outside of the object implementing this protocol.*/ 24 | 25 | - (NSDictionary *)JSONRepresentation; 26 | 27 | + (instancetype)objectWithJSONRepresentation:(NSDictionary *)JSONRepresentation; 28 | 29 | @end 30 | 31 | 32 | @interface QSAPIObject : NSObject 33 | 34 | 35 | + (NSArray *)JSONArrayWithObjects:(NSArray *)objects; 36 | 37 | + (NSArray *)objectsWithJSONArray:(NSArray *)JSONArray class:(Class)class; 38 | 39 | + (void)objectsWithJSONArray:(NSArray *)JSONArray class:(Class)class resultsBlock:(QSFetchResultsBlock)resultsBlock; 40 | 41 | 42 | @end 43 | 44 | 45 | -------------------------------------------------------------------------------- /Vesper/Classes/QSAPIObject.m: -------------------------------------------------------------------------------- 1 | // 2 | // QSAPIObject.m 3 | // Vesper 4 | // 5 | // Created by Brent Simmons on 3/6/14. 6 | // Copyright (c) 2014 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | #import "QSAPIObject.h" 10 | #import "NSArray+QSKit.h" 11 | 12 | 13 | @implementation QSAPIObject 14 | 15 | 16 | + (NSArray *)JSONArrayWithObjects:(NSArray *)objects { 17 | 18 | return [objects qs_map:^id(id obj) { 19 | return [obj JSONRepresentation]; 20 | }]; 21 | } 22 | 23 | + (NSArray *)objectsWithJSONArray:(NSArray *)JSONArray class:(Class)class { 24 | 25 | return [JSONArray qs_map:^id(NSDictionary *oneJSONDictionary) { 26 | return [class objectWithJSONRepresentation:oneJSONDictionary]; 27 | }]; 28 | } 29 | 30 | 31 | + (void)objectsWithJSONArray:(NSArray *)JSONArray class:(Class)class resultsBlock:(QSFetchResultsBlock)resultsBlock { 32 | 33 | dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), ^{ 34 | 35 | NSArray *objects = [self objectsWithJSONArray:JSONArray class:class]; 36 | QSCallFetchResultsBlock(resultsBlock, objects); 37 | }); 38 | } 39 | 40 | 41 | @end 42 | -------------------------------------------------------------------------------- /Vesper/Classes/QSBlocks.m: -------------------------------------------------------------------------------- 1 | // 2 | // QSBlocks.m 3 | // Vesper 4 | // 5 | // Created by Brent Simmons on 3/10/14. 6 | // Copyright (c) 2014 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | #import "QSBlocks.h" 10 | 11 | 12 | void QSCallCompletionBlock(QSVoidCompletionBlock completion) { 13 | 14 | if (!completion) { 15 | return; 16 | } 17 | 18 | dispatch_async(dispatch_get_main_queue(), ^{ 19 | @autoreleasepool { 20 | completion(); 21 | } 22 | }); 23 | } 24 | 25 | 26 | void QSCallBlockWithParameter(QSObjectResultBlock block, id obj) { 27 | 28 | if (!block) { 29 | return; 30 | } 31 | 32 | dispatch_async(dispatch_get_main_queue(), ^{ 33 | @autoreleasepool { 34 | block(obj); 35 | } 36 | }); 37 | } 38 | 39 | 40 | void QSCallFetchResultsBlock(QSFetchResultsBlock fetchResultsBlock, NSArray *fetchedObjects) { 41 | 42 | QSCallBlockWithParameter(fetchResultsBlock, fetchedObjects); 43 | } 44 | 45 | -------------------------------------------------------------------------------- /Vesper/Classes/QSDataObject.h: -------------------------------------------------------------------------------- 1 | // 2 | // QSDataObject.h 3 | // Vesper 4 | // 5 | // Created by Brent Simmons on 3/21/14. 6 | // Copyright (c) 2014 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | 10 | 11 | @protocol QSDataObject 12 | 13 | @optional 14 | 15 | //- (void)didFetch; /*Called right after object is created from the database.*/ 16 | 17 | @end 18 | 19 | -------------------------------------------------------------------------------- /Vesper/Classes/QSDataObjectDeleter.h: -------------------------------------------------------------------------------- 1 | // 2 | // QSDataObjectDeleter.h 3 | // Vesper 4 | // 5 | // Created by Brent Simmons on 3/8/14. 6 | // Copyright (c) 2014 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | 10 | @import Foundation; 11 | 12 | 13 | @class QSObjectModel; 14 | @class QSDatabaseQueue; 15 | 16 | 17 | @interface QSDataObjectDeleter : NSObject 18 | 19 | 20 | + (void)deleteObjectSpecifiers:(NSArray *)objectSpecifiers objectModel:(QSObjectModel *)objectModel queue:(QSDatabaseQueue *)queue; 21 | 22 | 23 | @end 24 | -------------------------------------------------------------------------------- /Vesper/Classes/QSDataObjectDeleter.m: -------------------------------------------------------------------------------- 1 | // 2 | // QSDataObjectDeleter.m 3 | // Vesper 4 | // 5 | // Created by Brent Simmons on 3/8/14. 6 | // Copyright (c) 2014 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | #import "QSDataObjectDeleter.h" 10 | #import "QSDatabaseUtilities.h" 11 | #import "QSDataModel.h" 12 | #import "QSDatabaseQueue.h" 13 | 14 | 15 | @implementation QSDataObjectDeleter 16 | 17 | 18 | + (void)deleteObjectsWithSpecifiers:(NSArray *)objectSpecifiers objectModel:(QSObjectModel *)objectModel database:(FMDatabase *)database { 19 | 20 | NSArray *uniqueIDs = [objectSpecifiers valueForKeyPath:QSUniqueIDKey]; 21 | if (QSIsEmpty(uniqueIDs)) { 22 | return; 23 | } 24 | 25 | QSDatabaseDeleteRowsWithUniqueIDs(uniqueIDs, QSUniqueIDKey, objectModel.tableName, database); 26 | 27 | for (QSRelationshipModel *oneRelationshipModel in objectModel.relationshipModels) { 28 | 29 | QSDatabaseDeleteRowsWithUniqueIDs(uniqueIDs, QSUniqueIDKey, oneRelationshipModel.tableName, database); 30 | } 31 | } 32 | 33 | 34 | + (void)deleteObjectSpecifiers:(NSArray *)objectSpecifiers objectModel:(QSObjectModel *)objectModel queue:(QSDatabaseQueue *)queue { 35 | 36 | [queue update:^(FMDatabase *database) { 37 | 38 | [self deleteObjectsWithSpecifiers:objectSpecifiers objectModel:objectModel database:database]; 39 | }]; 40 | } 41 | 42 | 43 | @end 44 | -------------------------------------------------------------------------------- /Vesper/Classes/QSDataObjectDictionary.h: -------------------------------------------------------------------------------- 1 | // 2 | // QSDataObjectDictionary.h 3 | // Vesper 4 | // 5 | // Created by Brent Simmons on 3/8/14. 6 | // Copyright (c) 2014 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | @import Foundation; 10 | 11 | 12 | @class QSObjectModel; 13 | 14 | 15 | @interface QSDataObjectDictionary : NSObject 16 | 17 | + (NSArray *)objectDictionariesForObjects:(NSArray *)databaseObjects objectModel:(QSObjectModel *)objectModel; 18 | 19 | @end 20 | -------------------------------------------------------------------------------- /Vesper/Classes/QSDataRowFetcher.h: -------------------------------------------------------------------------------- 1 | // 2 | // QSDataRowFetcher.h 3 | // Vesper 4 | // 5 | // Created by Brent Simmons on 3/8/14. 6 | // Copyright (c) 2014 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | @import Foundation; 10 | 11 | 12 | @interface QSRowFetcher : NSObject 13 | 14 | 15 | - (instancetype)initWithProperties:(NSDictionary *)properties cache:(QSWeakCache *)cache; 16 | 17 | - (NSArray *)objectsWithResultSet:(FMResultSet *)resultSet objectModel:(QSObjectModel *)objectModel; 18 | 19 | - (NSArray *)dictionariesWithResultSet:(FMResultSet *)resultSet objectModel:(QSObjectModel *)objectModel; 20 | 21 | @end 22 | -------------------------------------------------------------------------------- /Vesper/Classes/QSFetchRequest.h: -------------------------------------------------------------------------------- 1 | // 2 | // QSFetchRequest.h 3 | // Vesper 4 | // 5 | // Created by Brent Simmons on 3/20/14. 6 | // Copyright (c) 2014 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | 10 | @import Foundation; 11 | #import "QSDatabaseQueue.h" 12 | 13 | 14 | /*Wrapper for -[QSTable objects:fetchResultsBlock:] -- 15 | which takes two blocks, which makes it a little unwieldy.*/ 16 | 17 | 18 | @class QSTable; 19 | 20 | 21 | @interface QSFetchRequest : NSObject 22 | 23 | 24 | - (instancetype)initWithTable:(QSTable *)table resultSetBlock:(QSDatabaseResultSetBlock)resultSetBlock; 25 | 26 | - (void)performFetch:(QSFetchResultsBlock)fetchResultsBlock; 27 | 28 | 29 | @end 30 | -------------------------------------------------------------------------------- /Vesper/Classes/QSFetchRequest.m: -------------------------------------------------------------------------------- 1 | // 2 | // QSFetchRequest.m 3 | // Vesper 4 | // 5 | // Created by Brent Simmons on 3/20/14. 6 | // Copyright (c) 2014 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | #import "QSFetchRequest.h" 10 | #import "QSTable.h" 11 | 12 | 13 | @interface QSFetchRequest () 14 | 15 | @property (nonatomic, readwrite) QSTable *table; 16 | @property (nonatomic, copy, readonly) QSDatabaseResultSetBlock resultSetBlock; 17 | 18 | @end 19 | 20 | 21 | @implementation QSFetchRequest 22 | 23 | 24 | #pragma mark - Init 25 | 26 | - (instancetype)initWithTable:(QSTable *)table resultSetBlock:(QSDatabaseResultSetBlock)resultSetBlock { 27 | 28 | self = [super init]; 29 | if (!self) { 30 | return nil; 31 | } 32 | 33 | _table = table; 34 | _resultSetBlock = resultSetBlock; 35 | 36 | return self; 37 | } 38 | 39 | 40 | #pragma mark - API 41 | 42 | - (void)performFetch:(QSFetchResultsBlock)fetchResultsBlock { 43 | 44 | [self.table objects:self.resultSetBlock fetchResultsBlock:fetchResultsBlock]; 45 | } 46 | 47 | @end 48 | -------------------------------------------------------------------------------- /Vesper/Classes/QSObjectSpecifier.h: -------------------------------------------------------------------------------- 1 | // 2 | // QSObjectSpecifier.h 3 | // Vesper 4 | // 5 | // Created by Brent Simmons on 3/2/14. 6 | // Copyright (c) 2014 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | 10 | @import Foundation; 11 | 12 | 13 | @interface QSObjectSpecifier : NSObject 14 | 15 | 16 | + (NSArray *)objectSpecifiersWithObjects:(NSArray *)objects className:(NSString *)className; 17 | 18 | + (QSObjectSpecifier *)objectSpecifierWithClassName:(NSString *)className uniqueID:(id)uniqueID; 19 | 20 | @property (nonatomic, readonly) NSString *className; 21 | @property (nonatomic, readonly) id uniqueID; 22 | 23 | 24 | @end 25 | -------------------------------------------------------------------------------- /Vesper/Classes/QSRelationship.h: -------------------------------------------------------------------------------- 1 | // 2 | // QSRelationship.h 3 | // Vesper 4 | // 5 | // Created by Brent Simmons on 3/2/14. 6 | // Copyright (c) 2014 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | @import Foundation; 10 | 11 | @class FMResultSet; 12 | @class QSRelationshipModel; 13 | 14 | 15 | @interface QSRelationship : NSObject 16 | 17 | @property (nonatomic, readonly) NSSet *relationshipItems; /*QSRelationshipItem*/ 18 | @property (nonatomic, readonly) NSArray *sortedRelationshipItems; /*sorted by ix*/ 19 | @property (nonatomic, readonly) id parentID; 20 | @property (nonatomic, readonly) NSSet *childIDs; /*All childIDs referenced in relationshipItems.*/ 21 | 22 | /*Returns dictionary of QSRelationships keyed by parent ID.*/ 23 | 24 | + (NSDictionary *)relationshipsWithResultSet:(FMResultSet *)rs relationshipModel:(QSRelationshipModel *)relationshipModel; 25 | 26 | + (NSSet *)childIDsInRelationships:(NSDictionary *)relationships; /*Distinct childIDs, to make fetching efficient.*/ 27 | 28 | + (QSRelationship *)relationshipInRelationships:(NSDictionary *)relationships parentID:(id)parentID; 29 | 30 | @end 31 | 32 | 33 | @interface QSRelationshipItem : NSObject 34 | 35 | @property (nonatomic, readonly) id parentID; 36 | @property (nonatomic, readonly) id childID; 37 | @property (nonatomic, readonly) int64_t ix; 38 | 39 | 40 | @end 41 | -------------------------------------------------------------------------------- /Vesper/Classes/RSCoreDataUtilities.h: -------------------------------------------------------------------------------- 1 | // 2 | // RSCoreDataUtilities.h 3 | // Vesper 4 | // 5 | // Created by Brent Simmons on 12/6/12. 6 | // Copyright (c) 2012 Ranchero Software. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | 12 | @interface RSCoreDataUtilities : NSObject 13 | 14 | 15 | + (NSManagedObject *)fetchManagedObjectWithValue:(id)value forKey:(NSString *)key entityName:(NSString *)entityName managedObjectContext:(NSManagedObjectContext *)moc; 16 | 17 | + (NSManagedObject *)fetchOrInsertObjectWithValue:(id)value forKey:(NSString *)key entityName:(NSString *)entityName managedObjectContext:(NSManagedObjectContext *)moc didCreate:(BOOL *)didCreate; 18 | 19 | + (NSArray *)fetchAllObjectsWithEntityName:(NSString *)entityName managedObjectContext:(NSManagedObjectContext *)moc; 20 | + (NSArray *)fetchAllObjectsWithEntityName:(NSString *)entityName sortDescriptor:(NSSortDescriptor *)sortDescriptor managedObjectContext:(NSManagedObjectContext *)moc; 21 | 22 | + (NSManagedObject *)insertObjectWithEntityName:(NSString *)entityName managedObjectContext:(NSManagedObjectContext *)moc; 23 | + (NSManagedObject *)insertObjectWithValue:(id)value forKey:(NSString *)key entityName:(NSString *)entityName managedObjectContext:(NSManagedObjectContext *)moc; 24 | 25 | 26 | @end 27 | -------------------------------------------------------------------------------- /Vesper/Classes/RSGeometry.h: -------------------------------------------------------------------------------- 1 | // 2 | // RSGeometry.h 3 | // Vesper 4 | // 5 | // Created by Brent Simmons on 12/4/12. 6 | // Copyright (c) 2012 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | 10 | @import Foundation; 11 | 12 | 13 | CGRect CGRectCenteredHorizontallyInRect(CGRect rectToCenter, CGRect containingRect); 14 | CGRect CGRectCenteredVerticallyInRect(CGRect rectToCenter, CGRect containingRect); 15 | CGRect CGRectCenteredInRect(CGRect rectToCenter, CGRect containingRect); 16 | 17 | -------------------------------------------------------------------------------- /Vesper/Classes/RSGeometry.m: -------------------------------------------------------------------------------- 1 | // 2 | // RSGeometry.m 3 | // Vesper 4 | // 5 | // Created by Brent Simmons on 12/4/12. 6 | // Copyright (c) 2012 Ranchero Software. All rights reserved. 7 | // 8 | 9 | #import "RSGeometry.h" 10 | 11 | 12 | CGRect CGRectCenteredHorizontallyInRect(CGRect rectToCenter, CGRect containingRect) { 13 | 14 | rectToCenter.origin.x = QSFloor(CGRectGetMidX(containingRect)) - QSFloor(rectToCenter.size.width / 2); 15 | return rectToCenter; 16 | } 17 | 18 | 19 | CGRect CGRectCenteredVerticallyInRect(CGRect rectToCenter, CGRect containingRect) { 20 | 21 | rectToCenter.origin.y = QSFloor(CGRectGetMidY(containingRect)) - QSFloor(rectToCenter.size.height / 2); 22 | return rectToCenter; 23 | } 24 | 25 | 26 | CGRect CGRectCenteredInRect(CGRect rectToCenter, CGRect containingRect) { 27 | 28 | rectToCenter = CGRectCenteredHorizontallyInRect(rectToCenter, containingRect); 29 | return CGRectCenteredVerticallyInRect(rectToCenter, containingRect); 30 | } 31 | 32 | -------------------------------------------------------------------------------- /Vesper/Classes/ServerAttachment.h: -------------------------------------------------------------------------------- 1 | // 2 | // ServerAttachment.h 3 | // Vesper 4 | // 5 | // Created by Brent Simmons on 11/26/14. 6 | // Copyright (c) 2014 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | #import "ServerObject.h" 10 | 11 | @interface ServerAttachment : ServerObject 12 | 13 | @property (nonatomic) NSString *uniqueID; 14 | @property (nonatomic) int64_t height; 15 | @property (nonatomic) int64_t width; 16 | @property (nonatomic) NSString *mimeType; 17 | 18 | @end 19 | -------------------------------------------------------------------------------- /Vesper/Classes/ServerAttachment.m: -------------------------------------------------------------------------------- 1 | // 2 | // ServerAttachment.m 3 | // Vesper 4 | // 5 | // Created by Brent Simmons on 11/26/14. 6 | // Copyright (c) 2014 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | #import "ServerAttachment.h" 10 | 11 | @implementation ServerAttachment 12 | 13 | static NSString *kMimeTypeKey = @"mimeType"; 14 | static NSString *kWidthKey = @"width"; 15 | static NSString *kHeightKey = @"height"; 16 | 17 | + (instancetype)objectWithJSONDictionary:(NSDictionary *)JSONDictionary { 18 | 19 | ServerAttachment *attachment = [super objectWithJSONDictionary:JSONDictionary]; 20 | 21 | attachment.mimeType = [JSONDictionary qs_objectForKeyNotNSNull:kMimeTypeKey]; 22 | 23 | NSNumber *width = [JSONDictionary qs_objectForKeyNotNSNull:kWidthKey]; 24 | if (width) { 25 | attachment.width = width.longLongValue; 26 | } 27 | 28 | NSNumber *height = [JSONDictionary qs_objectForKeyNotNSNull:kHeightKey]; 29 | if (height) { 30 | attachment.height = height.longLongValue; 31 | } 32 | 33 | return attachment; 34 | } 35 | 36 | @end 37 | -------------------------------------------------------------------------------- /Vesper/Classes/SidebarAnimationController.h: -------------------------------------------------------------------------------- 1 | // 2 | // SidebarAnimationController.h 3 | // Vesper 4 | // 5 | // Created by Brent Simmons on 8/8/14. 6 | // Copyright (c) 2014 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | 10 | @import UIKit; 11 | 12 | 13 | @interface SidebarAnimationController : NSObject 14 | 15 | 16 | @property (nonatomic) BOOL presenting; 17 | 18 | 19 | @end 20 | -------------------------------------------------------------------------------- /Vesper/Classes/SidebarPresentationController.h: -------------------------------------------------------------------------------- 1 | // 2 | // SidebarPresentationController.h 3 | // Vesper 4 | // 5 | // Created by Brent Simmons on 8/8/14. 6 | // Copyright (c) 2014 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | 10 | @import UIKit; 11 | 12 | 13 | @interface SidebarPresentationController : UIPresentationController 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /Vesper/Classes/SidebarPresentationController.m: -------------------------------------------------------------------------------- 1 | // 2 | // SidebarPresentationController.m 3 | // Vesper 4 | // 5 | // Created by Brent Simmons on 8/8/14. 6 | // Copyright (c) 2014 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | #import "SidebarPresentationController.h" 10 | 11 | @implementation SidebarPresentationController 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /Vesper/Classes/SidebarTransitioningDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // SidebarTransitioningDelegate.h 3 | // Vesper 4 | // 5 | // Created by Brent Simmons on 8/8/14. 6 | // Copyright (c) 2014 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | 10 | @import UIKit; 11 | 12 | 13 | @interface SidebarTransitioningDelegate : NSObject 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /Vesper/Classes/UIImageView+RSExtras.h: -------------------------------------------------------------------------------- 1 | // 2 | // UIImageView+RSExtras.h 3 | // Vesper 4 | // 5 | // Created by Brent Simmons on 5/22/13. 6 | // Copyright (c) 2013 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | 10 | @import UIKit; 11 | 12 | 13 | @interface UIImageView (RSExtras) 14 | 15 | 16 | /*clipsToBounds YES, contentModeTop, autoresizing none*/ 17 | 18 | + (UIImageView *)rs_imageViewWithSnapshotOfView:(UIView *)view clearBackground:(BOOL)clearBackground; 19 | 20 | @end 21 | -------------------------------------------------------------------------------- /Vesper/Classes/UIImageView+RSExtras.m: -------------------------------------------------------------------------------- 1 | // 2 | // UIImageView+RSExtras.m 3 | // Vesper 4 | // 5 | // Created by Brent Simmons on 5/22/13. 6 | // Copyright (c) 2013 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | #import "UIImageView+RSExtras.h" 10 | 11 | 12 | @implementation UIImageView (RSExtras) 13 | 14 | 15 | + (UIImageView *)rs_imageViewWithSnapshotOfView:(UIView *)view clearBackground:(BOOL)clearBackground { 16 | 17 | UIImage *image = [view rs_snapshotImage:clearBackground]; 18 | if (image == nil) 19 | return nil; 20 | 21 | UIImageView *imageView = [[UIImageView alloc] initWithImage:image]; 22 | imageView.clipsToBounds = YES; 23 | imageView.contentMode = UIViewContentModeTop; 24 | imageView.autoresizingMask = UIViewAutoresizingNone; 25 | 26 | return imageView; 27 | } 28 | 29 | 30 | @end 31 | -------------------------------------------------------------------------------- /Vesper/Classes/UITextView+RSExtras.h: -------------------------------------------------------------------------------- 1 | // 2 | // UITextView+RSExtras.h 3 | // Vesper 4 | // 5 | // Created by Brent Simmons on 4/17/13. 6 | // Copyright (c) 2013 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | 10 | @import UIKit; 11 | 12 | 13 | @interface UITextView (RSExtras) 14 | 15 | 16 | - (NSString *)rs_linkAtPoint:(CGPoint)point; 17 | 18 | 19 | @end 20 | -------------------------------------------------------------------------------- /Vesper/Classes/VSAPICall.h: -------------------------------------------------------------------------------- 1 | // 2 | // VSAPICall.h 3 | // Vesper 4 | // 5 | // Created by Brent Simmons on 5/8/14. 6 | // Copyright (c) 2014 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | 10 | #import "VSMainThreadQueue.h" 11 | 12 | 13 | @protocol VSAPICallDelegate 14 | 15 | @required 16 | 17 | @property (nonatomic, readonly) NSString *authenticationToken; 18 | 19 | - (void)authenticationToken:(QSObjectResultBlock)resultBlock; 20 | - (void)authenticationTokenIsInvalid:(NSString *)authenticationToken; 21 | 22 | @end 23 | 24 | 25 | @interface VSAPICall : NSObject 26 | 27 | 28 | - (instancetype)initWithRequest:(NSURLRequest *)URLRequest taskDescription:(NSString *)taskDescription URLSession:(NSURLSession *)URLSession delegate:(id)delegate resultBlock:(VSAPIResultBlock)resultBlock; 29 | 30 | @property (nonatomic) BOOL setsAuthenticationToken; 31 | 32 | 33 | @end 34 | -------------------------------------------------------------------------------- /Vesper/Classes/VSAPIResult.h: -------------------------------------------------------------------------------- 1 | // 2 | // VSAPIResult.h 3 | // Vesper 4 | // 5 | // Created by Brent Simmons on 11/5/13. 6 | // Copyright (c) 2013 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | 10 | extern NSString *VSServerDateNotification; 11 | extern NSString *VSServerDateKey; 12 | 13 | 14 | @interface VSAPIResult : NSObject 15 | 16 | 17 | @property (nonatomic, readonly) NSURLRequest *request; 18 | @property (nonatomic, readonly) NSURLResponse *response; 19 | @property (nonatomic, readonly) NSError *error; 20 | @property (nonatomic, readonly) id JSONObject; 21 | @property (nonatomic, readonly) NSError *JSONError; /*Error creating JSON from returned data.*/ 22 | @property (nonatomic, readonly) NSString *responseSyncToken; 23 | @property (nonatomic, readonly) NSDate *responseServerDate; 24 | @property (nonatomic, assign, readonly) NSInteger statusCode; 25 | @property (nonatomic, readonly) NSData *data; 26 | @property (nonatomic, readonly) NSString *resultString; 27 | 28 | @property (nonatomic) id parsedObject; 29 | @property (nonatomic, assign) BOOL succeeded; 30 | 31 | 32 | + (VSAPIResult *)resultWithRequest:(NSURLRequest *)request response:(NSURLResponse *)response data:(NSData *)data error:(NSError *)error; 33 | 34 | 35 | @end 36 | -------------------------------------------------------------------------------- /Vesper/Classes/VSActivityPopover.h: -------------------------------------------------------------------------------- 1 | // 2 | // VSActivityPopover.h 3 | // Vesper 4 | // 5 | // Created by Brent Simmons on 8/4/13. 6 | // Copyright (c) 2013 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "VSMenuPopover.h" 11 | 12 | 13 | /*Doesn't inherit from VSMenuPopover because we need UIToolbar for translucency and blurring.*/ 14 | 15 | 16 | @interface VSActivityPopover : UIToolbar 17 | 18 | - (instancetype)initWithPopoverSpecifier:(NSString *)popoverSpecifier; 19 | 20 | - (void)addItemWithTitle:(NSString *)title image:(UIImage *)image target:(id)target action:(SEL)action; 21 | 22 | - (void)showInView:(UIView *)view fromBehindBar:(UIView *)bar animationDirection:(VSDirection)direction; 23 | 24 | - (void)dismiss:(VSPopoverDidDismissCallback)completion; 25 | 26 | @property (nonatomic, assign) BOOL showing; 27 | 28 | @end 29 | -------------------------------------------------------------------------------- /Vesper/Classes/VSAppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // VSAppDelegate.h 3 | // Vesper 4 | // 5 | // Created by Brent Simmons on 11/18/12. 6 | // Copyright (c) 2012 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | #import "VSAppDelegateProtocol.h" 10 | 11 | 12 | @interface VSAppDelegate : UIResponder 13 | 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /Vesper/Classes/VSAppDelegateProtocol.h: -------------------------------------------------------------------------------- 1 | // 2 | // VSAppDelegateProtocol.h 3 | // Vesper 4 | // 5 | // Created by Brent Simmons on 2/12/13. 6 | // Copyright (c) 2013 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | 10 | @import Foundation; 11 | 12 | 13 | @class VSTheme; 14 | @class VSTypographySettings; 15 | 16 | 17 | @protocol VSAppDelegate 18 | 19 | @required 20 | 21 | @property (nonatomic, readonly) VSTheme *theme; 22 | @property (nonatomic, readonly) VSTypographySettings *typographySettings; 23 | @property (nonatomic, assign, readonly) BOOL firstRun; 24 | @property (nonatomic, readonly) NSDate *firstRunDate; 25 | 26 | #if USE_SAFARI_VIEW_CONTROLLER 27 | - (void)openURL:(NSURL *)url; 28 | #endif 29 | 30 | #if TARGET_OS_IPHONE 31 | 32 | @property (nonatomic, assign, readonly) BOOL sidebarShowing; 33 | @property (nonatomic, readonly) UIViewController *rootRightSideViewController; /*timeline or credits; may have other views on top by z axis*/ 34 | 35 | #endif 36 | 37 | 38 | @end 39 | -------------------------------------------------------------------------------- /Vesper/Classes/VSArchiveIndicatorView.h: -------------------------------------------------------------------------------- 1 | // 2 | // VSArchiveIndicatorView.h 3 | // Vesper 4 | // 5 | // Created by Brent Simmons on 4/8/13. 6 | // Copyright (c) 2013 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | 12 | typedef NS_ENUM(NSUInteger, VSArchiveIndicatorState) { 13 | VSArchiveIndicatorStateHinting, 14 | VSArchiveIndicatorStateIndicating 15 | }; 16 | 17 | 18 | @interface VSArchiveIndicatorView : UIView 19 | 20 | @property (nonatomic, assign) VSArchiveIndicatorState archiveIndicatorState; 21 | @property (nonatomic, strong) NSString *text; 22 | @property (nonatomic, strong) UIFont *font; 23 | @property (nonatomic, assign) CGFloat arrowTranslationX; 24 | 25 | @end 26 | -------------------------------------------------------------------------------- /Vesper/Classes/VSAttachment.h: -------------------------------------------------------------------------------- 1 | // 2 | // VSAttachment.h 3 | // Vesper 4 | // 5 | // Created by Brent Simmons on 9/27/13. 6 | // Copyright (c) 2013 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | 10 | #import "QSAPIObject.h" 11 | 12 | 13 | /*Immutable*/ 14 | 15 | @interface VSAttachment : NSObject 16 | 17 | 18 | @property (nonatomic, readonly) NSString *uniqueID; 19 | @property (nonatomic, readonly) NSString *mimeType; 20 | @property (nonatomic, assign, readonly) int64_t height; 21 | @property (nonatomic, assign, readonly) int64_t width; 22 | 23 | /*Convenience*/ 24 | 25 | @property (nonatomic, assign, readonly) BOOL isImage; 26 | @property (nonatomic, assign, readonly) CGSize size; 27 | @property (nonatomic, readonly) NSString *path; /*May not exist on disk.*/ 28 | 29 | 30 | /*uniqueID and mimeType must not be nil.*/ 31 | 32 | + (instancetype)attachmentWithUniqueID:(NSString *)uniqueID mimeType:(NSString *)mimeType height:(int64_t)height width:(int64_t)width; 33 | 34 | 35 | @end 36 | -------------------------------------------------------------------------------- /Vesper/Classes/VSAttachmentData.h: -------------------------------------------------------------------------------- 1 | // 2 | // VSAttachmentData.h 3 | // Vesper 4 | // 5 | // Created by Brent Simmons on 2/19/13. 6 | // Copyright (c) 2013 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | 10 | @interface VSAttachmentData : NSObject 11 | 12 | @property (nonatomic) NSString *uniqueID; 13 | @property (nonatomic) NSData *binaryData; 14 | @property (nonatomic) NSString *path; 15 | 16 | @end 17 | -------------------------------------------------------------------------------- /Vesper/Classes/VSAttachmentData.m: -------------------------------------------------------------------------------- 1 | // 2 | // VSAttachmentData.m 3 | // Vesper 4 | // 5 | // Created by Brent Simmons on 2/19/13. 6 | // Copyright (c) 2013 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | #import "VSAttachmentData.h" 10 | 11 | 12 | @implementation VSAttachmentData 13 | 14 | @end 15 | -------------------------------------------------------------------------------- /Vesper/Classes/VSAttachmentSyncData.h: -------------------------------------------------------------------------------- 1 | // 2 | // VSAttachmentSyncData.h 3 | // Vesper 4 | // 5 | // Created by Brent Simmons on 11/25/13. 6 | // Copyright (c) 2013 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | 10 | 11 | @interface VSAttachmentSyncData : NSObject 12 | 13 | 14 | - (void)addUniqueIDOfAttachmentCreatedLocally:(NSString *)uniqueID; 15 | 16 | - (void)uniqueIDsOfAttachmentsToUpload:(QSFetchResultsBlock)fetchResultsBlock; 17 | 18 | 19 | @end 20 | -------------------------------------------------------------------------------- /Vesper/Classes/VSBasicWebViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // VSBasicWebViewController.h 3 | // Vesper 4 | // 5 | // Created by Brent Simmons on 4/23/14. 6 | // Copyright (c) 2014 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | 10 | @interface VSBasicWebViewController : UIViewController 11 | 12 | - (instancetype)initWithURL:(NSURL *)URL fallbackResourceName:(NSString *)fallbackResourceName title:(NSString *)title; 13 | 14 | @property (nonatomic) BOOL hasCloseButton; /*Set YES if it's modal*/ 15 | 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /Vesper/Classes/VSBinaryCache.h: -------------------------------------------------------------------------------- 1 | // 2 | // VSBinaryCache.h 3 | // Vesper 4 | // 5 | // Created by Brent Simmons on 7/18/14. 6 | // Copyright (c) 2014 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | 10 | @import Foundation; 11 | 12 | 13 | /*The folder this manages must already exist. 14 | Doesn't do any locking or queueing -- caller is responsible.*/ 15 | 16 | 17 | @interface VSBinaryCache : NSObject 18 | 19 | 20 | - (instancetype)initWithFolder:(NSString *)folder; 21 | 22 | - (NSString *)filePathForKey:(NSString *)key; 23 | 24 | - (BOOL)setBinaryData:(NSData *)data key:(NSString *)key error:(NSError **)error; 25 | 26 | - (NSData *)binaryDataForKey:(NSString *)key error:(NSError **)error; 27 | 28 | - (BOOL)removeBinaryDataForKey:(NSString *)key error:(NSError **)error; 29 | 30 | - (BOOL)binaryForKeyExists:(NSString *)key; 31 | 32 | - (UInt64)lengthOfBinaryDataForKey:(NSString *)key error:(NSError **)error; 33 | 34 | - (NSArray *)allKeys:(NSError **)error; 35 | 36 | 37 | extern NSString *VSBinaryKey; 38 | extern NSString *VSBinaryLength; 39 | 40 | - (NSArray *)allObjects:(NSError **)error; /*NSDictionary objects with VSBinaryKey and VSBinaryLength.*/ 41 | 42 | 43 | @end 44 | -------------------------------------------------------------------------------- /Vesper/Classes/VSBrowserBackgroundView.h: -------------------------------------------------------------------------------- 1 | // 2 | // VSBrowserBackgroundView.h 3 | // Vesper 4 | // 5 | // Created by Brent Simmons on 4/4/13. 6 | // Copyright (c) 2013 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface VSBrowserBackgroundView : UIView 12 | 13 | @property (nonatomic, strong) UIView *toolbarBorderView; 14 | @property (nonatomic, strong) UIView *statusBarBackgroundView; 15 | 16 | @end 17 | -------------------------------------------------------------------------------- /Vesper/Classes/VSBrowserLoadingView.h: -------------------------------------------------------------------------------- 1 | // 2 | // VSBrowserLoadingView.h 3 | // Vesper 4 | // 5 | // Created by Brent Simmons on 3/3/13. 6 | // Copyright (c) 2013 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | 12 | @interface VSBrowserLoadingView : UIView 13 | 14 | @property (nonatomic, strong) NSURL *url; 15 | @property (nonatomic, assign, getter=isLoading) BOOL loading; 16 | @end 17 | -------------------------------------------------------------------------------- /Vesper/Classes/VSBrowserToolbarView.h: -------------------------------------------------------------------------------- 1 | // 2 | // VSBrowserToolbarView.h 3 | // Vesper 4 | // 5 | // Created by Brent Simmons on 4/4/13. 6 | // Copyright (c) 2013 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "VSNavbarView.h" 11 | 12 | 13 | @class VSBrowserTextButton; 14 | 15 | @interface VSBrowserToolbarView : UIToolbar 16 | 17 | @property (nonatomic, strong) VSBrowserTextButton *doneButton; 18 | @property (nonatomic, strong) UIButton *backButton; 19 | @property (nonatomic, strong) UIButton *forwardButton; 20 | @property (nonatomic, strong) UIButton *activityButton; 21 | 22 | @end 23 | -------------------------------------------------------------------------------- /Vesper/Classes/VSBrowserViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // VSBrowserViewController.h 3 | // Vesper 4 | // 5 | // Created by Brent Simmons on 2/4/13. 6 | // Copyright (c) 2013 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "VSBaseViewController.h" 11 | #import "VSBrowserPullToRefreshView.h" 12 | 13 | 14 | @interface VSBrowserViewController : VSBaseViewController 15 | 16 | 17 | - (id)initWithURL:(NSURL *)initialURL; 18 | 19 | - (void)beginLoading; 20 | 21 | + (BOOL)canOpenURL:(NSURL *)url; 22 | 23 | 24 | @end 25 | -------------------------------------------------------------------------------- /Vesper/Classes/VSCameraViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // VSCameraViewController.h 3 | // Vesper 4 | // 5 | // Created by Brent Simmons on 2/4/13. 6 | // Copyright (c) 2013 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | #import "VSBaseViewController.h" 10 | 11 | @interface VSCameraViewController : VSBaseViewController 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /Vesper/Classes/VSCameraViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // VSCameraViewController.m 3 | // Vesper 4 | // 5 | // Created by Brent Simmons on 2/4/13. 6 | // Copyright (c) 2013 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | #import "VSCameraViewController.h" 10 | 11 | 12 | @interface VSCameraViewController () 13 | 14 | @end 15 | 16 | @implementation VSCameraViewController 17 | 18 | 19 | @end 20 | -------------------------------------------------------------------------------- /Vesper/Classes/VSCheckmarkAccessoryView.h: -------------------------------------------------------------------------------- 1 | // 2 | // VSCheckmarkAccessoryView.h 3 | // Vesper 4 | // 5 | // Created by Brent Simmons on 8/30/13. 6 | // Copyright (c) 2013 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface VSCheckmarkAccessoryView : UIView 12 | 13 | 14 | - (instancetype)initWithFrame:(CGRect)frame checkmarkOriginY:(CGFloat)checkmarkOriginY checkmarkMarginRight:(CGFloat)checkmarkMarginRight checkmarkImage:(UIImage *)checkmarkImage; 15 | 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /Vesper/Classes/VSCreditsViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // VSCreditsViewController.h 3 | // Vesper 4 | // 5 | // Created by Brent Simmons on 2/4/13. 6 | // Copyright (c) 2013 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | #import "VSBaseViewController.h" 10 | 11 | 12 | /*Use initWithTheme:*/ 13 | 14 | 15 | @class VSCreditsNavbarView; 16 | 17 | 18 | @interface VSCreditsViewController : VSBaseViewController 19 | 20 | 21 | @end 22 | 23 | -------------------------------------------------------------------------------- /Vesper/Classes/VSDateManager.h: -------------------------------------------------------------------------------- 1 | // 2 | // VSDateManager.h 3 | // Vesper 4 | // 5 | // Created by Brent Simmons on 5/4/14. 6 | // Copyright (c) 2014 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | 10 | 11 | 12 | @interface VSDateManager : NSObject 13 | 14 | 15 | + (instancetype)sharedManager; 16 | 17 | 18 | /*Adjusted for clock skew based on date returned by server.*/ 19 | 20 | - (NSDate *)currentDate; 21 | 22 | 23 | @end 24 | 25 | -------------------------------------------------------------------------------- /Vesper/Classes/VSDescriptionView.h: -------------------------------------------------------------------------------- 1 | // 2 | // VSDescriptionView.h 3 | // Vesper 4 | // 5 | // Created by Brent Simmons on 4/27/14. 6 | // Copyright (c) 2014 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | 10 | @interface VSDescriptionView : UIView 11 | 12 | 13 | - (instancetype)initWithText:(NSString *)text edgeInsets:(UIEdgeInsets)edgeInsets; 14 | 15 | @property (nonatomic, readonly) UILabel *label; 16 | 17 | - (void)updateText:(NSString *)s color:(UIColor *)color; 18 | 19 | @end 20 | -------------------------------------------------------------------------------- /Vesper/Classes/VSDetailNavbarView.h: -------------------------------------------------------------------------------- 1 | // 2 | // VSDetailNavbarView.h 3 | // Vesper 4 | // 5 | // Created by Brent Simmons on 4/4/13. 6 | // Copyright (c) 2013 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | #import "VSNavbarView.h" 10 | 11 | 12 | @interface VSDetailNavbarView : VSNavbarView 13 | 14 | @property (nonatomic, assign) BOOL editMode; 15 | 16 | - (id)initWithFrame:(CGRect)frame backButtonTitle:(NSString *)backButtonTitle; 17 | 18 | - (UIImage *)imageForAnimation:(BOOL)includePlusButton; 19 | 20 | //- (UIImage *)fullWidthImageForAnimation; /*Includes plus button or whatever is rightmost*/ 21 | 22 | @property (nonatomic, assign) BOOL readonly; /*If YES, hide camera and plus buttons.*/ 23 | 24 | - (void)displayKeyboardButton; /*forces switch to editMode immediately, without animation*/ 25 | 26 | @property (nonatomic, strong, readonly) UIButton *activityButton; 27 | 28 | /*Pan-back animation/interaction support*/ 29 | 30 | @property (nonatomic, assign) CGFloat panbackPercent; 31 | @property (nonatomic, strong, readonly) UILabel *panbackLabel; 32 | @property (nonatomic, strong, readonly) UIButton *backButton; 33 | @property (nonatomic, strong, readonly) UIImageView *panbackChevron; 34 | 35 | @end 36 | -------------------------------------------------------------------------------- /Vesper/Classes/VSDetailStatusView.h: -------------------------------------------------------------------------------- 1 | // 2 | // VSDetailStatusView.h 3 | // Vesper 4 | // 5 | // Created by Brent Simmons on 7/17/14. 6 | // Copyright (c) 2014 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | @import UIKit; 10 | 11 | 12 | @interface VSDetailStatusView : UIView 13 | 14 | 15 | /*Setting these updates the display appropriately.*/ 16 | 17 | @property (nonatomic) NSUInteger characterCount; 18 | @property (nonatomic) NSUInteger wordCount; 19 | @property (nonatomic) NSDate *creationDate; 20 | @property (nonatomic) NSDate *modificationDate; 21 | 22 | 23 | @end 24 | -------------------------------------------------------------------------------- /Vesper/Classes/VSDetailTextStorage.h: -------------------------------------------------------------------------------- 1 | // 2 | // VSDetailTextStorage.h 3 | // Vesper 4 | // 5 | // Created by Brent Simmons on 7/19/13. 6 | // Copyright (c) 2013 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface VSDetailTextStorage : NSTextStorage 12 | 13 | @property (nonatomic, strong) NSDictionary *titleAttributes; 14 | @property (nonatomic, strong) NSDictionary *bodyAttributes; 15 | @property (nonatomic, assign) BOOL readOnly; 16 | 17 | - (void)highlightLinks:(NSArray *)links; 18 | - (void)unhighlightLinks; 19 | 20 | - (instancetype)initAsReadOnly:(BOOL)readOnly; 21 | 22 | 23 | @end 24 | -------------------------------------------------------------------------------- /Vesper/Classes/VSDetailTextView.h: -------------------------------------------------------------------------------- 1 | // 2 | // VSDetailTextView.h 3 | // Vesper 4 | // 5 | // Created by Brent Simmons on 4/17/13. 6 | // Copyright (c) 2013 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | 12 | @interface VSDetailTextView : UITextView 13 | 14 | 15 | - (instancetype)initWithFrame:(CGRect)frame imageSize:(CGSize)imageSize tagProxies:(NSArray *)tagProxies readonly:(BOOL)readonly; 16 | 17 | @property (nonatomic, strong) UIImage *image; 18 | @property (nonatomic, strong, readonly) UIImageView *imageView; 19 | @property (nonatomic, assign) BOOL readonly; 20 | @property (nonatomic, assign) CGRect keyboardFrame; 21 | @property (nonatomic, assign, readonly) BOOL editing; 22 | 23 | 24 | - (CGSize)vs_contentSize; /*contentSize is apparently not working. As of iOS 7.0b5. Does ceilf on height and width.*/ 25 | - (void)setContentOffSetAnimatedForReal:(CGPoint)contentOffset; 26 | 27 | - (UIView *)viewForAnimation:(BOOL)clearBackground; 28 | 29 | 30 | @end 31 | 32 | 33 | //void VSDoContentOffsetHack(void); /*Use this only if you don't have a reference to the VSDetailTextView.*/ 34 | -------------------------------------------------------------------------------- /Vesper/Classes/VSDetailToSearchResultsAnimator.h: -------------------------------------------------------------------------------- 1 | // 2 | // VSDetailToSearchResultsAnimator.h 3 | // Vesper 4 | // 5 | // Created by Brent Simmons on 3/17/14. 6 | // Copyright (c) 2014 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | 10 | @class VSNote; 11 | @class VSTimelineViewController; 12 | @class VSDetailViewController; 13 | @class VSSearchResultsViewController; 14 | 15 | 16 | @interface VSDetailToSearchResultsAnimator : NSObject 17 | 18 | 19 | - (instancetype)initWithNote:(VSNote *)note timelineNote:(VSTimelineNote *)timelineNote indexPath:(NSIndexPath *)indexPath timelineViewController:(VSTimelineViewController *)timelineViewController searchResultsViewController:(VSSearchResultsViewController *)searchResultsViewController detailViewController:(VSDetailViewController *)detailViewController; 20 | 21 | - (void)animate:(QSVoidCompletionBlock)completion; 22 | 23 | 24 | @end 25 | -------------------------------------------------------------------------------- /Vesper/Classes/VSDetailToTimelineAnimator.h: -------------------------------------------------------------------------------- 1 | // 2 | // VSDetailToTimelineAnimator.h 3 | // Vesper 4 | // 5 | // Created by Brent Simmons on 3/17/14. 6 | // Copyright (c) 2014 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | 10 | 11 | @class VSTimelineViewController; 12 | @class VSDetailViewController; 13 | 14 | 15 | @interface VSDetailToTimelineAnimator : NSObject 16 | 17 | 18 | - (instancetype)initWithNote:(VSNote *)note indexPath:(NSIndexPath *)indexPath timelineViewController:(VSTimelineViewController *)timelineViewController detailViewController:(VSDetailViewController *)detailViewController; 19 | 20 | - (void)animate:(QSVoidCompletionBlock)completion; 21 | 22 | 23 | @end 24 | -------------------------------------------------------------------------------- /Vesper/Classes/VSDetailToolbar.h: -------------------------------------------------------------------------------- 1 | // 2 | // VSDetailToolbar.h 3 | // Vesper 4 | // 5 | // Created by Brent Simmons on 9/3/13. 6 | // Copyright (c) 2013 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | 10 | @class VSDetailStatusView; 11 | 12 | 13 | @interface VSDetailToolbar : UIToolbar 14 | 15 | @property (nonatomic, assign) BOOL showRestoreButton; /*Default is NO; shows archive button instead*/ 16 | 17 | - (UIImageView *)imageViewForAnimation; 18 | 19 | @property (nonatomic, readonly) VSDetailStatusView *statusView; 20 | 21 | 22 | @end 23 | -------------------------------------------------------------------------------- /Vesper/Classes/VSDetailTransitionNavbarView.h: -------------------------------------------------------------------------------- 1 | // 2 | // VSBlankNavbarView.h 3 | // Vesper 4 | // 5 | // Created by Brent Simmons on 4/30/13. 6 | // Copyright (c) 2013 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | #import "VSNavbarView.h" 10 | 11 | 12 | @interface VSDetailTransitionNavbarView : VSNavbarView 13 | 14 | 15 | - (UIImage *)imageForAnimation:(BOOL)includePlusButton; 16 | 17 | 18 | @end 19 | -------------------------------------------------------------------------------- /Vesper/Classes/VSDetailTransitionNavbarView.m: -------------------------------------------------------------------------------- 1 | // 2 | // VSBlankNavbarView.m 3 | // Vesper 4 | // 5 | // Created by Brent Simmons on 4/30/13. 6 | // Copyright (c) 2013 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | #import "VSDetailTransitionNavbarView.h" 10 | 11 | 12 | @implementation VSDetailTransitionNavbarView 13 | 14 | 15 | - (UIImage *)imageForAnimation:(BOOL)includePlusButton { 16 | 17 | CGSize size = self.bounds.size; 18 | if (!includePlusButton) { 19 | CGFloat composeButtonX = self.composeButton.frame.origin.x; 20 | size.width = composeButtonX - 1.0f; 21 | } 22 | 23 | UIGraphicsBeginImageContextWithOptions(size, NO, [UIScreen mainScreen].scale); 24 | CGContextRef context = UIGraphicsGetCurrentContext(); 25 | [self.layer renderInContext:context]; 26 | UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); 27 | UIGraphicsEndImageContext(); 28 | 29 | return image; 30 | } 31 | 32 | 33 | - (BOOL)clipsToBounds { 34 | return YES; 35 | } 36 | 37 | 38 | @end 39 | 40 | -------------------------------------------------------------------------------- /Vesper/Classes/VSDetailTransitionView.h: -------------------------------------------------------------------------------- 1 | // 2 | // VSDetailTransitionView.h 3 | // Vesper 4 | // 5 | // Created by Brent Simmons on 4/30/13. 6 | // Copyright (c) 2013 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | #import "VSSmokescreenView.h" 10 | 11 | 12 | @class VSNavbarView; 13 | 14 | @interface VSDetailTransitionView : VSSmokescreenView 15 | 16 | @property (nonatomic, strong, readonly) VSNavbarView *navbar; 17 | @property (nonatomic, strong, readonly) UIView *tableContainerView; 18 | 19 | @end 20 | -------------------------------------------------------------------------------- /Vesper/Classes/VSEditableTagView.h: -------------------------------------------------------------------------------- 1 | // 2 | // VSEditableTagView.h 3 | // Vesper 4 | // 5 | // Created by Brent Simmons on 4/12/13. 6 | // Copyright (c) 2013 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | 12 | @class VSTagProxy; 13 | 14 | 15 | @protocol VSEditableTagView 16 | 17 | @property (nonatomic, strong, readonly) VSTagProxy *tagProxy; 18 | 19 | @end 20 | -------------------------------------------------------------------------------- /Vesper/Classes/VSExportHeaderView.h: -------------------------------------------------------------------------------- 1 | // 2 | // VSExportHeaderView.h 3 | // Vesper 4 | // 5 | // Created by Brent Simmons on 7/4/16. 6 | // Copyright © 2016 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface VSExportHeaderView : UIView 12 | 13 | - (void)switchToSuccessMessage; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /Vesper/Classes/VSExportViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // VSExportViewController.h 3 | // Vesper 4 | // 5 | // Created by Brent Simmons on 7/1/16. 6 | // Copyright © 2016 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface VSExportViewController : UIViewController 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /Vesper/Classes/VSExporter.h: -------------------------------------------------------------------------------- 1 | // 2 | // VSExporter.h 3 | // Vesper 4 | // 5 | // Created by Brent Simmons on 7/4/16. 6 | // Copyright © 2016 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | extern NSString *VSExportDidCompleteNotification; 12 | 13 | @interface VSExporter : NSObject 14 | 15 | - (void)exportNotesAndPictures; 16 | 17 | @property (nonatomic, readonly) NSString *folder; 18 | 19 | @property (nonatomic, readonly) NSError *exportError; 20 | 21 | @end 22 | -------------------------------------------------------------------------------- /Vesper/Classes/VSGhostTagButton.h: -------------------------------------------------------------------------------- 1 | // 2 | // VSGhostTagButton.h 3 | // Vesper 4 | // 5 | // Created by Brent Simmons on 4/10/13. 6 | // Copyright (c) 2013 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "VSEditableTagView.h" 11 | 12 | 13 | /*On tap, sends ghostTagButtonTapped:(id)sender via responder chain.*/ 14 | 15 | @interface VSGhostTagButton : UIButton 16 | 17 | + (instancetype)button; 18 | 19 | @end 20 | -------------------------------------------------------------------------------- /Vesper/Classes/VSGroupedTableButtonViewCell.h: -------------------------------------------------------------------------------- 1 | // 2 | // VSGroupedTableButtonViewCell.h 3 | // Vesper 4 | // 5 | // Created by Brent Simmons on 5/2/14. 6 | // Copyright (c) 2014 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | 10 | 11 | @interface VSGroupedTableButtonViewCell : UITableViewCell 12 | 13 | 14 | - (instancetype)initWithLabelText:(NSString *)labelText destructive:(BOOL)destructive textAlignment:(NSTextAlignment)textAlignment; 15 | 16 | - (void)startProgress; 17 | - (void)stopProgress:(BOOL)success imageViewAnimationBlock:(QSVoidBlock)imageViewAnimationBlock; 18 | - (void)clearProgressViews:(BOOL)animated; 19 | 20 | 21 | @end 22 | -------------------------------------------------------------------------------- /Vesper/Classes/VSIconGridButton.h: -------------------------------------------------------------------------------- 1 | // 2 | // VSIconGridButton.h 3 | // Vesper 4 | // 5 | // Created by Brent Simmons on 5/13/13. 6 | // Copyright (c) 2013 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | 12 | @class VSMenuItem; 13 | 14 | 15 | @interface VSIconGridButton : UIButton 16 | 17 | 18 | - (instancetype)initWithFrame:(CGRect)frame menuItem:(VSMenuItem *)menuItem destructive:(BOOL)destructive popoverSpecifier:(NSString *)popoverSpecifier; 19 | 20 | 21 | @property (nonatomic, weak, readonly) VSMenuItem *menuItem; 22 | 23 | 24 | @end 25 | -------------------------------------------------------------------------------- /Vesper/Classes/VSIconGridPopover.h: -------------------------------------------------------------------------------- 1 | // 2 | // VSIconGridPopover.h 3 | // Vesper 4 | // 5 | // Created by Brent Simmons on 5/13/13. 6 | // Copyright (c) 2013 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | #import "VSMenuPopover.h" 10 | 11 | 12 | @class VSMenuItem; 13 | 14 | 15 | @interface VSIconGridPopover : VSMenuPopover 16 | 17 | 18 | 19 | @end 20 | -------------------------------------------------------------------------------- /Vesper/Classes/VSImagePickerController.h: -------------------------------------------------------------------------------- 1 | // 2 | // VSImagePickerController.h 3 | // Vesper 4 | // 5 | // Created by Brent Simmons on 4/17/13. 6 | // Copyright (c) 2013 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | 12 | /*Get a picture from the user and return it in a callback. The image will be resized down from the original image to a size suitable for syncing. The original image will also be saved to the user's camera roll.*/ 13 | 14 | 15 | @interface VSImagePickerController : NSObject 16 | 17 | - (instancetype)initWithViewController:(UIViewController *)viewController; 18 | 19 | /*When the callback is called, it's safe to release this object. If user cancels, the callback will be called with a nil UIImage.*/ 20 | 21 | - (void)runImagePickerForSourceType:(UIImagePickerControllerSourceType)sourceType callback:(QSImageResultBlock)callback; 22 | 23 | @end 24 | -------------------------------------------------------------------------------- /Vesper/Classes/VSImageScrollView.h: -------------------------------------------------------------------------------- 1 | // 2 | // VSImageScrollView.h 3 | // Vesper 4 | // 5 | // Created by Brent Simmons on 4/16/13. 6 | // Copyright (c) 2013 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | 12 | /*Displays image initially as aspect-fill, so we don't show the background.*/ 13 | 14 | @interface VSImageScrollView : UIScrollView 15 | 16 | - (id)initWithFrame:(CGRect)frame image:(UIImage *)image; 17 | 18 | @property (nonatomic, strong, readonly) UIImageView *imageView; 19 | @property (nonatomic, assign) BOOL closing; /*For animation*/ 20 | 21 | @end 22 | -------------------------------------------------------------------------------- /Vesper/Classes/VSImageUtilities.h: -------------------------------------------------------------------------------- 1 | // 2 | // VSImageUtilities.h 3 | // Vesper 4 | // 5 | // Created by Brent Simmons on 4/13/13. 6 | // Copyright (c) 2013 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | 10 | @import Foundation; 11 | 12 | 13 | UIImage *VSScaleAndRotateImageToMaxResolution(UIImage *image, CGFloat maxResolution); 14 | 15 | void VSDrawUIImageCenteredInRectWithAspectFill(UIImage *image, CGRect r); 16 | -------------------------------------------------------------------------------- /Vesper/Classes/VSInputTextTableViewCell.h: -------------------------------------------------------------------------------- 1 | // 2 | // VSInputTextTableViewCell.h 3 | // Vesper 4 | // 5 | // Created by Brent Simmons on 4/27/14. 6 | // Copyright (c) 2014 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | 10 | @protocol VSInputTextTableViewCellDelegate 11 | 12 | /*This table view cell is a delegate for its UITextField. 13 | But the view controller needs to handle this, 14 | so the cell passes it on.*/ 15 | 16 | @required 17 | - (BOOL)textFieldShouldReturn:(UITextField *)textField; 18 | 19 | @end 20 | 21 | 22 | @interface VSInputTextTableViewCell : UITableViewCell 23 | 24 | 25 | - (id)initWithLabelWidth:(CGFloat)labelWidth label:(NSString *)labelText placeholder:(NSString *)placeholder secure:(BOOL)secure delegate:(id)delegate; 26 | 27 | @property (nonatomic, readonly) UITextField *textField; 28 | 29 | - (void)updateShowHideButtonVisibility; 30 | 31 | @end 32 | -------------------------------------------------------------------------------- /Vesper/Classes/VSKeychain.h: -------------------------------------------------------------------------------- 1 | // 2 | // RSKeychain.h 3 | // Vesper 4 | // 5 | // Created by Brent Simmons on 5/6/14. 6 | // Copyright (c) 2014 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | 10 | BOOL VSKeychainGetPassword(NSString *username, NSString **password, NSError **error); 11 | BOOL VSKeychainSetPassword(NSString *username, NSString *password, NSError **error); 12 | BOOL VSKeychainDeletePassword(NSString *username, NSError **error); 13 | 14 | 15 | -------------------------------------------------------------------------------- /Vesper/Classes/VSLabelSwitchTableViewCell.h: -------------------------------------------------------------------------------- 1 | // 2 | // VSLabelSwitchTableViewCell.h 3 | // Vesper 4 | // 5 | // Created by Brent Simmons on 4/27/14. 6 | // Copyright (c) 2014 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | 10 | @interface VSLabelSwitchTableViewCell : UITableViewCell 11 | 12 | - (instancetype)initWithLabel:(NSString *)label; 13 | 14 | @property (nonatomic, readonly) UISwitch *switchView; 15 | 16 | @end 17 | -------------------------------------------------------------------------------- /Vesper/Classes/VSLinkButton.h: -------------------------------------------------------------------------------- 1 | // 2 | // VSLinkButton.h 3 | // Vesper 4 | // 5 | // Created by Brent Simmons on 4/25/14. 6 | // Copyright (c) 2014 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | 10 | @interface VSLinkButton : UIButton 11 | 12 | 13 | + (UIButton *)linkButtonWithTitle:(NSString *)title; 14 | 15 | 16 | @end 17 | 18 | -------------------------------------------------------------------------------- /Vesper/Classes/VSLinkButtonFooterView.h: -------------------------------------------------------------------------------- 1 | // 2 | // VSLinkButtonFooterView.h 3 | // Vesper 4 | // 5 | // Created by Brent Simmons on 4/27/14. 6 | // Copyright (c) 2014 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | 10 | @class VSLinkButtonFooterView; 11 | 12 | 13 | @protocol VSLinkButtonFooterViewDelegate 14 | 15 | @required 16 | 17 | - (void)linkButtonFooterViewTapped:(VSLinkButtonFooterView *)linkButtonFooterView; 18 | 19 | @end 20 | 21 | 22 | @interface VSLinkButtonFooterView : UIView 23 | 24 | 25 | - (instancetype)initWithText:(NSString *)text delegate:(id)delegate; 26 | 27 | 28 | @end 29 | -------------------------------------------------------------------------------- /Vesper/Classes/VSMainThreadQueue.h: -------------------------------------------------------------------------------- 1 | // 2 | // VSMainThreadQueue.h 3 | // Vesper 4 | // 5 | // Created by Brent Simmons on 5/9/14. 6 | // Copyright (c) 2014 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | 10 | #import "QSBlocks.h" 11 | 12 | 13 | @protocol VSOperation 14 | 15 | - (void)main; 16 | - (void)cancel; 17 | 18 | @property (nonatomic, copy) QSObjectResultBlock completionBlock; 19 | 20 | @end 21 | 22 | 23 | @interface VSMainThreadQueue : NSObject 24 | 25 | 26 | @property (nonatomic) NSUInteger numberOfOperations; 27 | @property (nonatomic) NSUInteger maxOperationsCount; 28 | 29 | - (void)addOperation:(id)operation; 30 | 31 | - (void)cancelOperations; 32 | 33 | @end 34 | -------------------------------------------------------------------------------- /Vesper/Classes/VSMenuButton.h: -------------------------------------------------------------------------------- 1 | // 2 | // VSMenuButton.h 3 | // Vesper 4 | // 5 | // Created by Brent Simmons on 5/6/13. 6 | // Copyright (c) 2013 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | 12 | typedef struct { 13 | CGFloat cornerRadius; 14 | CGFloat borderWidth; 15 | VSTextCaseTransform textCaseTransform; 16 | } VSMenuButtonLayoutBits; 17 | 18 | 19 | @class VSMenuItem; 20 | 21 | @interface VSMenuButton : UIButton 22 | 23 | 24 | - (instancetype)initWithFrame:(CGRect)frame menuItem:(VSMenuItem *)menuItem destructive:(BOOL)destructive popoverSpecifier:(NSString *)popoverSpecifier; 25 | 26 | 27 | @property (nonatomic, weak, readonly) VSMenuItem *menuItem; 28 | @property (nonatomic, assign) VSMenuButtonLayoutBits layoutBits; 29 | @property (nonatomic, strong) UIColor *borderColor; 30 | @property (nonatomic, assign) BOOL destructive; 31 | 32 | - (NSAttributedString *)attributedTitleStringWithColor:(UIColor *)color; 33 | - (NSAttributedString *)attributedTitle; 34 | - (NSAttributedString *)attributedTitlePressed; 35 | 36 | 37 | @end 38 | -------------------------------------------------------------------------------- /Vesper/Classes/VSMenuItem.h: -------------------------------------------------------------------------------- 1 | // 2 | // VSMenuItem.h 3 | // Vesper 4 | // 5 | // Created by Brent Simmons on 5/6/13. 6 | // Copyright (c) 2013 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | 12 | @interface VSMenuItem : NSObject 13 | 14 | @property (nonatomic, strong) NSString *title; 15 | @property (nonatomic, strong) UIImage *image; 16 | @property (nonatomic, strong) id target; 17 | @property (nonatomic, assign) SEL action; 18 | @property (nonatomic, assign) VSPosition position; 19 | 20 | @end 21 | 22 | 23 | -------------------------------------------------------------------------------- /Vesper/Classes/VSMenuItem.m: -------------------------------------------------------------------------------- 1 | // 2 | // VSMenuItem.m 3 | // Vesper 4 | // 5 | // Created by Brent Simmons on 5/6/13. 6 | // Copyright (c) 2013 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | #import "VSMenuItem.h" 10 | 11 | 12 | @implementation VSMenuItem 13 | 14 | @end 15 | 16 | -------------------------------------------------------------------------------- /Vesper/Classes/VSNavbarView.h: -------------------------------------------------------------------------------- 1 | // 2 | // VSNavbarView.h 3 | // Vesper 4 | // 5 | // Created by Brent Simmons on 2/6/13. 6 | // Copyright (c) 2013 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | 12 | @class VSTheme; 13 | 14 | @interface VSNavbarView : UIView 15 | 16 | @property (nonatomic, strong) NSString *title; 17 | @property (nonatomic, assign) BOOL showComposeButton; 18 | 19 | - (void)setupControls; /*Subclasses may override to create and place buttons*/ 20 | - (void)commonInit; /*Subclasses should call super first.*/ 21 | 22 | - (void)setAlphaForSubviews:(CGFloat)alpha; /*For animations*/ 23 | 24 | /*For subclasses*/ 25 | 26 | + (UIImage *)sidebarImage; 27 | + (UIImage *)sidebarImagePressed; 28 | + (UIColor *)buttonTintColor; 29 | + (UIColor *)navbarTitleColor; 30 | 31 | @property (nonatomic, strong) UIButton *sidebarButton; 32 | @property (nonatomic, strong) UIButton *composeButton; 33 | @property (nonatomic, strong) UILabel *titleField; 34 | 35 | @property (nonatomic, assign, readonly) CGFloat statusBarHeight; 36 | @property (nonatomic, assign, readonly) CGFloat heightMinusStatusBar; 37 | 38 | /*Animations*/ 39 | 40 | - (UIImage *)imageForAnimation:(BOOL)includeRightmostButton; 41 | 42 | @property (nonatomic, strong, readonly) UIFont *titleFieldFont; 43 | @property (nonatomic, assign, readonly) CGRect rectForTitleField; 44 | 45 | @end 46 | -------------------------------------------------------------------------------- /Vesper/Classes/VSNoNotesView.h: -------------------------------------------------------------------------------- 1 | // 2 | // VSNoNotesView.h 3 | // Vesper 4 | // 5 | // Created by Brent Simmons on 5/29/13. 6 | // Copyright (c) 2013 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | 12 | @interface VSNoNotesView : UIView 13 | 14 | 15 | - (instancetype)initWithFrame:(CGRect)frame image:(UIImage *)image; 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /Vesper/Classes/VSNoteTextRenderer.h: -------------------------------------------------------------------------------- 1 | // 2 | // VSNoteTextRenderer.h 3 | // Vesper 4 | // 5 | // Created by Brent Simmons on 5/9/13. 6 | // Copyright (c) 2013 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | 13 | extern NSString *VSLinkAttributeName; 14 | extern NSString *VSLinkUniqueIDAttributeName; 15 | extern NSString *VSLinkHighlightedColorAttributeName; 16 | 17 | 18 | @interface VSNoteTextRenderer : NSObject 19 | 20 | 21 | - (instancetype)initWithTitle:(NSString *)title text:(NSString *)text links:(NSArray *)links width:(CGFloat)textWidth useItalicFonts:(BOOL)useItalicFonts truncateIfNeeded:(BOOL)truncateIfNeeded; 22 | 23 | 24 | @property (nonatomic, assign, readonly) CGFloat height; 25 | @property (nonatomic, assign, readonly) BOOL truncated; 26 | 27 | @property (nonatomic, strong, readonly) NSArray *links; 28 | @property (nonatomic, strong, readonly) NSString *fullText; 29 | @property (nonatomic, assign, readonly) NSUInteger maximumNumberOfLines; 30 | 31 | /*These may be nil if links is empty.*/ 32 | 33 | @property (nonatomic, strong, readonly) NSAttributedString *attributedText; 34 | @property (nonatomic, assign, readonly) CTFramesetterRef framesetter; 35 | @property (nonatomic, assign, readonly) CTFrameRef frameref; 36 | 37 | - (void)renderTextInRect:(CGRect)r; 38 | - (void)renderTextInRect:(CGRect)r highlightedLinkID:(id)linkUniqueID; 39 | 40 | 41 | @end 42 | -------------------------------------------------------------------------------- /Vesper/Classes/VSPictureNavbarView.h: -------------------------------------------------------------------------------- 1 | // 2 | // VSPictureNavbarView.h 3 | // Vesper 4 | // 5 | // Created by Brent Simmons on 4/16/13. 6 | // Copyright (c) 2013 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | #import "VSNavbarView.h" 10 | 11 | 12 | @interface VSPictureNavbarView : VSNavbarView 13 | 14 | @property (nonatomic, strong, readonly) UIButton *trashButton; 15 | 16 | @end 17 | -------------------------------------------------------------------------------- /Vesper/Classes/VSPictureViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // VSPictureViewController.h 3 | // Vesper 4 | // 5 | // Created by Brent Simmons on 2/4/13. 6 | // Copyright (c) 2013 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | #import "VSBaseViewController.h" 10 | #import "VSImageScrollView.h" 11 | #import "VSPictureNavbarView.h" 12 | 13 | 14 | @interface VSPictureViewController : VSBaseViewController 15 | 16 | - (instancetype)initWithImage:(UIImage *)image; 17 | 18 | @property (nonatomic, strong, readonly) VSImageScrollView *scrollView; 19 | @property (nonatomic, strong, readonly) VSPictureNavbarView *navbar; 20 | 21 | @property (nonatomic, assign) BOOL readonly; /*Hide trash button if readonly*/ 22 | 23 | @end 24 | -------------------------------------------------------------------------------- /Vesper/Classes/VSPopoverBackgroundView.h: -------------------------------------------------------------------------------- 1 | // 2 | // VSPopoverBackgroundView.h 3 | // Vesper 4 | // 5 | // Created by Brent Simmons on 5/14/13. 6 | // Copyright (c) 2013 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | 12 | @class VSPopoverBackgroundView; 13 | 14 | @protocol VSPopoverBackgroundViewDelegate 15 | 16 | @required 17 | - (void)didTapPopoverBackgroundView:(VSPopoverBackgroundView *)popoverBackgroundView; 18 | 19 | @end 20 | 21 | 22 | @interface VSPopoverBackgroundView : UIView 23 | 24 | - (id)initWithFrame:(CGRect)frame popoverSpecifier:(NSString *)popoverSpecifier delegate:(id)delegate; 25 | 26 | - (void)restoreInitialAlpha; 27 | 28 | @end 29 | -------------------------------------------------------------------------------- /Vesper/Classes/VSProgressCircleView.h: -------------------------------------------------------------------------------- 1 | // 2 | // VSProgressCircleView.h 3 | // Vesper 4 | // 5 | // Created by Brent Simmons on 4/30/14. 6 | // Copyright (c) 2014 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | 10 | @interface VSProgressCircleView : UIView 11 | 12 | 13 | - (instancetype)initWithFrame:(CGRect)frame circleWidth:(CGFloat)circleWidth; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /Vesper/Classes/VSProgressView.h: -------------------------------------------------------------------------------- 1 | // 2 | // VSProgressView.h 3 | // Vesper 4 | // 5 | // Created by Brent Simmons on 4/30/14. 6 | // Copyright (c) 2014 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | 10 | @interface VSProgressView : UIView 11 | 12 | 13 | - (void)startAnimating; 14 | - (void)stopAnimating; 15 | - (BOOL)isAnimating; 16 | 17 | 18 | @end 19 | -------------------------------------------------------------------------------- /Vesper/Classes/VSPullToRefreshView.h: -------------------------------------------------------------------------------- 1 | // 2 | // VSPullToRefreshView.h 3 | // Vesper 4 | // 5 | // Created by Brent Simmons on 3/2/13. 6 | // Copyright (c) 2013 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | 12 | typedef enum { 13 | VSPullToRefreshIdle, 14 | VSPullToRefreshPulling, 15 | VSPullToRefreshLoading, 16 | } VSPullToRefreshState; 17 | 18 | 19 | @class VSPullToRefreshView; 20 | 21 | 22 | @protocol VSPullToRefreshDelegate 23 | 24 | - (void)refreshViewDidTriggerRefresh:(VSPullToRefreshView *)view; 25 | - (BOOL)refreshViewIsRefreshing:(VSPullToRefreshView *)view; 26 | 27 | @end 28 | 29 | 30 | @interface VSPullToRefreshView : UIView 31 | 32 | - (id)initWithFrame:(CGRect)frame scrollView:(UIScrollView *)scrollView delegate:(id)delegate; 33 | 34 | @property (nonatomic, assign) BOOL refreshInProgress; 35 | 36 | @end 37 | -------------------------------------------------------------------------------- /Vesper/Classes/VSRootViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // VSRootViewController.h 3 | // Vesper 4 | // 5 | // Created by Brent Simmons on 11/18/12. 6 | // Copyright (c) 2012 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | #import "VSBaseViewController.h" 10 | #import "VSRootViewManager.h" 11 | 12 | 13 | /*Manages two child controllers: 14 | 15 | 1. Sidebar - VSSidebarViewController 16 | 2. Main view - VSListViewController, usually 17 | 18 | */ 19 | 20 | 21 | @interface VSRootViewController : VSBaseViewController 22 | 23 | 24 | @property (nonatomic, strong, readonly) UIViewController *dataViewController; /*the non-sidebar view controller: timeline or credits etc.; may have other views on top by z-axis*/ 25 | 26 | 27 | @end 28 | -------------------------------------------------------------------------------- /Vesper/Classes/VSRootViewManager.h: -------------------------------------------------------------------------------- 1 | // 2 | // VSRootViewManager.h 3 | // Vesper 4 | // 5 | // Created by Brent Simmons on 2/8/13. 6 | // Copyright (c) 2013 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | 12 | @protocol VSRootViewManager 13 | 14 | @required 15 | 16 | - (void)showViewController:(UIViewController *)viewController; 17 | 18 | 19 | @end 20 | -------------------------------------------------------------------------------- /Vesper/Classes/VSRowHeightCache.h: -------------------------------------------------------------------------------- 1 | // 2 | // VSRowHeightCache.h 3 | // Vesper 4 | // 5 | // Created by Brent Simmons on 3/29/13. 6 | // Copyright (c) 2013 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | 10 | 11 | @class VSTimelineNote; 12 | 13 | 14 | @interface VSRowHeightCache : NSObject 15 | 16 | 17 | + (instancetype)sharedCache; 18 | 19 | - (CGFloat)cachedHeightForTimelineNote:(VSTimelineNote *)timelineNote; /*Returns 0.0f if not cached.*/ 20 | 21 | - (void)cacheHeight:(CGFloat)height forTimelineNote:(VSTimelineNote *)timelineNote; 22 | 23 | - (void)empty; 24 | 25 | @end 26 | 27 | -------------------------------------------------------------------------------- /Vesper/Classes/VSSQLDataController.h: -------------------------------------------------------------------------------- 1 | // 2 | // VSSQLDataController.h 3 | // Vesper 4 | // 5 | // Created by Brent Simmons on 2/20/14. 6 | // Copyright (c) 2014 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | 10 | @import Foundation; 11 | 12 | @interface VSSQLDataController : NSObject 13 | 14 | 15 | - (void)deletedNoteIDs:(QSFetchResultsBlock)fetchResultsBlock; /*Fetch results is array of clientIDs.*/ 16 | 17 | - (void)addDeletedNoteClientIDs:(NSArray *)clientIDs; 18 | 19 | - (void)removeDeletedNoteClientIDs:(NSArray *)clientIDs; 20 | 21 | 22 | @end 23 | -------------------------------------------------------------------------------- /Vesper/Classes/VSSearchBarContainerView.h: -------------------------------------------------------------------------------- 1 | // 2 | // VSSearchBarContainerView.h 3 | // Vesper 4 | // 5 | // Created by Brent Simmons on 3/20/13. 6 | // Copyright (c) 2013 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface VSSearchBarContainerView : UIView 12 | 13 | @property (nonatomic, strong, readonly) UISearchBar *searchBar; 14 | @property (nonatomic, assign) BOOL hasShadow; 15 | @property (nonatomic, strong, readonly) UIImageView *shadowImageView; 16 | @property (nonatomic, assign) BOOL inSearchMode; 17 | 18 | - (void)enableCancelButton; /*A hack, unfortunately. The system disables it once the keyboard disappears.*/ 19 | 20 | @end 21 | -------------------------------------------------------------------------------- /Vesper/Classes/VSSearchResultsToDetailAnimator.h: -------------------------------------------------------------------------------- 1 | // 2 | // VSSearchResultsToDetailAnimator.h 3 | // Vesper 4 | // 5 | // Created by Brent Simmons on 3/17/14. 6 | // Copyright (c) 2014 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | 10 | 11 | @class VSNote; 12 | @class VSTimelineViewController; 13 | @class VSDetailViewController; 14 | @class VSSearchResultsViewController; 15 | 16 | 17 | @interface VSSearchResultsToDetailAnimator : NSObject 18 | 19 | 20 | - (instancetype)initWithNote:(VSNote *)note timelineNote:(VSTimelineNote *)timelineNote indexPath:(NSIndexPath *)indexPath image:(UIImage *)image searchResultsViewController:(VSSearchResultsViewController *)searchResultsViewController timelineViewController:(VSTimelineViewController *)timelineViewController detailViewController:(VSDetailViewController *)detailViewController; 21 | 22 | - (void)animate:(QSVoidCompletionBlock)completion; 23 | 24 | 25 | 26 | @end 27 | -------------------------------------------------------------------------------- /Vesper/Classes/VSSearchResultsViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // VSSearchResultsViewController.h 3 | // Vesper 4 | // 5 | // Created by Brent Simmons on 3/29/13. 6 | // Copyright (c) 2013 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | #import "VSBaseViewController.h" 10 | 11 | 12 | @class VSTimelineViewController; 13 | @class VSNote; 14 | @class VSTag; 15 | @class VSTimelineContext; 16 | 17 | 18 | @interface VSSearchResultsViewController : VSBaseViewController 19 | 20 | 21 | - (instancetype)initWithContext:(VSTimelineContext *)context includeArchivedNotes:(BOOL)includeArchivedNotes archivedNotesOnly:(BOOL)archivedNotesOnly timelineViewController:(VSTimelineViewController *)timelineViewController; 22 | 23 | @property (nonatomic, strong) NSString *searchString; /*Setting searchString causes it to run the search.*/ 24 | @property (nonatomic, strong, readonly) UITableView *tableView; 25 | @property (nonatomic, strong) VSTimelineNote *draggedNote; 26 | 27 | - (void)detailViewDone:(id)sender; 28 | - (void)detailViewDoneViaPanBackAnimation:(id)sender; 29 | 30 | /*Pan-back animation support.*/ 31 | 32 | - (UIImage *)dragImageForNote:(VSNote *)note; 33 | - (CGRect)frameOfCellForNote:(VSNote *)note; 34 | - (void)prepareForPanBackAnimationWithNote:(VSNote *)note; 35 | - (UIView *)tableAnimationView; 36 | 37 | @end 38 | -------------------------------------------------------------------------------- /Vesper/Classes/VSSidebarArchiveStatusController.h: -------------------------------------------------------------------------------- 1 | // 2 | // VSSidebarArchiveStatusController.h 3 | // Vesper 4 | // 5 | // Created by Brent Simmons on 5/15/14. 6 | // Copyright (c) 2014 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | 10 | @interface VSSidebarArchiveStatusController : NSObject 11 | 12 | @property (nonatomic, readonly) BOOL hasAtLeastOneArchivedNote; // Observable 13 | 14 | @end 15 | -------------------------------------------------------------------------------- /Vesper/Classes/VSSidebarTableViewCell.h: -------------------------------------------------------------------------------- 1 | // 2 | // VSSidebarTableViewCell.h 3 | // Vesper 4 | // 5 | // Created by Brent Simmons on 2/9/13. 6 | // Copyright (c) 2013 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | 10 | @import UIKit; 11 | 12 | 13 | @interface VSSidebarTableViewCell : UITableViewCell 14 | 15 | @property (nonatomic, assign) BOOL showIcon; 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /Vesper/Classes/VSSidebarTagsController.h: -------------------------------------------------------------------------------- 1 | // 2 | // VSSidebarTagsController.h 3 | // Vesper 4 | // 5 | // Created by Brent Simmons on 10/22/13. 6 | // Copyright (c) 2013 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | 10 | @interface VSSidebarTagsController : NSObject 11 | 12 | @property (nonatomic, readonly) NSArray *orderedTags; // Observable 13 | 14 | @end 15 | -------------------------------------------------------------------------------- /Vesper/Classes/VSSidebarUntaggedStatusController.h: -------------------------------------------------------------------------------- 1 | // 2 | // VSSidebarUntaggedStatusController.h 3 | // Vesper 4 | // 5 | // Created by Brent Simmons on 6/9/14. 6 | // Copyright (c) 2014 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | 10 | @interface VSSidebarUntaggedStatusController : NSObject 11 | 12 | 13 | @property (nonatomic, readonly) BOOL hasAtLeastOneUntaggedNote; // Observable 14 | 15 | 16 | @end 17 | -------------------------------------------------------------------------------- /Vesper/Classes/VSSidebarView.h: -------------------------------------------------------------------------------- 1 | // 2 | // VSSidebarView.h 3 | // Vesper 4 | // 5 | // Created by Brent Simmons on 5/27/13. 6 | // Copyright (c) 2013 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | 10 | @import UIKit; 11 | 12 | @interface VSSidebarView : UIToolbar 13 | 14 | 15 | @property (nonatomic, strong) UITableView *tableView; 16 | @property (nonatomic, strong) UIView *backgroundView; 17 | 18 | @property (nonatomic, assign) CGFloat originX; 19 | 20 | /*Call from within animation blocks.*/ 21 | 22 | - (void)moveToSidebarOpenPosition; 23 | - (void)moveToSidebarClosedPosition; 24 | 25 | 26 | @end 27 | -------------------------------------------------------------------------------- /Vesper/Classes/VSSidebarViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // VSSidebarViewController.h 3 | // Vesper 4 | // 5 | // Created by Brent Simmons on 11/18/12. 6 | // Copyright (c) 2012 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | #import "VSBaseViewController.h" 10 | #import "VSRootViewManager.h" 11 | 12 | 13 | @class VSTag; 14 | @class VSSidebarView; 15 | @class VSListViewController; 16 | 17 | 18 | @interface VSSidebarViewController : VSBaseViewController 19 | 20 | @property (nonatomic, weak) id rootViewManager; 21 | @property (nonatomic, strong) VSSidebarView *sidebarView; 22 | 23 | - (void)selectRowForTag:(VSTag *)tag; /*Updates selection in table view. Doesn't do anything else.*/ 24 | 25 | - (void)showInitialViewController; 26 | 27 | @end 28 | 29 | -------------------------------------------------------------------------------- /Vesper/Classes/VSSignInFooterView.h: -------------------------------------------------------------------------------- 1 | // 2 | // VSSignInFooterView.h 3 | // Vesper 4 | // 5 | // Created by Brent Simmons on 5/20/14. 6 | // Copyright (c) 2014 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | 10 | @protocol VSSignInFooterViewDelegate 11 | 12 | @required 13 | 14 | - (void)privacyPolicyTapped:(id)sender; 15 | - (void)forgotPasswordTapped:(id)sender; 16 | 17 | @end 18 | 19 | 20 | @interface VSSignInFooterView : UIView 21 | 22 | 23 | - (instancetype)initWithFrame:(CGRect)frame delegate:(id)delegate; 24 | 25 | 26 | @end 27 | -------------------------------------------------------------------------------- /Vesper/Classes/VSSmokescreenView.h: -------------------------------------------------------------------------------- 1 | // 2 | // VSSmokescreenView.h 3 | // Vesper 4 | // 5 | // Created by Brent Simmons on 4/30/13. 6 | // Copyright (c) 2013 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | 12 | @interface VSSmokescreenView : UIView 13 | 14 | 15 | - (id)initWithFrame:(CGRect)frame backgroundColor:(UIColor *)backgroundColor; 16 | 17 | 18 | - (void)incrementUseCount; 19 | - (void)decrementUseCount; 20 | 21 | @property (nonatomic, assign, readonly) NSUInteger useCount; 22 | 23 | @end 24 | -------------------------------------------------------------------------------- /Vesper/Classes/VSSmokescreenView.m: -------------------------------------------------------------------------------- 1 | // 2 | // VSSmokescreenView.m 3 | // Vesper 4 | // 5 | // Created by Brent Simmons on 4/30/13. 6 | // Copyright (c) 2013 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | #import "VSSmokescreenView.h" 10 | 11 | 12 | @interface VSSmokescreenView () 13 | 14 | @property (nonatomic, assign, readwrite) NSUInteger useCount; 15 | @end 16 | 17 | 18 | @implementation VSSmokescreenView 19 | 20 | 21 | #pragma mark - Init 22 | 23 | - (id)initWithFrame:(CGRect)frame backgroundColor:(UIColor *)backgroundColor { 24 | 25 | self = [super initWithFrame:frame]; 26 | if (self == nil) 27 | return nil; 28 | 29 | self.backgroundColor = backgroundColor; 30 | self.opaque = YES; 31 | 32 | return self; 33 | } 34 | 35 | 36 | #pragma mark - Use Count 37 | 38 | - (void)incrementUseCount { 39 | self.useCount = self.useCount + 1; 40 | } 41 | 42 | 43 | - (void)decrementUseCount { 44 | self.useCount = self.useCount - 1; 45 | } 46 | 47 | 48 | @end 49 | -------------------------------------------------------------------------------- /Vesper/Classes/VSStatusBarNotification.h: -------------------------------------------------------------------------------- 1 | // 2 | // VSStatusBarNotification.h 3 | // Vesper 4 | // 5 | // Created by Brent Simmons on 5/3/14. 6 | // Copyright (c) 2014 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | 10 | 11 | @interface VSStatusBarNotification : NSObject 12 | 13 | 14 | - (instancetype)initWithView:(UIView *)view; 15 | 16 | - (void)show; 17 | - (void)hide; 18 | 19 | 20 | @end 21 | -------------------------------------------------------------------------------- /Vesper/Classes/VSStatusBarNotificationView.h: -------------------------------------------------------------------------------- 1 | // 2 | // VSStatusBarNotificationView.h 3 | // Vesper 4 | // 5 | // Created by Brent Simmons on 5/3/14. 6 | // Copyright (c) 2014 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | 10 | @interface VSStatusBarNotificationView : UIView 11 | 12 | 13 | - (instancetype)initWithIconName:(NSString *)iconName text:(NSString *)s; 14 | 15 | 16 | @end 17 | -------------------------------------------------------------------------------- /Vesper/Classes/VSSyncChangePasswordViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // VSSyncChangePasswordViewController.h 3 | // Vesper 4 | // 5 | // Created by Brent Simmons on 2/7/14. 6 | // Copyright (c) 2014 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | 10 | @interface VSSyncChangePasswordViewController : UIViewController 11 | 12 | @end 13 | -------------------------------------------------------------------------------- /Vesper/Classes/VSSyncContainerViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // VSSyncContainerViewController.h 3 | // Vesper 4 | // 5 | // Created by Brent Simmons on 2/7/14. 6 | // Copyright (c) 2014 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | 10 | 11 | @interface VSSyncContainerViewController : UIViewController 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /Vesper/Classes/VSSyncCreateAccountViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // VSSyncCreateAccountViewController.h 3 | // Vesper 4 | // 5 | // Created by Brent Simmons on 2/7/14. 6 | // Copyright (c) 2014 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | 10 | @interface VSSyncCreateAccountViewController : UIViewController 11 | 12 | @end 13 | -------------------------------------------------------------------------------- /Vesper/Classes/VSSyncForgotPasswordViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // VSSyncForgotPasswordViewController.h 3 | // Vesper 4 | // 5 | // Created by Brent Simmons on 5/20/14. 6 | // Copyright (c) 2014 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | 10 | NSString *VSSyncForgotPasswordEmailAddressUsedNotification; 11 | NSString *VSSyncForgotPasswordEmailAddress; 12 | 13 | 14 | @interface VSSyncForgotPasswordViewController : UIViewController 15 | 16 | 17 | - (instancetype)initWithEmailAddress:(NSString *)emailAddress; 18 | 19 | @end 20 | -------------------------------------------------------------------------------- /Vesper/Classes/VSSyncNoAccountHeaderView.h: -------------------------------------------------------------------------------- 1 | // 2 | // VSSyncNoAccountHeaderView.h 3 | // Vesper 4 | // 5 | // Created by Brent Simmons on 4/25/14. 6 | // Copyright (c) 2014 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | 10 | @interface VSSyncNoAccountHeaderView : UIView 11 | 12 | 13 | //- (void)updateLabelWidth:(CGFloat)superviewWidth; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /Vesper/Classes/VSSyncNoAccountViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // VSSyncNoAccountViewController.h 3 | // Vesper 4 | // 5 | // Created by Brent Simmons on 2/7/14. 6 | // Copyright (c) 2014 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | 10 | @interface VSSyncNoAccountViewController : UIViewController 11 | 12 | @end 13 | -------------------------------------------------------------------------------- /Vesper/Classes/VSSyncNote.h: -------------------------------------------------------------------------------- 1 | // 2 | // VSSyncNote.h 3 | // Vesper 4 | // 5 | // Created by Brent Simmons on 11/5/13. 6 | // Copyright (c) 2013 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | 10 | @interface VSSyncNote : VSSyncObject 11 | 12 | 13 | 14 | @property (nonatomic) NSNumber *clientID; 15 | @property (nonatomic) NSDate *creationDate; 16 | 17 | @property (nonatomic) NSString *text; 18 | @property (nonatomic) NSDate *textModificationDate; 19 | 20 | @property (nonatomic, assign) BOOL archived; 21 | @property (nonatomic) NSDate *archivedModificationDate; 22 | 23 | @property (nonatomic) NSDate *sortDate; 24 | @property (nonatomic) NSDate *sortDateModificationDate; 25 | 26 | @property (nonatomic) NSArray *tagUniqueIDs; 27 | @property (nonatomic) NSDate *tagsModificationDate; 28 | 29 | @property (nonatomic) NSArray *attachments; 30 | @property (nonatomic) NSDate *attachmentsModificationDate; 31 | 32 | 33 | @end 34 | -------------------------------------------------------------------------------- /Vesper/Classes/VSSyncNoteMerger.h: -------------------------------------------------------------------------------- 1 | // 2 | // VSSyncNoteMerger.h 3 | // Vesper 4 | // 5 | // Created by Brent Simmons on 11/12/13. 6 | // Copyright (c) 2013 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | 10 | 11 | void VSSyncMergeNotes(NSArray *JSONNotes, VSDataController *dataController, QSVoidCompletionBlock completion); 12 | 13 | -------------------------------------------------------------------------------- /Vesper/Classes/VSSyncSettingsViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // VSSyncSettingsViewController.h 3 | // Vesper 4 | // 5 | // Created by Brent Simmons on 2/7/14. 6 | // Copyright (c) 2014 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | 10 | @interface VSSyncSettingsViewController : UIViewController 11 | 12 | @end 13 | -------------------------------------------------------------------------------- /Vesper/Classes/VSSyncSignInViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // VSSyncSignInViewController.h 3 | // Vesper 4 | // 5 | // Created by Brent Simmons on 2/7/14. 6 | // Copyright (c) 2014 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | 10 | @interface VSSyncSignInViewController : UIViewController 11 | 12 | @end 13 | -------------------------------------------------------------------------------- /Vesper/Classes/VSSyncTagMerger.h: -------------------------------------------------------------------------------- 1 | // 2 | // VSSyncTagMerger.h 3 | // Vesper 4 | // 5 | // Created by Brent Simmons on 11/9/13. 6 | // Copyright (c) 2013 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | 10 | void VSSyncMergeTags(NSArray *JSONTags, VSDataController *dataController, QSVoidCompletionBlock completion); 11 | -------------------------------------------------------------------------------- /Vesper/Classes/VSSyncTagMerger.m: -------------------------------------------------------------------------------- 1 | // 2 | // VSSyncTagMerger.m 3 | // Vesper 4 | // 5 | // Created by Brent Simmons on 11/9/13. 6 | // Copyright (c) 2013 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | #import "VSSyncTagMerger.h" 10 | #import "VSSyncUtilities.h" 11 | 12 | 13 | static BOOL mergeTag(NSDictionary *JSONTag, VSTag *existingTag) { 14 | 15 | return VSSyncProperty(existingTag, JSONTag, @"name"); 16 | } 17 | 18 | 19 | void VSSyncMergeTags(NSArray *JSONTags, VSDataController *dataController, QSVoidCompletionBlock completion) { 20 | 21 | NSMutableArray *tagsToSave = [NSMutableArray new]; 22 | 23 | for (NSDictionary *oneJSONTag in JSONTags) { 24 | 25 | NSString *oneSyncTagName = oneJSONTag[VSSyncNameKey]; 26 | if (QSStringIsEmpty(oneSyncTagName)) { 27 | continue; 28 | } 29 | 30 | VSTag *oneTag = [[VSDataController sharedController] tagWithName:oneSyncTagName]; 31 | if (mergeTag(oneJSONTag, oneTag)) { 32 | [tagsToSave addObject:oneTag]; 33 | } 34 | } 35 | 36 | [dataController saveTags:[tagsToSave copy]]; 37 | 38 | QSCallCompletionBlock(completion); 39 | } 40 | -------------------------------------------------------------------------------- /Vesper/Classes/VSSyncUtilities.h: -------------------------------------------------------------------------------- 1 | // 2 | // VSSyncUtilities.h 3 | // Vesper 4 | // 5 | // Created by Brent Simmons on 11/9/13. 6 | // Copyright (c) 2013 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | 10 | BOOL VSSyncObjectHasLaterDate(NSDate *syncObjectDate, NSDate *existingObjectDate); 11 | 12 | 13 | /*Returns YES if existingObject got updated.*/ 14 | 15 | BOOL VSSyncProperty(id existingObject, id syncObject, NSString *propertyName); 16 | -------------------------------------------------------------------------------- /Vesper/Classes/VSTag.h: -------------------------------------------------------------------------------- 1 | // 2 | // VSTag.h 3 | // Vesper 4 | // 5 | // Created by Brent Simmons on 9/27/13. 6 | // Copyright (c) 2013 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | 10 | #import "QSAPIObject.h" 11 | 12 | @interface VSTag : NSObject 13 | 14 | 15 | /*Mutable: name may change in case. nameModificationDate may change.*/ 16 | 17 | 18 | - (instancetype)initWithName:(NSString *)name; 19 | 20 | @property (nonatomic, readonly) NSString *uniqueID; /*Normalized name; lower-cased.*/ 21 | @property (nonatomic) NSString *name; 22 | @property (nonatomic) NSDate *nameModificationDate; 23 | 24 | + (NSString *)uniqueIDForTagName:(NSString *)name; 25 | + (NSString *)normalizedTagName:(NSString *)name; 26 | 27 | 28 | @end 29 | -------------------------------------------------------------------------------- /Vesper/Classes/VSTagButton.h: -------------------------------------------------------------------------------- 1 | // 2 | // VSTagButton.h 3 | // Vesper 4 | // 5 | // Created by Brent Simmons on 4/10/13. 6 | // Copyright (c) 2013 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "VSEditableTagView.h" 11 | 12 | 13 | @class VSTagProxy; 14 | @class VSTagPopover; 15 | 16 | @interface VSTagButton : UIButton 17 | 18 | + (CGSize)sizeWithTitle:(NSString *)title; 19 | + (instancetype)buttonWithTagProxy:(VSTagProxy *)tagProxy; 20 | 21 | @property (nonatomic, strong, readonly) NSString *title; 22 | @property (nonatomic, strong, readonly) VSTagProxy *tagProxy; 23 | 24 | @end 25 | -------------------------------------------------------------------------------- /Vesper/Classes/VSTagDetailScrollView.h: -------------------------------------------------------------------------------- 1 | // 2 | // VSTagDetailScrollView.h 3 | // Vesper 4 | // 5 | // Created by Brent Simmons on 4/10/13. 6 | // Copyright (c) 2013 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | 12 | extern NSString *VSEditingTagViewOriginXDidChangeNotification; 13 | extern NSString *VSEditingTagViewOriginXKey; 14 | extern NSString *VSNewTagShouldStartNotification; 15 | extern NSString *VSTagsDidEndEditingNotification; 16 | 17 | 18 | @class VSTagButton; 19 | 20 | 21 | @interface VSTagDetailScrollView : UIScrollView 22 | 23 | 24 | - (instancetype)initWithFrame:(CGRect)frame tagProxies:(NSArray *)tagProxies; 25 | 26 | @property (nonatomic, strong, readonly) NSArray *tagProxies; 27 | @property (nonatomic, strong, readonly) NSArray *nonEditingTagProxies; /*Skips textField and ghost tag proxies*/ 28 | 29 | @property (nonatomic, assign) BOOL readonly; 30 | 31 | - (void)userChoseSuggestedTagName:(NSString *)tagName; 32 | 33 | - (void)deleteTagButton:(VSTagButton *)tagButton; 34 | 35 | - (void)updateWithTagProxies:(NSArray *)tagProxies; 36 | 37 | 38 | @end 39 | -------------------------------------------------------------------------------- /Vesper/Classes/VSTagPopover.h: -------------------------------------------------------------------------------- 1 | // 2 | // VSTagPopover.h 3 | // Vesper 4 | // 5 | // Created by Brent Simmons on 5/23/13. 6 | // Copyright (c) 2013 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | #import "VSIconGridPopover.h" 10 | 11 | 12 | @class VSTagProxy; 13 | 14 | @interface VSTagPopover : VSIconGridPopover 15 | 16 | @property (nonatomic, strong) VSTagProxy *tagProxy; 17 | 18 | @end 19 | -------------------------------------------------------------------------------- /Vesper/Classes/VSTagPopoverButton.h: -------------------------------------------------------------------------------- 1 | // 2 | // VSTagPopoverButton.h 3 | // Vesper 4 | // 5 | // Created by Brent Simmons on 5/23/13. 6 | // Copyright (c) 2013 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | 12 | @class VSMenuItem; 13 | 14 | 15 | @interface VSTagPopoverButton : UIButton 16 | 17 | 18 | - (instancetype)initWithFrame:(CGRect)frame menuItem:(VSMenuItem *)menuItem destructive:(BOOL)destructive popoverSpecifier:(NSString *)popoverSpecifier; 19 | 20 | 21 | @property (nonatomic, weak, readonly) VSMenuItem *menuItem; 22 | 23 | + (CGFloat)widthOfButtonWithTitle:(NSString *)title popoverSpecifier:(NSString *)popoverSpecifier; 24 | 25 | 26 | @end 27 | -------------------------------------------------------------------------------- /Vesper/Classes/VSTagProxy.h: -------------------------------------------------------------------------------- 1 | // 2 | // VSTagProxy.h 3 | // Vesper 4 | // 5 | // Created by Brent Simmons on 4/11/13. 6 | // Copyright (c) 2013 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | 12 | /*Used by VSDetailViewController. Probably not useful elsewhere.*/ 13 | 14 | @class VSTag; 15 | 16 | 17 | @interface VSTagProxy : NSObject 18 | 19 | 20 | @property (nonatomic, strong) VSTag *tag; /*May be nil.*/ 21 | @property (nonatomic, strong, readonly) VSTag *initialTag; /*May be nil; tag may change; this won't*/ 22 | @property (nonatomic, strong) NSString *name; /*May be nil.*/ 23 | @property (nonatomic, strong, readonly) NSString *normalizedName; /*May be nil; calculated on demand*/ 24 | @property (nonatomic, assign) BOOL isEditing; 25 | @property (nonatomic, assign, readonly) BOOL isGhostTag; 26 | 27 | + (instancetype)tagProxyWithTag:(VSTag *)tag; 28 | + (NSArray *)tagProxiesWithTags:(NSArray *)tags; 29 | 30 | + (instancetype)tagProxyWithName:(NSString *)name; 31 | 32 | - (void)createTagIfNeeded; 33 | 34 | @end 35 | 36 | 37 | @interface VSGhostTagProxy : VSTagProxy 38 | 39 | + (instancetype)ghostTagProxy; 40 | 41 | @end 42 | 43 | -------------------------------------------------------------------------------- /Vesper/Classes/VSTagSuggester.h: -------------------------------------------------------------------------------- 1 | // 2 | // VSTagSuggester.h 3 | // Vesper 4 | // 5 | // Created by Brent Simmons on 3/30/14. 6 | // Copyright (c) 2014 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | 10 | @interface VSTagSuggester : NSObject 11 | 12 | 13 | + (NSArray *)tags:(NSArray *)tags matchingSearchString:(NSString *)searchString; 14 | 15 | 16 | @end 17 | -------------------------------------------------------------------------------- /Vesper/Classes/VSTagSuggestionButton.h: -------------------------------------------------------------------------------- 1 | // 2 | // VSTagSuggestionButton.h 3 | // Vesper 4 | // 5 | // Created by Brent Simmons on 4/10/13. 6 | // Copyright (c) 2013 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | 12 | @interface VSTagSuggestionButton : UIButton 13 | 14 | + (CGSize)sizeWithTitle:(NSString *)title; 15 | 16 | + (instancetype)buttonWithTitle:(NSString *)title; 17 | 18 | @property (nonatomic, strong, readonly) NSString *tagName; /*Get this when pressed.*/ 19 | 20 | @end 21 | -------------------------------------------------------------------------------- /Vesper/Classes/VSTagSuggestionButtonsContainerView.h: -------------------------------------------------------------------------------- 1 | // 2 | // VSTagSuggestionButtonsContainerView.h 3 | // Vesper 4 | // 5 | // Created by Brent Simmons on 4/12/13. 6 | // Copyright (c) 2013 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | 12 | @interface VSTagSuggestionButtonsContainerView : UIView 13 | 14 | 15 | @property (nonatomic, strong) NSArray *buttons; 16 | //@property (nonatomic, assign, readonly) CGFloat buttonsWidth; 17 | @property (nonatomic, assign, readonly) CGFloat bubbleWidth; 18 | 19 | @end 20 | -------------------------------------------------------------------------------- /Vesper/Classes/VSTagSuggestionView.h: -------------------------------------------------------------------------------- 1 | // 2 | // VSTagSuggestionView.h 3 | // Vesper 4 | // 5 | // Created by Brent Simmons on 4/9/13. 6 | // Copyright (c) 2013 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | 12 | @class VSTagSuggestionView; 13 | 14 | @protocol VSTagSuggestionViewDelegate 15 | 16 | @required 17 | 18 | - (void)tagSuggestionView:(VSTagSuggestionView *)tagSuggestionView didChooseTagName:(NSString *)tagName; 19 | 20 | @end 21 | 22 | 23 | @interface VSTagSuggestionView : UIView 24 | 25 | + (CGSize)size; 26 | 27 | - (instancetype)initWithFrame:(CGRect)frame delegate:(id)delegate; 28 | 29 | 30 | @property (nonatomic, strong) NSSet *tagNamesForNote; /*tag names the note already has*/ 31 | 32 | /*Setting userTypeTag will animate showing the view if needed -- if there's something to suggest and the view isn't already open. Setting it to nil or @"" will animate closing the view.*/ 33 | 34 | @property (nonatomic, strong) NSString *userTypedTag; 35 | 36 | @end 37 | -------------------------------------------------------------------------------- /Vesper/Classes/VSTagTextFieldContainerView.h: -------------------------------------------------------------------------------- 1 | // 2 | // VSTagTextFieldContainerView.h 3 | // Vesper 4 | // 5 | // Created by Brent Simmons on 4/12/13. 6 | // Copyright (c) 2013 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | 12 | @class VSTagProxy; 13 | 14 | extern NSString *VSTagDidBeginEditingNotification; 15 | extern NSString *VSTagKey; 16 | 17 | @interface VSTagTextFieldContainerView : UIView 18 | 19 | 20 | + (CGSize)initialSize; 21 | + (instancetype)tagTextFieldContainerViewWithTagProxy:(VSTagProxy *)tagProxy; 22 | 23 | - (instancetype)initWithFrame:(CGRect)frame tagProxy:(VSTagProxy *)tagProxy; 24 | 25 | @property (nonatomic, strong, readonly) VSTagProxy *tagProxy; 26 | 27 | @property (nonatomic, assign, readonly) BOOL editing; 28 | @property (nonatomic, strong, readonly) NSString *text; 29 | @property (nonatomic, strong) NSString *userAcceptedSuggestedTag; /*Setting this changes the text*/ 30 | 31 | - (void)beginEditing; /*text field becomes first responder*/ 32 | - (void)updateTextForTagProxy; 33 | 34 | 35 | @end 36 | -------------------------------------------------------------------------------- /Vesper/Classes/VSTagsManager.h: -------------------------------------------------------------------------------- 1 | // 2 | // VSTagsManager.h 3 | // Vesper 4 | // 5 | // Created by Brent Simmons on 2/6/13. 6 | // Copyright (c) 2013 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | 12 | /*Main thread only.*/ 13 | 14 | @class VSTag; 15 | 16 | @interface VSTagsManager : NSObject 17 | 18 | 19 | //- (id)initWithManagedObjectContext:(NSManagedObjectContext *)moc; 20 | 21 | /*Both of these are observable.*/ 22 | 23 | @property (nonatomic, strong, readonly) NSSet *tags; 24 | @property (nonatomic, strong, readonly) NSSet *tagNames; 25 | 26 | //- (VSTag *)existingTagWithName:(NSString *)tagName; 27 | 28 | @end 29 | -------------------------------------------------------------------------------- /Vesper/Classes/VSTestDataImporter.h: -------------------------------------------------------------------------------- 1 | // 2 | // VSTestDataImporter.h 3 | // Vesper 4 | // 5 | // Created by Brent Simmons on 3/16/13. 6 | // Copyright (c) 2013 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | 10 | #if TESTING_DATABASE 11 | 12 | @class VSDataController; 13 | 14 | void importTweets(VSDataController *dataController); 15 | void importDaringFireball(VSDataController *dataController); 16 | 17 | #endif 18 | -------------------------------------------------------------------------------- /Vesper/Classes/VSTextRendererView.h: -------------------------------------------------------------------------------- 1 | // 2 | // VSTextRendererView.h 3 | // Vesper 4 | // 5 | // Created by Brent Simmons on 5/21/13. 6 | // Copyright (c) 2013 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | 12 | @class VSNoteTextRenderer; 13 | 14 | @interface VSTextRendererView : UIView 15 | 16 | @property (nonatomic, assign) BOOL highlightingLink; 17 | @property (nonatomic, strong) id highlightedLinkID; 18 | @property (nonatomic, strong) VSNoteTextRenderer *textRenderer; 19 | 20 | 21 | @end 22 | -------------------------------------------------------------------------------- /Vesper/Classes/VSTextView.h: -------------------------------------------------------------------------------- 1 | // 2 | // VSTextView.h 3 | // Vesper 4 | // 5 | // Created by Brent Simmons on 2/8/13. 6 | // Copyright (c) 2013 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | 12 | @class VSNoteTextRenderer; 13 | 14 | @interface VSTextView : UIView 15 | 16 | @property (nonatomic, strong) UIColor *highlightedLinkBackgroundColor; 17 | @property (nonatomic, strong) VSNoteTextRenderer *textRenderer; 18 | @property (nonatomic, assign, readonly) BOOL truncated; 19 | @property (nonatomic, assign, readonly) CGFloat widthOfTruncatedLine; /*return is undefined if not truncated*/ 20 | @property (nonatomic, assign, readonly) UIEdgeInsets edgeInsets; /*Make room for drawing outside text for rounded corners for links*/ 21 | 22 | + (CGRect)fullRectForApparentRect:(CGRect)apparentRect; /*Adds edgeInsets*/ 23 | 24 | @end 25 | -------------------------------------------------------------------------------- /Vesper/Classes/VSThemeLoader.h: -------------------------------------------------------------------------------- 1 | // 2 | // VSThemeLoader.h 3 | // Q Branch LLC 4 | // 5 | // Created by Brent Simmons on 6/26/13. 6 | // Copyright (c) 2012 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | 12 | @class VSTheme; 13 | 14 | @interface VSThemeLoader : NSObject 15 | 16 | // Just use -init if you want the default DB5.plist in the normal place. 17 | - (instancetype)initWithFilepath:(NSString *)f; 18 | 19 | @property (nonatomic, strong, readonly) VSTheme *defaultTheme; 20 | @property (nonatomic, strong, readonly) NSArray *themes; 21 | 22 | - (VSTheme *)themeNamed:(NSString *)themeName; 23 | 24 | @end 25 | -------------------------------------------------------------------------------- /Vesper/Classes/VSThumbnail.h: -------------------------------------------------------------------------------- 1 | // 2 | // VSThumbnail.h 3 | // Vesper 4 | // 5 | // Created by Brent Simmons on 3/10/13. 6 | // Copyright (c) 2013 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | 10 | @class VSAttachmentData; 11 | 12 | 13 | 14 | @interface VSThumbnail : NSObject 15 | 16 | 17 | @property (nonatomic, strong) NSString *uniqueID; 18 | @property (nonatomic, assign) NSUInteger scale; 19 | @property (nonatomic, strong) QS_IMAGE *image; 20 | 21 | 22 | /*Will send VSThumbnailRenderedNotification with VSThumbnailKey in userInfo for any thumbnails fetched/rendered async. 23 | thumbnailResultBlock may be nil. It will be called on any thread.*/ 24 | 25 | extern NSString *VSThumbnailRenderedNotification; 26 | extern NSString *VSThumbnailKey; 27 | 28 | 29 | typedef void (^QSThumbnailResultBlock)(VSThumbnail *thumbnail); 30 | 31 | + (void)renderAndSaveThumbnailForImage:(QS_IMAGE *)image attachmentID:(NSString *)attachmentID thumbnailResultBlock:(QSThumbnailResultBlock)thumbnailResultBlock; 32 | + (void)renderAndSaveThumbnailForAttachmentID:(NSString *)attachmentID thumbnailResultBlock:(QSThumbnailResultBlock)thumbnailResultBlock; 33 | 34 | 35 | /*Layout support. A thumbnail will have padding around the edges for shadows.*/ 36 | 37 | + (CGRect)thumbnailRectForApparentRect:(CGRect)apparentRect; 38 | + (CGRect)apparentRectForActualRect:(CGRect)actualRect; 39 | 40 | @end 41 | -------------------------------------------------------------------------------- /Vesper/Classes/VSThumbnailCache.h: -------------------------------------------------------------------------------- 1 | // 2 | // VSThumbnailCache.h 3 | // Vesper 4 | // 5 | // Created by Brent Simmons on 3/29/13. 6 | // Copyright (c) 2013 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | 10 | extern NSString *VSThumbnailCachedNotification; /*VSImageKey and QSUniqueIDKey in userInfo.*/ 11 | 12 | 13 | @interface VSThumbnailCache : NSObject 14 | 15 | 16 | + (instancetype)sharedCache; 17 | 18 | - (void)loadThumbnailsWithAttachmentIDs:(NSArray *)attachmentIDs; 19 | 20 | - (QS_IMAGE *)thumbnailForAttachmentID:(NSString *)attachmentID; 21 | 22 | 23 | @end 24 | -------------------------------------------------------------------------------- /Vesper/Classes/VSThumbnailDatabase.h: -------------------------------------------------------------------------------- 1 | // 2 | // VSThumbnailDatabase.h 3 | // Vesper 4 | // 5 | // Created by Brent Simmons on 3/15/13. 6 | // Copyright (c) 2013 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | 10 | @class VSThumbnail; 11 | 12 | 13 | /*All methods are thread-safe.*/ 14 | 15 | 16 | @interface VSThumbnailDatabase : NSObject 17 | 18 | + (instancetype)sharedDatabase; 19 | 20 | - (void)saveThumbnails:(NSArray *)thumbnails; 21 | - (void)saveThumbnail:(VSThumbnail *)thumbnail; 22 | 23 | - (void)fetchThumbnails:(NSArray *)attachmentIDs callback:(QSFetchResultsBlock)callback; 24 | 25 | - (void)deleteThumbnails:(NSArray *)attachmentIDs; 26 | 27 | - (void)deleteUnreferencedThumbnails:(NSArray *)referencedAttachmentIDs; 28 | 29 | @end 30 | 31 | -------------------------------------------------------------------------------- /Vesper/Classes/VSThumbnailRenderer.h: -------------------------------------------------------------------------------- 1 | // 2 | // VSThumbnailRenderer.h 3 | // Vesper 4 | // 5 | // Created by Brent Simmons on 10/23/13. 6 | // Copyright (c) 2013 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | @import Foundation; 10 | #if TARGET_OS_IPHONE 11 | @import UIKit; 12 | #else 13 | @import AppKit; 14 | #endif 15 | 16 | 17 | @interface VSThumbnailRenderer : NSObject 18 | 19 | 20 | /*Thread-safe. Rendering happens on a background queue. imageResultBlock could be called on any thread.*/ 21 | 22 | - (void)renderThumbnailWithImage:(QS_IMAGE *)fullSizeImage imageResultBlock:(QSImageResultBlock)imageResultBlock; 23 | 24 | - (void)renderThumbnailWithData:(NSData *)fullSizeImageData imageResultBlock:(QSImageResultBlock)imageResultBlock; 25 | 26 | 27 | /*Layout support. Thumbnails may have padding for a shadow. (See VSThumbnail.h for the methods you should call instead of these.)*/ 28 | 29 | CGRect VSThumbnailActualRectForApparentRect(CGRect apparentRect); 30 | CGRect VSThumbnailApparentRectForActualRect(CGRect actualRect); 31 | 32 | @end 33 | 34 | -------------------------------------------------------------------------------- /Vesper/Classes/VSThumbnailRotation.h: -------------------------------------------------------------------------------- 1 | // 2 | // VSThumbnailRotation.h 3 | // Vesper 4 | // 5 | // Created by Brent Simmons on 3/29/13. 6 | // Copyright (c) 2013 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | 12 | @class VSNote; 13 | 14 | NSInteger thumbnailRotationForNote(VSNote *note); 15 | -------------------------------------------------------------------------------- /Vesper/Classes/VSTickMarksView.h: -------------------------------------------------------------------------------- 1 | // 2 | // VSTickMarksView.h 3 | // Vesper 4 | // 5 | // Created by Brent Simmons on 8/30/13. 6 | // Copyright (c) 2013 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface VSTickMarksView : UIView 12 | 13 | - (instancetype)initWithSlider:(UISlider *)slider; 14 | 15 | - (void)refresh; 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /Vesper/Classes/VSTimelineCellButton.h: -------------------------------------------------------------------------------- 1 | // 2 | // VSTimelineCellButton.h 3 | // Vesper 4 | // 5 | // Created by Brent Simmons on 8/11/13. 6 | // Copyright (c) 2013 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface VSTimelineCellButton : UIButton 12 | 13 | 14 | - (instancetype)initWithFrame:(CGRect)frame themeSpecifier:(NSString *)themeSpecifier title:(NSString *)title; 15 | 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /Vesper/Classes/VSTimelineCellButtonContainer.h: -------------------------------------------------------------------------------- 1 | // 2 | // VSTimelineCellButtonContainer.h 3 | // Vesper 4 | // 5 | // Created by Brent Simmons on 8/11/13. 6 | // Copyright (c) 2013 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | 12 | @interface VSTimelineCellButtonContainer : UIView 13 | 14 | 15 | - (id)initWithFrame:(CGRect)frame buttons:(NSArray *)buttons themeSpecifier:(NSString *)themeSpecifier; 16 | 17 | @property (nonatomic, assign, readonly) CGFloat widthOfButtons; 18 | 19 | 20 | @end 21 | -------------------------------------------------------------------------------- /Vesper/Classes/VSTimelineContext.h: -------------------------------------------------------------------------------- 1 | // 2 | // VSTimelineContext.h 3 | // Vesper 4 | // 5 | // Created by Brent Simmons on 3/15/14. 6 | // Copyright (c) 2014 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | 10 | @class VSTimelineNotesController; 11 | @class VSTag; 12 | @class VSRowHeightCache; 13 | 14 | 15 | @interface VSTimelineContext : NSObject 16 | 17 | 18 | @property (nonatomic) NSString *title; 19 | @property (nonatomic) VSTag *tag; 20 | @property (nonatomic, assign) BOOL canReorderNotes; 21 | @property (nonatomic, assign) BOOL canMakeNewNotes; 22 | @property (nonatomic, assign) BOOL searchesArchivedNotesOnly; 23 | @property (nonatomic) VSTimelineNotesController *timelineNotesController; 24 | @property (nonatomic) NSString *noNotesImageName; 25 | @property (nonatomic, readonly) QS_IMAGE *noNotesImage; 26 | @property (nonatomic) BOOL showInitialNoNotesView; 27 | 28 | 29 | @end 30 | -------------------------------------------------------------------------------- /Vesper/Classes/VSTimelineContext.m: -------------------------------------------------------------------------------- 1 | // 2 | // VSTimelineContext.m 3 | // Vesper 4 | // 5 | // Created by Brent Simmons on 3/15/14. 6 | // Copyright (c) 2014 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | #import "VSTimelineContext.h" 10 | 11 | @implementation VSTimelineContext 12 | 13 | 14 | - (QS_IMAGE *)noNotesImage { 15 | 16 | return [QS_IMAGE 17 | imageNamed:self.noNotesImageName]; 18 | } 19 | 20 | 21 | @end 22 | -------------------------------------------------------------------------------- /Vesper/Classes/VSTimelineNote.h: -------------------------------------------------------------------------------- 1 | // 2 | // VSTimelineNote.h 3 | // Vesper 4 | // 5 | // Created by Brent Simmons on 3/1/14. 6 | // Copyright (c) 2014 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | 10 | @class VSNote; 11 | 12 | 13 | /*Mostly immutable. Properties that may change: 14 | sortDate 15 | archived 16 | */ 17 | 18 | @interface VSTimelineNote : NSObject 19 | 20 | 21 | + (VSTimelineNote *)timelineNoteWithNote:(VSNote *)note; 22 | 23 | 24 | @property (nonatomic, assign, readonly) int64_t uniqueID; 25 | @property (nonatomic, readonly) NSString *truncatedText; 26 | @property (nonatomic, readonly) NSArray *links; 27 | @property (nonatomic, readonly) NSString *thumbnailID; 28 | 29 | @property (nonatomic) NSDate *sortDate; 30 | @property (nonatomic, assign) BOOL archived; 31 | 32 | /*Calculated*/ 33 | 34 | @property (nonatomic, readonly) NSString *title; 35 | @property (nonatomic, readonly) NSString *remainingText; 36 | @property (nonatomic, assign, readonly) BOOL hasThumbnail; 37 | @property (nonatomic, readonly) QS_IMAGE *thumbnail; 38 | 39 | - (void)takeValuesFromNote:(VSNote *)note; 40 | 41 | 42 | @end 43 | -------------------------------------------------------------------------------- /Vesper/Classes/VSTimelineSectionHeaderView.h: -------------------------------------------------------------------------------- 1 | // 2 | // VSTimelineSectionHeaderView.h 3 | // Vesper 4 | // 5 | // Created by Brent Simmons on 5/22/13. 6 | // Copyright (c) 2013 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | 12 | @interface VSTimelineSectionHeaderView : UIView 13 | 14 | 15 | - (instancetype)initWithFrame:(CGRect)frame title:(NSString *)title; 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /Vesper/Classes/VSTimelineTableView.h: -------------------------------------------------------------------------------- 1 | // 2 | // VSTimelineTableView.h 3 | // Vesper 4 | // 5 | // Created by Brent Simmons on 3/29/13. 6 | // Copyright (c) 2013 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | 12 | @interface VSTimelineTableView : UITableView 13 | 14 | - (instancetype)initWithFrame:(CGRect)frame; 15 | 16 | @end 17 | -------------------------------------------------------------------------------- /Vesper/Classes/VSTimelineToDetailAnimator.h: -------------------------------------------------------------------------------- 1 | // 2 | // VSTimelineToDetailAnimator.h 3 | // Vesper 4 | // 5 | // Created by Brent Simmons on 3/16/14. 6 | // Copyright (c) 2014 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | 10 | @class VSNote; 11 | @class VSDetailViewController; 12 | @class VSTimelineViewController; 13 | 14 | 15 | @interface VSTimelineToDetailAnimator : NSObject 16 | 17 | 18 | - (instancetype)initWithNote:(VSNote *)note indexPath:(NSIndexPath *)indexPath detailAnimationImage:(UIImage *)detailAnimationImage timelineViewController:(VSTimelineViewController *)timelineViewController detailViewController:(VSDetailViewController *)detailViewController; 19 | 20 | - (void)animate:(QSVoidCompletionBlock)completion; 21 | 22 | 23 | 24 | @end 25 | -------------------------------------------------------------------------------- /Vesper/Classes/VSTutorialDataImporter.h: -------------------------------------------------------------------------------- 1 | // 2 | // VSTutorialDataImporter.h 3 | // Vesper 4 | // 5 | // Created by Brent Simmons on 3/16/13. 6 | // Copyright (c) 2013 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | 10 | @interface VSTutorialDataImporter : NSObject 11 | 12 | + (void)loadTutorialData:(QSVoidCompletionBlock)completion; 13 | 14 | @end 15 | 16 | -------------------------------------------------------------------------------- /Vesper/Classes/VSTypographyFontSizeCell.h: -------------------------------------------------------------------------------- 1 | // 2 | // VSTypographyFontSizeCell.h 3 | // Vesper 4 | // 5 | // Created by Brent Simmons on 8/29/13. 6 | // Copyright (c) 2013 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface VSTypographyFontSizeCell : UITableViewCell 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /Vesper/Classes/VSTypographySettings.h: -------------------------------------------------------------------------------- 1 | // 2 | // VSTypographySettings.h 3 | // Vesper 4 | // 5 | // Created by Brent Simmons on 9/1/13. 6 | // Copyright (c) 2013 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | 12 | extern NSString *VSTypographySettingsDidChangeNotification; 13 | 14 | @class VSTheme; 15 | 16 | 17 | @interface VSTypographySettings : NSObject 18 | 19 | - (instancetype)initWithTheme:(VSTheme *)theme; 20 | 21 | /*These are all observable, but it's best to watch for VSTypographySettingsDidChangeNotification instead.*/ 22 | 23 | @property (nonatomic, strong, readonly) QS_FONT *titleFont; 24 | @property (nonatomic, strong, readonly) QS_FONT *titleFontArchived; 25 | @property (nonatomic, strong, readonly) QS_FONT *titleLinkFont; 26 | @property (nonatomic, strong, readonly) QS_FONT *titleLinkFontArchived; 27 | @property (nonatomic, strong, readonly) QS_FONT *bodyFont; 28 | @property (nonatomic, strong, readonly) QS_FONT *bodyFontArchived; 29 | @property (nonatomic, strong, readonly) QS_FONT *bodyLinkFont; 30 | @property (nonatomic, strong, readonly) QS_FONT *bodyLinkFontArchived; 31 | @property (nonatomic, assign, readonly) BOOL useSmallCaps; /*For titles only*/ 32 | 33 | 34 | @end 35 | -------------------------------------------------------------------------------- /Vesper/Classes/VSTypographySmallCapsCell.h: -------------------------------------------------------------------------------- 1 | // 2 | // VSTypographySmallCapsCell.h 3 | // Vesper 4 | // 5 | // Created by Brent Simmons on 8/29/13. 6 | // Copyright (c) 2013 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface VSTypographySmallCapsCell : UITableViewCell 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /Vesper/Classes/VSTypographyTextWeightCell.h: -------------------------------------------------------------------------------- 1 | // 2 | // VSTypographyTextWeightCell.h 3 | // Vesper 4 | // 5 | // Created by Brent Simmons on 8/29/13. 6 | // Copyright (c) 2013 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface VSTypographyTextWeightCell : UITableViewCell 12 | 13 | - (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier text:(NSString *)text; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /Vesper/Classes/VSTypographyViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // VSTypographyViewController.h 3 | // Vesper 4 | // 5 | // Created by Brent Simmons on 8/28/13. 6 | // Copyright (c) 2013 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "VSBaseViewController.h" 11 | 12 | 13 | @interface VSTypographyViewController : VSBaseViewController 14 | 15 | 16 | @end 17 | -------------------------------------------------------------------------------- /Vesper/Classes/VSV1DataExtracter.h: -------------------------------------------------------------------------------- 1 | // 2 | // VSV1DataExtracter.h 3 | // Vesper 4 | // 5 | // Created by Brent Simmons on 9/30/13. 6 | // Copyright (c) 2013 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | 10 | /*Gets data from V1 database. 11 | 12 | Returns array of notes. It's up to the caller to deal 13 | with saving notes, tags, and attachments. 14 | 15 | Should be called from with a QSDatabaseQueue block. 16 | (Not main thread.)*/ 17 | 18 | 19 | @class FMDatabase; 20 | 21 | NSArray *VSV1Data(FMDatabase *database); 22 | 23 | -------------------------------------------------------------------------------- /Vesper/Classes/VSV1Importer.h: -------------------------------------------------------------------------------- 1 | // 2 | // VSV1Importer.h 3 | // Vesper 4 | // 5 | // Created by Brent Simmons on 3/28/14. 6 | // Copyright (c) 2014 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | 10 | @class VSDataController; 11 | 12 | 13 | void VSImportV1Notes(NSArray *notes, VSDataController *dataController); 14 | 15 | -------------------------------------------------------------------------------- /Vesper/Resources/Default-1334h@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brentsimmons/Vesper/2b05a1ccd2629c1eb757620186823418ac68bee6/Vesper/Resources/Default-1334h@2x.png -------------------------------------------------------------------------------- /Vesper/Resources/Default-2208h@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brentsimmons/Vesper/2b05a1ccd2629c1eb757620186823418ac68bee6/Vesper/Resources/Default-2208h@3x.png -------------------------------------------------------------------------------- /Vesper/Resources/Default-568h@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brentsimmons/Vesper/2b05a1ccd2629c1eb757620186823418ac68bee6/Vesper/Resources/Default-568h@2x.png -------------------------------------------------------------------------------- /Vesper/Resources/Default-Landscape.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brentsimmons/Vesper/2b05a1ccd2629c1eb757620186823418ac68bee6/Vesper/Resources/Default-Landscape.png -------------------------------------------------------------------------------- /Vesper/Resources/Default-Landscape@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brentsimmons/Vesper/2b05a1ccd2629c1eb757620186823418ac68bee6/Vesper/Resources/Default-Landscape@2x.png -------------------------------------------------------------------------------- /Vesper/Resources/Default-Portrait.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brentsimmons/Vesper/2b05a1ccd2629c1eb757620186823418ac68bee6/Vesper/Resources/Default-Portrait.png -------------------------------------------------------------------------------- /Vesper/Resources/Default-Portrait@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brentsimmons/Vesper/2b05a1ccd2629c1eb757620186823418ac68bee6/Vesper/Resources/Default-Portrait@2x.png -------------------------------------------------------------------------------- /Vesper/Resources/Default.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brentsimmons/Vesper/2b05a1ccd2629c1eb757620186823418ac68bee6/Vesper/Resources/Default.png -------------------------------------------------------------------------------- /Vesper/Resources/Default@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brentsimmons/Vesper/2b05a1ccd2629c1eb757620186823418ac68bee6/Vesper/Resources/Default@2x.png -------------------------------------------------------------------------------- /Vesper/Resources/Icon-Small@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brentsimmons/Vesper/2b05a1ccd2629c1eb757620186823418ac68bee6/Vesper/Resources/Icon-Small@2x.png -------------------------------------------------------------------------------- /Vesper/Resources/WebViewError.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Error 4 | 5 | 6 | 11 | 12 | 13 | 14 |
15 |

Unable to load the page

16 |

[[errorMessage]]

17 |
18 | 19 | 20 | -------------------------------------------------------------------------------- /Vesper/Resources/account-checkmark@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brentsimmons/Vesper/2b05a1ccd2629c1eb757620186823418ac68bee6/Vesper/Resources/account-checkmark@2x.png -------------------------------------------------------------------------------- /Vesper/Resources/account-x@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brentsimmons/Vesper/2b05a1ccd2629c1eb757620186823418ac68bee6/Vesper/Resources/account-x@2x.png -------------------------------------------------------------------------------- /Vesper/Resources/activity-camera@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brentsimmons/Vesper/2b05a1ccd2629c1eb757620186823418ac68bee6/Vesper/Resources/activity-camera@2x.png -------------------------------------------------------------------------------- /Vesper/Resources/activity-copy@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brentsimmons/Vesper/2b05a1ccd2629c1eb757620186823418ac68bee6/Vesper/Resources/activity-copy@2x.png -------------------------------------------------------------------------------- /Vesper/Resources/activity-delete@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brentsimmons/Vesper/2b05a1ccd2629c1eb757620186823418ac68bee6/Vesper/Resources/activity-delete@2x.png -------------------------------------------------------------------------------- /Vesper/Resources/activity-library@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brentsimmons/Vesper/2b05a1ccd2629c1eb757620186823418ac68bee6/Vesper/Resources/activity-library@2x.png -------------------------------------------------------------------------------- /Vesper/Resources/activity-mail@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brentsimmons/Vesper/2b05a1ccd2629c1eb757620186823418ac68bee6/Vesper/Resources/activity-mail@2x.png -------------------------------------------------------------------------------- /Vesper/Resources/activity-messages@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brentsimmons/Vesper/2b05a1ccd2629c1eb757620186823418ac68bee6/Vesper/Resources/activity-messages@2x.png -------------------------------------------------------------------------------- /Vesper/Resources/activity-newest@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brentsimmons/Vesper/2b05a1ccd2629c1eb757620186823418ac68bee6/Vesper/Resources/activity-newest@2x.png -------------------------------------------------------------------------------- /Vesper/Resources/activity-pressed@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brentsimmons/Vesper/2b05a1ccd2629c1eb757620186823418ac68bee6/Vesper/Resources/activity-pressed@2x.png -------------------------------------------------------------------------------- /Vesper/Resources/activity-print@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brentsimmons/Vesper/2b05a1ccd2629c1eb757620186823418ac68bee6/Vesper/Resources/activity-print@2x.png -------------------------------------------------------------------------------- /Vesper/Resources/activity-remove@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brentsimmons/Vesper/2b05a1ccd2629c1eb757620186823418ac68bee6/Vesper/Resources/activity-remove@2x.png -------------------------------------------------------------------------------- /Vesper/Resources/activity-safari@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brentsimmons/Vesper/2b05a1ccd2629c1eb757620186823418ac68bee6/Vesper/Resources/activity-safari@2x.png -------------------------------------------------------------------------------- /Vesper/Resources/activity@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brentsimmons/Vesper/2b05a1ccd2629c1eb757620186823418ac68bee6/Vesper/Resources/activity@2x.png -------------------------------------------------------------------------------- /Vesper/Resources/addbutton@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brentsimmons/Vesper/2b05a1ccd2629c1eb757620186823418ac68bee6/Vesper/Resources/addbutton@2x.png -------------------------------------------------------------------------------- /Vesper/Resources/all-notes@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brentsimmons/Vesper/2b05a1ccd2629c1eb757620186823418ac68bee6/Vesper/Resources/all-notes@2x.png -------------------------------------------------------------------------------- /Vesper/Resources/archive-full@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brentsimmons/Vesper/2b05a1ccd2629c1eb757620186823418ac68bee6/Vesper/Resources/archive-full@2x.png -------------------------------------------------------------------------------- /Vesper/Resources/archive@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brentsimmons/Vesper/2b05a1ccd2629c1eb757620186823418ac68bee6/Vesper/Resources/archive@2x.png -------------------------------------------------------------------------------- /Vesper/Resources/arrow-left@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brentsimmons/Vesper/2b05a1ccd2629c1eb757620186823418ac68bee6/Vesper/Resources/arrow-left@2x.png -------------------------------------------------------------------------------- /Vesper/Resources/arrow-right@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brentsimmons/Vesper/2b05a1ccd2629c1eb757620186823418ac68bee6/Vesper/Resources/arrow-right@2x.png -------------------------------------------------------------------------------- /Vesper/Resources/camera@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brentsimmons/Vesper/2b05a1ccd2629c1eb757620186823418ac68bee6/Vesper/Resources/camera@2x.png -------------------------------------------------------------------------------- /Vesper/Resources/checkmark@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brentsimmons/Vesper/2b05a1ccd2629c1eb757620186823418ac68bee6/Vesper/Resources/checkmark@2x.png -------------------------------------------------------------------------------- /Vesper/Resources/chevron@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brentsimmons/Vesper/2b05a1ccd2629c1eb757620186823418ac68bee6/Vesper/Resources/chevron@2x.png -------------------------------------------------------------------------------- /Vesper/Resources/cloud-error-status@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brentsimmons/Vesper/2b05a1ccd2629c1eb757620186823418ac68bee6/Vesper/Resources/cloud-error-status@2x.png -------------------------------------------------------------------------------- /Vesper/Resources/cloud-error@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brentsimmons/Vesper/2b05a1ccd2629c1eb757620186823418ac68bee6/Vesper/Resources/cloud-error@2x.png -------------------------------------------------------------------------------- /Vesper/Resources/cloud-logo@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brentsimmons/Vesper/2b05a1ccd2629c1eb757620186823418ac68bee6/Vesper/Resources/cloud-logo@2x.png -------------------------------------------------------------------------------- /Vesper/Resources/cloud-off@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brentsimmons/Vesper/2b05a1ccd2629c1eb757620186823418ac68bee6/Vesper/Resources/cloud-off@2x.png -------------------------------------------------------------------------------- /Vesper/Resources/cloud@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brentsimmons/Vesper/2b05a1ccd2629c1eb757620186823418ac68bee6/Vesper/Resources/cloud@2x.png -------------------------------------------------------------------------------- /Vesper/Resources/credits-bubble@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brentsimmons/Vesper/2b05a1ccd2629c1eb757620186823418ac68bee6/Vesper/Resources/credits-bubble@2x.png -------------------------------------------------------------------------------- /Vesper/Resources/credits-icon@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brentsimmons/Vesper/2b05a1ccd2629c1eb757620186823418ac68bee6/Vesper/Resources/credits-icon@2x.png -------------------------------------------------------------------------------- /Vesper/Resources/credits-names@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brentsimmons/Vesper/2b05a1ccd2629c1eb757620186823418ac68bee6/Vesper/Resources/credits-names@2x.png -------------------------------------------------------------------------------- /Vesper/Resources/credits-remember@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brentsimmons/Vesper/2b05a1ccd2629c1eb757620186823418ac68bee6/Vesper/Resources/credits-remember@2x.png -------------------------------------------------------------------------------- /Vesper/Resources/credits-vesper@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brentsimmons/Vesper/2b05a1ccd2629c1eb757620186823418ac68bee6/Vesper/Resources/credits-vesper@2x.png -------------------------------------------------------------------------------- /Vesper/Resources/export.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brentsimmons/Vesper/2b05a1ccd2629c1eb757620186823418ac68bee6/Vesper/Resources/export.png -------------------------------------------------------------------------------- /Vesper/Resources/export@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brentsimmons/Vesper/2b05a1ccd2629c1eb757620186823418ac68bee6/Vesper/Resources/export@2x.png -------------------------------------------------------------------------------- /Vesper/Resources/icon-ipad.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brentsimmons/Vesper/2b05a1ccd2629c1eb757620186823418ac68bee6/Vesper/Resources/icon-ipad.png -------------------------------------------------------------------------------- /Vesper/Resources/icon-ipad@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brentsimmons/Vesper/2b05a1ccd2629c1eb757620186823418ac68bee6/Vesper/Resources/icon-ipad@2x.png -------------------------------------------------------------------------------- /Vesper/Resources/icon@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brentsimmons/Vesper/2b05a1ccd2629c1eb757620186823418ac68bee6/Vesper/Resources/icon@2x.png -------------------------------------------------------------------------------- /Vesper/Resources/keyboard@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brentsimmons/Vesper/2b05a1ccd2629c1eb757620186823418ac68bee6/Vesper/Resources/keyboard@2x.png -------------------------------------------------------------------------------- /Vesper/Resources/listbutton@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brentsimmons/Vesper/2b05a1ccd2629c1eb757620186823418ac68bee6/Vesper/Resources/listbutton@2x.png -------------------------------------------------------------------------------- /Vesper/Resources/navbar-backarrow-pressed@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brentsimmons/Vesper/2b05a1ccd2629c1eb757620186823418ac68bee6/Vesper/Resources/navbar-backarrow-pressed@2x.png -------------------------------------------------------------------------------- /Vesper/Resources/navbar-backarrow@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brentsimmons/Vesper/2b05a1ccd2629c1eb757620186823418ac68bee6/Vesper/Resources/navbar-backarrow@2x.png -------------------------------------------------------------------------------- /Vesper/Resources/navbar-button-pressed@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brentsimmons/Vesper/2b05a1ccd2629c1eb757620186823418ac68bee6/Vesper/Resources/navbar-button-pressed@2x.png -------------------------------------------------------------------------------- /Vesper/Resources/navbar-button@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brentsimmons/Vesper/2b05a1ccd2629c1eb757620186823418ac68bee6/Vesper/Resources/navbar-button@2x.png -------------------------------------------------------------------------------- /Vesper/Resources/noarchive@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brentsimmons/Vesper/2b05a1ccd2629c1eb757620186823418ac68bee6/Vesper/Resources/noarchive@2x.png -------------------------------------------------------------------------------- /Vesper/Resources/nonotes@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brentsimmons/Vesper/2b05a1ccd2629c1eb757620186823418ac68bee6/Vesper/Resources/nonotes@2x.png -------------------------------------------------------------------------------- /Vesper/Resources/refresh@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brentsimmons/Vesper/2b05a1ccd2629c1eb757620186823418ac68bee6/Vesper/Resources/refresh@2x.png -------------------------------------------------------------------------------- /Vesper/Resources/restore@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brentsimmons/Vesper/2b05a1ccd2629c1eb757620186823418ac68bee6/Vesper/Resources/restore@2x.png -------------------------------------------------------------------------------- /Vesper/Resources/search-clear@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brentsimmons/Vesper/2b05a1ccd2629c1eb757620186823418ac68bee6/Vesper/Resources/search-clear@2x.png -------------------------------------------------------------------------------- /Vesper/Resources/search-icon@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brentsimmons/Vesper/2b05a1ccd2629c1eb757620186823418ac68bee6/Vesper/Resources/search-icon@2x.png -------------------------------------------------------------------------------- /Vesper/Resources/settings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brentsimmons/Vesper/2b05a1ccd2629c1eb757620186823418ac68bee6/Vesper/Resources/settings.png -------------------------------------------------------------------------------- /Vesper/Resources/settings@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brentsimmons/Vesper/2b05a1ccd2629c1eb757620186823418ac68bee6/Vesper/Resources/settings@2x.png -------------------------------------------------------------------------------- /Vesper/Resources/spinner/spin0@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brentsimmons/Vesper/2b05a1ccd2629c1eb757620186823418ac68bee6/Vesper/Resources/spinner/spin0@2x.png -------------------------------------------------------------------------------- /Vesper/Resources/spinner/spin10@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brentsimmons/Vesper/2b05a1ccd2629c1eb757620186823418ac68bee6/Vesper/Resources/spinner/spin10@2x.png -------------------------------------------------------------------------------- /Vesper/Resources/spinner/spin11@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brentsimmons/Vesper/2b05a1ccd2629c1eb757620186823418ac68bee6/Vesper/Resources/spinner/spin11@2x.png -------------------------------------------------------------------------------- /Vesper/Resources/spinner/spin1@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brentsimmons/Vesper/2b05a1ccd2629c1eb757620186823418ac68bee6/Vesper/Resources/spinner/spin1@2x.png -------------------------------------------------------------------------------- /Vesper/Resources/spinner/spin2@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brentsimmons/Vesper/2b05a1ccd2629c1eb757620186823418ac68bee6/Vesper/Resources/spinner/spin2@2x.png -------------------------------------------------------------------------------- /Vesper/Resources/spinner/spin3@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brentsimmons/Vesper/2b05a1ccd2629c1eb757620186823418ac68bee6/Vesper/Resources/spinner/spin3@2x.png -------------------------------------------------------------------------------- /Vesper/Resources/spinner/spin4@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brentsimmons/Vesper/2b05a1ccd2629c1eb757620186823418ac68bee6/Vesper/Resources/spinner/spin4@2x.png -------------------------------------------------------------------------------- /Vesper/Resources/spinner/spin5@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brentsimmons/Vesper/2b05a1ccd2629c1eb757620186823418ac68bee6/Vesper/Resources/spinner/spin5@2x.png -------------------------------------------------------------------------------- /Vesper/Resources/spinner/spin6@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brentsimmons/Vesper/2b05a1ccd2629c1eb757620186823418ac68bee6/Vesper/Resources/spinner/spin6@2x.png -------------------------------------------------------------------------------- /Vesper/Resources/spinner/spin7@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brentsimmons/Vesper/2b05a1ccd2629c1eb757620186823418ac68bee6/Vesper/Resources/spinner/spin7@2x.png -------------------------------------------------------------------------------- /Vesper/Resources/spinner/spin8@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brentsimmons/Vesper/2b05a1ccd2629c1eb757620186823418ac68bee6/Vesper/Resources/spinner/spin8@2x.png -------------------------------------------------------------------------------- /Vesper/Resources/spinner/spin9@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brentsimmons/Vesper/2b05a1ccd2629c1eb757620186823418ac68bee6/Vesper/Resources/spinner/spin9@2x.png -------------------------------------------------------------------------------- /Vesper/Resources/ssllock@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brentsimmons/Vesper/2b05a1ccd2629c1eb757620186823418ac68bee6/Vesper/Resources/ssllock@2x.png -------------------------------------------------------------------------------- /Vesper/Resources/taglist-untagged@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brentsimmons/Vesper/2b05a1ccd2629c1eb757620186823418ac68bee6/Vesper/Resources/taglist-untagged@2x.png -------------------------------------------------------------------------------- /Vesper/Resources/taglist@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brentsimmons/Vesper/2b05a1ccd2629c1eb757620186823418ac68bee6/Vesper/Resources/taglist@2x.png -------------------------------------------------------------------------------- /Vesper/Resources/thanks@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brentsimmons/Vesper/2b05a1ccd2629c1eb757620186823418ac68bee6/Vesper/Resources/thanks@2x.png -------------------------------------------------------------------------------- /Vesper/Resources/trash@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brentsimmons/Vesper/2b05a1ccd2629c1eb757620186823418ac68bee6/Vesper/Resources/trash@2x.png -------------------------------------------------------------------------------- /Vesper/Resources/tutorial.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brentsimmons/Vesper/2b05a1ccd2629c1eb757620186823418ac68bee6/Vesper/Resources/tutorial.jpg -------------------------------------------------------------------------------- /Vesper/Resources/typography@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brentsimmons/Vesper/2b05a1ccd2629c1eb757620186823418ac68bee6/Vesper/Resources/typography@2x.png -------------------------------------------------------------------------------- /Vesper/Resources/wallpaper@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brentsimmons/Vesper/2b05a1ccd2629c1eb757620186823418ac68bee6/Vesper/Resources/wallpaper@2x.png -------------------------------------------------------------------------------- /Vesper/Resources/webview-back@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brentsimmons/Vesper/2b05a1ccd2629c1eb757620186823418ac68bee6/Vesper/Resources/webview-back@2x.png -------------------------------------------------------------------------------- /Vesper/Resources/webview-downarrow@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brentsimmons/Vesper/2b05a1ccd2629c1eb757620186823418ac68bee6/Vesper/Resources/webview-downarrow@2x.png -------------------------------------------------------------------------------- /Vesper/Resources/webview-forward@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brentsimmons/Vesper/2b05a1ccd2629c1eb757620186823418ac68bee6/Vesper/Resources/webview-forward@2x.png -------------------------------------------------------------------------------- /Vesper/Vesper.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.developer.icloud-container-identifiers 6 | 7 | iCloud.$(CFBundleIdentifier) 8 | 9 | com.apple.developer.icloud-services 10 | 11 | CloudDocuments 12 | 13 | com.apple.developer.ubiquity-container-identifiers 14 | 15 | iCloud.$(CFBundleIdentifier) 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /Vesper/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /Vesper/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // Vesper 4 | // 5 | // Created by Brent Simmons on 11/18/12. 6 | // Copyright (c) 2012 Q Branch LLC. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "VSAppDelegate.h" 11 | 12 | 13 | int main(int argc, char *argv[]) { 14 | 15 | @autoreleasepool { 16 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([VSAppDelegate class])); 17 | } 18 | } 19 | 20 | 21 | --------------------------------------------------------------------------------