merged image

This commit is contained in:
Jeena Paradies 2012-11-24 03:44:07 +01:00
commit a626395050
18 changed files with 420 additions and 35 deletions

View file

@ -13,6 +13,8 @@
#import "Constants.h"
#import "AccessToken.h"
#import <Growl/Growl.h>
#import "NSData+Base64.h"
#import "MimeType.h"
@interface Controller : NSObject <GrowlApplicationBridgeDelegate> {
IBOutlet WebView *timelineView;

View file

@ -9,6 +9,7 @@
#import "Controller.h"
#import "NewMessageWindow.h"
#import "PostModel.h"
#import "NSData+Base64.h"
@implementation Controller
@synthesize loginViewWindow;
@ -259,7 +260,6 @@
return NO;
}
- (IBAction)openNewMessageWindow:(id)sender
{
[NSApp activateIgnoringOtherApps:YES];
@ -288,7 +288,6 @@
NewMessageWindow *newTweet = (NewMessageWindow *)[[NSDocumentController sharedDocumentController] openUntitledDocumentAndDisplay:YES error:nil];
[newTweet withString:aString];
}
}
- (void)handleGetURLEvent:(NSAppleEventDescriptor *)event withReplyEvent:(NSAppleEventDescriptor *)replyEvent
@ -307,11 +306,24 @@
if (post.location) {
locationObject = [NSString stringWithFormat:@"[%f, %f]", post.location.coordinate.latitude, post.location.coordinate.longitude];
}
NSString *func = [NSString stringWithFormat:@"tentia_instance.sendNewMessage(\"%@\", \"%@\", \"%@\", %@)",
NSString *imageFilePath = @"null";
if (post.imageFilePath) {
NSError *error;
NSString *mimeType = [MimeType mimeTypeForFileAtPath:post.imageFilePath error:&error];
NSData *data = [[NSData alloc] initWithContentsOfFile:post.imageFilePath];
NSString *base64 = [data base64Encoding_xcd];
[data release];
imageFilePath = [NSString stringWithFormat:@"\"data:%@;base64,%@\"", mimeType, base64];
}
NSString *func = [NSString stringWithFormat:@"tentia_instance.sendNewMessage(\"%@\", \"%@\", \"%@\", %@, %@)",
text,
post.inReplyTostatusId,
post.inReplyToEntity,
locationObject];
locationObject,
imageFilePath];
[timelineView stringByEvaluatingJavaScriptFromString:func];
}

View file

@ -184,15 +184,23 @@
<string key="NSTitle">Add current location</string>
<string key="NSKeyEquiv"/>
<int key="NSMnemonicLoc">2147483647</int>
<object class="NSCustomResource" key="NSOnImage">
<object class="NSCustomResource" key="NSOnImage" id="400068421">
<string key="NSClassName">NSImage</string>
<string key="NSResourceName">NSMenuCheckmark</string>
</object>
<object class="NSCustomResource" key="NSMixedImage">
<object class="NSCustomResource" key="NSMixedImage" id="196417858">
<string key="NSClassName">NSImage</string>
<string key="NSResourceName">NSMenuMixedState</string>
</object>
</object>
<object class="NSMenuItem" id="502380341">
<reference key="NSMenu" ref="723763594"/>
<string key="NSTitle">Add image</string>
<string key="NSKeyEquiv"/>
<int key="NSMnemonicLoc">2147483647</int>
<reference key="NSOnImage" ref="400068421"/>
<reference key="NSMixedImage" ref="196417858"/>
</object>
</object>
</object>
</object>
@ -263,6 +271,14 @@
</object>
<int key="connectionID">100054</int>
</object>
<object class="IBConnectionRecord">
<object class="IBActionConnection" key="connection">
<string key="label">addImage:</string>
<reference key="source" ref="512844837"/>
<reference key="destination" ref="502380341"/>
</object>
<int key="connectionID">100056</int>
</object>
<object class="IBConnectionRecord">
<object class="IBOutletConnection" key="connection">
<string key="label">delegate</string>
@ -378,6 +394,7 @@
<object class="NSMutableArray" key="children">
<bool key="EncodedWithXMLCoder">YES</bool>
<reference ref="921309347"/>
<reference ref="502380341"/>
</object>
<reference key="parent" ref="0"/>
</object>
@ -386,6 +403,11 @@
<reference key="object" ref="921309347"/>
<reference key="parent" ref="723763594"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">100055</int>
<reference key="object" ref="502380341"/>
<reference key="parent" ref="723763594"/>
</object>
</object>
</object>
<object class="NSMutableDictionary" key="flattenedProperties">
@ -403,6 +425,7 @@
<string>100040.IBPluginDependency</string>
<string>100041.IBPluginDependency</string>
<string>100043.IBPluginDependency</string>
<string>100055.IBPluginDependency</string>
<string>5.IBPluginDependency</string>
<string>5.IBWindowTemplateEditedContentRect</string>
<string>6.IBPluginDependency</string>
@ -421,6 +444,7 @@
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<string>{{127, 736}, {299, 113}}</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
</object>
@ -437,7 +461,7 @@
<reference key="dict.values" ref="0"/>
</object>
<nil key="sourceID"/>
<int key="maxID">100054</int>
<int key="maxID">100056</int>
</object>
<object class="IBClassDescriber" key="IBDocument.Classes">
<object class="NSMutableArray" key="referencedPartialClassDescriptions">

13
Mac/MimeType.h Normal file
View file

@ -0,0 +1,13 @@
//
// MimeType.h
// Tentia
//
// Created by Jeena on 23/11/2012.
//
//
#import <Foundation/Foundation.h>
@interface MimeType : NSObject
+(NSString *)mimeTypeForFileAtPath:(NSString *)path error:(NSError **)err;
@end

27
Mac/MimeType.m Normal file
View file

@ -0,0 +1,27 @@
//
// MimeType.m
// Tentia
//
// Created by Jeena on 23/11/2012.
//
//
#import "MimeType.h"
@implementation MimeType
+(NSString *)mimeTypeForFileAtPath:(NSString *)path error:(NSError **)err {
NSString *uti, *mimeType = nil;
if (!(uti = [[NSWorkspace sharedWorkspace] typeOfFile:path error:err]))
return nil;
if (err)
*err = nil;
if ((mimeType = (NSString *)UTTypeCopyPreferredTagWithClass((CFStringRef)uti, kUTTagClassMIMEType)))
mimeType = NSMakeCollectable(mimeType);
return mimeType;
}
@end

46
Mac/NSData+Base64.h Normal file
View file

@ -0,0 +1,46 @@
//
// Created by Cédric Luthi on 2012-02-24.
// Copyright (c) 2012 Cédric Luthi. All rights reserved.
//
#import "NSData+Base64.h"
#ifndef __has_feature
#define __has_feature(x) 0
#endif
@implementation NSData (Base64)
+ (id) dataWithBase64Encoding_xcd:(NSString *)base64Encoding
{
if ([base64Encoding length] % 4 != 0)
return nil;
NSString *plist = [NSString stringWithFormat:@"<?xml version=\"1.0\" encoding=\"UTF-8\"?><plist version=\"1.0\"><data>%@</data></plist>", base64Encoding];
return [NSPropertyListSerialization propertyListWithData:[plist dataUsingEncoding:NSASCIIStringEncoding] options:0 format:NULL error:NULL];
}
- (NSString *) base64Encoding_xcd
{
NSData *plist = [NSPropertyListSerialization dataWithPropertyList:self format:NSPropertyListXMLFormat_v1_0 options:0 error:NULL];
NSRange fullRange = NSMakeRange(0, [plist length]);
NSRange startRange = [plist rangeOfData:[@"<data>" dataUsingEncoding:NSASCIIStringEncoding] options:0 range:fullRange];
NSRange endRange = [plist rangeOfData:[@"</data>" dataUsingEncoding:NSASCIIStringEncoding] options:NSDataSearchBackwards range:fullRange];
if (startRange.location == NSNotFound || endRange.location == NSNotFound)
return nil;
NSUInteger base64Location = startRange.location + startRange.length;
NSUInteger base64length = endRange.location - base64Location;
NSData *base64Data = [NSData dataWithBytesNoCopy:(void *)((uintptr_t)base64Location + (uintptr_t)[plist bytes]) length:base64length freeWhenDone:NO];
NSString *base64Encoding = [[NSString alloc] initWithData:base64Data encoding:NSASCIIStringEncoding];
base64Encoding = [base64Encoding stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
base64Encoding = [base64Encoding stringByReplacingOccurrencesOfString:@"\n" withString:@""];
#if __has_feature(objc_arc)
return base64Encoding;
#else
return [base64Encoding autorelease];
#endif
}
@end

13
Mac/NSData+Base64.m Normal file
View file

@ -0,0 +1,13 @@
//
// Created by Cédric Luthi on 2012-02-24.
// Copyright (c) 2012 Cédric Luthi. All rights reserved.
//
#import <Foundation/Foundation.h>
@interface NSData (Base64)
+ (id) dataWithBase64Encoding_xcd:(NSString *)base64String;
- (NSString *) base64Encoding_xcd;
@end

View file

@ -11,7 +11,7 @@
#import <CoreLocation/CoreLocation.h>
@interface NewMessageWindow : NSDocument <NSTextFieldDelegate, CLLocationManagerDelegate>
@interface NewMessageWindow : NSDocument <NSTextFieldDelegate, CLLocationManagerDelegate, NSOpenSavePanelDelegate>
{
IBOutlet NSTextField *textField;
IBOutlet NSTextField *counter;
@ -22,6 +22,7 @@
NSMenuItem *addImage;
CLLocationManager *locationManager;
CLLocation *currentLocation;
NSString *imageFilePath;
}
@property (nonatomic, retain) IBOutlet NSTextField *textField;
@ -30,6 +31,7 @@
@property (assign) IBOutlet NSButton *addMenuButton;
@property (retain, nonatomic) CLLocationManager *locationManager;
@property (retain, nonatomic) CLLocation *currentLocation;
@property (retain, nonatomic) NSString *imageFilePath;
- (IBAction)sendTweet:(NSControl *)control;
- (void)inReplyTo:(NSString *)userName statusId:(NSString *)statusId withString:(NSString *)string;

View file

@ -22,12 +22,14 @@
@synthesize addMenuButton;
@synthesize textField, counter;
@synthesize locationManager, currentLocation;
@synthesize imageFilePath;
- (void)dealloc
{
[locationManager stopUpdatingLocation];
[locationManager release];
[currentLocation release];
[imageFilePath release];
[super dealloc];
}
@ -139,10 +141,6 @@
}
}
- (IBAction)addImage:(id)sender
{
}
- (IBAction)openAddMenu:(id)sender
{
NSRect frame = [(NSButton *)sender frame];
@ -203,6 +201,7 @@
post.inReplyTostatusId = inReplyTostatusId;
post.inReplyToEntity = inReplyToEntity;
post.location = self.currentLocation;
post.imageFilePath = self.imageFilePath;
[[NSNotificationCenter defaultCenter] postNotificationName:@"sendTweet" object:post];
[self close];
} else {
@ -246,4 +245,66 @@
return retval;
}
#pragma mark Add images
- (IBAction)addImage:(id)sender
{
NSMenuItem *menuItem = (NSMenuItem *)sender;
if (!self.imageFilePath)
{
[menuItem setTitle:@"Remove image"];
NSOpenPanel* openDlg = [NSOpenPanel openPanel];
[openDlg setPrompt:@"Select"];
[openDlg setDelegate:self];
// Enable the selection of files in the dialog.
[openDlg setCanChooseFiles:YES];
// Enable the selection of directories in the dialog.
[openDlg setCanChooseDirectories:NO];
// Display the dialog. If the OK button was pressed,
// process the files.
if ( [openDlg runModalForDirectory:nil file:nil] == NSOKButton )
{
// Get an array containing the full filenames of all
// files and directories selected.
NSArray* files = [openDlg filenames];
// Loop through all the files and process them.
for( int i = 0; i < [files count]; i++ )
{
self.imageFilePath = [files objectAtIndex:i];
}
}
}
else
{
self.imageFilePath = nil;
[menuItem setTitle:@"Add image"];
}
}
-(BOOL)panel:(id)sender shouldShowFilename:(NSString *)filename
{
NSString* ext = [filename pathExtension];
if (ext == @"" || ext == @"/" || ext == nil || ext == NULL || [ext length] < 1) {
return YES;
}
NSEnumerator* tagEnumerator = [[NSArray arrayWithObjects:@"png", @"jpg", @"gif", @"jpeg", nil] objectEnumerator];
NSString* allowedExt;
while ((allowedExt = [tagEnumerator nextObject]))
{
if ([ext caseInsensitiveCompare:allowedExt] == NSOrderedSame)
{
return YES;
}
}
return NO;
}
@end

View file

@ -14,13 +14,13 @@
NSString *inReplyTostatusId;
NSString *inReplyToEntity;
CLLocation *location;
NSImage *image;
NSString *imageFilePath;
}
@property (nonatomic, retain) NSString *text;
@property (nonatomic, retain) NSString *inReplyTostatusId;
@property (nonatomic, retain) NSString *inReplyToEntity;
@property (nonatomic, retain) CLLocation *location;
@property (nonatomic, retain) NSImage *image;
@property (nonatomic, retain) NSString *imageFilePath;
@end

View file

@ -11,7 +11,7 @@
@implementation PostModel
@synthesize text, inReplyTostatusId, inReplyToEntity, location, image;
@synthesize text, inReplyTostatusId, inReplyToEntity, location, imageFilePath;
- (void)dealloc
{
@ -19,7 +19,7 @@
[inReplyTostatusId release];
[inReplyToEntity release];
[location release];
[image release];
[imageFilePath release];
[super dealloc];
}

View file

@ -17,6 +17,8 @@
1F618ECA12DB5E6100E500D9 /* PostModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F618EC912DB5E6100E500D9 /* PostModel.m */; };
1F70619F1178FBB300C85707 /* Carbon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1F70619E1178FBB300C85707 /* Carbon.framework */; };
1F77DB47118C5F1C007C7F1E /* Constants.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F77DB46118C5F1C007C7F1E /* Constants.m */; };
1F880B6B165EE0F60022A84D /* NSData+Base64.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F880B6A165EE0F60022A84D /* NSData+Base64.m */; };
1F880B6E165FE8890022A84D /* MimeType.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F880B6D165FE8890022A84D /* MimeType.m */; };
1FA09847144602530079E258 /* libicucore.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 1FA09846144602530079E258 /* libicucore.dylib */; };
1FC254A01427DFAD0035D84B /* AccessToken.m in Sources */ = {isa = PBXBuildFile; fileRef = 1FC2549B1427D9930035D84B /* AccessToken.m */; };
1FDEF722164EFE9100F927F3 /* Growl.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1FDEF721164EFE9100F927F3 /* Growl.framework */; };
@ -65,6 +67,10 @@
1F70619E1178FBB300C85707 /* Carbon.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Carbon.framework; path = System/Library/Frameworks/Carbon.framework; sourceTree = SDKROOT; };
1F77DB45118C5F1C007C7F1E /* Constants.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = Constants.h; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; };
1F77DB46118C5F1C007C7F1E /* Constants.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = Constants.m; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.objc; };
1F880B69165EE0F60022A84D /* NSData+Base64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSData+Base64.h"; sourceTree = "<group>"; };
1F880B6A165EE0F60022A84D /* NSData+Base64.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSData+Base64.m"; sourceTree = "<group>"; };
1F880B6C165FE8890022A84D /* MimeType.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MimeType.h; sourceTree = "<group>"; };
1F880B6D165FE8890022A84D /* MimeType.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MimeType.m; sourceTree = "<group>"; };
1FA09846144602530079E258 /* libicucore.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libicucore.dylib; path = usr/lib/libicucore.dylib; sourceTree = SDKROOT; };
1FC2549A1427D9930035D84B /* AccessToken.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = AccessToken.h; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; };
1FC2549B1427D9930035D84B /* AccessToken.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = AccessToken.m; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.objc; };
@ -169,6 +175,10 @@
1F618EC912DB5E6100E500D9 /* PostModel.m */,
1FC2549A1427D9930035D84B /* AccessToken.h */,
1FC2549B1427D9930035D84B /* AccessToken.m */,
1F880B69165EE0F60022A84D /* NSData+Base64.h */,
1F880B6A165EE0F60022A84D /* NSData+Base64.m */,
1F880B6C165FE8890022A84D /* MimeType.h */,
1F880B6D165FE8890022A84D /* MimeType.m */,
);
name = Classes;
sourceTree = "<group>";
@ -286,6 +296,8 @@
1FFA36D81177D879006C8562 /* ViewDelegate.m in Sources */,
1F77DB47118C5F1C007C7F1E /* Constants.m in Sources */,
1F618ECA12DB5E6100E500D9 /* PostModel.m in Sources */,
1F880B6B165EE0F60022A84D /* NSData+Base64.m in Sources */,
1F880B6E165FE8890022A84D /* MimeType.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};

View file

@ -27,6 +27,7 @@
<p>Implemented remove deleted posts</p>
<p>Added a JS and CSS Plugin API</p>
<p>Implemented adding location to post</p>
<p>Implemented blue right border if you're mentioned in a post</p>
<p>Bugfixes</p>
<hr />