├── .gitignore ├── .settings └── launch.json ├── .travis.yml ├── EmailPeek.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ └── contents.xcworkspacedata └── xcshareddata │ └── xcschemes │ └── EmailPeek.xcscheme ├── EmailPeek.xcworkspace └── contents.xcworkspacedata ├── EmailPeek ├── AboutViewController.h ├── AboutViewController.m ├── AppDelegate.h ├── AppDelegate.m ├── Conversation.h ├── Conversation.m ├── ConversationFilter.h ├── ConversationFilter.m ├── ConversationFilterListViewController.h ├── ConversationFilterListViewController.m ├── ConversationListViewController.h ├── ConversationListViewController.m ├── ConversationManager.h ├── ConversationManager.m ├── ConversationViewController.h ├── ConversationViewController.m ├── EmailAddress.h ├── EmailAddress.m ├── Images.xcassets │ ├── AppIcon.appiconset │ │ ├── Contents.json │ │ ├── app120.png │ │ ├── app152.png │ │ ├── app180.png │ │ └── app76.png │ ├── attachment_icon.imageset │ │ ├── Contents.json │ │ ├── clippy22.png │ │ ├── clippy44.png │ │ └── clippy66.png │ ├── settings_icon.imageset │ │ ├── Contents.json │ │ ├── app22.png │ │ ├── app44.png │ │ └── app66.png │ └── urgent_icon.imageset │ │ ├── Contents.json │ │ ├── bang22-1.png │ │ ├── bang22.png │ │ └── bang66.png ├── ImportanceFilter.h ├── ImportanceFilter.m ├── Info.plist ├── Main.storyboard ├── Message.h ├── Message.m ├── MessageAttachment.h ├── MessageAttachment.m ├── MessageDetail.h ├── MessageDetail.m ├── MessageFilter.h ├── MessagePreview.h ├── MessagePreviewCell.h ├── MessagePreviewCell.m ├── MessagePreviewCell.xib ├── MessageViewController.h ├── MessageViewController.m ├── NSDate+Office365.h ├── NSDate+Office365.m ├── NothingFilter.h ├── NothingFilter.m ├── Office365Client.h ├── Office365Client.m ├── Office365ObjectTransformer.h ├── Office365ObjectTransformer.m ├── SenderFilter.h ├── SenderFilter.m ├── SenderFilterListViewController.h ├── SenderFilterListViewController.m ├── SettingsManager.h ├── SettingsManager.m ├── SettingsViewController.h ├── SettingsViewController.m ├── UIColor+Office365.h ├── UIColor+Office365.m ├── UnreadFilter.h ├── UnreadFilter.m ├── about.html └── main.m ├── EmailPeekTests ├── EmailPeekTests.m └── Info.plist ├── O365-iOS-EmailPeek.yml ├── Podfile ├── README-Localized ├── README-de-de.md ├── README-es-es.md ├── README-fr-fr.md ├── README-ja-jp.md ├── README-pt-br.md ├── README-ru-ru.md └── README-zh-tw.md ├── README.md └── readme-images └── emailpeek_video.png /.gitignore: -------------------------------------------------------------------------------- 1 | # Created by https://www.gitignore.io 2 | 3 | ### Xcode ### 4 | build/ 5 | *.pbxuser 6 | !default.pbxuser 7 | *.mode1v3 8 | !default.mode1v3 9 | *.mode2v3 10 | !default.mode2v3 11 | *.perspectivev3 12 | !default.perspectivev3 13 | xcuserdata 14 | *.xccheckout 15 | *.moved-aside 16 | DerivedData 17 | *.xcuserstate 18 | 19 | 20 | ### Objective-C ### 21 | # Xcode 22 | # 23 | build/ 24 | *.pbxuser 25 | !default.pbxuser 26 | *.mode1v3 27 | !default.mode1v3 28 | *.mode2v3 29 | !default.mode2v3 30 | *.perspectivev3 31 | !default.perspectivev3 32 | xcuserdata 33 | *.xccheckout 34 | *.moved-aside 35 | DerivedData 36 | *.hmap 37 | *.ipa 38 | *.xcuserstate 39 | 40 | # CocoaPods 41 | # 42 | Pods/ 43 | *Podfile.lock 44 | 45 | ### OSX ### 46 | .DS_Store 47 | .AppleDouble 48 | .LSOverride 49 | 50 | # Icon must end with two \r 51 | Icon 52 | 53 | 54 | # Thumbnails 55 | ._* 56 | 57 | # Files that might appear in the root of a volume 58 | .DocumentRevisions-V100 59 | .fseventsd 60 | .Spotlight-V100 61 | .TemporaryItems 62 | .Trashes 63 | .VolumeIcon.icns 64 | 65 | # Directories potentially created on remote AFP share 66 | .AppleDB 67 | .AppleDesktop 68 | Network Trash Folder 69 | Temporary Items 70 | .apdisk 71 | -------------------------------------------------------------------------------- /.settings/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.1.0", 3 | // List of configurations. Add new configurations or edit existing ones. 4 | // ONLY "node" and "mono" are supported, change "type" to switch. 5 | "configurations": [ 6 | { 7 | // Name of configuration; appears in the launch configuration drop down menu. 8 | "name": "Launch app.js", 9 | // Type of configuration. Possible values: "node", "mono". 10 | "type": "node", 11 | // Workspace relative or absolute path to the program. 12 | "program": "app.js", 13 | // Automatically stop program after launch. 14 | "stopOnEntry": true, 15 | // Command line arguments passed to the program. 16 | "args": [], 17 | // Workspace relative or absolute path to the working directory of the program being debugged. Default is the current workspace. 18 | "cwd": ".", 19 | // Workspace relative or absolute path to the runtime executable to be used. Default is the runtime executable on the PATH. 20 | "runtimeExecutable": null, 21 | // Environment variables passed to the program. 22 | "env": { } 23 | }, 24 | { 25 | "name": "Attach", 26 | "type": "node", 27 | // TCP/IP address. Default is "localhost". 28 | "address": "localhost", 29 | // Port to attach to. 30 | "port": 5858 31 | } 32 | ] 33 | } 34 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: objective-c 2 | osx_image: xcode7 3 | xcode_workspace: EmailPeek.xcworkspace 4 | xcode_scheme: EmailPeek 5 | script: 6 | - xctool -workspace EmailPeek.xcworkspace -scheme EmailPeek -sdk iphonesimulator 7 | notifications: 8 | slack: 9 | secure: MMzMQpLUr1pbKLNUek+5q4Z1SROBeGgr+kyP6MeSywTFRODKISt+nBEK2betlZ/Qc8i+tz/iOPOik8W71ijg5vWUygGBEyZjng72H9MwTV46bzAKWC5uHR7pf4sZmlsmZ4iEp9hXxmS6MDqUL/YkK2Dwa1xzgYPeSmF4Nr3Cm/0= 10 | email: 11 | recipients: 12 | - jak@microsoft.com 13 | on_success: never 14 | on_failure: always 15 | -------------------------------------------------------------------------------- /EmailPeek.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /EmailPeek.xcodeproj/xcshareddata/xcschemes/EmailPeek.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 29 | 35 | 36 | 37 | 38 | 39 | 44 | 45 | 47 | 53 | 54 | 55 | 56 | 57 | 63 | 64 | 65 | 66 | 75 | 77 | 83 | 84 | 85 | 86 | 87 | 88 | 94 | 96 | 102 | 103 | 104 | 105 | 107 | 108 | 111 | 112 | 113 | -------------------------------------------------------------------------------- /EmailPeek.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /EmailPeek/AboutViewController.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Microsoft. All rights reserved. Licensed under the MIT license. 3 | * See full license at the bottom of this file. 4 | */ 5 | 6 | #import 7 | 8 | @interface AboutViewController : UIViewController 9 | 10 | @end 11 | 12 | // ********************************************************* 13 | // 14 | // O365-iOS-EmailPeek, https://github.com/OfficeDev/O365-iOS-EmailPeek 15 | // 16 | // Copyright (c) Microsoft Corporation 17 | // All rights reserved. 18 | // 19 | // MIT License: 20 | // Permission is hereby granted, free of charge, to any person obtaining 21 | // a copy of this software and associated documentation files (the 22 | // "Software"), to deal in the Software without restriction, including 23 | // without limitation the rights to use, copy, modify, merge, publish, 24 | // distribute, sublicense, and/or sell copies of the Software, and to 25 | // permit persons to whom the Software is furnished to do so, subject to 26 | // the following conditions: 27 | // 28 | // The above copyright notice and this permission notice shall be 29 | // included in all copies or substantial portions of the Software. 30 | // 31 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 32 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 33 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 34 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 35 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 36 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 37 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 38 | // 39 | // ********************************************************* -------------------------------------------------------------------------------- /EmailPeek/AboutViewController.m: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Microsoft. All rights reserved. Licensed under the MIT license. 3 | * See full license at the bottom of this file. 4 | */ 5 | 6 | #import "AboutViewController.h" 7 | 8 | static NSString * const kAboutEmailPeekFileName = @"about.html"; 9 | 10 | @interface AboutViewController () 11 | 12 | @property (weak, nonatomic) IBOutlet UIWebView *webView; 13 | 14 | @end 15 | 16 | @implementation AboutViewController 17 | 18 | - (void)viewDidLoad 19 | { 20 | [super viewDidLoad]; 21 | 22 | NSURL *aboutURL = [[NSBundle mainBundle] URLForResource:kAboutEmailPeekFileName 23 | withExtension:nil]; 24 | NSURLRequest *aboutRequest = [NSURLRequest requestWithURL:aboutURL]; 25 | 26 | [self.webView loadRequest:aboutRequest]; 27 | } 28 | 29 | @end 30 | 31 | // ********************************************************* 32 | // 33 | // O365-iOS-EmailPeek, https://github.com/OfficeDev/O365-iOS-EmailPeek 34 | // 35 | // Copyright (c) Microsoft Corporation 36 | // All rights reserved. 37 | // 38 | // MIT License: 39 | // Permission is hereby granted, free of charge, to any person obtaining 40 | // a copy of this software and associated documentation files (the 41 | // "Software"), to deal in the Software without restriction, including 42 | // without limitation the rights to use, copy, modify, merge, publish, 43 | // distribute, sublicense, and/or sell copies of the Software, and to 44 | // permit persons to whom the Software is furnished to do so, subject to 45 | // the following conditions: 46 | // 47 | // The above copyright notice and this permission notice shall be 48 | // included in all copies or substantial portions of the Software. 49 | // 50 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 51 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 52 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 53 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 54 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 55 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 56 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 57 | // 58 | // ********************************************************* -------------------------------------------------------------------------------- /EmailPeek/AppDelegate.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Microsoft. All rights reserved. Licensed under the MIT license. 3 | * See full license at the bottom of this file. 4 | */ 5 | 6 | #import 7 | 8 | @interface AppDelegate : UIResponder 9 | 10 | @property (strong, nonatomic) UIWindow *window; 11 | 12 | @end 13 | 14 | // ********************************************************* 15 | // 16 | // O365-iOS-EmailPeek, https://github.com/OfficeDev/O365-iOS-EmailPeek 17 | // 18 | // Copyright (c) Microsoft Corporation 19 | // All rights reserved. 20 | // 21 | // MIT License: 22 | // Permission is hereby granted, free of charge, to any person obtaining 23 | // a copy of this software and associated documentation files (the 24 | // "Software"), to deal in the Software without restriction, including 25 | // without limitation the rights to use, copy, modify, merge, publish, 26 | // distribute, sublicense, and/or sell copies of the Software, and to 27 | // permit persons to whom the Software is furnished to do so, subject to 28 | // the following conditions: 29 | // 30 | // The above copyright notice and this permission notice shall be 31 | // included in all copies or substantial portions of the Software. 32 | // 33 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 34 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 35 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 36 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 37 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 38 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 39 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 40 | // 41 | // ********************************************************* 42 | -------------------------------------------------------------------------------- /EmailPeek/AppDelegate.m: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Microsoft. All rights reserved. Licensed under the MIT license. 3 | * See full license at the bottom of this file. 4 | */ 5 | 6 | #import "AppDelegate.h" 7 | 8 | #import "UIColor+Office365.h" 9 | #import "Office365Client.h" 10 | #import "SettingsManager.h" 11 | #import "ConversationManager.h" 12 | 13 | #import "ConversationListViewController.h" 14 | #import "MessageViewController.h" 15 | 16 | // You will set your application's clientId and redirect URI. You get 17 | // these when you register your application in Azure AD. 18 | static NSString * const kClientId = @"ENTER_REDIRECT_URI_HERE"; 19 | static NSString * const kRedirectURLString = @"ENTER_CLIENT_ID_HERE"; 20 | static NSString * const kAuthorityURLString = @"https://login.microsoftonline.com/common"; 21 | 22 | @interface AppDelegate () 23 | 24 | @property (strong, nonatomic) UIApplication *application; 25 | @property (strong, nonatomic) Office365Client *office365Client; 26 | @property (strong, nonatomic) SettingsManager *settingsManager; 27 | @property (strong, nonatomic) ConversationManager *conversationManager; 28 | 29 | @end 30 | 31 | @implementation AppDelegate 32 | 33 | - (BOOL) application:(UIApplication *)application 34 | didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 35 | { 36 | self.window.tintColor = [UIColor o365_primaryColor]; 37 | 38 | self.application = application; 39 | 40 | self.settingsManager = [[SettingsManager alloc] init]; 41 | [self.settingsManager reload]; 42 | 43 | self.office365Client = [[Office365Client alloc] initWithClientId:kClientId 44 | redirectURL:[NSURL URLWithString:kRedirectURLString] 45 | authorityURL:[NSURL URLWithString:kAuthorityURLString]]; 46 | 47 | self.conversationManager = [[ConversationManager alloc] init]; 48 | self.conversationManager.office365Client = self.office365Client; 49 | self.conversationManager.settingsManager = self.settingsManager; 50 | self.conversationManager.application = application; 51 | 52 | // Pull out the starting view controllers to configure them 53 | UISplitViewController *splitVC = (UISplitViewController *)self.window.rootViewController; 54 | UINavigationController *navigationVC = splitVC.viewControllers[0]; 55 | ConversationListViewController *conversationListVC = navigationVC.viewControllers[0]; 56 | 57 | // Configure the split view controller 58 | splitVC.delegate = self; 59 | splitVC.preferredDisplayMode = UISplitViewControllerDisplayModeAllVisible; 60 | 61 | // Pass the context to the starting view controller 62 | conversationListVC.conversationManager = self.conversationManager; 63 | NSNotificationCenter *notificationCenter = self.conversationManager.notificationCenter; 64 | [notificationCenter addObserver:self 65 | selector:@selector(allConversationsDidChange:) 66 | name:ConversationManagerAllConversationsDidChangeNotification 67 | object:self.conversationManager]; 68 | 69 | [self registerForLocalNotifications]; 70 | 71 | return YES; 72 | } 73 | 74 | - (void)applicationDidBecomeActive:(UIApplication *)application 75 | { 76 | if (self.office365Client.isConnected) { 77 | [self.conversationManager refreshAllConversations]; 78 | } 79 | } 80 | 81 | - (void)applicationWillResignActive:(UIApplication *)application 82 | { 83 | [self.settingsManager save]; 84 | } 85 | 86 | - (void)applicationWillTerminate:(UIApplication *)application 87 | { 88 | NSNotificationCenter *notificationCenter = self.conversationManager.notificationCenter; 89 | 90 | [notificationCenter removeObserver:self 91 | name:ConversationManagerAllConversationsDidChangeNotification 92 | object:self.conversationManager]; 93 | } 94 | 95 | #pragma mark - UISplitViewControllerDelegate 96 | - (BOOL) splitViewController:(UISplitViewController *)splitViewController 97 | collapseSecondaryViewController:(UIViewController *)secondaryViewController 98 | ontoPrimaryViewController:(UIViewController *)primaryViewController 99 | { 100 | if (![secondaryViewController isKindOfClass:[UINavigationController class]]) { 101 | return NO; 102 | } 103 | 104 | UINavigationController *navigationVC = (UINavigationController *)secondaryViewController; 105 | 106 | if (![navigationVC.viewControllers[0] isKindOfClass:[MessageViewController class]]) { 107 | return NO; 108 | } 109 | 110 | MessageViewController *messageVC = navigationVC.viewControllers[0]; 111 | 112 | if (!messageVC.message) { 113 | return YES; 114 | } 115 | 116 | return NO; 117 | } 118 | 119 | - (UISplitViewControllerDisplayMode)targetDisplayModeForActionInSplitViewController:(UISplitViewController *)svc 120 | { 121 | if (svc.displayMode == UISplitViewControllerDisplayModePrimaryHidden) { 122 | return UISplitViewControllerDisplayModeAllVisible; 123 | } 124 | else { 125 | return UISplitViewControllerDisplayModePrimaryHidden; 126 | } 127 | } 128 | 129 | #pragma mark - Local Notifications 130 | - (void)registerForLocalNotifications 131 | { 132 | UIUserNotificationType notificationTypes = UIUserNotificationTypeBadge | 133 | UIUserNotificationTypeAlert | 134 | UIUserNotificationTypeSound; 135 | UIUserNotificationSettings *notificationSettings = [UIUserNotificationSettings settingsForTypes:notificationTypes 136 | categories:nil]; 137 | 138 | [self.application registerUserNotificationSettings:notificationSettings]; 139 | } 140 | 141 | - (void)updateIconBadgeCount:(NSUInteger)iconBadgeCount 142 | { 143 | UIUserNotificationSettings *notificationSettings = self.application.currentUserNotificationSettings; 144 | 145 | if (notificationSettings.types & UIUserNotificationTypeBadge) { 146 | self.application.applicationIconBadgeNumber = iconBadgeCount; 147 | } 148 | } 149 | 150 | - (void)sendLocalNotificationWithTitle:(NSString *)title 151 | body:(NSString *)body 152 | { 153 | UIUserNotificationSettings *notificationSettings = self.application.currentUserNotificationSettings; 154 | 155 | if (notificationSettings.types & UIUserNotificationTypeAlert) { 156 | UILocalNotification *localNotification = [[UILocalNotification alloc] init]; 157 | 158 | localNotification.alertBody = body; 159 | localNotification.soundName = UILocalNotificationDefaultSoundName; 160 | 161 | [self.application presentLocalNotificationNow:localNotification]; 162 | } 163 | } 164 | 165 | #pragma mark - Notification Center 166 | - (void)addRefreshNotificationObservers 167 | { 168 | NSNotificationCenter *notificationCenter = self.conversationManager.notificationCenter; 169 | 170 | [notificationCenter addObserver:self 171 | selector:@selector(allConversationsRefreshDidEnd:) 172 | name:ConversationManagerAllConversationsRefreshDidEndNotification 173 | object:self.conversationManager]; 174 | 175 | [notificationCenter addObserver:self 176 | selector:@selector(allConversationsRefreshDidFail:) 177 | name:ConversationManagerAllConversationsRefreshDidFailNotification 178 | object:self.conversationManager]; 179 | } 180 | 181 | - (void)removeRefreshNotificationObservers 182 | { 183 | NSNotificationCenter *notificationCenter = self.conversationManager.notificationCenter; 184 | 185 | [notificationCenter removeObserver:self 186 | name:ConversationManagerAllConversationsRefreshDidEndNotification 187 | object:self.conversationManager]; 188 | 189 | [notificationCenter removeObserver:self 190 | name:ConversationManagerAllConversationsRefreshDidFailNotification 191 | object:self.conversationManager]; 192 | } 193 | 194 | - (void)allConversationsDidChange:(NSNotification *)notification 195 | { 196 | NSUInteger unreadCount = [notification.userInfo[ConversationManagerAllConversationsUnreadMessageCountKey] unsignedIntegerValue]; 197 | 198 | [self updateIconBadgeCount:unreadCount]; 199 | } 200 | 201 | - (void)allConversationsRefreshDidEnd:(NSNotification *)notification 202 | { 203 | [self sendLocalNotificationWithTitle:@"Updated Messages" 204 | body:@"Your message list has been refreshed"]; 205 | 206 | [self removeRefreshNotificationObservers]; 207 | 208 | } 209 | 210 | - (void)allConversationsRefreshDidFail:(NSNotification *)notification 211 | { 212 | [self removeRefreshNotificationObservers]; 213 | } 214 | 215 | @end 216 | 217 | // ********************************************************* 218 | // 219 | // O365-iOS-EmailPeek, https://github.com/OfficeDev/O365-iOS-EmailPeek 220 | // 221 | // Copyright (c) Microsoft Corporation 222 | // All rights reserved. 223 | // 224 | // MIT License: 225 | // Permission is hereby granted, free of charge, to any person obtaining 226 | // a copy of this software and associated documentation files (the 227 | // "Software"), to deal in the Software without restriction, including 228 | // without limitation the rights to use, copy, modify, merge, publish, 229 | // distribute, sublicense, and/or sell copies of the Software, and to 230 | // permit persons to whom the Software is furnished to do so, subject to 231 | // the following conditions: 232 | // 233 | // The above copyright notice and this permission notice shall be 234 | // included in all copies or substantial portions of the Software. 235 | // 236 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 237 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 238 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 239 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 240 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 241 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 242 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 243 | // 244 | // ********************************************************* 245 | -------------------------------------------------------------------------------- /EmailPeek/Conversation.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Microsoft. All rights reserved. Licensed under the MIT license. 3 | * See full license at the bottom of this file. 4 | */ 5 | 6 | #import "MessagePreview.h" 7 | 8 | @class Message; 9 | 10 | @interface Conversation : NSObject 11 | 12 | @property (readonly, nonatomic) NSArray *messages; 13 | 14 | // Additional calculated properties 15 | @property (readonly, nonatomic) NSArray *unreadMessages; 16 | 17 | @property (readonly, nonatomic) Message *oldestMessage; 18 | @property (readonly, nonatomic) Message *newestMessage; 19 | @property (readonly, nonatomic) Message *oldestUnreadMessage; 20 | @property (readonly, nonatomic) Message *previewMessage; 21 | 22 | @property (readonly, nonatomic) NSUInteger unreadMessageCount; 23 | 24 | - (instancetype)initWithMessages:(NSArray *)messages; 25 | 26 | - (instancetype)initWithGUID:(NSString *)guid 27 | messages:(NSArray *)messages; 28 | 29 | 30 | @end 31 | 32 | // ********************************************************* 33 | // 34 | // O365-iOS-EmailPeek, https://github.com/OfficeDev/O365-iOS-EmailPeek 35 | // 36 | // Copyright (c) Microsoft Corporation 37 | // All rights reserved. 38 | // 39 | // MIT License: 40 | // Permission is hereby granted, free of charge, to any person obtaining 41 | // a copy of this software and associated documentation files (the 42 | // "Software"), to deal in the Software without restriction, including 43 | // without limitation the rights to use, copy, modify, merge, publish, 44 | // distribute, sublicense, and/or sell copies of the Software, and to 45 | // permit persons to whom the Software is furnished to do so, subject to 46 | // the following conditions: 47 | // 48 | // The above copyright notice and this permission notice shall be 49 | // included in all copies or substantial portions of the Software. 50 | // 51 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 52 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 53 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 54 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 55 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 56 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 57 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 58 | // 59 | // ********************************************************* 60 | -------------------------------------------------------------------------------- /EmailPeek/Conversation.m: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Microsoft. All rights reserved. Licensed under the MIT license. 3 | * See full license at the bottom of this file. 4 | */ 5 | 6 | #import "Conversation.h" 7 | 8 | #import "Message.h" 9 | 10 | @implementation Conversation 11 | 12 | @synthesize guid = _guid; 13 | @synthesize unreadMessages = _unreadMessages; 14 | 15 | #pragma mark - Initialization 16 | - (instancetype)init 17 | { 18 | return [self initWithMessages:nil]; 19 | } 20 | 21 | - (instancetype)initWithMessages:(NSArray *)messages 22 | { 23 | return [self initWithGUID:[[messages firstObject] conversationGUID] 24 | messages:messages]; 25 | } 26 | 27 | - (instancetype)initWithGUID:(NSString *)guid 28 | messages:(NSArray *)messages 29 | { 30 | self = [super init]; 31 | 32 | if (self) { 33 | _guid = [guid copy]; 34 | _messages = [messages sortedArrayUsingSelector:@selector(compare:)]; 35 | } 36 | 37 | return self; 38 | } 39 | 40 | #pragma mark - Properties 41 | - (NSArray *)unreadMessages 42 | { 43 | if (!_unreadMessages) { 44 | NSMutableArray *unreadMessages = [[NSMutableArray alloc] init]; 45 | 46 | for (Message *message in self.messages) { 47 | if (!message.isRead) { 48 | [unreadMessages addObject:message]; 49 | } 50 | } 51 | 52 | _unreadMessages = [unreadMessages copy]; 53 | } 54 | 55 | return _unreadMessages; 56 | } 57 | 58 | - (Message *)oldestMessage 59 | { 60 | return [self.messages firstObject]; 61 | } 62 | 63 | - (Message *)newestMessage 64 | { 65 | return [self.messages lastObject]; 66 | } 67 | 68 | - (Message *)oldestUnreadMessage 69 | { 70 | return [self.unreadMessages firstObject]; 71 | } 72 | 73 | - (Message *)previewMessage 74 | { 75 | return self.oldestUnreadMessage ? self.oldestUnreadMessage : self.newestMessage; 76 | } 77 | 78 | - (NSUInteger)messageCount 79 | { 80 | return self.messages.count; 81 | } 82 | 83 | - (NSUInteger)unreadMessageCount 84 | { 85 | return self.unreadMessages.count; 86 | } 87 | 88 | #pragma mark - MessagePreview 89 | - (NSString *)conversationGUID 90 | { 91 | return self.guid; 92 | } 93 | 94 | - (NSString *)subject 95 | { 96 | return self.oldestMessage.subject; 97 | } 98 | 99 | - (EmailAddress *)sender 100 | { 101 | return self.previewMessage.sender; 102 | } 103 | 104 | - (NSArray *)toRecipients 105 | { 106 | return self.previewMessage.toRecipients; 107 | } 108 | 109 | - (NSArray *)ccRecipients 110 | { 111 | return self.previewMessage.ccRecipients; 112 | } 113 | 114 | - (NSString *)bodyPreview 115 | { 116 | return self.previewMessage.bodyPreview; 117 | } 118 | 119 | - (NSDate *)dateReceived 120 | { 121 | return self.newestMessage.dateReceived; 122 | } 123 | 124 | - (BOOL)isReadOnServer 125 | { 126 | return self.previewMessage.isReadOnServer; 127 | } 128 | 129 | - (BOOL)isReadOnClient 130 | { 131 | return self.previewMessage.isReadOnClient; 132 | } 133 | 134 | - (BOOL)isRead 135 | { 136 | return self.previewMessage.isRead; 137 | } 138 | 139 | - (BOOL)isHidden 140 | { 141 | for (Message *message in self.messages) { 142 | if (!message.isHidden) { 143 | return NO; 144 | } 145 | } 146 | 147 | return YES; 148 | } 149 | 150 | - (BOOL)hasAttachments 151 | { 152 | return self.previewMessage.hasAttachments; 153 | } 154 | 155 | - (MessageImportance)importance 156 | { 157 | return self.previewMessage.importance; 158 | } 159 | 160 | - (NSArray *)categories 161 | { 162 | return self.previewMessage.categories; 163 | } 164 | 165 | - (NSComparisonResult)compare:(id)object 166 | { 167 | return [self.dateReceived compare:object.dateReceived]; 168 | } 169 | 170 | @end 171 | 172 | // ********************************************************* 173 | // 174 | // O365-iOS-EmailPeek, https://github.com/OfficeDev/O365-iOS-EmailPeek 175 | // 176 | // Copyright (c) Microsoft Corporation 177 | // All rights reserved. 178 | // 179 | // MIT License: 180 | // Permission is hereby granted, free of charge, to any person obtaining 181 | // a copy of this software and associated documentation files (the 182 | // "Software"), to deal in the Software without restriction, including 183 | // without limitation the rights to use, copy, modify, merge, publish, 184 | // distribute, sublicense, and/or sell copies of the Software, and to 185 | // permit persons to whom the Software is furnished to do so, subject to 186 | // the following conditions: 187 | // 188 | // The above copyright notice and this permission notice shall be 189 | // included in all copies or substantial portions of the Software. 190 | // 191 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 192 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 193 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 194 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 195 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 196 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 197 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 198 | // 199 | // ********************************************************* 200 | 201 | -------------------------------------------------------------------------------- /EmailPeek/ConversationFilter.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Microsoft. All rights reserved. Licensed under the MIT license. 3 | * See full license at the bottom of this file. 4 | */ 5 | 6 | #import "MessageFilter.h" 7 | 8 | @interface ConversationFilter : NSObject 9 | 10 | @property (readonly, nonatomic) NSString *conversationGUID; 11 | @property (readonly, nonatomic) NSString *conversationSubject; 12 | 13 | - (instancetype)initWithConversationGUID:(NSString *)conversationGUID 14 | conversationSubject:(NSString *)conversationSubject; 15 | 16 | @end 17 | 18 | // ********************************************************* 19 | // 20 | // O365-iOS-EmailPeek, https://github.com/OfficeDev/O365-iOS-EmailPeek 21 | // 22 | // Copyright (c) Microsoft Corporation 23 | // All rights reserved. 24 | // 25 | // MIT License: 26 | // Permission is hereby granted, free of charge, to any person obtaining 27 | // a copy of this software and associated documentation files (the 28 | // "Software"), to deal in the Software without restriction, including 29 | // without limitation the rights to use, copy, modify, merge, publish, 30 | // distribute, sublicense, and/or sell copies of the Software, and to 31 | // permit persons to whom the Software is furnished to do so, subject to 32 | // the following conditions: 33 | // 34 | // The above copyright notice and this permission notice shall be 35 | // included in all copies or substantial portions of the Software. 36 | // 37 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 38 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 39 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 40 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 41 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 42 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 43 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 44 | // 45 | // ********************************************************* 46 | -------------------------------------------------------------------------------- /EmailPeek/ConversationFilter.m: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Microsoft. All rights reserved. Licensed under the MIT license. 3 | * See full license at the bottom of this file. 4 | */ 5 | 6 | #import "ConversationFilter.h" 7 | 8 | @implementation ConversationFilter 9 | 10 | #pragma mark - Initialization 11 | - (instancetype)init 12 | { 13 | return [self initWithConversationGUID:nil 14 | conversationSubject:nil]; 15 | } 16 | 17 | - (instancetype)initWithConversationGUID:(NSString *)conversationGUID 18 | conversationSubject:(NSString *)conversationSubject 19 | { 20 | self = [super init]; 21 | 22 | if (self) { 23 | _conversationGUID = [conversationGUID copy]; 24 | _conversationSubject = [conversationSubject copy]; 25 | } 26 | 27 | return self; 28 | } 29 | 30 | 31 | #pragma mark - NSCoding 32 | - (instancetype)initWithCoder:(NSCoder *)aDecoder 33 | { 34 | self = [super init]; 35 | 36 | if (self) { 37 | _conversationGUID = [aDecoder decodeObjectForKey:@"conversationGUID"]; 38 | _conversationSubject = [aDecoder decodeObjectForKey:@"conversationSubject"]; 39 | } 40 | 41 | return self; 42 | } 43 | 44 | - (void)encodeWithCoder:(NSCoder *)aCoder 45 | { 46 | [aCoder encodeObject:self.conversationGUID forKey:@"conversationGUID"]; 47 | [aCoder encodeObject:self.conversationSubject forKey:@"conversationSubject"]; 48 | } 49 | 50 | 51 | #pragma mark - NSObject 52 | - (NSString *)description 53 | { 54 | return self.conversationSubject; 55 | } 56 | 57 | - (BOOL)isEqual:(id)object 58 | { 59 | if (self == object) { 60 | return YES; 61 | } 62 | 63 | if (![object isKindOfClass:[ConversationFilter class]]) { 64 | return NO; 65 | } 66 | 67 | return [self.conversationGUID isEqualToString:[object conversationGUID]]; 68 | } 69 | 70 | - (NSUInteger)hash 71 | { 72 | return [self.conversationGUID hash]; 73 | } 74 | 75 | 76 | #pragma mark - MessageFilter 77 | - (NSString *)serverSideFilter 78 | { 79 | return [NSString stringWithFormat:@"ConversationId eq '%@'", self.conversationGUID]; 80 | } 81 | 82 | 83 | @end 84 | 85 | // ********************************************************* 86 | // 87 | // O365-iOS-EmailPeek, https://github.com/OfficeDev/O365-iOS-EmailPeek 88 | // 89 | // Copyright (c) Microsoft Corporation 90 | // All rights reserved. 91 | // 92 | // MIT License: 93 | // Permission is hereby granted, free of charge, to any person obtaining 94 | // a copy of this software and associated documentation files (the 95 | // "Software"), to deal in the Software without restriction, including 96 | // without limitation the rights to use, copy, modify, merge, publish, 97 | // distribute, sublicense, and/or sell copies of the Software, and to 98 | // permit persons to whom the Software is furnished to do so, subject to 99 | // the following conditions: 100 | // 101 | // The above copyright notice and this permission notice shall be 102 | // included in all copies or substantial portions of the Software. 103 | // 104 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 105 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 106 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 107 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 108 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 109 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 110 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 111 | // 112 | // ********************************************************* 113 | -------------------------------------------------------------------------------- /EmailPeek/ConversationFilterListViewController.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Microsoft. All rights reserved. Licensed under the MIT license. 3 | * See full license at the bottom of this file. 4 | */ 5 | 6 | #import 7 | 8 | @class ConversationFilter; 9 | 10 | @protocol ConversationFilterListViewControllerDelegate; 11 | 12 | @interface ConversationFilterListViewController : UITableViewController 13 | 14 | @property (copy, nonatomic) NSArray *conversationFilterList; 15 | 16 | @property (weak, nonatomic) id delegate; 17 | 18 | @end 19 | 20 | 21 | @protocol ConversationFilterListViewControllerDelegate 22 | 23 | - (void)conversationFilterListViewController:(ConversationFilterListViewController *)conversationFilterListVC 24 | didRemoveConversationFilter:(ConversationFilter *)conversationFilter; 25 | 26 | - (void)conversationFilterListViewControllerDidComplete:(ConversationFilterListViewController *)conversationFilterListVC; 27 | 28 | @end 29 | 30 | // ********************************************************* 31 | // 32 | // O365-iOS-EmailPeek, https://github.com/OfficeDev/O365-iOS-EmailPeek 33 | // 34 | // Copyright (c) Microsoft Corporation 35 | // All rights reserved. 36 | // 37 | // MIT License: 38 | // Permission is hereby granted, free of charge, to any person obtaining 39 | // a copy of this software and associated documentation files (the 40 | // "Software"), to deal in the Software without restriction, including 41 | // without limitation the rights to use, copy, modify, merge, publish, 42 | // distribute, sublicense, and/or sell copies of the Software, and to 43 | // permit persons to whom the Software is furnished to do so, subject to 44 | // the following conditions: 45 | // 46 | // The above copyright notice and this permission notice shall be 47 | // included in all copies or substantial portions of the Software. 48 | // 49 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 50 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 51 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 52 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 53 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 54 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 55 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 56 | // 57 | // ********************************************************* -------------------------------------------------------------------------------- /EmailPeek/ConversationFilterListViewController.m: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Microsoft. All rights reserved. Licensed under the MIT license. 3 | * See full license at the bottom of this file. 4 | */ 5 | 6 | #import "ConversationFilterListViewController.h" 7 | #import "ConversationFilter.h" 8 | 9 | @interface ConversationFilterListViewController () 10 | 11 | @property (strong, nonatomic) NSMutableArray *mutableConversationFilterList; 12 | 13 | @end 14 | 15 | @implementation ConversationFilterListViewController 16 | 17 | #pragma mark - Lifecycle 18 | - (void)viewWillDisappear:(BOOL)animated 19 | { 20 | [super viewWillDisappear:animated]; 21 | 22 | if (self.isMovingFromParentViewController) { 23 | [self.delegate conversationFilterListViewControllerDidComplete:self]; 24 | } 25 | } 26 | 27 | #pragma mark - Properties 28 | - (void)setConversationFilterList:(NSArray *)conversationFilterList 29 | { 30 | self.mutableConversationFilterList = [conversationFilterList mutableCopy]; 31 | 32 | [self.tableView reloadData]; 33 | } 34 | 35 | - (NSArray *)conversationFilterList 36 | { 37 | return [self.mutableConversationFilterList copy]; 38 | } 39 | 40 | - (NSMutableArray *)mutableConversationFilterList 41 | { 42 | if (!_mutableConversationFilterList) { 43 | _mutableConversationFilterList = [[NSMutableArray alloc] init]; 44 | } 45 | 46 | return _mutableConversationFilterList; 47 | } 48 | 49 | 50 | #pragma mark - Actions 51 | - (IBAction)infoButtonTapped:(UIBarButtonItem *)sender 52 | { 53 | UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"Following a Conversation" 54 | message:@"Indicate that you would like to follow a conversation by tapping the button when viewing a message." 55 | preferredStyle:UIAlertControllerStyleAlert]; 56 | 57 | UIAlertAction *okAction = [UIAlertAction actionWithTitle:@"OK" 58 | style:UIAlertActionStyleDefault 59 | handler:NULL]; 60 | 61 | [alertController addAction:okAction]; 62 | 63 | [self presentViewController:alertController 64 | animated:YES 65 | completion:NULL]; 66 | } 67 | 68 | 69 | #pragma mark - UITableViewDataSource 70 | - (NSInteger) tableView:(UITableView *)tableView 71 | numberOfRowsInSection:(NSInteger)section 72 | { 73 | return self.mutableConversationFilterList.count; 74 | } 75 | 76 | - (UITableViewCell *) tableView:(UITableView *)tableView 77 | cellForRowAtIndexPath:(NSIndexPath *)indexPath 78 | { 79 | UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"UITableViewCell" 80 | forIndexPath:indexPath]; 81 | 82 | ConversationFilter *conversationFilter = self.mutableConversationFilterList[indexPath.row]; 83 | 84 | cell.textLabel.text = conversationFilter.conversationSubject; 85 | 86 | return cell; 87 | } 88 | 89 | - (BOOL) tableView:(UITableView *)tableView 90 | canEditRowAtIndexPath:(NSIndexPath *)indexPath 91 | { 92 | return YES; 93 | } 94 | 95 | - (void) tableView:(UITableView *)tableView 96 | commitEditingStyle:(UITableViewCellEditingStyle)editingStyle 97 | forRowAtIndexPath:(NSIndexPath *)indexPath 98 | { 99 | if (editingStyle != UITableViewCellEditingStyleDelete) { 100 | return; 101 | } 102 | 103 | ConversationFilter *conversationFilter = self.mutableConversationFilterList[indexPath.row]; 104 | 105 | [self.mutableConversationFilterList removeObjectAtIndex:indexPath.row]; 106 | 107 | [self.delegate conversationFilterListViewController:self 108 | didRemoveConversationFilter:conversationFilter]; 109 | 110 | [tableView deleteRowsAtIndexPaths:@[indexPath] 111 | withRowAnimation:UITableViewRowAnimationFade]; 112 | } 113 | 114 | @end 115 | 116 | // ********************************************************* 117 | // 118 | // O365-iOS-EmailPeek, https://github.com/OfficeDev/O365-iOS-EmailPeek 119 | // 120 | // Copyright (c) Microsoft Corporation 121 | // All rights reserved. 122 | // 123 | // MIT License: 124 | // Permission is hereby granted, free of charge, to any person obtaining 125 | // a copy of this software and associated documentation files (the 126 | // "Software"), to deal in the Software without restriction, including 127 | // without limitation the rights to use, copy, modify, merge, publish, 128 | // distribute, sublicense, and/or sell copies of the Software, and to 129 | // permit persons to whom the Software is furnished to do so, subject to 130 | // the following conditions: 131 | // 132 | // The above copyright notice and this permission notice shall be 133 | // included in all copies or substantial portions of the Software. 134 | // 135 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 136 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 137 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 138 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 139 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 140 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 141 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 142 | // 143 | // ********************************************************* 144 | -------------------------------------------------------------------------------- /EmailPeek/ConversationListViewController.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Microsoft. All rights reserved. Licensed under the MIT license. 3 | * See full license at the bottom of this file. 4 | */ 5 | 6 | #import 7 | 8 | @class Office365Client; 9 | @class SettingsManager; 10 | @class ConversationManager; 11 | 12 | @interface ConversationListViewController : UITableViewController 13 | 14 | @property (strong, nonatomic) ConversationManager *conversationManager; 15 | 16 | @end 17 | 18 | // ********************************************************* 19 | // 20 | // O365-iOS-EmailPeek, https://github.com/OfficeDev/O365-iOS-EmailPeek 21 | // 22 | // Copyright (c) Microsoft Corporation 23 | // All rights reserved. 24 | // 25 | // MIT License: 26 | // Permission is hereby granted, free of charge, to any person obtaining 27 | // a copy of this software and associated documentation files (the 28 | // "Software"), to deal in the Software without restriction, including 29 | // without limitation the rights to use, copy, modify, merge, publish, 30 | // distribute, sublicense, and/or sell copies of the Software, and to 31 | // permit persons to whom the Software is furnished to do so, subject to 32 | // the following conditions: 33 | // 34 | // The above copyright notice and this permission notice shall be 35 | // included in all copies or substantial portions of the Software. 36 | // 37 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 38 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 39 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 40 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 41 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 42 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 43 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 44 | // 45 | // ********************************************************* -------------------------------------------------------------------------------- /EmailPeek/ConversationManager.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Microsoft. All rights reserved. Licensed under the MIT license. 3 | * See full license at the bottom of this file. 4 | */ 5 | 6 | #import 7 | #import 8 | 9 | @class Office365Client; 10 | @class SettingsManager; 11 | @class Message; 12 | @class MessageDetail; 13 | 14 | extern NSString * const ConversationManagerAllConversationsDidChangeNotification; 15 | 16 | extern NSString * const ConversationManagerAllConversationsRefreshDidBeginNotification; 17 | extern NSString * const ConversationManagerAllConversationsRefreshDidEndNotification; 18 | extern NSString * const ConversationManagerAllConversationsRefreshDidFailNotification; 19 | 20 | extern NSString * const ConversationManagerAllConversationsMessageCountKey; 21 | extern NSString * const ConversationManagerAllConversationsUnreadMessageCountKey; 22 | 23 | extern NSString * const ConversationManagerAllConversationsErrorKey; 24 | 25 | @interface ConversationManager : NSObject 26 | 27 | // Dependencies of this class 28 | @property (strong, nonatomic) UIApplication *application; 29 | @property (strong, nonatomic) Office365Client *office365Client; 30 | @property (strong, nonatomic) SettingsManager *settingsManager; 31 | @property (strong, nonatomic) NSNotificationCenter *notificationCenter; 32 | 33 | 34 | @property (readonly, copy, nonatomic) NSArray *allConversations; 35 | @property (readonly, strong, nonatomic) NSDate *allConversationsRefreshDate; 36 | @property (readonly, assign, nonatomic) BOOL allConversationsRefreshInProgress; 37 | 38 | @property (readonly, strong, nonatomic) NSArray *quickResponseBodies; 39 | 40 | @property (readonly, nonatomic) NSUInteger messageCount; 41 | @property (readonly, nonatomic) NSUInteger unreadMessageCount; 42 | 43 | @property (readonly, nonatomic) BOOL isConnected; 44 | 45 | - (void)refreshAllConversations; 46 | 47 | - (void)messageDetailForMessage:(Message *)message 48 | completionHandler:(void (^)(MessageDetail *messageDetail, NSError *error))completionHandler; 49 | 50 | /** 51 | If the user has indicated that they want to mark the read status on the server, 52 | then this method will update the read status in Outlook. If the user has not 53 | set that flag, then the message will be updated on the server with a new 54 | category called 'EmailPeek - Read'. 55 | */ 56 | - (void)markMessage:(Message *)message 57 | isRead:(BOOL)isRead; 58 | - (void) markMessage:(Message *)message 59 | isHidden:(BOOL)isHidden 60 | completionHandler:(void (^)(Message *updatedMessage, NSError *error))completionHandler; 61 | 62 | - (void)replyToMessage:(Message *)message 63 | replyAll:(BOOL)replyAll 64 | responseBody:(NSString *)responseBody 65 | completionHandler:(void (^)(BOOL success, NSError *))completionHandler; 66 | 67 | 68 | // Connection Related Methods 69 | - (void)connectWithCompletionHandler:(void (^)(BOOL success, NSError *error))completionHandler; 70 | - (void)disconnectWithCompletionHandler:(void (^)(BOOL success, NSError *error))completionHandler; 71 | 72 | @end 73 | 74 | // ********************************************************* 75 | // 76 | // O365-iOS-EmailPeek, https://github.com/OfficeDev/O365-iOS-EmailPeek 77 | // 78 | // Copyright (c) Microsoft Corporation 79 | // All rights reserved. 80 | // 81 | // MIT License: 82 | // Permission is hereby granted, free of charge, to any person obtaining 83 | // a copy of this software and associated documentation files (the 84 | // "Software"), to deal in the Software without restriction, including 85 | // without limitation the rights to use, copy, modify, merge, publish, 86 | // distribute, sublicense, and/or sell copies of the Software, and to 87 | // permit persons to whom the Software is furnished to do so, subject to 88 | // the following conditions: 89 | // 90 | // The above copyright notice and this permission notice shall be 91 | // included in all copies or substantial portions of the Software. 92 | // 93 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 94 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 95 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 96 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 97 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 98 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 99 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 100 | // 101 | // ********************************************************* 102 | 103 | -------------------------------------------------------------------------------- /EmailPeek/ConversationViewController.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Microsoft. All rights reserved. Licensed under the MIT license. 3 | * See full license at the bottom of this file. 4 | */ 5 | 6 | #import 7 | 8 | @class Conversation; 9 | @class ConversationManager; 10 | 11 | @protocol MessageViewControllerDelegate; 12 | 13 | @interface ConversationViewController : UITableViewController 14 | 15 | @property (strong, nonatomic) Conversation *conversation; 16 | @property (strong, nonatomic) ConversationManager *conversationManager; 17 | 18 | @property (weak, nonatomic) id delegate; 19 | 20 | @end 21 | 22 | // ********************************************************* 23 | // 24 | // O365-iOS-EmailPeek, https://github.com/OfficeDev/O365-iOS-EmailPeek 25 | // 26 | // Copyright (c) Microsoft Corporation 27 | // All rights reserved. 28 | // 29 | // MIT License: 30 | // Permission is hereby granted, free of charge, to any person obtaining 31 | // a copy of this software and associated documentation files (the 32 | // "Software"), to deal in the Software without restriction, including 33 | // without limitation the rights to use, copy, modify, merge, publish, 34 | // distribute, sublicense, and/or sell copies of the Software, and to 35 | // permit persons to whom the Software is furnished to do so, subject to 36 | // the following conditions: 37 | // 38 | // The above copyright notice and this permission notice shall be 39 | // included in all copies or substantial portions of the Software. 40 | // 41 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 42 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 43 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 44 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 45 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 46 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 47 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 48 | // 49 | // ********************************************************* -------------------------------------------------------------------------------- /EmailPeek/ConversationViewController.m: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Microsoft. All rights reserved. Licensed under the MIT license. 3 | * See full license at the bottom of this file. 4 | */ 5 | 6 | #import "ConversationViewController.h" 7 | #import "MessageViewController.h" 8 | #import "Conversation.h" 9 | #import "MessagePreview.h" 10 | #import "Message.h" 11 | #import "MessagePreviewCell.h" 12 | #import "ConversationManager.h" 13 | 14 | 15 | static NSString * const CellIdentifier = @"MessagePreviewCell"; 16 | 17 | @interface ConversationViewController () 18 | 19 | @property (strong, nonatomic) NSMutableArray *messages; 20 | 21 | @end 22 | 23 | @implementation ConversationViewController 24 | 25 | #pragma mark - Properties 26 | - (void)setConversationManager:(ConversationManager *)conversationManager 27 | { 28 | // Remove the existing notification registrations 29 | NSNotificationCenter *notificationCenter = _conversationManager.notificationCenter; 30 | 31 | [notificationCenter removeObserver:self 32 | name:nil 33 | object:_conversationManager]; 34 | 35 | _conversationManager = conversationManager; 36 | 37 | notificationCenter = _conversationManager.notificationCenter; 38 | 39 | [notificationCenter addObserver:self 40 | selector:@selector(allConversationsDidChange:) 41 | name:ConversationManagerAllConversationsDidChangeNotification 42 | object:_conversationManager]; 43 | } 44 | 45 | - (void)setConversation:(Conversation *)conversation 46 | { 47 | _conversation = conversation; 48 | 49 | NSArray *ascendingList = [conversation.messages sortedArrayUsingSelector:@selector(compare:)]; 50 | NSArray *descendingList = [[ascendingList reverseObjectEnumerator] allObjects]; 51 | 52 | self.messages = [descendingList mutableCopy]; 53 | 54 | [self.tableView reloadData]; 55 | } 56 | 57 | 58 | #pragma mark - Lifecycle 59 | - (void)viewDidLoad 60 | { 61 | [super viewDidLoad]; 62 | 63 | self.tableView.layoutMargins = UIEdgeInsetsZero; 64 | 65 | UINib *cellNib = [UINib nibWithNibName:CellIdentifier 66 | bundle:nil]; 67 | 68 | [self.tableView registerNib:cellNib 69 | forCellReuseIdentifier:CellIdentifier]; 70 | } 71 | 72 | - (void)prepareForSegue:(UIStoryboardSegue *)segue 73 | sender:(id)sender 74 | { 75 | if ([segue.identifier isEqualToString:@"showMessage"]) { 76 | NSIndexPath *selectedIndexPath = [self.tableView indexPathForCell:sender]; 77 | Message *selectedMessage = self.messages[selectedIndexPath.row]; 78 | 79 | UINavigationController *navigationVC = segue.destinationViewController; 80 | MessageViewController *messageVC = navigationVC.viewControllers[0]; 81 | 82 | messageVC.conversationManager = self.conversationManager; 83 | messageVC.message = selectedMessage; 84 | messageVC.delegate = self.delegate; 85 | } 86 | } 87 | 88 | - (void)dealloc 89 | { 90 | NSNotificationCenter *notificationCenter = _conversationManager.notificationCenter; 91 | 92 | [notificationCenter removeObserver:self 93 | name:nil 94 | object:_conversationManager]; 95 | } 96 | 97 | 98 | #pragma mark - UITableViewDataSource 99 | - (NSInteger) tableView:(UITableView *)tableView 100 | numberOfRowsInSection:(NSInteger)section 101 | { 102 | return self.messages.count; 103 | } 104 | 105 | - (UITableViewCell *) tableView:(UITableView *)tableView 106 | cellForRowAtIndexPath:(NSIndexPath *)indexPath 107 | { 108 | Message *message = self.messages[indexPath.row]; 109 | MessagePreviewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier 110 | forIndexPath:indexPath]; 111 | 112 | cell.messagePreview = message; 113 | 114 | return cell; 115 | } 116 | 117 | - (BOOL) tableView:(UITableView *)tableView 118 | canEditRowAtIndexPath:(NSIndexPath *)indexPath 119 | { 120 | return YES; 121 | } 122 | 123 | - (void) tableView:(UITableView *)tableView 124 | commitEditingStyle:(UITableViewCellEditingStyle)editingStyle 125 | forRowAtIndexPath:(NSIndexPath *)indexPath 126 | { 127 | if (editingStyle != UITableViewCellEditingStyleDelete) { 128 | return; 129 | } 130 | 131 | Message *message = self.messages[indexPath.row]; 132 | 133 | [self.conversationManager markMessage:message 134 | isHidden:YES 135 | completionHandler:NULL]; 136 | 137 | [self.messages removeObjectAtIndex:indexPath.row]; 138 | 139 | [self.tableView deleteRowsAtIndexPaths:@[indexPath] 140 | withRowAnimation:UITableViewRowAnimationAutomatic]; 141 | } 142 | 143 | 144 | #pragma mark - UITableViewDelegate 145 | - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath 146 | { 147 | [self performSegueWithIdentifier:@"showMessage" 148 | sender:[self.tableView cellForRowAtIndexPath:indexPath]]; 149 | } 150 | 151 | - (NSString *) tableView:(UITableView *)tableView 152 | titleForDeleteConfirmationButtonForRowAtIndexPath:(NSIndexPath *)indexPath 153 | { 154 | return @"Hide"; 155 | } 156 | 157 | 158 | #pragma mark - Notifications 159 | - (void)allConversationsDidChange:(NSNotification *)notification 160 | { 161 | __block Conversation *newConversation; 162 | 163 | [self.conversationManager.allConversations enumerateObjectsUsingBlock:^(Conversation *updatedConversation, NSUInteger idx, BOOL *stop) { 164 | if ([self.conversation.conversationGUID isEqualToString:updatedConversation.conversationGUID]) { 165 | newConversation = updatedConversation; 166 | *stop = YES; 167 | } 168 | }]; 169 | 170 | dispatch_async(dispatch_get_main_queue(), ^{ 171 | // Keep track of the selected message so we can keep it highlighted 172 | Message *activeMessage; 173 | 174 | if (self.tableView.indexPathForSelectedRow) { 175 | activeMessage = self.messages[self.tableView.indexPathForSelectedRow.row]; 176 | } 177 | 178 | self.conversation = newConversation; 179 | 180 | // Reset the selection on the active message 181 | if (activeMessage) { 182 | NSUInteger activeIndex = [self.messages indexOfObject:activeMessage]; 183 | 184 | if (activeIndex != NSNotFound) { 185 | NSIndexPath *selectedIndexPath = [NSIndexPath indexPathForRow:activeIndex inSection:0]; 186 | 187 | [self.tableView reloadRowsAtIndexPaths:@[selectedIndexPath] 188 | withRowAnimation:NO]; 189 | 190 | // This is required to restore the highlight 191 | [self.tableView selectRowAtIndexPath:selectedIndexPath 192 | animated:NO 193 | scrollPosition:UITableViewScrollPositionNone]; 194 | } 195 | } 196 | }); 197 | } 198 | 199 | @end 200 | 201 | // ********************************************************* 202 | // 203 | // O365-iOS-EmailPeek, https://github.com/OfficeDev/O365-iOS-EmailPeek 204 | // 205 | // Copyright (c) Microsoft Corporation 206 | // All rights reserved. 207 | // 208 | // MIT License: 209 | // Permission is hereby granted, free of charge, to any person obtaining 210 | // a copy of this software and associated documentation files (the 211 | // "Software"), to deal in the Software without restriction, including 212 | // without limitation the rights to use, copy, modify, merge, publish, 213 | // distribute, sublicense, and/or sell copies of the Software, and to 214 | // permit persons to whom the Software is furnished to do so, subject to 215 | // the following conditions: 216 | // 217 | // The above copyright notice and this permission notice shall be 218 | // included in all copies or substantial portions of the Software. 219 | // 220 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 221 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 222 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 223 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 224 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 225 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 226 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 227 | // 228 | // ********************************************************* 229 | -------------------------------------------------------------------------------- /EmailPeek/EmailAddress.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Microsoft. All rights reserved. Licensed under the MIT license. 3 | * See full license at the bottom of this file. 4 | */ 5 | 6 | #import 7 | 8 | @interface EmailAddress : NSObject 9 | 10 | @property (readonly, nonatomic) NSString *name; 11 | @property (readonly, nonatomic) NSString *address; 12 | 13 | - (instancetype)initWithName:(NSString *)name 14 | address:(NSString *)address; 15 | 16 | @end 17 | 18 | // ********************************************************* 19 | // 20 | // O365-iOS-EmailPeek, https://github.com/OfficeDev/O365-iOS-EmailPeek 21 | // 22 | // Copyright (c) Microsoft Corporation 23 | // All rights reserved. 24 | // 25 | // MIT License: 26 | // Permission is hereby granted, free of charge, to any person obtaining 27 | // a copy of this software and associated documentation files (the 28 | // "Software"), to deal in the Software without restriction, including 29 | // without limitation the rights to use, copy, modify, merge, publish, 30 | // distribute, sublicense, and/or sell copies of the Software, and to 31 | // permit persons to whom the Software is furnished to do so, subject to 32 | // the following conditions: 33 | // 34 | // The above copyright notice and this permission notice shall be 35 | // included in all copies or substantial portions of the Software. 36 | // 37 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 38 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 39 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 40 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 41 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 42 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 43 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 44 | // 45 | // ********************************************************* 46 | -------------------------------------------------------------------------------- /EmailPeek/EmailAddress.m: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Microsoft. All rights reserved. Licensed under the MIT license. 3 | * See full license at the bottom of this file. 4 | */ 5 | 6 | #import "EmailAddress.h" 7 | 8 | @implementation EmailAddress 9 | 10 | #pragma mark - Initialization 11 | - (instancetype)init 12 | { 13 | return [self initWithName:nil 14 | address:nil]; 15 | } 16 | 17 | - (instancetype)initWithName:(NSString *)name 18 | address:(NSString *)address 19 | { 20 | self = [super init]; 21 | 22 | if (self) { 23 | _name = [name copy]; 24 | _address = [address copy]; 25 | } 26 | 27 | return self; 28 | } 29 | 30 | 31 | #pragma mark - NSCoding 32 | - (instancetype)initWithCoder:(NSCoder *)aDecoder 33 | { 34 | self = [super init]; 35 | 36 | if (self) { 37 | _name = [aDecoder decodeObjectForKey:@"name"]; 38 | _address = [aDecoder decodeObjectForKey:@"address"]; 39 | } 40 | 41 | return self; 42 | } 43 | 44 | - (void)encodeWithCoder:(NSCoder *)aCoder 45 | { 46 | [aCoder encodeObject:self.name forKey:@"name"]; 47 | [aCoder encodeObject:self.address forKey:@"address"]; 48 | } 49 | 50 | 51 | #pragma mark - NSObject 52 | - (NSString *)description 53 | { 54 | return self.name ? self.name : self.address; 55 | } 56 | 57 | - (BOOL)isEqual:(id)object 58 | { 59 | if (self == object) { 60 | return YES; 61 | } 62 | 63 | if (![object isKindOfClass:[EmailAddress class]]) { 64 | return NO; 65 | } 66 | 67 | return [self.address caseInsensitiveCompare:[(EmailAddress *)object address]] == NSOrderedSame; 68 | } 69 | 70 | - (NSUInteger)hash 71 | { 72 | return [self.address hash]; 73 | } 74 | 75 | @end 76 | 77 | // ********************************************************* 78 | // 79 | // O365-iOS-EmailPeek, https://github.com/OfficeDev/O365-iOS-EmailPeek 80 | // 81 | // Copyright (c) Microsoft Corporation 82 | // All rights reserved. 83 | // 84 | // MIT License: 85 | // Permission is hereby granted, free of charge, to any person obtaining 86 | // a copy of this software and associated documentation files (the 87 | // "Software"), to deal in the Software without restriction, including 88 | // without limitation the rights to use, copy, modify, merge, publish, 89 | // distribute, sublicense, and/or sell copies of the Software, and to 90 | // permit persons to whom the Software is furnished to do so, subject to 91 | // the following conditions: 92 | // 93 | // The above copyright notice and this permission notice shall be 94 | // included in all copies or substantial portions of the Software. 95 | // 96 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 97 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 98 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 99 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 100 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 101 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 102 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 103 | // 104 | // ********************************************************* 105 | 106 | -------------------------------------------------------------------------------- /EmailPeek/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" : "29x29", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "40x40", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "40x40", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "size" : "60x60", 25 | "idiom" : "iphone", 26 | "filename" : "app120.png", 27 | "scale" : "2x" 28 | }, 29 | { 30 | "size" : "60x60", 31 | "idiom" : "iphone", 32 | "filename" : "app180.png", 33 | "scale" : "3x" 34 | }, 35 | { 36 | "idiom" : "ipad", 37 | "size" : "29x29", 38 | "scale" : "1x" 39 | }, 40 | { 41 | "idiom" : "ipad", 42 | "size" : "29x29", 43 | "scale" : "2x" 44 | }, 45 | { 46 | "idiom" : "ipad", 47 | "size" : "40x40", 48 | "scale" : "1x" 49 | }, 50 | { 51 | "idiom" : "ipad", 52 | "size" : "40x40", 53 | "scale" : "2x" 54 | }, 55 | { 56 | "size" : "76x76", 57 | "idiom" : "ipad", 58 | "filename" : "app76.png", 59 | "scale" : "1x" 60 | }, 61 | { 62 | "size" : "76x76", 63 | "idiom" : "ipad", 64 | "filename" : "app152.png", 65 | "scale" : "2x" 66 | } 67 | ], 68 | "info" : { 69 | "version" : 1, 70 | "author" : "xcode" 71 | } 72 | } -------------------------------------------------------------------------------- /EmailPeek/Images.xcassets/AppIcon.appiconset/app120.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OfficeDev/O365-iOS-EmailPeek/d822aacd3b48bf84862ead6f7284e72b68530b42/EmailPeek/Images.xcassets/AppIcon.appiconset/app120.png -------------------------------------------------------------------------------- /EmailPeek/Images.xcassets/AppIcon.appiconset/app152.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OfficeDev/O365-iOS-EmailPeek/d822aacd3b48bf84862ead6f7284e72b68530b42/EmailPeek/Images.xcassets/AppIcon.appiconset/app152.png -------------------------------------------------------------------------------- /EmailPeek/Images.xcassets/AppIcon.appiconset/app180.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OfficeDev/O365-iOS-EmailPeek/d822aacd3b48bf84862ead6f7284e72b68530b42/EmailPeek/Images.xcassets/AppIcon.appiconset/app180.png -------------------------------------------------------------------------------- /EmailPeek/Images.xcassets/AppIcon.appiconset/app76.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OfficeDev/O365-iOS-EmailPeek/d822aacd3b48bf84862ead6f7284e72b68530b42/EmailPeek/Images.xcassets/AppIcon.appiconset/app76.png -------------------------------------------------------------------------------- /EmailPeek/Images.xcassets/attachment_icon.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x", 6 | "filename" : "clippy22.png" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x", 11 | "filename" : "clippy44.png" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "scale" : "3x", 16 | "filename" : "clippy66.png" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /EmailPeek/Images.xcassets/attachment_icon.imageset/clippy22.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OfficeDev/O365-iOS-EmailPeek/d822aacd3b48bf84862ead6f7284e72b68530b42/EmailPeek/Images.xcassets/attachment_icon.imageset/clippy22.png -------------------------------------------------------------------------------- /EmailPeek/Images.xcassets/attachment_icon.imageset/clippy44.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OfficeDev/O365-iOS-EmailPeek/d822aacd3b48bf84862ead6f7284e72b68530b42/EmailPeek/Images.xcassets/attachment_icon.imageset/clippy44.png -------------------------------------------------------------------------------- /EmailPeek/Images.xcassets/attachment_icon.imageset/clippy66.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OfficeDev/O365-iOS-EmailPeek/d822aacd3b48bf84862ead6f7284e72b68530b42/EmailPeek/Images.xcassets/attachment_icon.imageset/clippy66.png -------------------------------------------------------------------------------- /EmailPeek/Images.xcassets/settings_icon.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x", 6 | "filename" : "app22.png" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x", 11 | "filename" : "app44.png" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "scale" : "3x", 16 | "filename" : "app66.png" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /EmailPeek/Images.xcassets/settings_icon.imageset/app22.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OfficeDev/O365-iOS-EmailPeek/d822aacd3b48bf84862ead6f7284e72b68530b42/EmailPeek/Images.xcassets/settings_icon.imageset/app22.png -------------------------------------------------------------------------------- /EmailPeek/Images.xcassets/settings_icon.imageset/app44.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OfficeDev/O365-iOS-EmailPeek/d822aacd3b48bf84862ead6f7284e72b68530b42/EmailPeek/Images.xcassets/settings_icon.imageset/app44.png -------------------------------------------------------------------------------- /EmailPeek/Images.xcassets/settings_icon.imageset/app66.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OfficeDev/O365-iOS-EmailPeek/d822aacd3b48bf84862ead6f7284e72b68530b42/EmailPeek/Images.xcassets/settings_icon.imageset/app66.png -------------------------------------------------------------------------------- /EmailPeek/Images.xcassets/urgent_icon.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x", 6 | "filename" : "bang22-1.png" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x", 11 | "filename" : "bang22.png" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "scale" : "3x", 16 | "filename" : "bang66.png" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /EmailPeek/Images.xcassets/urgent_icon.imageset/bang22-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OfficeDev/O365-iOS-EmailPeek/d822aacd3b48bf84862ead6f7284e72b68530b42/EmailPeek/Images.xcassets/urgent_icon.imageset/bang22-1.png -------------------------------------------------------------------------------- /EmailPeek/Images.xcassets/urgent_icon.imageset/bang22.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OfficeDev/O365-iOS-EmailPeek/d822aacd3b48bf84862ead6f7284e72b68530b42/EmailPeek/Images.xcassets/urgent_icon.imageset/bang22.png -------------------------------------------------------------------------------- /EmailPeek/Images.xcassets/urgent_icon.imageset/bang66.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OfficeDev/O365-iOS-EmailPeek/d822aacd3b48bf84862ead6f7284e72b68530b42/EmailPeek/Images.xcassets/urgent_icon.imageset/bang66.png -------------------------------------------------------------------------------- /EmailPeek/ImportanceFilter.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Microsoft. All rights reserved. Licensed under the MIT license. 3 | * See full license at the bottom of this file. 4 | */ 5 | 6 | #import "MessageFilter.h" 7 | 8 | @interface ImportanceFilter : NSObject 9 | 10 | @property (assign, nonatomic) MessageImportance messageImportance; 11 | 12 | - (instancetype)initWithMessageImportance:(MessageImportance)messageImportance; 13 | 14 | @end 15 | 16 | // ********************************************************* 17 | // 18 | // O365-iOS-EmailPeek, https://github.com/OfficeDev/O365-iOS-EmailPeek 19 | // 20 | // Copyright (c) Microsoft Corporation 21 | // All rights reserved. 22 | // 23 | // MIT License: 24 | // Permission is hereby granted, free of charge, to any person obtaining 25 | // a copy of this software and associated documentation files (the 26 | // "Software"), to deal in the Software without restriction, including 27 | // without limitation the rights to use, copy, modify, merge, publish, 28 | // distribute, sublicense, and/or sell copies of the Software, and to 29 | // permit persons to whom the Software is furnished to do so, subject to 30 | // the following conditions: 31 | // 32 | // The above copyright notice and this permission notice shall be 33 | // included in all copies or substantial portions of the Software. 34 | // 35 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 36 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 37 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 38 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 39 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 40 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 41 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 42 | // 43 | // ********************************************************* 44 | -------------------------------------------------------------------------------- /EmailPeek/ImportanceFilter.m: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Microsoft. All rights reserved. Licensed under the MIT license. 3 | * See full license at the bottom of this file. 4 | */ 5 | 6 | #import "ImportanceFilter.h" 7 | 8 | @implementation ImportanceFilter 9 | 10 | #pragma mark - Initialization 11 | - (instancetype)init 12 | { 13 | return [self initWithMessageImportance:MessageImportanceHigh]; 14 | } 15 | 16 | - (instancetype)initWithMessageImportance:(MessageImportance)messageImportance 17 | { 18 | self = [super init]; 19 | 20 | if (self) { 21 | _messageImportance = messageImportance; 22 | } 23 | 24 | return self; 25 | } 26 | 27 | 28 | #pragma mark - NSCoding 29 | - (instancetype)initWithCoder:(NSCoder *)aDecoder 30 | { 31 | self = [super init]; 32 | 33 | if (self) { 34 | _messageImportance = [aDecoder decodeIntegerForKey:@"messageImportance"]; 35 | } 36 | 37 | return self; 38 | } 39 | 40 | - (void)encodeWithCoder:(NSCoder *)aCoder 41 | { 42 | [aCoder encodeInteger:self.messageImportance forKey:@"messageImportance"]; 43 | } 44 | 45 | 46 | #pragma mark - MessageFilter 47 | - (NSString *)serverSideFilter 48 | { 49 | // NOTE: The example provided at https://msdn.microsoft.com/office/office365/APi/complex-types-for-mail-contacts-calendar#UseODataqueryparametersFilterrequests 50 | // suggests that the following should work, but I didn't have success: 51 | // 52 | // Importance eq Microsoft.Exchange.Services.OData.Model.Importance'High' 53 | 54 | // This might seem like overkill, but I didn't want to rely on the order 55 | // that the enumeration was declared; we could optimize this with a static 56 | // but it isn't going to be a significant savings 57 | NSArray *importanceLookup = @[@(MessageImportanceLow), 58 | @(MessageImportanceNormal), 59 | @(MessageImportanceHigh)]; 60 | 61 | NSUInteger importanceValue = [importanceLookup indexOfObject:@(self.messageImportance)]; 62 | 63 | return [NSString stringWithFormat:@"Importance eq '%lu'", (unsigned long)importanceValue]; 64 | } 65 | 66 | @end 67 | 68 | // ********************************************************* 69 | // 70 | // O365-iOS-EmailPeek, https://github.com/OfficeDev/O365-iOS-EmailPeek 71 | // 72 | // Copyright (c) Microsoft Corporation 73 | // All rights reserved. 74 | // 75 | // MIT License: 76 | // Permission is hereby granted, free of charge, to any person obtaining 77 | // a copy of this software and associated documentation files (the 78 | // "Software"), to deal in the Software without restriction, including 79 | // without limitation the rights to use, copy, modify, merge, publish, 80 | // distribute, sublicense, and/or sell copies of the Software, and to 81 | // permit persons to whom the Software is furnished to do so, subject to 82 | // the following conditions: 83 | // 84 | // The above copyright notice and this permission notice shall be 85 | // included in all copies or substantial portions of the Software. 86 | // 87 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 88 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 89 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 90 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 91 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 92 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 93 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 94 | // 95 | // ********************************************************* 96 | 97 | -------------------------------------------------------------------------------- /EmailPeek/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | com.microsoft.$(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 | UIBackgroundModes 26 | 27 | UILaunchStoryboardName 28 | Main 29 | UIMainStoryboardFile 30 | Main 31 | UIRequiredDeviceCapabilities 32 | 33 | armv7 34 | 35 | UIStatusBarTintParameters 36 | 37 | UINavigationBar 38 | 39 | Style 40 | UIBarStyleDefault 41 | Translucent 42 | 43 | 44 | 45 | UISupportedInterfaceOrientations 46 | 47 | UIInterfaceOrientationPortrait 48 | UIInterfaceOrientationLandscapeLeft 49 | UIInterfaceOrientationLandscapeRight 50 | 51 | UISupportedInterfaceOrientations~ipad 52 | 53 | UIInterfaceOrientationPortrait 54 | UIInterfaceOrientationPortraitUpsideDown 55 | UIInterfaceOrientationLandscapeLeft 56 | UIInterfaceOrientationLandscapeRight 57 | 58 | NSAppTransportSecurity 59 | 60 | NSExceptionDomains 61 | 62 | outlook.office365.com 63 | 64 | NSIncludeSubmdomains 65 | 66 | NSExceptionRequiresForwardSecrecy 67 | 68 | 69 | 70 | 71 | 72 | 73 | -------------------------------------------------------------------------------- /EmailPeek/Message.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Microsoft. All rights reserved. Licensed under the MIT license. 3 | * See full license at the bottom of this file. 4 | */ 5 | 6 | #import "MessagePreview.h" 7 | 8 | @interface Message : NSObject 9 | 10 | - (instancetype)initWithGUID:(NSString *)guid 11 | conversationGUID:(NSString *)conversationGUID 12 | subject:(NSString *)subject 13 | sender:(EmailAddress *)sender 14 | toRecipients:(NSArray *)toRecipients 15 | ccRecipients:(NSArray *)ccRecipients 16 | bodyPreview:(NSString *)bodyPreview 17 | dateReceived:(NSDate *)dateReceived 18 | isReadOnServer:(BOOL)isReadOnServer 19 | isReadOnClient:(BOOL)isReadOnClient 20 | isHidden:(BOOL)isHidden 21 | hasAttachments:(BOOL)hasAttachments 22 | importance:(MessageImportance)importance 23 | categories:(NSArray *)categories; 24 | 25 | @end 26 | 27 | // ********************************************************* 28 | // 29 | // O365-iOS-EmailPeek, https://github.com/OfficeDev/O365-iOS-EmailPeek 30 | // 31 | // Copyright (c) Microsoft Corporation 32 | // All rights reserved. 33 | // 34 | // MIT License: 35 | // Permission is hereby granted, free of charge, to any person obtaining 36 | // a copy of this software and associated documentation files (the 37 | // "Software"), to deal in the Software without restriction, including 38 | // without limitation the rights to use, copy, modify, merge, publish, 39 | // distribute, sublicense, and/or sell copies of the Software, and to 40 | // permit persons to whom the Software is furnished to do so, subject to 41 | // the following conditions: 42 | // 43 | // The above copyright notice and this permission notice shall be 44 | // included in all copies or substantial portions of the Software. 45 | // 46 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 47 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 48 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 49 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 50 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 51 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 52 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 53 | // 54 | // ********************************************************* 55 | -------------------------------------------------------------------------------- /EmailPeek/Message.m: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Microsoft. All rights reserved. Licensed under the MIT license. 3 | * See full license at the bottom of this file. 4 | */ 5 | 6 | #import "Message.h" 7 | 8 | @implementation Message 9 | 10 | @synthesize guid = _guid; 11 | @synthesize conversationGUID = _conversationGUID; 12 | @synthesize subject = _subject; 13 | @synthesize sender = _sender; 14 | @synthesize toRecipients = _toRecipients; 15 | @synthesize ccRecipients = _ccRecipients; 16 | @synthesize bodyPreview = _bodyPreview; 17 | @synthesize dateReceived = _dateReceived; 18 | @synthesize isReadOnServer = _isReadOnServer; 19 | @synthesize isReadOnClient = _isReadOnClient; 20 | @synthesize isRead = _isRead; 21 | @synthesize isHidden = _isHidden; 22 | @synthesize hasAttachments = _hasAttachments; 23 | @synthesize importance = _importance; 24 | @synthesize categories = _categories; 25 | 26 | 27 | #pragma mark - Initialization 28 | - (instancetype)init 29 | { 30 | return [self initWithGUID:nil 31 | conversationGUID:nil 32 | subject:nil 33 | sender:nil 34 | toRecipients:nil 35 | ccRecipients:nil 36 | bodyPreview:nil 37 | dateReceived:nil 38 | isReadOnServer:NO 39 | isReadOnClient:NO 40 | isHidden:NO 41 | hasAttachments:NO 42 | importance:MessageImportanceNormal 43 | categories:nil]; 44 | } 45 | 46 | - (instancetype)initWithGUID:(NSString *)guid 47 | conversationGUID:(NSString *)conversationGUID 48 | subject:(NSString *)subject 49 | sender:(EmailAddress *)sender 50 | toRecipients:(NSArray *)toRecipients 51 | ccRecipients:(NSArray *)ccRecipients 52 | bodyPreview:(NSString *)bodyPreview 53 | dateReceived:(NSDate *)dateReceived 54 | isReadOnServer:(BOOL)isReadOnServer 55 | isReadOnClient:(BOOL)isReadOnClient 56 | isHidden:(BOOL)isHidden 57 | hasAttachments:(BOOL)hasAttachments 58 | importance:(MessageImportance)importance 59 | categories:(NSArray *)categories 60 | { 61 | self = [super init]; 62 | 63 | if (self) { 64 | _guid = [guid copy]; 65 | _conversationGUID = [conversationGUID copy]; 66 | _subject = [subject copy]; 67 | _sender = sender; 68 | _toRecipients = toRecipients ? [toRecipients copy] : @[]; 69 | _ccRecipients = ccRecipients ? [ccRecipients copy] : @[]; 70 | _bodyPreview = [bodyPreview copy]; 71 | _dateReceived = dateReceived; 72 | _isReadOnServer = isReadOnServer; 73 | _isReadOnClient = isReadOnClient; 74 | _isRead = isReadOnServer || isReadOnClient; 75 | _isHidden = isHidden; 76 | _hasAttachments = hasAttachments; 77 | _importance = importance; 78 | _categories = [categories copy]; 79 | } 80 | 81 | return self; 82 | } 83 | 84 | 85 | #pragma mark - Properties 86 | - (NSUInteger)messageCount 87 | { 88 | return 1; 89 | } 90 | 91 | 92 | #pragma mark - Convenience Methods 93 | - (NSComparisonResult)compare:(id)object 94 | { 95 | return [self.dateReceived compare:object.dateReceived]; 96 | } 97 | 98 | 99 | #pragma mark - NSObject 100 | - (BOOL)isEqual:(id)object 101 | { 102 | if (self == object) { 103 | return YES; 104 | } 105 | 106 | if (![object isKindOfClass:[Message class]]) { 107 | return NO; 108 | } 109 | 110 | return [self.guid isEqualToString:[object guid]]; 111 | } 112 | 113 | - (NSUInteger)hash 114 | { 115 | return [self.guid hash]; 116 | } 117 | 118 | @end 119 | 120 | // ********************************************************* 121 | // 122 | // O365-iOS-EmailPeek, https://github.com/OfficeDev/O365-iOS-EmailPeek 123 | // 124 | // Copyright (c) Microsoft Corporation 125 | // All rights reserved. 126 | // 127 | // MIT License: 128 | // Permission is hereby granted, free of charge, to any person obtaining 129 | // a copy of this software and associated documentation files (the 130 | // "Software"), to deal in the Software without restriction, including 131 | // without limitation the rights to use, copy, modify, merge, publish, 132 | // distribute, sublicense, and/or sell copies of the Software, and to 133 | // permit persons to whom the Software is furnished to do so, subject to 134 | // the following conditions: 135 | // 136 | // The above copyright notice and this permission notice shall be 137 | // included in all copies or substantial portions of the Software. 138 | // 139 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 140 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 141 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 142 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 143 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 144 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 145 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 146 | // 147 | // ********************************************************* 148 | 149 | -------------------------------------------------------------------------------- /EmailPeek/MessageAttachment.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Microsoft. All rights reserved. Licensed under the MIT license. 3 | * See full license at the bottom of this file. 4 | */ 5 | 6 | #import 7 | 8 | @interface MessageAttachment : NSObject 9 | 10 | @property (readonly, nonatomic) NSString *guid; 11 | @property (readonly, nonatomic) NSString *name; 12 | @property (readonly, nonatomic) NSString *contentType; 13 | @property (readonly, nonatomic) NSUInteger byteCount; 14 | 15 | - (instancetype)initWithGUID:(NSString *)guid 16 | name:(NSString *)name 17 | contentType:(NSString *)contentType 18 | byteCount:(NSUInteger)byteCount; 19 | 20 | @end 21 | 22 | // ********************************************************* 23 | // 24 | // O365-iOS-EmailPeek, https://github.com/OfficeDev/O365-iOS-EmailPeek 25 | // 26 | // Copyright (c) Microsoft Corporation 27 | // All rights reserved. 28 | // 29 | // MIT License: 30 | // Permission is hereby granted, free of charge, to any person obtaining 31 | // a copy of this software and associated documentation files (the 32 | // "Software"), to deal in the Software without restriction, including 33 | // without limitation the rights to use, copy, modify, merge, publish, 34 | // distribute, sublicense, and/or sell copies of the Software, and to 35 | // permit persons to whom the Software is furnished to do so, subject to 36 | // the following conditions: 37 | // 38 | // The above copyright notice and this permission notice shall be 39 | // included in all copies or substantial portions of the Software. 40 | // 41 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 42 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 43 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 44 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 45 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 46 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 47 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 48 | // 49 | // ********************************************************* 50 | -------------------------------------------------------------------------------- /EmailPeek/MessageAttachment.m: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Microsoft. All rights reserved. Licensed under the MIT license. 3 | * See full license at the bottom of this file. 4 | */ 5 | 6 | #import "MessageAttachment.h" 7 | 8 | @implementation MessageAttachment 9 | 10 | #pragma mark - Initialization 11 | - (instancetype)init 12 | { 13 | return [self initWithGUID:nil 14 | name:nil 15 | contentType:nil 16 | byteCount:0]; 17 | } 18 | 19 | - (instancetype)initWithGUID:(NSString *)guid 20 | name:(NSString *)name 21 | contentType:(NSString *)contentType 22 | byteCount:(NSUInteger)byteCount 23 | { 24 | self = [super init]; 25 | 26 | if (self) { 27 | _guid = [guid copy]; 28 | _name = [name copy]; 29 | _contentType = [contentType copy]; 30 | _byteCount = byteCount; 31 | } 32 | 33 | return self; 34 | } 35 | 36 | #pragma mark - NSObject 37 | - (NSString *)description 38 | { 39 | return self.name; 40 | } 41 | 42 | @end 43 | 44 | // ********************************************************* 45 | // 46 | // O365-iOS-EmailPeek, https://github.com/OfficeDev/O365-iOS-EmailPeek 47 | // 48 | // Copyright (c) Microsoft Corporation 49 | // All rights reserved. 50 | // 51 | // MIT License: 52 | // Permission is hereby granted, free of charge, to any person obtaining 53 | // a copy of this software and associated documentation files (the 54 | // "Software"), to deal in the Software without restriction, including 55 | // without limitation the rights to use, copy, modify, merge, publish, 56 | // distribute, sublicense, and/or sell copies of the Software, and to 57 | // permit persons to whom the Software is furnished to do so, subject to 58 | // the following conditions: 59 | // 60 | // The above copyright notice and this permission notice shall be 61 | // included in all copies or substantial portions of the Software. 62 | // 63 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 64 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 65 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 66 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 67 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 68 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 69 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 70 | // 71 | // ********************************************************* 72 | -------------------------------------------------------------------------------- /EmailPeek/MessageDetail.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Microsoft. All rights reserved. Licensed under the MIT license. 3 | * See full license at the bottom of this file. 4 | */ 5 | 6 | #import 7 | 8 | // UniqueBody is not used at this time 9 | // it could be considered in future revisions when working with 10 | // conversations. 11 | @interface MessageDetail : NSObject 12 | 13 | @property (readonly, nonatomic) NSString *guid; 14 | @property (readonly, nonatomic) NSString *body; 15 | @property (readonly, nonatomic) BOOL isBodyHTML; 16 | @property (readonly, nonatomic) NSString *uniqueBody; 17 | @property (readonly, nonatomic) BOOL isUniqueBodyHTML; 18 | @property (readonly, nonatomic) NSArray *attachments; 19 | 20 | - (instancetype)initWithGUID:(NSString *)guid 21 | body:(NSString *)body 22 | isBodyHTML:(BOOL)isBodyHTML 23 | uniqueBody:(NSString *)uniqueBody 24 | isUniqueBodyHTML:(BOOL)isUniqueBodyHTML 25 | attachments:(NSArray *)attachments; 26 | 27 | @end 28 | 29 | // ********************************************************* 30 | // 31 | // O365-iOS-EmailPeek, https://github.com/OfficeDev/O365-iOS-EmailPeek 32 | // 33 | // Copyright (c) Microsoft Corporation 34 | // All rights reserved. 35 | // 36 | // MIT License: 37 | // Permission is hereby granted, free of charge, to any person obtaining 38 | // a copy of this software and associated documentation files (the 39 | // "Software"), to deal in the Software without restriction, including 40 | // without limitation the rights to use, copy, modify, merge, publish, 41 | // distribute, sublicense, and/or sell copies of the Software, and to 42 | // permit persons to whom the Software is furnished to do so, subject to 43 | // the following conditions: 44 | // 45 | // The above copyright notice and this permission notice shall be 46 | // included in all copies or substantial portions of the Software. 47 | // 48 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 49 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 50 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 51 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 52 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 53 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 54 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 55 | // 56 | // ********************************************************* 57 | -------------------------------------------------------------------------------- /EmailPeek/MessageDetail.m: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Microsoft. All rights reserved. Licensed under the MIT license. 3 | * See full license at the bottom of this file. 4 | */ 5 | 6 | #import "MessageDetail.h" 7 | 8 | @implementation MessageDetail 9 | 10 | #pragma mark - Initialization 11 | - (instancetype)init 12 | { 13 | return [self initWithGUID:nil 14 | body:nil 15 | isBodyHTML:NO 16 | uniqueBody:nil 17 | isUniqueBodyHTML:NO 18 | attachments:nil]; 19 | } 20 | 21 | - (instancetype)initWithGUID:(NSString *)guid 22 | body:(NSString *)body 23 | isBodyHTML:(BOOL)isBodyHTML 24 | uniqueBody:(NSString *)uniqueBody 25 | isUniqueBodyHTML:(BOOL)isUniqueBodyHTML 26 | attachments:(NSArray *)attachments 27 | { 28 | self = [super init]; 29 | 30 | if (self) { 31 | _guid = [guid copy]; 32 | _body = [body copy]; 33 | _isBodyHTML = isBodyHTML; 34 | _uniqueBody = [uniqueBody copy]; 35 | _isUniqueBodyHTML = isUniqueBodyHTML; 36 | _attachments = [attachments copy]; 37 | } 38 | 39 | return self; 40 | } 41 | 42 | #pragma mark - NSObject 43 | - (BOOL)isEqual:(id)object 44 | { 45 | if (self == object) { 46 | return YES; 47 | } 48 | 49 | if (![object isKindOfClass:[MessageDetail class]]) { 50 | return NO; 51 | } 52 | 53 | return [self.guid isEqualToString:[object guid]]; 54 | } 55 | 56 | - (NSUInteger)hash 57 | { 58 | return [self.guid hash]; 59 | } 60 | 61 | @end 62 | 63 | // ********************************************************* 64 | // 65 | // O365-iOS-EmailPeek, https://github.com/OfficeDev/O365-iOS-EmailPeek 66 | // 67 | // Copyright (c) Microsoft Corporation 68 | // All rights reserved. 69 | // 70 | // MIT License: 71 | // Permission is hereby granted, free of charge, to any person obtaining 72 | // a copy of this software and associated documentation files (the 73 | // "Software"), to deal in the Software without restriction, including 74 | // without limitation the rights to use, copy, modify, merge, publish, 75 | // distribute, sublicense, and/or sell copies of the Software, and to 76 | // permit persons to whom the Software is furnished to do so, subject to 77 | // the following conditions: 78 | // 79 | // The above copyright notice and this permission notice shall be 80 | // included in all copies or substantial portions of the Software. 81 | // 82 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 83 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 84 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 85 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 86 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 87 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 88 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 89 | // 90 | // ********************************************************* 91 | 92 | -------------------------------------------------------------------------------- /EmailPeek/MessageFilter.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Microsoft. All rights reserved. Licensed under the MIT license. 3 | * See full license at the bottom of this file. 4 | */ 5 | 6 | #import 7 | 8 | #import "Message.h" 9 | 10 | @protocol MessageFilter 11 | 12 | - (NSString *)serverSideFilter; 13 | 14 | @end 15 | 16 | // ********************************************************* 17 | // 18 | // O365-iOS-EmailPeek, https://github.com/OfficeDev/O365-iOS-EmailPeek 19 | // 20 | // Copyright (c) Microsoft Corporation 21 | // All rights reserved. 22 | // 23 | // MIT License: 24 | // Permission is hereby granted, free of charge, to any person obtaining 25 | // a copy of this software and associated documentation files (the 26 | // "Software"), to deal in the Software without restriction, including 27 | // without limitation the rights to use, copy, modify, merge, publish, 28 | // distribute, sublicense, and/or sell copies of the Software, and to 29 | // permit persons to whom the Software is furnished to do so, subject to 30 | // the following conditions: 31 | // 32 | // The above copyright notice and this permission notice shall be 33 | // included in all copies or substantial portions of the Software. 34 | // 35 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 36 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 37 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 38 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 39 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 40 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 41 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 42 | // 43 | // ********************************************************* 44 | -------------------------------------------------------------------------------- /EmailPeek/MessagePreview.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Microsoft. All rights reserved. Licensed under the MIT license. 3 | * See full license at the bottom of this file. 4 | */ 5 | 6 | #import 7 | 8 | #import "EmailAddress.h" 9 | 10 | typedef NS_ENUM(NSUInteger, MessageImportance) { 11 | MessageImportanceLow, 12 | MessageImportanceNormal, 13 | MessageImportanceHigh, 14 | }; 15 | 16 | @protocol MessagePreview 17 | 18 | @property (readonly, nonatomic) NSString *guid; 19 | @property (readonly, nonatomic) NSString *conversationGUID; 20 | @property (readonly, nonatomic) NSString *subject; 21 | @property (readonly, nonatomic) EmailAddress *sender; 22 | @property (readonly, nonatomic) NSArray *toRecipients; 23 | @property (readonly, nonatomic) NSArray *ccRecipients; 24 | @property (readonly, nonatomic) NSString *bodyPreview; 25 | @property (readonly, nonatomic) NSDate *dateReceived; 26 | @property (readonly, nonatomic) BOOL isReadOnServer; 27 | @property (readonly, nonatomic) BOOL isReadOnClient; 28 | @property (readonly, nonatomic) BOOL isRead; 29 | @property (readonly, nonatomic) BOOL isHidden; 30 | @property (readonly, nonatomic) BOOL hasAttachments; 31 | @property (readonly, nonatomic) MessageImportance importance; 32 | @property (readonly, nonatomic) NSArray *categories; 33 | @property (readonly, nonatomic) NSUInteger messageCount; 34 | 35 | - (NSComparisonResult)compare:(id)object; 36 | 37 | @end 38 | 39 | // ********************************************************* 40 | // 41 | // O365-iOS-EmailPeek, https://github.com/OfficeDev/O365-iOS-EmailPeek 42 | // 43 | // Copyright (c) Microsoft Corporation 44 | // All rights reserved. 45 | // 46 | // MIT License: 47 | // Permission is hereby granted, free of charge, to any person obtaining 48 | // a copy of this software and associated documentation files (the 49 | // "Software"), to deal in the Software without restriction, including 50 | // without limitation the rights to use, copy, modify, merge, publish, 51 | // distribute, sublicense, and/or sell copies of the Software, and to 52 | // permit persons to whom the Software is furnished to do so, subject to 53 | // the following conditions: 54 | // 55 | // The above copyright notice and this permission notice shall be 56 | // included in all copies or substantial portions of the Software. 57 | // 58 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 59 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 60 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 61 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 62 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 63 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 64 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 65 | // 66 | // ********************************************************* 67 | -------------------------------------------------------------------------------- /EmailPeek/MessagePreviewCell.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Microsoft. All rights reserved. Licensed under the MIT license. 3 | * See full license at the bottom of this file. 4 | */ 5 | 6 | #import 7 | 8 | #import "MessagePreview.h" 9 | 10 | /* 11 | This cell is used in two different places--ConversationListViewController and 12 | ConversationViewController. 13 | */ 14 | @interface MessagePreviewCell : UITableViewCell 15 | 16 | @property (strong, nonatomic) id messagePreview; 17 | 18 | @end 19 | 20 | // ********************************************************* 21 | // 22 | // O365-iOS-EmailPeek, https://github.com/OfficeDev/O365-iOS-EmailPeek 23 | // 24 | // Copyright (c) Microsoft Corporation 25 | // All rights reserved. 26 | // 27 | // MIT License: 28 | // Permission is hereby granted, free of charge, to any person obtaining 29 | // a copy of this software and associated documentation files (the 30 | // "Software"), to deal in the Software without restriction, including 31 | // without limitation the rights to use, copy, modify, merge, publish, 32 | // distribute, sublicense, and/or sell copies of the Software, and to 33 | // permit persons to whom the Software is furnished to do so, subject to 34 | // the following conditions: 35 | // 36 | // The above copyright notice and this permission notice shall be 37 | // included in all copies or substantial portions of the Software. 38 | // 39 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 40 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 41 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 42 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 43 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 44 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 45 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 46 | // 47 | // ********************************************************* -------------------------------------------------------------------------------- /EmailPeek/MessagePreviewCell.m: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Microsoft. All rights reserved. Licensed under the MIT license. 3 | * See full license at the bottom of this file. 4 | */ 5 | 6 | #import "MessagePreviewCell.h" 7 | 8 | #import "UIColor+Office365.h" 9 | #import "NSDate+Office365.h" 10 | #import "Message.h" 11 | #import "Conversation.h" 12 | 13 | const UILayoutPriority kEnableConstraintPriority = 950; 14 | const UILayoutPriority kDisableConstraintPriority = 850; 15 | 16 | @interface MessagePreviewCell () 17 | 18 | @property (weak, nonatomic) IBOutlet UIView *messageStateView; 19 | @property (weak, nonatomic) IBOutlet UILabel *senderLabel; 20 | @property (weak, nonatomic) IBOutlet UILabel *subjectLabel; 21 | @property (weak, nonatomic) IBOutlet UILabel *bodyPreviewLabel; 22 | @property (weak, nonatomic) IBOutlet UILabel *dateReceivedLabel; 23 | @property (weak, nonatomic) IBOutlet UILabel *messageCountLabel; 24 | @property (weak, nonatomic) IBOutlet UIView *messageCountBackgroundView; 25 | 26 | @property (weak, nonatomic) IBOutlet NSLayoutConstraint *messageCountBackgroundViewWidthConstraint; 27 | @property (weak, nonatomic) IBOutlet NSLayoutConstraint *importanceLabelWidthConstraint; 28 | @property (weak, nonatomic) IBOutlet NSLayoutConstraint *attachmentsLabelWidthConstraint; 29 | 30 | @end 31 | 32 | @implementation MessagePreviewCell 33 | 34 | #pragma mark - Lifecycle 35 | - (void)awakeFromNib 36 | { 37 | [super awakeFromNib]; 38 | 39 | [self setupUI]; 40 | } 41 | 42 | 43 | #pragma mark - Properties 44 | - (void)setMessagePreview:(id)messagePreview 45 | { 46 | _messagePreview = messagePreview; 47 | 48 | [self updateUI]; 49 | } 50 | 51 | 52 | #pragma mark - UI Setup/Update 53 | - (void)setupUI 54 | { 55 | self.preservesSuperviewLayoutMargins = NO; 56 | 57 | self.selectedBackgroundView = [[UIView alloc] init]; 58 | self.selectedBackgroundView.backgroundColor = [UIColor o365_primaryHighlightColor]; 59 | 60 | self.messageCountBackgroundView.layer.cornerRadius = CGRectGetHeight(self.messageCountBackgroundView.bounds) / 2.0; 61 | self.messageCountBackgroundView.layer.masksToBounds = YES; 62 | self.messageCountBackgroundView.backgroundColor = [UIColor o365_primaryColor]; 63 | } 64 | 65 | -(void)updateUI 66 | { 67 | self.subjectLabel.text = self.messagePreview.subject; 68 | self.senderLabel.text = self.messagePreview.sender.name; 69 | self.dateReceivedLabel.text = [self.messagePreview.dateReceived o365_relativeString]; 70 | self.bodyPreviewLabel.text = self.messagePreview.bodyPreview; 71 | self.messageCountLabel.text = [NSString stringWithFormat:@"%lu", (unsigned long)self.messagePreview.messageCount]; 72 | self.messageStateView.backgroundColor = [self stateViewColor]; 73 | 74 | // These aspects are either shown or hidden 75 | self.attachmentsLabelWidthConstraint.priority = self.messagePreview.hasAttachments ? kEnableConstraintPriority : kDisableConstraintPriority; 76 | self.importanceLabelWidthConstraint.priority = self.messagePreview.importance == MessageImportanceHigh ? kEnableConstraintPriority : kDisableConstraintPriority; 77 | self.messageCountBackgroundViewWidthConstraint.priority = self.messagePreview.messageCount > 1 ? kEnableConstraintPriority : kDisableConstraintPriority; 78 | } 79 | 80 | - (UIColor *)stateViewColor 81 | { 82 | if (self.highlighted || self.selected) { return [UIColor o365_primaryColor]; } 83 | if (!self.messagePreview.isRead) { return [UIColor o365_unreadMessageColor]; } 84 | 85 | return [UIColor o365_defaultMessageColor]; 86 | } 87 | 88 | - (void)setHighlighted:(BOOL)highlighted 89 | animated:(BOOL)animated 90 | { 91 | [super setHighlighted:highlighted 92 | animated:animated]; 93 | 94 | [self updateBackgroundColors]; 95 | } 96 | 97 | - (void)setSelected:(BOOL)selected 98 | animated:(BOOL)animated 99 | { 100 | [super setSelected:selected 101 | animated:animated]; 102 | 103 | [self updateBackgroundColors]; 104 | } 105 | 106 | - (void)updateBackgroundColors 107 | { 108 | // NOTE: If we don't explicitly set this color again, it will be set to 109 | // transparent by default 110 | self.messageCountBackgroundView.backgroundColor = [UIColor o365_primaryColor]; 111 | self.messageStateView.backgroundColor = [self stateViewColor]; 112 | } 113 | 114 | @end 115 | 116 | // ********************************************************* 117 | // 118 | // O365-iOS-EmailPeek, https://github.com/OfficeDev/O365-iOS-EmailPeek 119 | // 120 | // Copyright (c) Microsoft Corporation 121 | // All rights reserved. 122 | // 123 | // MIT License: 124 | // Permission is hereby granted, free of charge, to any person obtaining 125 | // a copy of this software and associated documentation files (the 126 | // "Software"), to deal in the Software without restriction, including 127 | // without limitation the rights to use, copy, modify, merge, publish, 128 | // distribute, sublicense, and/or sell copies of the Software, and to 129 | // permit persons to whom the Software is furnished to do so, subject to 130 | // the following conditions: 131 | // 132 | // The above copyright notice and this permission notice shall be 133 | // included in all copies or substantial portions of the Software. 134 | // 135 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 136 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 137 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 138 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 139 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 140 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 141 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 142 | // 143 | // ********************************************************* 144 | -------------------------------------------------------------------------------- /EmailPeek/MessageViewController.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Microsoft. All rights reserved. Licensed under the MIT license. 3 | * See full license at the bottom of this file. 4 | */ 5 | 6 | #import 7 | 8 | @class Message; 9 | @class ConversationManager; 10 | 11 | @protocol MessageViewControllerDelegate; 12 | 13 | @interface MessageViewController : UIViewController 14 | 15 | @property (strong, nonatomic) ConversationManager *conversationManager; 16 | @property (strong, nonatomic) Message *message; 17 | 18 | @property (weak, nonatomic) id delegate; 19 | 20 | @end 21 | 22 | @protocol MessageViewControllerDelegate 23 | 24 | - (BOOL) messageViewController:(MessageViewController *)messageViewController 25 | isFollowingSenderForMessage:(Message *)message; 26 | - (BOOL) messageViewController:(MessageViewController *)messageViewController 27 | isFollowingConversationForMessage:(Message *)message; 28 | 29 | - (void)messageViewController:(MessageViewController *)messageViewController 30 | shouldFollowSender:(BOOL)shouldFollow 31 | forMessage:(Message *)message; 32 | - (void) messageViewController:(MessageViewController *)messageViewController 33 | shouldFollowConversation:(BOOL)shouldFollow 34 | forMessage:(Message *)message; 35 | 36 | 37 | - (void)messageViewController:(MessageViewController *)messageViewController 38 | shouldReplyAll:(BOOL)replyAll 39 | toMessage:(Message *)message 40 | withResponse:(NSString *)response; 41 | 42 | @end 43 | 44 | // ********************************************************* 45 | // 46 | // O365-iOS-EmailPeek, https://github.com/OfficeDev/O365-iOS-EmailPeek 47 | // 48 | // Copyright (c) Microsoft Corporation 49 | // All rights reserved. 50 | // 51 | // MIT License: 52 | // Permission is hereby granted, free of charge, to any person obtaining 53 | // a copy of this software and associated documentation files (the 54 | // "Software"), to deal in the Software without restriction, including 55 | // without limitation the rights to use, copy, modify, merge, publish, 56 | // distribute, sublicense, and/or sell copies of the Software, and to 57 | // permit persons to whom the Software is furnished to do so, subject to 58 | // the following conditions: 59 | // 60 | // The above copyright notice and this permission notice shall be 61 | // included in all copies or substantial portions of the Software. 62 | // 63 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 64 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 65 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 66 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 67 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 68 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 69 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 70 | // 71 | // ********************************************************* -------------------------------------------------------------------------------- /EmailPeek/NSDate+Office365.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Microsoft. All rights reserved. Licensed under the MIT license. 3 | * See full license at the bottom of this file. 4 | */ 5 | 6 | #import 7 | 8 | //Helpers for formatting dates 9 | @interface NSDate (Office365) 10 | 11 | - (NSString *)o365_relativeString; 12 | - (NSString *)o365_mediumString; 13 | 14 | @end 15 | 16 | // ********************************************************* 17 | // 18 | // O365-iOS-EmailPeek, https://github.com/OfficeDev/O365-iOS-EmailPeek 19 | // 20 | // Copyright (c) Microsoft Corporation 21 | // All rights reserved. 22 | // 23 | // MIT License: 24 | // Permission is hereby granted, free of charge, to any person obtaining 25 | // a copy of this software and associated documentation files (the 26 | // "Software"), to deal in the Software without restriction, including 27 | // without limitation the rights to use, copy, modify, merge, publish, 28 | // distribute, sublicense, and/or sell copies of the Software, and to 29 | // permit persons to whom the Software is furnished to do so, subject to 30 | // the following conditions: 31 | // 32 | // The above copyright notice and this permission notice shall be 33 | // included in all copies or substantial portions of the Software. 34 | // 35 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 36 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 37 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 38 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 39 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 40 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 41 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 42 | // 43 | // ********************************************************* 44 | -------------------------------------------------------------------------------- /EmailPeek/NSDate+Office365.m: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Microsoft. All rights reserved. Licensed under the MIT license. 3 | * See full license at the bottom of this file. 4 | */ 5 | 6 | #import "NSDate+Office365.h" 7 | 8 | //Helpers for formatting dates 9 | @implementation NSDate (Office365) 10 | 11 | - (NSString *)o365_relativeString 12 | { 13 | NSString *relativeDate; 14 | NSCalendar *currentCalendar = [NSCalendar currentCalendar]; 15 | NSTimeInterval secondsBackForDayOnly = 6 * 60 * 60 * 24; 16 | NSDate *dayOnlyCutoffDate = [NSDate dateWithTimeIntervalSinceNow:-secondsBackForDayOnly]; 17 | 18 | if ([currentCalendar isDateInToday:self]) { 19 | relativeDate = [NSDateFormatter localizedStringFromDate:self 20 | dateStyle:NSDateFormatterNoStyle 21 | timeStyle:NSDateFormatterShortStyle]; 22 | } 23 | else if ([currentCalendar isDateInYesterday:self]) { 24 | relativeDate = @"Yesterday"; 25 | } 26 | else if ([self compare:dayOnlyCutoffDate] == NSOrderedDescending) { 27 | NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init]; 28 | 29 | dateFormatter.dateFormat = @"EEEE"; 30 | 31 | relativeDate = [dateFormatter stringFromDate:self]; 32 | } 33 | else { 34 | relativeDate = [NSDateFormatter localizedStringFromDate:self 35 | dateStyle:NSDateFormatterShortStyle 36 | timeStyle:NSDateFormatterNoStyle]; 37 | } 38 | 39 | return relativeDate; 40 | } 41 | 42 | - (NSString *)o365_mediumString 43 | { 44 | static NSDateFormatter *dateFormatter; 45 | 46 | if (!dateFormatter) { 47 | dateFormatter = [[NSDateFormatter alloc] init]; 48 | 49 | dateFormatter.dateFormat = @"MMMM d, YYYY 'at' h:mm a"; 50 | } 51 | 52 | return [dateFormatter stringFromDate:self]; 53 | } 54 | 55 | @end 56 | 57 | // ********************************************************* 58 | // 59 | // O365-iOS-EmailPeek, https://github.com/OfficeDev/O365-iOS-EmailPeek 60 | // 61 | // Copyright (c) Microsoft Corporation 62 | // All rights reserved. 63 | // 64 | // MIT License: 65 | // Permission is hereby granted, free of charge, to any person obtaining 66 | // a copy of this software and associated documentation files (the 67 | // "Software"), to deal in the Software without restriction, including 68 | // without limitation the rights to use, copy, modify, merge, publish, 69 | // distribute, sublicense, and/or sell copies of the Software, and to 70 | // permit persons to whom the Software is furnished to do so, subject to 71 | // the following conditions: 72 | // 73 | // The above copyright notice and this permission notice shall be 74 | // included in all copies or substantial portions of the Software. 75 | // 76 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 77 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 78 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 79 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 80 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 81 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 82 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 83 | // 84 | // ********************************************************* 85 | 86 | -------------------------------------------------------------------------------- /EmailPeek/NothingFilter.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Microsoft. All rights reserved. Licensed under the MIT license. 3 | * See full license at the bottom of this file. 4 | */ 5 | 6 | #import "MessageFilter.h" 7 | 8 | /** 9 | This is a filter that will not match any messages. It is used in 10 | every request since all of the filters are "or'd" together, if there 11 | weren't any present, all items would be returned instead of none. 12 | */ 13 | @interface NothingFilter : NSObject 14 | 15 | @end 16 | 17 | // ********************************************************* 18 | // 19 | // O365-iOS-EmailPeek, https://github.com/OfficeDev/O365-iOS-EmailPeek 20 | // 21 | // Copyright (c) Microsoft Corporation 22 | // All rights reserved. 23 | // 24 | // MIT License: 25 | // Permission is hereby granted, free of charge, to any person obtaining 26 | // a copy of this software and associated documentation files (the 27 | // "Software"), to deal in the Software without restriction, including 28 | // without limitation the rights to use, copy, modify, merge, publish, 29 | // distribute, sublicense, and/or sell copies of the Software, and to 30 | // permit persons to whom the Software is furnished to do so, subject to 31 | // the following conditions: 32 | // 33 | // The above copyright notice and this permission notice shall be 34 | // included in all copies or substantial portions of the Software. 35 | // 36 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 37 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 38 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 39 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 40 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 41 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 42 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 43 | // 44 | // ********************************************************* 45 | -------------------------------------------------------------------------------- /EmailPeek/NothingFilter.m: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Microsoft. All rights reserved. Licensed under the MIT license. 3 | * See full license at the bottom of this file. 4 | */ 5 | 6 | #import "NothingFilter.h" 7 | 8 | @implementation NothingFilter 9 | 10 | #pragma mark - NSCoding 11 | - (instancetype)initWithCoder:(NSCoder *)aDecoder 12 | { 13 | return [super init]; 14 | } 15 | 16 | - (void)encodeWithCoder:(NSCoder *)aCoder 17 | { 18 | } 19 | 20 | 21 | #pragma mark - MessageFilter 22 | - (NSString *)serverSideFilter 23 | { 24 | return @"Id eq 'bogus'"; 25 | } 26 | 27 | @end 28 | 29 | // ********************************************************* 30 | // 31 | // O365-iOS-EmailPeek, https://github.com/OfficeDev/O365-iOS-EmailPeek 32 | // 33 | // Copyright (c) Microsoft Corporation 34 | // All rights reserved. 35 | // 36 | // MIT License: 37 | // Permission is hereby granted, free of charge, to any person obtaining 38 | // a copy of this software and associated documentation files (the 39 | // "Software"), to deal in the Software without restriction, including 40 | // without limitation the rights to use, copy, modify, merge, publish, 41 | // distribute, sublicense, and/or sell copies of the Software, and to 42 | // permit persons to whom the Software is furnished to do so, subject to 43 | // the following conditions: 44 | // 45 | // The above copyright notice and this permission notice shall be 46 | // included in all copies or substantial portions of the Software. 47 | // 48 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 49 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 50 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 51 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 52 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 53 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 54 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 55 | // 56 | // ********************************************************* 57 | -------------------------------------------------------------------------------- /EmailPeek/Office365Client.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Microsoft. All rights reserved. Licensed under the MIT license. 3 | * See full license at the bottom of this file. 4 | */ 5 | 6 | #import 7 | 8 | @class Message; 9 | @class MessageDetail; 10 | 11 | extern NSString * const Office365ClientDidConnectNotification; 12 | extern NSString * const Office365ClientDidDisconnectNotification; 13 | 14 | 15 | // The main class that talks to Office 365 and performs operations in Outlook 16 | @interface Office365Client : NSObject 17 | 18 | // Dependencies 19 | @property (strong, nonatomic) NSNotificationCenter *notificationCenter; 20 | 21 | // App specific credentials provided by Azure when registering the app 22 | @property (readonly, nonatomic) NSString *clientId; 23 | @property (readonly, nonatomic) NSURL *redirectURL; 24 | @property (readonly, nonatomic) NSURL *authorityURL; 25 | 26 | // Convenience 27 | @property (readonly, nonatomic) BOOL isConnected; 28 | 29 | - (instancetype)initWithClientId:(NSString *)clientId 30 | redirectURL:(NSURL *)redirectURL 31 | authorityURL:(NSURL *)authorityURL; 32 | 33 | // Connect and disconnect from Office 365 34 | - (void)connectWithCompletionHandler:(void (^)(BOOL success, NSError *error))completionHandler; 35 | - (void)disconnectWithCompletionHandler:(void (^)(BOOL success, NSError *error))completionHandler; 36 | 37 | // Perform mail operations in Outlook 38 | - (void)fetchMessagesFromDate:(NSDate *)fromDate 39 | withFilter:(NSString *)filter 40 | completionHandler:(void (^)(NSSet *messages, NSError *error))completionHandler; 41 | 42 | - (void)fetchMessageDetailForMessage:(Message *)message 43 | completionHandler:(void (^)(MessageDetail *messageDetail, NSError *error))completionHandler; 44 | 45 | - (void)replyToMessage:(Message *)message 46 | replyAll:(BOOL)replyAll 47 | responseBody:(NSString *)responseBody 48 | completionHandler:(void (^)(BOOL success, NSError *error))completionHandler; 49 | 50 | - (void) markMessage:(Message *)message 51 | isRead:(BOOL)isRead 52 | updateOutlookFlag:(BOOL)updateOutlookFlag 53 | completionHandler:(void (^)(Message *updatedMessage, NSError *error))completionHandler; 54 | 55 | - (void) markMessage:(Message *)message 56 | isHidden:(BOOL)isHidden 57 | completionHandler:(void (^)(Message *updatedMessage, NSError *error))completionHandler; 58 | 59 | @end 60 | 61 | // ********************************************************* 62 | // 63 | // O365-iOS-EmailPeek, https://github.com/OfficeDev/O365-iOS-EmailPeek 64 | // 65 | // Copyright (c) Microsoft Corporation 66 | // All rights reserved. 67 | // 68 | // MIT License: 69 | // Permission is hereby granted, free of charge, to any person obtaining 70 | // a copy of this software and associated documentation files (the 71 | // "Software"), to deal in the Software without restriction, including 72 | // without limitation the rights to use, copy, modify, merge, publish, 73 | // distribute, sublicense, and/or sell copies of the Software, and to 74 | // permit persons to whom the Software is furnished to do so, subject to 75 | // the following conditions: 76 | // 77 | // The above copyright notice and this permission notice shall be 78 | // included in all copies or substantial portions of the Software. 79 | // 80 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 81 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 82 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 83 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 84 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 85 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 86 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 87 | // 88 | // ********************************************************* 89 | 90 | -------------------------------------------------------------------------------- /EmailPeek/Office365ObjectTransformer.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Microsoft. All rights reserved. Licensed under the MIT license. 3 | * See full license at the bottom of this file. 4 | */ 5 | 6 | #import 7 | 8 | @class Message; 9 | @class MessageDetail; 10 | @class EmailAddress; 11 | @class MSOutlookMessage; 12 | @class MSOutlookRecipient; 13 | 14 | extern NSString * const MessageCategoryIsReadOnClient; 15 | extern NSString * const MessageCategoryIsHiddenOnClient; 16 | 17 | @interface Office365ObjectTransformer : NSObject 18 | 19 | // Convert from MSOutlookMessage to Message 20 | - (NSString *)outlookMessageFieldsForMessage; 21 | - (Message *)messageFromOutlookMessage:(MSOutlookMessage *)outlookMessage; 22 | - (NSArray *)messagesFromOutlookMessages:(NSArray *)outlookMessages; 23 | 24 | - (NSString *)outlookMessageFieldsForMessageDetail; 25 | - (MessageDetail *)messageDetailFromOutlookMessage:(MSOutlookMessage *)outlookMessage; 26 | 27 | @end 28 | 29 | // ********************************************************* 30 | // 31 | // O365-iOS-EmailPeek, https://github.com/OfficeDev/O365-iOS-EmailPeek 32 | // 33 | // Copyright (c) Microsoft Corporation 34 | // All rights reserved. 35 | // 36 | // MIT License: 37 | // Permission is hereby granted, free of charge, to any person obtaining 38 | // a copy of this software and associated documentation files (the 39 | // "Software"), to deal in the Software without restriction, including 40 | // without limitation the rights to use, copy, modify, merge, publish, 41 | // distribute, sublicense, and/or sell copies of the Software, and to 42 | // permit persons to whom the Software is furnished to do so, subject to 43 | // the following conditions: 44 | // 45 | // The above copyright notice and this permission notice shall be 46 | // included in all copies or substantial portions of the Software. 47 | // 48 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 49 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 50 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 51 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 52 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 53 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 54 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 55 | // 56 | // ********************************************************* 57 | -------------------------------------------------------------------------------- /EmailPeek/Office365ObjectTransformer.m: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Microsoft. All rights reserved. Licensed under the MIT license. 3 | * See full license at the bottom of this file. 4 | */ 5 | 6 | #import "Office365ObjectTransformer.h" 7 | 8 | #import "Message.h" 9 | #import "MessageDetail.h" 10 | #import "MessageAttachment.h" 11 | 12 | #import "MSOutlookMessage.h" 13 | #import "MSOutlookItemBody.h" 14 | #import "MSOutlookRecipient.h" 15 | #import "MSOutlookEmailAddress.h" 16 | #import "MSOutlookAttachment.h" 17 | 18 | NSString * const MessageCategoryIsReadOnClient = @"EmailPeek - Read"; 19 | NSString * const MessageCategoryIsHiddenOnClient = @"EmailPeek - Hidden"; 20 | 21 | @implementation Office365ObjectTransformer 22 | 23 | // Convert from MSOutlookMessage to Message 24 | #pragma mark - Message 25 | // Ignored fields 26 | // * $$__ODataType 27 | // * From 28 | // * BccRecipients 29 | // * ReplyTo 30 | // * DateTimeSent 31 | // * IsDeliveryReceiptRequested 32 | // * IsReadReceiptRequested 33 | // * IsDraft 34 | // * ParentFolderId 35 | // * ChangeKey 36 | // * DateTimeCreated 37 | // * DateTimeLastModified 38 | - (NSString *)outlookMessageFieldsForMessage 39 | { 40 | return [@[@"Id", 41 | @"ConversationId", 42 | @"Subject", 43 | @"Sender", 44 | @"ToRecipients", 45 | @"CcRecipients", 46 | @"BodyPreview", 47 | @"DateTimeReceived", 48 | @"IsRead", 49 | @"HasAttachments", 50 | @"Importance", 51 | @"Categories"] componentsJoinedByString:@","]; 52 | } 53 | 54 | - (Message *)messageFromOutlookMessage:(MSOutlookMessage *)outlookMessage 55 | { 56 | if (!outlookMessage) { 57 | return nil; 58 | } 59 | 60 | return [[Message alloc] initWithGUID:outlookMessage.Id 61 | conversationGUID:outlookMessage.ConversationId 62 | subject:outlookMessage.Subject 63 | sender:[self emailAddressFromOutlookRecipient:outlookMessage.Sender] 64 | toRecipients:[self emailAddressesFromOutlookRecipients:outlookMessage.ToRecipients] 65 | ccRecipients:[self emailAddressesFromOutlookRecipients:outlookMessage.CcRecipients] 66 | bodyPreview:outlookMessage.BodyPreview 67 | dateReceived:outlookMessage.DateTimeReceived 68 | isReadOnServer:outlookMessage.IsRead 69 | isReadOnClient:[outlookMessage.Categories containsObject:MessageCategoryIsReadOnClient] 70 | isHidden:[outlookMessage.Categories containsObject:MessageCategoryIsHiddenOnClient] 71 | hasAttachments:outlookMessage.HasAttachments 72 | importance:[self messageImportanceFromOutlookImportance:outlookMessage.Importance] 73 | categories:outlookMessage.Categories]; 74 | } 75 | 76 | - (NSArray *)messagesFromOutlookMessages:(NSArray *)outlookMessages 77 | { 78 | if (!outlookMessages) { 79 | return nil; 80 | } 81 | 82 | NSMutableArray *messages = [[NSMutableArray alloc] initWithCapacity:outlookMessages.count]; 83 | 84 | for (MSOutlookMessage *outlookMessage in outlookMessages) { 85 | [messages addObject:[self messageFromOutlookMessage:outlookMessage]]; 86 | } 87 | 88 | return [messages copy]; 89 | } 90 | 91 | #pragma mark - MessageDetail 92 | // Ignored fields 93 | // * Body.$$__ODataType 94 | // * UniqueBody.$$__ODataType 95 | - (NSString *)outlookMessageFieldsForMessageDetail 96 | { 97 | return [@[@"Id", 98 | @"Body", 99 | @"UniqueBody", 100 | @"Attachments"] componentsJoinedByString:@","]; 101 | } 102 | 103 | - (MessageDetail *)messageDetailFromOutlookMessage:(MSOutlookMessage *)outlookMessage 104 | { 105 | if (!outlookMessage) { 106 | return nil; 107 | } 108 | 109 | return [[MessageDetail alloc] initWithGUID:outlookMessage.Id 110 | body:outlookMessage.Body.Content 111 | isBodyHTML:outlookMessage.Body.ContentType == MSOutlook_BodyType_HTML 112 | uniqueBody:outlookMessage.UniqueBody.Content 113 | isUniqueBodyHTML:outlookMessage.UniqueBody.ContentType == MSOutlook_BodyType_HTML 114 | attachments:[self messageAttachmentsFromOutlookAttachments:outlookMessage.Attachments]]; 115 | } 116 | 117 | 118 | #pragma mark - MessageImportance 119 | - (MessageImportance)messageImportanceFromOutlookImportance:(MSOutlookImportance)outlookImportance 120 | { 121 | MessageImportance importance; 122 | 123 | switch (outlookImportance) { 124 | case MSOutlook_Importance_Low: 125 | importance = MessageImportanceLow; 126 | break; 127 | case MSOutlook_Importance_Normal: 128 | importance = MessageImportanceNormal; 129 | break; 130 | case MSOutlook_Importance_High: 131 | importance = MessageImportanceHigh; 132 | break; 133 | } 134 | 135 | return importance; 136 | } 137 | 138 | 139 | #pragma mark - EmailAddress 140 | // Ignored fields 141 | // * $$__ODataType 142 | // * EmailAddress.$$__ODataType 143 | - (EmailAddress *)emailAddressFromOutlookRecipient:(MSOutlookRecipient *)outlookRecipient 144 | { 145 | if (!outlookRecipient) { 146 | return nil; 147 | } 148 | 149 | return [[EmailAddress alloc] initWithName:outlookRecipient.EmailAddress.Name 150 | address:outlookRecipient.EmailAddress.Address]; 151 | } 152 | 153 | - (NSArray *)emailAddressesFromOutlookRecipients:(NSArray *)outlookRecipients 154 | { 155 | if (!outlookRecipients) { 156 | return nil; 157 | } 158 | 159 | NSMutableArray *emailAddresses = [[NSMutableArray alloc] initWithCapacity:outlookRecipients.count]; 160 | 161 | for (MSOutlookRecipient *outlookRecipient in outlookRecipients) { 162 | [emailAddresses addObject:[self emailAddressFromOutlookRecipient:outlookRecipient]]; 163 | } 164 | 165 | return [emailAddresses copy]; 166 | } 167 | 168 | 169 | #pragma mark - Attachment 170 | // Ignored fields 171 | // * $$__ODataType; 172 | // * IsInline 173 | // * DateTimeLastModified 174 | - (MessageAttachment *)messageAttachmentFromOutlookAttachment:(MSOutlookAttachment *)outlookAttachment 175 | { 176 | if (!outlookAttachment) { 177 | return nil; 178 | } 179 | 180 | return [[MessageAttachment alloc] initWithGUID:outlookAttachment.Id 181 | name:outlookAttachment.Name 182 | contentType:outlookAttachment.ContentType 183 | byteCount:(NSUInteger)outlookAttachment.Size]; 184 | } 185 | 186 | - (NSArray *)messageAttachmentsFromOutlookAttachments:(NSArray *)outlookAttachments 187 | { 188 | if (!outlookAttachments) { 189 | return nil; 190 | } 191 | 192 | NSMutableArray *attachments = [[NSMutableArray alloc] initWithCapacity:outlookAttachments.count]; 193 | 194 | for (MSOutlookAttachment *outlookAttachment in outlookAttachments) { 195 | [attachments addObject:[self messageAttachmentFromOutlookAttachment:outlookAttachment]]; 196 | } 197 | 198 | return [attachments copy]; 199 | } 200 | 201 | @end 202 | 203 | // ********************************************************* 204 | // 205 | // O365-iOS-EmailPeek, https://github.com/OfficeDev/O365-iOS-EmailPeek 206 | // 207 | // Copyright (c) Microsoft Corporation 208 | // All rights reserved. 209 | // 210 | // MIT License: 211 | // Permission is hereby granted, free of charge, to any person obtaining 212 | // a copy of this software and associated documentation files (the 213 | // "Software"), to deal in the Software without restriction, including 214 | // without limitation the rights to use, copy, modify, merge, publish, 215 | // distribute, sublicense, and/or sell copies of the Software, and to 216 | // permit persons to whom the Software is furnished to do so, subject to 217 | // the following conditions: 218 | // 219 | // The above copyright notice and this permission notice shall be 220 | // included in all copies or substantial portions of the Software. 221 | // 222 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 223 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 224 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 225 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 226 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 227 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 228 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 229 | // 230 | // ********************************************************* 231 | 232 | -------------------------------------------------------------------------------- /EmailPeek/SenderFilter.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Microsoft. All rights reserved. Licensed under the MIT license. 3 | * See full license at the bottom of this file. 4 | */ 5 | 6 | #import "MessageFilter.h" 7 | 8 | @class EmailAddress; 9 | 10 | @interface SenderFilter : NSObject 11 | 12 | @property (readonly, nonatomic) EmailAddress *emailAddress; 13 | 14 | - (instancetype)initWithEmailAddress:(EmailAddress *)emailAddress; 15 | 16 | @end 17 | 18 | // ********************************************************* 19 | // 20 | // O365-iOS-EmailPeek, https://github.com/OfficeDev/O365-iOS-EmailPeek 21 | // 22 | // Copyright (c) Microsoft Corporation 23 | // All rights reserved. 24 | // 25 | // MIT License: 26 | // Permission is hereby granted, free of charge, to any person obtaining 27 | // a copy of this software and associated documentation files (the 28 | // "Software"), to deal in the Software without restriction, including 29 | // without limitation the rights to use, copy, modify, merge, publish, 30 | // distribute, sublicense, and/or sell copies of the Software, and to 31 | // permit persons to whom the Software is furnished to do so, subject to 32 | // the following conditions: 33 | // 34 | // The above copyright notice and this permission notice shall be 35 | // included in all copies or substantial portions of the Software. 36 | // 37 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 38 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 39 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 40 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 41 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 42 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 43 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 44 | // 45 | // ********************************************************* 46 | -------------------------------------------------------------------------------- /EmailPeek/SenderFilter.m: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Microsoft. All rights reserved. Licensed under the MIT license. 3 | * See full license at the bottom of this file. 4 | */ 5 | 6 | #import "SenderFilter.h" 7 | 8 | #import "EmailAddress.h" 9 | 10 | @implementation SenderFilter 11 | 12 | #pragma mark - Initialization 13 | - (instancetype)init 14 | { 15 | return [self initWithEmailAddress:nil]; 16 | } 17 | 18 | - (instancetype)initWithEmailAddress:(EmailAddress *)emailAddress 19 | { 20 | self = [super init]; 21 | 22 | if (self) { 23 | _emailAddress = emailAddress; 24 | } 25 | 26 | return self; 27 | } 28 | 29 | 30 | #pragma mark - NSCoding 31 | - (instancetype)initWithCoder:(NSCoder *)aDecoder 32 | { 33 | self = [super init]; 34 | 35 | if (self) { 36 | _emailAddress = [aDecoder decodeObjectForKey:@"emailAddress"]; 37 | } 38 | 39 | return self; 40 | } 41 | 42 | - (void)encodeWithCoder:(NSCoder *)aCoder 43 | { 44 | [aCoder encodeObject:self.emailAddress forKey:@"emailAddress"]; 45 | } 46 | 47 | 48 | #pragma mark - NSObject 49 | - (NSString *)description 50 | { 51 | return [self.emailAddress description]; 52 | } 53 | 54 | - (BOOL)isEqual:(id)object 55 | { 56 | if (self == object) { 57 | return YES; 58 | } 59 | 60 | if (![object isKindOfClass:[SenderFilter class]]) { 61 | return NO; 62 | } 63 | 64 | return [self.emailAddress isEqual:[object emailAddress]]; 65 | } 66 | 67 | - (NSUInteger)hash 68 | { 69 | return [self.emailAddress hash]; 70 | } 71 | 72 | 73 | #pragma mark - MessageFilter 74 | - (NSString *)serverSideFilter 75 | { 76 | return [NSString stringWithFormat:@"Sender/EmailAddress/Address eq '%@'", self.emailAddress.address]; 77 | } 78 | 79 | @end 80 | 81 | // ********************************************************* 82 | // 83 | // O365-iOS-EmailPeek, https://github.com/OfficeDev/O365-iOS-EmailPeek 84 | // 85 | // Copyright (c) Microsoft Corporation 86 | // All rights reserved. 87 | // 88 | // MIT License: 89 | // Permission is hereby granted, free of charge, to any person obtaining 90 | // a copy of this software and associated documentation files (the 91 | // "Software"), to deal in the Software without restriction, including 92 | // without limitation the rights to use, copy, modify, merge, publish, 93 | // distribute, sublicense, and/or sell copies of the Software, and to 94 | // permit persons to whom the Software is furnished to do so, subject to 95 | // the following conditions: 96 | // 97 | // The above copyright notice and this permission notice shall be 98 | // included in all copies or substantial portions of the Software. 99 | // 100 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 101 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 102 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 103 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 104 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 105 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 106 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 107 | // 108 | // ********************************************************* 109 | 110 | -------------------------------------------------------------------------------- /EmailPeek/SenderFilterListViewController.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Microsoft. All rights reserved. Licensed under the MIT license. 3 | * See full license at the bottom of this file. 4 | */ 5 | 6 | #import 7 | 8 | @class SenderFilter; 9 | 10 | @protocol SenderFilterListViewControllerDelegate; 11 | 12 | @interface SenderFilterListViewController : UITableViewController 13 | 14 | @property (copy, nonatomic) NSArray *senderFilterList; 15 | 16 | @property (weak, nonatomic) id delegate; 17 | 18 | @end 19 | 20 | 21 | @protocol SenderFilterListViewControllerDelegate 22 | 23 | - (void)senderFilterListViewController:(SenderFilterListViewController *)senderFilterListVC 24 | didAddSenderFilter:(SenderFilter *)senderFilter; 25 | 26 | - (void)senderFilterListViewController:(SenderFilterListViewController *)senderFilterListVC 27 | didRemoveSenderFilter:(SenderFilter *)senderFilter; 28 | 29 | - (void)senderFilterListViewControllerDidComplete:(SenderFilterListViewController *)senderFilterListVC; 30 | 31 | @end 32 | 33 | // ********************************************************* 34 | // 35 | // O365-iOS-EmailPeek, https://github.com/OfficeDev/O365-iOS-EmailPeek 36 | // 37 | // Copyright (c) Microsoft Corporation 38 | // All rights reserved. 39 | // 40 | // MIT License: 41 | // Permission is hereby granted, free of charge, to any person obtaining 42 | // a copy of this software and associated documentation files (the 43 | // "Software"), to deal in the Software without restriction, including 44 | // without limitation the rights to use, copy, modify, merge, publish, 45 | // distribute, sublicense, and/or sell copies of the Software, and to 46 | // permit persons to whom the Software is furnished to do so, subject to 47 | // the following conditions: 48 | // 49 | // The above copyright notice and this permission notice shall be 50 | // included in all copies or substantial portions of the Software. 51 | // 52 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 53 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 54 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 55 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 56 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 57 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 58 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 59 | // 60 | // ********************************************************* -------------------------------------------------------------------------------- /EmailPeek/SenderFilterListViewController.m: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Microsoft. All rights reserved. Licensed under the MIT license. 3 | * See full license at the bottom of this file. 4 | */ 5 | 6 | #import "SenderFilterListViewController.h" 7 | 8 | #import "SenderFilter.h" 9 | 10 | @interface SenderFilterListViewController () 11 | 12 | // Track a mutable version internally even though we are exposing 13 | // an immutable version publicly 14 | @property (strong, nonatomic) NSMutableArray *mutableSenderFilterList; 15 | 16 | @end 17 | 18 | @implementation SenderFilterListViewController 19 | 20 | #pragma mark - Lifecycle 21 | - (void)viewWillDisappear:(BOOL)animated 22 | { 23 | [super viewWillDisappear:animated]; 24 | 25 | if (self.isMovingFromParentViewController) { 26 | [self.delegate senderFilterListViewControllerDidComplete:self]; 27 | } 28 | } 29 | 30 | #pragma mark - Properties 31 | - (void)setSenderFilterList:(NSArray *)senderFilterList 32 | { 33 | self.mutableSenderFilterList = [senderFilterList mutableCopy]; 34 | 35 | [self.tableView reloadData]; 36 | } 37 | 38 | - (NSArray *)senderFilterList 39 | { 40 | return [self.mutableSenderFilterList copy]; 41 | } 42 | 43 | - (NSMutableArray *)mutableSenderFilterList 44 | { 45 | if (!_mutableSenderFilterList) { 46 | _mutableSenderFilterList = [[NSMutableArray alloc] init]; 47 | } 48 | 49 | return _mutableSenderFilterList; 50 | } 51 | 52 | #pragma mark - Actions 53 | - (IBAction)addSenderTapped 54 | { 55 | UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"New Sender" 56 | message:@"Type the name and address of the sender you would like to follow." 57 | preferredStyle:UIAlertControllerStyleAlert]; 58 | 59 | [alertController addTextFieldWithConfigurationHandler:^(UITextField *textField) { 60 | textField.placeholder = @"John Doe"; 61 | textField.spellCheckingType = UITextSpellCheckingTypeNo; 62 | textField.autocapitalizationType = UITextAutocapitalizationTypeWords; 63 | textField.autocorrectionType = UITextAutocorrectionTypeNo; 64 | }]; 65 | 66 | [alertController addTextFieldWithConfigurationHandler:^(UITextField *textField) { 67 | textField.placeholder = @"email@sample.com"; 68 | textField.keyboardType = UIKeyboardTypeEmailAddress; 69 | textField.spellCheckingType = UITextSpellCheckingTypeNo; 70 | textField.autocapitalizationType = UITextAutocapitalizationTypeNone; 71 | textField.autocorrectionType = UITextAutocorrectionTypeNo; 72 | }]; 73 | 74 | UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:@"Cancel" 75 | style:UIAlertActionStyleCancel 76 | handler:NULL]; 77 | 78 | UIAlertAction *addAction = [UIAlertAction actionWithTitle:@"Add" 79 | style:UIAlertActionStyleDefault 80 | handler:^(UIAlertAction *action) { 81 | UITextField *nameField = alertController.textFields[0]; 82 | UITextField *emailField = alertController.textFields[1]; 83 | 84 | [self addSenderWithName:nameField.text 85 | address:emailField.text]; 86 | }]; 87 | 88 | [alertController addAction:cancelAction]; 89 | [alertController addAction:addAction]; 90 | 91 | [self presentViewController:alertController 92 | animated:YES 93 | completion:NULL]; 94 | } 95 | 96 | - (void)addSenderWithName:(NSString *)name 97 | address:(NSString *)address 98 | { 99 | name = [name stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]; 100 | address = [address stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]; 101 | 102 | if (address.length == 0) { 103 | return; 104 | } 105 | 106 | NSIndexPath *insertIndexPath = [NSIndexPath indexPathForRow:self.mutableSenderFilterList.count 107 | inSection:0]; 108 | 109 | EmailAddress *emailAddress = [[EmailAddress alloc] initWithName:name 110 | address:address]; 111 | SenderFilter *newFilter = [[SenderFilter alloc] initWithEmailAddress:emailAddress]; 112 | 113 | [self.mutableSenderFilterList addObject:newFilter]; 114 | 115 | [self.delegate senderFilterListViewController:self 116 | didAddSenderFilter:newFilter]; 117 | 118 | [self.tableView insertRowsAtIndexPaths:@[insertIndexPath] 119 | withRowAnimation:UITableViewRowAnimationAutomatic]; 120 | } 121 | 122 | #pragma mark - UITableViewDataSource 123 | - (NSInteger) tableView:(UITableView *)tableView 124 | numberOfRowsInSection:(NSInteger)section 125 | { 126 | return self.mutableSenderFilterList.count; 127 | } 128 | 129 | - (UITableViewCell *) tableView:(UITableView *)tableView 130 | cellForRowAtIndexPath:(NSIndexPath *)indexPath 131 | { 132 | UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"UITableViewCell" 133 | forIndexPath:indexPath]; 134 | 135 | SenderFilter *senderFilter = self.mutableSenderFilterList[indexPath.row]; 136 | 137 | cell.textLabel.text = senderFilter.emailAddress.name; 138 | cell.detailTextLabel.text = senderFilter.emailAddress.address; 139 | 140 | return cell; 141 | } 142 | 143 | - (BOOL) tableView:(UITableView *)tableView 144 | canEditRowAtIndexPath:(NSIndexPath *)indexPath 145 | { 146 | return YES; 147 | } 148 | 149 | - (void) tableView:(UITableView *)tableView 150 | commitEditingStyle:(UITableViewCellEditingStyle)editingStyle 151 | forRowAtIndexPath:(NSIndexPath *)indexPath 152 | { 153 | if (editingStyle != UITableViewCellEditingStyleDelete) { 154 | return; 155 | } 156 | 157 | SenderFilter *senderFilter = [self.mutableSenderFilterList objectAtIndex:indexPath.row]; 158 | 159 | [self.mutableSenderFilterList removeObjectAtIndex:indexPath.row]; 160 | 161 | [self.delegate senderFilterListViewController:self 162 | didRemoveSenderFilter:senderFilter]; 163 | 164 | [tableView deleteRowsAtIndexPaths:@[indexPath] 165 | withRowAnimation:UITableViewRowAnimationFade]; 166 | } 167 | 168 | @end 169 | 170 | // ********************************************************* 171 | // 172 | // O365-iOS-EmailPeek, https://github.com/OfficeDev/O365-iOS-EmailPeek 173 | // 174 | // Copyright (c) Microsoft Corporation 175 | // All rights reserved. 176 | // 177 | // MIT License: 178 | // Permission is hereby granted, free of charge, to any person obtaining 179 | // a copy of this software and associated documentation files (the 180 | // "Software"), to deal in the Software without restriction, including 181 | // without limitation the rights to use, copy, modify, merge, publish, 182 | // distribute, sublicense, and/or sell copies of the Software, and to 183 | // permit persons to whom the Software is furnished to do so, subject to 184 | // the following conditions: 185 | // 186 | // The above copyright notice and this permission notice shall be 187 | // included in all copies or substantial portions of the Software. 188 | // 189 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 190 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 191 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 192 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 193 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 194 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 195 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 196 | // 197 | // ********************************************************* 198 | -------------------------------------------------------------------------------- /EmailPeek/SettingsManager.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Microsoft. All rights reserved. Licensed under the MIT license. 3 | * See full license at the bottom of this file. 4 | */ 5 | 6 | #import 7 | 8 | #import "MessagePreview.h" 9 | 10 | @class SenderFilter; 11 | @class ConversationFilter; 12 | 13 | @interface SettingsManager : NSObject 14 | 15 | // General settings 16 | @property (assign, nonatomic) BOOL updateServerSideReadStatus; 17 | 18 | // Message consideration criteria 19 | @property (assign, nonatomic) NSUInteger daysBackToConsider; 20 | @property (readonly, nonatomic) NSDate *startingDate; 21 | 22 | @property (assign, nonatomic) BOOL includeUrgentMessages; 23 | @property (assign, nonatomic) BOOL includeUnreadMessages; 24 | 25 | @property (readonly, nonatomic) NSArray *senderFilterList; 26 | @property (readonly, nonatomic) NSArray *conversationFilterList; 27 | 28 | // Dependencies 29 | @property (strong, nonatomic) NSNotificationCenter *notificationCenter; 30 | 31 | 32 | - (void)restoreDefaultSettings; 33 | 34 | // When working with the original objects 35 | - (void)followSenderEmailAddress:(EmailAddress *)emailAddress; 36 | - (void)followConversation:(id)messagePreview; 37 | 38 | - (void)unfollowSenderEmailAddress:(EmailAddress *)emailAddress; 39 | - (void)unfollowConversation:(id)messagePreview; 40 | 41 | - (BOOL)isFollowingSenderEmailAddress:(EmailAddress *)emailAddress; 42 | - (BOOL)isFollowingConversation:(id)messagePreview; 43 | 44 | // When working with the MessageFilter objects 45 | - (void)addSenderFilter:(SenderFilter *)senderFilter; 46 | - (void)addConversationFilter:(ConversationFilter *)conversationFilter; 47 | 48 | - (void)removeSenderFilter:(SenderFilter *)senderFilter; 49 | - (void)removeConversationFilter:(ConversationFilter *)conversationFilter; 50 | 51 | - (BOOL)save; 52 | - (BOOL)reload; 53 | 54 | @end 55 | 56 | // ********************************************************* 57 | // 58 | // O365-iOS-EmailPeek, https://github.com/OfficeDev/O365-iOS-EmailPeek 59 | // 60 | // Copyright (c) Microsoft Corporation 61 | // All rights reserved. 62 | // 63 | // MIT License: 64 | // Permission is hereby granted, free of charge, to any person obtaining 65 | // a copy of this software and associated documentation files (the 66 | // "Software"), to deal in the Software without restriction, including 67 | // without limitation the rights to use, copy, modify, merge, publish, 68 | // distribute, sublicense, and/or sell copies of the Software, and to 69 | // permit persons to whom the Software is furnished to do so, subject to 70 | // the following conditions: 71 | // 72 | // The above copyright notice and this permission notice shall be 73 | // included in all copies or substantial portions of the Software. 74 | // 75 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 76 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 77 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 78 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 79 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 80 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 81 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 82 | // 83 | // ********************************************************* 84 | 85 | -------------------------------------------------------------------------------- /EmailPeek/SettingsManager.m: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Microsoft. All rights reserved. Licensed under the MIT license. 3 | * See full license at the bottom of this file. 4 | */ 5 | 6 | #import "SettingsManager.h" 7 | 8 | #import "SenderFilter.h" 9 | #import "ConversationFilter.h" 10 | #import "EmailAddress.h" 11 | 12 | static NSString * const kArchiveFileName = @"settings.archive"; 13 | 14 | @interface SettingsManager () 15 | 16 | @property (readonly, nonatomic) NSURL *saveURL; 17 | 18 | @property (strong, nonatomic) NSMutableArray *mutableSenderFilterList; 19 | @property (strong, nonatomic) NSMutableArray *mutableConversationFilterList; 20 | 21 | @end 22 | 23 | @implementation SettingsManager 24 | 25 | #pragma mark - Initialization 26 | - (instancetype)init 27 | { 28 | self = [super init]; 29 | 30 | if (self) { 31 | [self restoreDefaultSettings]; 32 | } 33 | 34 | return self; 35 | } 36 | 37 | 38 | #pragma mark - Properties 39 | - (NSURL *)saveURL 40 | { 41 | NSArray *documentURLs = [[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory 42 | inDomains:NSUserDomainMask]; 43 | 44 | return [documentURLs[0] URLByAppendingPathComponent:@"settings.archive"]; 45 | } 46 | 47 | - (NSMutableArray *)mutableSenderFilterList 48 | { 49 | if (!_mutableSenderFilterList) { 50 | _mutableSenderFilterList = [[NSMutableArray alloc] init]; 51 | } 52 | 53 | return _mutableSenderFilterList; 54 | } 55 | 56 | - (NSMutableArray *)mutableConversationFilterList 57 | { 58 | if (!_mutableConversationFilterList) { 59 | _mutableConversationFilterList = [[NSMutableArray alloc] init]; 60 | } 61 | 62 | return _mutableConversationFilterList; 63 | } 64 | 65 | - (NSArray *)senderFilterList 66 | { 67 | return [self.mutableSenderFilterList copy]; 68 | } 69 | 70 | - (NSArray *)conversationFilterList 71 | { 72 | return [self.mutableConversationFilterList copy]; 73 | } 74 | 75 | - (NSDate *)startingDate 76 | { 77 | NSTimeInterval secondsBackToConsider = self.daysBackToConsider * 60 * 60 * 24; 78 | 79 | NSDate *daysAgoDate = [NSDate dateWithTimeIntervalSinceNow:-secondsBackToConsider]; 80 | 81 | return [[NSCalendar currentCalendar] startOfDayForDate:daysAgoDate]; 82 | } 83 | 84 | - (NSNotificationCenter *)notificationCenter 85 | { 86 | if (!_notificationCenter) { 87 | _notificationCenter = [NSNotificationCenter defaultCenter]; 88 | } 89 | 90 | return _notificationCenter; 91 | } 92 | 93 | 94 | #pragma mark - Follow Lists 95 | - (void)followSenderEmailAddress:(EmailAddress *)emailAddress 96 | { 97 | SenderFilter *senderFilter = [[SenderFilter alloc] initWithEmailAddress:emailAddress]; 98 | 99 | [self addSenderFilter:senderFilter]; 100 | } 101 | 102 | - (void)followConversation:(id)messagePreview 103 | { 104 | ConversationFilter *conversationFilter = [[ConversationFilter alloc] initWithConversationGUID:messagePreview.conversationGUID 105 | conversationSubject:messagePreview.subject]; 106 | 107 | [self addConversationFilter:conversationFilter]; 108 | } 109 | 110 | - (void)unfollowSenderEmailAddress:(EmailAddress *)emailAddress 111 | { 112 | SenderFilter *senderFilter = [[SenderFilter alloc] initWithEmailAddress:emailAddress]; 113 | 114 | [self removeSenderFilter:senderFilter]; 115 | } 116 | 117 | - (void)unfollowConversation:(id)messagePreview 118 | { 119 | ConversationFilter *conversationFilter = [[ConversationFilter alloc] initWithConversationGUID:messagePreview.conversationGUID 120 | conversationSubject:messagePreview.subject]; 121 | 122 | [self removeConversationFilter:conversationFilter]; 123 | } 124 | 125 | - (BOOL)isFollowingSenderEmailAddress:(EmailAddress *)emailAddress 126 | { 127 | SenderFilter *senderFilter = [[SenderFilter alloc] initWithEmailAddress:emailAddress]; 128 | 129 | return [self.mutableSenderFilterList containsObject:senderFilter]; 130 | } 131 | 132 | - (BOOL)isFollowingConversation:(id)messagePreview 133 | { 134 | ConversationFilter *conversationFilter = [[ConversationFilter alloc] initWithConversationGUID:messagePreview.conversationGUID 135 | conversationSubject:messagePreview.subject]; 136 | 137 | return [self.mutableConversationFilterList containsObject:conversationFilter]; 138 | } 139 | 140 | - (void)addSenderFilter:(SenderFilter *)senderFilter 141 | { 142 | if ([self.mutableSenderFilterList containsObject:senderFilter]) { 143 | return; 144 | } 145 | 146 | [self.mutableSenderFilterList addObject:senderFilter]; 147 | } 148 | 149 | - (void)addConversationFilter:(ConversationFilter *)conversationFilter 150 | { 151 | if ([self.mutableConversationFilterList containsObject:conversationFilter]) { 152 | return; 153 | } 154 | 155 | [self.mutableConversationFilterList addObject:conversationFilter]; 156 | } 157 | 158 | - (void)removeSenderFilter:(SenderFilter *)senderFilter 159 | { 160 | [self.mutableSenderFilterList removeObject:senderFilter]; 161 | } 162 | 163 | - (void)removeConversationFilter:(ConversationFilter *)conversationFilter 164 | { 165 | [self.mutableConversationFilterList removeObject:conversationFilter]; 166 | } 167 | 168 | 169 | #pragma mark - Misc Public Methods 170 | - (void)restoreDefaultSettings 171 | { 172 | self.updateServerSideReadStatus = NO; 173 | 174 | self.daysBackToConsider = 7; 175 | self.includeUrgentMessages = YES; 176 | self.includeUnreadMessages = YES; 177 | 178 | self.mutableSenderFilterList = nil; 179 | self.mutableConversationFilterList = nil; 180 | } 181 | 182 | - (BOOL)save 183 | { 184 | // Wrap up all of the settings in a dictionary, and persist the dictionary 185 | NSMutableDictionary *settings = [[NSMutableDictionary alloc] init]; 186 | 187 | settings[@"updateServerSideReadStatus"] = @(self.updateServerSideReadStatus); 188 | settings[@"daysBackToConsider"] = @(self.daysBackToConsider); 189 | settings[@"includeUrgentMessages"] = @(self.includeUrgentMessages); 190 | settings[@"includeUnreadMessages"] = @(self.includeUnreadMessages); 191 | settings[@"mutableSenderFilterList"] = self.mutableSenderFilterList; 192 | settings[@"mutableConversationFilterList"] = self.mutableConversationFilterList; 193 | 194 | return [NSKeyedArchiver archiveRootObject:settings 195 | toFile:[self.saveURL path]]; 196 | } 197 | 198 | - (BOOL)reload 199 | { 200 | NSDictionary *settings = [NSKeyedUnarchiver unarchiveObjectWithFile:[self.saveURL path]]; 201 | 202 | if (!settings) { 203 | return NO; 204 | } 205 | 206 | self.updateServerSideReadStatus = [settings[@"updateServerSideReadStatus"] boolValue]; 207 | self.daysBackToConsider = [settings[@"daysBackToConsider"] unsignedIntegerValue]; 208 | self.includeUrgentMessages = [settings[@"includeUrgentMessages"] boolValue]; 209 | self.includeUnreadMessages = [settings[@"includeUnreadMessages"] boolValue]; 210 | self.mutableSenderFilterList = settings[@"mutableSenderFilterList"]; 211 | self.mutableConversationFilterList = settings[@"mutableConversationFilterList"]; 212 | 213 | return YES; 214 | } 215 | 216 | 217 | @end 218 | 219 | // ********************************************************* 220 | // 221 | // O365-iOS-EmailPeek, https://github.com/OfficeDev/O365-iOS-EmailPeek 222 | // 223 | // Copyright (c) Microsoft Corporation 224 | // All rights reserved. 225 | // 226 | // MIT License: 227 | // Permission is hereby granted, free of charge, to any person obtaining 228 | // a copy of this software and associated documentation files (the 229 | // "Software"), to deal in the Software without restriction, including 230 | // without limitation the rights to use, copy, modify, merge, publish, 231 | // distribute, sublicense, and/or sell copies of the Software, and to 232 | // permit persons to whom the Software is furnished to do so, subject to 233 | // the following conditions: 234 | // 235 | // The above copyright notice and this permission notice shall be 236 | // included in all copies or substantial portions of the Software. 237 | // 238 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 239 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 240 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 241 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 242 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 243 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 244 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 245 | // 246 | // ********************************************************* 247 | 248 | -------------------------------------------------------------------------------- /EmailPeek/SettingsViewController.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Microsoft. All rights reserved. Licensed under the MIT license. 3 | * See full license at the bottom of this file. 4 | */ 5 | 6 | #import 7 | 8 | @class SettingsManager; 9 | 10 | @protocol SettingsViewControllerDelegate; 11 | 12 | @interface SettingsViewController : UITableViewController 13 | 14 | @property (weak, nonatomic) id delegate; 15 | @property (strong, nonatomic) SettingsManager *settingsManager; 16 | 17 | @end 18 | 19 | 20 | @protocol SettingsViewControllerDelegate 21 | 22 | - (void)settingsViewControllerShouldDisconnect:(SettingsViewController *)settingsVC; 23 | - (void)settingsViewControllerDidChangeSettings:(SettingsViewController *)settingsVC; 24 | 25 | @end 26 | 27 | // ********************************************************* 28 | // 29 | // O365-iOS-EmailPeek, https://github.com/OfficeDev/O365-iOS-EmailPeek 30 | // 31 | // Copyright (c) Microsoft Corporation 32 | // All rights reserved. 33 | // 34 | // MIT License: 35 | // Permission is hereby granted, free of charge, to any person obtaining 36 | // a copy of this software and associated documentation files (the 37 | // "Software"), to deal in the Software without restriction, including 38 | // without limitation the rights to use, copy, modify, merge, publish, 39 | // distribute, sublicense, and/or sell copies of the Software, and to 40 | // permit persons to whom the Software is furnished to do so, subject to 41 | // the following conditions: 42 | // 43 | // The above copyright notice and this permission notice shall be 44 | // included in all copies or substantial portions of the Software. 45 | // 46 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 47 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 48 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 49 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 50 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 51 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 52 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 53 | // 54 | // ********************************************************* -------------------------------------------------------------------------------- /EmailPeek/UIColor+Office365.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Microsoft. All rights reserved. Licensed under the MIT license. 3 | * See full license at the bottom of this file. 4 | */ 5 | 6 | #import 7 | 8 | //Helpers for managing UI colors in one place 9 | @interface UIColor (Office365) 10 | 11 | + (UIColor *)o365_primaryColor; 12 | + (UIColor *)o365_primaryHighlightColor; 13 | 14 | + (UIColor *)o365_unreadMessageColor; 15 | + (UIColor *)o365_defaultMessageColor; 16 | 17 | @end 18 | 19 | // ********************************************************* 20 | // 21 | // O365-iOS-EmailPeek, https://github.com/OfficeDev/O365-iOS-EmailPeek 22 | // 23 | // Copyright (c) Microsoft Corporation 24 | // All rights reserved. 25 | // 26 | // MIT License: 27 | // Permission is hereby granted, free of charge, to any person obtaining 28 | // a copy of this software and associated documentation files (the 29 | // "Software"), to deal in the Software without restriction, including 30 | // without limitation the rights to use, copy, modify, merge, publish, 31 | // distribute, sublicense, and/or sell copies of the Software, and to 32 | // permit persons to whom the Software is furnished to do so, subject to 33 | // the following conditions: 34 | // 35 | // The above copyright notice and this permission notice shall be 36 | // included in all copies or substantial portions of the Software. 37 | // 38 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 39 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 40 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 41 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 42 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 43 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 44 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 45 | // 46 | // ********************************************************* 47 | -------------------------------------------------------------------------------- /EmailPeek/UIColor+Office365.m: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Microsoft. All rights reserved. Licensed under the MIT license. 3 | * See full license at the bottom of this file. 4 | */ 5 | 6 | #import "UIColor+Office365.h" 7 | 8 | //Helpers for managing UI colors in one place 9 | @implementation UIColor (Office365) 10 | 11 | + (UIColor *)o365_primaryColor 12 | { 13 | return [UIColor colorWithRed:1.0 14 | green:0.6 15 | blue:0.2 16 | alpha:1.0]; 17 | } 18 | 19 | + (UIColor *)o365_primaryHighlightColor 20 | { 21 | return [UIColor colorWithRed:1.0 22 | green:0.75 23 | blue:0.35 24 | alpha:1.0]; 25 | } 26 | 27 | + (UIColor *)o365_unreadMessageColor 28 | { 29 | return [UIColor colorWithRed:0.15 30 | green:0.60 31 | blue:0.72 32 | alpha:1.0]; 33 | } 34 | 35 | + (UIColor *)o365_defaultMessageColor 36 | { 37 | return [UIColor colorWithRed:0.74 38 | green:0.74 39 | blue:0.74 40 | alpha:1.0]; 41 | } 42 | 43 | @end 44 | 45 | // ********************************************************* 46 | // 47 | // O365-iOS-EmailPeek, https://github.com/OfficeDev/O365-iOS-EmailPeek 48 | // 49 | // Copyright (c) Microsoft Corporation 50 | // All rights reserved. 51 | // 52 | // MIT License: 53 | // Permission is hereby granted, free of charge, to any person obtaining 54 | // a copy of this software and associated documentation files (the 55 | // "Software"), to deal in the Software without restriction, including 56 | // without limitation the rights to use, copy, modify, merge, publish, 57 | // distribute, sublicense, and/or sell copies of the Software, and to 58 | // permit persons to whom the Software is furnished to do so, subject to 59 | // the following conditions: 60 | // 61 | // The above copyright notice and this permission notice shall be 62 | // included in all copies or substantial portions of the Software. 63 | // 64 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 65 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 66 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 67 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 68 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 69 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 70 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 71 | // 72 | // ********************************************************* 73 | -------------------------------------------------------------------------------- /EmailPeek/UnreadFilter.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Microsoft. All rights reserved. Licensed under the MIT license. 3 | * See full license at the bottom of this file. 4 | */ 5 | 6 | #import "MessageFilter.h" 7 | 8 | @interface UnreadFilter : NSObject 9 | 10 | @end 11 | 12 | // ********************************************************* 13 | // 14 | // O365-iOS-EmailPeek, https://github.com/OfficeDev/O365-iOS-EmailPeek 15 | // 16 | // Copyright (c) Microsoft Corporation 17 | // All rights reserved. 18 | // 19 | // MIT License: 20 | // Permission is hereby granted, free of charge, to any person obtaining 21 | // a copy of this software and associated documentation files (the 22 | // "Software"), to deal in the Software without restriction, including 23 | // without limitation the rights to use, copy, modify, merge, publish, 24 | // distribute, sublicense, and/or sell copies of the Software, and to 25 | // permit persons to whom the Software is furnished to do so, subject to 26 | // the following conditions: 27 | // 28 | // The above copyright notice and this permission notice shall be 29 | // included in all copies or substantial portions of the Software. 30 | // 31 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 32 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 33 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 34 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 35 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 36 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 37 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 38 | // 39 | // ********************************************************* 40 | -------------------------------------------------------------------------------- /EmailPeek/UnreadFilter.m: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Microsoft. All rights reserved. Licensed under the MIT license. 3 | * See full license at the bottom of this file. 4 | */ 5 | #import "UnreadFilter.h" 6 | 7 | @implementation UnreadFilter 8 | 9 | #pragma mark - NSCoding 10 | - (instancetype)initWithCoder:(NSCoder *)aDecoder 11 | { 12 | return [super init]; 13 | } 14 | 15 | - (void)encodeWithCoder:(NSCoder *)aCoder 16 | { 17 | } 18 | 19 | 20 | #pragma mark - MessageFilter 21 | - (NSString *)serverSideFilter 22 | { 23 | return @"IsRead eq false"; 24 | } 25 | 26 | @end 27 | 28 | // ********************************************************* 29 | // 30 | // O365-iOS-EmailPeek, https://github.com/OfficeDev/O365-iOS-EmailPeek 31 | // 32 | // Copyright (c) Microsoft Corporation 33 | // All rights reserved. 34 | // 35 | // MIT License: 36 | // Permission is hereby granted, free of charge, to any person obtaining 37 | // a copy of this software and associated documentation files (the 38 | // "Software"), to deal in the Software without restriction, including 39 | // without limitation the rights to use, copy, modify, merge, publish, 40 | // distribute, sublicense, and/or sell copies of the Software, and to 41 | // permit persons to whom the Software is furnished to do so, subject to 42 | // the following conditions: 43 | // 44 | // The above copyright notice and this permission notice shall be 45 | // included in all copies or substantial portions of the Software. 46 | // 47 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 48 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 49 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 50 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 51 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 52 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 53 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 54 | // 55 | // ********************************************************* 56 | -------------------------------------------------------------------------------- /EmailPeek/about.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |

Email Peek - An iOS app built using Office 365

5 |

Email Peek is a cool mail app built using the Office 365 APIs on the iOS platform. This app allows you to peek at just the email conversations you truly care about when you are away, such as when you are on vacation and also optionally send quick replies to messages without typing. This app uses many of the rich features of the Office 365 APIs such as server-side filtering, categories, etc.

6 |

Give us feedback

7 |

We hope you found this sample useful. We would love to hear from you, so drop us an email at 8 | docthis@microsoft.com with your comments or 9 | log an issue in our GitHub repository.

10 |

For more details on what else you can do with the Office 365 services in your iOS app, start with the 11 | Getting started with iOS page on dev.office.com.

12 |

Thanks, and happy coding!

13 |

Your Office 365 Development team

14 |
15 | 16 | 17 | 21 | 25 | 26 |
18 | See on GitHub 19 | 20 | 22 | Suggest on UserVoice 23 | 24 |
27 |
28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /EmailPeek/main.m: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Microsoft. All rights reserved. Licensed under the MIT license. See full license at the bottom of this file. 3 | */ 4 | 5 | #import 6 | #import "AppDelegate.h" 7 | 8 | int main(int argc, char * argv[]) { 9 | @autoreleasepool { 10 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 11 | } 12 | } 13 | 14 | // ********************************************************* 15 | // 16 | // O365-iOS-EmailPeek, https://github.com/OfficeDev/O365-iOS-EmailPeek 17 | // 18 | // Copyright (c) Microsoft Corporation 19 | // All rights reserved. 20 | // 21 | // MIT License: 22 | // Permission is hereby granted, free of charge, to any person obtaining 23 | // a copy of this software and associated documentation files (the 24 | // "Software"), to deal in the Software without restriction, including 25 | // without limitation the rights to use, copy, modify, merge, publish, 26 | // distribute, sublicense, and/or sell copies of the Software, and to 27 | // permit persons to whom the Software is furnished to do so, subject to 28 | // the following conditions: 29 | // 30 | // The above copyright notice and this permission notice shall be 31 | // included in all copies or substantial portions of the Software. 32 | // 33 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 34 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 35 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 36 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 37 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 38 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 39 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 40 | // 41 | // ********************************************************* 42 | -------------------------------------------------------------------------------- /EmailPeekTests/EmailPeekTests.m: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Microsoft. All rights reserved. Licensed under the MIT license. See full license at the bottom of this file. 3 | */ 4 | 5 | #import 6 | #import 7 | 8 | @interface EmailPeekTests : XCTestCase 9 | 10 | @end 11 | 12 | @implementation EmailPeekTests 13 | 14 | - (void)setUp { 15 | [super setUp]; 16 | // Put setup code here. This method is called before the invocation of each test method in the class. 17 | } 18 | 19 | - (void)tearDown { 20 | // Put teardown code here. This method is called after the invocation of each test method in the class. 21 | [super tearDown]; 22 | } 23 | 24 | - (void)testExample { 25 | // This is an example of a functional test case. 26 | XCTAssert(YES, @"Pass"); 27 | } 28 | 29 | - (void)testPerformanceExample { 30 | // This is an example of a performance test case. 31 | [self measureBlock:^{ 32 | // Put the code you want to measure the time of here. 33 | }]; 34 | } 35 | 36 | @end 37 | 38 | 39 | // ********************************************************* 40 | // 41 | // O365-iOS-EmailPeek, https://github.com/OfficeDev/O365-iOS-EmailPeek 42 | // 43 | // Copyright (c) Microsoft Corporation 44 | // All rights reserved. 45 | // 46 | // MIT License: 47 | // Permission is hereby granted, free of charge, to any person obtaining 48 | // a copy of this software and associated documentation files (the 49 | // "Software"), to deal in the Software without restriction, including 50 | // without limitation the rights to use, copy, modify, merge, publish, 51 | // distribute, sublicense, and/or sell copies of the Software, and to 52 | // permit persons to whom the Software is furnished to do so, subject to 53 | // the following conditions: 54 | // 55 | // The above copyright notice and this permission notice shall be 56 | // included in all copies or substantial portions of the Software. 57 | // 58 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 59 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 60 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 61 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 62 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 63 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 64 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 65 | // 66 | // ********************************************************* 67 | -------------------------------------------------------------------------------- /EmailPeekTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | com.microsoft.$(PRODUCT_NAME:rfc1034identifier) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /O365-iOS-EmailPeek.yml: -------------------------------------------------------------------------------- 1 | ### YamlMime:Sample 2 | sample: 3 | - name: Email Peek - An iOS app built using Office 365 4 | path: '' 5 | description: Email Peek is a cool mail app built using the Office 365 APIs on the iOS platform. This app uses many of the features of the Office 365 Mail API such as read/write, server-side filtering, and categories. 6 | readme: '' 7 | generateZip: FALSE 8 | isLive: TRUE 9 | technologies: 10 | - Office Add-in 11 | azureDeploy: '' 12 | author: davidchesnut 13 | platforms: [] 14 | languages: 15 | - Objective-C 16 | extensions: 17 | products: 18 | - Office 365 19 | scenarios: [] 20 | -------------------------------------------------------------------------------- /Podfile: -------------------------------------------------------------------------------- 1 | source 'https://github.com/Cocoapods/Specs.git' 2 | platform :ios, '8.0' 3 | 4 | target 'EmailPeek' do 5 | pod 'ADALiOS', '~> 1.2.1' 6 | pod 'Office365/Outlook', '= 0.9.1' 7 | pod 'Office365/Discovery', '= 0.9.1' 8 | end 9 | 10 | target 'EmailPeekTests' do 11 | 12 | end 13 | 14 | -------------------------------------------------------------------------------- /README-Localized/README-ja-jp.md: -------------------------------------------------------------------------------- 1 | #Email Peek - Office 365 を使用して構築された iOS アプリ # 2 | [![ビルドの状態](https://travis-ci.org/OfficeDev/O365-iOS-EmailPeek.svg)](https://travis-ci.org/OfficeDev/O365-iOS-EmailPeek) 3 | 4 | Email Peek は、iOS プラットフォームで Office 365 API を使用して構築された優れたメール アプリです。このアプリを使用すると、休暇中などの不在時に、本当に重要なメールの会話のみをすばやく確認できます。Email Peek では、メッセージにすばやく返信するのも簡単で、入力する必要もありません。このアプリは、読み取り/書き込み、サーバー側のフィルタリング、カテゴリなど、Office 365 メール API の多くの機能を使用しています。 5 | 6 | [![Office 365 iOS Email Peek](../readme-images/emailpeek_video.png)](https://youtu.be/WqEqxKD6Bfw "活用できるサンプルを確認するにはこちらをクリックしてください") 7 | 8 | **目次** 9 | 10 | * [環境をセットアップする](#set-up-your-environment) 11 | * [CocoaPods を使用して O365 iOS SDK をインポートする](#use-cocoapods-to-import-the-o365-ios-sdk) 12 | * [Microsoft Azure にアプリを登録する](#register-your-app-with-microsoft-azure) 13 | * [プロジェクトにクライアント ID とリダイレクト URI を取り込む](#get-the-client-id-and-redirect-uri-into-the-project) 14 | * [重要なコード ファイル](#code-of-interest) 15 | * [質問とコメント](#questions-and-comments) 16 | * [トラブルシューティング](#troubleshooting) 17 | * [その他の技術情報](#additional-resources) 18 | 19 | 20 | 21 | ## 環境のセットアップ ## 22 | 23 | Email Peek を実行するには、次のものが必要です。 24 | 25 | 26 | *Apple の[Xcode](https://developer.apple.com/)。 27 | *Office 365 アカウント。Office 365 アカウントは、[Office 365 開発者向けサイト](http://msdn.microsoft.com/library/office/fp179924.aspx)にサイン アップすると取得できます。これにより、Office 365 のデータを対象とするアプリの作成に使用できる API にアクセスできるようになります。 28 | *アプリケーションを登録する Microsoft Azure テナント。Azure Active Directory は、アプリケーションが認証と承認に使用する ID サービスを提供します。こちらから試用版サブスクリプションを取得できます。[Microsoft Azure](https://account.windowsazure.com/SignUp) 29 | 30 | **重要**:Azure サブスクリプションが Office 365 テナントにバインドされていることを確認する必要もあります。これを行うには、Active Directory チームのブログ投稿「[複数の Windows Azure Active Directory を作成して管理する](http://blogs.technet.com/b/ad/archive/2013/11/08/creating-and-managing-multiple-windows-azure-active-directories.aspx)」の「**新しいディレクトリを追加する**」セクションをご覧ください。また、詳細については、「[開発者向けサイトに Azure Active Directory へのアクセスをセットアップする](http://msdn.microsoft.com/office/office365/howto/setup-development-environment#bk_CreateAzureSubscription)」もご覧ください。 31 | 32 | 33 | *依存関係マネージャーとしての [CocoaPods](https://cocoapods.org/) のインストール。CocoaPods を使用すると、Office 365 と Azure Active Directory 認証ライブラリ (ADAL) の依存関係をプロジェクトに導入することができます。 34 | 35 | Office 365 アカウント、および Office 365 開発者サイトにバインドされた Azure AD アカウントを取得したら、次の手順を実行する必要があります。 36 | 37 | 1. Azure にアプリケーションを登録し、Office 365 Exchange Online の適切なアクセス許可を構成します。 38 | 2. CocoaPods をインストールし、これを使用して、プロジェクトに Office 365 と ADAL 認証の依存関係を取り込みます。 39 | 3. Azure アプリの登録固有の情報 (ClientID と RedirectUri) を、Email Peek アプリに入力します。 40 | 41 | ## CocoaPods を使用して O365 iOS SDK をインポートする 42 | 注:依存関係マネージャーとして **CocoaPods** を初めて使用する場合は、これをインストールしてからプロジェクトで Office 365 iOS SDK の依存関係を取り込む必要があります。 43 | 44 | Mac の**ターミナル** アプリから、次の 2 行のコードを入力します。 45 | 46 | sudo gem install cocoapods 47 | pod setup 48 | 49 | インストールとセットアップが成功すると、「**ターミナルのセットアップが完了しました**」というメッセージが表示されます。CocoaPods とその使用法の詳細については、「[CocoaPods](https://cocoapods.org/)」をご覧ください。 50 | 51 | 52 | **プロジェクトに iOS 版 Office 365 SDK の依存関係を取り込む** 53 | Email Peek アプリには、プロジェクトに Office 365 と ADAL コンポーネント (pods) を取り込む podfile が既に含まれています。podfile がある場所は、サンプルの root ("Podfile") です。次の例は、ファイルの内容を示しています。 54 | 55 | target ‘O365-iOS-EmailPeek’ do 56 | pod 'ADALiOS', '~> 1.2.1' 57 | pod 'Office365/Outlook', '= 0.9.1' 58 | pod 'Office365/Discovery', '= 0.9.1' 59 | end 60 | 61 | 62 | **Terminal** (プロジェクト フォルダーのルート) にあるプロジェクトのディレクトリに移動して、次のコマンドを実行する必要があります。 63 | 64 | 65 | pod install 66 | 67 | 注:「これらの依存関係がプロジェクトに追加されました。今すぐ Xcode (**O365-iOS-EmailPeek.xcworkspace**) でプロジェクトの代わりにワークスペースを開く必要があります」という確認のメッセージを受信する必要があります。Podfile で構文エラーが発生すると、インストール コマンドを実行する際にエラーが発生します。 68 | 69 | ## Microsoft Azure にアプリを登録する 70 | 1. Azure AD 資格情報を使用して、[Azure 管理ポータル](https://manage.windowsazure.com)にサインインします。 71 | 2. 左側のメニューで **[Active Directory]** を選んでから、Office 365 開発者向けサイトのディレクトリを選びます。 72 | 3. 上部のメニューで、**[アプリケーション]** を選びます。 73 | 4. 下部のメニューから、**[追加]** を選びます。 74 | 5. **[何を行いますか]** ページで、**[組織で開発中のアプリケーションを追加]** を選びます。 75 | 6. **[アプリケーションについてお聞かせください]** ページで、アプリケーション名には「**O365-iOS-EmailPeek**」を指定し、種類は**[NATIVE CLIENT APPLICATION]** を選びます。 76 | 7. ページの右下隅にある矢印アイコンを選びます。 77 | 8. [アプリケーション情報] ページで、リダイレクト URI を指定します。この例では http://localhost/emailpeek を指定します。続いて、ページの右下隅にあるチェック ボックスを選びます。この値は、「**プロジェクトに ClientID と RedirectUri を取り込む**」セクションで使用するため覚えておいてください。 78 | 9. アプリケーションが正常に追加されたら、アプリケーションの [クイック スタート] ページに移動します。上部のメニューにある [構成] を選びます。 79 | 10. **[他のアプリケーションへのアクセス許可]** の下で、**[Office 365 Exchange Online アプリケーションを追加する]** アクセス許可を追加し、**[ユーザーのメールの読み取りと書き込み]** と **[ユーザーとしてメールを送信]** の各アクセス許可を選びます。 80 | 13. **[構成]** ページで、**[クライアント ID]** に指定された値をコピーします。この値は、「**プロジェクトに ClientID と RedirectUri を取り込む**」セクションで使用するため覚えておいてください。 81 | 14. 下部のメニューで、**[保存]** を選びます。 82 | 83 | 84 | ## プロジェクトにクライアント ID とリダイレクト URI を取り込む 85 | 86 | 最後に、前のセクション「**Microsoft Azure にアプリを登録する**」で記録したクライアント ID とリダイレクト URI を追加する必要があります。 87 | 88 | **O365-iOS-EmailPeek** プロジェクトのディレクトリを参照し、ワークスペース (O365-EmailPeek-iOS.xcworkspace) を開きます。**AppDelegate.m** ファイルで、**ClientID** と **RedirectUri** の各値がファイルの一番上に追加されていることが分かります。このファイルに必要な値を指定します。 89 | 90 | // You will set your application's clientId and redirect URI.You get 91 | // these when you register your application in Azure AD. 92 | static NSString * const kClientId = @"ENTER_REDIRECT_URI_HERE"; 93 | static NSString * const kRedirectURLString = @"ENTER_CLIENT_ID_HERE"; 94 | static NSString * const kAuthorityURLString = @"https://login.microsoftonline.com/common"; 95 | 96 | 97 | 98 | ## 重要なコード ファイル 99 | 100 | 101 | **モデル** 102 | 103 | これらのドメインのエンティティは、アプリケーションのデータを表すカスタム クラスです。これらのすべてのクラスは変更できません。これらは Office 365 SDK で提供される基本的なエンティティをラップします。 104 | 105 | **Office365 ヘルパー** 106 | 107 | ヘルパーは、API 呼び出しを行って Office 365 と実際に通信するクラスです。このアーキテクチャでは、Office365 SDK からアプリの残りの部分が切り離されます。 108 | 109 | **Office365 サーバー側フィルター** 110 | 111 | これらのクラスを使用すると、フェッチ中に正しい Office 365 サーバー側フィルターの句で適切な API 呼び出しを行うことができます。 112 | 113 | **ConversationManager と SettingsManager** 114 | 115 | これらのクラスでは、アプリの会話と設定を管理できます。 116 | 117 | **コントローラー** 118 | 119 | これらは、Email Peek でサポートされているさまざまなビューのコントローラーです。 120 | 121 | **ビュー** 122 | 123 | これにより、ConversationListViewController と ConversationViewController の 2 つの異なる場所で使用されるカスタム セルが実装されます。 124 | 125 | 126 | ## 質問とコメント 127 | 128 | Email Peek アプリ サンプルについて、Microsoft にフィードバックをお寄せください。フィードバックはこのリポジトリの「[問題](https://github.com/OfficeDev/O365-EmailPeek-iOS)」セクションで送信できます。
129 |
130 | Office 365 開発全般の質問につきましては、[スタック オーバーフロー](http://stackoverflow.com/questions/tagged/Office365+API)に投稿してください。質問には、[Office365] と [API] のタグを付けてください。 131 | 132 | ## トラブルシューティング 133 | Xcode 7.0 のアップデートにより、iOS 9 を実行するシミュレーターやデバイス用に App Transport Security を使用できるようになりました。「[App Transport Security のテクニカル ノート](https://developer.apple.com/library/prerelease/ios/technotes/App-Transport-Security-Technote/)」をご覧ください。 134 | 135 | このサンプルでは、plist 内の次のドメインのために一時的な例外を作成しました: 136 | 137 | - outlook.office365.com 138 | 139 | これらの例外が含まれていないと、Xcode で iOS 9 シミュレーターにデプロイされたときに、このアプリで Office 365 API へのすべての呼び出しが失敗します。 140 | 141 | 142 | ## その他の技術情報 143 | 144 | * [iOS 用 Office 365 Connect アプリ](https://github.com/OfficeDev/O365-iOS-Connect) 145 | * [iOS 用 Office 365 コード スニペット](https://github.com/OfficeDev/O365-iOS-Snippets) 146 | * [iOS 用 Office 365 プロファイル サンプル](https://github.com/OfficeDev/O365-iOS-Profile) 147 | * [Office 365 API ドキュメント](http://msdn.microsoft.com/office/office365/howto/platform-development-overview) 148 | * [Office 365 API のサンプル コードとビデオ](https://msdn.microsoft.com/office/office365/howto/starter-projects-and-code-samples) 149 | * [Office デベロッパー センター](http://dev.office.com/) 150 | * [Email Peek の Medium の記事](https://medium.com/office-app-development/why-read-email-when-you-can-peek-2af947d352dc) 151 | 152 | ## 著作権 153 | 154 | Copyright (c) 2015 Microsoft.All rights reserved. 155 | 156 | -------------------------------------------------------------------------------- /README-Localized/README-pt-br.md: -------------------------------------------------------------------------------- 1 | #Email Peek – um aplicativo iOS criado usando o Office 365 # 2 | [![Status da Compilação](https://travis-ci.org/OfficeDev/O365-iOS-EmailPeek.svg)](https://travis-ci.org/OfficeDev/O365-iOS-EmailPeek) 3 | 4 | O Email Peek é um aplicativo de email interessante, criado por meio de APIs do Office 365 na plataforma iOS. Esse aplicativo permite ver apenas as conversas de email realmente importantes quando você está ausente, como quando estiver de férias. O Email Peek também facilita o envio de respostas rápidas às mensagens sem a necessidade de digitar. Esse aplicativo usa muitos dos recursos da API de Email do Office 365, como ler/gravar, filtragem do lado do servidor e categorias. 5 | 6 | [![Office 365 iOS Email Peek](../readme-images/emailpeek_video.png)](https://youtu.be/WqEqxKD6Bfw "Clique no exemplo para vê-lo em ação") 7 | 8 | **Sumário** 9 | 10 | * [Set up your environment](#set-up-your-environment) 11 | * [Use CocoaPods to import the O365 iOS SDK](#use-cocoapods-to-import-the-o365-ios-sdk) 12 | * [Registrar seu aplicativo no Microsoft Azure](#register-your-app-with-microsoft-azure) 13 | * [Obter a ID de Cliente e URI de Redirecionamento no projeto](#get-the-client-id-and-redirect-uri-into-the-project) 14 | * [Arquivos de código importantes](#code-of-interest) 15 | * [Perguntas e comentários](#questions-and-comments) 16 | * [Solução de problemas](#troubleshooting) 17 | * [Recursos adicionais](#additional-resources) 18 | 19 | 20 | 21 | ## Configurar seu ambiente ## 22 | 23 | Para executar o Email Peek, você precisa do seguinte: 24 | 25 | 26 | * [Xcode](https://developer.apple.com/) da Apple. 27 | * Uma conta do Office 365. Você pode obter uma conta do Office 365 ao se inscrever em um [Site do Desenvolvedor do Office 365](http://msdn.microsoft.com/library/office/fp179924.aspx). Isso dará acesso a APIs que você pode usar para criar aplicativos que visam dados do Office 365. 28 | * Um locatário do Microsoft Azure para registrar seu aplicativo. O Azure Active Directory fornece serviços de identidade que os aplicativos usam para autenticação e autorização. Uma assinatura de avaliação pode ser adquirida aqui: [Microsoft Azure](https://account.windowsazure.com/SignUp). 29 | 30 | **Importante**: você também deve assegurar que a assinatura do Azure esteja vinculada ao locatário do Office 365. Para fazer isso, confira a seção ** Adicionar um novo diretório** na postagem do blog da equipe do Active Directory, [Criando e Gerenciando Vários Microsoft Azure Active Directories](http://blogs.technet.com/b/ad/archive/2013/11/08/creating-and-managing-multiple-windows-azure-active-directories.aspx). Para saber mais, você também pode ler o artigo [Configurar o acesso ao Azure Active Directory para seu Site do Desenvolvedor](http://msdn.microsoft.com/office/office365/howto/setup-development-environment#bk_CreateAzureSubscription). 31 | 32 | 33 | * Instalação do [CocoaPods](https://cocoapods.org/) como gerente de dependência. O CocoaPods permitirá que você receba as dependências do Office 365 e da ADAL (Azure Active Directory Authentication Library) no projeto. 34 | 35 | Depois que você tiver uma conta do Office 365 e uma conta do Azure AD associada ao seu Site do Desenvolvedor do Office 365, será preciso executar as seguintes etapas: 36 | 37 | 1. Registrar seu aplicativo no Azure e configurar as permissões apropriadas do Office 365 Exchange Online. 38 | 2. Instalar e usar o CocoaPods para obter dependências de autenticação do Office 365 e da ADAL no projeto. 39 | 3. Inserir as especificações de registro do aplicativo do Azure (ClientID e RedirectUri) para o aplicativo Email Peek. 40 | 41 | ## Usar o CocoaPods para importar o O365 iOS SDK 42 | Observação: Se, como gerente de dependência, você nunca tiver usado o **CocoaPods** anteriormente, terá que instalá-lo antes de obter dependências do Office 365 iOS SDK em seu projeto. 43 | 44 | Insira as próximas duas linhas de código a partir do aplicativo do **Terminal** em seu Mac. 45 | 46 | sudo gem install cocoapods 47 | pod setup 48 | 49 | Se a instalação e a configuração forem bem-sucedidas, você deverá ver a mensagem **Configuração concluída no Terminal**. Para saber mais sobre o CocoaPods e seu uso, confira [CocoaPods](https://cocoapods.org/). 50 | 51 | 52 | **Obter as dependências do Office 365 iOS SDK em seu projeto** 53 | O aplicativo Email Peek já contém um podfile que receberá os componentes (pods) do Office 365 e da ADAL no projeto. Ele está localizado na raiz do exemplo ("Podfile"). O exemplo mostra o conteúdo do arquivo. 54 | 55 | target ‘O365-iOS-EmailPeek’ do 56 | pod 'ADALiOS', '~> 1.2.1' 57 | pod 'Office365/Outlook', '= 0.9.1' 58 | pod 'Office365/Discovery', '= 0.9.1' 59 | end 60 | 61 | 62 | Você só precisará navegar até o diretório do projeto no **Terminal** (raiz da pasta do projeto) e executar o comando a seguir. 63 | 64 | 65 | pod install 66 | 67 | Observação: Você receberá a confirmação de que essas dependências foram adicionadas ao projeto e que, de agora em diante, deverá abrir o espaço de trabalho em vez do projeto no Xcode (**O365-iOS-EmailPeek.xcworkspace**). Se houver um erro de sintaxe no Podfile, você encontrará um erro ao executar o comando de instalação. 68 | 69 | ## Registrar seu aplicativo no Microsoft Azure 70 | 1. Acesse o [Portal de Gerenciamento do Azure](https://manage.windowsazure.com) usando suas credenciais do Azure AD. 71 | 2. Escolha **Active Directory** no menu à esquerda e escolha o diretório para o Site do Desenvolvedor do Office 365. 72 | 3. No menu superior, escolha **Aplicativos**. 73 | 4. Escolha **Adicionar** no menu inferior. 74 | 5. Na página **O que você deseja fazer?**, escolha **Adicionar um aplicativo que minha organização esteja desenvolvendo**. 75 | 6. Na página **Conte-nos sobre seu aplicativo**, especifique **O365-iOS-EmailPeek** para o nome do aplicativo e escolha **APLICATIVO CLIENTE NATIVO** como o tipo. 76 | 7. Escolha o ícone de seta no canto inferior direito da página. 77 | 8. Na página de informações do Aplicativo, especifique um URI de Redirecionamento. Para este exemplo, você pode especificar http://localhost/emailpeek e, em seguida, marcar a caixa de seleção no canto inferior direito da página. Lembre-se desse valor para a seção **Obter ClientID e RedirectUri no projeto**. 78 | 9. Após adicionar o aplicativo com êxito, você será direcionado para a página Início Rápido do aplicativo. Escolha Configurar no menu superior. 79 | 10. Em **permissões para outros aplicativos**, adicione a permissão a seguir: **Adicionar o aplicativo do Office 365 Exchange Online** e escolha as permissões **Ler e gravar emails de usuários** e **Enviar email como um usuário**. 80 | 13. Copie o valor especificado da **ID do cliente** na página **Configurar**. Lembre-se desse valor para a seção **Obter ClientID e RedirectUri no projeto**. 81 | 14. Selecione **Salvar** no menu inferior. 82 | 83 | 84 | ## Obter a ID de Cliente e o URI de Redirecionamento no projeto 85 | 86 | Por fim, você precisará adicionar a ID de Cliente e o URI de Redirecionamento gravados na seção anterior **Registrar seu aplicativo no Microsoft Azure**. 87 | 88 | Navegue pelo diretório do projeto **O365-iOS-EmailPeek** e abra o espaço de trabalho (O365-EmailPeek-iOS.xcworkspace). No arquivo **AppDelegate.m** você verá que os valores **ClientID** e **RedirectUri** podem ser adicionados à parte superior do arquivo. Forneça os valores necessários neste arquivo. 89 | 90 | // Você definirá a ID do Cliente e o URI de Redirecionamento do aplicativo. Você obtém 91 | // isso ao registrar seu aplicativo no Azure AD. 92 | static NSString * const kClientId = @"ENTER_REDIRECT_URI_HERE"; 93 | static NSString * const kRedirectURLString = @"ENTER_CLIENT_ID_HERE"; 94 | static NSString * const kAuthorityURLString = @"https://login.microsoftonline.com/common"; 95 | 96 | 97 | 98 | ## Arquivos de código importantes 99 | 100 | 101 | **Modelos** 102 | 103 | Essas entidades de domínio são classes personalizadas que representam os dados do aplicativo. Todas essas classes são imutáveis. Elas encapsulam as entidades básicas fornecidas pelo SDK do Office 365. 104 | 105 | **Auxiliares do Office365** 106 | 107 | Os auxiliares são as classes que realmente se comunicam com o Office 365 ao fazer chamadas à API. Essa arquitetura desvincula o restante do aplicativo do SDK do Office 365. 108 | 109 | **Filtros no Servidor do Office365** 110 | 111 | Essas classes ajudam a fazer a chamada à API apropriada com as cláusulas corretas do filtro do servidor do Office 365 durante a busca. 112 | 113 | **ConversationManager e SettingsManager** 114 | 115 | Essas classes ajudam a gerenciar as conversas e as configurações no aplicativo. 116 | 117 | **Controladores** 118 | 119 | Esses são os controladores para os diversos modos de exibição compatíveis com o Email Peek. 120 | 121 | **Modos de exibição** 122 | 123 | Isso implementa uma célula personalizada que é usada em dois lugares diferentes, no ConversationListViewController e no ConversationViewController. 124 | 125 | 126 | ## Perguntas e comentários 127 | 128 | Adoraríamos receber seus comentários sobre o exemplo do aplicativo Email Peek. Você pode enviar seus comentários para nós na seção [Problemas](https://github.com/OfficeDev/O365-EmailPeek-iOS) deste repositório.
129 |
130 | Perguntas sobre o desenvolvimento do Office 365 em geral devem ser publicadas no [Stack Overflow](http://stackoverflow.com/questions/tagged/Office365+API). Marque suas perguntas com [Office365] e [API]. 131 | 132 | ## Solução de problemas 133 | Com a atualização do Xcode 7.0, a Segurança de Transporte do Aplicativo está habilitada para simuladores e dispositivos que estão executando o iOS 9. Confira [App Transport Security Technote](https://developer.apple.com/library/prerelease/ios/technotes/App-Transport-Security-Technote/). 134 | 135 | Para este exemplo, criamos uma exceção temporária para o seguinte domínio na plist: 136 | 137 | - outlook.office365.com 138 | 139 | Se essas exceções não estiverem incluídas, todas as chamadas na API do Office 365 falharão neste aplicativo se ele for implantado em um simulador de iOS 9 no Xcode. 140 | 141 | 142 | ## Recursos adicionais 143 | 144 | * [Aplicativo Connect do Office 365 para iOS](https://github.com/OfficeDev/O365-iOS-Connect) 145 | * [Trechos de Código do Office 365 para iOS](https://github.com/OfficeDev/O365-iOS-Snippets) 146 | * [Perfil de Exemplo do Office 365 para iOS](https://github.com/OfficeDev/O365-iOS-Profile) 147 | * [Documentação APIs do Office 365](http://msdn.microsoft.com/office/office365/howto/platform-development-overview) 148 | * [Vídeos e exemplos de código da API do Office 365](https://msdn.microsoft.com/office/office365/howto/starter-projects-and-code-samples) 149 | * [Centro de Desenvolvimento do Office](http://dev.office.com/) 150 | * [Artigo da Medium sobre o Email Peek](https://medium.com/office-app-development/why-read-email-when-you-can-peek-2af947d352dc) 151 | 152 | ## Copyright 153 | 154 | Copyright © 2015 Microsoft. Todos os direitos reservados. 155 | 156 | -------------------------------------------------------------------------------- /README-Localized/README-ru-ru.md: -------------------------------------------------------------------------------- 1 | #Email Peek — приложение для iOS, созданное с помощью Office 365 # 2 | [![Состояние сборки](https://travis-ci.org/OfficeDev/O365-iOS-EmailPeek.svg)](https://travis-ci.org/OfficeDev/O365-iOS-EmailPeek) 3 | 4 | Email Peek — это полезное почтовое приложение, созданное с помощью API Office 365 на платформе iOS. Это приложение позволяет просматривать только действительно важные беседы, когда вас нет на месте, например во время отпуска. Кроме того, с Email Peek вы без труда сможете отправлять короткие ответы на сообщения, не печатая. Это приложение использует многие функции API Почты Office 365, такие как чтение и запись, фильтрация на стороне сервера и категории. 5 | 6 | [![Office 365 iOS Email Peek](../readme-images/emailpeek_video.png)](https://youtu.be/WqEqxKD6Bfw "Щелкните, чтобы просмотреть пример в действии") 7 | 8 | **Содержание** 9 | 10 | * [Настройка среды](#set-up-your-environment) 11 | * [Импорт пакета SDK Office 365 для iOS с помощью диспетчера зависимостей CocoaPods](#use-cocoapods-to-import-the-o365-ios-sdk) 12 | * [Регистрация приложения в Microsoft Azure](#register-your-app-with-microsoft-azure) 13 | * [Добавление идентификатора клиента и URI перенаправления в проект](#get-the-client-id-and-redirect-uri-into-the-project) 14 | * [Важные файлы кода](#code-of-interest) 15 | * [Вопросы и комментарии](#questions-and-comments) 16 | * [Устранение неполадок](#troubleshooting) 17 | * [Дополнительные ресурсы](#additional-resources) 18 | 19 | 20 | 21 | ## Настройка среды ## 22 | 23 | Чтобы запустить Email Peek, необходимо следующее: 24 | 25 | 26 | * Среда разработки [Xcode](https://developer.apple.com/) от Apple. 27 | * Учетная запись Office 365. Учетную запись Office 365 можно получить, подписавшись на [Сайт разработчика Office 365](http://msdn.microsoft.com/library/office/fp179924.aspx). Так вы получите доступ к API, с помощью которых можно создавать приложения, ориентированные на данные в Office 365. 28 | * Клиент Microsoft Azure для регистрации приложения. В Azure Active Directory доступны службы идентификации, которые приложения используют для проверки подлинности и авторизации. Пробную подписку можно получить здесь: [Microsoft Azure](https://account.windowsazure.com/SignUp). 29 | 30 | **Важно**! Убедитесь, что ваша подписка на Azure привязана к клиенту Office 365. Для этого просмотрите раздел, посвященный **добавлению нового каталога**, в записи блога команды Active Directory о [создании нескольких каталогов Windows Azure Active Directory и управлении ими](http://blogs.technet.com/b/ad/archive/2013/11/08/creating-and-managing-multiple-windows-azure-active-directories.aspx). Дополнительные сведения можно найти в разделе о [настройке доступа к Azure Active Directory для Сайта разработчика](http://msdn.microsoft.com/office/office365/howto/setup-development-environment#bk_CreateAzureSubscription). 31 | 32 | 33 | * Диспетчер зависимостей [CocoaPods](https://cocoapods.org/). Диспетчер зависимостей CocoaPods позволяет добавить в проект зависимости Office 365 и ADAL. 34 | 35 | После того как вы создали учетную запись Office 365 и связали учетную запись Azure AD с Сайтом разработчика Office 365, сделайте следующее: 36 | 37 | 1. Зарегистрируйте приложение в Azure и настройте необходимые разрешения Office 365 Exchange Online. 38 | 2. Установите диспетчер зависимостей CocoaPods и добавьте в проект зависимости Office 365 и проверки подлинности ADAL. 39 | 3. Введите сведения о регистрации приложения в Azure (ClientID и RedirectUri) в приложение Email Peel. 40 | 41 | ## Импорт пакета SDK Office 365 для iOS с помощью диспетчера зависимостей CocoaPods 42 | Примечание. Если до этого вы никогда не пользовались диспетчером зависимостей **CocoaPods**, его необходимо установить перед добавлением зависимостей пакета SDK Office 365 для iOS в проект. 43 | 44 | Введите приведенные ниже две строки кода из приложения **Терминал** на Mac. 45 | 46 | sudo gem install cocoapods 47 | pod setup 48 | 49 | После установки и настройки отобразится сообщение **Setup completed in Terminal**. Дополнительные сведения о диспетчере зависимостей CocoaPods и его использовании см. на сайте [CocoaPods](https://cocoapods.org/). 50 | 51 | 52 | **Добавление зависимостей пакета SDK Office 365 для iOS в проект** 53 | Приложение Email Peek уже содержит компонент podfile, который добавит компоненты Office 365 и ADAL (pod) в проект. Он расположен в корневой папке приложения ("Podfile"). В примере показано содержимое файла. 54 | 55 | target ‘O365-iOS-EmailPeek’ do 56 | pod 'ADALiOS', '~> 1.2.1' 57 | pod 'Office365/Outlook', '= 0.9.1' 58 | pod 'Office365/Discovery', '= 0.9.1' 59 | end 60 | 61 | 62 | Необходимо просто перейти в каталог проекта в программе **Терминал** (корневую папку проекта) и выполнить следующую команду. 63 | 64 | 65 | pod install 66 | 67 | Примечание. Вы должны получить подтверждение, что эти зависимости добавлены в проект и теперь необходимо открывать рабочую область, а не проект в Xcode (**O365-iOS-EmailPeek.xcworkspace**). Если в компоненте Podfile есть синтаксическая ошибка, при выполнении команды install возникнет ошибка. 68 | 69 | ## Регистрация приложения в Microsoft Azure 70 | 1. Войдите на [портал управления Azure](https://manage.windowsazure.com), используя учетные данные Azure AD. 71 | 2. Выберите элемент **Active Directory** в меню слева, а затем выберите каталог для сайта разработчика Office 365. 72 | 3. В верхнем меню выберите элемент **Приложения**. 73 | 4. В нижней меню выберите команду **Добавить**. 74 | 5. На странице **Что вы хотите сделать?** выберите команду **Добавить приложение, разрабатываемое моей организацией**. 75 | 6. На странице **Расскажите о своем приложении** укажите имя приложения **O365-iOS-EmailPeek** и выберите тип **СОБСТВЕННОЕ КЛИЕНТСКОЕ ПРИЛОЖЕНИЕ**. 76 | 7. Щелкните значок стрелки в правом нижнем углу страницы. 77 | 8. На странице сведений о приложении укажите URI перенаправления (для этого приложения вы можете указать http://localhost/emailpeek), а затем установите флажок в правом нижнем углу страницы. Запомните это значение для раздела **Добавление идентификатора клиента и URI перенаправления в проект**. 78 | 9. После добавления приложения откроется страница "Быстрый запуск". Выберите пункт "Настройка" в верхнем меню. 79 | 10. В разделе **разрешений для других приложений** добавьте следующее разрешение: **Добавление приложения Office 365 Exchange Online** и выберите разрешения на **чтение и создание писем от имени пользователя** и **отправку почты от имени пользователя**. 80 | 13. Скопируйте значение **идентификатора клиента** на странице **Настройка**. Запомните это значение для раздела **Добавление идентификатора клиента и URI перенаправления в проект**. 81 | 14 Выберите команду **Сохранить** в нижнем меню. 82 | 83 | 84 | ## Добавление идентификатора клиента и URI перенаправления в проект 85 | 86 | Наконец, необходимо добавить идентификатор клиента и URI перенаправления, записанные в предыдущем разделе **Регистрация приложения в Microsoft Azure**. 87 | 88 | Перейдите в каталог проекта **O365-iOS-EmailPeek** и откройте рабочую область (O365-EmailPeek-iOS.xcworkspace). Значения **ClientID** и **RedirectUri** можно добавить в верхней части файла **AppDelegate.m**. Укажите необходимые значения в этом файле. 89 | 90 | // Вы добавите идентификатор клиента и URI перенаправления. Вы получаете 91 | // их при регистрации приложения в Azure AD. 92 | static NSString * const kClientId = @"ENTER_REDIRECT_URI_HERE"; 93 | static NSString * const kRedirectURLString = @"ENTER_CLIENT_ID_HERE"; 94 | static NSString * const kAuthorityURLString = @"https://login.microsoftonline.com/common"; 95 | 96 | 97 | 98 | ## Важные файлы кода 99 | 100 | 101 | **Модели** 102 | 103 | Эти объекты — это специальные классы, которые представляют данные приложения. Все эти классы являются неизменными. Они являются оболочкой для основных объектов, предусмотренных пакетом SDK Office 365. 104 | 105 | **Вспомогательные приложения Office 365** 106 | 107 | Вспомогательные приложения — это классы, которые взаимодействуют с Office 365, осуществляя вызовы API. Эта архитектура отделяет остальную часть приложения от пакета SDK Office 365. 108 | 109 | **Серверные фильтры Office 365** 110 | 111 | Эти классы помогают осуществить необходимый вызов API с правильными серверными предложениями фильтра Office 365 во время доступа. 112 | 113 | **ConversationManager и SettingsManager** 114 | 115 | Эти классы помогают управлять беседами и параметрами в приложении. 116 | 117 | **Контроллеры** 118 | 119 | Это контроллеры различных представлений, которые поддерживаются в Email Peek. 120 | 121 | **Представления** 122 | 123 | Добавляет специальную ячейку, используемую в контроллерах ConversationListViewController и ConversationViewController. 124 | 125 | 126 | ## Вопросы и комментарии 127 | 128 | Мы будем рады получить ваш отзыв о приложении Email Peek. Вы можете отправить отзыв в разделе [Issues](https://github.com/OfficeDev/O365-EmailPeek-iOS) этого репозитория.
129 |
130 | Общие вопросы о разработке решений для Office 365 следует публиковать на сайте [Stack Overflow](http://stackoverflow.com/questions/tagged/Office365+API). Не забывайте помечать свои вопросы тегами {Office365] и [API]. 131 | 132 | ## Устранение неполадок 133 | Для симуляторов и устройств под управлением iOS 9 с обновлением Xcode 7.0 поддерживается технология App Transport Security. См. [технический комментарий к App Transport Security](https://developer.apple.com/library/prerelease/ios/technotes/App-Transport-Security-Technote/). 134 | 135 | Для этого приложения мы создали временное исключение для следующего домена в plist: 136 | 137 | — outlook.office365.com 138 | 139 | Если эти исключения не включены, при развертывании на симуляторе с iOS 9 в Xcode вызов API Office 365 в этом приложении будет невозможен. 140 | 141 | 142 | ## Дополнительные ресурсы 143 | 144 | * [Приложение Office 365 Connect для iOS](https://github.com/OfficeDev/O365-iOS-Connect) 145 | * [Фрагменты кода Office 365 для iOS](https://github.com/OfficeDev/O365-iOS-Snippets) 146 | * [Пример Office 365 Profile для iOS](https://github.com/OfficeDev/O365-iOS-Profile) 147 | * [Документация по API Office 365](http://msdn.microsoft.com/office/office365/howto/platform-development-overview) 148 | * [Примеры кода API Office 365 и видео](https://msdn.microsoft.com/office/office365/howto/starter-projects-and-code-samples) 149 | * [Центр разработки для Office](http://dev.office.com/) 150 | * [Статья о Email Peek на сайте Medium](https://medium.com/office-app-development/why-read-email-when-you-can-peek-2af947d352dc) 151 | 152 | ## Авторские права 153 | 154 | (c) Корпорация Майкрософт (Microsoft Corporation), 2015. Все права защищены. 155 | 156 | -------------------------------------------------------------------------------- /README-Localized/README-zh-tw.md: -------------------------------------------------------------------------------- 1 | #電子郵件預覽 - 使用 Office 365 # 建置的 iOS 應用程式 2 | [![組建狀態](https://travis-ci.org/OfficeDev/O365-iOS-EmailPeek.svg)](https://travis-ci.org/OfficeDev/O365-iOS-EmailPeek) 3 | 4 | 電子郵件預覽是在 iOS 平台上,使用 Office 365 API 建置的一個很棒的郵件應用程式。這個應用程式可讓您預覽您不在時 (例如度假) 真正關心的電子郵件交談。電子郵件預覽也能讓您輕鬆且快速地回覆郵件,而不需輸入。這個應用程式使用 Office 365 郵件 API 的許多功能,例如讀取/寫入、伺服器端篩選及類別。 5 | 6 | [![Office 365 iOS Email Peek](../readme-images/emailpeek_video.png)](https://youtu.be/WqEqxKD6Bfw "Click to see the sample in action") 7 | 8 | **目錄** 9 | 10 | * [設定您的環境](#set-up-your-environment) 11 | * [使用 CocoaPods 以匯入 O365 iOS SDK](#use-cocoapods-to-import-the-o365-ios-sdk) 12 | * [使用 Microsoft Azure 註冊您的應用程式](#register-your-app-with-microsoft-azure) 13 | * [取得用戶端識別碼,並將 Uri 重新導向至專案](#get-the-client-id-and-redirect-uri-into-the-project) 14 | * [重要程式碼檔案](#code-of-interest) 15 | * [問題和意見](#questions-and-comments) 16 | * [疑難排解](#troubleshooting") 17 | * [其他資源](#additional-resources) 18 | 19 | 20 | 21 | ## 設定您的環境 ## 22 | 23 | 若要執行電子郵件預覽,您需要下列項目︰ 24 | 25 | 26 | * 來自 Apple 的 [Xcode](https://developer.apple.com/)。 27 | * Office 365 帳戶。您可以註冊 [Office 365 開發人員網站 ](http://msdn.microsoft.com/library/office/fp179924.aspx)來取得 Office 365 帳戶。這會讓您存取 API,可用來建立目標為 Office 365 資料的應用程式。 28 | * 用來註冊您的應用程式的 Microsoft Azure 租用戶。Azure Active Directory 會提供識別服務,以便應用程式用於驗證和授權。可以在這裡取得試用版訂閱︰[Microsoft Azure](https://account.windowsazure.com/SignUp)。 29 | 30 | **重要**:您還需要確定您的 Azure 訂用帳戶已繫結至您的 Office 365 租用戶。若要這麼做,請參閱 Active Directory 小組的部落格文章[建立和管理多個 Windows Azure Active Directory](http://blogs.technet.com/b/ad/archive/2013/11/08/creating-and-managing-multiple-windows-azure-active-directories.aspx) 的**新增目錄**一節。您也可以閱讀[為您的開發人員網站設定 Azure Active Directory 存取](http://msdn.microsoft.com/office/office365/howto/setup-development-environment#bk_CreateAzureSubscription)的詳細資訊。 31 | 32 | 33 | *以相依性管理員身分安裝 [CocoaPods](https://cocoapods.org/)。CocoaPods 可讓您將 Office 365 和 Azure Active Directory Authentication Library (ADAL) 相依性提取至專案中。 34 | 35 | 一旦您有 Office 365 帳戶和已繫結至您的 Office 365 開發人員網站的 Azure AD 帳戶,您必須執行下列步驟︰ 36 | 37 | 1. 使用 Azure 註冊您的應用程式,並設定適當的 Office 365 Exchange Online 權限。 38 | 2. 安裝並使用 CocoaPods,將 Office 365 和 ADAL 驗證相依性置入您的專案中。 39 | 3. 在電子郵件預覽應用程式中輸入 Azure 應用程式註冊細節 (ClientID 和 RedirectUri)。 40 | 41 | ## 使用 CocoaPods 以匯入 O365 iOS SDK 42 | 附註:如果您從未以依存關係管理員身分使用 **CocoaPods**,您必須先安裝它,才能將 Office 365 iOS SDK 相依性置於您的專案。 43 | 44 | 在 Mac 上,從 **Terminal** 應用程式輸入接下來的兩行程式碼。 45 | 46 | sudo gem install cocoapods 47 | pod setup 48 | 49 | 如果安裝和設定都成功,您應該會看到**終端機安裝完成**訊息。如需有關 CocoaPods 和其用法的詳細資訊,請參閱 [CocoaPods](https://cocoapods.org/)。 50 | 51 | 52 | **在您的專案中取得 Office 365 SDK for iOS 相依性** 53 | 電子郵件預覽應用程式已經包含可將 Office 365 和 ADAL 元件 (pods) 放入專案的 podfile。它位於範例根目錄 ("Podfile") 中。此範例會顯示檔案的內容。 54 | 55 | target ‘O365-iOS-EmailPeek’ do 56 | pod 'ADALiOS', '~> 1.2.1' 57 | pod 'Office365/Outlook', '= 0.9.1' 58 | pod 'Office365/Discovery', '= 0.9.1' 59 | end 60 | 61 | 62 | 您只需要瀏覽到 **Terminal** (專案資料夾的根目錄) 中的專案目錄,然後執行下列命令。 63 | 64 | 65 | pod install 66 | 67 | 附註:您應該會收到這些相依性已加入至專案的確認,且從現在起,您必須在 Xcode 上開啟工作區而非專案 (**O365-iOS-EmailPeek.xcworkspace**)。如果在 Podfile 中有語法錯誤,就會在執行安裝命令時發生錯誤。 68 | 69 | ## 向 Microsoft Azure 註冊您的應用程式 70 | 1. 使用 Azure AD 認證登入 [Azure 管理入口網站](https://manage.windowsazure.com)。 71 | 2. 選取左邊功能表上的 [Active Directory]****,然後選取您的 Office 365 開發人員網站的目錄。 72 | 3. 在上方功能表中,選取 [應用程式]****。 73 | 4. 從下方功能表選取 [新增]****。 74 | 5. 在 [您想要做什麼]**** 頁面上,選取 [新增我的組織正在開發的應用程式]****。 75 | 6. 在 [告訴我們您的應用程式]**** 頁面上,為應用程式名稱指定 **O365-iOS-EmailPeek**,並為類型選取 [原生用戶端應用程式]****。 76 | 7. 選取頁面右下角的箭號圖示。 77 | 8. 在 [應用程式的資訊] 頁面上,指定重新導向 URI,在這個範例中,您可以指定 http://localhost/emailpeek,然後選取頁面右下角的核取方塊。為**將 ClientID 和 RedirectUri 置於專案**一節記憶此值。 78 | 9. 一旦成功新增應用程式,您就會進入應用程式的 [快速入門] 頁面。選取頂端功能表中的 [設定]。 79 | 10. 在 [其他應用程式的權限]**** 下新增下列權限︰[新增 Office 365 Exchange Online 應用程式]****,再依序選取 [讀取和寫入使用者郵件]**** 和 [以使用者身分傳送郵件]**** 權限。 80 | 13. 在 [設定]**** 頁面上複製為 [用戶端識別碼]**** 指定的值。為**將 ClientID 和 RedirectUri 置於專案**一節記憶此值。 81 | 14. 選取底部功能表中的 [儲存]****。 82 | 83 | 84 | ## 取得用戶端識別碼,並將 Uri 重新導向至專案 85 | 86 | 最後,您需要新增上一節**向 Microsoft Azure 註冊您的應用程式**所記錄的用戶端識別碼 和重新導向的 Uri。 87 | 88 | 瀏覽 **O365-iOS-EmailPeek** 專案目錄並開啟工作區 (O365-EmailPeek-iOS.xcworkspace)。在 **AppDelegate.m** 檔案中,您會看到檔案頂端新增 **ClientID** 和 **RedirectUri** 值。在此檔案中提供必要的值。 89 | 90 | // 您會設定應用程式的 clientId 和重新導向 URI。您會在 91 | // Azure AD 中登錄應用程式時取得。 92 | static NSString * const kClientId = @"ENTER_REDIRECT_URI_HERE"; 93 | static NSString * const kRedirectURLString = @"ENTER_CLIENT_ID_HERE"; 94 | static NSString * const kAuthorityURLString = @"https://login.microsoftonline.com/common"; 95 | 96 | 97 | 98 | # # 重要的程式碼檔案 99 | 100 | 101 | **模型** 102 | 103 | 這些網域實體是代表應用程式資料的自訂類別。所有這些類別都是不變的。他們會包裝 Office 365 SDK 所提供的基本實體。 104 | 105 | **Office365 協助程式** 106 | 107 | 協助程式是藉由 API 呼叫,與 Office 365 實際通訊的類別。這種架構會從 Office365 SDK 中解構其餘應用程式。 108 | 109 | **Office365 伺服器端篩選** 110 | 111 | 這些類別可在擷取期間,以正確的 Office 365 伺服器端篩選子句來協助進行適當的 API 呼叫。 112 | 113 | **ConversationManager 和 SettingsManager** 114 | 115 | 這些類別可幫助管理應用程式中的對話和設定。 116 | 117 | ** 控制器 ** 118 | 119 | 這些是適用於電子郵件預覽支援的不同檢視的控制器。 120 | 121 | **檢視** 122 | 123 | 這會實作兩個不同位置 (ConversationListViewController 和 ConversationViewController) 中使用的自訂儲存格。 124 | 125 | 126 | ## 問題與意見 127 | 128 | 我們樂於在電子郵件預覽應用程式範例中取得您的意見反應。您可以在此儲存機制的[問題](https://github.com/OfficeDev/O365-EmailPeek-iOS)區段中,將意見反應傳給我們。
129 |
130 | Office 365 的一般開發問題必須張貼至[堆疊溢位](http://stackoverflow.com/questions/tagged/Office365+API)。請確定使用 [Office365] 和 [API] 標記您的問題。 131 | 132 | ## 疑難排解 133 | 利用 Xcode 7.0 更新,會針對執行 iOS 9 的模擬器和裝置啟用應用程式傳輸安全性。請參閱 [應用程式傳輸安全性技術說明](https://developer.apple.com/library/prerelease/ios/technotes/App-Transport-Security-Technote/)。 134 | 135 | 在這個範例中,我們已經為 plist 中的下列網域建立暫存例外狀況: 136 | 137 | - outlook.office365.com 138 | 139 | 如果不包含這些例外狀況,在 Xcode 中部署到 iOS 9 模擬器時,所有 Office 365 API 的呼叫都會在此應用程式中進行。 140 | 141 | 142 | ## 其他資源 143 | 144 | * [iOS 的 Office 365 Connect 應用程式](https://github.com/OfficeDev/O365-iOS-Connect) 145 | * [iOS 的 Office 365 程式碼片段](https://github.com/OfficeDev/O365-iOS-Snippets) 146 | * [iOS 的 Office 365 設定檔範例](https://github.com/OfficeDev/O365-iOS-Profile) 147 | * [Office 365 API 文件](http://msdn.microsoft.com/office/office365/howto/platform-development-overview) 148 | * [Office 365 API 程式碼範例和視訊](https://msdn.microsoft.com/office/office365/howto/starter-projects-and-code-samples) 149 | * [Office 開發中心](http://dev.office.com/) 150 | * [電子郵件預覽上的媒體文件](https://medium.com/office-app-development/why-read-email-when-you-can-peek-2af947d352dc) 151 | 152 | ## 著作權 153 | 154 | Copyright (c) 2015 Microsoft.著作權所有,並保留一切權利。 155 | -------------------------------------------------------------------------------- /readme-images/emailpeek_video.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OfficeDev/O365-iOS-EmailPeek/d822aacd3b48bf84862ead6f7284e72b68530b42/readme-images/emailpeek_video.png --------------------------------------------------------------------------------