Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

Twitpic integration #167

Open
wants to merge 18 commits into from

2 participants

@dlinsin

I integrated Twitpic as a picture sharing service, based on SHKTwitter and SHKTwitterForm. It features an option to only upload the picture to Twitpic or upload and send it directly to Twitter as well. There's also a bugfix in the code by Troy Gaul, which fixes an issue running iOS 4.2 and trying to switch on/off services. I added all translations except for one, which I couldn't figure out.

@bluesuedesw

Was not able to get your TwitPic solution to work. Got a Access Error each time stating "Client application is not permitted to use xAuth." Do I have to email twitter and request xAuth privileges or am I doing it wrong?

@dlinsin
@bluesuedesw

Thanks for the help David, got it operational now that I have xAuth access. Great work. I think it should share to both Twitter & TwitPic by default, but I like that you made it optional.

@dlinsin
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Feb 2, 2011
  1. @dlinsin
Commits on Feb 6, 2011
  1. @dlinsin
  2. @dlinsin
  3. @dlinsin
Commits on Feb 7, 2011
  1. @dlinsin

    * added TwitPic config

    dlinsin authored
  2. @dlinsin

    * implemented request

    dlinsin authored
  3. Fixed bug where editing didn't appear to work on 4.2 due to reading b…

    Troy Gaul authored
    …ack the on state before it had changed.
  4. @dlinsin

    * added twitpic to shares

    dlinsin authored
    * fixed URL
Commits on Feb 8, 2011
  1. @dlinsin

    * working sharing feature

    dlinsin authored
  2. @dlinsin

    * fixed wrong label

    dlinsin authored
    * always an image present, so don't use the full desc length
  3. @dlinsin
  4. @dlinsin
  5. @dlinsin

    * sending out tweet, based on initial config

    dlinsin authored
    * code used from SHKTwitter
  6. @dlinsin

    * added note

    dlinsin authored
  7. @dlinsin

    * added notes to clarify copy

    dlinsin authored
  8. @dlinsin
Commits on Feb 9, 2011
  1. @dlinsin
Commits on Feb 13, 2011
  1. @dlinsin
This page is out of date. Refresh to see the latest.
View
2  .gitignore
@@ -4,6 +4,8 @@
*.perspective
*.perspectivev3
*.mode1v3
+*.xcworkspace
+*xcuserdata
build
.DS_Store
Classes/ShareKit/SHKConfig.h
View
1  Classes/ShareKit/Core/SHKSharers.plist
@@ -21,6 +21,7 @@
<string>SHKReadItLater</string>
<string>SHKInstapaper</string>
<string>SHKTumblr</string>
+ <string>SHKTwitPic</string>
</array>
</dict>
</plist>
View
1  Classes/ShareKit/Localization/de.lproj/Localizable.strings
@@ -40,6 +40,7 @@
"Create an account at %@" = "Erstelle einen Account auf %@";
"Send to Twitter" = "An Twitter senden";
+"Send to TwitPic" = "An TwitPic senden";
"Message is too long" = "Nachricht zu lang";
"Twitter posts can only be 140 characters in length." = "Twitter Nachrichten können maximal 140 Zeichen lang sein.";
View
1  Classes/ShareKit/Localization/en.lproj/Localizable.strings
@@ -40,6 +40,7 @@
"Create an account at %@" = "Create an account at %@";
"Send to Twitter" = "Send to Twitter";
+"Send to TwitPic" = "Send to TwitPic";
"Message is too long" = "Message is too long";
"Twitter posts can only be 140 characters in length." = "Twitter posts can only be 140 characters in length.";
View
1  Classes/ShareKit/Localization/fr.lproj/Localizable.strings
@@ -40,6 +40,7 @@
"Create an account at %@" = "Créer un compte sur %@";
"Send to Twitter" = "Envoyer sur Twitter";
+"Send to TwitPic" = "Envoyer sur TwitPic";
"Message is too long" = "Message trop long";
"Twitter posts can only be 140 characters in length." = "Les messages Twitter ne peuvent dépasser 140 caractères.";
View
1  Classes/ShareKit/Localization/ko.lproj/Localizable.strings
@@ -40,6 +40,7 @@
"Create an account at %@" = "%@ 계정 만들기";
"Send to Twitter" = "Twitter로 보내기";
+"Send to TwitPic" = "TwitPic로 보내기";
"Message is too long" = "메시지가 너무 깁니다";
"Twitter posts can only be 140 characters in length." = "Twitter 메시지는 140자를 넘을 수 없습니다.";
View
1  Classes/ShareKit/Localization/nl.lproj/Localizable.strings
@@ -40,6 +40,7 @@
"Create an account at %@" = "Maak een account op %@";
"Send to Twitter" = "Verzend naar Twitter";
+"Send to TwitPic" = "Verzend naar TwitPic";
"Message is too long" = "Bericht is te lang";
"Twitter posts can only be 140 characters in length." = "Twitter bericht mag maar 140 karakters bevatten.";
View
BIN  Classes/ShareKit/Localization/vi.lproj/Localizable.strings
Binary file not shown
View
1  Classes/ShareKit/Localization/zh_CN.lproj/Localizable.strings
@@ -41,6 +41,7 @@
"Create an account at %@" = "在 %@ 上创建一个账户";
"Send to Twitter" = "发送到 Twitter";
+"Send to TwitPic" = "发送到 TwitPic";
"Message is too long" = "消息太长了";
"Twitter posts can only be 140 characters in length." = "Twitter 消息不能超过 140 个字符。";
View
9 Classes/ShareKit/SHKConfig.h
@@ -79,13 +79,20 @@
#define SHKBitLyLogin @""
#define SHKBitLyKey @""
+// Evernote http://www.evernote.com/about/developer/api/
+#define SHKEvernoteConsumerKey @""
+#define SHKEvernoteSecretKey @""
+#define SHKEvernoteUserStoreURL @""
+#define SHKEvernoteNetStoreURLBase @""
+
// ShareMenu Ordering
#define SHKShareMenuAlphabeticalOrder 1 // Setting this to 1 will show list in Alphabetical Order, setting to 0 will follow the order in SHKShares.plist
// Append 'Shared With 'Signature to Email (and related forms)
#define SHKSharedWithSignature 0
-
+// TwitPic http://dev.twitpic.com/
+#define SHKTwitPicAPIKey @""
/*
UI Configuration : Basic
View
44 Classes/ShareKit/Sharers/Services/TwitPic/SHKTwitPic.h
@@ -0,0 +1,44 @@
+//
+// SHKTwitPic.h
+// ShareKit
+//
+// Created by David Linsin on 2/5/11.
+// Copyright 2011 furryfishApps.com. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+#import "SHKOAuthSharer.h"
+#import "SHKTwitPicForm.h"
+
+@interface SHKTwitPic : SHKOAuthSharer {
+ NSString *twitPicAPIKey;
+}
+
+@property (nonatomic, retain) NSString *twitPicAPIKey;
+
+#pragma mark -
+#pragma mark UI Implementation
+
+- (void)showTwitterForm;
+
+#pragma mark -
+#pragma mark Share API Methods
+
+- (void)sendForm:(SHKTwitPicForm *)form;
+
+- (void)sendImage;
+- (void)sendImage:(OAServiceTicket *)ticket didFinishWithData:(NSData *)data;
+- (void)sendImage:(OAServiceTicket *)ticket didFailWithError:(NSError*)error;
+
+- (void)sendStatus:(NSString*)status;
+- (void)sendStatusTicket:(OAServiceTicket *)ticket didFinishWithData:(NSData *)data;
+- (void)sendStatusTicket:(OAServiceTicket *)ticket didFailWithError:(NSError*)error;
+
+#pragma mark -
+#pragma mark twitpic specific
+
+- (BOOL)shareOnTwitter;
+- (void)setShareOnTwitter:(BOOL)share;
+
+
+@end
View
340 Classes/ShareKit/Sharers/Services/TwitPic/SHKTwitPic.m
@@ -0,0 +1,340 @@
+//
+// SHKTwitPic.m
+// ShareKit
+//
+// Created by David Linsin on 2/5/11.
+// Copyright 2011 furryfishApps.com. All rights reserved.
+//
+
+#import "SHKTwitPic.h"
+
+
+@implementation SHKTwitPic
+
+@synthesize twitPicAPIKey;
+
+- (id)init {
+ self = [super init];
+ if (self) {
+ // OAUTH
+ self.consumerKey = SHKTwitterConsumerKey;
+ self.secretKey = SHKTwitterSecret;
+ self.authorizeCallbackURL = [NSURL URLWithString:SHKTwitterCallbackUrl];// HOW-TO: In your Twitter application settings, use the "Callback URL" field. If you do not have this field in the settings, set your application type to 'Browser'.
+
+
+ // You do not need to edit these, they are the same for everyone
+ self.authorizeURL = [NSURL URLWithString:@"https://twitter.com/oauth/authorize"];
+ self.requestURL = [NSURL URLWithString:@"https://twitter.com/oauth/request_token"];
+ self.accessURL = [NSURL URLWithString:@"https://twitter.com/oauth/access_token"];
+
+ self.twitPicAPIKey = SHKTwitPicAPIKey;
+ }
+ return self;
+}
+
+
+#pragma mark -
+#pragma mark Configuration : Service Defination
+
++ (NSString *)sharerTitle {
+ return @"TwitPic";
+}
+
++ (BOOL)canShareImage {
+ return YES;
+}
+
+
+#pragma mark -
+#pragma mark Configuration : Dynamic Enable
+
+- (BOOL)shouldAutoShare {
+ return NO;
+}
+
+
+#pragma mark -
+#pragma mark Authorization
+
+- (BOOL)isAuthorized {
+ return [super restoreAccessToken];
+}
+
+- (void)promptAuthorization {
+ [super authorizationFormShow];
+}
+
+
+#pragma mark xAuth
+
++ (NSString *)authorizationFormCaption {
+ return SHKLocalizedString(@"Create a free account at %@", @"Twitter.com");
+}
+
++ (NSArray *)authorizationFormFields {
+ if ([SHKTwitterUsername isEqualToString:@""])
+ return [super authorizationFormFields];
+
+ return [NSArray arrayWithObjects:
+ [SHKFormFieldSettings label:SHKLocalizedString(@"Username") key:@"username" type:SHKFormFieldTypeText start:nil],
+ [SHKFormFieldSettings label:SHKLocalizedString(@"Password") key:@"password" type:SHKFormFieldTypePassword start:nil],
+ [SHKFormFieldSettings label:SHKLocalizedString(@"Send to Twitter") key:@"sendToTwitter" type:SHKFormFieldTypeSwitch start:SHKFormFieldSwitchOn],
+ nil];
+}
+
+- (void)authorizationFormValidate:(SHKFormController *)form {
+ self.pendingForm = form;
+ [self tokenAccess];
+}
+
+- (void)tokenAccessModifyRequest:(OAMutableURLRequest *)oRequest {
+ NSDictionary *formValues = [pendingForm formValues];
+ OARequestParameter *username = [[[OARequestParameter alloc] initWithName:@"x_auth_username"
+ value:[formValues objectForKey:@"username"]] autorelease];
+
+ OARequestParameter *password = [[[OARequestParameter alloc] initWithName:@"x_auth_password"
+ value:[formValues objectForKey:@"password"]] autorelease];
+
+ OARequestParameter *mode = [[[OARequestParameter alloc] initWithName:@"x_auth_mode"
+ value:@"client_auth"] autorelease];
+
+ [oRequest setParameters:[NSArray arrayWithObjects:username, password, mode, nil]];
+}
+
+- (void)tokenAccessTicket:(OAServiceTicket *)ticket didFinishWithData:(NSData *)data {
+ if (ticket.didSucceed) {
+ [self setShareOnTwitter:[[[super.pendingForm formValues] objectForKey:@"sendToTwitter"] isEqualToString:SHKFormFieldSwitchOn]];
+ [pendingForm close];
+ } else {
+ NSString *response = [[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding] autorelease];
+
+ SHKLog(@"tokenAccessTicket Response Body: %@", response);
+
+ [self tokenAccessTicket:ticket didFailWithError:[SHK error:response]];
+ return;
+ }
+
+ [super tokenAccessTicket:ticket didFinishWithData:data];
+}
+
+#pragma mark -
+#pragma mark UI Implementation
+
+- (void)show {
+ [item setCustomValue:item.title forKey:@"status"];
+ [self showTwitterForm];
+}
+
+- (void)showTwitterForm {
+ SHKTwitPicForm *rootView = [[SHKTwitPicForm alloc] initWithNibName:nil bundle:nil];
+ rootView.delegate = self;
+
+ // force view to load so we can set textView text
+ [rootView view];
+
+ rootView.textView.text = [item customValueForKey:@"status"];
+ rootView.hasAttachment = YES;
+
+ [self pushViewController:rootView animated:NO];
+
+ [[SHK currentHelper] showViewController:self];
+}
+
+- (void)sendForm:(SHKTwitPicForm *)form {
+ [item setCustomValue:form.textView.text forKey:@"status"];
+ [self tryToSend];
+}
+
+#pragma mark -
+#pragma mark Share API Methods
+
+- (BOOL)validate {
+ NSString *status = [item customValueForKey:@"status"];
+ return status != nil && (int)status.length >= 0 && status.length <= 140;
+}
+
+- (BOOL)send {
+ if (![self validate]) {
+ [self show];
+ } else {
+ [self sendImage];
+ [self sendDidStart];
+ return YES;
+ }
+ return NO;
+}
+
+- (NSString*)oauthHeader {
+ NSURL *serviceURL = [NSURL URLWithString:@"https://api.twitter.com/1/account/verify_credentials.json"];
+
+ OAMutableURLRequest *oRequest = [[OAMutableURLRequest alloc] initWithURL:serviceURL
+ consumer:consumer
+ token:accessToken
+ realm:@"http://api.twitter.com/"
+ signatureProvider:signatureProvider];
+ [oRequest prepare];
+
+ NSDictionary * headerDict = [oRequest allHTTPHeaderFields];
+ NSString * oauthHeader = [NSString stringWithString:[headerDict valueForKey:@"Authorization"]];
+
+ [oRequest release];
+ oRequest = nil;
+ return oauthHeader;
+}
+
+- (NSData*)imageData {
+ CGFloat compression = 0.9f;
+ NSData *imageData = UIImageJPEGRepresentation([item image], compression);
+
+ // TODO
+ // Note from Nate to creator of sendImage method - This seems like it could be a source of sluggishness.
+ // For example, if the image is large (say 3000px x 3000px for example), it would be better to resize the image
+ // to an appropriate size (max of img.ly) and then start trying to compress.
+
+ while ([imageData length] > 700000 && compression > 0.1) {
+ // NSLog(@"Image size too big, compression more: current data size: %d bytes",[imageData length]);
+ compression -= 0.1;
+ imageData = UIImageJPEGRepresentation([item image], compression);
+
+ }
+ return imageData;
+}
+
+- (void)sendImage {
+ NSString * oauthHeader = [self oauthHeader];
+
+ NSURL *serviceURL = [NSURL URLWithString:@"http://api.twitpic.com/2/upload.json"];
+ OAMutableURLRequest *oRequest = [[OAMutableURLRequest alloc] initWithURL:serviceURL
+ consumer:consumer
+ token:accessToken
+ realm:@"http://api.twitter.com/"
+ signatureProvider:signatureProvider];
+
+ // NASTY workaround to prevent Authorization HTTP header field to be set later on, TwitPic doesn't like it
+ [oRequest prepare];
+ [oRequest setValue:nil forHTTPHeaderField:@"Authorization"];
+ // END NASTY workaround
+
+ [oRequest setHTTPMethod:@"POST"];
+ [oRequest setValue:@"https://api.twitter.com/1/account/verify_credentials.json" forHTTPHeaderField:@"X-Auth-Service-Provider"];
+ [oRequest setValue:oauthHeader forHTTPHeaderField:@"X-Verify-Credentials-Authorization"];
+
+
+ NSString *boundary = @"0xKhTmLbOuNdArY";
+ NSString *contentType = [NSString stringWithFormat:@"multipart/form-data; boundary=%@",boundary];
+ [oRequest setValue:contentType forHTTPHeaderField:@"Content-Type"];
+
+ NSMutableData *body = [NSMutableData data];
+
+ [body appendData:[[NSString stringWithFormat:@"--%@\r\n",boundary] dataUsingEncoding:NSUTF8StringEncoding]];
+ [body appendData:[@"Content-Disposition: form-data; name=\"key\"\r\n\r\n" dataUsingEncoding:NSUTF8StringEncoding]];
+ [body appendData:[self.twitPicAPIKey dataUsingEncoding:NSUTF8StringEncoding]];
+ [body appendData:[@"\r\n" dataUsingEncoding:NSUTF8StringEncoding]];
+
+ [body appendData:[[NSString stringWithFormat:@"--%@\r\n",boundary] dataUsingEncoding:NSUTF8StringEncoding]];
+ [body appendData:[@"Content-Disposition: form-data; name=\"media\"; filename=\"upload.jpg\"\r\n" dataUsingEncoding:NSUTF8StringEncoding]];
+ [body appendData:[@"Content-Type: image/jpg\r\n\r\n" dataUsingEncoding:NSUTF8StringEncoding]];
+ [body appendData:[self imageData]];
+ [body appendData:[@"\r\n" dataUsingEncoding:NSUTF8StringEncoding]];
+
+ [body appendData:[[NSString stringWithFormat:@"--%@\r\n",boundary] dataUsingEncoding:NSUTF8StringEncoding]];
+ [body appendData:[[NSString stringWithString:@"Content-Disposition: form-data; name=\"message\"\r\n\r\n"] dataUsingEncoding:NSUTF8StringEncoding]];
+ [body appendData:[[item customValueForKey:@"status"] dataUsingEncoding:NSUTF8StringEncoding]];
+ [body appendData:[@"\r\n" dataUsingEncoding:NSUTF8StringEncoding]];
+
+ [body appendData:[[NSString stringWithFormat:@"--%@--\r\n",boundary] dataUsingEncoding:NSUTF8StringEncoding]];
+
+ [oRequest setHTTPBody:body];
+
+ [self sendDidStart];
+
+ // Start the request
+ OAAsynchronousDataFetcher *fetcher = [OAAsynchronousDataFetcher asynchronousFetcherWithRequest:oRequest
+ delegate:self
+ didFinishSelector:@selector(sendImage:didFinishWithData:)
+ didFailSelector:@selector(sendImage:didFailWithError:)];
+
+ [fetcher start];
+
+
+ [oRequest release];
+}
+
+- (void)sendImage:(OAServiceTicket *)ticket didFinishWithData:(NSData *)data {
+ if (ticket.didSucceed) {
+ if ([self shareOnTwitter]) {
+ NSString *url = @"";
+ NSScanner *scanner = [NSScanner scannerWithString:[[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding] autorelease]];
+ [scanner scanUpToString:@"\"url\":\"" intoString:nil];
+
+ if ([scanner scanString:@"\"url\":\"" intoString:nil]) {
+ [scanner scanUpToCharactersFromSet:[NSCharacterSet characterSetWithCharactersInString:@"\""] intoString:&url];
+ url = [url stringByReplacingOccurrencesOfString:@"\\" withString:@""];
+ NSString *twitPicStatus = [NSString stringWithFormat:@"%@ %@", [item customValueForKey:@"status"], url];
+ [self sendStatus: twitPicStatus];
+ } else {
+ [self sendDidFailWithError:nil];
+ }
+ } else {
+ [self sendDidFinish];
+ }
+ } else {
+ [self sendDidFailWithError:nil];
+ }
+}
+
+- (void)sendImage:(OAServiceTicket *)ticket didFailWithError:(NSError*)error {
+ [self sendDidFailWithError:error];
+}
+
+- (void)sendStatus:(NSString*)status {
+ OAMutableURLRequest *oRequest = [[OAMutableURLRequest alloc] initWithURL:[NSURL URLWithString:@"http://api.twitter.com/1/statuses/update.json"]
+ consumer:consumer
+ token:accessToken
+ realm:nil
+ signatureProvider:nil];
+
+ [oRequest setHTTPMethod:@"POST"];
+
+ OARequestParameter *statusParam = [[OARequestParameter alloc] initWithName:@"status" value:status];
+ NSArray *params = [NSArray arrayWithObjects:statusParam, nil];
+ [oRequest setParameters:params];
+ [statusParam release];
+
+ OAAsynchronousDataFetcher *fetcher = [OAAsynchronousDataFetcher asynchronousFetcherWithRequest:oRequest
+ delegate:self
+ didFinishSelector:@selector(sendStatusTicket:didFinishWithData:)
+ didFailSelector:@selector(sendStatusTicket:didFailWithError:)];
+
+ [fetcher start];
+ [oRequest release];
+}
+
+- (void)sendStatusTicket:(OAServiceTicket *)ticket didFinishWithData:(NSData *)data {
+
+ if (ticket.didSucceed) {
+ [self sendDidFinish];
+ } else {
+ NSString *string = @"Your picture is on TwitPic, but we couldn't share it on Twitter!";
+ NSError *error = [NSError errorWithDomain:@"Twitter" code:2 userInfo:[NSDictionary dictionaryWithObject:string forKey:NSLocalizedDescriptionKey]];
+ [self sendDidFailWithError:error];
+ }
+
+}
+
+- (void)sendStatusTicket:(OAServiceTicket *)ticket didFailWithError:(NSError*)error {
+ [self sendDidFailWithError:error];
+}
+
+#pragma mark -
+#pragma mark twitpic specific
+
+- (BOOL)shareOnTwitter {
+ return [[NSUserDefaults standardUserDefaults] boolForKey:[NSString stringWithFormat:@"%@_shareOnTwitter", [self sharerId]]];
+}
+
+- (void)setShareOnTwitter:(BOOL)share {
+ [[NSUserDefaults standardUserDefaults] setBool:share forKey:[NSString stringWithFormat:@"%@_shareOnTwitter", [self sharerId]]];
+}
+
+@end
View
49 Classes/ShareKit/Sharers/Services/TwitPic/SHKTwitPicForm.h
@@ -0,0 +1,49 @@
+//
+// SHKTwitPicForm.h
+// ShareKit
+//
+// Created by Nathan Weiner on 6/22/10.
+// Adapted by David Linsin on 2/8/11 to support TwitPic.
+
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+//
+//
+
+#import <UIKit/UIKit.h>
+
+
+@interface SHKTwitPicForm : UIViewController <UITextViewDelegate>
+{
+ id delegate;
+ UITextView *textView;
+ UILabel *counter;
+ BOOL hasAttachment;
+}
+
+@property (nonatomic, retain) id delegate;
+@property (nonatomic, retain) UITextView *textView;
+@property (nonatomic, retain) UILabel *counter;
+@property BOOL hasAttachment;
+
+- (void)layoutCounter;
+- (void)save;
+- (void)keyboardWillShow:(NSNotification *)notification;
+
+@end
View
239 Classes/ShareKit/Sharers/Services/TwitPic/SHKTwitPicForm.m
@@ -0,0 +1,239 @@
+//
+// SHKTwitPicForm.m
+// ShareKit
+//
+// Created by Nathan Weiner on 6/22/10.
+// Adapted by David Linsin on 2/8/11 to support TwitPic.
+
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+//
+//
+
+#import "SHKTwitPicForm.h"
+#import "SHK.h"
+#import "SHKTwitPic.h"
+
+
+@implementation SHKTwitPicForm
+
+@synthesize delegate;
+@synthesize textView;
+@synthesize counter;
+@synthesize hasAttachment;
+
+- (void)dealloc
+{
+ [delegate release];
+ [textView release];
+ [counter release];
+ [super dealloc];
+}
+
+- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
+{
+ if ((self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]))
+ {
+ self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemCancel
+ target:self
+ action:@selector(cancel)];
+
+ self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:SHKLocalizedString(@"Send to TwitPic")
+ style:UIBarButtonItemStyleDone
+ target:self
+ action:@selector(save)];
+ }
+ return self;
+}
+
+
+
+- (void)loadView
+{
+ [super loadView];
+
+ self.view.backgroundColor = [UIColor whiteColor];
+
+ self.textView = [[UITextView alloc] initWithFrame:self.view.bounds];
+ textView.delegate = self;
+ textView.font = [UIFont systemFontOfSize:15];
+ textView.contentInset = UIEdgeInsetsMake(5,5,0,0);
+ textView.backgroundColor = [UIColor whiteColor];
+ textView.autoresizesSubviews = YES;
+ textView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
+
+ [self.view addSubview:textView];
+}
+
+- (void)viewDidAppear:(BOOL)animated
+{
+ [super viewDidAppear:animated];
+
+ NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
+ [nc addObserver:self selector:@selector(keyboardWillShow:) name: UIKeyboardWillShowNotification object:nil];
+
+ [self.textView becomeFirstResponder];
+}
+
+- (void)viewDidDisappear:(BOOL)animated
+{
+ [super viewDidDisappear:animated];
+
+ // Remove observers
+ NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
+ [nc removeObserver:self name: UIKeyboardWillShowNotification object:nil];
+
+ // Remove the SHK view wrapper from the window
+ [[SHK currentHelper] viewWasDismissed];
+}
+
+- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
+{
+ return YES;
+}
+
+//#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+- (void)keyboardWillShow:(NSNotification *)notification
+{
+ CGRect keyboardFrame;
+ CGFloat keyboardHeight;
+
+ // 3.2 and above
+ /*if (UIKeyboardFrameEndUserInfoKey)
+ {
+ [[notification.userInfo valueForKey:UIKeyboardFrameEndUserInfoKey] getValue:&keyboardFrame];
+ if ([[UIDevice currentDevice] orientation] == UIDeviceOrientationPortrait || [[UIDevice currentDevice] orientation] == UIDeviceOrientationPortraitUpsideDown)
+ keyboardHeight = keyboardFrame.size.height;
+ else
+ keyboardHeight = keyboardFrame.size.width;
+ }
+
+ // < 3.2
+ else
+ {*/
+
+ [[notification.userInfo valueForKey:UIKeyboardBoundsUserInfoKey] getValue:&keyboardFrame];
+ keyboardHeight = keyboardFrame.size.height;
+ //}
+
+ // Find the bottom of the screen (accounting for keyboard overlay)
+ // This is pretty much only for pagesheet's on the iPad
+ UIInterfaceOrientation orient = [[UIApplication sharedApplication] statusBarOrientation];
+ BOOL inLandscape = orient == UIInterfaceOrientationLandscapeLeft || orient == UIInterfaceOrientationLandscapeRight;
+ BOOL upsideDown = orient == UIInterfaceOrientationPortraitUpsideDown || orient == UIInterfaceOrientationLandscapeRight;
+
+ CGPoint topOfViewPoint = [self.view convertPoint:CGPointZero toView:nil];
+ CGFloat topOfView = inLandscape ? topOfViewPoint.x : topOfViewPoint.y;
+
+ CGFloat screenHeight = inLandscape ? [[UIScreen mainScreen] applicationFrame].size.width : [[UIScreen mainScreen] applicationFrame].size.height;
+
+ CGFloat distFromBottom = screenHeight - ((upsideDown ? screenHeight - topOfView : topOfView ) + self.view.bounds.size.height) + ([UIApplication sharedApplication].statusBarHidden || upsideDown ? 0 : 20);
+ CGFloat maxViewHeight = self.view.bounds.size.height - keyboardHeight + distFromBottom;
+
+ textView.frame = CGRectMake(0,0,self.view.bounds.size.width,maxViewHeight);
+ [self layoutCounter];
+}
+//#pragma GCC diagnostic pop
+
+#pragma mark -
+
+- (void)updateCounter
+{
+ if (counter == nil)
+ {
+ self.counter = [[UILabel alloc] initWithFrame:CGRectZero];
+ counter.backgroundColor = [UIColor clearColor];
+ counter.opaque = NO;
+ counter.font = [UIFont boldSystemFontOfSize:14];
+ counter.textAlignment = UITextAlignmentRight;
+
+ counter.autoresizesSubviews = YES;
+ counter.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleTopMargin;
+
+ [self.view addSubview:counter];
+ [self layoutCounter];
+
+ [counter release];
+ }
+
+ int count = (hasAttachment?115:140) - textView.text.length;
+ counter.text = [NSString stringWithFormat:@"%@%i", hasAttachment ? @"Image + ":@"" , count];
+ counter.textColor = count >= 0 ? [UIColor blackColor] : [UIColor redColor];
+}
+
+- (void)layoutCounter
+{
+ counter.frame = CGRectMake(textView.bounds.size.width-150-15,
+ textView.bounds.size.height-15-9,
+ 150,
+ 15);
+}
+
+- (void)textViewDidBeginEditing:(UITextView *)textView
+{
+ [self updateCounter];
+}
+
+- (void)textViewDidChange:(UITextView *)textView
+{
+ [self updateCounter];
+}
+
+- (void)textViewDidEndEditing:(UITextView *)textView
+{
+ [self updateCounter];
+}
+
+#pragma mark -
+
+- (void)cancel
+{
+ [[SHK currentHelper] hideCurrentViewControllerAnimated:YES];
+ [(SHKTwitPic *)delegate sendDidCancel];
+}
+
+- (void)save
+{
+ if (textView.text.length > (hasAttachment?115:140))
+ {
+ [[[[UIAlertView alloc] initWithTitle:SHKLocalizedString(@"Message is too long")
+ message:SHKLocalizedString(@"Twitter posts can only be 140 characters in length.")
+ delegate:nil
+ cancelButtonTitle:SHKLocalizedString(@"Close")
+ otherButtonTitles:nil] autorelease] show];
+ return;
+ }
+
+ else if (textView.text.length == 0)
+ {
+ [[[[UIAlertView alloc] initWithTitle:SHKLocalizedString(@"Message is empty")
+ message:SHKLocalizedString(@"You must enter a message in order to post.")
+ delegate:nil
+ cancelButtonTitle:SHKLocalizedString(@"Close")
+ otherButtonTitles:nil] autorelease] show];
+ return;
+ }
+
+ [(SHKTwitPic *)delegate sendForm:self];
+
+ [[SHK currentHelper] hideCurrentViewControllerAnimated:YES];
+}
+
+@end
View
5 Classes/ShareKit/UI/SHKShareMenu.m
@@ -250,9 +250,10 @@ - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
UISwitch *toggle = (UISwitch *)[cell editingAccessoryView];
- [toggle setOn:!toggle.on animated:YES];
+ BOOL newOn = !toggle.on;
+ [toggle setOn:newOn animated:YES];
- if (toggle.on)
+ if (newOn)
[exclusions removeObjectForKey:[rowData objectForKey:@"className"]];
else
View
20 ShareKit.xcodeproj/project.pbxproj
@@ -106,6 +106,8 @@
43D1DEF011D5CDD200550D75 /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 43D1DEEF11D5CDD200550D75 /* SystemConfiguration.framework */; };
43EF406E11D3FFF800B1F700 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 43EF406D11D3FFF800B1F700 /* Security.framework */; };
43FF9C7412270E9F00ADE53C /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 43FF9C7212270E9F00ADE53C /* Localizable.strings */; };
+ B61E9AE112FED78600EB044B /* SHKTwitPicForm.m in Sources */ = {isa = PBXBuildFile; fileRef = B61E9AE012FED78600EB044B /* SHKTwitPicForm.m */; };
+ B69E7E0B12FDA9C400EE23DC /* SHKTwitPic.m in Sources */ = {isa = PBXBuildFile; fileRef = B69E7E0A12FDA9C400EE23DC /* SHKTwitPic.m */; };
/* End PBXBuildFile section */
/* Begin PBXFileReference section */
@@ -311,6 +313,10 @@
43FF9C7312270E9F00ADE53C /* en */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; name = en; path = Classes/ShareKit/Localization/en.lproj/Localizable.strings; sourceTree = SOURCE_ROOT; };
43FF9C7512270EB900ADE53C /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = de; path = Classes/ShareKit/Localization/de.lproj/Localizable.strings; sourceTree = SOURCE_ROOT; };
8D1107310486CEB800E47090 /* ShareKit-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "ShareKit-Info.plist"; plistStructureDefinitionIdentifier = "com.apple.xcode.plist.structure-definition.iphone.info-plist"; sourceTree = "<group>"; };
+ B61E9ADF12FED78600EB044B /* SHKTwitPicForm.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SHKTwitPicForm.h; sourceTree = "<group>"; };
+ B61E9AE012FED78600EB044B /* SHKTwitPicForm.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SHKTwitPicForm.m; sourceTree = "<group>"; };
+ B69E7E0912FDA9C400EE23DC /* SHKTwitPic.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SHKTwitPic.h; sourceTree = "<group>"; };
+ B69E7E0A12FDA9C400EE23DC /* SHKTwitPic.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SHKTwitPic.m; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@@ -720,6 +726,7 @@
43A536C011DBE3B9004A1712 /* Services */ = {
isa = PBXGroup;
children = (
+ B69E7E0812FDA9A800EE23DC /* TwitPic */,
43A536C111DBE3B9004A1712 /* Delicious */,
4379F2891291AC9700D2A41E /* Evernote */,
43A536C411DBE3B9004A1712 /* Facebook */,
@@ -891,6 +898,17 @@
name = Localization;
sourceTree = "<group>";
};
+ B69E7E0812FDA9A800EE23DC /* TwitPic */ = {
+ isa = PBXGroup;
+ children = (
+ B69E7E0912FDA9C400EE23DC /* SHKTwitPic.h */,
+ B69E7E0A12FDA9C400EE23DC /* SHKTwitPic.m */,
+ B61E9ADF12FED78600EB044B /* SHKTwitPicForm.h */,
+ B61E9AE012FED78600EB044B /* SHKTwitPicForm.m */,
+ );
+ path = TwitPic;
+ sourceTree = "<group>";
+ };
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
@@ -1052,6 +1070,8 @@
4379F2C11291AC9700D2A41E /* SHKEvernote.m in Sources */,
4379F2EA1291AE5700D2A41E /* NSData+md5.m in Sources */,
4379F3B21291C45700D2A41E /* SHKTextMessage.m in Sources */,
+ B69E7E0B12FDA9C400EE23DC /* SHKTwitPic.m in Sources */,
+ B61E9AE112FED78600EB044B /* SHKTwitPicForm.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Something went wrong with that request. Please try again.