├── arclib
├── __phutil_library_init__.php
├── src
│ ├── .phutil_module_cache
│ ├── InboxUncrustifyLintEngine.php
│ └── InboxUncrustifyLinter.php
├── .phutil_module_cache
└── __phutil_library_map__.php
├── InboxFramework
├── Inbox
│ ├── en.lproj
│ │ └── InfoPlist.strings
│ ├── Models
│ │ ├── API Calls
│ │ │ ├── INSaveTagTask.h
│ │ │ ├── INSaveDraftTask.h
│ │ │ ├── INDeleteDraftTask.h
│ │ │ ├── INSendDraftTask.h
│ │ │ ├── INMarkMessageAsReadTask.h
│ │ │ ├── INUploadFileTask.h
│ │ │ ├── INAddRemoveTagsTask.h
│ │ │ ├── INMarkMessageAsReadTask.m
│ │ │ ├── INAPITask.h
│ │ │ ├── INSendDraftTask.m
│ │ │ ├── INSaveTagTask.m
│ │ │ ├── INUploadFileTask.m
│ │ │ ├── INDeleteDraftTask.m
│ │ │ ├── INSaveDraftTask.m
│ │ │ └── INAddRemoveTagsTask.m
│ │ ├── Concrete Classes
│ │ │ ├── INThread+Private.h
│ │ │ ├── INContact.h
│ │ │ ├── INThread+Private.m
│ │ │ ├── INContact.m
│ │ │ ├── INNamespace.m
│ │ │ ├── INTag.m
│ │ │ ├── INTag.h
│ │ │ ├── INMessage.h
│ │ │ ├── INFile.h
│ │ │ ├── INMessage.m
│ │ │ ├── INNamespace.h
│ │ │ ├── INFile.m
│ │ │ ├── INThread.m
│ │ │ ├── INDraft.h
│ │ │ ├── INDraft.m
│ │ │ └── INThread.h
│ │ ├── INModelProvider+Private.h
│ │ ├── INMessageProvider.h
│ │ ├── INThreadProvider.h
│ │ ├── INMessageProvider.m
│ │ ├── INThreadProvider.m
│ │ ├── INModelObject+Uniquing.h
│ │ └── INModelObject+Uniquing.m
│ ├── Categories
│ │ ├── FMDatabase+INModelQueries.h
│ │ ├── FMDatabase+INModelQueries.m
│ │ ├── NSPredicate+Inspection.h
│ │ ├── NSDictionary+FormatConversion.h
│ │ ├── FMResultSet+INModelQueries.h
│ │ ├── NSError+InboxErrors.h
│ │ ├── NSObject+AssociatedObjects.h
│ │ ├── NSString+FormatConversion.h
│ │ ├── NSPredicate+Inspection.m
│ │ ├── NSError+InboxErrors.m
│ │ ├── FMResultSet+INModelQueries.m
│ │ ├── NSObject+AssociatedObjects.m
│ │ ├── NSDictionary+FormatConversion.m
│ │ ├── NSString+FormatConversion.m
│ │ └── NSObject+Properties.h
│ ├── INSyncEngine.h
│ ├── Inbox-Prefix.pch
│ ├── Helpers
│ │ ├── INPredicateToQueryParamConverter.h
│ │ ├── INPredicateToSQLConverter.h
│ │ ├── INModelResponseSerializer.h
│ │ ├── INPredicateToQueryParamConverter.m
│ │ └── INModelResponseSerializer.m
│ ├── Info.plist
│ ├── Inbox-Info.plist
│ └── Inbox.h
├── InboxTests
│ ├── en.lproj
│ │ └── InfoPlist.strings
│ └── InboxTests-Info.plist
├── InboxFramework.xcodeproj
│ └── project.xcworkspace
│ │ ├── contents.xcworkspacedata
│ │ └── xcshareddata
│ │ └── InboxFramework.xccheckout
├── Documentation
│ └── index-template.txt
├── InboxUI
│ ├── Categories
│ │ ├── UIView+FrameAdditions.h
│ │ └── UIView+FrameAdditions.m
│ └── Views
│ │ ├── INRecipientsLabel.h
│ │ └── INMessageContentView.h
└── Vendor
│ └── PDKeychainBindings
│ ├── PDKeychainBindings.h
│ ├── PDKeychainBindingsController.h
│ └── PDKeychainBindings.m
├── InboxExamples
├── Triage
│ ├── Triage
│ │ ├── en.lproj
│ │ │ └── InfoPlist.strings
│ │ ├── TRMessageActionButton.h
│ │ ├── main.m
│ │ ├── TRAppDelegate.h
│ │ ├── Triage-Prefix.pch
│ │ ├── INPlaceholderTextView.h
│ │ ├── TRMessageCardView.h
│ │ ├── TRViewController.h
│ │ ├── TRMessageActionButton.m
│ │ ├── Info.plist
│ │ ├── TRAppDelegate.m
│ │ └── INPlaceholderTextView.m
│ ├── Documentation
│ │ └── demo.mov
│ ├── Podfile
│ ├── Triage.xcworkspace
│ │ └── contents.xcworkspacedata
│ └── Triage.xcodeproj
│ │ └── project.xcworkspace
│ │ ├── contents.xcworkspacedata
│ │ └── xcuserdata
│ │ └── bengotow.xcuserdatad
│ │ └── UserInterfaceState.xcuserstate
├── Snapmail
│ ├── Snapmail
│ │ ├── en.lproj
│ │ │ └── InfoPlist.strings
│ │ ├── Images.xcassets
│ │ │ ├── snap-read.imageset
│ │ │ │ ├── snap-read@2x.png
│ │ │ │ └── Contents.json
│ │ │ ├── snap-sent.imageset
│ │ │ │ ├── snap-sent@2x.png
│ │ │ │ └── Contents.json
│ │ │ ├── send-button.imageset
│ │ │ │ ├── send-button@2x.png
│ │ │ │ └── Contents.json
│ │ │ ├── snap-unread.imageset
│ │ │ │ ├── snap-unread@2x.png
│ │ │ │ └── Contents.json
│ │ │ ├── snap-sending.imageset
│ │ │ │ ├── snap-sending@2x.png
│ │ │ │ └── Contents.json
│ │ │ ├── capture-button.imageset
│ │ │ │ ├── capture-button@2x.png
│ │ │ │ └── Contents.json
│ │ │ ├── AppIcon.appiconset
│ │ │ │ └── Contents.json
│ │ │ └── LaunchImage.launchimage
│ │ │ │ └── Contents.json
│ │ ├── main.m
│ │ ├── Snapmail-Prefix.pch
│ │ ├── INAppDelegate.h
│ │ ├── INCaptureViewController.h
│ │ ├── INSnapViewController.h
│ │ ├── INContactsViewController.h
│ │ ├── INHomeViewController.h
│ │ ├── Snapmail-Info.plist
│ │ ├── INContactsViewController.xib
│ │ ├── INSnapViewController.m
│ │ ├── INAppDelegate.m
│ │ ├── INCaptureViewController.m
│ │ ├── INHomeViewController.xib
│ │ ├── INCaptureViewController.xib
│ │ ├── INContactsViewController.m
│ │ └── INSnapViewController.xib
│ ├── Podfile
│ ├── Snapmail.xcworkspace
│ │ ├── contents.xcworkspacedata
│ │ └── xcuserdata
│ │ │ └── bengotow.xcuserdatad
│ │ │ └── UserInterfaceState.xcuserstate
│ └── Snapmail.xcodeproj
│ │ └── project.xcworkspace
│ │ └── contents.xcworkspacedata
├── SimpleMail
│ ├── SimpleMail
│ │ ├── en.lproj
│ │ │ └── InfoPlist.strings
│ │ ├── Images.xcassets
│ │ │ ├── unread_dot.imageset
│ │ │ │ ├── unread_dot.png
│ │ │ │ ├── unread_dot@2x.png
│ │ │ │ └── Contents.json
│ │ │ ├── AppIcon.appiconset
│ │ │ │ └── Contents.json
│ │ │ └── LaunchImage.launchimage
│ │ │ │ └── Contents.json
│ │ ├── SMAppDelegate.h
│ │ ├── main.m
│ │ ├── SMInboxTableViewController.h
│ │ ├── SimpleMail-Prefix.pch
│ │ ├── SMThreadTableViewCell.h
│ │ ├── SMThreadTableViewCell.m
│ │ ├── SimpleMail-Info.plist
│ │ └── SMAppDelegate.m
│ ├── Podfile
│ ├── SimpleMail.xcworkspace
│ │ └── contents.xcworkspacedata
│ └── SimpleMail.xcodeproj
│ │ └── project.xcworkspace
│ │ └── contents.xcworkspacedata
└── SwiftEightBall
│ ├── screenshot.png
│ ├── SwiftEightBall
│ ├── Images.xcassets
│ │ ├── unread_dot.imageset
│ │ │ ├── unread_dot.png
│ │ │ ├── unread_dot@2x.png
│ │ │ └── Contents.json
│ │ ├── AppIcon.appiconset
│ │ │ └── Contents.json
│ │ └── LaunchImage.launchimage
│ │ │ └── Contents.json
│ ├── Info.plist
│ └── AppDelegate.swift
│ ├── SwiftEightBall.xcodeproj
│ └── project.xcworkspace
│ │ └── contents.xcworkspacedata
│ └── SwiftEightBall.xcworkspace
│ └── contents.xcworkspacedata
├── .arcconfig
├── .gitmodules
├── LICENSE.md
├── .gitignore
└── InboxKit.podspec
/arclib/__phutil_library_init__.php:
--------------------------------------------------------------------------------
1 | "../../"
7 | end
8 |
9 |
--------------------------------------------------------------------------------
/InboxExamples/Snapmail/Snapmail/Images.xcassets/snap-read.imageset/snap-read@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nylas/inbox-ios/HEAD/InboxExamples/Snapmail/Snapmail/Images.xcassets/snap-read.imageset/snap-read@2x.png
--------------------------------------------------------------------------------
/InboxExamples/Snapmail/Snapmail/Images.xcassets/snap-sent.imageset/snap-sent@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nylas/inbox-ios/HEAD/InboxExamples/Snapmail/Snapmail/Images.xcassets/snap-sent.imageset/snap-sent@2x.png
--------------------------------------------------------------------------------
/InboxExamples/Triage/Podfile:
--------------------------------------------------------------------------------
1 |
2 | # Uncomment this line to define a global platform for your project
3 | # platform :ios, "6.0"
4 |
5 | target "Triage" do
6 | pod 'InboxKit', :path => "../../"
7 | end
8 |
9 |
--------------------------------------------------------------------------------
/InboxExamples/SimpleMail/Podfile:
--------------------------------------------------------------------------------
1 |
2 | # Uncomment this line to define a global platform for your project
3 | # platform :ios, "6.0"
4 |
5 | target "SimpleMail" do
6 | pod 'InboxKit', :path => "../../"
7 | end
8 |
9 |
--------------------------------------------------------------------------------
/InboxExamples/SimpleMail/SimpleMail/Images.xcassets/unread_dot.imageset/unread_dot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nylas/inbox-ios/HEAD/InboxExamples/SimpleMail/SimpleMail/Images.xcassets/unread_dot.imageset/unread_dot.png
--------------------------------------------------------------------------------
/InboxExamples/Snapmail/Snapmail/Images.xcassets/send-button.imageset/send-button@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nylas/inbox-ios/HEAD/InboxExamples/Snapmail/Snapmail/Images.xcassets/send-button.imageset/send-button@2x.png
--------------------------------------------------------------------------------
/InboxExamples/Snapmail/Snapmail/Images.xcassets/snap-unread.imageset/snap-unread@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nylas/inbox-ios/HEAD/InboxExamples/Snapmail/Snapmail/Images.xcassets/snap-unread.imageset/snap-unread@2x.png
--------------------------------------------------------------------------------
/InboxExamples/SimpleMail/SimpleMail/Images.xcassets/unread_dot.imageset/unread_dot@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nylas/inbox-ios/HEAD/InboxExamples/SimpleMail/SimpleMail/Images.xcassets/unread_dot.imageset/unread_dot@2x.png
--------------------------------------------------------------------------------
/InboxExamples/Snapmail/Snapmail/Images.xcassets/snap-sending.imageset/snap-sending@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nylas/inbox-ios/HEAD/InboxExamples/Snapmail/Snapmail/Images.xcassets/snap-sending.imageset/snap-sending@2x.png
--------------------------------------------------------------------------------
/InboxExamples/Triage/Triage.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/InboxExamples/Snapmail/Snapmail.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/InboxExamples/Snapmail/Snapmail/Images.xcassets/capture-button.imageset/capture-button@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nylas/inbox-ios/HEAD/InboxExamples/Snapmail/Snapmail/Images.xcassets/capture-button.imageset/capture-button@2x.png
--------------------------------------------------------------------------------
/InboxExamples/SimpleMail/SimpleMail.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/InboxExamples/SwiftEightBall/SwiftEightBall/Images.xcassets/unread_dot.imageset/unread_dot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nylas/inbox-ios/HEAD/InboxExamples/SwiftEightBall/SwiftEightBall/Images.xcassets/unread_dot.imageset/unread_dot.png
--------------------------------------------------------------------------------
/InboxExamples/SwiftEightBall/SwiftEightBall/Images.xcassets/unread_dot.imageset/unread_dot@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nylas/inbox-ios/HEAD/InboxExamples/SwiftEightBall/SwiftEightBall/Images.xcassets/unread_dot.imageset/unread_dot@2x.png
--------------------------------------------------------------------------------
/InboxExamples/Snapmail/Snapmail.xcworkspace/xcuserdata/bengotow.xcuserdatad/UserInterfaceState.xcuserstate:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nylas/inbox-ios/HEAD/InboxExamples/Snapmail/Snapmail.xcworkspace/xcuserdata/bengotow.xcuserdatad/UserInterfaceState.xcuserstate
--------------------------------------------------------------------------------
/InboxExamples/Triage/Triage.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/InboxExamples/Snapmail/Snapmail.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/InboxExamples/SimpleMail/SimpleMail.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/InboxFramework/InboxFramework.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/InboxExamples/SwiftEightBall/SwiftEightBall.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/InboxExamples/Triage/Triage.xcodeproj/project.xcworkspace/xcuserdata/bengotow.xcuserdatad/UserInterfaceState.xcuserstate:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nylas/inbox-ios/HEAD/InboxExamples/Triage/Triage.xcodeproj/project.xcworkspace/xcuserdata/bengotow.xcuserdatad/UserInterfaceState.xcuserstate
--------------------------------------------------------------------------------
/InboxFramework/Documentation/index-template.txt:
--------------------------------------------------------------------------------
1 | For an introduction to the Inbox iOS SDK and Getting Started guides, see the [Inbox iOS Documentation](http://inboxapp.com/docs/ios). For more information about Inbox's REST API, check out the [Inbox API Reference](inboxapp.com/docs/api).
2 |
--------------------------------------------------------------------------------
/.arcconfig:
--------------------------------------------------------------------------------
1 | {
2 | "project_id" : "bigsur",
3 | "conduit_uri" : "https://review.inboxapp.com/",
4 | "lint.engine" : "InboxUncrustifyLintEngine",
5 | "lint.uncrustify.script": "uncrustify -c uncrustify.cfg -l OC --no-backup --mtime ",
6 | "load" : [
7 | "arclib"
8 | ]
9 | }
10 |
--------------------------------------------------------------------------------
/InboxFramework/Inbox/Models/API Calls/INSaveTagTask.h:
--------------------------------------------------------------------------------
1 | //
2 | // INSaveTagTask.h
3 | // InboxFramework
4 | //
5 | // Created by Ben Gotow on 9/17/14.
6 | // Copyright (c) 2014 Inbox. All rights reserved.
7 | //
8 |
9 | #import "INAPITask.h"
10 |
11 | @interface INSaveTagTask : INAPITask
12 |
13 | @end
14 |
--------------------------------------------------------------------------------
/InboxExamples/Snapmail/Snapmail/Images.xcassets/send-button.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "2x",
6 | "filename" : "send-button@2x.png"
7 | }
8 | ],
9 | "info" : {
10 | "version" : 1,
11 | "author" : "xcode"
12 | }
13 | }
--------------------------------------------------------------------------------
/InboxFramework/Inbox/Models/API Calls/INSaveDraftTask.h:
--------------------------------------------------------------------------------
1 | //
2 | // INSaveDraftChange.h
3 | // InboxFramework
4 | //
5 | // Created by Ben Gotow on 5/16/14.
6 | // Copyright (c) 2014 Inbox. All rights reserved.
7 | //
8 |
9 | #import "INAPITask.h"
10 |
11 | @interface INSaveDraftTask : INAPITask
12 |
13 | @end
14 |
--------------------------------------------------------------------------------
/InboxFramework/Inbox/Models/API Calls/INDeleteDraftTask.h:
--------------------------------------------------------------------------------
1 | //
2 | // INDeleteDraftChange.h
3 | // InboxFramework
4 | //
5 | // Created by Ben Gotow on 5/20/14.
6 | // Copyright (c) 2014 Inbox. All rights reserved.
7 | //
8 |
9 | #import "INAPITask.h"
10 |
11 | @interface INDeleteDraftTask : INAPITask
12 |
13 | @end
14 |
--------------------------------------------------------------------------------
/InboxFramework/Inbox/Models/API Calls/INSendDraftTask.h:
--------------------------------------------------------------------------------
1 | //
2 | // INSendDraftChange.h
3 | // InboxFramework
4 | //
5 | // Created by Ben Gotow on 5/20/14.
6 | // Copyright (c) 2014 Inbox. All rights reserved.
7 | //
8 |
9 | #import "INAddRemoveTagsTask.h"
10 |
11 | @interface INSendDraftTask : INAPITask
12 |
13 | @end
14 |
--------------------------------------------------------------------------------
/InboxFramework/Inbox/Categories/FMDatabase+INModelQueries.h:
--------------------------------------------------------------------------------
1 | //
2 | // FMDatabase+FMDatabase_SchemaVersioning_h.h
3 | // BigSur
4 | //
5 | // Created by Ben Gotow on 4/22/14.
6 | // Copyright (c) 2014 Inbox. All rights reserved.
7 | //
8 |
9 | #import "FMDatabase.h"
10 |
11 | @interface FMDatabase (INModelQueries)
12 |
13 | @end
14 |
--------------------------------------------------------------------------------
/InboxFramework/Inbox/Models/API Calls/INMarkMessageAsReadTask.h:
--------------------------------------------------------------------------------
1 | //
2 | // INMarkMessageAsReadTask.h
3 | // InboxFramework
4 | //
5 | // Created by Ben Gotow on 6/17/14.
6 | // Copyright (c) 2014 Inbox. All rights reserved.
7 | //
8 |
9 | #import "INAPITask.h"
10 |
11 | @interface INMarkMessageAsReadTask : INAPITask
12 |
13 | @end
14 |
--------------------------------------------------------------------------------
/InboxFramework/Inbox/Categories/FMDatabase+INModelQueries.m:
--------------------------------------------------------------------------------
1 | //
2 | // FMDatabase+FMDatabase_SchemaVersioning_h.m
3 | // BigSur
4 | //
5 | // Created by Ben Gotow on 4/22/14.
6 | // Copyright (c) 2014 Inbox. All rights reserved.
7 | //
8 |
9 | #import "FMDatabase+INModelQueries.h"
10 |
11 | @implementation FMDatabase (INModelQueries)
12 |
13 | @end
14 |
--------------------------------------------------------------------------------
/InboxExamples/Triage/Triage/TRMessageActionButton.h:
--------------------------------------------------------------------------------
1 | //
2 | // TRMessageActionButton.h
3 | // Triage
4 | //
5 | // Created by Ben Gotow on 5/8/14.
6 | // Copyright (c) 2014 Inbox. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface TRMessageActionButton : UIButton
12 | {
13 | UIView * _selectedView;
14 | }
15 |
16 | @end
17 |
--------------------------------------------------------------------------------
/InboxFramework/Inbox/Models/API Calls/INUploadFileTask.h:
--------------------------------------------------------------------------------
1 | //
2 | // INSaveAttachmentChange.h
3 | // InboxFramework
4 | //
5 | // Created by Ben Gotow on 5/21/14.
6 | // Copyright (c) 2014 Inbox. All rights reserved.
7 | //
8 |
9 | #import "INAPITask.h"
10 |
11 | @interface INUploadFileTask : INAPITask
12 |
13 | - (NSMutableArray *)waitingDrafts;
14 |
15 | @end
16 |
--------------------------------------------------------------------------------
/InboxExamples/SwiftEightBall/SwiftEightBall.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/InboxFramework/Inbox/Categories/NSPredicate+Inspection.h:
--------------------------------------------------------------------------------
1 | //
2 | // NSPredicate+Inspection.h
3 | // BigSur
4 | //
5 | // Created by Ben Gotow on 5/1/14.
6 | // Copyright (c) 2014 Inbox. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface NSPredicate (Inspection)
12 |
13 | - (BOOL)containsOrMatches:(NSString*)expression;
14 |
15 | @end
16 |
--------------------------------------------------------------------------------
/InboxExamples/SimpleMail/SimpleMail/SMAppDelegate.h:
--------------------------------------------------------------------------------
1 | //
2 | // SMAppDelegate.h
3 | // SimpleMail
4 | //
5 | // Created by Ben Gotow on 7/8/14.
6 | // Copyright (c) 2014 Inbox. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface SMAppDelegate : UIResponder
12 |
13 | @property (strong, nonatomic) UIWindow *window;
14 |
15 | @end
16 |
--------------------------------------------------------------------------------
/InboxExamples/Snapmail/Snapmail/Images.xcassets/snap-read.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x"
6 | },
7 | {
8 | "idiom" : "universal",
9 | "scale" : "2x",
10 | "filename" : "snap-read@2x.png"
11 | }
12 | ],
13 | "info" : {
14 | "version" : 1,
15 | "author" : "xcode"
16 | }
17 | }
--------------------------------------------------------------------------------
/InboxExamples/Snapmail/Snapmail/Images.xcassets/snap-sent.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x"
6 | },
7 | {
8 | "idiom" : "universal",
9 | "scale" : "2x",
10 | "filename" : "snap-sent@2x.png"
11 | }
12 | ],
13 | "info" : {
14 | "version" : 1,
15 | "author" : "xcode"
16 | }
17 | }
--------------------------------------------------------------------------------
/InboxExamples/Snapmail/Snapmail/Images.xcassets/snap-sending.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x"
6 | },
7 | {
8 | "idiom" : "universal",
9 | "scale" : "2x",
10 | "filename" : "snap-sending@2x.png"
11 | }
12 | ],
13 | "info" : {
14 | "version" : 1,
15 | "author" : "xcode"
16 | }
17 | }
--------------------------------------------------------------------------------
/InboxExamples/Snapmail/Snapmail/Images.xcassets/snap-unread.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x"
6 | },
7 | {
8 | "idiom" : "universal",
9 | "scale" : "2x",
10 | "filename" : "snap-unread@2x.png"
11 | }
12 | ],
13 | "info" : {
14 | "version" : 1,
15 | "author" : "xcode"
16 | }
17 | }
--------------------------------------------------------------------------------
/arclib/src/.phutil_module_cache:
--------------------------------------------------------------------------------
1 | {"__symbol_cache_version__":11,"c04d6a5c54d3a7b7ce80cbe38ad327be":{"have":{"class":{"InboxUncrustifyLinter":19,"UncrustifyLintEngine":1112}},"need":{"function":{"Futures":410},"class":{"ArcanistLinter":49,"ArcanistLintEngine":1141,"ExecFuture":297,"ArcanistUsageException":760}},"xmap":{"InboxUncrustifyLinter":["ArcanistLinter"],"UncrustifyLintEngine":["ArcanistLintEngine"]}}}
--------------------------------------------------------------------------------
/InboxExamples/Snapmail/Snapmail/Images.xcassets/capture-button.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x"
6 | },
7 | {
8 | "idiom" : "universal",
9 | "scale" : "2x",
10 | "filename" : "capture-button@2x.png"
11 | }
12 | ],
13 | "info" : {
14 | "version" : 1,
15 | "author" : "xcode"
16 | }
17 | }
--------------------------------------------------------------------------------
/InboxFramework/Inbox/Categories/NSDictionary+FormatConversion.h:
--------------------------------------------------------------------------------
1 | //
2 | // NSDictionary+FormatConversion.h
3 | // BigSur
4 | //
5 | // Created by Ben Gotow on 5/1/14.
6 | // Copyright (c) 2014 Inbox. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface NSDictionary (FormatConversion)
12 |
13 | - (id)objectForKey:(id)key asType:(NSString*)type;
14 |
15 | @end
16 |
--------------------------------------------------------------------------------
/InboxFramework/Inbox/Models/API Calls/INAddRemoveTagsTask.h:
--------------------------------------------------------------------------------
1 | //
2 | // INAddRemoveTagsChange.h
3 | // InboxFramework
4 | //
5 | // Created by Ben Gotow on 5/16/14.
6 | // Copyright (c) 2014 Inbox. All rights reserved.
7 | //
8 |
9 | #import "INAPITask.h"
10 |
11 | @interface INAddRemoveTagsTask : INAPITask
12 |
13 | - (NSMutableArray *)tagIDsToAdd;
14 | - (NSMutableArray *)tagIDsToRemove;
15 |
16 | @end
17 |
--------------------------------------------------------------------------------
/InboxFramework/Inbox/Categories/FMResultSet+INModelQueries.h:
--------------------------------------------------------------------------------
1 | //
2 | // FMResultSet+INModelQueries.h
3 | // BigSur
4 | //
5 | // Created by Ben Gotow on 4/22/14.
6 | // Copyright (c) 2014 Inbox. All rights reserved.
7 | //
8 |
9 | #import "FMResultSet.h"
10 | #import "INModelObject.h"
11 |
12 | @interface FMResultSet (INModelQueries)
13 |
14 | - (INModelObject *)nextModelOfClass:(Class)klass;
15 |
16 | @end
17 |
--------------------------------------------------------------------------------
/InboxFramework/Inbox/Models/Concrete Classes/INThread+Private.h:
--------------------------------------------------------------------------------
1 | //
2 | // INThread+Private.h
3 | // InboxFramework
4 | //
5 | // Created by Ben Gotow on 5/22/14.
6 | // Copyright (c) 2014 Inbox. All rights reserved.
7 | //
8 |
9 | #import "INThread.h"
10 |
11 | @interface INThread (Private)
12 |
13 | - (void)addDraftID:(NSString*)draftID;
14 | - (void)removeDraftID:(NSString*)draftID;
15 |
16 |
17 | @end
18 |
--------------------------------------------------------------------------------
/InboxExamples/SimpleMail/SimpleMail/main.m:
--------------------------------------------------------------------------------
1 | //
2 | // main.m
3 | // SimpleMail
4 | //
5 | // Created by Ben Gotow on 7/8/14.
6 | // Copyright (c) 2014 Inbox. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | #import "SMAppDelegate.h"
12 |
13 | int main(int argc, char * argv[])
14 | {
15 | @autoreleasepool {
16 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([SMAppDelegate class]));
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/InboxExamples/Snapmail/Snapmail/main.m:
--------------------------------------------------------------------------------
1 |
2 | //
3 | // main.m
4 | // Snapmail
5 | //
6 | // Created by Ben Gotow on 6/16/14.
7 | // Copyright (c) 2014 InboxApp, Inc. All rights reserved.
8 | //
9 |
10 | #import
11 |
12 | #import "INAppDelegate.h"
13 |
14 | int main(int argc, char * argv[])
15 | {
16 | @autoreleasepool {
17 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([INAppDelegate class]));
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/InboxExamples/Triage/Triage/main.m:
--------------------------------------------------------------------------------
1 |
2 | //
3 | // main.m
4 | // Snapmail
5 | //
6 | // Created by Ben Gotow on 6/16/14.
7 | // Copyright (c) 2014 InboxApp, Inc. All rights reserved.
8 | //
9 |
10 | #import
11 |
12 | #import "TRAppDelegate.h"
13 |
14 | int main(int argc, char * argv[])
15 | {
16 | @autoreleasepool {
17 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([TRAppDelegate class]));
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/InboxExamples/SimpleMail/SimpleMail/SMInboxTableViewController.h:
--------------------------------------------------------------------------------
1 | //
2 | // SMInboxTableViewController.h
3 | // SimpleMail
4 | //
5 | // Created by Ben Gotow on 7/8/14.
6 | // Copyright (c) 2014 Inbox. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface SMInboxTableViewController : UITableViewController
12 |
13 | @property (nonatomic, strong) INThreadProvider * threadProvider;
14 |
15 | @end
16 |
--------------------------------------------------------------------------------
/InboxFramework/Inbox/INSyncEngine.h:
--------------------------------------------------------------------------------
1 | //
2 | // INSyncEngine.h
3 | // BigSur
4 | //
5 | // Created by Ben Gotow on 5/16/14.
6 | // Copyright (c) 2014 Inbox. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @protocol INSyncEngine
12 |
13 | - (BOOL)providesCompleteCacheOf:(Class)klass;
14 |
15 | /* Clear all sync state, usually called during the logout process. */
16 | - (void)resetSyncState;
17 |
18 | @end
19 |
--------------------------------------------------------------------------------
/InboxExamples/Snapmail/Snapmail/Snapmail-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
8 |
9 | #ifndef __IPHONE_5_0
10 | #warning "This project uses features only available in iOS SDK 5.0 and later."
11 | #endif
12 |
13 | #ifdef __OBJC__
14 | #import
15 | #import
16 | #import "Inbox.h"
17 | #endif
18 |
--------------------------------------------------------------------------------
/InboxExamples/Triage/Triage/TRAppDelegate.h:
--------------------------------------------------------------------------------
1 | //
2 | // TRAppDelegate.h
3 | // Triage
4 | //
5 | // Created by Ben Gotow on 5/7/14.
6 | // Copyright (c) 2014 Inbox. All rights reserved.
7 | //
8 |
9 | #import
10 | #import "TRViewController.h"
11 |
12 | @interface TRAppDelegate : UIResponder
13 |
14 | @property (strong, nonatomic) TRViewController * viewController;
15 | @property (strong, nonatomic) UIWindow *window;
16 |
17 | @end
18 |
--------------------------------------------------------------------------------
/InboxExamples/SimpleMail/SimpleMail/SimpleMail-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
8 |
9 | #ifndef __IPHONE_5_0
10 | #warning "This project uses features only available in iOS SDK 5.0 and later."
11 | #endif
12 |
13 | #ifdef __OBJC__
14 | #import
15 | #import
16 | #import "Inbox.h"
17 | #endif
18 |
--------------------------------------------------------------------------------
/InboxExamples/Triage/Triage/Triage-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
8 |
9 | #ifndef __IPHONE_5_0
10 | #warning "This project uses features only available in iOS SDK 5.0 and later."
11 | #endif
12 |
13 | #ifdef __OBJC__
14 | #import
15 | #import
16 |
17 | #import "Inbox.h"
18 | #endif
19 |
--------------------------------------------------------------------------------
/InboxExamples/Triage/Triage/INPlaceholderTextView.h:
--------------------------------------------------------------------------------
1 | //
2 | // INPlaceholderTextView.h
3 | // BigSur
4 | //
5 | // DRAWN FROM http://stackoverflow.com/questions/1328638/placeholder-in-uitextview
6 |
7 | #import
8 |
9 | @interface INPlaceholderTextView : UITextView
10 |
11 | @property (nonatomic, retain) NSString *placeholder;
12 | @property (nonatomic, retain) UIColor *placeholderColor;
13 |
14 | -(void)textChanged:(NSNotification*)notification;
15 |
16 |
17 | @end
18 |
--------------------------------------------------------------------------------
/InboxExamples/SimpleMail/SimpleMail/Images.xcassets/unread_dot.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal"
5 | },
6 | {
7 | "idiom" : "universal",
8 | "scale" : "1x",
9 | "filename" : "unread_dot.png"
10 | },
11 | {
12 | "idiom" : "universal",
13 | "scale" : "2x",
14 | "filename" : "unread_dot@2x.png"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/InboxExamples/Snapmail/Snapmail/INAppDelegate.h:
--------------------------------------------------------------------------------
1 | //
2 | // INAppDelegate.h
3 | // Snapmail
4 | //
5 | // Created by Ben Gotow on 6/16/14.
6 | // Copyright (c) 2014 InboxApp, Inc. All rights reserved.
7 | //
8 |
9 | #import
10 | #import "INHomeViewController.h"
11 |
12 | @interface INAppDelegate : UIResponder
13 |
14 | @property (strong, nonatomic) UIWindow * window;
15 | @property (strong, nonatomic) INHomeViewController * viewController;
16 |
17 | @end
18 |
--------------------------------------------------------------------------------
/InboxExamples/SwiftEightBall/SwiftEightBall/Images.xcassets/unread_dot.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal"
5 | },
6 | {
7 | "idiom" : "universal",
8 | "scale" : "1x",
9 | "filename" : "unread_dot.png"
10 | },
11 | {
12 | "idiom" : "universal",
13 | "scale" : "2x",
14 | "filename" : "unread_dot@2x.png"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/arclib/.phutil_module_cache:
--------------------------------------------------------------------------------
1 | {"__symbol_cache_version__":11,"d24912c462effca0c0ff3edcc1756454":{"have":{"class":{"InboxUncrustifyLintEngine":19}},"need":{"class":{"ArcanistLintEngine":53,"InboxUncrustifyLinter":472}},"xmap":{"InboxUncrustifyLintEngine":["ArcanistLintEngine"]}},"5f8e940e7021ae81e87a0e19aefcd275":{"have":{"class":{"InboxUncrustifyLinter":19}},"need":{"function":{"Futures":410},"class":{"ArcanistLinter":49,"ExecFuture":297,"ArcanistUsageException":882}},"xmap":{"InboxUncrustifyLinter":["ArcanistLinter"]}}}
--------------------------------------------------------------------------------
/InboxExamples/SimpleMail/SimpleMail/Images.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "iphone",
5 | "size" : "29x29",
6 | "scale" : "2x"
7 | },
8 | {
9 | "idiom" : "iphone",
10 | "size" : "40x40",
11 | "scale" : "2x"
12 | },
13 | {
14 | "idiom" : "iphone",
15 | "size" : "60x60",
16 | "scale" : "2x"
17 | }
18 | ],
19 | "info" : {
20 | "version" : 1,
21 | "author" : "xcode"
22 | }
23 | }
--------------------------------------------------------------------------------
/InboxExamples/SwiftEightBall/SwiftEightBall/Images.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "iphone",
5 | "size" : "29x29",
6 | "scale" : "2x"
7 | },
8 | {
9 | "idiom" : "iphone",
10 | "size" : "40x40",
11 | "scale" : "2x"
12 | },
13 | {
14 | "idiom" : "iphone",
15 | "size" : "60x60",
16 | "scale" : "2x"
17 | }
18 | ],
19 | "info" : {
20 | "version" : 1,
21 | "author" : "xcode"
22 | }
23 | }
--------------------------------------------------------------------------------
/InboxFramework/Inbox/Categories/NSError+InboxErrors.h:
--------------------------------------------------------------------------------
1 | //
2 | // NSError+InboxErrors.h
3 | // InboxFramework
4 | //
5 | // Created by Ben Gotow on 5/27/14.
6 | // Copyright (c) 2014 Inbox. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface NSError (InboxErrors)
12 |
13 | + (NSError*)inboxErrorWithFormat:(NSString *)format, ...;
14 | + (NSError*)inboxErrorWithDescription:(NSString *)desc;
15 | + (NSError*)inboxErrorWithDescription:(NSString *)desc underlyingError:(NSError*)underlying;
16 |
17 | @end
18 |
--------------------------------------------------------------------------------
/InboxFramework/Inbox/Inbox-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 | #ifdef __OBJC__
8 |
9 | #import
10 |
11 | #ifndef COCOAPODS
12 | #import "INDependencyNamespacing.h"
13 | #endif
14 |
15 | #import "AFNetworking.h"
16 |
17 | #import "FMDatabase.h"
18 | #import "FMDatabaseQueue.h"
19 | #import "FMResultSet.h"
20 | #import "FMResultSet+INModelQueries.h"
21 | #import "FMDatabaseAdditions.h"
22 |
23 | #endif
24 |
--------------------------------------------------------------------------------
/InboxFramework/Inbox/Helpers/INPredicateToQueryParamConverter.h:
--------------------------------------------------------------------------------
1 | //
2 | // INPredicateToQueryParamConverter.h
3 | // BigSur
4 | //
5 | // Created by Ben Gotow on 5/2/14.
6 | // Copyright (c) 2014 Inbox. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface INPredicateToQueryParamConverter : NSObject
12 |
13 | @property (nonatomic, strong) NSDictionary * keysToParamsTable;
14 | @property (nonatomic, strong) NSDictionary * keysToLIKEParamsTable;
15 |
16 | - (NSDictionary*)paramsForPredicate:(NSPredicate*)predicate;
17 |
18 | @end
19 |
--------------------------------------------------------------------------------
/InboxFramework/InboxUI/Categories/UIView+FrameAdditions.h:
--------------------------------------------------------------------------------
1 | #import
2 |
3 | @interface UIView (FrameAdditions)
4 |
5 | - (void)in_setFrameY:(float)y;
6 | - (void)in_setFrameX:(float)x;
7 | - (void)in_shiftFrame:(CGPoint)offset;
8 | - (void)in_setFrameOrigin:(CGPoint)origin;
9 | - (void)in_setFrameSize:(CGSize)size;
10 | - (void)in_setFrameCenter:(CGPoint)p;
11 | - (void)in_setFrameWidth:(float)w;
12 | - (void)in_setFrameHeight:(float)h;
13 | - (CGPoint)in_topRight;
14 | - (CGPoint)in_bottomRight;
15 | - (CGPoint)in_bottomLeft;
16 | - (id)viewAncestorOfClass:(Class)klass;
17 |
18 | @end
19 |
--------------------------------------------------------------------------------
/InboxFramework/Inbox/Categories/NSObject+AssociatedObjects.h:
--------------------------------------------------------------------------------
1 | //
2 | // NSObject+AssociatedObjects.h
3 | //
4 | // Created by Andy Matuschak on 8/27/09.
5 | // Public domain because I love you.
6 | //
7 |
8 | #import
9 |
10 | @interface NSObject (AMAssociatedObjects)
11 |
12 | - (void)associateValue:(id)value withKey:(void *)key; // Strong reference
13 | - (void)weaklyAssociateValue:(id)value withKey:(void *)key;
14 | - (id)associatedValueForKey:(void *)key;
15 | - (void)performSelectorOnMainThreadOnce:(SEL)selector;
16 | - (void)markPerformedSelector:(SEL)selector;
17 |
18 | @end
19 |
--------------------------------------------------------------------------------
/InboxExamples/SimpleMail/SimpleMail/Images.xcassets/LaunchImage.launchimage/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "orientation" : "portrait",
5 | "idiom" : "iphone",
6 | "extent" : "full-screen",
7 | "minimum-system-version" : "7.0",
8 | "scale" : "2x"
9 | },
10 | {
11 | "orientation" : "portrait",
12 | "idiom" : "iphone",
13 | "subtype" : "retina4",
14 | "extent" : "full-screen",
15 | "minimum-system-version" : "7.0",
16 | "scale" : "2x"
17 | }
18 | ],
19 | "info" : {
20 | "version" : 1,
21 | "author" : "xcode"
22 | }
23 | }
--------------------------------------------------------------------------------
/InboxExamples/SwiftEightBall/SwiftEightBall/Images.xcassets/LaunchImage.launchimage/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "orientation" : "portrait",
5 | "idiom" : "iphone",
6 | "extent" : "full-screen",
7 | "minimum-system-version" : "7.0",
8 | "scale" : "2x"
9 | },
10 | {
11 | "orientation" : "portrait",
12 | "idiom" : "iphone",
13 | "subtype" : "retina4",
14 | "extent" : "full-screen",
15 | "minimum-system-version" : "7.0",
16 | "scale" : "2x"
17 | }
18 | ],
19 | "info" : {
20 | "version" : 1,
21 | "author" : "xcode"
22 | }
23 | }
--------------------------------------------------------------------------------
/InboxFramework/Inbox/Categories/NSString+FormatConversion.h:
--------------------------------------------------------------------------------
1 | //
2 | // NSString+FormatConversion.h
3 | // Mib.io
4 | //
5 | // Created by Ben Gotow on 6/7/12.
6 | // Copyright (c) 2012 Foundry376. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface NSString (FormatConversion)
12 |
13 | + (NSString *)stringWithDate:(NSDate *)date format:(NSString *)f;
14 | - (NSDate *)dateValueWithFormat:(NSString *)f;
15 | - (NSString *)md5Value;
16 |
17 | + (NSString *)generateUUIDWithExtension:(NSString *)ext;
18 | - (NSString *)urlencode;
19 |
20 | - (id)asJSONObjectOfClass:(Class)klass;
21 |
22 | @end
23 |
--------------------------------------------------------------------------------
/InboxFramework/Inbox/Models/INModelProvider+Private.h:
--------------------------------------------------------------------------------
1 | //
2 | // INModelView.h
3 | // BigSur
4 | //
5 | // Created by Ben Gotow on 4/24/14.
6 | // Copyright (c) 2014 Inbox. All rights reserved.
7 | //
8 |
9 | @interface INModelProvider (Private)
10 |
11 | - (NSPredicate*)fetchPredicate;
12 | - (void)fetchFromCache;
13 | - (void)fetchFromAPI;
14 | - (NSDictionary *)queryParamsForPredicate:(NSPredicate*)predicate;
15 |
16 | #pragma mark Receiving Updates from the Database;
17 |
18 | - (void)managerDidPersistModels:(NSArray *)savedArray;
19 | - (void)managerDidUnpersistModels:(NSArray*)models;
20 | - (void)managerDidReset;
21 |
22 | @end
--------------------------------------------------------------------------------
/InboxExamples/SimpleMail/SimpleMail/SMThreadTableViewCell.h:
--------------------------------------------------------------------------------
1 | //
2 | // SMThreadTableViewCell.h
3 | // SimpleMail
4 | //
5 | // Created by Ben Gotow on 7/8/14.
6 | // Copyright (c) 2014 Inbox. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface SMThreadTableViewCell : UITableViewCell
12 |
13 | @property (nonatomic, strong) IBOutlet UILabel * dateLabel;
14 | @property (nonatomic, strong) IBOutlet UILabel * fromLabel;
15 | @property (nonatomic, strong) IBOutlet UILabel * bodyLabel;
16 | @property (nonatomic, strong) IBOutlet UIImageView * unreadDot;
17 |
18 | - (void)setThread:(INThread*)thread;
19 |
20 | @end
21 |
--------------------------------------------------------------------------------
/InboxFramework/InboxUI/Views/INRecipientsLabel.h:
--------------------------------------------------------------------------------
1 | //
2 | // INRecipientsLabel.h
3 | // BigSur
4 | //
5 | // Created by Ben Gotow on 5/2/14.
6 | // Copyright (c) 2014 Inbox. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface INRecipientsLabel : UIView
12 | {
13 | NSMutableArray * _buttons;
14 | UIButton * _moreButton;
15 | }
16 | @property (nonatomic, strong) UIColor * textColor;
17 | @property (nonatomic, strong) UIFont * textFont;
18 | @property (nonatomic, assign) BOOL recipientsClickable;
19 |
20 | - (void)setPrefixString:(NSString*)prefix andRecipients:(NSArray*)recipients includeMe:(BOOL)includeMe;
21 |
22 | @end
23 |
--------------------------------------------------------------------------------
/.gitmodules:
--------------------------------------------------------------------------------
1 | [submodule "InboxFramework/Submodules/AFNetworking"]
2 | path = InboxFramework/Submodules/AFNetworking
3 | url = https://github.com/AFNetworking/AFNetworking.git
4 | [submodule "InboxFramework/Submodules/FMDB"]
5 | path = InboxFramework/Submodules/FMDB
6 | url = https://github.com/ccgus/fmdb.git
7 | [submodule "InboxFramework/Submodules/Kiwi"]
8 | path = InboxFramework/Submodules/Kiwi
9 | url = https://github.com/kiwi-bdd/Kiwi.git
10 | [submodule "InboxFramework/Submodules/PDKeychainBindingsController"]
11 | path = InboxFramework/Submodules/PDKeychainBindingsController
12 | url = https://github.com/carlbrown/PDKeychainBindingsController.git
13 |
--------------------------------------------------------------------------------
/arclib/__phutil_library_map__.php:
--------------------------------------------------------------------------------
1 | 2,
11 | 'class' =>
12 | array(
13 | 'InboxUncrustifyLintEngine' => 'src/InboxUncrustifyLintEngine.php',
14 | 'InboxUncrustifyLinter' => 'src/InboxUncrustifyLinter.php',
15 | ),
16 | 'function' =>
17 | array(
18 | ),
19 | 'xmap' =>
20 | array(
21 | 'InboxUncrustifyLintEngine' => 'ArcanistLintEngine',
22 | 'InboxUncrustifyLinter' => 'ArcanistLinter',
23 | ),
24 | ));
25 |
--------------------------------------------------------------------------------
/InboxExamples/Snapmail/Snapmail/INCaptureViewController.h:
--------------------------------------------------------------------------------
1 | //
2 | // INCaptureViewController.h
3 | // Snapmail
4 | //
5 | // Created by Ben Gotow on 6/16/14.
6 | // Copyright (c) 2014 InboxApp, Inc. All rights reserved.
7 | //
8 |
9 | #import
10 | #import
11 |
12 | @interface INCaptureViewController : UIViewController
13 |
14 | @property (nonatomic, strong) INThread * thread;
15 | @property (nonatomic, strong) UIImagePickerController * picker;
16 | @property (weak, nonatomic) IBOutlet UIButton *toggleSideButton;
17 |
18 | - (id)initWithThread:(INThread*)thread;
19 |
20 | @end
21 |
--------------------------------------------------------------------------------
/InboxFramework/Inbox/Helpers/INPredicateToSQLConverter.h:
--------------------------------------------------------------------------------
1 | //
2 | // INPredicateConverter.h
3 | // BigSur
4 | //
5 | // Created by Ben Gotow on 4/23/14.
6 | // Copyright (c) 2014 Inbox. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface INPredicateToSQLConverter : NSObject
12 |
13 | @property (nonatomic, strong) Class modelClass;
14 | @property (nonatomic, strong) NSMutableArray * additionalJoins;
15 | @property (nonatomic, strong) NSMutableArray * additionalJoinRHSExpressions;
16 |
17 | + (INPredicateToSQLConverter*)converterForModelClass:(Class)modelClass;
18 |
19 | - (NSString *)SQLForPredicate:(NSPredicate*)predicate;
20 | - (NSString *)SQLForSortDescriptors:(NSArray*)descriptors;
21 |
22 | @end
23 |
--------------------------------------------------------------------------------
/InboxFramework/Inbox/Models/Concrete Classes/INContact.h:
--------------------------------------------------------------------------------
1 | //
2 | // INContact.h
3 | // BigSur
4 | //
5 | // Created by Ben Gotow on 4/22/14.
6 | // Copyright (c) 2014 Inbox. All rights reserved.
7 | //
8 |
9 | #import "INModelObject.h"
10 |
11 | /** The INContact class provides a native wrapper around Inbox contacts
12 | http://inboxapp.com/docs/api#contacts
13 | */
14 | @interface INContact : INModelObject
15 |
16 | @property (nonatomic, strong) NSString * name;
17 | @property (nonatomic, strong) NSString * email;
18 | @property (nonatomic, strong) NSString * source;
19 | @property (nonatomic, strong) NSString * providerName;
20 | @property (nonatomic, strong) NSString * accountID;
21 | @property (nonatomic, strong) NSString * UID;
22 |
23 | @end
24 |
--------------------------------------------------------------------------------
/InboxFramework/Inbox/Models/Concrete Classes/INThread+Private.m:
--------------------------------------------------------------------------------
1 | //
2 | // INThread+Private.m
3 | // InboxFramework
4 | //
5 | // Created by Ben Gotow on 5/22/14.
6 | // Copyright (c) 2014 Inbox. All rights reserved.
7 | //
8 |
9 | #import "INThread+Private.h"
10 |
11 | @implementation INThread (Private)
12 |
13 | - (void)removeDraftID:(NSString*)draftID
14 | {
15 | NSMutableArray * IDs = [[self draftIDs] mutableCopy];
16 | [IDs removeObject: draftID];
17 | [self setDraftIDs: IDs];
18 | }
19 |
20 | - (void)addDraftID:(NSString*)draftID
21 | {
22 | NSMutableArray * IDs = [[self draftIDs] mutableCopy];
23 | if (![IDs containsObject: draftID])
24 | [IDs addObject: draftID];
25 | [self setDraftIDs: IDs];
26 | }
27 |
28 | @end
29 |
--------------------------------------------------------------------------------
/InboxFramework/Vendor/PDKeychainBindings/PDKeychainBindings.h:
--------------------------------------------------------------------------------
1 | //
2 | // PDKeychainBindings.h
3 | // PDKeychainBindingsController
4 | //
5 | // Created by Carl Brown on 7/10/11.
6 | // Copyright 2011 PDAgent, LLC. Released under MIT License.
7 | //
8 |
9 | #import
10 |
11 |
12 | @interface PDKeychainBindings : NSObject {
13 | @private
14 |
15 | }
16 |
17 | + (PDKeychainBindings *)sharedKeychainBindings;
18 |
19 | - (id)objectForKey:(NSString *)defaultName;
20 | - (void)setObject:(NSString *)value forKey:(NSString *)defaultName;
21 | - (void)setString:(NSString *)value forKey:(NSString *)defaultName;
22 | - (void)removeObjectForKey:(NSString *)defaultName;
23 |
24 | - (NSString *)stringForKey:(NSString *)defaultName;
25 | @end
26 |
--------------------------------------------------------------------------------
/InboxExamples/Snapmail/Snapmail/INSnapViewController.h:
--------------------------------------------------------------------------------
1 | //
2 | // INSnapViewController.h
3 | // Snapmail
4 | //
5 | // Created by Ben Gotow on 6/16/14.
6 | // Copyright (c) 2014 InboxApp, Inc. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface INSnapViewController : UIViewController
12 |
13 | @property (nonatomic, weak) IBOutlet UIActivityIndicatorView * spinner;
14 | @property (nonatomic, weak) IBOutlet UIImageView * imageView;
15 | @property (nonatomic, weak) IBOutlet UILabel * errorLabel;
16 | @property (nonatomic, weak) IBOutlet UILabel * timeLabel;
17 |
18 | @property (nonatomic, strong) NSTimer * timer;
19 | @property (nonatomic, strong) INMessageProvider * provider;
20 |
21 | - (id)initWithThread:(INThread*)thread;
22 |
23 | @end
24 |
--------------------------------------------------------------------------------
/InboxFramework/Inbox/Categories/NSPredicate+Inspection.m:
--------------------------------------------------------------------------------
1 | //
2 | // NSPredicate+Inspection.m
3 | // BigSur
4 | //
5 | // Created by Ben Gotow on 5/1/14.
6 | // Copyright (c) 2014 Inbox. All rights reserved.
7 | //
8 |
9 | #import "NSPredicate+Inspection.h"
10 |
11 | @implementation NSPredicate (Inspection)
12 |
13 | - (BOOL)containsOrMatches:(NSString*)expression
14 | {
15 | NSMutableString * descriptions = [NSMutableString string];
16 | if ([self isKindOfClass: [NSCompoundPredicate class]]) {
17 | for (NSPredicate * sub in [(NSCompoundPredicate*)self subpredicates])
18 | [descriptions appendString: [sub description]];
19 | } else {
20 | [descriptions appendString: [self description]];
21 | }
22 |
23 | if ([descriptions rangeOfString: expression].location != NSNotFound)
24 | return YES;
25 | return NO;
26 | }
27 | @end
28 |
--------------------------------------------------------------------------------
/InboxExamples/Snapmail/Snapmail/INContactsViewController.h:
--------------------------------------------------------------------------------
1 | //
2 | // INContactsViewController.h
3 | // BigSur
4 | //
5 | // Created by Ben Gotow on 5/5/14.
6 | // Copyright (c) 2014 Inbox. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | typedef void (^ ContactSelectionBlock)(NSArray * contacts);
12 |
13 | @interface INContactsViewController : UIViewController
14 |
15 | @property (nonatomic, strong) INNamespace * namespace;
16 | @property (nonatomic, strong) INModelProvider * contactsProvider;
17 | @property (nonatomic, strong) ContactSelectionBlock contactSelectionCallback;
18 | @property (nonatomic, weak) IBOutlet UITableView * tableView;
19 |
20 | - (id)initForSelectingContactInNamespace:(INNamespace*)ns withCallback:(ContactSelectionBlock)block;
21 |
22 | @end
23 |
--------------------------------------------------------------------------------
/InboxFramework/InboxTests/InboxTests-Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | ${EXECUTABLE_NAME}
9 | CFBundleIdentifier
10 | Inbox.${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 | INAPIPath
22 | http://localhost:5555/
23 |
24 |
25 |
--------------------------------------------------------------------------------
/InboxFramework/Vendor/PDKeychainBindings/PDKeychainBindingsController.h:
--------------------------------------------------------------------------------
1 | //
2 | // PDKeychainBindingsController.h
3 | // PDKeychainBindingsController
4 | //
5 | // Created by Carl Brown on 7/10/11.
6 | // Copyright 2011 PDAgent, LLC. Released under MIT License.
7 | //
8 |
9 | #import
10 | #import "PDKeychainBindings.h"
11 |
12 |
13 | @interface PDKeychainBindingsController : NSObject {
14 | @private
15 | PDKeychainBindings *_keychainBindings;
16 | NSMutableDictionary *_valueBuffer;
17 | }
18 |
19 | + (PDKeychainBindingsController *)sharedKeychainBindingsController;
20 | - (PDKeychainBindings *) keychainBindings;
21 |
22 | - (id)values; // accessor object for PDKeychainBindings values. This property is observable using key-value observing.
23 |
24 | - (NSString*)stringForKey:(NSString*)key;
25 | - (BOOL)storeString:(NSString*)string forKey:(NSString*)key;
26 |
27 | @end
28 |
29 |
--------------------------------------------------------------------------------
/InboxFramework/Inbox/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | ${EXECUTABLE_NAME}
9 | CFBundleIdentifier
10 | Inbox.${PRODUCT_NAME:rfc1034identifier}
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | ${PRODUCT_NAME}
15 | CFBundlePackageType
16 | FMWK
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | ${CURRENT_PROJECT_VERSION}
23 | NSPrincipalClass
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/InboxExamples/Triage/Triage/TRMessageCardView.h:
--------------------------------------------------------------------------------
1 | //
2 | // TRMessageCardView.h
3 | // Triage
4 | //
5 | // Created by Ben Gotow on 5/8/14.
6 | // Copyright (c) 2014 Inbox. All rights reserved.
7 | //
8 |
9 | #import
10 | #import "INPlaceholderTextView.h"
11 |
12 | @interface TRMessageCardView : UIView
13 |
14 | @property (nonatomic, strong) UIView * headersView;
15 | @property (nonatomic, strong) UILabel * subjectLabel;
16 | @property (nonatomic, strong) INRecipientsLabel * fromLabel;
17 | @property (nonatomic, strong) INMessageContentView * bodyView;
18 | @property (nonatomic, strong) INPlaceholderTextView * replyView;
19 | @property (nonatomic, strong) UIButton * exitButton;
20 |
21 | @property (nonatomic, assign) float angle;
22 | @property (nonatomic, strong) INThread * thread;
23 |
24 | - (void)setThread:(INThread*)thread;
25 | - (void)setShowReplyView:(BOOL)showReply;
26 | - (float)desiredHeight;
27 |
28 | @end
29 |
--------------------------------------------------------------------------------
/InboxFramework/Inbox/Models/Concrete Classes/INContact.m:
--------------------------------------------------------------------------------
1 | //
2 | // INContact.m
3 | // BigSur
4 | //
5 | // Created by Ben Gotow on 4/22/14.
6 | // Copyright (c) 2014 Inbox. All rights reserved.
7 | //
8 |
9 | #import "INContact.h"
10 |
11 | @implementation INContact
12 |
13 | + (NSMutableDictionary *)resourceMapping
14 | {
15 | NSMutableDictionary * mapping = [super resourceMapping];
16 |
17 | [mapping addEntriesFromDictionary:@{
18 | @"source": @"source",
19 | @"name": @"name",
20 | @"providerName": @"provider_name",
21 | @"email": @"email",
22 | @"accountID": @"account_id",
23 | @"UID": @"uid"
24 | }];
25 | return mapping;
26 | }
27 |
28 | + (NSString *)resourceAPIName
29 | {
30 | return @"contacts";
31 | }
32 |
33 | + (NSArray *)databaseIndexProperties
34 | {
35 | return [[super databaseIndexProperties] arrayByAddingObjectsFromArray: @[@"name", @"email", @"accountID"]];
36 | }
37 |
38 | - (void)setup
39 | {
40 | }
41 |
42 |
43 | @end
44 |
--------------------------------------------------------------------------------
/InboxFramework/Inbox/Inbox-Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | English
7 | CFBundleExecutable
8 | ${EXECUTABLE_NAME}
9 | CFBundleIconFile
10 |
11 | CFBundleIdentifier
12 | Inbox.${PRODUCT_NAME:rfc1034identifier}
13 | CFBundleInfoDictionaryVersion
14 | 6.0
15 | CFBundleName
16 | ${PRODUCT_NAME}
17 | CFBundlePackageType
18 | FMWK
19 | CFBundleShortVersionString
20 | 1.0
21 | CFBundleSignature
22 | ????
23 | CFBundleVersion
24 | 1
25 | NSPrincipalClass
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/InboxFramework/Inbox/Helpers/INModelResponseSerializer.h:
--------------------------------------------------------------------------------
1 | //
2 | // INModelArrayResponseSerializer.h
3 | // BigSur
4 | //
5 | // Created by Ben Gotow on 4/28/14.
6 | // Copyright (c) 2014 Inbox. All rights reserved.
7 | //
8 |
9 | /**
10 | A subclass of AFJSONResponseSerializer that automatically parses Inbox API
11 | responses and saves the returned INModelObjects to the local data store.
12 |
13 | Any models that are already in memory are updated. This causes
14 | INModelObjectChangedNotifications so changes propogate to views and controllers
15 | listening on these models.
16 | */
17 |
18 | @class AFJSONResponseSerializer;
19 |
20 | @interface INModelResponseSerializer : AFJSONResponseSerializer
21 |
22 | @property (nonatomic, strong) Class modelClass;
23 | @property (nonatomic, strong) NSArray * modelsCurrentlyMatching;
24 |
25 | - (id)initWithModelClass:(Class)klass;
26 |
27 | - (id)responseObjectForResponse:(NSURLResponse *)response data:(NSData *)data error:(NSError * __autoreleasing *)error;
28 |
29 | @end
30 |
--------------------------------------------------------------------------------
/InboxFramework/InboxUI/Views/INMessageContentView.h:
--------------------------------------------------------------------------------
1 | //
2 | // INMessageContentView.h
3 | // BigSur
4 | //
5 | // Created by Ben Gotow on 5/23/14.
6 | // Copyright (c) 2014 Inbox. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @protocol INMessageContentViewDelegate
12 |
13 | - (void)messageContentViewSizeDetermined:(CGSize)size;
14 |
15 | @end
16 |
17 | @interface INMessageContentView : UIView
18 | {
19 | NSString * _content;
20 | BOOL _contentLoadCompleted;
21 | }
22 |
23 | @property (nonatomic, weak) IBOutlet NSObject * delegate;
24 |
25 | @property (nonatomic, strong) UIColor * tintColor;
26 | @property (nonatomic, strong) UIWebView * webView;
27 | @property (nonatomic, strong) UITextView * textView;
28 | @property (nonatomic, assign) UIEdgeInsets contentMargin;
29 | @property (nonatomic, strong) NSURL * contentBaseURL;
30 |
31 | - (void)clearContent;
32 | - (void)setContent:(NSString*)content;
33 | - (void)setContentMargin:(UIEdgeInsets)margin;
34 |
35 | - (float)bodyHeight;
36 | - (UIScrollView*)scrollView;
37 |
38 | @end
39 |
--------------------------------------------------------------------------------
/InboxExamples/Snapmail/Snapmail/INHomeViewController.h:
--------------------------------------------------------------------------------
1 | //
2 | // INViewController.h
3 | // Snapmail
4 | //
5 | // Created by Ben Gotow on 6/16/14.
6 | // Copyright (c) 2014 InboxApp, Inc. All rights reserved.
7 | //
8 |
9 | #import
10 | #import "INSnapViewController.h"
11 | #import "INCaptureViewController.h"
12 |
13 | @interface INHomeViewController : UIViewController
14 |
15 | @property (weak, nonatomic) IBOutlet UITableView * tableView;
16 | @property (weak, nonatomic) IBOutlet UILabel *statusLabel;
17 | @property (strong, nonatomic) UIRefreshControl * tableRefreshControl;
18 |
19 | @property (nonatomic, strong) INSnapViewController * snapController;
20 | @property (nonatomic, strong) INCaptureViewController * captureController;
21 |
22 | @property (nonatomic, strong) INModelProvider * sendingProvider;
23 | @property (nonatomic, strong) INThreadProvider * threadProvider;
24 |
25 | @property (nonatomic, strong) INMessageProvider * messageProvider;
26 |
27 | - (void)dismissSnapViewController;
28 |
29 | @end
30 |
--------------------------------------------------------------------------------
/InboxExamples/Snapmail/Snapmail/Images.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "iphone",
5 | "size" : "29x29",
6 | "scale" : "2x"
7 | },
8 | {
9 | "idiom" : "iphone",
10 | "size" : "40x40",
11 | "scale" : "2x"
12 | },
13 | {
14 | "idiom" : "iphone",
15 | "size" : "60x60",
16 | "scale" : "2x"
17 | },
18 | {
19 | "idiom" : "ipad",
20 | "size" : "29x29",
21 | "scale" : "1x"
22 | },
23 | {
24 | "idiom" : "ipad",
25 | "size" : "29x29",
26 | "scale" : "2x"
27 | },
28 | {
29 | "idiom" : "ipad",
30 | "size" : "40x40",
31 | "scale" : "1x"
32 | },
33 | {
34 | "idiom" : "ipad",
35 | "size" : "40x40",
36 | "scale" : "2x"
37 | },
38 | {
39 | "idiom" : "ipad",
40 | "size" : "76x76",
41 | "scale" : "1x"
42 | },
43 | {
44 | "idiom" : "ipad",
45 | "size" : "76x76",
46 | "scale" : "2x"
47 | }
48 | ],
49 | "info" : {
50 | "version" : 1,
51 | "author" : "xcode"
52 | }
53 | }
--------------------------------------------------------------------------------
/InboxExamples/Triage/Triage/TRViewController.h:
--------------------------------------------------------------------------------
1 | //
2 | // TRViewController.h
3 | // Triage
4 | //
5 | // Created by Ben Gotow on 5/7/14.
6 | // Copyright (c) 2014 Inbox. All rights reserved.
7 | //
8 |
9 | #import
10 | #import "TRMessageActionButton.h"
11 |
12 | @interface TRViewController : UIViewController
13 |
14 | @property (nonatomic, weak) IBOutlet UIButton * messageDismissView;
15 | @property (weak, nonatomic) IBOutlet TRMessageActionButton *saveButton;
16 | @property (weak, nonatomic) IBOutlet TRMessageActionButton *archiveButton;
17 | @property (weak, nonatomic) IBOutlet UIView *emptyView;
18 | @property (weak, nonatomic) IBOutlet UILabel *emptyTextLabel;
19 |
20 | @property (nonatomic, strong) UIPanGestureRecognizer * cardDragRecognizer;
21 | @property (nonatomic, strong) UITapGestureRecognizer * cardDTapRecognizer;
22 | @property (nonatomic, strong) NSMutableArray * cardViews;
23 | @property (nonatomic, strong) UIDynamicAnimator * animator;
24 |
25 | @property (nonatomic, strong) INModelProvider * threadProvider;
26 |
27 | @end
28 |
--------------------------------------------------------------------------------
/InboxFramework/Inbox/Models/INMessageProvider.h:
--------------------------------------------------------------------------------
1 | //
2 | // INMessageProvider.h
3 | // BigSur
4 | //
5 | // Created by Ben Gotow on 4/30/14.
6 | // Copyright (c) 2014 Inbox. All rights reserved.
7 | //
8 |
9 | #import "INModelProvider.h"
10 |
11 | /** A concrete subclass of INModelProvider specifically for managing result sets
12 | of messages and drafts. This subclass adds support for API query parameters that
13 | are specific to messages and drafts.
14 | */
15 | @interface INMessageProvider : INModelProvider
16 |
17 | /**
18 | @param threadID The thread ID to fetch messages for.
19 | @param namespaceID The namespace in which the thread lives.
20 | @return An INMessageProvider initialized for displaying messages.
21 | */
22 | - (id)initForMessagesInThread:(NSString *)threadID andNamespaceID:(NSString*)namespaceID;
23 |
24 | /**
25 | @param threadID The thread ID to fetch drafts for.
26 | @param namespaceID The namespace in which the thread lives.
27 | @return An INMessageProvider initialized for displaying drafts.
28 | */
29 | - (id)initForDraftsInThread:(NSString *)threadID andNamespaceID:(NSString*)namespaceID;
30 |
31 | @end
32 |
--------------------------------------------------------------------------------
/InboxExamples/SwiftEightBall/SwiftEightBall/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | ${EXECUTABLE_NAME}
9 | CFBundleIdentifier
10 | Inbox.${PRODUCT_NAME:rfc1034identifier}
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | ${PRODUCT_NAME}
15 | CFBundlePackageType
16 | APPL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 1
23 | LSRequiresIPhoneOS
24 |
25 | UIMainStoryboardFile
26 | Main
27 | INAPIPath
28 | http://localhost:5555/
29 | UIRequiredDeviceCapabilities
30 |
31 | armv7
32 |
33 |
34 |
35 |
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 | ----
3 |
4 | Copyright (c) 2014 InboxApp, Inc. and Contributors
5 |
6 | Permission is hereby granted, free of charge, to any person obtaining a copy
7 | of this software and associated documentation files (the "Software"), to deal
8 | in the Software without restriction, including without limitation the rights
9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | copies of the Software, and to permit persons to whom the Software is
11 | furnished to do so, subject to the following conditions:
12 |
13 | The above copyright notice and this permission notice shall be included in
14 | all copies or substantial portions of the Software.
15 |
16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | THE SOFTWARE.
--------------------------------------------------------------------------------
/InboxFramework/Inbox/Categories/NSError+InboxErrors.m:
--------------------------------------------------------------------------------
1 | //
2 | // NSError+InboxErrors.m
3 | // InboxFramework
4 | //
5 | // Created by Ben Gotow on 5/27/14.
6 | // Copyright (c) 2014 Inbox. All rights reserved.
7 | //
8 |
9 | #import "NSError+InboxErrors.h"
10 |
11 | @implementation NSError (InboxErrors)
12 |
13 | + (NSError*)inboxErrorWithFormat:(NSString *)format, ...
14 | {
15 | va_list args;
16 | va_start(args, format);
17 | NSString * description = [[NSString alloc] initWithFormat:format arguments:args];
18 | va_end(args);
19 | return [NSError errorWithDomain:@"Inbox" code:-1 userInfo:@{NSLocalizedDescriptionKey: description}];
20 | }
21 |
22 | + (NSError*)inboxErrorWithDescription:(NSString *)desc
23 | {
24 | return [NSError errorWithDomain:@"Inbox" code:-1 userInfo:@{NSLocalizedDescriptionKey: desc}];
25 | }
26 |
27 | + (NSError*)inboxErrorWithDescription:(NSString *)desc underlyingError:(NSError*)underlying
28 | {
29 | desc = [desc stringByAppendingFormat: @" %@", [underlying localizedDescription]];
30 | return [NSError errorWithDomain:@"Inbox" code:-1 userInfo:@{NSLocalizedDescriptionKey: desc, NSUnderlyingErrorKey: underlying}];
31 | }
32 |
33 | @end
34 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *Pods
2 |
3 | *Podfile.lock
4 |
5 | /.DS_Store
6 |
7 | *DerivedData
8 |
9 | /BigSur.xcodeproj/xcuserdata
10 |
11 | /BigSur.xcworkspace/xcuserdata
12 |
13 | *.DS_Store
14 |
15 | /build
16 |
17 | /file_list
18 |
19 | *.uncrustify
20 |
21 | /html/
22 |
23 | /InboxFramework/DerivedData
24 |
25 | /InboxFramework/InboxFramework.xcodeproj/xcuserdata
26 | /InboxFramework/InboxFramework.xcworkspace/xcuserdata
27 |
28 | /InboxFramework/InboxFramework.xcodeproj/project.xcworkspace/xcuserdata
29 |
30 | /InboxFramework/Pods
31 |
32 | /BigSur/DerivedData
33 |
34 | /BigSur/Pods/
35 |
36 | /BigSur/Podfile.lock
37 |
38 | /InboxFramework/Podfile.lock
39 |
40 | /InboxExamples/Triage/Pods
41 |
42 | /InboxExamples/Triage/Podfile.lock
43 |
44 | /InboxExamples/Triage/DerivedData
45 |
46 | /InboxExamples/Triage/Triage.xcworkspace/xcuserdata
47 |
48 | /InboxExamples/Triage/Triage.xcodeproj/xcuserdata
49 |
50 | /BigSur/BigSur.xcworkspace/xcuserdata/bengotow.xcuserdatad/UserInterfaceState.xcuserstate
51 |
52 | *.xcbkptlist
53 |
54 | *xcuserdata
55 |
56 | /InboxExamples/Snapmail/Pods
57 |
58 | /InboxExamples/Snapmail/Snapmail.xcodeproj/project.xcworkspace/xcuserdata
59 |
60 | *.xcuserstate
61 |
--------------------------------------------------------------------------------
/InboxFramework/Inbox/Categories/FMResultSet+INModelQueries.m:
--------------------------------------------------------------------------------
1 | //
2 | // FMResultSet+INModelQueries.m
3 | // BigSur
4 | //
5 | // Created by Ben Gotow on 4/22/14.
6 | // Copyright (c) 2014 Inbox. All rights reserved.
7 | //
8 |
9 | #import "FMResultSet+INModelQueries.h"
10 | #import "INModelObject+Uniquing.h"
11 |
12 | @implementation FMResultSet (INModelQueries)
13 |
14 | - (INModelObject *)nextModelOfClass:(Class)klass
15 | {
16 | if ([klass isSubclassOfClass:[INModelObject class]] == NO)
17 | @throw @"Can only be used with subclasses of INModelObject";
18 |
19 | [self next];
20 |
21 | if (![self hasAnotherRow])
22 | return nil;
23 |
24 | NSError * err = nil;
25 | NSData * jsonData = [self dataNoCopyForColumn:@"data"];
26 | NSDictionary * json = [NSJSONSerialization JSONObjectWithData:jsonData options:NSJSONReadingAllowFragments error:&err];
27 |
28 | if (json && !err) {
29 | BOOL created = NO;
30 | INModelObject * model = [klass attachedInstanceMatchingID: json[@"id"] createIfNecessary:YES didCreate: &created];
31 | if (created) {
32 | [model updateWithResourceDictionary: json];
33 | [model setup];
34 | }
35 | return model;
36 |
37 | } else {
38 | return nil;
39 | }
40 | }
41 |
42 | @end
43 |
--------------------------------------------------------------------------------
/InboxExamples/Snapmail/Snapmail/Images.xcassets/LaunchImage.launchimage/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "orientation" : "portrait",
5 | "idiom" : "iphone",
6 | "extent" : "full-screen",
7 | "minimum-system-version" : "7.0",
8 | "scale" : "2x"
9 | },
10 | {
11 | "orientation" : "portrait",
12 | "idiom" : "iphone",
13 | "subtype" : "retina4",
14 | "extent" : "full-screen",
15 | "minimum-system-version" : "7.0",
16 | "scale" : "2x"
17 | },
18 | {
19 | "orientation" : "portrait",
20 | "idiom" : "ipad",
21 | "extent" : "full-screen",
22 | "minimum-system-version" : "7.0",
23 | "scale" : "1x"
24 | },
25 | {
26 | "orientation" : "landscape",
27 | "idiom" : "ipad",
28 | "extent" : "full-screen",
29 | "minimum-system-version" : "7.0",
30 | "scale" : "1x"
31 | },
32 | {
33 | "orientation" : "portrait",
34 | "idiom" : "ipad",
35 | "extent" : "full-screen",
36 | "minimum-system-version" : "7.0",
37 | "scale" : "2x"
38 | },
39 | {
40 | "orientation" : "landscape",
41 | "idiom" : "ipad",
42 | "extent" : "full-screen",
43 | "minimum-system-version" : "7.0",
44 | "scale" : "2x"
45 | }
46 | ],
47 | "info" : {
48 | "version" : 1,
49 | "author" : "xcode"
50 | }
51 | }
--------------------------------------------------------------------------------
/InboxFramework/Inbox/Models/INThreadProvider.h:
--------------------------------------------------------------------------------
1 | //
2 | // INThreadProvider.h
3 | // BigSur
4 | //
5 | // Created by Ben Gotow on 4/28/14.
6 | // Copyright (c) 2014 Inbox. All rights reserved.
7 | //
8 |
9 | #import "INModelProvider.h"
10 | #import "INNamespace.h"
11 |
12 | /** A concrete subclass of INModelProvider that exposes convenience functions
13 | for counting unread threads and supports additional query parameters on underlying
14 | API requests.
15 | */
16 | @interface INThreadProvider : INModelProvider
17 |
18 | /*
19 | @param namespaceID The namespace to fetch threads for. To fetch a subset of
20 | the threads in the namespace, set the model provider's itemFilterPredicate.
21 |
22 | @return An initialized INThreadProvider for threads in the given namespace.
23 | */
24 | - (id)initWithNamespaceID:(NSString *)namespaceID;
25 |
26 | /*
27 | Count the number of unread threads in this provider's collection. This method
28 | returns the number of threads matching the itemFilterPredicate that also have the
29 | unread tag, and does not apply the provider's itemRange, giving a total number
30 | of unread threads, not just the ones that are currently being provided to the delegate.
31 |
32 | @param callback A block to be called when the unread count is determined. The
33 | block will be called on the main thread asynchronously.
34 | */
35 | - (void)countUnreadItemsWithCallback:(LongBlock)callback;
36 |
37 | @end
38 |
--------------------------------------------------------------------------------
/InboxFramework/Inbox/Categories/NSObject+AssociatedObjects.m:
--------------------------------------------------------------------------------
1 | //
2 | // NSObject+AssociatedObjects.m
3 | //
4 | // Created by Andy Matuschak on 8/27/09.
5 | // Public domain because I love you.
6 | //
7 |
8 | #import "NSObject+AssociatedObjects.h"
9 | #import
10 |
11 | @implementation NSObject (AMAssociatedObjects)
12 |
13 | - (void)associateValue:(id)value withKey:(void *)key
14 | {
15 | objc_setAssociatedObject(self, key, value, OBJC_ASSOCIATION_RETAIN);
16 | }
17 |
18 | - (void)weaklyAssociateValue:(id)value withKey:(void *)key
19 | {
20 | objc_setAssociatedObject(self, key, value, OBJC_ASSOCIATION_ASSIGN);
21 | }
22 |
23 | - (id)associatedValueForKey:(void *)key
24 | {
25 | return objc_getAssociatedObject(self, key);
26 | }
27 |
28 | #pragma clang diagnostic push
29 | #pragma clang diagnostic ignored "-Warc-performSelector-leaks"
30 |
31 | - (void)performSelectorOnMainThreadOnce:(SEL)selector
32 | {
33 | [self associateValue:[NSNumber numberWithBool:YES] withKey:(void *)selector];
34 |
35 | dispatch_async(dispatch_get_main_queue(), ^{
36 | if ([self associatedValueForKey:(void *)selector]) {
37 | [self performSelector:selector];
38 | [self associateValue:nil withKey:(void *)selector];
39 | }
40 | });
41 | }
42 |
43 | - (void)markPerformedSelector:(SEL)selector
44 | {
45 | [self associateValue:nil withKey:(void *)selector];
46 | }
47 |
48 | #pragma clang diagnostic pop
49 |
50 | @end
51 |
--------------------------------------------------------------------------------
/InboxFramework/Inbox/Inbox.h:
--------------------------------------------------------------------------------
1 | //
2 | // Inbox.h
3 | // InboxFramework
4 | //
5 | // Created by Ben Gotow on 5/8/14.
6 | // Copyright (c) 2014 Inbox. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | #ifndef InboxFramework_Inb_xh_h
12 | #define InboxFramework_Inb_xh_h
13 |
14 | //! Project version number for Inbox.
15 | FOUNDATION_EXPORT double InboxVersionNumber;
16 |
17 | //! Project version string for Inbox.
18 | FOUNDATION_EXPORT const unsigned char InboxVersionString[];
19 |
20 |
21 | /** If you're getting errors saying "Header could not be found," select the
22 | header file in Xcode and make sure it's visibility is "Public" in the framework
23 | build target.
24 | */
25 |
26 | #import "INAPIManager.h"
27 | #import "INDatabaseManager.h"
28 | #import "INMessageProvider.h"
29 | #import "INThreadProvider.h"
30 | #import "INThread.h"
31 | #import "INModelObject.h"
32 | #import "INMessage.h"
33 | #import "INContact.h"
34 | #import "INNamespace.h"
35 | #import "INTag.h"
36 | #import "INAPITask.h"
37 | #import "INAddRemoveTagsTask.h"
38 | #import "INSendDraftTask.h"
39 | #import "INUploadFileTask.h"
40 | #import "INSaveDraftTask.h"
41 | #import "INDeleteDraftTask.h"
42 | #import "INSaveTagTask.h"
43 | #import "INSyncEngine.h"
44 | #import "INFile.h"
45 | #import "INDraft.h"
46 | #import "NSError+InboxErrors.h"
47 |
48 | #ifdef TARGET_OS_IPHONE
49 | #import "INMessageContentView.h"
50 | #import "INRecipientsLabel.h"
51 | #endif
52 |
53 | #endif
54 |
--------------------------------------------------------------------------------
/InboxFramework/Inbox/Categories/NSDictionary+FormatConversion.m:
--------------------------------------------------------------------------------
1 | //
2 | // NSDictionary+FormatConversion.m
3 | // BigSur
4 | //
5 | // Created by Ben Gotow on 5/1/14.
6 | // Copyright (c) 2014 Inbox. All rights reserved.
7 | //
8 |
9 | #import "NSDictionary+FormatConversion.h"
10 | #import "NSString+FormatConversion.h"
11 | #import "INModelObject.h"
12 |
13 | @implementation NSDictionary (FormatConversion)
14 |
15 | - (id)objectForKey:(id)key asType:(NSString*)type
16 | {
17 | id value = [self objectForKey:key];
18 |
19 | NSAssert(value != nil, @"You cannot call -objectForKey:asType: for a nonexistent key, because nonexistence cannot be distinguished from NSNull=nil in the return value.");
20 |
21 | if ([[self objectForKey:key] isKindOfClass:[NSNull class]]) {
22 | return nil;
23 | }
24 |
25 | if ([type isEqualToString:@"float"]) {
26 | return [NSNumber numberWithFloat:[value floatValue]];
27 | }
28 | else if ([type isEqualToString:@"int"]) {
29 | return [NSNumber numberWithInt:[value intValue]];
30 | }
31 | else if ([type isEqualToString:@"T@\"NSString\""]) {
32 | if ([value isKindOfClass:[NSNumber class]])
33 | return [value stringValue];
34 | else if ([value isKindOfClass:[NSString class]])
35 | return value;
36 | else
37 | return [value stringValue];
38 | }
39 | else if ([type isEqualToString:@"T@\"NSDate\""]) {
40 | return [NSDate dateWithTimeIntervalSince1970: [value doubleValue]];
41 | }
42 |
43 | return value;
44 | }
45 |
46 | @end
47 |
--------------------------------------------------------------------------------
/InboxFramework/Inbox/Models/API Calls/INMarkMessageAsReadTask.m:
--------------------------------------------------------------------------------
1 | //
2 | // INMarkMessageAsReadTask.m
3 | // InboxFramework
4 | //
5 | // Created by Ben Gotow on 6/17/14.
6 | // Copyright (c) 2014 Inbox. All rights reserved.
7 | //
8 |
9 | #import "INMarkMessageAsReadTask.h"
10 | #import "INMessage.h"
11 | #import "INDatabaseManager.h"
12 |
13 | @implementation INMarkMessageAsReadTask
14 |
15 |
16 | - (NSURLRequest *)buildAPIRequest
17 | {
18 | NSAssert([self model], @"INMarkMessageAsReadTask asked to buildRequest with no access to a message model!");
19 | NSAssert([[self model] namespaceID], @"INMarkMessageAsReadTask asked to buildRequest with no namespace!");
20 |
21 | NSError * error = nil;
22 | NSString * path = [self.model resourceAPIPath];
23 | NSString * url = [[NSURL URLWithString:path relativeToURL:[INAPIManager shared].AF.baseURL] absoluteString];
24 |
25 | NSMutableDictionary * params = [NSMutableDictionary dictionary];
26 | [params setObject:@(NO) forKey:@"unread"];
27 |
28 | return [[[[INAPIManager shared] AF] requestSerializer] requestWithMethod:@"PUT" URLString:url parameters:params error:&error];
29 | }
30 |
31 | - (void)applyLocally
32 | {
33 | [(INMessage*)self.model setUnread: NO];
34 | [[INDatabaseManager shared] persistModel: self.model];
35 | }
36 |
37 | - (void)rollbackLocally
38 | {
39 | [(INMessage*)self.model setUnread: YES];
40 | [[INDatabaseManager shared] persistModel: self.model];
41 | }
42 |
43 | - (BOOL)canCancelPendingTask:(INAPITask*)other
44 | {
45 | return ([[other model] isEqual: self.model] && [other isKindOfClass: [self class]]);
46 | }
47 |
48 | @end
49 |
--------------------------------------------------------------------------------
/InboxExamples/Triage/Triage/TRMessageActionButton.m:
--------------------------------------------------------------------------------
1 | //
2 | // TRMessageActionButton.m
3 | // Triage
4 | //
5 | // Created by Ben Gotow on 5/8/14.
6 | // Copyright (c) 2014 Inbox. All rights reserved.
7 | //
8 |
9 | #import "TRMessageActionButton.h"
10 |
11 | @implementation TRMessageActionButton
12 |
13 | - (id)initWithFrame:(CGRect)frame
14 | {
15 | self = [super initWithFrame:frame];
16 | if (self) {
17 |
18 | }
19 | return self;
20 | }
21 |
22 | - (void)awakeFromNib
23 | {
24 | _selectedView = [[UIView alloc] initWithFrame: self.bounds];
25 | [[_selectedView layer] setCornerRadius: self.bounds.size.width / 2];
26 | [_selectedView setBackgroundColor: [self tintColor]];
27 | [self insertSubview:_selectedView belowSubview:self.titleLabel];
28 | [_selectedView setTransform: CGAffineTransformMakeScale(0.1, 0.1)];
29 | [_selectedView setAlpha: 0];
30 |
31 | [self setTitleColor:[UIColor whiteColor] forState:UIControlStateSelected];
32 | }
33 |
34 | - (void)setSelected:(BOOL)selected
35 | {
36 | if (self.selected == selected)
37 | return;
38 |
39 | [super setSelected: selected];
40 |
41 | [UIView animateWithDuration:0.5 delay:0 usingSpringWithDamping:0.45 initialSpringVelocity:0 options:UIViewAnimationOptionBeginFromCurrentState animations:^{
42 | if (selected == NO) {
43 | [_selectedView setTransform: CGAffineTransformMakeScale(0.1, 0.1)];
44 | [_selectedView setAlpha: 0];
45 | } else {
46 | [_selectedView setTransform: CGAffineTransformMakeScale(1.1, 1.1)];
47 | [_selectedView setAlpha: 1];
48 | }
49 | } completion:NULL];
50 | }
51 |
52 | @end
53 |
--------------------------------------------------------------------------------
/InboxFramework/Vendor/PDKeychainBindings/PDKeychainBindings.m:
--------------------------------------------------------------------------------
1 | //
2 | // PDKeychainBindings.m
3 | // PDKeychainBindings
4 | //
5 | // Created by Carl Brown on 7/10/11.
6 | // Copyright 2011 PDAgent, LLC. Released under MIT License.
7 | //
8 |
9 | #import "PDKeychainBindings.h"
10 | #import "PDKeychainBindingsController.h"
11 |
12 | @implementation PDKeychainBindings
13 |
14 | + (PDKeychainBindings *)sharedKeychainBindings
15 | {
16 | return [[PDKeychainBindingsController sharedKeychainBindingsController] keychainBindings];
17 | }
18 |
19 | - (id)objectForKey:(NSString *)defaultName {
20 | //return [[[PDKeychainBindingsController sharedKeychainBindingsController] valueBuffer] objectForKey:defaultName];
21 | return [[PDKeychainBindingsController sharedKeychainBindingsController] valueForKeyPath:[NSString stringWithFormat:@"values.%@",defaultName]];
22 | }
23 |
24 | - (void)setObject:(NSString *)value forKey:(NSString *)defaultName {
25 | [[PDKeychainBindingsController sharedKeychainBindingsController] setValue:value forKeyPath:[NSString stringWithFormat:@"values.%@",defaultName]];
26 | }
27 |
28 | - (void)setString:(NSString *)value forKey:(NSString *)defaultName {
29 | [[PDKeychainBindingsController sharedKeychainBindingsController] setValue:value forKeyPath:[NSString stringWithFormat:@"values.%@",defaultName]];
30 | }
31 |
32 | - (void)removeObjectForKey:(NSString *)defaultName {
33 | [[PDKeychainBindingsController sharedKeychainBindingsController] setValue:nil forKeyPath:[NSString stringWithFormat:@"values.%@",defaultName]];
34 | }
35 |
36 | - (NSString *)stringForKey:(NSString *)defaultName {
37 | return (NSString *) [self objectForKey:defaultName];
38 | }
39 |
40 | @end
41 |
--------------------------------------------------------------------------------
/InboxExamples/SimpleMail/SimpleMail/SMThreadTableViewCell.m:
--------------------------------------------------------------------------------
1 | //
2 | // SMThreadTableViewCell.m
3 | // SimpleMail
4 | //
5 | // Created by Ben Gotow on 7/8/14.
6 | // Copyright (c) 2014 Inbox. All rights reserved.
7 | //
8 |
9 | #import "SMThreadTableViewCell.h"
10 |
11 | static NSDateFormatter * threadDateFormatter;
12 |
13 | @implementation SMThreadTableViewCell
14 |
15 | - (void)setThread:(INThread *)thread
16 | {
17 | if (!threadDateFormatter) {
18 | threadDateFormatter = [[NSDateFormatter alloc] init];
19 | [threadDateFormatter setDateStyle: NSDateFormatterShortStyle];
20 | [threadDateFormatter setTimeStyle: NSDateFormatterShortStyle];
21 | }
22 |
23 | // display subject and snippet Gmail-style
24 | NSString * body = [NSString stringWithFormat:@"%@—%@", [thread subject], [thread snippet]];
25 | [[self bodyLabel] setText: body];
26 |
27 | // format dates nicely
28 | NSString * date = [threadDateFormatter stringFromDate: [thread lastMessageDate]];
29 | [[self dateLabel] setText: date];
30 |
31 | [[self unreadDot] setHidden: ![thread unread]];
32 |
33 | // collect the names of the participants, except for ourselves
34 | // to populate the top label of the cell
35 | INNamespace * namespace = [[[INAPIManager shared] namespaces] firstObject];
36 | NSMutableArray * names = [NSMutableArray array];
37 | for (NSDictionary * participant in [thread participants]) {
38 | if ([participant[@"email"] isEqualToString: [namespace emailAddress]])
39 | continue;
40 |
41 | if ([participant[@"name"] length])
42 | [names addObject: participant[@"name"]];
43 | else
44 | [names addObject: participant[@"email"]];
45 | }
46 |
47 | [[self fromLabel] setText: [names componentsJoinedByString:@", "]];
48 | }
49 |
50 | @end
51 |
--------------------------------------------------------------------------------
/InboxFramework/Inbox/Models/INMessageProvider.m:
--------------------------------------------------------------------------------
1 | //
2 | // INMessageProvider.m
3 | // BigSur
4 | //
5 | // Created by Ben Gotow on 4/30/14.
6 | // Copyright (c) 2014 Inbox. All rights reserved.
7 | //
8 |
9 | #import "INMessageProvider.h"
10 | #import "INModelProvider+Private.h"
11 | #import "INPredicateToQueryParamConverter.h"
12 | #import "INThread.h"
13 |
14 | @implementation INMessageProvider
15 |
16 | - (id)initForMessagesInThread:(NSString *)threadID andNamespaceID:(NSString*)namespaceID
17 | {
18 | NSPredicate * threadPredicate = [NSComparisonPredicate predicateWithFormat:@"threadID = %@", threadID];
19 | self = [super initWithClass:[INMessage class] andNamespaceID:namespaceID andUnderlyingPredicate:threadPredicate];
20 | if (self) {
21 | }
22 | return self;
23 | }
24 |
25 |
26 | - (id)initForDraftsInThread:(NSString *)threadID andNamespaceID:(NSString*)namespaceID
27 | {
28 | NSPredicate * threadPredicate = [NSComparisonPredicate predicateWithFormat:@"threadID = %@", threadID];
29 | self = [super initWithClass:[INDraft class] andNamespaceID:namespaceID andUnderlyingPredicate:threadPredicate];
30 | if (self) {
31 | }
32 | return self;
33 | }
34 |
35 |
36 | - (NSDictionary *)queryParamsForPredicate:(NSPredicate*)predicate
37 | {
38 | INPredicateToQueryParamConverter * converter = [[INPredicateToQueryParamConverter alloc] init];
39 | [converter setKeysToParamsTable: @{@"to": @"to", @"from": @"from", @"cc": @"cc", @"bcc": @"bcc", @"threadID": @"thread_id", @"label": @"label"}];
40 | [converter setKeysToLIKEParamsTable:@{@"subject":@"subject"}];
41 |
42 | NSMutableDictionary * params = [[converter paramsForPredicate: predicate] mutableCopy];
43 | [params addEntriesFromDictionary: [super queryParamsForPredicate: predicate]];
44 | return params;
45 | }
46 |
47 |
48 | @end
49 |
--------------------------------------------------------------------------------
/InboxKit.podspec:
--------------------------------------------------------------------------------
1 | #
2 | # Be sure to run `pod spec lint InboxSDK.podspec' to ensure this is a
3 | # valid spec and to remove all comments including this before submitting the spec.
4 | #
5 | # To learn more about Podspec attributes see http://docs.cocoapods.org/specification.html
6 | # To see working Podspecs in the CocoaPods repo see https://github.com/CocoaPods/Specs/
7 | #
8 |
9 | Pod::Spec.new do |s|
10 |
11 | s.name = "InboxKit"
12 | s.version = "0.0.6"
13 | s.summary = "The Inbox iOS framework provides a native interface to the Inbox API."
14 | s.description = "The Inbox iOS framework provides a native interface to the Inbox API, with additional features that make it easy to build full-fledged mail apps for iOS or add the email functionality you need to existing applications."
15 | s.homepage = "https://github.com/inboxapp/inbox-ios"
16 | s.license = { :type => "MIT", :file => "LICENSE.md" }
17 | s.platform = :ios, "7.0"
18 |
19 | s.author = { "Ben Gotow" => "ben@nylas.com" }
20 | s.social_media_url = "http://twitter.com/bengotow"
21 |
22 | s.prefix_header_file = "InboxFramework/Inbox/Inbox-Prefix.pch"
23 |
24 | s.source = { :git => "https://github.com/inboxapp/inbox-ios.git", :submodules => true, :tag => s.version }
25 | s.source_files = "InboxFramework/Inbox/*.{h,m}", "InboxFramework/Inbox/**/*.{h,m}", "InboxFramework/InboxUI/**/*.{h,m}", "InboxFramework/Submodules/PDKeychainBindingsController/PDKeychainBindingsController/*.{h,m}"
26 |
27 | s.dependency 'FMDB'
28 | s.dependency 'AFNetworking', '~> 2.0'
29 |
30 | s.public_header_files = "InboxFramework/Inbox/*.h", "InboxFramework/Inbox/**/*.h", "InboxFramework/InboxUI/**/*.h"
31 |
32 | s.libraries = "sqlite3"
33 | s.requires_arc = true
34 |
35 | end
36 |
--------------------------------------------------------------------------------
/InboxFramework/Inbox/Models/API Calls/INAPITask.h:
--------------------------------------------------------------------------------
1 | //
2 | // INAPICall.h
3 | // BigSur
4 | //
5 | // Created by Ben Gotow on 4/22/14.
6 | // Copyright (c) 2014 Inbox. All rights reserved.
7 | //
8 |
9 | #import
10 | #import "INModelObject.h"
11 |
12 | @class INMessage;
13 | @class AFHTTPRequestOperation;
14 |
15 | static NSString * INTaskProgressNotification = @"INTaskProgressNotification";
16 |
17 | typedef enum : NSUInteger {
18 | INAPITaskStateWaiting,
19 | INAPITaskStateInProgress,
20 | INAPITaskStateFinished,
21 | INAPITaskStateCancelled,
22 | INAPITaskStateServerUnreachable,
23 | INAPITaskStateServerRejected
24 | } INAPITaskState;
25 |
26 |
27 | typedef void (^ CallbackBlock)(INAPITask * change, BOOL finished);
28 |
29 | @interface INAPITask : NSObject
30 |
31 | @property (nonatomic, strong) NSString * ID;
32 | @property (nonatomic, strong) INModelObject * model;
33 | @property (nonatomic, strong) NSMutableDictionary * data;
34 | @property (nonatomic, assign) INAPITaskState state;
35 | @property (nonatomic, assign) float percentComplete;
36 |
37 | + (instancetype)operationForModel:(INModelObject *)model;
38 |
39 | - (id)initWithModel:(INModelObject*)model;
40 | - (id)initWithCoder:(NSCoder *)aDecoder;
41 | - (void)encodeWithCoder:(NSCoder *)aCoder;
42 |
43 | - (NSString*)extendedDescription;
44 |
45 | - (BOOL)canCancelPendingTask:(INAPITask*)other;
46 | - (BOOL)canStartAfterTask:(INAPITask*)other;
47 | - (NSArray*)dependenciesIn:(NSArray*)others;
48 |
49 | - (BOOL)inProgress;
50 | - (NSString*)error;
51 |
52 | - (void)applyLocally;
53 | - (void)applyRemotelyWithCallback:(CallbackBlock)callback;
54 | - (void)rollbackLocally;
55 |
56 | - (void)handleSuccess:(AFHTTPRequestOperation *)operation withResponse:(id)responseObject;
57 |
58 | @end
59 |
--------------------------------------------------------------------------------
/arclib/src/InboxUncrustifyLintEngine.php:
--------------------------------------------------------------------------------
1 | getPaths();
12 |
13 | $uncrustify_linter = new InboxUncrustifyLinter();
14 |
15 | // Remove any paths that don't exist before we add paths to linters. We want
16 | // to do this for linters that operate on file contents because the
17 | // generated list of paths will include deleted paths when a file is
18 | // removed.
19 | foreach ($paths as $key => $path) {
20 | if (!$this->pathExists($path)) {
21 | unset($paths[$key]);
22 | }
23 | }
24 |
25 | foreach ($paths as $path) {
26 | if (!preg_match('/^.*\.(m|h)$/i', $path)) {
27 | // This isn't a python file, so don't try to apply the PyLint linter
28 | // to it.
29 | continue;
30 | } else {
31 | echo $path;
32 | }
33 |
34 | // Add the path, to tell the linter it should examine the source code
35 | // to try to find problems.
36 | $uncrustify_linter->addPath($path);
37 | }
38 |
39 | // We only built one linter, but you can build more than one (e.g., a
40 | // Javascript linter for JS), and return a list of linters to execute. You
41 | // can also add a path to more than one linter (for example, if you want
42 | // to run a Python linter and a more general text linter on every .py file).
43 |
44 | return array(
45 | $uncrustify_linter
46 | );
47 | }
48 |
49 | }
--------------------------------------------------------------------------------
/InboxFramework/Inbox/Models/Concrete Classes/INNamespace.m:
--------------------------------------------------------------------------------
1 | //
2 | // INNamespace.m
3 | // BigSur
4 | //
5 | // Created by Ben Gotow on 4/28/14.
6 | // Copyright (c) 2014 Inbox. All rights reserved.
7 | //
8 |
9 | #import "INNamespace.h"
10 | #import "INTag.h"
11 | #import "INContact.h"
12 | #import "INThreadProvider.h"
13 | #import "INMessageProvider.h"
14 | #import "INThread.h"
15 |
16 | @implementation INNamespace
17 |
18 | + (NSMutableDictionary *)resourceMapping
19 | {
20 | NSMutableDictionary * mapping = [super resourceMapping];
21 | [mapping addEntriesFromDictionary:@{
22 | @"emailAddress": @"email_address",
23 | @"provider": @"provider",
24 | @"status": @"status",
25 | @"scope": @"scope",
26 | @"lastSync": @"last_sync",
27 | @"name": @"name"
28 | }];
29 | return mapping;
30 | }
31 |
32 | + (NSString *)resourceAPIName
33 | {
34 | return @"n";
35 | }
36 |
37 | - (NSString *)resourceAPIPath
38 | {
39 | return [NSString stringWithFormat:@"/n/%@", self.ID];
40 | }
41 |
42 | - (INModelProvider *)newContactProvider
43 | {
44 | return [[INModelProvider alloc] initWithClass:[INContact class] andNamespaceID:[self ID] andUnderlyingPredicate:nil];
45 | }
46 |
47 | - (INModelProvider *)newTagProvider
48 | {
49 | return [[INModelProvider alloc] initWithClass:[INTag class] andNamespaceID:[self ID] andUnderlyingPredicate:nil];
50 | }
51 |
52 | - (INThreadProvider *)newThreadProvider
53 | {
54 | return [[INThreadProvider alloc] initWithNamespaceID: [self ID]];
55 | }
56 |
57 | - (INMessageProvider *)newDraftsProvider
58 | {
59 | return [[INMessageProvider alloc] initWithClass:[INDraft class] andNamespaceID:[self ID] andUnderlyingPredicate:nil];
60 | }
61 |
62 | - (INMessageProvider *)newMessageProvider
63 | {
64 | return [[INMessageProvider alloc] initWithClass:[INMessage class] andNamespaceID:[self ID] andUnderlyingPredicate:nil];
65 | }
66 |
67 | @end
68 |
--------------------------------------------------------------------------------
/InboxExamples/Triage/Triage/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleDisplayName
8 | ${PRODUCT_NAME}
9 | CFBundleExecutable
10 | ${EXECUTABLE_NAME}
11 | CFBundleIdentifier
12 | Inbox.${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 | CFBundleURLTypes
24 |
25 |
26 | CFBundleTypeRole
27 | Editor
28 | CFBundleURLSchemes
29 |
30 | in-8ptbagaxzcpxre0h4k6fl3x6d
31 |
32 |
33 |
34 | CFBundleVersion
35 | 1.0
36 | INAPIPath
37 | https://api.nylas.com/
38 | INAppID
39 | 8ptbagaxzcpxre0h4k6fl3x6d
40 | LSRequiresIPhoneOS
41 |
42 | UIRequiredDeviceCapabilities
43 |
44 | armv7
45 |
46 | UISupportedInterfaceOrientations
47 |
48 | UIInterfaceOrientationPortrait
49 |
50 | UISupportedInterfaceOrientations~ipad
51 |
52 | UIInterfaceOrientationPortrait
53 | UIInterfaceOrientationPortraitUpsideDown
54 | UIInterfaceOrientationLandscapeLeft
55 | UIInterfaceOrientationLandscapeRight
56 |
57 |
58 |
59 |
--------------------------------------------------------------------------------
/InboxExamples/SimpleMail/SimpleMail/SimpleMail-Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleDisplayName
8 | ${PRODUCT_NAME}
9 | CFBundleExecutable
10 | ${EXECUTABLE_NAME}
11 | CFBundleIdentifier
12 | com.inbox.${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 | CFBundleURLTypes
24 |
25 |
26 | CFBundleTypeRole
27 | Editor
28 | CFBundleURLIconFile
29 |
30 | CFBundleURLName
31 | in-6fqe68ue317qr4qvddcwjfncd
32 | CFBundleURLSchemes
33 |
34 | in-6fqe68ue317qr4qvddcwjfncd
35 |
36 |
37 |
38 | CFBundleVersion
39 | 1.0
40 | INAPIPath
41 | https://api.nylas.com/
42 | INAppID
43 | 6fqe68ue317qr4qvddcwjfncd
44 | LSRequiresIPhoneOS
45 |
46 | UIMainStoryboardFile
47 | Main
48 | UIRequiredDeviceCapabilities
49 |
50 | armv7
51 |
52 | UISupportedInterfaceOrientations
53 |
54 | UIInterfaceOrientationPortrait
55 | UIInterfaceOrientationLandscapeLeft
56 | UIInterfaceOrientationLandscapeRight
57 |
58 |
59 |
60 |
--------------------------------------------------------------------------------
/InboxFramework/Inbox/Helpers/INPredicateToQueryParamConverter.m:
--------------------------------------------------------------------------------
1 | //
2 | // INPredicateToQueryParamConverter.m
3 | // BigSur
4 | //
5 | // Created by Ben Gotow on 5/2/14.
6 | // Copyright (c) 2014 Inbox. All rights reserved.
7 | //
8 |
9 | #import "INPredicateToQueryParamConverter.h"
10 |
11 | @implementation INPredicateToQueryParamConverter
12 |
13 | - (NSDictionary*)paramsForPredicate:(NSPredicate*)predicate
14 | {
15 | NSMutableDictionary * params = [NSMutableDictionary dictionary];
16 |
17 | if ([predicate isKindOfClass: [NSCompoundPredicate class]]) {
18 | if ([(NSCompoundPredicate*)predicate compoundPredicateType] != NSAndPredicateType)
19 | NSAssert(false, @"Only AND predicates are currently supported in constructing queries.");
20 |
21 | for (NSPredicate * subpredicate in [(NSCompoundPredicate*)predicate subpredicates])
22 | [params addEntriesFromDictionary: [self paramsForPredicate: subpredicate]];
23 |
24 | } else if ([predicate isKindOfClass: [NSComparisonPredicate class]]) {
25 | NSComparisonPredicate * pred = (NSComparisonPredicate*)predicate;
26 | if ([[pred rightExpression] expressionType] != NSConstantValueExpressionType)
27 | NSAssert(false, @"Only constant values can be on the RHS of predicates.");
28 | if ([[pred leftExpression] expressionType] != NSKeyPathExpressionType)
29 | NSAssert(false, @"Only property names can be on the LHS of predicates.");
30 |
31 |
32 | NSString * keyPath = [[pred leftExpression] keyPath];
33 | NSString * rhs = [[pred rightExpression] constantValue];
34 |
35 | if (_keysToParamsTable[keyPath]) {
36 | NSAssert([pred predicateOperatorType] == NSEqualToPredicateOperatorType, @"Sorry, predicates for %@ can only use the '=' operator.", keyPath);
37 | NSString * param = _keysToParamsTable[keyPath];
38 | [params setObject:rhs forKey:param];
39 | }
40 |
41 | if (_keysToLIKEParamsTable[keyPath]) {
42 | NSString * param = _keysToLIKEParamsTable[keyPath];
43 | [params setObject:rhs forKey:param];
44 | }
45 | }
46 |
47 | return params;
48 | }
49 | @end
50 |
--------------------------------------------------------------------------------
/InboxFramework/Inbox/Models/INThreadProvider.m:
--------------------------------------------------------------------------------
1 | //
2 | // INThreadProvider.m
3 | // BigSur
4 | //
5 | // Created by Ben Gotow on 4/28/14.
6 | // Copyright (c) 2014 Inbox. All rights reserved.
7 | //
8 |
9 | #import "INThreadProvider.h"
10 | #import "INModelProvider+Private.h"
11 | #import "INAPIManager.h"
12 | #import "INThread.h"
13 | #import "INTag.h"
14 | #import "INModelResponseSerializer.h"
15 | #import "INPredicateToQueryParamConverter.h"
16 |
17 | @implementation INThreadProvider
18 |
19 | - (id)initWithNamespaceID:(NSString *)namespaceID
20 | {
21 | self = [super initWithClass:[INThread class] andNamespaceID:namespaceID andUnderlyingPredicate:nil];
22 | if (self) {
23 | }
24 | return self;
25 | }
26 |
27 | - (NSDictionary *)queryParamsForPredicate:(NSPredicate*)predicate
28 | {
29 | INPredicateToQueryParamConverter * converter = [[INPredicateToQueryParamConverter alloc] init];
30 | [converter setKeysToParamsTable: @{@"to": @"to", @"from": @"from", @"cc": @"cc", @"bcc": @"bcc", @"tagIDs":@"tag"}];
31 | [converter setKeysToLIKEParamsTable: @{@"subject": @"subject"}];
32 |
33 | NSMutableDictionary * params = [[converter paramsForPredicate: predicate] mutableCopy];
34 | [params addEntriesFromDictionary: [super queryParamsForPredicate: predicate]];
35 |
36 | NSSortDescriptor * descriptor = [[self itemSortDescriptors] firstObject];
37 | if (descriptor) {
38 | if (![[descriptor key] isEqualToString: @"lastMessageDate"])
39 | NSAssert(false, @"Sorry, the backend only supports ordering threads by `lastMessageDate`, so this provider cannot load threads.");
40 | }
41 |
42 | return params;
43 | }
44 |
45 | - (void)refresh
46 | {
47 | [super refresh];
48 | }
49 |
50 | - (void)countUnreadItemsWithCallback:(LongBlock)callback
51 | {
52 | NSPredicate * unreadPredicate = [NSComparisonPredicate predicateWithFormat:@"ANY tagIDs = %@", INTagIDUnread];
53 | NSPredicate * predicate = [[NSCompoundPredicate alloc] initWithType:NSAndPredicateType subpredicates:@[[self fetchPredicate], unreadPredicate]];
54 | [[INDatabaseManager shared] countModelsOfClass:[INThread class] matching:predicate withCallback:^(long count) {
55 | callback(count);
56 | }];
57 | }
58 |
59 | @end
60 |
--------------------------------------------------------------------------------
/InboxFramework/Inbox/Models/Concrete Classes/INTag.m:
--------------------------------------------------------------------------------
1 | //
2 | // INLabel.m
3 | // BigSur
4 | //
5 | // Created by Ben Gotow on 4/30/14.
6 | // Copyright (c) 2014 Inbox. All rights reserved.
7 | //
8 |
9 | #import "INTag.h"
10 | #import "INNamespace.h"
11 | #import "INSaveTagTask.h"
12 |
13 | @implementation INTag
14 |
15 | + (instancetype)tagWithID:(NSString*)ID
16 | {
17 | return [self instanceWithID: ID inNamespaceID: nil];
18 | }
19 |
20 | + (NSMutableDictionary *)resourceMapping
21 | {
22 | NSMutableDictionary * mapping = [super resourceMapping];
23 | [mapping addEntriesFromDictionary:@{
24 | @"providedName": @"name"
25 | }];
26 | return mapping;
27 | }
28 |
29 | + (NSString *)resourceAPIName
30 | {
31 | return @"tags";
32 | }
33 |
34 | - (id)initInNamespace:(INNamespace*)namespace
35 | {
36 | NSAssert(namespace, @"initInNamespace: called with a nil namespace.");
37 | self = [super init];
38 | if (self) {
39 | [self setNamespaceID: [namespace ID]];
40 | }
41 | return self;
42 | }
43 |
44 | - (NSString*)name
45 | {
46 | // pretend we have localization
47 | NSDictionary * localized = @{INTagIDArchive: @"Archive", INTagIDInbox: @"Inbox", INTagIDTrash: @"Trash", INTagIDUnread: @"Unread", INTagIDSent: @"Sent", INTagIDStarred: @"Starred"};
48 | if ([localized objectForKey: self.ID])
49 | return [localized objectForKey: self.ID];
50 | if (self.providedName)
51 | return self.providedName;
52 | return [self.ID capitalizedString];
53 | }
54 |
55 | - (void)setName:(NSString*)name
56 | {
57 | // in the future, check the readonly flag here
58 | _providedName = name;
59 | }
60 |
61 | - (UIColor*)color
62 | {
63 | NSInteger count = 0;
64 | for (int ii = 0; ii < [[self name] length]; ii ++)
65 | count += [[self name] characterAtIndex:ii];
66 |
67 | return [UIColor colorWithHue:(count % 1000) / 1000.0 saturation:0.8 brightness:0.6 alpha:1];
68 | }
69 |
70 | - (void)save
71 | {
72 | INSaveTagTask * save = [INSaveTagTask operationForModel: self];
73 | [[INAPIManager shared] queueTask: save];
74 | }
75 |
76 | + (NSArray *)databaseIndexProperties
77 | {
78 | return [[super databaseIndexProperties] arrayByAddingObjectsFromArray: @[@"providedName"]];
79 | }
80 |
81 | @end
82 |
--------------------------------------------------------------------------------
/InboxFramework/Inbox/Models/Concrete Classes/INTag.h:
--------------------------------------------------------------------------------
1 | //
2 | // INLabel.h
3 | // BigSur
4 | //
5 | // Created by Ben Gotow on 4/30/14.
6 | // Copyright (c) 2014 Inbox. All rights reserved.
7 | //
8 |
9 | #import "INModelObject.h"
10 |
11 | static NSString * INTagIDUnread = @"unread";
12 | static NSString * INTagIDUnseen = @"unseen";
13 | static NSString * INTagIDArchive = @"archive";
14 | static NSString * INTagIDTrash = @"trash";
15 | static NSString * INTagIDDraft = @"drafts";
16 | static NSString * INTagIDInbox = @"inbox";
17 | static NSString * INTagIDStarred = @"starred";
18 | static NSString * INTagIDSent = @"sent";
19 |
20 | /** A simple wrapper around an Inbox tag. See the Inbox Tags documentation for
21 | more information about tags: http://inboxapp.com/docs/api#tags
22 | */
23 | @interface INTag : INModelObject
24 |
25 | @property (nonatomic, strong) NSString * providedName;
26 |
27 | /**
28 | @param ID A tag ID. May be a user-generated ID, or one of the built-in Inbox tag IDs:
29 | INTagIDUnread, INTagIDSent, etc.
30 |
31 | @return An INTag model with the given ID.
32 | */
33 | + (instancetype)tagWithID:(NSString*)ID;
34 |
35 | /**
36 | Initialize a new INTag model in the given namespace. This should only be used for creating
37 | new tags, not for retrieving existing tags.
38 |
39 | @param namespace The namespace to create the tag in.
40 | @return An INTag model
41 | */
42 | - (id)initInNamespace:(INNamespace*)namespace;
43 |
44 | /**
45 | @return The display-ready name of the tag, localized when possible to reflect the
46 | user's locale.
47 | */
48 | - (NSString*)name;
49 |
50 | /**
51 | Set the name of the tag. After setting the tag name, you should call -save to commit changes.
52 | Also note that provider tags (gmail-) cannot be renamed.
53 | @param name The new tag name
54 | */
55 | - (void)setName:(NSString*)name;
56 |
57 |
58 | /**
59 | @return The color of the tag. When possible, applications should use a tag's color
60 | in their UI to give users a tag presentation that is consistent and easy to scan.
61 | */
62 | - (UIColor*)color;
63 |
64 | /**
65 | Save the tag back to the Inbox API. Note that provider tags (gmail-) are not modifiable,
66 | and in general you can only modify the names of tags.
67 | */
68 | - (void)save;
69 |
70 | @end
71 |
--------------------------------------------------------------------------------
/InboxExamples/Snapmail/Snapmail/Snapmail-Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleDisplayName
8 | ${PRODUCT_NAME}
9 | CFBundleExecutable
10 | ${EXECUTABLE_NAME}
11 | CFBundleIdentifier
12 | com.inbox.${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 | CFBundleURLTypes
24 |
25 |
26 | CFBundleTypeRole
27 | Editor
28 | CFBundleURLName
29 | Inbox
30 | CFBundleURLSchemes
31 |
32 | in-c3ozq7z6yx0yigb6kv132o2cr
33 |
34 |
35 |
36 | CFBundleVersion
37 | 1.0
38 | INAPIPath
39 | https://api.nylas.com/
40 | INAppID
41 | c3ozq7z6yx0yigb6kv132o2cr
42 | LSRequiresIPhoneOS
43 |
44 | UIRequiredDeviceCapabilities
45 |
46 | armv7
47 |
48 | UIStatusBarStyle
49 | UIStatusBarStyleBlackTranslucent
50 | UISupportedInterfaceOrientations
51 |
52 | UIInterfaceOrientationPortrait
53 | UIInterfaceOrientationLandscapeLeft
54 | UIInterfaceOrientationLandscapeRight
55 |
56 | UISupportedInterfaceOrientations~ipad
57 |
58 | UIInterfaceOrientationPortrait
59 | UIInterfaceOrientationPortraitUpsideDown
60 | UIInterfaceOrientationLandscapeLeft
61 | UIInterfaceOrientationLandscapeRight
62 |
63 | UIViewControllerBasedStatusBarAppearance
64 |
65 |
66 |
67 |
--------------------------------------------------------------------------------
/InboxFramework/Inbox/Models/INModelObject+Uniquing.h:
--------------------------------------------------------------------------------
1 | //
2 | // INModelObject+Uniquing.h
3 | // BigSur
4 | //
5 | // Created by Ben Gotow on 4/28/14.
6 | // Copyright (c) 2014 Inbox. All rights reserved.
7 | //
8 |
9 | #import "INModelObject.h"
10 |
11 | @interface INModelObject (Uniquing)
12 |
13 | /** @name Globally Unique Instances */
14 |
15 | /**
16 | Returns the model object with the given ID currently in memory, if one exists.
17 | If one does not exist and the 'shouldCreate' option is provided, it is created
18 | and attached to the instance table. If you intend to create the model, you should
19 | allow this method to do it while locking the instance lookup table to prevent
20 | threading issues that could result in two copies of the model in memory.
21 |
22 | The primary purpose of this method is to retrieve an instance of an object so
23 | you can avoid allocating a new one, and avoid scenarios where multiple copies of
24 | a single logical object are floating around, which may be out of sync with each
25 | other and the local datastore.
26 |
27 | @param ID The ID of the object you're looking for.
28 |
29 | @param shouldCreate YES if you intend to create this model. You should always let
30 | ths method create the object for you and lock while it attaches it to the instance table.
31 |
32 | @param didCreate A BOOL, passed by reference, indicating whether the model returned
33 | was just created.
34 |
35 | @return An instance, or nil.
36 | */
37 | + (id)attachedInstanceMatchingID:(id)ID createIfNecessary:(BOOL)shouldCreate didCreate:(BOOL*)didCreate;
38 |
39 | /**
40 | Locks the instance table and attaches the provided model. This method throws an
41 | exception if another model of the same class is already in the instance table
42 | with the same ID.
43 | @param obj The object to attach as the official copy of this model.
44 | */
45 | + (void)attachInstance:(INModelObject *)obj;
46 |
47 | /**
48 | @return A copy of the INModelObject that is not attached to the instance table.
49 | This is useful if you want to clone an object to modify it and keep two versions alive.
50 | */
51 | - (id)detatchedCopy;
52 |
53 | /**
54 | @return YES, if this object has not been attached to the instance tree and is not the
55 | official version of the object.
56 | */
57 | - (BOOL)isDetatched;
58 |
59 | @end
60 |
--------------------------------------------------------------------------------
/InboxExamples/SwiftEightBall/SwiftEightBall/AppDelegate.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.swift
3 | // SwiftMail
4 | //
5 | // Created by Ben Gotow on 7/28/14.
6 | // Copyright (c) 2014 Inbox. All rights reserved.
7 | //
8 |
9 | import UIKit
10 | import Inbox
11 |
12 | @UIApplicationMain
13 | class AppDelegate: UIResponder, UIApplicationDelegate {
14 |
15 | var window: UIWindow?
16 |
17 |
18 | func application(application: UIApplication!, didFinishLaunchingWithOptions launchOptions: NSDictionary!) -> Bool {
19 | // Override point for customization after application launch.
20 | return true
21 | }
22 |
23 | func applicationWillResignActive(application: UIApplication!) {
24 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
25 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
26 | }
27 |
28 | func applicationDidEnterBackground(application: UIApplication!) {
29 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
30 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
31 | }
32 |
33 | func applicationWillEnterForeground(application: UIApplication!) {
34 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
35 | }
36 |
37 | func applicationDidBecomeActive(application: UIApplication!) {
38 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
39 | }
40 |
41 | func applicationWillTerminate(application: UIApplication!) {
42 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
43 | }
44 |
45 |
46 | }
47 |
48 |
--------------------------------------------------------------------------------
/InboxExamples/Snapmail/Snapmail/INContactsViewController.xib:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
--------------------------------------------------------------------------------
/InboxFramework/Inbox/Models/Concrete Classes/INMessage.h:
--------------------------------------------------------------------------------
1 | //
2 | // INMessage.h
3 | // BigSur
4 | //
5 | // Created by Ben Gotow on 4/30/14.
6 | // Copyright (c) 2014 Inbox. All rights reserved.
7 | //
8 |
9 | #import "INModelObject.h"
10 |
11 | @class INThread;
12 | @class INNamespace;
13 | @class INFile;
14 |
15 | /** The INMessage class provides access to message attributes and convenience
16 | methods for accessing attachments, marking as read, etc.
17 |
18 | You should not create INMessage objects directly. You can fetch messages by
19 | asking an INNamespace for a newMessageProvider and configuring that provider to
20 | return the result set you want (for example, all unread messages.)
21 |
22 | To compose or send a new message, create an instance of INDraft and call it's
23 | -save and -send methods, respectively.
24 |
25 | The Inbox platform is similar to Gmail in that many actions are taken on threads,
26 | not on messages. If you're looking to archive, label, or delete a message, see
27 | the documentation for INThread.
28 | */
29 | @interface INMessage : INModelObject
30 |
31 | @property (nonatomic, strong) NSString * body;
32 | @property (nonatomic, strong) NSString * snippet;
33 | @property (nonatomic, strong) NSDate * date;
34 | @property (nonatomic, strong) NSString * subject;
35 | @property (nonatomic, strong) NSString * threadID;
36 | @property (nonatomic, strong) NSArray * files;
37 | @property (nonatomic, strong) NSArray * from;
38 | @property (nonatomic, strong) NSArray * to;
39 | @property (nonatomic, strong) NSArray * cc;
40 | @property (nonatomic, strong) NSArray * bcc;
41 | @property (nonatomic, assign) BOOL unread;
42 |
43 | /*
44 | @return The parent thread of this message. Depending on how this message instance was
45 | loaded, the thread may or may not be available in the cache. After calling this method,
46 | you should check if the thread's data is loaded by calling -isDataAvailable, and call
47 | -reload: if necessary to fully populate the thread.
48 | */
49 | - (INThread*)thread;
50 |
51 | /*
52 | @return An array of INFile objects representing files on this message.
53 | INFile objects can be queried for previews, download links, etc.
54 | */
55 | - (NSArray*)files;
56 |
57 | /*
58 | Mark the individual message as read. This change takes effect immediately in the local cache
59 | but may not sync back to the server immediately.
60 | */
61 | - (void)markAsRead;
62 |
63 | @end
64 |
--------------------------------------------------------------------------------
/InboxExamples/SimpleMail/SimpleMail/SMAppDelegate.m:
--------------------------------------------------------------------------------
1 | //
2 | // SMAppDelegate.m
3 | // SimpleMail
4 | //
5 | // Created by Ben Gotow on 7/8/14.
6 | // Copyright (c) 2014 Inbox. All rights reserved.
7 | //
8 |
9 | #import "SMAppDelegate.h"
10 |
11 | @implementation SMAppDelegate
12 |
13 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
14 | {
15 | // Override point for customization after application launch.
16 | return YES;
17 | }
18 |
19 | - (void)applicationWillResignActive:(UIApplication *)application
20 | {
21 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
22 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
23 | }
24 |
25 | - (void)applicationDidEnterBackground:(UIApplication *)application
26 | {
27 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
28 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
29 | }
30 |
31 | - (void)applicationWillEnterForeground:(UIApplication *)application
32 | {
33 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
34 | }
35 |
36 | - (void)applicationDidBecomeActive:(UIApplication *)application
37 | {
38 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
39 | }
40 |
41 | - (void)applicationWillTerminate:(UIApplication *)application
42 | {
43 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
44 | }
45 |
46 | - (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation
47 | {
48 | return [[INAPIManager shared] handleURL: url];
49 | }
50 |
51 | @end
52 |
--------------------------------------------------------------------------------
/arclib/src/InboxUncrustifyLinter.php:
--------------------------------------------------------------------------------
1 | getConfiguredScript();
7 | $root = $this->getEngine()->getWorkingCopy()->getProjectRoot();
8 |
9 | $futures = array();
10 | foreach ($paths as $path) {
11 | $future = new ExecFuture('%C %s', $script, $path);
12 | $future->setCWD($root);
13 | $futures[$path] = $future;
14 | }
15 |
16 | foreach (Futures($futures)->limit(4) as $path => $future) {
17 | list($stdout) = $future->resolvex();
18 | $this->output[$path] = $stdout;
19 | }
20 | }
21 |
22 | public function getLinterName() {
23 | return "Inbox Uncrustify Linter";
24 | }
25 |
26 | public function lintPath($path) {
27 | // Not necessary to do anything because uncrustify writes directly stderr when there's a problem
28 |
29 | // $dict = array(
30 | // 'path' => idx($match, 'file', $path),
31 | // 'line' => $line,
32 | // 'char' => $char,
33 | // 'code' => idx($match, 'code', $this->getLinterName()),
34 | // 'severity' => $this->getMatchSeverity($match),
35 | // 'name' => idx($match, 'name', 'Lint'),
36 | // 'description' => idx($match, 'message', 'Undefined Lint Message'),
37 | // );
38 | //
39 | // $original = idx($match, 'original');
40 | // if ($original !== null) {
41 | // $dict['original'] = $original;
42 | // }
43 | //
44 | // $replacement = idx($match, 'replacement');
45 | // if ($replacement !== null) {
46 | // $dict['replacement'] = $replacement;
47 | // }
48 | //
49 | // $lint = ArcanistLintMessage::newFromDictionary($dict);
50 | // $this->addLintMessage($lint);
51 | }
52 |
53 | private function getConfiguredScript() {
54 | $key = 'lint.uncrustify.script';
55 | $config = $this->getEngine()
56 | ->getConfigurationManager()
57 | ->getConfigFromAnySource($key);
58 |
59 | if (!$config) {
60 | throw new ArcanistUsageException(
61 | "InboxUncrustifyLinter: ".
62 | "You must configure '{$key}' to point to an uncrustify script to execute.");
63 | }
64 |
65 | // NOTE: No additional validation since the "script" can be some random
66 | // shell command and/or include flags, so it does not need to point to some
67 | // file on disk.
68 |
69 | return $config;
70 | }
71 | }
72 |
73 | ?>
--------------------------------------------------------------------------------
/InboxExamples/Snapmail/Snapmail/INSnapViewController.m:
--------------------------------------------------------------------------------
1 | //
2 | // INSnapViewController.m
3 | // Snapmail
4 | //
5 | // Created by Ben Gotow on 6/16/14.
6 | // Copyright (c) 2014 InboxApp, Inc. All rights reserved.
7 | //
8 |
9 | #import "INSnapViewController.h"
10 | #import "INHomeViewController.h"
11 |
12 | @implementation INSnapViewController
13 |
14 | - (id)initWithThread:(INThread*)thread
15 | {
16 | self = [super init];
17 | if (self) {
18 | _provider = [thread newMessageProvider];
19 | _provider.delegate = self;
20 | [_provider refresh];
21 | }
22 | return self;
23 | }
24 |
25 | - (void)viewDidLoad
26 | {
27 | [super viewDidLoad];
28 | [_errorLabel setText: @""];
29 | [_spinner startAnimating];
30 | }
31 |
32 | - (void)viewWillDisappear:(BOOL)animated
33 | {
34 | [_timer invalidate];
35 | _timer = nil;
36 | }
37 |
38 | - (void)displaySnapImage
39 | {
40 | // TODO iterate over snaps and find the oldest unread one...
41 | INMessage * message = nil;
42 | for (INMessage * msg in [_provider items]) {
43 | if ([[msg attachmentIDs] count] > 0)
44 | message = msg;
45 | }
46 |
47 | if (message == nil)
48 | return;
49 |
50 | INFile * file = [[message attachments] firstObject];
51 | if (file == nil)
52 | [(INHomeViewController*)self.parentViewController dismissSnapViewController];
53 |
54 | [file getDataWithCallback:^(NSError *error, NSData *data) {
55 | [_spinner stopAnimating];
56 | if (error) {
57 | [_errorLabel setText: [error localizedDescription]];
58 | return;
59 | }
60 |
61 | [message markAsRead];
62 |
63 | UIImage * img = [UIImage imageWithData: data];
64 | [_imageView setImage: img];
65 | [_timeLabel setText: @"5"];
66 |
67 | [_timer invalidate];
68 | _timer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(countdown) userInfo:nil repeats:YES];
69 | }];
70 | }
71 |
72 | - (void)countdown
73 | {
74 | int timeRemaining = [[_timeLabel text] intValue];
75 | timeRemaining -= 1;
76 |
77 | if (timeRemaining == 0) {
78 | [_imageView setImage: nil];
79 | [self displaySnapImage];
80 | } else {
81 | [_timeLabel setText: [NSString stringWithFormat:@"%d", timeRemaining]];
82 | }
83 | }
84 |
85 | - (void)providerDataChanged:(INModelProvider *)provider
86 | {
87 | [self displaySnapImage];
88 | }
89 |
90 | - (void)provider:(INModelProvider *)provider dataFetchFailed:(NSError *)error
91 | {
92 | [_errorLabel setText: [error localizedDescription]];
93 | }
94 |
95 | @end
96 |
--------------------------------------------------------------------------------
/InboxFramework/Inbox/Models/API Calls/INSendDraftTask.m:
--------------------------------------------------------------------------------
1 | //
2 | // INSendDraftChange.m
3 | // InboxFramework
4 | //
5 | // Created by Ben Gotow on 5/20/14.
6 | // Copyright (c) 2014 Inbox. All rights reserved.
7 | //
8 |
9 | #import "INSendDraftTask.h"
10 | #import "INDatabaseManager.h"
11 | #import "INDeleteDraftTask.h"
12 | #import "INSaveDraftTask.h"
13 | #import "INDraft.h"
14 | #import "INTag.h"
15 |
16 | @implementation INSendDraftTask
17 |
18 | - (BOOL)canStartAfterTask:(INAPITask *)other
19 | {
20 | if ([[other model] isEqual: self.model] && [other isKindOfClass: [INDeleteDraftTask class]])
21 | return NO;
22 | return YES;
23 | }
24 |
25 | - (BOOL)canCancelPendingTask:(INAPITask*)other
26 | {
27 | if ([[other model] isEqual: self.model] && [other isKindOfClass: [INSendDraftTask class]])
28 | return YES;
29 | if ([[other model] isEqual: self.model] && [other isKindOfClass: [INDeleteDraftTask class]])
30 | return YES;
31 | return NO;
32 | }
33 |
34 | - (NSURLRequest *)buildAPIRequest
35 | {
36 | INDraft * draft = (INDraft*)self.model;
37 |
38 | NSAssert(self.model, @"INSendDraftChange asked to buildRequest with no model!");
39 | NSAssert([self.model namespaceID], @"INSendDraftChange asked to buildRequest with no namespace!");
40 | NSAssert([self.model namespaceID], @"The Inbox API now requires drafts with versions. Refresh this INDraft object to get one with a version.");
41 |
42 | NSError * error = nil;
43 | NSString * sendPath = [NSString stringWithFormat:@"/n/%@/send", [draft namespaceID]];
44 | NSString * url = [[NSURL URLWithString:sendPath relativeToURL:[INAPIManager shared].AF.baseURL] absoluteString];
45 |
46 | return [[[[INAPIManager shared] AF] requestSerializer] requestWithMethod:@"POST" URLString:url parameters:@{@"draft_id": [draft ID], @"version": [draft version]} error:&error];
47 | }
48 |
49 | - (NSArray*)dependenciesIn:(NSArray*)others
50 | {
51 | NSMutableArray * dependencies = [NSMutableArray array];
52 | for (INAPITask * other in others) {
53 | if (other == self)
54 | continue;
55 |
56 | if ([other isKindOfClass: [INSaveDraftTask class]] && [[other model] isEqual: [self model]])
57 | [dependencies addObject: other];
58 | }
59 | return dependencies;
60 | }
61 |
62 | - (void)handleSuccess:(AFHTTPRequestOperation *)operation withResponse:(id)responseObject
63 | {
64 | [super handleSuccess: operation withResponse: responseObject];
65 | [[INDatabaseManager shared] unpersistModel: [self model] willResaveSameModel: NO];
66 | }
67 |
68 |
69 | @end
70 |
--------------------------------------------------------------------------------
/InboxFramework/Inbox/Models/API Calls/INSaveTagTask.m:
--------------------------------------------------------------------------------
1 | //
2 | // INSaveTagTask.m
3 | // InboxFramework
4 | //
5 | // Created by Ben Gotow on 9/17/14.
6 | // Copyright (c) 2014 Inbox. All rights reserved.
7 | //
8 |
9 | #import "INSaveTagTask.h"
10 | #import "INTag.h"
11 | #import "INDatabaseManager.h"
12 |
13 | @implementation INSaveTagTask
14 |
15 | - (BOOL)canStartAfterTask:(INAPITask *)other
16 | {
17 | return YES;
18 | }
19 |
20 | - (BOOL)canCancelPendingTask:(INAPITask*)other
21 | {
22 | if ([[other model] isEqual: self.model] && [other isKindOfClass: [INSaveTagTask class]])
23 | return YES;
24 | return NO;
25 | }
26 |
27 | - (NSURLRequest *)buildAPIRequest
28 | {
29 | NSAssert(self.model, @"INSaveTagTask asked to buildRequest with no model!");
30 | NSAssert([self.model namespaceID], @"INSaveTagTask asked to buildRequest with no namespace!");
31 |
32 | NSError * error = nil;
33 | NSString * path = nil;
34 |
35 | if ([self.model isUnsynced])
36 | path = [NSString stringWithFormat:@"/n/%@/tags", [self.model namespaceID]];
37 | else
38 | path = [NSString stringWithFormat:@"/n/%@/tags/%@", [self.model namespaceID], [self.model ID]];
39 |
40 | NSString * url = [[NSURL URLWithString:path relativeToURL:[INAPIManager shared].AF.baseURL] absoluteString];
41 | NSMutableDictionary * params = [[self.model resourceDictionary] mutableCopy];
42 | [params removeObjectForKey: @"id"];
43 | [params removeObjectForKey: @"namespace_id"];
44 |
45 | return [[[[INAPIManager shared] AF] requestSerializer] requestWithMethod:@"POST" URLString:url parameters:params error:&error];
46 | }
47 |
48 | - (void)handleSuccess:(AFHTTPRequestOperation *)operation withResponse:(id)responseObject
49 | {
50 | if (![responseObject isKindOfClass: [NSDictionary class]])
51 | return NSLog(@"SaveTag weird response: %@", responseObject);
52 |
53 | INTag * tag = (INTag *)[self model];
54 |
55 | // remove the tag from the local cache and then update it with the API response
56 | // and save it again. This is important, because the JSON that comes back from an
57 | // initial save gives the tag an ID and we want to replace the old tag.
58 | [[INDatabaseManager shared] unpersistModel: tag willResaveSameModel:YES];
59 | [tag updateWithResourceDictionary: responseObject];
60 | [[INDatabaseManager shared] persistModel: tag];
61 | }
62 |
63 | - (void)applyLocally
64 | {
65 | [[INDatabaseManager shared] persistModel: [self model]];
66 | }
67 |
68 | - (void)rollbackLocally
69 | {
70 | }
71 |
72 | @end
73 |
--------------------------------------------------------------------------------
/InboxFramework/Inbox/Models/INModelObject+Uniquing.m:
--------------------------------------------------------------------------------
1 | //
2 | // INModelObject+Uniquing.m
3 | // BigSur
4 | //
5 | // Created by Ben Gotow on 4/28/14.
6 | // Copyright (c) 2014 Inbox. All rights reserved.
7 | //
8 |
9 | #import "INModelObject+Uniquing.h"
10 | #import "INDatabaseManager.h"
11 |
12 | static NSMapTable * modelInstanceTable;
13 |
14 | @implementation INModelObject (Uniquing)
15 |
16 | + (id)attachedInstanceMatchingID:(id)ID createIfNecessary:(BOOL)shouldCreate didCreate:(BOOL*)didCreate
17 | {
18 | if (!modelInstanceTable)
19 | modelInstanceTable = [[NSMapTable alloc] initWithKeyOptions:NSPointerFunctionsStrongMemory valueOptions:NSPointerFunctionsWeakMemory capacity:1000];
20 |
21 | id obj = nil;
22 | @synchronized(modelInstanceTable) {
23 | obj = [modelInstanceTable objectForKey:[INModelObject attachmentKeyForClass:self ID:ID]];
24 | if (shouldCreate && !obj) {
25 | obj = [[self alloc] init];
26 | [obj setID: ID];
27 | [modelInstanceTable setObject:obj forKey:[INModelObject attachmentKeyForClass:[obj class] ID:[obj ID]]];
28 | if (didCreate) *didCreate = YES;
29 | }
30 | }
31 | return obj;
32 | }
33 |
34 | + (void)attachInstance:(INModelObject *)obj
35 | {
36 | NSAssert(obj, @"-attachInstance called with a null object.");
37 | NSAssert([obj isKindOfClass:[INModelObject class]], @"Only subclasses of INModelObject can be attached.");
38 |
39 | @synchronized(modelInstanceTable) {
40 | id existing = [INModelObject attachedInstanceMatchingID:[obj ID] createIfNecessary: NO didCreate: NULL];
41 | if (!existing)
42 | [modelInstanceTable setObject:obj forKey:[INModelObject attachmentKeyForClass:[obj class] ID:[obj ID]]];
43 | else if (existing != obj)
44 | NSAssert(false, @"Attaching an instance when another instance is already in memory for this class+ID combination. Where did this object come from?");
45 | }
46 | }
47 |
48 | + (NSString *)attachmentKeyForClass:(Class)klass ID:(id)ID
49 | {
50 | if ([ID isKindOfClass:[NSNumber class]])
51 | ID = [ID stringValue];
52 |
53 | char cString[255];
54 | sprintf(cString, "%p-%s", (__bridge void *)klass, [ID cStringUsingEncoding:NSUTF8StringEncoding]);
55 | return [NSString stringWithCString:cString encoding:NSUTF8StringEncoding];
56 | }
57 |
58 | - (id)detatchedCopy
59 | {
60 | Class klass = [self class];
61 | id copy = [[klass alloc] init];
62 |
63 | [copy updateWithResourceDictionary:[self resourceDictionary]];
64 | return copy;
65 | }
66 |
67 | - (BOOL)isDetatched
68 | {
69 | return [INModelObject attachedInstanceMatchingID:[self ID] createIfNecessary: NO didCreate: NULL] != self;
70 | }
71 |
72 | @end
73 |
--------------------------------------------------------------------------------
/InboxFramework/Inbox/Models/API Calls/INUploadFileTask.m:
--------------------------------------------------------------------------------
1 | //
2 | // INUploadFileTask.m
3 | // InboxFramework
4 | //
5 | // Created by Ben Gotow on 5/21/14.
6 | // Copyright (c) 2014 Inbox. All rights reserved.
7 | //
8 |
9 | #import "INUploadFileTask.h"
10 | #import "INDatabaseManager.h"
11 | #import "INFile.h"
12 | #import "INDraft.h"
13 |
14 | @implementation INUploadFileTask
15 |
16 | - (void)applyLocally
17 | {
18 | [[INDatabaseManager shared] persistModel: self.model];
19 | }
20 |
21 | - (void)rollbackLocally
22 | {
23 | [[INDatabaseManager shared] unpersistModel:self.model willResaveSameModel:NO];
24 | }
25 |
26 | - (NSURLRequest *)buildAPIRequest
27 | {
28 | INFile * file = (INFile *)self.model;
29 |
30 | NSAssert(file, @"INUploadFileTask asked to buildRequest with no model!");
31 | NSAssert([file namespaceID], @"INUploadFileTask asked to buildRequest with no namespace!");
32 | NSAssert([file localDataPath], @"INUploadFileTask asked to upload a file with no local data.");
33 |
34 | NSString * path = [NSString stringWithFormat:@"/n/%@/files", [file namespaceID]];
35 | NSString * url = [[NSURL URLWithString:path relativeToURL:[INAPIManager shared].AF.baseURL] absoluteString];
36 |
37 | return [[[[INAPIManager shared] AF] requestSerializer] multipartFormRequestWithMethod:@"POST" URLString:url parameters:nil constructingBodyWithBlock:^(id formData) {
38 | NSURL * fileURL = [NSURL fileURLWithPath: [file localDataPath]];
39 | [formData appendPartWithFileURL:fileURL name:@"file" fileName:[file filename] mimeType:[file mimetype] error:NULL];
40 | } error:NULL];
41 | }
42 |
43 | - (NSMutableArray *)waitingDrafts
44 | {
45 | if (!self.data[@"waitingDrafts"])
46 | [self.data setObject:[NSMutableArray array] forKey:@"waitingDrafts"];
47 | return self.data[@"waitingDrafts"];
48 | }
49 |
50 | - (void)handleSuccess:(AFHTTPRequestOperation *)operation withResponse:(id)responseObject
51 | {
52 | if ([responseObject isKindOfClass: [NSArray class]])
53 | responseObject = [responseObject firstObject];
54 |
55 | if (![responseObject isKindOfClass: [NSDictionary class]])
56 | return NSLog(@"SaveDraft weird response: %@", responseObject);
57 |
58 | NSString * oldID = [self.model ID];
59 |
60 | INFile * file = (INFile *)self.model;
61 | [[INDatabaseManager shared] unpersistModel: file willResaveSameModel:YES];
62 | [file updateWithResourceDictionary: responseObject];
63 | [[INDatabaseManager shared] persistModel: file];
64 |
65 | for (INDraft * draft in [self waitingDrafts])
66 | [draft fileWithID:oldID uploadedAs:[self.model ID]];
67 | }
68 |
69 | @end
70 |
--------------------------------------------------------------------------------
/InboxExamples/Triage/Triage/TRAppDelegate.m:
--------------------------------------------------------------------------------
1 | //
2 | // TRAppDelegate.m
3 | // Triage
4 | //
5 | // Created by Ben Gotow on 5/7/14.
6 | // Copyright (c) 2014 Inbox. All rights reserved.
7 | //
8 |
9 | #import "TRAppDelegate.h"
10 |
11 | @implementation TRAppDelegate
12 |
13 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
14 | {
15 | // Override point for customization after application launch.
16 | self.viewController = [[TRViewController alloc] init];
17 |
18 | self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
19 | self.window.rootViewController = _viewController;
20 | [self.window makeKeyAndVisible];
21 |
22 | return YES;
23 | }
24 |
25 | - (void)applicationWillResignActive:(UIApplication *)application
26 | {
27 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
28 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
29 | }
30 |
31 | - (void)applicationDidEnterBackground:(UIApplication *)application
32 | {
33 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
34 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
35 | }
36 |
37 | - (void)applicationWillEnterForeground:(UIApplication *)application
38 | {
39 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
40 | }
41 |
42 | - (void)applicationDidBecomeActive:(UIApplication *)application
43 | {
44 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
45 | }
46 |
47 | - (void)applicationWillTerminate:(UIApplication *)application
48 | {
49 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
50 | }
51 |
52 | - (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation
53 | {
54 | return [[INAPIManager shared] handleURL: url];
55 | }
56 |
57 | @end
58 |
--------------------------------------------------------------------------------
/InboxFramework/Inbox/Models/API Calls/INDeleteDraftTask.m:
--------------------------------------------------------------------------------
1 | //
2 | // INDeleteDraftChange.m
3 | // InboxFramework
4 | //
5 | // Created by Ben Gotow on 5/20/14.
6 | // Copyright (c) 2014 Inbox. All rights reserved.
7 | //
8 |
9 | #import "INDeleteDraftTask.h"
10 | #import "INThread+Private.h"
11 | #import "INSaveDraftTask.h"
12 | #import "INSendDraftTask.h"
13 |
14 | @implementation INDeleteDraftTask
15 |
16 | - (BOOL)canCancelPendingTask:(INAPITask*)other
17 | {
18 | if ([[other model] isEqual: self.model] && [other isKindOfClass: [INSaveDraftTask class]])
19 | return YES;
20 | if ([[other model] isEqual: self.model] && [other isKindOfClass: [INSendDraftTask class]])
21 | return YES;
22 | if ([[other model] isEqual: self.model] && [other isKindOfClass: [INDeleteDraftTask class]])
23 | return YES;
24 | return NO;
25 | }
26 |
27 | - (BOOL)canStartAfterTask:(INAPITask*)other
28 | {
29 | // If the other operation is sending the draft, it's too late!
30 | // Gotta tell the user the draft couldn't be deleted.
31 | if ([[other model] isEqual: self.model] && [other isKindOfClass: [INSendDraftTask class]])
32 | return NO;
33 | return YES;
34 | }
35 |
36 | - (NSURLRequest *)buildAPIRequest
37 | {
38 | NSAssert(self.model, @"INDeleteDraftChange asked to buildRequest with no model!");
39 | NSAssert([self.model namespaceID], @"INDeleteDraftChange asked to buildRequest with no namespace!");
40 |
41 | NSError * error = nil;
42 | NSString * url = [[NSURL URLWithString:[self.model resourceAPIPath] relativeToURL:[INAPIManager shared].AF.baseURL] absoluteString];
43 | return [[[[INAPIManager shared] AF] requestSerializer] requestWithMethod:@"DELETE" URLString:url parameters:nil error:&error];
44 | }
45 |
46 | - (void)applyLocally
47 | {
48 | INDraft * draft = (INDraft *)[self model];
49 | [[INDatabaseManager shared] unpersistModel: draft willResaveSameModel: NO];
50 |
51 | INThread * thread = [draft thread];
52 | if (thread) {
53 | [thread removeDraftID: [draft ID]];
54 | [[INDatabaseManager shared] persistModel: thread];
55 | }
56 | }
57 |
58 | - (void)applyRemotelyWithCallback:(CallbackBlock)callback
59 | {
60 | // If we're deleting a draft that was never synced to the server,
61 | // there's no need for an API call. Just return.
62 | if ([self.model isUnsynced])
63 | callback(self, YES);
64 | else
65 | [super applyRemotelyWithCallback: callback];
66 | }
67 |
68 | - (void)rollbackLocally
69 | {
70 | // re-persist the message to the database
71 | INDraft * draft = (INDraft *)[self model];
72 | [[INDatabaseManager shared] persistModel: draft];
73 |
74 | INThread * thread = [draft thread];
75 | if (thread) {
76 | [thread addDraftID: [draft ID]];
77 | [[INDatabaseManager shared] persistModel: thread];
78 | }
79 | }
80 |
81 |
82 | @end
83 |
--------------------------------------------------------------------------------
/InboxFramework/Inbox/Models/Concrete Classes/INFile.h:
--------------------------------------------------------------------------------
1 | //
2 | // INAttachment.h
3 | // InboxFramework
4 | //
5 | // Created by Ben Gotow on 5/21/14.
6 | // Copyright (c) 2014 Inbox. All rights reserved.
7 | //
8 |
9 | #import "INModelObject.h"
10 | #import "INAPIManager.h"
11 |
12 | @class INUploadFileTask;
13 |
14 | typedef void (^ AttachmentDownloadBlock)(NSError * error, NSData * data);
15 |
16 | /** INAttachment represents a single attachment on an email message. Attachments
17 | may be created, uploaded and attached to drafts, or fetched from the server for
18 | existing messages.
19 | */
20 | @interface INFile : INModelObject
21 |
22 | @property (nonatomic, strong) NSString * localDataPath;
23 | @property (nonatomic, strong) UIImage * localPreview;
24 | @property (nonatomic, strong) NSString * filename;
25 | @property (nonatomic, strong) NSString * mimetype;
26 |
27 | /**
28 | Initialize an INAttachment with the provided image as a JPG. Images may be
29 | compressed and/or downsized automatically if they are too large.
30 |
31 | @param image The image to upload.
32 |
33 | @param namespace The namespace to add this attachment in.
34 |
35 | @return An initialized INAttachment object. To start uploading this attachment, you need
36 | to call -upload.
37 | */
38 | - (id)initWithImage:(UIImage*)image inNamespace:(INNamespace*)namespace;
39 |
40 | /**
41 | Initialize an INAttachment with the arbitrary file data provided.
42 |
43 | @param filename The display filename of the attachment.
44 | @param mimetype The mimetype of the attachment, such as "image/jpeg" or "text/plain".
45 | @param data The attachment data.
46 | @param previewOrNil A small UIImage to use for displaying this attachment in your app.
47 | If you don't provide a preview image, subsequent requests for this attachment's localPreview
48 | may return nil.
49 | @param namespace The namespace to add this attachment in.
50 |
51 | @return An initialized INAttachment object. To start uploading this attachment, you need
52 | to call -upload.
53 | */
54 | - (id)initWithFilename:(NSString*)filename mimetype:(NSString*)mimetype andData:(NSData*)data andPreview:(UIImage*)previewOrNil inNamespace:(INNamespace*)namespace;
55 |
56 | /**
57 | Start uploading this attachment in the background. To track the progress of the upload
58 | operation, observe the INUploadAttachmentTask returned from -uploadTask for the
59 | INTaskProgressNotification notification.
60 | */
61 | - (void)upload;
62 |
63 | /**
64 | @return The upload task that is currently trying to upload this attachment object. To track
65 | the progress of this upload, listen for INTaskProgressNotification notifications for this
66 | object.
67 | */
68 | - (INUploadFileTask*)uploadTask;
69 |
70 | /**
71 | Asynchronously fetches the attachment data from the server.
72 |
73 | @param callback The callback to invoke when attachment data has been successfully downloaded,
74 | or an error has occurred.
75 | */
76 | - (void)getDataWithCallback:(AttachmentDownloadBlock)callback;
77 |
78 | @end
79 |
--------------------------------------------------------------------------------
/InboxFramework/Inbox/Models/Concrete Classes/INMessage.m:
--------------------------------------------------------------------------------
1 | //
2 | // INMessage.m
3 | // BigSur
4 | //
5 | // Created by Ben Gotow on 4/30/14.
6 | // Copyright (c) 2014 Inbox. All rights reserved.
7 | //
8 |
9 | #import "INMessage.h"
10 | #import "INThread.h"
11 | #import "INFile.h"
12 | #import "NSString+FormatConversion.h"
13 | #import "INModelObject+Uniquing.h"
14 | #import "INNamespace.h"
15 | #import "INMarkMessageAsReadTask.h"
16 |
17 | @implementation INMessage
18 |
19 |
20 | + (NSMutableDictionary *)resourceMapping
21 | {
22 | NSMutableDictionary * mapping = [super resourceMapping];
23 | [mapping addEntriesFromDictionary:@{
24 | @"subject": @"subject",
25 | @"body": @"body",
26 | @"snippet": @"snippet",
27 | @"threadID": @"thread_id",
28 | @"date": @"date",
29 | @"from": @"from",
30 | @"to": @"to",
31 | @"cc": @"cc",
32 | @"bcc": @"bcc",
33 | @"unread": @"unread",
34 | }];
35 | return mapping;
36 | }
37 |
38 | + (NSString *)resourceAPIName
39 | {
40 | return @"messages";
41 | }
42 |
43 | + (NSArray *)databaseIndexProperties
44 | {
45 | return [[super databaseIndexProperties] arrayByAddingObjectsFromArray: @[@"threadID", @"subject", @"date"]];
46 | }
47 |
48 | - (INThread*)thread
49 | {
50 | if (!_threadID)
51 | return nil;
52 | return [INThread instanceWithID: [self threadID] inNamespaceID: [self namespaceID]];
53 | }
54 |
55 | - (NSMutableDictionary *)resourceDictionary
56 | {
57 | NSMutableDictionary * dict = [super resourceDictionary];
58 | NSMutableArray * files = [NSMutableArray array];
59 | NSMutableArray * fileIDs = [NSMutableArray array];
60 | for (INFile * file in _files) {
61 | [files addObject: [file resourceDictionary]];
62 | [fileIDs addObject: [file ID]];
63 | }
64 | [dict setObject:files forKey:@"files"];
65 | [dict setObject:fileIDs forKey:@"file_ids"];
66 |
67 | return dict;
68 | }
69 |
70 | - (void)updateWithResourceDictionary:(NSDictionary *)dict
71 | {
72 | [super updateWithResourceDictionary: dict];
73 |
74 | NSMutableArray * files = [NSMutableArray array];
75 | if (dict[@"files"]) {
76 | for (NSDictionary * fileDict in dict[@"files"]) {
77 | INFile * file = [INFile attachedInstanceMatchingID: fileDict[@"id"] createIfNecessary:YES didCreate: NULL];
78 | [file updateWithResourceDictionary: fileDict];
79 | [files addObject: file];
80 | }
81 | } else {
82 | for (NSDictionary * ID in dict[@"file_ids"]) {
83 | INFile * file = [INFile attachedInstanceMatchingID: ID createIfNecessary:YES didCreate: NULL];
84 | [files addObject: file];
85 | }
86 | }
87 | _files = [NSArray arrayWithArray: files];
88 | }
89 |
90 | - (void)markAsRead
91 | {
92 | if (self.unread == NO)
93 | return;
94 |
95 | INMarkMessageAsReadTask * task = [[INMarkMessageAsReadTask alloc] initWithModel: self];
96 | [[INAPIManager shared] queueTask: task];
97 | }
98 |
99 |
100 | @end
101 |
--------------------------------------------------------------------------------
/InboxFramework/Inbox/Models/Concrete Classes/INNamespace.h:
--------------------------------------------------------------------------------
1 | //
2 | // INNamespace.h
3 | // BigSur
4 | //
5 | // Created by Ben Gotow on 4/28/14.
6 | // Copyright (c) 2014 Inbox. All rights reserved.
7 | //
8 |
9 | #import "INModelObject.h"
10 | #import "INModelProvider.h"
11 |
12 | @class INThreadProvider;
13 | @class INMessageProvider;
14 |
15 | /**
16 | Namespaces are an important concept in Inbox. Typically, a user authenticates with
17 | the Inbox API and the access token you are given provides access to one namespace:
18 | the user's email account. Threads, messages, contacts, files, etc. live within the
19 | namespace, and the INNamespace object provides convenience methods for creating
20 | model providers for these types. You can also use the properties on INNamespace
21 | to determine the user's email address, check Inbox sync status, and more.
22 |
23 | Note: In the future, a single access token may grant you access to multiple namespaces,
24 | and a namespace may not always be an entire email account.
25 | */
26 | @interface INNamespace : INModelObject
27 |
28 | @property (nonatomic, strong) NSString * emailAddress;
29 | @property (nonatomic, strong) NSString * name;
30 | @property (nonatomic, strong) NSString * provider;
31 | @property (nonatomic, strong) NSString * status;
32 | @property (nonatomic, strong) NSArray * scope;
33 | @property (nonatomic, strong) NSDate * lastSync;
34 |
35 | /**
36 | Initializes and returns a new INModelProvider for displaying contacts in this namespace.
37 | To display contacts matching certain criteria, create a new contact provider using this method
38 | and then set it's itemFilterPredicate to narrow the models it provides.
39 | @return An initialized INModelProvider for displaying contacts.
40 | */
41 | - (INModelProvider *)newContactProvider;
42 |
43 | /**
44 | Initializes and returns a new INThreadProvider for displaying threads in this namespace.
45 | To display threads matching certain criteria, create a new thread provider using this method
46 | and then set it's itemFilterPredicate to narrow the models it provides.
47 | @return An initialized INThreadProvider for displaying threads.
48 | */
49 | - (INThreadProvider *)newThreadProvider;
50 |
51 | /**
52 | Initializes and returns a new INModelProvider for displaying tags in this namespace.
53 | @return An initialized INModelProvider for displaying tags.
54 | */
55 | - (INModelProvider *)newTagProvider;
56 |
57 | /**
58 | Initializes and returns a new INMessageProvider for displaying drafts in this namespace.
59 | @return An initialized INMessageProvider for displaying drafts.
60 | */
61 | - (INMessageProvider *)newDraftsProvider;
62 |
63 | /**
64 | Initializes and returns a new INMessageProvider for displaying messages in this namespace.
65 | Note that threads, not messages, are the objects you most often apply changes to. In many
66 | cases, you should use threads instead of messages. For example, you archive a thread, not
67 | a message.
68 | @return An initialized INMessageProvider for displaying messages.
69 | */
70 | - (INMessageProvider *)newMessageProvider;
71 |
72 | @end
73 |
--------------------------------------------------------------------------------
/InboxExamples/Snapmail/Snapmail/INAppDelegate.m:
--------------------------------------------------------------------------------
1 | //
2 | // INAppDelegate.m
3 | // Snapmail
4 | //
5 | // Created by Ben Gotow on 6/16/14.
6 | // Copyright (c) 2014 InboxApp, Inc. All rights reserved.
7 | //
8 |
9 | #import "INAppDelegate.h"
10 | #import "INAPIManager.h"
11 |
12 | @implementation INAppDelegate
13 |
14 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
15 | {
16 | _viewController = [[INHomeViewController alloc] init];
17 |
18 | [[UIApplication sharedApplication] setStatusBarStyle: UIStatusBarStyleLightContent];
19 | [[UINavigationBar appearance] setBarTintColor: [UIColor colorWithRed:78/255.0 green:168/255.0 blue:133/255.0 alpha:1]];
20 | [[UINavigationBar appearance] setTintColor: [UIColor whiteColor]];
21 | [[UINavigationBar appearance] setTitleTextAttributes: @{NSForegroundColorAttributeName: [UIColor whiteColor]}];
22 |
23 | self.window = [[UIWindow alloc] initWithFrame: [[UIScreen mainScreen] bounds]];
24 | self.window.rootViewController = [[UINavigationController alloc] initWithRootViewController: _viewController];;
25 | [self.window makeKeyAndVisible];
26 |
27 | return YES;
28 | }
29 |
30 | - (void)applicationWillResignActive:(UIApplication *)application
31 | {
32 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
33 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
34 | }
35 |
36 | - (void)applicationDidEnterBackground:(UIApplication *)application
37 | {
38 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
39 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
40 | }
41 |
42 | - (void)applicationWillEnterForeground:(UIApplication *)application
43 | {
44 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
45 | }
46 |
47 | - (void)applicationDidBecomeActive:(UIApplication *)application
48 | {
49 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
50 | }
51 |
52 | - (void)applicationWillTerminate:(UIApplication *)application
53 | {
54 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
55 | }
56 |
57 | - (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation
58 | {
59 | return [[INAPIManager shared] handleURL: url];
60 | }
61 |
62 | @end
63 |
--------------------------------------------------------------------------------
/InboxExamples/Snapmail/Snapmail/INCaptureViewController.m:
--------------------------------------------------------------------------------
1 | //
2 | // INCaptureViewController.m
3 | // Snapmail
4 | //
5 | // Created by Ben Gotow on 6/16/14.
6 | // Copyright (c) 2014 InboxApp, Inc. All rights reserved.
7 | //
8 |
9 | #import "INCaptureViewController.h"
10 | #import "INContactsViewController.h"
11 |
12 | @implementation INCaptureViewController
13 |
14 | - (id)initWithThread:(INThread*)thread
15 | {
16 | self = [super init];
17 | if (self) {
18 | _thread = thread;
19 |
20 | }
21 | return self;
22 | }
23 |
24 | - (void)viewDidLoad
25 | {
26 | [super viewDidLoad];
27 |
28 | [_toggleSideButton setHidden: ![UIImagePickerController isCameraDeviceAvailable: UIImagePickerControllerCameraDeviceFront]];
29 | }
30 |
31 | - (void)didReceiveMemoryWarning
32 | {
33 | [super didReceiveMemoryWarning];
34 | }
35 |
36 | - (IBAction)toggleSideTapped:(id)sender
37 | {
38 | if (_picker.cameraDevice == UIImagePickerControllerCameraDeviceFront)
39 | [_picker setCameraDevice: UIImagePickerControllerCameraDeviceRear];
40 | else
41 | [_picker setCameraDevice: UIImagePickerControllerCameraDeviceFront];
42 |
43 | }
44 |
45 | - (IBAction)cancelTapped:(id)sender
46 | {
47 | [_picker dismissViewControllerAnimated:YES completion:NULL];
48 | }
49 |
50 | - (IBAction)captureTapped:(id)sender
51 | {
52 | [_picker takePicture];
53 | }
54 |
55 | - (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
56 | {
57 | UIImage * img = [info objectForKey: UIImagePickerControllerOriginalImage];
58 |
59 | if (!_thread) {
60 | INNamespace * namespace = [[[INAPIManager shared] namespaces] firstObject];
61 | INContactsViewController * contacts = [[INContactsViewController alloc] initForSelectingContactInNamespace:namespace withCallback:^(NSArray * contacts) {
62 | [self sendImage: img to: contacts];
63 | [picker dismissViewControllerAnimated:NO completion:NULL];
64 | [picker dismissViewControllerAnimated:NO completion:NULL];
65 | }];
66 | UINavigationController * nav = [[UINavigationController alloc] initWithRootViewController: contacts];
67 | [picker presentViewController: nav animated: NO completion: NULL];
68 |
69 | } else {
70 | [self sendImage: img to:nil];
71 | [picker dismissViewControllerAnimated:YES completion:NULL];
72 | }
73 | }
74 |
75 | - (void)sendImage:(UIImage*)image to:(NSArray*)contacts
76 | {
77 | INNamespace * namespace = [[[INAPIManager shared] namespaces] firstObject];
78 | INDraft * draft = nil;
79 |
80 | if (_thread) {
81 | draft = [[INDraft alloc] initInNamespace:namespace inReplyTo:_thread];
82 | } else {
83 | draft = [[INDraft alloc] initInNamespace:namespace];
84 | [draft setSubject: @"You've got a new snap!"];
85 | }
86 |
87 | INFile * file = [[INFile alloc] initWithImage:image inNamespace:namespace];
88 | [file upload];
89 | [draft addAttachment: file];
90 |
91 | if (contacts)
92 | [draft setTo: @[@{@"name": [[contacts firstObject] name], @"email": @"bengotow@gmail.com"}]];
93 |
94 | [draft send];
95 |
96 | }
97 |
98 | @end
99 |
--------------------------------------------------------------------------------
/InboxFramework/InboxUI/Categories/UIView+FrameAdditions.m:
--------------------------------------------------------------------------------
1 | //
2 | // UIViewAdditions.m
3 | // PAR Works iOS SDK
4 | //
5 | // Copyright 2013 PAR Works, Inc.
6 | //
7 | // Licensed under the Apache License, Version 2.0 (the "License");
8 | // you may not use this file except in compliance with the License.
9 | // You may obtain a copy of the License at
10 | //
11 | // http://www.apache.org/licenses/LICENSE-2.0
12 | //
13 | // Unless required by applicable law or agreed to in writing, software
14 | // distributed under the License is distributed on an "AS IS" BASIS,
15 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 | // See the License for the specific language governing permissions and
17 | // limitations under the License.
18 | //
19 |
20 |
21 |
22 | #import "UIView+FrameAdditions.h"
23 |
24 | @implementation UIView (FrameAdditions)
25 |
26 | - (void)in_setFrameY:(float)y
27 | {
28 | CGRect frame = [self frame];
29 | frame.origin.y = y;
30 | [self setFrame: frame];
31 | }
32 |
33 | - (void)in_setFrameX:(float)x
34 | {
35 | CGRect frame = [self frame];
36 | frame.origin.x = x;
37 | [self setFrame: frame];
38 | }
39 |
40 | - (void)in_shiftFrame:(CGPoint)offset
41 | {
42 | CGRect frame = [self frame];
43 | [self setFrame: CGRectMake(frame.origin.x + offset.x, frame.origin.y + offset.y, frame.size.width, frame.size.height)];
44 | }
45 |
46 | - (void)in_setFrameOrigin:(CGPoint)origin
47 | {
48 | CGRect frame = [self frame];
49 | [self setFrame: CGRectMake(origin.x, origin.y, frame.size.width, frame.size.height)];
50 | }
51 |
52 | - (void)in_setFrameSize:(CGSize)size
53 | {
54 | CGRect frame = [self frame];
55 | [self setFrame: CGRectMake(frame.origin.x, frame.origin.y, size.width, size.height)];
56 | }
57 |
58 | - (void)in_setFrameCenter:(CGPoint)p
59 | {
60 | CGRect frame = [self frame];
61 | [self setFrame: CGRectMake(p.x - frame.size.width / 2, p.y - frame.size.height / 2, frame.size.width, frame.size.height)];
62 | }
63 |
64 | - (void)in_setFrameWidth:(float)w
65 | {
66 | CGRect frame = [self frame];
67 | frame.size.width = w;
68 | [self setFrame: frame];
69 | }
70 |
71 | - (void)in_setFrameHeight:(float)h
72 | {
73 | CGRect frame = [self frame];
74 | frame.size.height = h;
75 | [self setFrame: frame];
76 | }
77 |
78 | - (CGPoint)in_topRight
79 | {
80 | return CGPointMake([self frame].origin.x + [self frame].size.width, [self frame].origin.y);
81 | }
82 |
83 | - (CGPoint)in_bottomRight
84 | {
85 | return CGPointMake([self frame].origin.x + [self frame].size.width, [self frame].origin.y + [self frame].size.height);
86 | }
87 |
88 | - (CGPoint)in_bottomLeft
89 | {
90 | return CGPointMake([self frame].origin.x, [self frame].origin.y + [self frame].size.height);
91 | }
92 |
93 | - (id)viewAncestorOfClass:(Class)klass
94 | {
95 | if ([[self superview] isKindOfClass: klass])
96 | return [self superview];
97 | else
98 | return [[self superview] viewAncestorOfClass: klass];
99 | }
100 |
101 | @end
102 |
--------------------------------------------------------------------------------
/InboxFramework/Inbox/Categories/NSString+FormatConversion.m:
--------------------------------------------------------------------------------
1 | //
2 | // NSString+DateConversion.m
3 | // Mib.io
4 | //
5 | // Created by Ben Gotow on 6/7/12.
6 | // Copyright (c) 2012 Foundry376. All rights reserved.
7 | //
8 |
9 | #import "NSString+FormatConversion.h"
10 | #import
11 |
12 | static NSMutableDictionary * formatters;
13 |
14 | @implementation NSString (FormatConversion)
15 |
16 | + (NSDateFormatter *)formatterForFormat:(NSString *)f
17 | {
18 | if (formatters == nil)
19 | formatters = [[NSMutableDictionary alloc] init];
20 |
21 | NSDateFormatter * formatter = [formatters objectForKey:f];
22 |
23 | if (!formatter) {
24 | formatter = [[NSDateFormatter alloc] init];
25 | [formatter setDateFormat:f];
26 | [formatters setObject:formatter forKey:f];
27 | }
28 | return formatter;
29 | }
30 |
31 | + (NSString *)stringWithDate:(NSDate *)date format:(NSString *)f
32 | {
33 | return [[NSString formatterForFormat:f] stringFromDate:date];
34 | }
35 |
36 | - (NSDate *)dateValueWithFormat:(NSString *)f
37 | {
38 | return [[NSString formatterForFormat:f] dateFromString:self];
39 | }
40 |
41 | - (NSString *)md5Value
42 | {
43 | const char * cStr = [self UTF8String];
44 | unsigned char digest[16];
45 |
46 | CC_MD5(cStr, (CC_LONG)strlen(cStr), digest); // This is the md5 call
47 |
48 | NSMutableString * output = [NSMutableString stringWithCapacity:CC_MD5_DIGEST_LENGTH * 2];
49 |
50 | for (int i = 0; i < CC_MD5_DIGEST_LENGTH; i++)
51 | [output appendFormat:@"%02x", digest[i]];
52 |
53 | return output;
54 | }
55 |
56 | + (NSString *)generateUUIDWithExtension:(NSString *)ext
57 | {
58 | CFUUIDRef theUUID = CFUUIDCreate(NULL);
59 | CFStringRef string = CFUUIDCreateString(NULL, theUUID);
60 |
61 | CFRelease(theUUID);
62 | NSString * s = (NSString *)CFBridgingRelease(string);
63 |
64 | if (ext)
65 | s = [s stringByAppendingFormat:@".%@", ext];
66 | return s;
67 | }
68 |
69 | - (NSString *)urlencode
70 | {
71 | NSMutableString * output = [NSMutableString string];
72 | const unsigned char * source = (const unsigned char *)[self UTF8String];
73 | unsigned long sourceLen = strlen((const char *)source);
74 |
75 | for (int i = 0; i < sourceLen; ++i) {
76 | const unsigned char thisChar = source[i];
77 |
78 | if (thisChar == ' ')
79 | [output appendString:@"+"];
80 | else if ((thisChar == '.') || (thisChar == '-') || (thisChar == '_') || (thisChar == '~') ||
81 | ((thisChar >= 'a') && (thisChar <= 'z')) ||
82 | ((thisChar >= 'A') && (thisChar <= 'Z')) ||
83 | ((thisChar >= '0') && (thisChar <= '9')))
84 | [output appendFormat:@"%c", thisChar];
85 | else
86 | [output appendFormat:@"%%%02X", thisChar];
87 | }
88 |
89 | return output;
90 | }
91 |
92 | - (id)asJSONObjectOfClass:(Class)klass
93 | {
94 | if ([self length] == 0)
95 | return nil;
96 |
97 | NSData * data = [self dataUsingEncoding:NSUTF8StringEncoding];
98 | id obj = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:NULL];
99 |
100 | if ([obj isKindOfClass:klass])
101 | return obj;
102 | else
103 | return nil;
104 | }
105 |
106 | @end
107 |
--------------------------------------------------------------------------------
/InboxFramework/Inbox/Models/Concrete Classes/INFile.m:
--------------------------------------------------------------------------------
1 | //
2 | // INAttachment.m
3 | // InboxFramework
4 | //
5 | // Created by Ben Gotow on 5/21/14.
6 | // Copyright (c) 2014 Inbox. All rights reserved.
7 | //
8 |
9 | #import "INFile.h"
10 | #import "INModelObject+Uniquing.h"
11 | #import "INNamespace.h"
12 | #import "INUploadFileTask.h"
13 |
14 | @implementation INFile
15 |
16 | + (NSMutableDictionary *)resourceMapping
17 | {
18 | NSMutableDictionary * mapping = [super resourceMapping];
19 | [mapping addEntriesFromDictionary: @{
20 | @"filename": @"filename",
21 | @"mimetype": @"mimetype",
22 |
23 | @"localDataPath": @"__localDataPath",
24 | }];
25 | return mapping;
26 | }
27 |
28 | + (NSString *)resourceAPIName
29 | {
30 | return @"files";
31 | }
32 |
33 | - (id)initWithImage:(UIImage*)image inNamespace:(INNamespace*)namespace
34 | {
35 | return [self initWithFilename:@"image.jpg" mimetype:@"image/jpeg" andData:UIImageJPEGRepresentation(image, 0.85) andPreview: image inNamespace:namespace];
36 | }
37 |
38 | - (id)initWithFilename:(NSString*)filename mimetype:(NSString*)mimetype andData:(NSData*)data andPreview:(UIImage*)previewOrNil inNamespace:(INNamespace*)namespace
39 | {
40 | NSAssert(data, @"You must provide attachment data.");
41 | NSAssert(filename, @"You must provide an attachment filename.");
42 | NSAssert(mimetype, @"You must provide an attachment mimetype.");
43 | NSAssert(namespace, @"You must provide an attachment namespace.");
44 |
45 | self = [super init];
46 | if (self) {
47 | self.namespaceID = [namespace ID];
48 | self.filename = filename;
49 | self.mimetype = mimetype;
50 | self.localPreview = previewOrNil;
51 | self.localDataPath = [[NSString stringWithFormat: @"~/Documents/%@.data", self.ID] stringByExpandingTildeInPath];
52 | [data writeToFile: _localDataPath atomically:NO];
53 | [INFile attachInstance: self];
54 |
55 | }
56 | return self;
57 | }
58 |
59 | - (UIImage*)localPreview
60 | {
61 | if (_localPreview)
62 | return _localPreview;
63 |
64 | // TODO: Return previews
65 | return nil;
66 | }
67 |
68 | - (void)upload
69 | {
70 | NSAssert(_localDataPath, @"Before calling -upload, you need to use one of the designated initializers to provide a reference to data to upload.");
71 | if ([self uploadTask])
72 | return;
73 |
74 | INUploadFileTask * upload = [[INUploadFileTask alloc] initWithModel: self];
75 | [[INAPIManager shared] queueTask: upload];
76 | }
77 |
78 | - (INUploadFileTask*)uploadTask
79 | {
80 | for (INUploadFileTask * change in [[INAPIManager shared] taskQueue]) {
81 | if ([change isKindOfClass: [INUploadFileTask class]] && [[change model] isEqual: self])
82 | return change;
83 | }
84 | return nil;
85 | }
86 |
87 | - (void)getDataWithCallback:(AttachmentDownloadBlock)callback
88 | {
89 | NSString * path = [NSString stringWithFormat:@"/n/%@/files/%@/download", self.namespaceID, self.ID];
90 | AFHTTPRequestOperation * op = [[INAPIManager shared].AF GET:path parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) {
91 | callback(nil, responseObject);
92 | } failure:^(AFHTTPRequestOperation *operation, NSError *error) {
93 | callback(error, nil);
94 | }];
95 | [op setResponseSerializer: [AFHTTPResponseSerializer serializer]];
96 | }
97 |
98 | @end
99 |
--------------------------------------------------------------------------------
/InboxExamples/Snapmail/Snapmail/INHomeViewController.xib:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
--------------------------------------------------------------------------------
/InboxExamples/Triage/Triage/INPlaceholderTextView.m:
--------------------------------------------------------------------------------
1 | //
2 | // INPlaceholderTextView.m
3 | // BigSur
4 | //
5 |
6 | #import "INPlaceholderTextView.h"
7 |
8 |
9 | @interface INPlaceholderTextView ()
10 |
11 | @property (nonatomic, retain) UILabel *placeHolderLabel;
12 |
13 | @end
14 |
15 | @implementation INPlaceholderTextView
16 |
17 | CGFloat const UI_PLACEHOLDER_TEXT_CHANGED_ANIMATION_DURATION = 0.25;
18 |
19 | - (void)dealloc
20 | {
21 | [[NSNotificationCenter defaultCenter] removeObserver:self];
22 | #if __has_feature(objc_arc)
23 | #else
24 | [_placeHolderLabel release]; _placeHolderLabel = nil;
25 | [_placeholderColor release]; _placeholderColor = nil;
26 | [_placeholder release]; _placeholder = nil;
27 | [super dealloc];
28 | #endif
29 | }
30 |
31 | - (void)awakeFromNib
32 | {
33 | [super awakeFromNib];
34 |
35 | // Use Interface Builder User Defined Runtime Attributes to set
36 | // placeholder and placeholderColor in Interface Builder.
37 | if (!self.placeholder) {
38 | [self setPlaceholder:@""];
39 | }
40 |
41 | if (!self.placeholderColor) {
42 | [self setPlaceholderColor:[UIColor lightGrayColor]];
43 | }
44 |
45 | [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(textChanged:) name:UITextViewTextDidChangeNotification object:nil];
46 | }
47 |
48 | - (id)initWithFrame:(CGRect)frame
49 | {
50 | if( (self = [super initWithFrame:frame]) )
51 | {
52 | [self setPlaceholder:@""];
53 | [self setPlaceholderColor:[UIColor lightGrayColor]];
54 | [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(textChanged:) name:UITextViewTextDidChangeNotification object:nil];
55 | }
56 | return self;
57 | }
58 |
59 | - (void)textChanged:(NSNotification *)notification
60 | {
61 | if([[self placeholder] length] == 0)
62 | {
63 | return;
64 | }
65 |
66 | [UIView animateWithDuration:UI_PLACEHOLDER_TEXT_CHANGED_ANIMATION_DURATION animations:^{
67 | if([[self text] length] == 0)
68 | {
69 | [[self viewWithTag:999] setAlpha:1];
70 | }
71 | else
72 | {
73 | [[self viewWithTag:999] setAlpha:0];
74 | }
75 | }];
76 | }
77 |
78 | - (void)setText:(NSString *)text {
79 | [super setText:text];
80 | [self textChanged:nil];
81 | }
82 |
83 | - (void)drawRect:(CGRect)rect
84 | {
85 | if( [[self placeholder] length] > 0 )
86 | {
87 | if (_placeHolderLabel == nil )
88 | {
89 | _placeHolderLabel = [[UILabel alloc] initWithFrame:CGRectMake(self.textContainerInset.left + 5,self.textContainerInset.top,self.bounds.size.width - 16,0)];
90 | _placeHolderLabel.lineBreakMode = NSLineBreakByWordWrapping;
91 | _placeHolderLabel.numberOfLines = 0;
92 | _placeHolderLabel.font = self.font;
93 | _placeHolderLabel.backgroundColor = [UIColor clearColor];
94 | _placeHolderLabel.textColor = self.placeholderColor;
95 | _placeHolderLabel.alpha = 0;
96 | _placeHolderLabel.tag = 999;
97 | [self addSubview:_placeHolderLabel];
98 | }
99 |
100 | _placeHolderLabel.text = self.placeholder;
101 | [_placeHolderLabel sizeToFit];
102 | [self sendSubviewToBack:_placeHolderLabel];
103 | }
104 |
105 | if( [[self text] length] == 0 && [[self placeholder] length] > 0 )
106 | {
107 | [[self viewWithTag:999] setAlpha:1];
108 | }
109 |
110 | [super drawRect:rect];
111 | }
112 |
113 | @end
--------------------------------------------------------------------------------
/InboxFramework/Inbox/Helpers/INModelResponseSerializer.m:
--------------------------------------------------------------------------------
1 | //
2 | // INModelArrayResponseSerializer.m
3 | // BigSur
4 | //
5 | // Created by Ben Gotow on 4/28/14.
6 | // Copyright (c) 2014 Inbox. All rights reserved.
7 | //
8 |
9 | #import "INModelResponseSerializer.h"
10 | #import "INModelObject.h"
11 | #import "INModelObject+Uniquing.h"
12 | #import "INDatabaseManager.h"
13 | #import "NSError+InboxErrors.h"
14 |
15 |
16 | @implementation INModelResponseSerializer
17 |
18 | - (id)initWithModelClass:(Class)klass
19 | {
20 | self = [super init];
21 |
22 | if (self) {
23 | _modelClass = klass;
24 | self.readingOptions = NSJSONReadingAllowFragments;
25 | }
26 | return self;
27 | }
28 |
29 | - (id)responseObjectForResponse:(NSURLResponse *)response data:(NSData *)data error:(NSError * __autoreleasing *)error
30 | {
31 | id responseObject = [super responseObjectForResponse:response data:data error:error];
32 | if (!responseObject || (error && *error))
33 | return nil;
34 |
35 | BOOL badJSONClass = ([responseObject isKindOfClass:[NSArray class]] == NO);
36 | BOOL badAPIResponse = ([responseObject isKindOfClass: [NSDictionary class]] && [responseObject[@"type"] isEqualToString: @"api_error"]);
37 |
38 | if (badAPIResponse) {
39 | if (error)
40 | *error = [NSError inboxErrorWithDescription: responseObject[@"message"]];
41 | return nil;
42 | }
43 |
44 | if (badJSONClass) {
45 | if (error)
46 | *error = [NSError inboxErrorWithDescription: @"The JSON object returned was not an NSArray"];
47 | return nil;
48 | }
49 |
50 | NSMutableArray * models = [NSMutableArray array];
51 | NSMutableArray * modifiedOrUnloadedModels = [NSMutableArray array];
52 | NSMutableArray * modelsToDelete = [NSMutableArray arrayWithArray: _modelsCurrentlyMatching];
53 |
54 | dispatch_sync(dispatch_get_main_queue(), ^{
55 | for (NSDictionary * modelDictionary in responseObject) {
56 | BOOL created = NO;
57 |
58 | // TODO: Remove this so it continues and throw an exception
59 | if (!modelDictionary[@"id"] || [modelDictionary[@"id"] isKindOfClass: [NSNull class]])
60 | continue;
61 |
62 | INModelObject * object = [_modelClass attachedInstanceMatchingID: modelDictionary[@"id"] createIfNecessary: YES didCreate: &created];
63 | [modelsToDelete removeObject: object];
64 |
65 | if (created) {
66 | // If we don't have a copy of the object in memory, inflate one and write it
67 | // to the database. Note that these will probably be freed shortly.
68 | [object updateWithResourceDictionary:modelDictionary];
69 | [object setup];
70 | [modifiedOrUnloadedModels addObject: object];
71 |
72 | } else {
73 | // If we have a copy of the object in memory already, let's be smart. Only apply
74 | // changes to the model if necessary. This prevents unnecessary notifications from
75 | // being fired, animations in the interface, etc.
76 | if ([object differentFromResourceDictionary: modelDictionary]) {
77 | [object updateWithResourceDictionary:modelDictionary];
78 | [modifiedOrUnloadedModels addObject: object];
79 | }
80 | }
81 |
82 | [models addObject:object];
83 | }
84 | });
85 |
86 | // Save models to our local database. The database will notify it's
87 | // observers that these models have been saved, and INModelProviders
88 | // will automatically compute alterations, triggering UI updates.
89 | [[INDatabaseManager shared] unpersistModels: modelsToDelete];
90 | [[INDatabaseManager shared] persistModels: modifiedOrUnloadedModels];
91 | _modelsCurrentlyMatching = nil;
92 |
93 | return models;
94 | }
95 |
96 | @end
97 |
98 |
--------------------------------------------------------------------------------
/InboxFramework/InboxFramework.xcodeproj/project.xcworkspace/xcshareddata/InboxFramework.xccheckout:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDESourceControlProjectFavoriteDictionaryKey
6 |
7 | IDESourceControlProjectIdentifier
8 | ACCB086E-6EB2-4819-B467-341DB1D59551
9 | IDESourceControlProjectName
10 | InboxFramework
11 | IDESourceControlProjectOriginsDictionary
12 |
13 | 09397265-E7D3-47F9-B2E2-49FB444FD53C
14 | https://github.com/kiwi-bdd/Kiwi.git
15 | 59CC8397-C42A-4C3C-9FF0-7F23BB915152
16 | https://github.com/carlbrown/PDKeychainBindingsController.git
17 | 9499EAF2-4498-47F3-8D0D-7B109B9BD5D0
18 | https://github.com/AFNetworking/AFNetworking.git
19 | AD710768-7887-4862-9ECC-7B8F562C1700
20 | https://github.com/ccgus/fmdb.git
21 | F91478D6-B52C-42BD-924C-4C00BF902D59
22 | ssh://github.com/inboxapp/inbox-ios.git
23 |
24 | IDESourceControlProjectPath
25 | InboxFramework/InboxFramework.xcodeproj/project.xcworkspace
26 | IDESourceControlProjectRelativeInstallPathDictionary
27 |
28 | 09397265-E7D3-47F9-B2E2-49FB444FD53C
29 | ../../Submodules/Kiwi
30 | 59CC8397-C42A-4C3C-9FF0-7F23BB915152
31 | ../../Submodules/PDKeychainBindingsController
32 | 9499EAF2-4498-47F3-8D0D-7B109B9BD5D0
33 | ../../Submodules/AFNetworking
34 | AD710768-7887-4862-9ECC-7B8F562C1700
35 | ../../Submodules/FMDB
36 | F91478D6-B52C-42BD-924C-4C00BF902D59
37 | ../../..
38 |
39 | IDESourceControlProjectURL
40 | ssh://github.com/inboxapp/inbox-ios.git
41 | IDESourceControlProjectVersion
42 | 110
43 | IDESourceControlProjectWCCIdentifier
44 | F91478D6-B52C-42BD-924C-4C00BF902D59
45 | IDESourceControlProjectWCConfigurations
46 |
47 |
48 | IDESourceControlRepositoryExtensionIdentifierKey
49 | public.vcs.git
50 | IDESourceControlWCCIdentifierKey
51 | 9499EAF2-4498-47F3-8D0D-7B109B9BD5D0
52 | IDESourceControlWCCName
53 | AFNetworking
54 |
55 |
56 | IDESourceControlRepositoryExtensionIdentifierKey
57 | public.vcs.git
58 | IDESourceControlWCCIdentifierKey
59 | AD710768-7887-4862-9ECC-7B8F562C1700
60 | IDESourceControlWCCName
61 | FMDB
62 |
63 |
64 | IDESourceControlRepositoryExtensionIdentifierKey
65 | public.vcs.git
66 | IDESourceControlWCCIdentifierKey
67 | F91478D6-B52C-42BD-924C-4C00BF902D59
68 | IDESourceControlWCCName
69 | Inbox-iOS
70 |
71 |
72 | IDESourceControlRepositoryExtensionIdentifierKey
73 | public.vcs.git
74 | IDESourceControlWCCIdentifierKey
75 | 09397265-E7D3-47F9-B2E2-49FB444FD53C
76 | IDESourceControlWCCName
77 | Kiwi
78 |
79 |
80 | IDESourceControlRepositoryExtensionIdentifierKey
81 | public.vcs.git
82 | IDESourceControlWCCIdentifierKey
83 | 59CC8397-C42A-4C3C-9FF0-7F23BB915152
84 | IDESourceControlWCCName
85 | PDKeychainBindingsController
86 |
87 |
88 |
89 |
90 |
--------------------------------------------------------------------------------
/InboxExamples/Snapmail/Snapmail/INCaptureViewController.xib:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
28 |
38 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
--------------------------------------------------------------------------------
/InboxFramework/Inbox/Models/Concrete Classes/INThread.m:
--------------------------------------------------------------------------------
1 | //
2 | // INThread.m
3 | // BigSur
4 | //
5 | // Created by Ben Gotow on 4/28/14.
6 | // Copyright (c) 2014 Inbox. All rights reserved.
7 | //
8 |
9 | #import "INThread.h"
10 | #import "INTag.h"
11 | #import "INAddRemoveTagsTask.h"
12 |
13 | @implementation INThread
14 |
15 | + (NSMutableDictionary *)resourceMapping
16 | {
17 | NSMutableDictionary * mapping = [super resourceMapping];
18 |
19 | [mapping addEntriesFromDictionary:@{
20 | @"subject": @"subject",
21 | @"participants": @"participants",
22 | @"lastMessageDate": @"last_message_timestamp",
23 | @"messageIDs": @"message_ids",
24 | @"draftIDs": @"draft_ids",
25 | @"tagIDs": @"tags",
26 | @"snippet": @"snippet"
27 | }];
28 | return mapping;
29 | }
30 |
31 | + (NSString *)resourceAPIName
32 | {
33 | return @"threads";
34 | }
35 |
36 | - (NSArray*)tags
37 | {
38 | NSMutableArray * tags = [NSMutableArray array];
39 | for (NSString * ID in [self tagIDs])
40 | [tags addObject: [INTag tagWithID: ID]];
41 | return tags;
42 | }
43 |
44 | - (void)updateWithResourceDictionary:(NSDictionary *)dict
45 | {
46 | [super updateWithResourceDictionary:dict];
47 | if ([[[self tagIDs] firstObject] isKindOfClass: [NSDictionary class]])
48 | _tagIDs = [_tagIDs valueForKey: @"id"];
49 | }
50 |
51 | - (void)setTagIDs:(NSArray *)tagIDs
52 | {
53 | NSMutableArray * unique = [NSMutableArray array];
54 | for (NSString * ID in tagIDs)
55 | if (![unique containsObject: ID])
56 | [unique addObject: ID];
57 | _tagIDs = unique;
58 | }
59 |
60 | - (BOOL)hasTagWithID:(NSString*)ID
61 | {
62 | return [[self tagIDs] containsObject: ID];
63 | }
64 |
65 | - (INMessageProvider*)newMessageProvider
66 | {
67 | return [[INMessageProvider alloc] initForMessagesInThread: [self ID] andNamespaceID:[self namespaceID]];
68 | }
69 |
70 | - (INModelProvider*)newDraftProvider
71 | {
72 | return [[INMessageProvider alloc] initForDraftsInThread:[self ID] andNamespaceID:[self namespaceID]];
73 | }
74 |
75 | #pragma mark Database
76 |
77 | + (NSArray *)databaseIndexProperties
78 | {
79 | return [[super databaseIndexProperties] arrayByAddingObjectsFromArray: @[@"lastMessageDate", @"subject"]];
80 | }
81 |
82 | + (NSArray *)databaseJoinTableProperties
83 | {
84 | return @[@"tagIDs"];
85 | }
86 |
87 | #pragma mark Operations on Threads
88 |
89 | - (void)archive
90 | {
91 | INAddRemoveTagsTask * task = [INAddRemoveTagsTask operationForModel: self];
92 | [[task tagIDsToRemove] addObject: INTagIDInbox];
93 | [[task tagIDsToAdd] addObject: INTagIDArchive];
94 | [[INAPIManager shared] queueTask: task];
95 | }
96 |
97 | - (void)unarchive
98 | {
99 | INAddRemoveTagsTask * task = [INAddRemoveTagsTask operationForModel: self];
100 | [[task tagIDsToRemove] addObject: INTagIDArchive];
101 | [[task tagIDsToAdd] addObject: INTagIDInbox];
102 | [[INAPIManager shared] queueTask: task];
103 | }
104 |
105 | - (void)star
106 | {
107 | INAddRemoveTagsTask * task = [INAddRemoveTagsTask operationForModel: self];
108 | [[task tagIDsToAdd] addObject: INTagIDStarred];
109 | [[INAPIManager shared] queueTask: task];
110 | }
111 |
112 | - (void)unstar
113 | {
114 | INAddRemoveTagsTask * task = [INAddRemoveTagsTask operationForModel: self];
115 | [[task tagIDsToRemove] addObject: INTagIDStarred];
116 | [[INAPIManager shared] queueTask: task];
117 | }
118 |
119 | - (void)markAsRead
120 | {
121 | if ([self hasTagWithID: INTagIDUnread]) {
122 | INAddRemoveTagsTask * task = [INAddRemoveTagsTask operationForModel: self];
123 | [[task tagIDsToRemove] addObject: INTagIDUnread];
124 | [[INAPIManager shared] queueTask: task];
125 | }
126 | }
127 |
128 | - (void)markAsSeen
129 | {
130 | if ([self hasTagWithID: INTagIDUnseen]) {
131 | INAddRemoveTagsTask * task = [INAddRemoveTagsTask operationForModel: self];
132 | [[task tagIDsToRemove] addObject: INTagIDUnseen];
133 | [[INAPIManager shared] queueTask: task];
134 | }
135 | }
136 |
137 | @end
138 |
--------------------------------------------------------------------------------
/InboxExamples/Snapmail/Snapmail/INContactsViewController.m:
--------------------------------------------------------------------------------
1 | //
2 | // INContactsViewController.m
3 | // BigSur
4 | //
5 | // Created by Ben Gotow on 5/5/14.
6 | // Copyright (c) 2014 Inbox. All rights reserved.
7 | //
8 |
9 | #import "INContactsViewController.h"
10 | #import "INAppDelegate.h"
11 |
12 |
13 | @implementation INContactsViewController
14 |
15 | - (id)initForSelectingContactInNamespace:(INNamespace*)ns withCallback:(ContactSelectionBlock)block;
16 | {
17 | self = [super init];
18 | if (self) {
19 | _namespace = ns;
20 | _contactSelectionCallback = block;
21 | }
22 | return self;
23 | }
24 |
25 | - (void)viewDidLoad
26 | {
27 | [super viewDidLoad];
28 |
29 | [self setTitle: @"Contacts"];
30 |
31 | UIBarButtonItem * left = [[UIBarButtonItem alloc] initWithTitle:@"Cancel" style:UIBarButtonItemStyleBordered target:self action:@selector(cancelTapped:)];
32 | [[self navigationItem] setLeftBarButtonItem: left];
33 | UIBarButtonItem * right = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed: @"send-button.png"] style:UIBarButtonItemStyleBordered target:self action:@selector(sendTapped:)];
34 | [[self navigationItem] setRightBarButtonItem: right];
35 |
36 | [_tableView setRowHeight: 50];
37 |
38 | self.contactsProvider = [self.namespace newContactProvider];
39 | [_contactsProvider setItemSortDescriptors: @[[[NSSortDescriptor alloc] initWithKey:@"name" ascending:YES]]];
40 | [_contactsProvider setDelegate:self];
41 | [_contactsProvider refresh];
42 | }
43 |
44 | - (IBAction)cancelTapped:(id)sender
45 | {
46 | [self dismissViewControllerAnimated:YES completion:NULL];
47 | }
48 |
49 | - (IBAction)sendTapped:(id)sender
50 | {
51 | if (!_contactSelectionCallback)
52 | return;
53 |
54 | NSMutableArray * contacts = [NSMutableArray array];
55 | for (NSIndexPath * ip in [_tableView indexPathsForSelectedRows]) {
56 | INContact * contact = [[_contactsProvider items] objectAtIndex: [ip row]];
57 | [contacts addObject: contact];
58 | }
59 | _contactSelectionCallback(contacts);
60 | }
61 |
62 | #pragma Provider Delegate
63 |
64 | - (void)provider:(INModelProvider*)provider dataAltered:(INModelProviderChangeSet *)changeSet
65 | {
66 | [_tableView beginUpdates];
67 | [_tableView deleteRowsAtIndexPaths:[changeSet indexPathsFor: INModelProviderChangeRemove] withRowAnimation:UITableViewRowAnimationAutomatic];
68 | [_tableView insertRowsAtIndexPaths:[changeSet indexPathsFor: INModelProviderChangeAdd] withRowAnimation:UITableViewRowAnimationAutomatic];
69 | [_tableView endUpdates];
70 | [_tableView reloadRowsAtIndexPaths:[changeSet indexPathsFor: INModelProviderChangeUpdate] withRowAnimation:UITableViewRowAnimationNone];
71 | }
72 |
73 | - (void)provider:(INModelProvider*)provider dataFetchFailed:(NSError *)error
74 | {
75 | [[[UIAlertView alloc] initWithTitle:@"Error!" message:[error localizedDescription] delegate:nil cancelButtonTitle:@"OK" otherButtonTitles: nil] show];
76 | }
77 |
78 | - (void)providerDataChanged:(INModelProvider*)provider
79 | {
80 | [_tableView reloadData];
81 | }
82 |
83 |
84 | #pragma mark Table View Data
85 |
86 | - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
87 | {
88 | return [[_contactsProvider items] count];
89 | }
90 |
91 | - (UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
92 | {
93 | UITableViewCell * cell = (UITableViewCell*)[tableView dequeueReusableCellWithIdentifier:@"contact"];
94 | if (!cell) cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:@"contact"];
95 |
96 | INContact * contact = [[_contactsProvider items] objectAtIndex: [indexPath row]];
97 | NSString * name = [contact name];
98 | if ([name length] == 0)
99 | name = [[[contact email] componentsSeparatedByString:@"@"] firstObject];
100 |
101 | [[cell textLabel] setText: name];
102 | [[cell detailTextLabel] setText: [contact email]];
103 | [[cell detailTextLabel] setTextColor: [UIColor grayColor]];
104 | return cell;
105 | }
106 |
107 | - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
108 | {
109 | }
110 |
111 |
112 | @end
113 |
--------------------------------------------------------------------------------
/InboxFramework/Inbox/Categories/NSObject+Properties.h:
--------------------------------------------------------------------------------
1 | /*
2 | * NSObject+Properties.h
3 | * AQToolkit
4 | *
5 | * Created by Jim Dovey on 10/7/2008.
6 | *
7 | * Copyright (c) 2008-2009, Jim Dovey
8 | * All rights reserved.
9 | *
10 | * Redistribution and use in source and binary forms, with or without
11 | * modification, are permitted provided that the following conditions
12 | * are met:
13 | *
14 | * Redistributions of source code must retain the above copyright notice,
15 | * this list of conditions and the following disclaimer.
16 | *
17 | * Redistributions in binary form must reproduce the above copyright
18 | * notice, this list of conditions and the following disclaimer in the
19 | * documentation and/or other materials provided with the distribution.
20 | *
21 | * Neither the name of this project's author nor the names of its
22 | * contributors may be used to endorse or promote products derived from
23 | * this software without specific prior written permission.
24 | *
25 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
26 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
27 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
28 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
29 | * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
30 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
31 | * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
32 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
33 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
34 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
35 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 | *
37 | */
38 |
39 | #import
40 | #import
41 |
42 | // type notes:
43 | // I'm not 100% certain what @encode(NSString) would return. @encode(id) returns '@',
44 | // and the types of properties are actually encoded as such along with a strong-type
45 | // value following. Therefore, if you want to check for a specific class, you can
46 | // provide a type string of '@"NSString"'. The following macro will do this for you.
47 | #define statictype(x) "@\"" #x "\""
48 |
49 | // Also, note that the runtime information doesn't include an atomicity hint, so we
50 | // can't determine that information
51 |
52 | @interface NSObject (AQProperties)
53 |
54 | + (BOOL)hasProperties;
55 | + (BOOL)hasPropertyNamed:(NSString *)name;
56 | + (BOOL)hasPropertyNamed:(NSString *)name ofType:(const char *)type; // an @encode() or statictype() type string
57 | + (NSString *)typeOfPropertyNamed:(NSString *)name; // returns an @encode() or statictype() string. Copy to keep
58 | + (SEL)getterForPropertyNamed:(NSString *)name;
59 | + (SEL)setterForPropertyNamed:(NSString *)name;
60 | + (NSString *)retentionMethodOfPropertyNamed:(NSString *)name; // returns one of: copy, retain, assign
61 | + (NSArray *)propertyNames;
62 |
63 | // instance convenience accessors for above routines (who likes to type [myObj class] all the time ?)
64 | - (BOOL)hasProperties;
65 | - (BOOL)hasPropertyNamed:(NSString *)name;
66 | - (BOOL)hasPropertyNamed:(NSString *)name ofType:(const char *)type;
67 | - (BOOL)hasPropertyForKVCKey:(NSString *)key;
68 | - (NSString *)typeOfPropertyNamed:(NSString *)name;
69 | - (SEL)getterForPropertyNamed:(NSString *)name;
70 | - (SEL)setterForPropertyNamed:(NSString *)name;
71 | - (NSString *)retentionMethodOfPropertyNamed:(NSString *)name;
72 | - (NSArray *)propertyNames;
73 |
74 | @end
75 |
76 | // Pure C API, adding to the existing API in objc/runtime.h.
77 | // The functions above are implemented in terms of these.
78 |
79 | // returns a static buffer - copy the string to retain it, as it will
80 | // be overwritten on the next call to this function
81 | NSString *property_getTypeString(objc_property_t property);
82 |
83 | // getter/setter functions: unlike those above, these will return NULL unless a getter/setter is EXPLICITLY defined
84 | SEL property_getGetter(objc_property_t property);
85 |
86 | SEL property_getSetter(objc_property_t property);
87 |
88 | // this returns a static (data-segment) string, so the caller does not need to call free() on the result
89 | const char *property_getRetentionMethod(objc_property_t property);
90 |
--------------------------------------------------------------------------------
/InboxFramework/Inbox/Models/API Calls/INSaveDraftTask.m:
--------------------------------------------------------------------------------
1 | //
2 | // INSaveDraftChange.m
3 | // InboxFramework
4 | //
5 | // Created by Ben Gotow on 5/16/14.
6 | // Copyright (c) 2014 Inbox. All rights reserved.
7 | //
8 |
9 | #import "INSaveDraftTask.h"
10 | #import "INThread.h"
11 | #import "INThread+Private.h"
12 | #import "INTag.h"
13 | #import "INDeleteDraftTask.h"
14 | #import "INSendDraftTask.h"
15 | #import "INModelObject+Uniquing.h"
16 | #import "INUploadFileTask.h"
17 |
18 | @implementation INSaveDraftTask
19 |
20 | - (BOOL)canStartAfterTask:(INAPITask *)other
21 | {
22 | if ([[other model] isEqual: self.model] && [other isKindOfClass: [INDeleteDraftTask class]])
23 | return NO;
24 | if ([[other model] isEqual: self.model] && [other isKindOfClass: [INSendDraftTask class]])
25 | return NO;
26 | return YES;
27 | }
28 |
29 | - (BOOL)canCancelPendingTask:(INAPITask*)other
30 | {
31 | if ([[other model] isEqual: self.model] && [other isKindOfClass: [INSaveDraftTask class]])
32 | return YES;
33 | return NO;
34 | }
35 |
36 | - (NSArray*)dependenciesIn:(NSArray *)others
37 | {
38 | NSMutableArray * dependencies = [NSMutableArray array];
39 | INMessage * draft = (INMessage *)[self model];
40 |
41 | // are any requests uploading files that are referenced in our draft?
42 | // we need to wait for those to finish...
43 | for (INAPITask * other in others) {
44 | if ([other isKindOfClass: [INUploadFileTask class]] && [[draft files] containsObject: [other model]])
45 | [dependencies addObject: other];
46 | }
47 |
48 | return dependencies;
49 | }
50 |
51 | - (NSURLRequest *)buildAPIRequest
52 | {
53 | NSAssert(self.model, @"INSaveDraftChange asked to buildRequest with no model!");
54 | NSAssert([self.model namespaceID], @"INSaveDraftChange asked to buildRequest with no namespace!");
55 |
56 | NSError * error = nil;
57 | NSString * path = nil;
58 |
59 | if ([self.model isUnsynced])
60 | path = [NSString stringWithFormat:@"/n/%@/drafts", [self.model namespaceID]];
61 | else
62 | path = [NSString stringWithFormat:@"/n/%@/drafts/%@", [self.model namespaceID], [self.model ID]];
63 |
64 | NSString * url = [[NSURL URLWithString:path relativeToURL:[INAPIManager shared].AF.baseURL] absoluteString];
65 | NSMutableDictionary * params = [[self.model resourceDictionary] mutableCopy];
66 | [params removeObjectForKey: @"id"];
67 | INThread * thread = [(INDraft*)self.model thread];
68 | if (thread) [params setObject:[thread ID] forKey:@"replying_to_thread"];
69 |
70 | return [[[[INAPIManager shared] AF] requestSerializer] requestWithMethod:@"POST" URLString:url parameters:params error:&error];
71 | }
72 |
73 | - (void)handleSuccess:(AFHTTPRequestOperation *)operation withResponse:(id)responseObject
74 | {
75 | if (![responseObject isKindOfClass: [NSDictionary class]])
76 | return NSLog(@"SaveDraft weird response: %@", responseObject);
77 |
78 | INDraft * draft = (INDraft *)[self model];
79 | NSString * draftInitialID = [draft ID];
80 |
81 | // remove the draft from the local cache and then update it with the API response
82 | // and save it again. This is important, because the JSON that comes back gives the
83 | // draft a different ID and we want to replace the old draft since it's outdated.
84 | [[INDatabaseManager shared] unpersistModel: draft willResaveSameModel:YES];
85 |
86 | [draft updateWithResourceDictionary: responseObject];
87 | [[INDatabaseManager shared] persistModel: draft];
88 |
89 | // if the draft ID changed, update our local cache so it has the new draft ID
90 | if (![draftInitialID isEqualToString: [draft ID]]) {
91 | INThread * thread = [draft thread];
92 | [thread removeDraftID: draftInitialID];
93 | [thread addDraftID: [draft ID]];
94 | [[INDatabaseManager shared] persistModel: thread];
95 | }
96 | }
97 |
98 | - (void)applyLocally
99 | {
100 | INDraft * draft = (INDraft *)[self model];
101 | if ([draft thread]) {
102 | INThread * thread = [draft thread];
103 | [thread addDraftID: [draft ID]];
104 | [[INDatabaseManager shared] persistModel: thread];
105 | }
106 |
107 | [[INDatabaseManager shared] persistModel: draft];
108 | }
109 |
110 | - (void)rollbackLocally
111 | {
112 | // we deliberately do not roll back draft saves. They shouldn't ever be rejected
113 | // by the server, and we don't want to loose people's data under any circumstance.
114 | }
115 |
116 | @end
117 |
--------------------------------------------------------------------------------
/InboxExamples/Snapmail/Snapmail/INSnapViewController.xib:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
41 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
--------------------------------------------------------------------------------
/InboxFramework/Inbox/Models/Concrete Classes/INDraft.h:
--------------------------------------------------------------------------------
1 | //
2 | // INDraft.h
3 | // InboxFramework
4 | //
5 | // Created by Ben Gotow on 5/22/14.
6 | // Copyright (c) 2014 Inbox. All rights reserved.
7 | //
8 |
9 | #import "INMessage.h"
10 | #import "INFile.h"
11 |
12 | typedef enum : NSUInteger {
13 | INDraftStateUnsent,
14 | INDraftStateSending,
15 | INDraftStateSendingFailed,
16 | INDraftStateSent
17 | } INDraftState;
18 |
19 | /**
20 | Drafts are messages that may be sent, saved, and deleted. You can create new drafts
21 | using one of the designated initializers, save them, add files, and send them using
22 | the methods documented below. The Inbox framework takes care of persisting pending
23 | draft operations, ensuring that -save, -send and other methods are eventually persistent,
24 | even if they are called when the user is offline.
25 |
26 | To list drafts available in a namespace, retrieve an INMessageProvider from the namespace.
27 |
28 | Drafts receive a new ID each time they are saved. If your application is presenting a draft,
29 | be prepared for the draft's ID to change after calls to -save. You can monitor changes all
30 | Inbox objects by subscribing to INModelObjectChangedNotification.
31 | */
32 | @interface INDraft : INMessage
33 |
34 | @property (nonatomic, strong) NSString * version;
35 | @property (nonatomic, strong) NSString * internalState;
36 |
37 | /*
38 | Initialize a new draft for sending a new message in the specified namespace.
39 | @return An initalized instance of INDraft
40 | */
41 | - (id)initInNamespace:(INNamespace*)namespace;
42 |
43 | /*
44 | Initialize a new draft for replying to an existing thread. It's important to use
45 | this initializer when replying so the Inbox API can properly append the draft to
46 | the existing thread.
47 |
48 | @param The namespace to create the draft in
49 | @param The thread that this draft is being created in reply to.
50 | @return An initalized instance of INDraft
51 | */
52 | - (id)initInNamespace:(INNamespace*)namespace inReplyTo:(INThread*)thread;
53 |
54 | /**
55 | Add a file to the thread. The file does not need to be fully uploaded
56 | to be attached to a draft. However, you should call [INFile upload] to start
57 | the upload process before adding the file to the draft.
58 |
59 | If files are still uploading when you call -save, the draft will not be
60 | saved to the server until files have finished uploading.
61 |
62 | @param file The INFile object to add to the draft.
63 | */
64 | - (void)addFile:(INFile*)file;
65 |
66 | /**
67 | Add a file to the thread at a particular index.
68 | @param file The INFile object to add to the draft.
69 | @param index The index where the draft should be attached.
70 | */
71 | - (void)addFile:(INFile*)file atIndex:(NSInteger)index;
72 |
73 | /**
74 | Remove the provided file from the draft. Note that you need to call -save
75 | to commit your changes to Inbox after modifying the draft.
76 |
77 | @param file The file to remove from the draft.
78 | */
79 | - (void)removeFile:(INFile*)file;
80 |
81 | /**
82 | Remove the provided file from the draft. Note that you need to call -save
83 | to commit your changes to Inbox after modifying the draft.
84 |
85 | @param index The index of the file to remove from the draft.
86 | */
87 | - (void)removeFileAtIndex:(NSInteger)index;
88 |
89 | /**
90 | Called internally when an file has finished uploading and it's ID has changed.
91 | @param ID The ID that was initially assigned to the INFile.
92 | @param uploadedID The ID assigned by the server that now represents the INFile.
93 | */
94 | - (void)fileWithID:(NSString*)ID uploadedAs:(NSString*)uploadedID;
95 |
96 | /**
97 | The current state of the draft. See INDraftState for a list of available states.
98 | */
99 | - (INDraftState)state;
100 |
101 | #pragma mark Operations on Drafts
102 |
103 | /**
104 | Save the draft. This method updates the local cache to reflect
105 | the change immediately but may be performed later on the Inbox server if an internet
106 | connection is not available.
107 |
108 | If you've added files to the draft and files are still uploading, the
109 | draft will not be saved to the server until file uploads are complete.
110 | */
111 | - (void)save;
112 |
113 | /**
114 | Send the draft. This method is eventually persistent and may
115 | be performed later if an internet connection is not available.
116 |
117 | Drafts will not be sent until all pending saves are complete and files have
118 | been uploaded. It's safe to call -save and -send back to back
119 | */
120 | - (void)send;
121 |
122 | /**
123 | Delete the draft. This method updates the local cache to reflect
124 | the change immediately but may be performed later on the Inbox server if an internet
125 | connection is not available.
126 |
127 | Deleting a draft will cancel any pending save or send operations.
128 | */
129 | - (void)delete;
130 |
131 | @end
132 |
--------------------------------------------------------------------------------
/InboxFramework/Inbox/Models/Concrete Classes/INDraft.m:
--------------------------------------------------------------------------------
1 | //
2 | // INDraft.m
3 | // InboxFramework
4 | //
5 | // Created by Ben Gotow on 5/22/14.
6 | // Copyright (c) 2014 Inbox. All rights reserved.
7 | //
8 |
9 | #import "INDraft.h"
10 | #import "INNamespace.h"
11 | #import "INThread.h"
12 | #import "INSaveDraftTask.h"
13 | #import "INSendDraftTask.h"
14 | #import "INDeleteDraftTask.h"
15 | #import "INUploadFileTask.h"
16 |
17 | @implementation INDraft
18 |
19 | + (NSMutableDictionary *)resourceMapping
20 | {
21 | NSMutableDictionary * mapping = [super resourceMapping];
22 | [mapping addEntriesFromDictionary:@{ @"internalState": @"state", @"version": @"version" }];
23 | return mapping;
24 | }
25 |
26 | + (NSString *)resourceAPIName
27 | {
28 | return @"drafts";
29 | }
30 |
31 | - (id)initInNamespace:(INNamespace*)namespace
32 | {
33 | NSAssert(namespace, @"initInNamespace: called with a nil namespace.");
34 | self = [super init];
35 | if (self) {
36 | [self setFrom: @[@{@"email": [namespace emailAddress], @"name": [namespace emailAddress]}]];
37 | [self setNamespaceID: [namespace ID]];
38 | [self setDate: [NSDate date]];
39 | }
40 | return self;
41 | }
42 |
43 | - (id)initInNamespace:(INNamespace*)namespace inReplyTo:(INThread*)thread
44 | {
45 | NSAssert(namespace, @"initInNamespace: called with a nil namespace.");
46 | NSAssert([thread isUnsynced] == NO, @"It looks like you're creating a new draft on a new thread. Instead of creating an INThread and then creating a draft on that thread, just create a new draft with [INDraft initInNamespace:]. A new thread will be created automatically when you send the draft!");
47 |
48 | self = [self initInNamespace: namespace];
49 | if (self) {
50 | NSMutableDictionary * recipients = [NSMutableDictionary dictionary];
51 | for (NSDictionary * recipient in [thread participants]) {
52 | BOOL isMe = [[[INAPIManager shared] namespaceEmailAddresses] containsObject: recipient[@"email"]];
53 | if (!isMe)
54 | [recipients setObject: recipient forKey: recipient[@"email"]];
55 | }
56 | [self setTo: [recipients allValues]];
57 | [self setSubject: thread.subject];
58 | [self setThreadID: [thread ID]];
59 | }
60 | return self;
61 | }
62 |
63 | - (void)addFile:(INFile*)file
64 | {
65 | [self addFile:file atIndex:0];
66 | }
67 |
68 | - (void)addFile:(INFile*)file atIndex:(NSInteger)index
69 | {
70 | NSMutableArray * files = [self.files mutableCopy];
71 | if (!files) files = [NSMutableArray array];
72 | if (![files containsObject: file])
73 | [files insertObject:file atIndex: index];
74 | self.files = files;
75 |
76 | if ([file isUnsynced]) {
77 | if (![file uploadTask])
78 | [file upload];
79 |
80 | // we can't save with this file ID. Find the file upload task
81 | // and tell it to update us when the draft upload has finished.
82 | [[[file uploadTask] waitingDrafts] addObject: self];
83 | }
84 | }
85 |
86 | - (void)removeFile:(INFile*)file
87 | {
88 | NSMutableArray * files = [self.files mutableCopy];
89 | [files removeObject: file];
90 | self.files = files;
91 |
92 | [[[file uploadTask] waitingDrafts] removeObject: self];
93 | }
94 |
95 | - (void)removeFileAtIndex:(NSInteger)index
96 | {
97 | [self removeFile: [self.files objectAtIndex: index]];
98 | }
99 |
100 | - (void)fileWithID:(NSString*)ID uploadedAs:(NSString*)uploadedID
101 | {
102 | // No longer necessary, since the files array references the same
103 | // INFile objects that are being modified. Not refactoring this away
104 | // completely, because it may be useful in the future.
105 | }
106 |
107 | - (INDraftState)state
108 | {
109 | if ([_internalState isEqualToString: @"sending"])
110 | return INDraftStateSending;
111 | else if ([_internalState isEqualToString: @"sending_failed"])
112 | return INDraftStateSendingFailed;
113 | else if ([_internalState isEqualToString: @"sent"])
114 | return INDraftStateSent;
115 | return INDraftStateUnsent;
116 | }
117 |
118 | #pragma mark Operations on Drafts
119 |
120 | - (void)save
121 | {
122 | INSaveDraftTask * save = [INSaveDraftTask operationForModel: self];
123 | [[INAPIManager shared] queueTask: save];
124 | }
125 |
126 | - (void)send
127 | {
128 | // Always save before sending, so the API consumer doesn't have to worry about it.
129 | // If they call -save themselves, this new INSaveDraftTask should invalidate the
130 | // other one and prevent a duplicate save anyway.
131 | [self save];
132 |
133 | INSendDraftTask * send = [INSendDraftTask operationForModel: self];
134 | [[INAPIManager shared] queueTask: send];
135 | }
136 |
137 | - (void)delete
138 | {
139 | INDeleteDraftTask * delete = [INDeleteDraftTask operationForModel: self];
140 | [[INAPIManager shared] queueTask: delete];
141 | }
142 |
143 | @end
144 |
--------------------------------------------------------------------------------
/InboxFramework/Inbox/Models/Concrete Classes/INThread.h:
--------------------------------------------------------------------------------
1 | //
2 | // INThread.h
3 | // BigSur
4 | //
5 | // Created by Ben Gotow on 4/28/14.
6 | // Copyright (c) 2014 Inbox. All rights reserved.
7 | //
8 |
9 | #import "INModelObject.h"
10 | #import "INModelProvider.h"
11 | #import "INMessageProvider.h"
12 | #import "INMessage.h"
13 | #import "INDraft.h"
14 |
15 | @class INTag;
16 |
17 | /** The INThread class provides a native wrapper around Inbox threads
18 | http://inboxapp.com/docs/api#threads
19 |
20 | Threads are the central object of the Inbox API and the INThread class
21 | provides convenience methods for performing many actions, such as tagging,
22 | archiving, and deleting threads.
23 |
24 | You should not create instances of INThread directly. Instead, obtain an
25 | INNamespace object (representing an email account) and use an INThreadProvider:
26 |
27 | NSPredicate * unread = [NSComparisonPredicate predicateWithFormat:@"ANY tagIDs = %@", INTagIDUnread];
28 | INNamespace * namespace = [[[INAPIManager shared] namespaces] firstObject];
29 | self.threadProvider = [namespace newThreadProvider];
30 | self.threadProvider.itemFilterPredicate = unread;
31 | self.threadProvider.delegate = self;
32 |
33 | // Implement the INModelProviderDelegate protocol to get threads
34 |
35 | If you're looking to create a new thread, see INDraft.
36 | */
37 | @interface INThread : INModelObject
38 |
39 | @property (nonatomic, strong) NSString * subject;
40 | @property (nonatomic, strong) NSString * snippet;
41 | @property (nonatomic, strong) NSArray * participants;
42 | @property (nonatomic, strong) NSDate * lastMessageDate;
43 | @property (nonatomic, strong) NSArray * messageIDs;
44 | @property (nonatomic, strong) NSArray * draftIDs;
45 | @property (nonatomic, strong) NSArray * tagIDs;
46 | @property (nonatomic, assign) BOOL unread;
47 |
48 | /*
49 | @return An array of INTag objects for the tags on this thread.
50 | */
51 | - (NSArray*)tags;
52 |
53 | /*
54 | @return An array of NSString tag IDs for the tags on this thread.
55 | */
56 | - (NSArray*)tagIDs;
57 |
58 | /*
59 | @param ID The ID to check for.
60 | @return YES if this thread has a tag with the given ID.
61 | */
62 | - (BOOL)hasTagWithID:(NSString*)ID;
63 |
64 | /**
65 | Initializes and returns a new INModelProvider for displaying messages in this thread.
66 | To further filter the messages (for example, to show just messages with attachments in
67 | the thread), you can set the itemFilterPredicate on the returned provider.
68 |
69 | @return An initialized INModelProvider for displaying messages.
70 | */
71 | - (INMessageProvider*)newMessageProvider;
72 |
73 | /**
74 | Initializes and returns a new INModelProvider for displaying drafts on this thread.
75 | @return An initialized INModelProvider for displaying drafts.
76 | */
77 | - (INMessageProvider*)newDraftProvider;
78 |
79 | #pragma mark Operations on Threads
80 |
81 | /**
82 | Archive the thread. This method updates the local cache to reflect the change
83 | immediately but may be performed later on the Inbox server if an internet
84 | connection is not available.
85 | */
86 | - (void)archive;
87 |
88 | /**
89 | Unarchive the thread. This method updates the local cache to reflect the change
90 | immediately but may be performed later on the Inbox server if an internet
91 | connection is not available.
92 | */
93 | - (void)unarchive;
94 |
95 | /**
96 | Mark this thread as read. This method removes the 'unread' tag, and marks every
97 | message in the thread as read. If the thread does not have the unread tag, it
98 | has no effect.
99 |
100 | This method updates the local cache to reflect the change immediately but may be
101 | performed later on the Inbox server if an internet connection is not available.
102 | */
103 | - (void)markAsRead;
104 |
105 | /**
106 | Mark this thread as seen. You should mark threads as "seen" as soon as the user
107 | views any part of the thread, or sees the thread subject and snippet onscreen.
108 | This indicates that the user has seen the thread and the thread should not be
109 | presented as "new" from another device or application. If the thread does not have
110 | the unseen tag, this method has no effect.
111 |
112 | Your application should use the unseen tag, rather than the unread tag, to highlight
113 | new threads the user may be interested in.
114 |
115 | Additional notes:
116 | - Threads become "unseen" again if new messages arrive in the thread.
117 | - Threads become seen automatically if you mark any of their messages as read.
118 |
119 | This method updates the local cache to reflect the change immediately but may be
120 | performed later on the Inbox server if an internet connection is not available.
121 | */
122 | - (void)markAsSeen;
123 |
124 | /**
125 | Star the thread. On some email platforms, this is known as 'flagging'.
126 |
127 | This method updates the local cache to reflect the change immediately but may be
128 | performed later on the Inbox server if an internet connection is not available.
129 | */
130 | - (void)star;
131 |
132 | /**
133 | Unstar the thread. On some email platforms, this is known as 'unflagging'.
134 |
135 | This method updates the local cache to reflect the change immediately but may be
136 | performed later on the Inbox server if an internet connection is not available.
137 | */
138 | - (void)unstar;
139 |
140 |
141 | @end
142 |
--------------------------------------------------------------------------------
/InboxFramework/Inbox/Models/API Calls/INAddRemoveTagsTask.m:
--------------------------------------------------------------------------------
1 | //
2 | // INAddRemoveTagsChange.m
3 | // InboxFramework
4 | //
5 | // Created by Ben Gotow on 5/16/14.
6 | // Copyright (c) 2014 Inbox. All rights reserved.
7 | //
8 |
9 | #import "INSaveTagTask.h"
10 | #import "INAddRemoveTagsTask.h"
11 | #import "INThread.h"
12 | #import "INMessage.h"
13 | #import "INTag.h"
14 |
15 | @implementation INAddRemoveTagsTask
16 |
17 |
18 | - (NSMutableArray *)tagIDsToAdd
19 | {
20 | if (!self.data[@"tagIDsToAdd"])
21 | [self.data setObject: [NSMutableArray array] forKey:@"tagIDsToAdd"];
22 | return self.data[@"tagIDsToAdd"];
23 | }
24 |
25 | - (NSMutableArray *)tagIDsToRemove
26 | {
27 | if (!self.data[@"tagIDsToRemove"])
28 | [self.data setObject: [NSMutableArray array] forKey:@"tagIDsToRemove"];
29 | return self.data[@"tagIDsToRemove"];
30 | }
31 |
32 | - (NSMutableArray *)tagIDStringsToAdd
33 | {
34 | NSMutableArray * tagIDStrings = [NSMutableArray array];
35 | for (NSObject * tag in [self tagIDsToAdd]) {
36 | if ([tag isKindOfClass: [INTag class]]) {
37 | [tagIDStrings addObject: [(INTag*)tag ID]];
38 | } else {
39 | [tagIDStrings addObject: (NSString*)tag];
40 | }
41 | }
42 | return tagIDStrings;
43 | }
44 |
45 | - (NSMutableArray *)tagIDStringsToRemove
46 | {
47 | NSMutableArray * tagIDStrings = [NSMutableArray array];
48 | for (NSObject * tag in [self tagIDsToRemove]) {
49 | if ([tag isKindOfClass: [INTag class]]) {
50 | [tagIDStrings addObject: [(INTag*)tag ID]];
51 | } else {
52 | [tagIDStrings addObject: (NSString*)tag];
53 | }
54 | }
55 | return tagIDStrings;
56 | }
57 |
58 | - (INThread*)thread
59 | {
60 | if ([self.model isKindOfClass: [INThread class]])
61 | return (INThread*)self.model;
62 | if ([self.model isKindOfClass: [INMessage class]])
63 | return [(INMessage*)self.model thread];
64 | return nil;
65 | }
66 |
67 | - (NSURLRequest *)buildAPIRequest
68 | {
69 | NSAssert([self thread], @"INSaveDraftChange asked to buildRequest with no access to a thread model!");
70 | NSAssert([[self thread] namespaceID], @"INSaveDraftChange asked to buildRequest with no namespace!");
71 |
72 | NSError * error = nil;
73 | NSString * path = [[self thread] resourceAPIPath];
74 | NSString * url = [[NSURL URLWithString:path relativeToURL:[INAPIManager shared].AF.baseURL] absoluteString];
75 |
76 | NSMutableDictionary * params = [NSMutableDictionary dictionary];
77 | [params setObject:[self tagIDStringsToAdd] forKey:@"add_tags"];
78 | [params setObject:[self tagIDStringsToRemove] forKey:@"remove_tags"];
79 |
80 | return [[[[INAPIManager shared] AF] requestSerializer] requestWithMethod:@"PUT" URLString:url parameters:params error:&error];
81 | }
82 |
83 | - (void)applyLocally
84 | {
85 | NSMutableArray * newTagIDs = [NSMutableArray arrayWithArray: [[self thread] tagIDs]];
86 | [newTagIDs addObjectsFromArray: self.tagIDStringsToAdd];
87 | [newTagIDs removeObjectsInArray: self.tagIDStringsToRemove];
88 | [[self thread] setTagIDs: newTagIDs];
89 | [[INDatabaseManager shared] persistModel: [self thread]];
90 | }
91 |
92 | - (void)rollbackLocally
93 | {
94 | NSMutableArray * newTagIDs = [NSMutableArray arrayWithArray: [[self thread] tagIDs]];
95 | [newTagIDs removeObjectsInArray: self.tagIDStringsToAdd];
96 | [newTagIDs addObjectsFromArray: self.tagIDStringsToRemove];
97 | [[self thread] setTagIDs: newTagIDs];
98 | [[INDatabaseManager shared] persistModel: [self thread]];
99 | }
100 |
101 | - (void)handleSuccess:(AFHTTPRequestOperation *)operation withResponse:(id)responseObject
102 | {
103 | if ([responseObject isKindOfClass: [NSDictionary class]]) {
104 | [[self thread] updateWithResourceDictionary: responseObject];
105 | [[INDatabaseManager shared] persistModel: [self thread]];
106 | }
107 | }
108 |
109 | - (BOOL)canCancelPendingTask:(INAPITask*)other
110 | {
111 | if ([[other model] isEqual: self.model] && [other isKindOfClass: [INAddRemoveTagsTask class]]) {
112 | INAddRemoveTagsTask * otherTask = (INAddRemoveTagsTask*)other;
113 |
114 | // do we add ALL the tags 'other' is removing?
115 | BOOL invalidatesRemoved = [[NSSet setWithArray: [otherTask tagIDStringsToRemove]] isSubsetOfSet:[NSSet setWithArray: [self tagIDStringsToAdd]]];
116 |
117 | // do we remove ALL the tags 'other' is adding?
118 | BOOL invalidatesAdded = [[NSSet setWithArray: [otherTask tagIDStringsToAdd]] isSubsetOfSet:[NSSet setWithArray: [self tagIDStringsToRemove]]];
119 |
120 | // if we do both, we effectively null the effect of this operation
121 | return invalidatesRemoved && invalidatesAdded;
122 | }
123 | return NO;
124 | }
125 |
126 | - (NSArray *)dependenciesIn:(NSArray *)others
127 | {
128 | NSMutableArray * dependencies = [NSMutableArray array];
129 | for (INAPITask * other in others) {
130 | if (other == self) {
131 | continue;
132 | }
133 | if ([other isKindOfClass: [INSaveTagTask class]] && [[NSSet setWithArray:[self tagIDStringsToAdd]] containsObject:[[other model] ID]]) {
134 | [dependencies addObject: other];
135 | }
136 | }
137 | return dependencies;
138 | }
139 |
140 |
141 | @end
142 |
--------------------------------------------------------------------------------