2 // HMScreenshotWindowController.m
5 // Created by Hori,Masaki on 2014/04/06.
6 // Copyright (c) 2014年 Hori,Masaki. All rights reserved.
9 #import "HMScreenshotWindowController.h"
10 #import "HMUserDefaults.h"
11 #import "HMMaskSelectView.h"
12 #import "HMMaskInfomation.h"
14 #import "HMAppDelegate.h"
16 #import <Accounts/Accounts.h>
17 #import <Social/Social.h>
20 @interface NSFileManager (KCDExtension)
21 - (NSString *)_web_pathWithUniqueFilenameForPath:(NSString *)path;
24 @interface HMScreenshotWindowController ()
26 @property (readonly) NSData *snapData;
27 @property (strong) NSImage *snap;
30 @property (strong) ACAccountStore *accountStore;
31 @property BOOL availableTwitter;
32 @property NSInteger shortURLLength;
35 - (void)postImage:(NSData *)jpeg withStatus:(NSString *)status;
38 @implementation HMScreenshotWindowController
39 @synthesize snapImageRep = _snapImageRep;
40 @synthesize snap = _snap;
41 @synthesize appendKanColleTag = _appendKanColleTag;
42 @synthesize useMask = _useMask;
44 + (NSSet *)keyPathsForValuesAffectingLeaveLength
46 return [NSSet setWithObjects:@"tweetString", @"appendKanColleTag", nil];
48 + (NSSet *)keyPathsForValuesAffectingLeaveLengthColor
50 return [NSSet setWithObject:@"leaveLength"];
52 + (NSSet *)keyPathsForValuesAffectingSnap
54 return [NSSet setWithObject:@"snapData"];
56 + (NSSet *)keyPathsForValuesAffectingCanTweet
58 return [NSSet setWithObject:@"leaveLength"];
63 self = [super initWithWindowNibName:NSStringFromClass([self class])];
65 _accountStore = [ACAccountStore new];
67 [self checkShortURLLength];
69 NSString *tag = NSLocalizedString(@"kancolle", @"kancolle twitter hash tag");
71 _tagString = [NSString stringWithFormat:@" #%@", tag];
75 _appendKanColleTag = HMStandardDefaults.appendKanColleTag;
77 self.tweetString = @"";
79 _useMask = HMStandardDefaults.useMask;
84 - (NSBitmapImageRep *)snapImageRep
88 - (void)setSnapImageRep:(NSBitmapImageRep *)snapImageRep
90 _snapImageRep = snapImageRep;
96 NSBitmapImageRep *rep = self.snapImageRep;
99 NSImage *image = [[NSImage alloc] initWithSize:[self.snapImageRep size]];
100 [image addRepresentation:self.snapImageRep];
103 for(HMMaskInfomation *info in self.maskSelectView.masks) {
105 NSBezierPath *path = [NSBezierPath bezierPathWithRect:info.maskRect];
106 [info.maskColor set];
112 NSData *tiffData = [image TIFFRepresentation];
113 rep = [NSBitmapImageRep imageRepWithData:tiffData];
116 return [rep representationUsingType:NSJPEGFileType properties:nil];
120 if(_snap) return _snap;
122 NSImage *image = [[NSImage alloc] initWithData:self.snapData];
124 self.tweetString = @"";
128 - (void)setSnap:(NSImage *)snap
136 - (void)setUseMask:(BOOL)useMask
138 HMStandardDefaults.useMask = useMask;
141 - (NSInteger)leaveLength
143 const NSUInteger maxTweetLength = 140;
144 if(self.appendKanColleTag) return maxTweetLength - self.tagString.length - self.shortURLLength - self.tweetString.length;
145 return maxTweetLength - self.shortURLLength - self.tweetString.length;
147 - (NSColor *)leaveLengthColor
149 if(self.leaveLength < 0) {
150 return [NSColor colorWithCalibratedRed:159/255.0 green:14/255.0 blue:0 alpha:1];
152 return [NSColor controlTextColor];
154 - (BOOL)appendKanColleTag
156 return _appendKanColleTag;
158 - (void)setAppendKanColleTag:(BOOL)appendKanColleTag
160 HMStandardDefaults.appendKanColleTag = appendKanColleTag;
161 _appendKanColleTag = appendKanColleTag;
165 ACAccountType *twitterType = [self.accountStore accountTypeWithAccountTypeIdentifier:ACAccountTypeIdentifierTwitter];
166 if(![twitterType accessGranted]) {
167 [self.accountStore requestAccessToAccountsWithType:twitterType
169 completion:^(BOOL granted, NSError *error) {
171 NSLog(@"No access granted");
173 // NSLog(@"succsess");
177 NSArray *accounts = [self.accountStore accountsWithAccountType:twitterType];
178 if([accounts count] == 0) {
179 NSLog(@"twitter account not avail.");
180 NSLog(@"Accounts -> %@", self.accountStore.accounts);
183 self.availableTwitter = YES;
185 return self.availableTwitter && self.leaveLength >= 0;
189 return self.snapData ? YES : NO;
192 - (NSURL *)saveDirectoryURL
194 HMAppDelegate *appDelegate = [[NSApplication sharedApplication] delegate];
195 return [NSURL fileURLWithPath:appDelegate.screenShotSaveDirectory];
198 - (IBAction)tweet:(id)sender
205 NSString *status = self.tweetString;
206 if(!status) status = @"";
207 if(self.appendKanColleTag) {
208 status = [status stringByAppendingString:self.tagString];
211 if(self.leaveLength >= 0) {
212 [self postImage:self.snapData withStatus:status];
213 [self.window.sheetParent endSheet:self.window returnCode:NSOKButton + 1];
219 - (IBAction)saveSnap:(id)sender
221 [self.window.sheetParent endSheet:self.window returnCode:NSOKButton + 0];
223 if(!self.snapData) return;
225 NSBundle *mainBundle = [NSBundle mainBundle];
226 NSDictionary *infoList = [mainBundle localizedInfoDictionary];
227 NSString *filename = [infoList objectForKey:@"CFBundleName"];
228 if([filename length] == 0) {
231 filename = [filename stringByAppendingPathExtension:@"jpg"];
232 NSURL *path = [[self saveDirectoryURL] URLByAppendingPathComponent:filename];
234 filename = [[NSFileManager defaultManager] _web_pathWithUniqueFilenameForPath:[path path]];
236 [self.snapData writeToFile:filename atomically:YES];
238 - (IBAction)cancel:(id)sender
240 [self.window.sheetParent endSheet:self.window returnCode:NSCancelButton];
242 - (void)postImage:(NSData *)jpeg withStatus:(NSString *)status
244 ACAccountType *twitterType = [self.accountStore accountTypeWithAccountTypeIdentifier:ACAccountTypeIdentifierTwitter];
246 SLRequestHandler requestHandler =
247 ^(NSData *responseData, NSHTTPURLResponse *urlResponse, NSError *error) {
249 NSInteger statusCode = urlResponse.statusCode;
250 if (statusCode >= 200 && statusCode < 300) {
251 // NSDictionary *postResponseData =
252 // [NSJSONSerialization JSONObjectWithData:responseData
253 // options:NSJSONReadingMutableContainers
255 // NSLog(@"[SUCCESS!] Created Tweet with ID: %@", postResponseData[@"id_str"]);
258 NSLog(@"[ERROR] Server responded: status code %ld %@", statusCode,
259 [NSHTTPURLResponse localizedStringForStatusCode:statusCode]);
263 NSLog(@"[ERROR] An error occurred while posting: %@", [error localizedDescription]);
267 ACAccountStoreRequestAccessCompletionHandler accountStoreHandler =
268 ^(BOOL granted, NSError *error) {
270 NSArray *accounts = [self.accountStore accountsWithAccountType:twitterType];
271 NSURL *url = [NSURL URLWithString:@"https://api.twitter.com"
272 @"/1.1/statuses/update_with_media.json"];
273 NSDictionary *params = @{@"status" : status};
274 SLRequest *request = [SLRequest requestForServiceType:SLServiceTypeTwitter
275 requestMethod:SLRequestMethodPOST
278 [request addMultipartData:jpeg
281 filename:@"image.jpg"];
282 [request setAccount:[accounts lastObject]];
283 [request performRequestWithHandler:requestHandler];
286 NSLog(@"[ERROR] An error occurred while asking for user authorization: %@",
287 [error localizedDescription]);
291 [self.accountStore requestAccessToAccountsWithType:twitterType
293 completion:accountStoreHandler];
296 - (void)checkShortURLLength
298 ACAccountType *twitterType = [self.accountStore accountTypeWithAccountTypeIdentifier:ACAccountTypeIdentifierTwitter];
300 SLRequestHandler requestHandler =
301 ^(NSData *responseData, NSHTTPURLResponse *urlResponse, NSError *error) {
303 NSInteger statusCode = urlResponse.statusCode;
304 if (statusCode >= 200 && statusCode < 300) {
305 NSDictionary *postResponseData =
306 [NSJSONSerialization JSONObjectWithData:responseData
307 options:NSJSONReadingMutableContainers
309 // NSLog(@"[SUCCESS!] characters_reserved_per_media is %@", postResponseData[@"characters_reserved_per_media"]);
311 self.shortURLLength = [postResponseData[@"characters_reserved_per_media"] integerValue];
314 NSLog(@"[ERROR] Server responded: status code %ld %@", statusCode,
315 [NSHTTPURLResponse localizedStringForStatusCode:statusCode]);
319 NSLog(@"[ERROR] An error occurred while posting: %@", [error localizedDescription]);
323 ACAccountStoreRequestAccessCompletionHandler accountStoreHandler =
324 ^(BOOL granted, NSError *error) {
326 NSArray *accounts = [self.accountStore accountsWithAccountType:twitterType];
327 NSURL *url = [NSURL URLWithString:@"https://api.twitter.com"
328 @"/1.1/help/configuration.json"];
329 SLRequest *request = [SLRequest requestForServiceType:SLServiceTypeTwitter
330 requestMethod:SLRequestMethodGET
333 [request setAccount:[accounts lastObject]];
334 [request performRequestWithHandler:requestHandler];
337 NSLog(@"[ERROR] An error occurred while asking for user authorization: %@",
338 [error localizedDescription]);
342 [self.accountStore requestAccessToAccountsWithType:twitterType
344 completion:accountStoreHandler];
352 - (BOOL)control:(NSControl*)control textView:(NSTextView*)textView doCommandBySelector:(SEL)commandSelector
355 if (commandSelector == @selector(insertNewline:))
357 [textView insertNewlineIgnoringFieldEditor:self];
366 - (void)windowWillClose:(NSNotification *)notification
368 [self.maskSelectView disableAllMasks:self];