From 45be91f33f0a4972da7a26b3cea2884563392170 Mon Sep 17 00:00:00 2001 From: Jeena Paradies Date: Fri, 2 Nov 2012 02:15:17 +0100 Subject: [PATCH] fixed #1 #2 --- Controller.m | 2 +- Core.js | 226 ++--------------------------- English.lproj/MainMenu.xib | 52 +++---- English.lproj/NewMessageWindow.xib | 1 - NewMessageWindow.h | 2 +- NewMessageWindow.m | 34 ++++- OauthImplementation.js | 4 +- Tentia.xcodeproj/project.pbxproj | 4 - ViewDelegate.m | 16 ++ hmac-helper.js | 10 ++ 10 files changed, 97 insertions(+), 254 deletions(-) diff --git a/Controller.m b/Controller.m index 9649b2b..b04af1b 100644 --- a/Controller.m +++ b/Controller.m @@ -233,7 +233,7 @@ - (void)unreadMentions:(NSInteger)count { if (![mentionsViewWindow isVisible] && count > 0) { - [timelineViewWindow setTitle:[NSString stringWithFormat:@"Tentia (@%i)", count]]; + [timelineViewWindow setTitle:[NSString stringWithFormat:@"Tentia (^%i)", count]]; [[[NSApplication sharedApplication] dockTile] setBadgeLabel:[NSString stringWithFormat:@"%i", count]]; } else { [timelineViewWindow setTitle:[NSString stringWithFormat:@"Tentia"]]; diff --git a/Core.js b/Core.js index de905f4..f308964 100644 --- a/Core.js +++ b/Core.js @@ -22,16 +22,11 @@ function Core(action) { this.cache = {}; this.is_not_init = false; -/* - if (action == "home_timeline") { - this.usernames = []; - this.getUsernames("friends"); - this.getUsernames("followers"); - } -*/ + var _this = this; + setInterval(function() { _this.getNewData() }, this.timeout); } -Core.prototype.newStatus = function(status, supress_new_with_timeout) { +Core.prototype.newStatus = function(status) { if(status != null && status.length > 0) { this.since_id = status[0]["id"]; for(var i = status.length-1, c=0; i>=c; --i) { @@ -46,10 +41,6 @@ Core.prototype.newStatus = function(status, supress_new_with_timeout) { } } - if(!supress_new_with_timeout) { - var _this = this; - setTimeout(function() { _this.getNewData() }, this.timeout); - } if(this.action == "mentions" && this.is_not_init) { this.unread_mentions += status.length; controller.unreadMentions_(this.unread_mentions); @@ -231,11 +222,10 @@ Core.prototype.getTemplate = function() { return jQuery.extend(true, {}, this.template); } -Core.prototype.getNewData = function(supress_new_with_timeout) { +Core.prototype.getNewData = function() { var those = this; - var url = URI(controller.stringForKey_("api_root")); - url.path(url.directory() + "posts"); + var url = URI(mkApiRootPath("/posts")); url.addSearch("post_types", "https://tent.io/types/post/status/v0.1.0"); url.addSearch("limit", this.max_length); if(this.since_id) { @@ -258,7 +248,7 @@ Core.prototype.getNewData = function(supress_new_with_timeout) { throw e; } - those.newStatus(json, supress_new_with_timeout); + those.newStatus(json); } var data = null; @@ -266,24 +256,6 @@ Core.prototype.getNewData = function(supress_new_with_timeout) { if (controller.stringForKey_("user_access_token")) { getURL(url.toString(), http_method, callback, data); // FIXME: error callback } - - /* - $.ajax( - { beforeSend: function(xhr) { - xhr.setRequestHeader("Authorization", ); - }, - url: url + url2, - dataType: 'json', - success: function(data) { - _this.newStatus(data, supress_new_with_timeout); - }, - error:function (xhr, ajaxOptions, thrownError){ - alert(xhr.status); - alert(thrownError); - setTimeout(function() { _this.getNewData(supress_new_with_timeout) }, this.timeout); - } - } - );*/ } @@ -291,7 +263,7 @@ Core.prototype.sendNewMessage = function(content, in_reply_to_status_id, in_repl var _this = this; - var url = URI(controller.stringForKey_("api_root") + "/posts"); + var url = URI(mkApiRootPath("/posts")); var http_method = "POST"; var callback = function(data) { _this.getNewData(true); } @@ -315,185 +287,11 @@ Core.prototype.sendNewMessage = function(content, in_reply_to_status_id, in_repl getURL(url.toString(), http_method, callback, JSON.stringify(data)); // FIXME: error callback } -/* - -Core.prototype.retweet = function(status_id, item) { - var url = API_PATH + "statuses/retweet/" + status_id + ".json"; - var _this = this; - - var message = { method:"POST" , action:url }; - - OAuth.completeRequest(message, - { consumerKey : OAUTH_CONSUMER_KEY - , consumerSecret: OAUTH_CONSUMER_SECRET - , token : controller.accessToken.accessToken() - , tokenSecret : controller.accessToken.secret() - }); - - $.ajax({ - beforeSend: function(xhr) { - xhr.setRequestHeader("Authorization", OAuth.getAuthorizationHeader("", message.parameters)); - }, - url: url, - type: 'POST', - dataType: 'json', - success: function(data) { - item.parentNode.replaceChild(_this.getItem(data), item); - }, - error:function (xhr, ajaxOptions, thrownError) { - alert(xhr.status); - alert(thrownError); - } - }); -} - -Core.prototype.getUsernames = function(type, cursor) { - cursor = typeof cursor == "undefined" ? -1 : cursor; - - var url = API_PATH + type + "/ids.json"; - var _this = this; - var parameters = { stringify_ids: "true", cursor:cursor }; - - var message = { method:"GET" , action:url, parameters:parameters }; - - OAuth.completeRequest(message, - { consumerKey : OAUTH_CONSUMER_KEY - , consumerSecret: OAUTH_CONSUMER_SECRET - , token : controller.accessToken.accessToken() - , tokenSecret : controller.accessToken.secret() - }); - - $.ajax({ - beforeSend: function(xhr) { - xhr.setRequestHeader("Authorization", OAuth.getAuthorizationHeader("", message.parameters)); - }, - url: url + "?stringify_ids=true&cursor=" + cursor , - type: 'GET', - dataType: 'json', - success: function(data) { - for (var i=0; i < data.ids.length; i = i + 100) { - _this.getUsernamesFromIds(data.ids.slice(i, i + 100)); - } - if (data.next_cursor > 0) { - _this.getUsernames(type, data.next_cursor); - } - }, - error:function (xhr, ajaxOptions, thrownError) { - alert(xhr.status); - alert(thrownError); - } - }); -} - -Core.prototype.getUsernamesFromIds = function(ids) { - - var url = API_PATH + "users/lookup.json"; - var _this = this; - var parameters = { user_id:ids.join(",") }; - var message = { method:"GET" , action:url, parameters:parameters }; - - OAuth.completeRequest(message, - { consumerKey : OAUTH_CONSUMER_KEY - , consumerSecret: OAUTH_CONSUMER_SECRET - , token : controller.accessToken.accessToken() - , tokenSecret : controller.accessToken.secret() - }); - - $.ajax({ - beforeSend: function(xhr) { - xhr.setRequestHeader("Authorization", OAuth.getAuthorizationHeader("", message.parameters)); - }, - url: url + "?user_id=" + ids.join(","), - type: 'GET', - dataType: 'json', - success: function(data) { - for (var i=0; i < data.length; i++) { - _this.usernames.push(data[i].screen_name); - } - }, - error:function (xhr, ajaxOptions, thrownError) { - alert(xhr.status); - alert(thrownError); - } - }); -} - -Core.prototype.findUsernamesFor = function(query) { - var ret = []; - for (var i=0; i < this.usernames.length; i++) { - if(this.usernames[i].startsWith(query)) { - ret.push(this.usernames[i]); - } - } - return ret; -} -*/ /* Helper functions */ function replaceURLWithHTMLLinks(text, entities, message_node) { var exp = /(([^\^]https?|ftp|file):\/\/[-A-Z0-9+&@#\/%?=~_()|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/ig; return text.replace(exp, "$1"); - - /* - var urls = entities.urls; - - for(var i = 0; i" + replace + ""); - - var media = null; - - // add thumbnail - if(replace.startsWith("http://youtube.com/") || replace.startsWith("http://www.youtube.com/")) { - var v = getUrlVars(replace)["v"]; - if (v) { - media = { - type: "tentia_youtube", - url: original, - media_url: "http://img.youtube.com/vi/" + v + "/1.jpg" - } - } - - } else if (replace.startsWith("http://twitpic.com/")) { - media = { - type: "tentia_photo", - url: original, - media_url: "http://twitpic.com/show/mini/" + replace.substring("http://twitpic.com/".length) - } - - } else if (replace.startsWith("http://yfrog")) { - media = { - type: "tentia_photo", - url: original, - media_url: replace + ":small" - } - - } else if (replace.startsWith("http://instagr.am/p/") || replace.startsWith("http://instagram.com/p/")) { - media = { - type: "tentia_photo", - url: original, - media_url: replace + "media?size=t" - } - } - - if(media) { - if(entities.media) { - entities.media.push(media); - } else { - entities.media = [media]; - } - } - - } - - return text;*/ } function replaceUsernamesWithLinks(text, mentions) { @@ -505,9 +303,10 @@ function replaceUsernamesWithLinks(text, mentions) { } function replyTo(entity, status_id, mentions) { - var string = "^" + entity + " "; + var string = "^" + entity.replace("https://", "") + " "; for (var i = 0; i < mentions.length; i++) { - string += "^" + mentions[i].entity + " "; + var e = mentions[i].entity.replace("https://", ""); + if(string.indexOf(e) == -1) string += "^" + e + " "; } controller.openNewMessageWindowInReplyTo_statusId_withString_(entity, status_id, string); } @@ -575,11 +374,14 @@ function parseMentions(text, post_id, entity) { }) } - var res = text.match(/((\^https?):\/\/\S+)/ig); + var res = text.match(/(\^\S+)/ig); if (res) { for (var i = 0; i < res.length; i++) { var e = res[i].substring(1); + if (e.substring(0,7) != "http://" && e.substring(0,8) != "https://") { + e = "https://" + e; + } if (e != entity) { mentions.push({entity:e}); } diff --git a/English.lproj/MainMenu.xib b/English.lproj/MainMenu.xib index 747e36f..930c402 100644 --- a/English.lproj/MainMenu.xib +++ b/English.lproj/MainMenu.xib @@ -886,7 +886,7 @@ - + 256 YES @@ -916,6 +916,7 @@ {376, 581} + @@ -932,6 +933,8 @@ {376, 581} + + {{0, 0}, {2560, 1418}} {10000000000000, 10000000000000} @@ -1070,7 +1073,6 @@ {{391, 46}, {75, 32}} - _NS:9 YES @@ -1719,11 +1721,6 @@ - - 73 - - - 79 @@ -2227,16 +2224,6 @@ - - 544 - - - - - 551 - - - 559 @@ -2364,6 +2351,21 @@ + + 73 + + + + + 551 + + + + + 544 + + + @@ -2611,7 +2613,7 @@ - 622 + 627 @@ -2625,15 +2627,11 @@ YES login: logout: - openNewMessageWindow: - sendTweet: YES id id - id - id @@ -2642,8 +2640,6 @@ YES login: logout: - openNewMessageWindow: - sendTweet: YES @@ -2655,14 +2651,6 @@ logout: id - - openNewMessageWindow: - id - - - sendTweet: - id - diff --git a/English.lproj/NewMessageWindow.xib b/English.lproj/NewMessageWindow.xib index b8a4397..273c84f 100644 --- a/English.lproj/NewMessageWindow.xib +++ b/English.lproj/NewMessageWindow.xib @@ -95,7 +95,6 @@ {{257, 2}, {38, 17}} - YES 68157504 diff --git a/NewMessageWindow.h b/NewMessageWindow.h index 2513461..7d993e6 100644 --- a/NewMessageWindow.h +++ b/NewMessageWindow.h @@ -10,7 +10,7 @@ #import -@interface NewMessageWindow : NSDocument +@interface NewMessageWindow : NSDocument { IBOutlet NSTextField *textField; IBOutlet NSTextField *counter; diff --git a/NewMessageWindow.m b/NewMessageWindow.m index c387ba2..0fa4fa8 100644 --- a/NewMessageWindow.m +++ b/NewMessageWindow.m @@ -10,6 +10,10 @@ #import "Constants.h" #import "TweetModel.h" +@interface NewMessageWindow (private) +- (BOOL)isCommandEnterEvent:(NSEvent *)e; +@end + @implementation NewMessageWindow @synthesize textField, counter; @@ -43,6 +47,7 @@ { [super windowControllerDidLoadNib:aController]; // Add any code here that needs to be executed once the windowController has loaded the document's window. + } - (NSData *)dataOfType:(NSString *)typeName error:(NSError **)outError @@ -85,12 +90,16 @@ [inReplyToEntity release]; inReplyToEntity = entity; [inReplyToEntity retain]; + + [self controlTextDidChange:nil]; } - (void)withString:(NSString *)aString { [textField setStringValue:aString]; NSRange range = {[[textField stringValue] length] , 0}; - [[textField currentEditor] setSelectedRange:range]; + [[textField currentEditor] setSelectedRange:range]; + + [self controlTextDidChange:nil]; } -(void)controlTextDidChange:(NSNotification *)aNotification { @@ -120,4 +129,27 @@ } +- (BOOL)isCommandEnterEvent:(NSEvent *)e { + NSUInteger flags = (e.modifierFlags & NSDeviceIndependentModifierFlagsMask); + BOOL isCommand = (flags & NSCommandKeyMask) == NSCommandKeyMask; + BOOL isEnter = (e.keyCode == 0x24); // VK_RETURN + return (isCommand && isEnter); +} + +- (BOOL)control:(NSControl *)control textView:(NSTextView *)fieldEditor doCommandBySelector:(SEL)commandSelector +{ + BOOL retval = NO; + + if (commandSelector == @selector(insertNewline:)) { + retval = YES; // causes Apple to NOT fire the default enter action + textField.stringValue = [NSString stringWithFormat:@"%@\n", textField.stringValue]; + } + + if (commandSelector == @selector(noop:)) { + retval = YES; + [self sendTweet:control]; + } + + return retval; +} @end diff --git a/OauthImplementation.js b/OauthImplementation.js index 06e6880..09e40bb 100644 --- a/OauthImplementation.js +++ b/OauthImplementation.js @@ -66,7 +66,7 @@ OauthImplementation.prototype.register = function (url) { var data = JSON.parse(resp.responseText); those.authRequest(data); } - getURL(those.apiRoot() + "/apps", "POST", callback, JSON.stringify(those.app_info)); + getURL(mkApiRootPath("/apps"), "POST", callback, JSON.stringify(those.app_info)); }); } @@ -98,7 +98,7 @@ OauthImplementation.prototype.requestAccessToken = function(responseBody) { var urlVars = getUrlVars(responseBody); if(this.state && this.state != "" && urlVars["state"] == this.state) { - var url = this.apiRoot() + "/apps/" + this.register_data["id"] + "/authorizations"; + var url = mkApiRootPath("/apps/") + this.register_data["id"] + "/authorizations"; var requestBody = JSON.stringify({ 'code' : urlVars["code"], diff --git a/Tentia.xcodeproj/project.pbxproj b/Tentia.xcodeproj/project.pbxproj index e1af4ea..2c2dff3 100644 --- a/Tentia.xcodeproj/project.pbxproj +++ b/Tentia.xcodeproj/project.pbxproj @@ -11,7 +11,6 @@ 1DDD582D0DA1D0D100B32029 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 1DDD582A0DA1D0D100B32029 /* MainMenu.xib */; }; 1F122D49118E1DE100E83B77 /* Icon.icns in Resources */ = {isa = PBXBuildFile; fileRef = 1F122D48118E1DE100E83B77 /* Icon.icns */; }; 1F1990C6117BCA960049BEA7 /* ApplicationServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1F1990C5117BCA960049BEA7 /* ApplicationServices.framework */; }; - 1F245D6F1632AEFE00E4469A /* jso.js in Sources */ = {isa = PBXBuildFile; fileRef = 1F245D6E1632AEFE00E4469A /* jso.js */; }; 1F2746FC12D9057600339B4F /* dsa_pub.pem in Resources */ = {isa = PBXBuildFile; fileRef = 1FE2FCA6117A8952000504B0 /* dsa_pub.pem */; }; 1F4673FE1180F7EA006CC37C /* Core.js in Resources */ = {isa = PBXBuildFile; fileRef = 1F4673E61180F654006CC37C /* Core.js */; }; 1F4674081180F7EE006CC37C /* jQuery.js in Resources */ = {isa = PBXBuildFile; fileRef = 1F4673E21180F519006CC37C /* jQuery.js */; }; @@ -75,7 +74,6 @@ 1F1990C5117BCA960049BEA7 /* ApplicationServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ApplicationServices.framework; path = System/Library/Frameworks/ApplicationServices.framework; sourceTree = SDKROOT; }; 1F1990DF117BD2250049BEA7 /* Appcast.xml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = Appcast.xml; sourceTree = ""; }; 1F1990E1117BD2650049BEA7 /* ReleaseNotes.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; lineEnding = 0; path = ReleaseNotes.html; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.html; }; - 1F245D6E1632AEFE00E4469A /* jso.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = jso.js; sourceTree = ""; }; 1F36440E118CC173008198EF /* OAuthConsumer.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = OAuthConsumer.framework; sourceTree = ""; }; 1F4673E21180F519006CC37C /* jQuery.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = jQuery.js; sourceTree = ""; }; 1F4673E41180F590006CC37C /* jQuery-Plugins.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = "jQuery-Plugins.js"; sourceTree = ""; }; @@ -174,7 +172,6 @@ 1F9D655D163B63E300B7282B /* URI.min.js */, 1F9816C6163915A100AFD4EE /* enc-base64-min.js */, 1F9816C7163915A100AFD4EE /* hmac-sha256.js */, - 1F245D6E1632AEFE00E4469A /* jso.js */, 1F4673E61180F654006CC37C /* Core.js */, 1FC254911427ADF90035D84B /* OauthImplementation.js */, 1FC2549D1427DC2B0035D84B /* Constants.js */, @@ -355,7 +352,6 @@ 1FFA36D81177D879006C8562 /* ViewDelegate.m in Sources */, 1F77DB47118C5F1C007C7F1E /* Constants.m in Sources */, 1F618ECA12DB5E6100E500D9 /* TweetModel.m in Sources */, - 1F245D6F1632AEFE00E4469A /* jso.js in Sources */, 1F9816C8163915A100AFD4EE /* enc-base64-min.js in Sources */, 1F9816C9163915A100AFD4EE /* hmac-sha256.js in Sources */, 1F9D655E163B63E300B7282B /* URI.min.js in Sources */, diff --git a/ViewDelegate.m b/ViewDelegate.m index f3802f6..ad041fb 100644 --- a/ViewDelegate.m +++ b/ViewDelegate.m @@ -65,4 +65,20 @@ } } +- (NSArray *)webView:(WebView *)sender contextMenuItemsForElement:(NSDictionary *)element defaultMenuItems:(NSArray *)defaultMenuItems { + for (NSMenuItem*item in defaultMenuItems) { + if ([[item title] isEqualToString:@"Reload"]) { + [item setAction:@selector(reload:)]; + [item setTarget:self]; + } + } + + return defaultMenuItems; +} + +- (void)reload:(id)sender { + [timelineView stringByEvaluatingJavaScriptFromString:@"tentia_instance.getNewData();"]; + [mentionsView stringByEvaluatingJavaScriptFromString:@"tentia_instance.getNewData();"]; +} + @end diff --git a/hmac-helper.js b/hmac-helper.js index 53c4f1d..f3ad041 100644 --- a/hmac-helper.js +++ b/hmac-helper.js @@ -104,6 +104,16 @@ function findProfileURL(entity, callback) { }); } +function mkApiRootPath(path) { + var api_root = controller.stringForKey_("api_root"); + if((api_root.substring(api_root.length - 1, api_root.length) != "/") && (path.substring(0, 1) != "/")) { + api_root += "/"; + } else if((api_root.substring(api_root.length - 1, api_root.length) == "/") && (path.substring(0, 1) == "/")) { + api_root = api_root.substring(0, api_root.length -1); + } + return api_root + path; +} + function debug(string) { if (typeof string == "Object") { string = JSON.stirngify(string);