Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

initial re-commit

  • Loading branch information...
commit 9b4fa824a6b37110123d6193fbbe00990d2e9056 1 parent 0152395
@rmxdave rmxdave authored
Showing with 7,951 additions and 2,373 deletions.
  1. +9 −8 README.txt
  2. +35 −0 app/assistants/about-assistant.js
  3. +215 −5 app/assistants/app-assistant.js
  4. +108 −0 app/assistants/dashboard-assistant.js
  5. +85 −61 app/assistants/finishAuth-assistant.js
  6. +43 −67 app/assistants/launch-assistant.js
  7. +835 −1,251 app/assistants/main-assistant.js
  8. +190 −176 app/assistants/oauth-assistant.js
  9. +42 −0 app/assistants/pictureView-assistant.js
  10. +168 −0 app/assistants/preferences-assistant.js
  11. +517 −0 app/assistants/profile-assistant.js
  12. +1 −3 app/assistants/stage-assistant.js
  13. +303 −0 app/assistants/status-assistant.js
  14. +72 −0 app/assistants/stream-assistant.js
  15. +303 −0 app/assistants/toasters/compose.js
  16. +27 −0 app/assistants/toasters/confirm.js
  17. +48 −0 app/assistants/toasters/convo.js
  18. +43 −0 app/assistants/toasters/lookup.js
  19. +24 −0 app/assistants/toasters/profile.js
  20. +39 −0 app/assistants/toasters/retweet.js
  21. +43 −0 app/assistants/toasters/search.js
  22. +35 −0 app/assistants/toasters/status-list.js
  23. +358 −0 app/assistants/toasters/tweet.js
  24. +39 −0 app/assistants/toasters/user-list.js
  25. +8 −9 app/config/config.js
  26. +206 −2 app/global/app-globals.js
  27. +47 −0 app/helpers/bitly.js
  28. +136 −0 app/helpers/tweet.js
  29. +354 −0 app/helpers/twitter.js
  30. +41 −0 app/models/account.js
  31. +97 −0 app/models/asyncWrappers.js
  32. +55 −0 app/models/local.js
  33. +1 −0  app/models/metrix.js
  34. +615 −0 app/models/metrixCore.js
  35. +42 −42 app/models/panel.js
  36. +82 −0 app/models/toaster-chain.js
  37. +89 −0 app/models/toaster.js
  38. +18 −0 app/views/about/about-scene.html
  39. +1 −0  app/views/dashboard/dashboard-scene.html
  40. +16 −0 app/views/dashboard/item-info.html
  41. +40 −39 app/views/finishAuth/finishAuth-scene.html
  42. +3 −6 app/views/launch/launch-scene.html
  43. +29 −109 app/views/main/main-scene.html
  44. +1 −0  app/views/metrix/displayBulletin-dialog.html
  45. +9 −0 app/views/pictureView/pictureView-scene.html
  46. +6 −0 app/views/preferences/preferences-scene.html
  47. +8 −0 app/views/preferences/section.html
  48. +5 −0 app/views/preferences/select.html
  49. +8 −0 app/views/preferences/toggle.html
  50. +82 −0 app/views/profile/content.html
  51. +11 −0 app/views/profile/profile-scene.html
  52. +24 −0 app/views/status/status-scene.html
  53. +1 −0  app/views/stream/stream-scene.html
  54. +3 −0  app/views/templates/account-card.html
  55. +1 −0  app/views/templates/account-menu.html
  56. +4 −0 app/views/templates/list-follows.html
  57. +4 −0 app/views/templates/list-item.html
  58. +4 −1 app/views/templates/panel.html
  59. +32 −0 app/views/templates/panels/lists.html
  60. +22 −0 app/views/templates/panels/search.html
  61. +5 −3 app/views/templates/panels/timeline.html
  62. +3 −0  app/views/templates/search-list-item.html
  63. +18 −0 app/views/templates/toasters/compose.html
  64. +9 −0 app/views/templates/toasters/confirm.html
  65. +7 −0 app/views/templates/toasters/convo.html
  66. +13 −0 app/views/templates/toasters/lookup.html
  67. +71 −0 app/views/templates/toasters/profile.html
  68. +9 −0 app/views/templates/toasters/retweet.html
  69. +7 −0 app/views/templates/toasters/status-list.html
  70. +16 −0 app/views/templates/toasters/tweet.html
  71. +18 −0 app/views/templates/tweets/convo-item.html
  72. +1 −1  app/views/templates/tweets/convo.html
  73. +16 −17 app/views/templates/tweets/details.html
  74. +12 −16 app/views/templates/tweets/item.html
  75. +9 −15 app/views/templates/tweets/search.html
  76. +10 −0 app/views/templates/user-item.html
  77. +10 −4 appinfo.json
  78. BIN  dash-icon.png
  79. +1 −1  framework_config.json
  80. BIN  icon128.png
  81. BIN  icon24.png
  82. BIN  icon256.png
  83. BIN  icon48.png
  84. BIN  icon64.png
  85. BIN  images/Metrix/Thumbs.db
  86. BIN  images/Metrix/header-button-inverse.png
  87. BIN  images/Metrix/header-button.png
  88. BIN  images/Metrix/menu-icon-back-bnk.png
  89. BIN  images/Metrix/menu-icon-back-dwn.png
  90. BIN  images/Metrix/menu-icon-back-upp.png
  91. BIN  images/Metrix/menu-icon-forward-bnk.png
  92. BIN  images/Metrix/menu-icon-forward-dwn.png
  93. BIN  images/Metrix/menu-icon-forward-upp.png
  94. BIN  images/low/Untitled-2.png
  95. BIN  images/low/avatar-shadow.png
  96. BIN  images/low/backgrounds/bg.png
  97. BIN  images/low/backgrounds/fabric.png
  98. BIN  images/low/backgrounds/texture1.png
  99. BIN  images/low/buttons/negative-tapped.png
  100. BIN  images/low/buttons/negative.png
  101. BIN  images/low/buttons/neutral-tapped.png
  102. BIN  images/low/buttons/neutral.png
  103. BIN  images/low/buttons/positive-tapped.png
  104. BIN  images/low/buttons/positive.png
  105. BIN  images/low/buttons/signin-tapped.png
  106. BIN  images/low/buttons/signin.png
  107. BIN  images/low/buttons/submit-tapped.png
  108. BIN  images/low/buttons/submit.png
  109. BIN  images/low/compose-bg.png
  110. BIN  images/low/compose-opts-bg.png
  111. BIN  images/low/dialogbg.png
  112. BIN  images/low/divider-bg.png
  113. BIN  images/low/failwhale.png
  114. BIN  images/low/header-bar.png
  115. BIN  images/low/header-bg.png
  116. BIN  images/low/icons/camera.png
  117. BIN  images/low/icons/cancel.png
  118. BIN  images/low/icons/compose.png
  119. BIN  images/low/icons/confirm.png
  120. BIN  images/low/icons/convo.png
  121. BIN  images/low/icons/delete.png
  122. BIN  images/low/icons/dm.png
  123. BIN  images/low/icons/edit.png
  124. BIN  images/low/icons/favorite-active.png
  125. BIN  images/low/icons/favorite.png
  126. BIN  images/low/icons/geotag-active.png
  127. BIN  images/low/icons/geotag.png
  128. BIN  images/low/icons/link.png
  129. BIN  images/low/icons/lists.png
  130. BIN  images/low/icons/mentions.png
  131. BIN  images/low/icons/messages.png
  132. BIN  images/low/icons/new-card.png
  133. BIN  images/low/icons/opts.png
  134. BIN  images/low/icons/profile-favorite-tapped.png
  135. BIN  images/low/icons/profile-favorite.png
  136. BIN  images/low/icons/profile-history-tapped.png
  137. BIN  images/low/icons/profile-history.png
  138. BIN  images/low/icons/profile-info-tapped.png
  139. BIN  images/low/icons/profile-info.png
  140. BIN  images/low/icons/profile-mentions-tapped.png
  141. BIN  images/low/icons/profile-mentions.png
  142. BIN  images/low/icons/refresh.png
  143. BIN  images/low/icons/reply.png
  144. BIN  images/low/icons/retweet.png
  145. BIN  images/low/icons/search-button.png
  146. BIN  images/low/icons/search.png
  147. BIN  images/low/icons/tweets.png
  148. BIN  images/low/icons/user-search.png
  149. BIN  images/low/icons/verified.png
  150. BIN  images/low/img-load.gif
  151. BIN  images/low/indicator.png
  152. BIN  images/low/list-card.png
  153. BIN  images/low/list-spacer.png
  154. BIN  images/low/load-fade.png
  155. BIN  images/low/loading-bg.png
  156. BIN  images/low/loading.gif
  157. BIN  images/low/nav-bar.png
  158. BIN  images/low/nav-icon-border.png
  159. BIN  images/low/new-content.png
  160. BIN  images/low/photo-bg.png
  161. BIN  images/low/photobg.png
  162. BIN  images/low/profile-opts-tapped.png
  163. BIN  images/low/profile-opts.png
  164. BIN  images/low/retweets-card.png
  165. BIN  images/low/rt-button.png
  166. BIN  images/low/rt-icon.png
  167. BIN  images/low/scene-top.png
  168. BIN  images/low/search-box.png
  169. BIN  images/low/search-card.png
  170. BIN  images/low/search-icon.png
  171. BIN  images/low/splash-logo.png
  172. BIN  images/low/textarea-border.png
  173. BIN  images/low/themes/ash/bg.png
  174. BIN  images/low/themes/ash/compose-bg.png
  175. BIN  images/low/themes/ash/header-bar.png
  176. BIN  images/low/themes/ash/indicator.png
  177. BIN  images/low/themes/ash/nav-bar.png
  178. BIN  images/low/themes/ash/toaster-bg.png
  179. BIN  images/low/themes/pure/bg.png
  180. BIN  images/low/themes/sunnyvale/bg.png
  181. BIN  images/low/themes/sunnyvale/header-bar.png
  182. BIN  images/low/themes/sunnyvale/indicator.png
  183. BIN  images/low/themes/sunnyvale/nav-bar.png
  184. BIN  images/low/themes/sunnyvale/nav-icon-border.png
  185. BIN  images/low/themes/sunnyvale/toaster-bg.png
  186. BIN  images/low/title-bg.png
  187. BIN  images/low/toaster-bg.png
  188. BIN  images/low/toaster-controls.png
  189. BIN  images/low/tweet-border-bottom.png
  190. BIN  images/low/tweet-border-top.png
  191. BIN  images/low/tweet-border.png
  192. BIN  images/low/tweet-highlight-bottom.png
  193. BIN  images/low/tweet-highlight.png
  194. BIN  images/low/user-card.png
  195. BIN  images/trans13.png
  196. BIN  images/trans9.png
  197. +12 −3 index.html
  198. +9 −0 lib/Ajax.js
  199. +68 −0 lib/Date.js
  200. +124 −153 lib/OAuth/OAuth.js
  201. +561 −0 lib/OAuth/OAuth.js.bak
  202. +30 −0 lib/String.js
  203. +75 −32 sources.json
  204. BIN  splash-bg.png
  205. BIN  splash-icon.png
  206. +96 −0 stylesheets/ash.css
  207. +848 −349 stylesheets/phnx.css
  208. +93 −0 stylesheets/rebirth.css
  209. +113 −0 stylesheets/sunnyvale.css
View
17 README.txt
@@ -1,17 +1,18 @@
-=============================================
- phnx - a twitter app
-=============================================
+============================================
+ phnx - a twitter app
+============================================
Author: David Strack
Twitter: @rmxdave
-Email: david@davidstrack.com
-Web: http://prettyappmachine.com
+Email: davidstrack@gmail.com
+Web: http://davidstrack.com
+License:
You may not reproduce any part of this application without written permission from the author.
-Viewing source code for educational purposes is permitted - as long as nothing is copied for use in
-another application.
+Viewing or modifying source code for personal or educational purposes is permitted
+ - but you may NOT copy, distribute, or reproduce any portion of this application.
Before you steal this app, remember that you are hurting a young developer and his family,
not a large software company.
-Copyright 2010 - 2011 David Strack (D.B.A. Pretty App Machine)
+Copyright 2010 - 2011 David Strack
View
35 app/assistants/about-assistant.js
@@ -0,0 +1,35 @@
+function AboutAssistant(){}
+
+AboutAssistant.prototype = {
+ setup: function() {
+ var appMenu = [
+ Mojo.Menu.editItem,
+ {
+ label: 'Contact Support',
+ command: 'cmdSupport'
+ }
+ ];
+
+ this.controller.setupWidget(Mojo.Menu.appMenu, {omitDefaultItems: true}, {visible: true, items: appMenu});
+ this.controller.get('version').update(Mojo.appInfo.version);
+
+ this.controller.listen('head-honcho', Mojo.Event.tap, this.awesomeSauce.bind(this));
+ this.controller.listen('series-of-tubes', Mojo.Event.tap, this.coolio.bind(this));
+ },
+ awesomeSauce: function(event) {
+ var Twitter = new TwitterAPI(this.controller.stageController.user);
+ Twitter.getUser('rmxdave', function(r){
+ this.controller.stageController.pushScene({
+ name: 'profile',
+ disableSceneScroller: true
+ }, r.responseJSON);
+ }.bind(this));
+ },
+ coolio: function(event) {
+ global.openBrowser('http://phnxapp.com');
+ },
+ cleanup: function() {
+ this.controller.stopListening('head-honcho', Mojo.Event.tap, this.awesomeSauce);
+ this.controller.stopListening('series-of-tubes', Mojo.Event.tap, this.coolio);
+ }
+};
View
220 app/assistants/app-assistant.js
@@ -1,7 +1,217 @@
-function AppAssistant(){
-
-}
+function AppAssistant(){}
AppAssistant.prototype = {
-
-}
+ setup: function() {
+ var prefs = new LocalStorage();
+
+ if (prefs.read('sendAnalytics')) {
+ global.Metrix = new Metrix();
+ global.Metrix.postDeviceData();
+ }
+ },
+ handleLaunch: function(params) {
+ if (params.action === 'checkNotifications') {
+ var prefs = new LocalStorage();
+ var stageFocused = false; // temporaray
+ if (prefs.read('notifications') && !stageFocused) {
+ // Only background check notifications when enabled
+ // and when there are no stages present
+ this.checkNotifications();
+ }
+ else if (prefs.read('notifications') && stageFocused) {
+ global.setTimer(); // reset the timer anyway
+ }
+ }
+ else if (params.dockMode) {
+ // This is exhibition mode
+ }
+ else {
+ Mojo.Log.info('params: ' + params);
+ // Launch the app normally, load the default user if it exists.
+ this.launchMain();
+ // this.checkNotifications(); // for debugging
+ }
+ },
+ handleCommand: function(event) {
+ var stage = this.controller.getActiveStageController();
+ if (event.command === 'cmdPreferences') {
+ stage.pushScene('preferences');
+ }
+ else if (event.command === 'cmdAbout') {
+ stage.pushScene('about');
+ }
+ else if (event.command === 'cmdSupport') {
+ var service = new Mojo.Service.Request('palm://com.palm.applicationManager', {
+ method: 'open',
+ parameters: {
+ id: 'com.palm.app.email',
+ params: {
+ summary: "phnx support",
+ recipients: [{
+ value : 'support@phnxapp.com',
+ contactDisplay : 'support@phnxapp.com'
+ }]
+ }
+ }
+ });
+ }
+ },
+ launchMain: function() {
+ var prefs = new LocalStorage();
+ this.userCookie = new Mojo.Model.Cookie('phoenixFirstRun');
+
+ var user = {};
+
+ var defaultUser = prefs.read('defaultAccount');
+
+ // The app poops out on very first load if the Lawnchair store doesn't exist.
+ // Using a cookie to get around this...
+ if (typeof(this.userCookie.get()) !== "undefined") {
+ var am = new Account();
+ var accounts;
+ am.all(function(r){
+ accounts = r;
+ if (accounts.length > 0) {
+ Mojo.Log.info('Starting app, accounts exist');
+ // Push the main scene with the first account set as default.
+ if (defaultUser !== '0') {
+ for (var i=0; i < accounts.length; i++) {
+ if (accounts[i].id === defaultUser) {
+ user = accounts[i];
+ }
+ }
+ }
+ else {
+ // Use the first user if an explicit default has not been chosen
+ user = accounts[0];
+ }
+
+ Mojo.Log.info('User set as ' + user.screen_name);
+
+ var launchArgs = {
+ user: user,
+ users: accounts
+ };
+ prefs.write('defaultAccount', user.id);
+ var stageName = global.mainStage + user.key;
+
+ this.pushStage(stageName, launchArgs);
+ }
+ else {
+ this.launchNew();
+ }
+ }.bind(this));
+ }
+ else {
+ // This is the very first time the app is being launched,
+ // so just init the Lawnchair store
+
+ // Set the cookie, too.
+ this.userCookie.put({
+ run: true
+ });
+
+ var store = new Lawnchair('phnxAccounts');
+ this.launchNew();
+ }
+
+ },
+ launchNew: function() {
+ var launchArgs = {};
+ var stageName = global.authStage;
+ this.pushStage(stageName, launchArgs);
+ },
+ pushStage: function(stageName, launchArgs) {
+ var args = {
+ name: stageName,
+ lightweight: true
+ };
+
+ var pushMainScene = function(stageController) {
+ if (stageName !== global.authStage) {
+ global.stageActions(stageController);
+ }
+ stageController.pushScene('launch', launchArgs);
+ };
+
+ var userStage = this.controller.getStageProxy(stageName);
+ if (!userStage) {
+ this.controller.createStageWithCallback(args, pushMainScene, "card");
+ }
+ else {
+ userStage.activate();
+ }
+ },
+ checkNotifications: function() {
+ // Check for notifications
+ Mojo.Log.info('Checking notifications');
+ var prefs = new LocalStorage();
+
+ am = new Account();
+ am.all(function(r){
+
+ var callback = function(response, meta) {
+ if (response.responseJSON.length > 0) {
+ prefs.write(meta.user.id + '_' + meta.resource.name, response.responseJSON[0].id_str);
+ this.createDashboard(meta.resource, response.responseJSON, meta.user, r);
+ }
+ };
+
+ for (var i=0; i < r.length; i++) {
+ var user = r[i];
+ Mojo.Log.info('Checking ' + user.username + ' notifications');
+
+ // Name matches panel IDs in main-assistant
+ // Noun is used in dashboard title
+ var resources = [
+ {name: 'home', noun: 'Tweet', lastId: prefs.read(user.id + '_home'), enabled: prefs.read('notificationHome')},
+ {name: 'mentions', noun: 'Mention', lastId: prefs.read(user.id + '_mentions'), enabled: prefs.read('notificationMentions')},
+ {name: 'messages', noun: 'Direct Message', lastId: prefs.read(user.id + '_messages'), enabled: prefs.read('notificationMessages')}
+ ];
+
+ for (var j=0; j < resources.length; j++) {
+ var resource = resources[j];
+ if (resource.enabled && resource.lastId !== null) {
+ Mojo.Log.info('Checking ' + resource.name + ' last ID:' + resource.lastId);
+ var Twitter = new TwitterAPI(user);
+ Twitter.notificationCheck(resource, callback.bind(this), {"since_id": resource.lastId}, user);
+ }
+ }
+ }
+ }.bind(this));
+
+ // Reset the alarm
+ global.setTimer();
+ },
+ createDashboard: function(resource, items, account, accounts) {
+ var appController = Mojo.Controller.getAppController();
+ var dashboardStage = appController.getStageProxy(global.dashboardStage);
+
+ var userId;
+
+ if (items[0].user) {
+ userId = items[0].user.id_str;
+ }
+ else if (items[0].sender) {
+ userId = items[0].sender.id_str;
+ }
+
+ // Check if the user's stage is active & has scenes
+ var userStage = appController.getStageProxy(global.mainStage + userId);
+
+ if (userStage && userStage.isActiveAndHasScenes()) {
+ userStage.delegateToSceneAssistant('refreshPanelId', resource.name);
+ }
+ else {
+ if (dashboardStage) {
+ dashboardStage.delegateToSceneAssistant('update', items, resource, account, accounts);
+ }
+ else {
+ var pushDashboard = function(stageController){
+ stageController.pushScene('dashboard', items, resource, account, accounts);
+ };
+ appController.createStageWithCallback({name: global.dashboardStage, lightweight: true}, pushDashboard, 'dashboard');
+ }
+ }
+ }
+};
View
108 app/assistants/dashboard-assistant.js
@@ -0,0 +1,108 @@
+// Note: phnx themes are not loaded in the dashboard stage so don't use those styles.
+function DashboardAssistant(items, resource, account, accounts) {
+ this.count = 0;
+ this.items = items;
+ this.resource = resource;
+ this.account = account;
+ this.accounts = accounts;
+}
+
+DashboardAssistant.prototype = {
+ setup: function() {
+
+ this.controller.listen(this.controller.stageController.document, Mojo.Event.stageActivate, this.stageActivate.bind(this));
+
+ // Display the dashboard
+ this.update(this.items, this.resource, this.account, this.accounts);
+ },
+ update: function(items, resource, account, accounts) {
+ this.items = items;
+ this.resource = resource;
+ this.account = account;
+ this.accounts = accounts;
+ // Show a new notification and update the dashboard
+ var from;
+ if (items[0].user) {
+ this.title = this.resource.noun + ' from @' + items[0].user.screen_name;
+ from = items[0].user.screen_name;
+ }
+ else {
+ // Direct messages have different property names
+ this.title = 'Message from @' + items[0].sender.screen_name;
+ from = items[0].sender.screen_name;
+ }
+ this.message = items[0].text;
+ this.count += items.length;
+
+ var bannerMessage = '@' + from + ': ' + this.message;
+
+ var bannerParams = {
+ messageText: bannerMessage,
+ soundClass: 'notifications'
+ };
+
+ Mojo.Controller.getAppController().showBanner(bannerParams, {source: "notification"}, 'phnx');
+ this.controller.stageController.indicateNewContent(true); // flashy
+ var info = {title: this.title, message: this.message, count: this.count};
+
+ var renderedInfo = Mojo.View.render({object: info, template: 'dashboard/item-info'});
+ var infoElement = this.controller.get('dashboardinfo');
+ infoElement.innerHTML = renderedInfo;
+ this.listenDashboard();
+ },
+ listenDashboard: function() {
+ this.controller.listen(this.controller.get('dashboard-icon'), Mojo.Event.tap, this.iconTapped.bind(this));
+ this.controller.listen(this.controller.get('dashboard-body'), Mojo.Event.tap, this.bodyTapped.bind(this));
+ },
+ iconTapped: function(event) {
+ var launchArgs = {
+ user: this.account,
+ users: this.accounts,
+ autoScroll: false
+ };
+ this.createStage(launchArgs);
+ },
+ bodyTapped: function(event) {
+ var launchArgs = {
+ user: this.account,
+ users: this.accounts,
+ autoScroll: true,
+ panel: this.resource.name
+ };
+ this.createStage(launchArgs);
+ },
+ createStage: function(launchArgs) {
+ var app = this.controller.stageController.getAppController();
+ var stageName = global.mainStage + this.account.id;
+ Mojo.Log.info('Launching stage ' + stageName);
+ var args = {
+ name: stageName,
+ lightweight: true
+ };
+
+ var pushMainScene = function(stageController) {
+ global.stageActions(stageController);
+ stageController.pushScene('launch', launchArgs);
+ };
+
+ var userStage = app.getStageProxy(stageName);
+
+ if (!userStage) {
+ app.createStageWithCallback(args, pushMainScene, "card");
+ }
+ else {
+ userStage.activate();
+ if (launchArgs.autoScroll) {
+ userStage.delegateToSceneAssistant('refreshAndScrollTo', this.resource.name);
+ }
+ }
+ },
+ stageActivate: function(event) {
+ this.controller.stageController.indicateNewContent(false); // no more flashy
+ },
+ cleanup: function() {
+ this.controller.stopListening(this.controller.stageController.document, Mojo.Event.stageActivate, this.stageActivate);
+ var appController = Mojo.Controller.getAppController();
+ appController.closeStage(global.dashboardStage);
+ }
+};
View
146 app/assistants/finishAuth-assistant.js
@@ -1,94 +1,118 @@
function FinishAuthAssistant(r) {
- this.tokens = {oauth_token: "", oauth_token_secret: "", user_id: "", screen_name: ""};
+ this.tokens = {
+ oauth_token: '',
+ oauth_token_secret: '',
+ user_id: '',
+ screen_name: ''
+ };
this.response = r.response;
}
FinishAuthAssistant.prototype = {
- setup: function(){
+ setup: function() {
+ this.controller.setupWidget(Mojo.Menu.appMenu, {omitDefaultItems: true}, {visible: true, items: global.menuItems});
+ this.userCookie = new Mojo.Model.Cookie('phoenixFirstRun');
+ this.themeCookie = new Mojo.Model.Cookie('phnxTheme');
+
+ //load the selected theme
+ if (typeof(this.themeCookie.get()) !== "undefined"){
+ this.controller.document.getElementsByTagName("body")[0].addClassName(this.themeCookie.get().className);
+ }
+ else{
+ this.controller.document.getElementsByTagName("body")[0].addClassName('default');
+ }
+ this.loadSuggestedUsers();
this.listen();
- var tokens = this.response.strip().split("&");
+ var tokens = this.response.strip().split('&');
var i;
for (i = 0; i < tokens.length; i++) {
var token = tokens[i];
- if (token.substr(0, 12) === "oauth_token=") {
+ if (token.substr(0, 12) === 'oauth_token=') {
this.tokens.oauth_token = token.substr(12);
}
- else if (token.substr(0, 18) === "oauth_token_secret") {
+ else if (token.substr(0, 18) === 'oauth_token_secret') {
this.tokens.oauth_token_secret = token.substr(19);
}
- else if (token.substr(0,8) === "user_id="){
+ else if (token.substr(0,8) === 'user_id=') {
this.tokens.user_id = token.substr(8);
}
- else if (token.substr(0,12) === "screen_name="){
+ else if (token.substr(0,12) === 'screen_name=') {
this.tokens.screen_name = token.substr(12);
}
}
this.storeTokens();
},
- storeTokens: function(){
- var u = {
- key: this.tokens.screen_name,
+ loadSuggestedUsers: function() {
+ //TODO: AJAX call to web service to download suggested users.
+ },
+ storeTokens: function() {
+ var account = new Account();
+ this.user = {
+ key: this.tokens.user_id,
id: this.tokens.user_id,
username: this.tokens.screen_name,
token: this.tokens.oauth_token,
secret: this.tokens.oauth_token_secret
};
-
- currentUser = u;
- cachedUsers.push(u);
- var users = new Lawnchair("phoenixusers");
- users.save(u);
- //
- // Mojo.Controller.stageController.swapScene({
- // 'name': 'main',
- // transition: Mojo.Transition.crossFade
- // });
+ account.load(this.user);
+ account.save();
+ if (global.accounts.length === 0) {
+ var prefs = new LocalStorage();
+ prefs.write('defaultAccount', this.user.id);
+ }
+ global.accounts.push(this.user);
+ this.controller.stageController.Toasters = new ToasterChain();
},
- nextTapped: function(event){
- Mojo.Controller.stageController.swapScene({
- 'name': 'main',
- transition: Mojo.Transition.crossFade,
- disableSceneScroller: true
- });
+ nextTapped: function(event) {
+ // TODO: Create stage for this user, close this stage
+ var account = new Account();
+ account.all(this.createStage.bind(this));
+ },
+ createStage: function(accounts) {
+ var stageName = global.mainStage + this.user.id;
+ var args = {
+ name: stageName,
+ lightweight: true
+ };
+
+ var launchArgs = {
+ user: this.user,
+ users: accounts
+ };
+
+ var pushMainScene = function(stageController) {
+ global.stageActions(stageController);
+ stageController.pushScene('launch', launchArgs);
+ };
+
+ var app = Mojo.Controller.getAppController();
+ var userStage = app.getStageProxy(stageName);
+
+ if (userStage) {
+ userStage.activate();
+ }
+ else {
+ app.createStageWithCallback(args, pushMainScene, "card");
+ }
+ setTimeout(function(){
+ app.closeStage(global.authStage);
+ }, 1000);
},
- followTapped: function(event){
+ followTapped: function(event) {
var userId = event.currentTarget.id;
- var url = 'http://api.twitter.com/1/friendships/create.json';
- var message = {
- method: "POST",
- action: url,
- parameters: []
- };
- message.parameters.push(["screen_name", userId]);
- OAuth.completeRequest(message, {
- consumerKey: twitter.key,
- consumerSecret: twitter.secret,
- token: currentUser.token,
- tokenSecret: currentUser.secret
- });
- var authHeader = OAuth.getAuthorizationHeader('http://api.twitter.com', message.parameters);
- var request = new Ajax.Request(url, {
- method: "POST",
- requestHeaders: {
- Authorization: authHeader,
- Accept: 'application/json'
- },
- postBody: "screen_name=" + userId,
- onSuccess: function(transport){
- banner('Thanks for following!');
- },
- onFailure: function(transport){
- ex('Sadface! There was an error...');
- }
- });
+ var user = this.user;
+ var Twitter = new TwitterAPI(user);
+ Twitter.followUserName(userId, function(response, meta) {
+ banner('Thanks for following!');
+ }, this);
},
- listen: function(event){
- this.controller.listen('next', Mojo.Event.tap, this.nextTapped.bind(this));
+ listen: function(event) {
+ this.controller.listen('next-button', Mojo.Event.tap, this.nextTapped.bind(this));
this.controller.listen('rmxdave', Mojo.Event.tap, this.followTapped.bind(this));
this.controller.listen('phnxapp', Mojo.Event.tap, this.followTapped.bind(this));
},
- cleanup: function(event){
- this.controller.stopListening('next', Mojo.Event.tap, this.nextTapped());
- this.controller.stopListening('rmxdave', Mojo.Event.tap, this.followTapped());
- this.controller.stopListening('phnxapp', Mojo.Event.tap, this.followTapped());
+ cleanup: function(event) {
+ this.controller.stopListening('next-button', Mojo.Event.tap, this.nextTapped);
+ this.controller.stopListening('rmxdave', Mojo.Event.tap, this.followTapped);
+ this.controller.stopListening('phnxapp', Mojo.Event.tap, this.followTapped);
}
};
View
110 app/assistants/launch-assistant.js
@@ -1,82 +1,58 @@
-function LaunchAssistant() {}
+function LaunchAssistant(args) {
+ if (args.user) {
+ this.hasUser = true;
+ this.args = args;
+ }
+ else {
+ this.hasUser = false;
+ }
+}
LaunchAssistant.prototype = {
setup: function() {
- //$('version-info').update("Version " + Mojo.Controller.appInfo.version);
- var that = this;
- this.userCookie = new Mojo.Model.Cookie('phoenixFirstRun');
- this.themeCookie = new Mojo.Model.Cookie('phnxTheme');
- //load the theme
- if (typeof(this.themeCookie.get()) !== "undefined"){
- $$('body')[0].addClassName(this.themeCookie.get().className);
- }
- else{
- $$('body')[0].addClassName('default');
- }
+ this.controller.setupWidget(Mojo.Menu.appMenu, {omitDefaultItems: true}, {visible: true, items: global.menuItems});
+ // this.controller.stageController.Toasters = new ToasterChain();
- if (typeof(this.userCookie.get()) !== "undefined") {
- //using a regular cookie makes sure that the Lawnchair stores have been initialized
- setTimeout(function(){
- that.startApp();
- }, 1000);
- }else{
- //just create the cookie so it isn't null anymore
- this.userCookie.put({
- run: true
- });
- var user = new Lawnchair('phoenixusers'); //create the lawnchair stores
- var prefs = new Lawnchair('phoenixprefs');
- var timelines = new Lawnchair('phoenixtimelines');
+ if (this.hasUser) {
+ this.controller.stageController.user = this.args.user;
+ this.controller.stageController.users = this.args.users;
+ global.accounts = this.args.users;
setTimeout(function(){
- that.controller.get("add-button").setStyle({"bottom":"0px"});
- }, 500);
- }
- },
- startApp: function(){
- var users = new Lawnchair('phoenixusers');
- var that = this;
- users.all(function(r){
- if (r.length === 0){
- var that = this;
- setTimeout(function(){
- that.controller.get("add-button").setStyle({"bottom":"0px"});
- }, 500);
- }else{
- currentUser = r[0];
- cachedUsers = r;
- Mojo.Controller.stageController.swapScene({
+ var opts = {};
+ if (this.hasUser && this.args.autoScroll) {
+ opts.autoScroll = true;
+ opts.panel = this.args.panel;
+ }
+ this.controller.stageController.swapScene({
'name': 'main',
transition: Mojo.Transition.crossFade,
disableSceneScroller: true
- });
-
- }
- }.bind(this));
+ }, opts);
+ }.bind(this), 500);
+ }
+ else {
+ this.showAddButton();
+ }
},
- doOAuth: function() {
- this.visited = true;
- var oauthConfig={
- callbackScene:'finishAuth', //Name of the assistant to be called on the OAuth Success
- requestTokenUrl:'https://api.twitter.com/oauth/request_token',
- requestTokenMethod:'GET', // Optional - 'GET' by default if not specified
- authorizeUrl:'https://api.twitter.com/oauth/authorize',
- accessTokenUrl:'https://api.twitter.com/oauth/access_token',
- accessTokenMethod:'GET', // Optional - 'GET' by default if not specified
- consumer_key: twitter.key,
- consumer_key_secret: twitter.secret,
- callback:'http://www.google.com' // Optional - 'oob' by default if not specified
- };
- Mojo.Controller.stageController.swapScene('oauth',oauthConfig);
+ showAddButton: function() {
+ setTimeout(function(){
+ // short delay for visual effect
+ this.controller.get('add-button').setStyle({'opacity': '1'});
+ }.bind(this), 800);
},
- buttonTapped: function(event){
- this.doOAuth();
+ buttonTapped: function(event) {
+ this.controller.stageController.swapScene('oauth');
},
- activate: function(event){
+ activate: function(event) {
+ //load the current theme
+ var prefs = new LocalStorage();
+ var theme = prefs.read('theme');
+ this.controller.stageController.loadStylesheet('stylesheets/' + theme +'.css');
+
this.controller.listen(this.controller.get("add-button"), Mojo.Event.tap, this.buttonTapped.bind(this));
- //this.controller.listen(this.controller.get("btnGo"), Mojo.Event.tap, this.checkActivation.bind(this));
},
- deactivate: function(event){
- this.controller.stopListening(this.controller.get("add-button"), Mojo.Event.tap, this.buttonTapped.bind(this));
+ deactivate: function(event) {
+ this.controller.stopListening(this.controller.get("add-button"), Mojo.Event.tap, this.buttonTapped);
}
-}
+};
View
2,086 app/assistants/main-assistant.js
@@ -1,167 +1,189 @@
-// TODO: Profile list listeners, user buttons (follow, mention, DM, block/spam)
-
-function MainAssistant() {
-
+function MainAssistant(opts) {
+ if (typeof(opts) === 'undefined') {
+ opts = {};
+ }
+ this.opts = opts;
this.offset = 0;
this.currentPage = 0; //index position of the item in the below array
- this.currentTweet = {}; //placeholder for when a tweet is tapped
- this.tweetBar = false; //flag. true when the tweetbar is visible
- this.rtBar = false; //true when the RT bar is visible
- this.linksBar = false; //true when the links bar is visible
- this.setupComplete = false;
this.loadingMore = false; //flag to determine if items should go to the bottom of a list
- this.accountPanel = false; //is the account panel open?
this.imagePreview = false;
this.loading = false;
- this.convo = false; //is the conversation view open?
- this.profile = false;
- //some compose variables
- this.compose = {
- visible: false,
- sending: false, //to prevent chained duplicate submissions
- reply_to: null,
- lat: null,
- lng: null
- };
- this.count = 80; //how many tweets to load each request
- this.renderLimit = 1000; //umm...this scares me. used in list widgets
+ this.savedSearchesLoaded = false;
+ this.searchLoaded = false;
+ this.switcher = false;
- /**
- this.panels:
- @panel id is used for html elements (and some misc stuff)
- @index is used rarely
- @position is used in panel templates
- @resource is used by the resource helper to figure out endpoint urls
- @refresh tells if this panel should be refreshed globally
- @update tells if this panel should be updated globally
-
- TODO: make panels truly dynamic
- **/
-
- this.panels = [
- {index: 0, position: 1, id: "home", title: "home", type: "timeline", resource: "home", height: 0, refresh: true, update: true, state: {left: 0, top: 0}, model: {items:[]}},
- {index: 1, position: 2, id: "mentions", title: "mentions", type: "timeline", resource: "mentions", height: 0, refresh: true, update: true, state: {left: -133, top: 0}, model: {items:[]}},
- {index: 2, position: 3, id: "messages", title: "messages", type: "timeline", resource: "messages", height: 0, refresh: true, update: true, state: {left: -339, top: 0}, model: {items:[]}}
- //{id: "navLists", title: "lists", type: "all-lists", state: {left: -559, top: 0}},
- //{id: "navSearch", title: "search", type: "search", state: {left: -654, top: 0}}
- ];
-
- this.timeline = 0; //index position of the timeline, default to first one
- this.users = new Lawnchair('phoenixusers');
+ this.count = 20; //how many tweets to load each request
+ this.renderLimit = 1000; //umm...this scares me. used in list widgets to prevent flickering...
+ this.toasters = new ToasterChain();
}
MainAssistant.prototype = {
- setup: function(){
- var btns = $$(".bar-btn");
- var i;
- for (i=0; i < btns.length; i++) {
- btns[i].addClassName("no-label");
- //btns[i].addClassName("big");
+ setup: function() {
+ // Start the background notifications timer
+ global.setTimer();
+
+ this.user = this.controller.stageController.user;
+ this.users = this.controller.stageController.users;
+
+ var homeItems, mentionsItems, messagesItems, i;
+
+ if (this.user.home && this.user.mentions && this.user.messages) {
+ homeItems = this.user.home;
+ mentionsItems = this.user.mentions;
+ messagesItems = this.user.messages;
+
+ // A very sloppy and inelegant way to update the times of these tweets.
+ // TODO: Fix this abomination
+ var th = new TweetHelper();
+ var tweet, d;
+ for (i=0; i < homeItems.length; i++) {
+ tweet = homeItems[i];
+ d = new Date(tweet.created_at);
+ tweet.time_str = d.toRelativeTime(1500);
+ }
+
+ for (i=0; i < mentionsItems.length; i++) {
+ tweet = mentionsItems[i];
+ d = new Date(tweet.created_at);
+ tweet.time_str = d.toRelativeTime(1500);
+ }
+
+ for (i=0; i < messagesItems.length; i++) {
+ tweet = messagesItems[i];
+ d = new Date(tweet.created_at);
+ tweet.time_str = d.toRelativeTime(1500);
+ }
+ }
+ else {
+ homeItems = [];
+ mentionsItems = [];
+ messagesItems = [];
}
+
+ /**
+ this.panels:
+ @id is used for html elements (and some misc stuff)
+ @index is used rarely
+ @position is used in panel templates
+ @resource is used by the resource helper to figure out endpoint urls
+ @refresh tells if this panel should be refreshed globally
+ @update tells if this panel should be updated globally
+
+ TODO: make panels truly dynamic
+ **/
+
+ this.panels = [
+ {index: 0, position: 1, id: "home", title: "home", type: "timeline", resource: "home", height: 0, refresh: true, update: true, state: {left: 0, top: 0}, model: {items:homeItems}},
+ {index: 1, position: 2, id: "mentions", title: "mentions", type: "timeline", resource: "mentions", height: 0, refresh: true, update: true, state: {left: -133, top: 0}, model: {items:mentionsItems}},
+ {index: 2, position: 3, id: "messages", title: "messages", type: "timeline", resource: "messages", height: 0, refresh: true, update: true, state: {left: -339, top: 0}, model: {items:messagesItems}},
+ {index: 3, position: 4, id: "lists", title: "lists", type: "lists", height: 0, refresh: false, update: false},
+ {index: 4, position: 5, id: "search", title: "search", type: "search", height: 0, refresh: false, update: false}
+ ];
+
+ this.timeline = 0; //index position of the timeline, default to first one
+
+ this.controller.get('header-title').update(this.user.username);
+
+ // Build the account menu items
+
+ var am = new Account();
+ am.all(function(r){
+ this.users = r;
+ }.bind(this));
+
+ var accountMenuItems = [];
+ if (this.users) {
+ for (i=0; i < this.users.length; i++) {
+ accountMenuItems.push({
+ label: '@' + this.users[i].username,
+ command: 'account-' + this.users[i].id
+ });
+ }
+ }
+ else {
+ var me = {
+ label: '@' + this.user.username,
+ command: 'account-' + this.user.id
+ };
+ this.users = [me];
+ accountMenuItems.push(me);
+ }
+
+ accountMenuItems.push({
+ label: 'New Account',
+ command: 'cmdNewAccount'
+ });
+
+ accountMenuItems.push({
+ label: 'Logout @' + this.user.username,
+ command: 'cmdRemoveAccount'
+ });
+
var menuItems = [
Mojo.Menu.editItem,
{
- label: "Accounts",
- command: 'cmdAccounts'
+ label: 'Accounts',
+ items: accountMenuItems
},
{
- label: 'Theme',
- items: [
- {label: 'Rebirth', command: 'theme-default'},
- {label: 'Flat', command: 'theme-dark'},
- {label: 'Cobalt', command: 'theme-black'},
- {label: 'Rose', command: 'theme-pink'},
- {label: 'Dexter', command: 'theme-red'},
- {label: 'Commando', command: 'theme-brown'},
- {label: 'Sky', command: 'theme-clouds'},
- {label: '#SB45', command: 'theme-sb45'}
- ]
+ label: 'Lookup User',
+ command: 'cmdFindUser'
},
{
- label: 'Font Size',
- items: [
- {label: 'Small', command: 'font-small'},
- {label: 'Medium', command: 'font-medium'},
- {label: 'Large', command: 'font-large'}
- ]
+ label: 'Preferences',
+ command: 'cmdPreferences'
},
{
- label: "My Profile",
- command: 'cmdMyProfile'
+ label: 'About phnx',
+ command: 'cmdAbout'
},
{
- label: "Logout @" + currentUser.username,
- command: 'cmdRemoveAccount'
+ label: 'Contact Support',
+ command: 'cmdSupport'
}
];
- this.controller.setupWidget(Mojo.Menu.appMenu, {omitDefaultItems: true}, {visible: true, items: menuItems});
-
- this.accountsModel = {
- items: []
- };
-
- this.navModel = {
- items: this.panels
- };
- this.convoModel = {
- items: []
- };
-
- this.controller.setupWidget("accounts-scroller",{mode: 'vertical'},{});
-
- //highlight the first nav button
- this.navModel.items[0].cssClass = "active";
- this.controller.setupWidget("header", {mode: 'horizontal'}, this.model = {});
- this.controller.setupWidget("nav-list",{itemTemplate: "templates/nav-item",listTemplate: "templates/header-list"}, this.navModel);
- this.controller.setupWidget("accounts-list",{itemTemplate: "templates/account-icon",listTemplate: "templates/list"}, this.accountsModel);
- this.controller.setupWidget('convo-scroller',{mode: 'vertical'},{});
- this.controller.setupWidget('convo-list', {itemTemplate: "templates/tweets/item",listTemplate: "templates/list"}, this.convoModel);
- var that = this;
- this.users.all(function(r){
- that.accountsModel.items = r;
- cachedUsers = r;
- that.controller.modelChanged(that.accountsModel);
- });
+ this.controller.setupWidget(Mojo.Menu.appMenu, {omitDefaultItems: true}, {visible: true, items: menuItems});
- //create the panels
- var panelHtml = "";
- for (i=0; i < this.panels.length; i++) {
- var panel = this.panels[i];
+ // create the panels
+ var panelHtml = '';
+ for (var j=0; j < this.panels.length; j++) {
+ var panel = this.panels[j];
var content = Mojo.View.render({
object: panel,
template: 'templates/panels/' + panel.type
});
panelHtml += content;
- this.controller.get('scrollItems').update(panelHtml); //replace the html every time
+
+ this.controller.get('scrollItems').update(panelHtml);
+
this.controller.setupWidget(panel.id + "-scroller",{mode: 'vertical'},{});
- if (panel.type === "timeline"){
+ if (panel.type === "timeline") {
this.controller.setupWidget('list-' + panel.id,{itemTemplate: "templates/tweets/item",listTemplate: "templates/list", renderLimit: this.renderLimit}, panel.model);
}
}
- this.userTweets = {
- items: []
- };
- this.userFavorites = {
- items: []
- };
- this.userMentions = {
- items: []
- };
-
- this.controller.setupWidget('profile-tweets-list', {itemTemplate: "templates/tweets/user",listTemplate: "templates/list"}, this.userTweets);
- // this.controller.setupWidget('profile-mentions-list', {itemTemplate: "templates/tweets/item",listTemplate: "templates/list"}, this.userMentions);
- this.controller.setupWidget('profile-favorites-list', {itemTemplate: "templates/tweets/item",listTemplate: "templates/list"}, this.userFavorites);
- this.controller.setupWidget("info-scroller",{mode: 'vertical'},{});
-
- this.controller.setupWidget("profile-tweets-scroller",{mode: 'vertical'},{});
- // this.controller.setupWidget("profile-mentions-scroller",{mode: 'vertical'},{});
- this.controller.setupWidget("profile-favorites-scroller",{mode: 'vertical'},{});
+
+ // Set up Lists and Search widgets
+ this.savedSearchesModel = {items: []};
+ this.trendingTopicsModel = {items: []};
+
+ this.controller.setupWidget('trending-topics-list',{itemTemplate: "templates/search-list-item",listTemplate: "templates/list", renderLimit: 10}, this.trendingTopicsModel);
+ this.controller.setupWidget('saved-searches-list',{itemTemplate: "templates/search-list-item",listTemplate: "templates/list", renderLimit: 30}, this.savedSearchesModel);
+
+ this.listsModel = {items: []};
+ this.listsYouFollowModel = {items: []};
+
+ this.controller.setupWidget('your-lists-list',{itemTemplate: "templates/list-item",listTemplate: "templates/list", renderLimit: 30}, this.listsModel);
+ this.controller.setupWidget('lists-you-follow-list',{itemTemplate: "templates/list-follows",listTemplate: "templates/list", renderLimit: 30}, this.listsYouFollowModel);
+
this.setScrollerSizes();
- var panelElements = $$('.panel');
- var loadMoreBtns = $$('.load-more');
+
+ var panelElements = this.controller.select('.panel');
+ var loadMoreBtns = this.controller.select('.load-more');
+ var timelineLists = this.controller.select('.timeline-list');
+
this.controller.setupWidget(
"sideScroller",
this.attributes = {
@@ -172,1085 +194,590 @@ MainAssistant.prototype = {
snapIndex: 0
}
);
- this.controller.setupWidget(
- "profile-side-scroller",
- this.attributes = {
- mode: 'horizontal-snap'
- },
- this.sideScrollModel = {
- snapElements: { x: $$('.profile-panel')},
- snapIndex: 0
- }
- );
-
-
//listen to the lists
- for (i=0; i < panelElements.length; i++) {
- var el = panelElements[i];
+ for (i=0; i < timelineLists.length; i++) {
+ var el = timelineLists[i];
this.controller.listen(el, Mojo.Event.listTap, this.tweetTapped.bind(this));
}
+
//listen to the load more buttons
for (i=0; i < loadMoreBtns.length; i++) {
var btn = loadMoreBtns[i];
this.controller.listen(btn, Mojo.Event.tap, this.moreButtonTapped.bind(this));
}
- //listen to the nav links
- this.controller.listen(this.controller.get('nav-list'), Mojo.Event.listTap, this.navLinkTapped.bind(this));
-
- var fontCookie = new Mojo.Model.Cookie('phnxFont');
-
- //load the theme
- if (typeof(fontCookie.get()) !== "undefined"){
- $('scene-container').addClassName(fontCookie.get().fontName);
- }
- else{
- $('scene-container').addClassName('font-small');
- }
-
+
this.addListeners();
-
- //scroll up the command bar
- this.controller.get("command-bar").setStyle({"bottom": "0px"});
- //load things!
- this.refreshAll();
- },
-
- handleCommand: function(event){
- if (event.type === Mojo.Event.back){
- if (this.compose.visible){
- this.toggleCompose(false);
- }
- else if (this.tweetBar && !this.rtBar){
- this.showTweetBar(false);
- }
- else if (this.tweetBar && this.rtBar){
- this.controller.get("tweet-bar").setStyle({"bottom":"0px"});
- this.controller.get("rt-bar").setStyle({"bottom":"-200px"});
- this.rtBar = false;
- }
- else if (this.imagePreview){
- this.closePreview();
- }
- else if (this.convo){
- this.hideConvo();
- }
- else if (this.profile){
- this.hideProfile();
- }
- else if (this.accountPanel){
- this.toggleAccountPanel(false);
+ setTimeout(function(){
+ this.refreshAll();
+ this.loadLists();
+ this.getRetweeted();
+ // get the avatar for the minimized card
+ this.getUserAvatar();
+
+ if (this.opts.autoScroll) {
+ var panel = this.getPanel(this.opts.panel);
+ this.scrollTo(panel.index);
}
- else if (!this.accountPanel && !this.compose.visible && !this.tweetBar && !this.rtBar){
- this.toggleAccountPanel(true);
+ }.bind(this),10);
+ },
+ handleCommand: function(event) {
+ if (event.type === Mojo.Event.back) {
+ if (this.toasters.items.length > 0) {
+ if (this.imagePreview) {
+ this.toasters.items[this.toasters.items.length - 1].closePreview();
+ }
+ else {
+ this.toasters.back();
+ }
+ event.stop();
}
- event.stop();
+
}
- else if (event.type === Mojo.Event.forward){
- if (!this.loading){
- this.refresh();
+ else if (event.type === Mojo.Event.forward) {
+ var prefs = new LocalStorage();
+ var onSwipe = prefs.read('forwardSwipe');
+ if (Ajax.activeRequestCount === 0) {
+ if (onSwipe === 'current') {
+ this.refresh();
+ }
+ else if (onSwipe === 'all') {
+ this.refreshAll();
+ }
}
}
- else if (typeof(event.command) !== 'undefined'){
- if (event.command.indexOf('theme-') > -1){
+ else if (typeof(event.command) !== 'undefined') {
+ if (event.command.indexOf('theme-') > -1) {
this.switchTheme(event.command);
}
- else if (event.command.indexOf('font-') > -1){
+ else if (event.command.indexOf('font-') > -1) {
this.changeFont(event.command);
}
- else if (event.command === 'cmdAccounts'){
- banner('Tip: back gesture to show accounts');
- this.toggleAccountPanel(true);
+ else if (event.command.indexOf('account-') > -1) {
+ var userId = event.command.substr(event.command.indexOf('-') + 1);
+ this.openAccount(userId);
}
- else if (event.command === 'cmdMyProfile'){
- this.showProfile(currentUser.username, true);
+ else if (event.command === 'cmdNewAccount') {
+ this.newAccountTapped();
}
- else if (event.command === 'cmdRemoveAccount'){
- this.users.remove(currentUser.key);
- this.users.all(function(r){
- cachedUsers = r;
- if (cachedUsers.length > 0){
- currentUser = cachedUsers[0];
- Mojo.Controller.stageController.swapScene({
- 'name': 'main',
- transition: Mojo.Transition.crossFade,
- disableSceneScroller: true
- });
- }
- else{
- Mojo.Controller.stageController.swapScene({
- 'name': 'launch',
- transition: Mojo.Transition.crossFade
- });
- }
- });
+ else if (event.command === 'cmdMyProfile') {
+ // this.showProfile(this.user.username, true);
+ var Twitter = new TwitterAPI(this.user);
+ Twitter.getUser(this.user.username, function(response){
+ this.controller.stageController.pushScene({
+ name: 'profile',
+ disableSceneScroller: true
+ }, response.responseJSON);
+ }.bind(this));
+ }
+ else if (event.command === 'cmdFindUser') {
+ this.toasters.add(new LookupToaster(this));
+ }
+ // else if (event.command === 'cmdPreferences') {
+ // // this.controller.stageController.pushScene('preferences');
+ // }
+ else if (event.command === 'cmdRemoveAccount') {
+ this.logout();
}
}
},
-
- switchTheme: function(command){
- var theme = command.substr(command.indexOf('-') + 1);
- var classes = $$('body')[0].classNames();
- var i;
- for (i=0; i < classes.length; i++) {
- $$('body')[0].removeClassName(classes[i]);
- }
-
- $$('body')[0].addClassName(theme);
-
- //add cookie to save theme
- var themeCookie = new Mojo.Model.Cookie('phnxTheme');
- themeCookie.put({
- className: theme
- });
- },
- changeFont: function(font){
- //var font = command.substr(command.indexOf('-') + 1);
- var classes = $('scene-container').classNames();
- var i;
- for (i=0; i < classes.length; i++) {
- $('scene-container').removeClassName(classes[i]);
- }
- $('scene-container').addClassName(font);
-
- var fontCookie = new Mojo.Model.Cookie('phnxFont');
- fontCookie.put({
- fontName: font
- });
- },
- setScrollerSizes: function(){
- //header 64px on 320 width devices, 128 on hi-res devices
- //TODO: set navScroller dynamically
- //TODO: set SCROLL STATES for nav items dynamically (oh boy...)
-
- var screenHeight = this.controller.window.innerHeight;
- var screenWidth = this.controller.window.innerWidth;
- var height = screenHeight - 64; //subtract the header
- var i;
- //grab each panel element. There should be as many of these as there are in this.panels
- var panelElements = $$(".panel");
- var totalWidth = 0; //the width of the main container
- for (i=0; i < panelElements.length; i++) {
- var panel = panelElements[i];
- panel.setStyle({
- "width": screenWidth + "px"
- });
- totalWidth += screenWidth;
+ switchTheme: function(command) {
+ // var theme = command.substr(command.indexOf('-') + 1);
+ // var classes = this.controller.select('body')[0].classNames();
+ // var i;
+ // for (i=0; i < classes.length; i++) {
+ // this.controller.select('body')[0].removeClassName(classes[i]);
+ // }
+ //
+ // this.controller.select('body')[0].addClassName(theme);
+ //
+ // //add cookie to save theme
+ // var themeCookie = new Mojo.Model.Cookie('phnxTheme');
+ // themeCookie.put({
+ // className: theme
+ // });
+ },
+ changeFont: function(cmdFont) {
+ var font = cmdFont.substr(cmdFont.indexOf('-') + 1);
+ var fonts = ['small', 'medium', 'large'];
+ // var body = this.controller.select('body')[0];
+ var body = this.controller.document.getElementsByTagName("body")[0];
+ for (var i=0; i < fonts.length; i++) {
+ Element.removeClassName(body, 'font-' + fonts[i]);
+ }
+ Element.addClassName(body, 'font-' + font);
+ var prefs = new LocalStorage();
+ prefs.write('fontSize', font);
+ },
+ setScrollerSizes: function() {
+ if (this.controller.window && this.controller) {
+ var screenHeight = this.controller.window.innerHeight;
+ var screenWidth = this.controller.window.innerWidth;
+ var height = screenHeight - 0; //subtract the header
+ // var height = screenHeight; //subtract the header
+ var i;
+ //grab each panel element. There should be as many of these as there are in this.panels
+
+ var panelElements = this.controller.select('.panel');
+ var totalWidth = 0; //the width of the main container
+ for (i=0; i < panelElements.length; i++) {
+ var panel = panelElements[i];
+ panel.setStyle({
+ "width": screenWidth + "px"
+ });
+ totalWidth += screenWidth;
- //each scroller needs a max height. otherwise they don't scroll
- this.controller.get(this.panels[i].id + "-scroller").setStyle({"max-height": height + "px"});
- }
-
- //set the container width
- this.controller.get('scrollItems').setStyle({'width' : totalWidth + 'px'});
- //set the height of the dark 'shim' that we use sometimes
- this.controller.get('shim').setStyle({'height': screenHeight + 'px'});
- //set the height of the accounts bar
- this.controller.get('accounts-panel').setStyle({'height': screenHeight + 'px'});
- this.controller.get('convo-scroller').setStyle({'max-height': (screenHeight - 60) + 'px'});
- this.controller.get('profile-panel').setStyle({'height': (screenHeight - 20) + 'px' });
-
- //set the height of profile scrollers
- this.controller.get('profile-tweets-scroller').setStyle({'max-height': (screenHeight - 134) + 'px'});
- this.controller.get('profile-favorites-scroller').setStyle({'max-height': (screenHeight - 134) + 'px'});
- $('image-preview').hide();
- },
-
- navLinkTapped: function(event){
- var panelId = event.item.id;
- var panelIndex;
- var i;
- //get the index of the panel for the nav item
- for (i=0; i < this.panels.length; i++) {
- if (this.panels[i].id === panelId){
- panelIndex = i;
+ //each scroller needs a max height. otherwise they don't scroll
+ this.controller.get(this.panels[i].id + "-scroller").setStyle({"max-height": height + "px"});
}
+
+ //set the container width
+ this.controller.get('scrollItems').setStyle({'width' : totalWidth + 'px'});
+ //set the height of the dark 'shim' that we use sometimes
+ this.controller.get('shim').setStyle({'height': screenHeight + 'px'});
+ this.controller.get('image-preview').hide();
}
-
- //if it's the current panel, scroll to the top
- //otherwise, scroll to that panel
- if (this.timeline === panelIndex){
- this.controller.get('list-' + panelId).mojo.revealItem(0, true);
- }else{
- this.scrollTo(panelIndex);
- }
-
},
-
- scrollTo: function(idx){
+ scrollTo: function(idx) {
//this moves the horizontal scroller
this.controller.get("sideScroller").mojo.setSnapIndex(idx, true);
},
-
- scrollerChanged: function(event){
+ scrollerChanged: function(event) {
var panel = this.panels[event.value];
- //update the index
- this.timeline = event.value;
- //scroll the top nav
- this.scrollNav(panel.id);
- },
-
- scrollNav: function(id){
- //if this selector breaks, use the "class" attribute in the navModel items
- var divs = $$(".nav-item");
- var i;
- //remove the active class from any items that have it
- for (i=0; i < divs.length; i++) {
- divs[i].removeClassName("active");
- }
- //move the nav scroller to the preset state
- for (i=0; i < this.navModel.items.length; i++) {
- var nav = this.navModel.items[i];
- if (nav.id === id){
- this.controller.get("header").mojo.setState(nav.state, true);
+ //hide the beacon and new content indicator on the old panel
+ var oldPanel = this.panels[this.timeline];
+ if (oldPanel.refresh) {
+ // newTweets = this.controller.select('#panel-' + oldPanel.id + ' .new-tweet');
+ // for (var i=0; i < newTweets.length; i++) {
+ // this.controller.get(newTweets[i]).removeClassName('new-tweet');
+ // }
+ this.controller.get(oldPanel.id + '-beacon').removeClassName('show');
+ }
+ if (event.value === 4) {
+ // enable the search box
+ this.controller.get('txtSearch').disabled = false;
+ if (this.searchLoaded === false) {
+ this.searchLoaded = true;
+ this.loadSearch();
}
}
- this.controller.get('nav-' + id).addClassName("active");
- },
-
- scrollMovement: function(event){
- //this function was created for "infinite scrolling"
- //not in use - too unstable
- var scroller = this.controller.get(event.srcElement.id);
- var timeline = "";
- var size = 0;
- if (scroller.id === "tweets-scroller"){
- size = this.tweetsModel.items.length;
- timeline = "tweets";
- }
- //var size = scroller.mojo.scrollerSize().height;
- var position = scroller.mojo.getScrollPosition().top;
- var leeway = size * - 50; //assume px per status item. lower number means load starts further from bottom. range 40-80px
- if ((position / leeway) > 1.2){
- this.loadMore(timeline);
+ else {
+ this.controller.get('txtSearch').blur();
+ this.controller.get('txtSearch').disabled = true;
}
- },
+
+ //update the index
+ this.timeline = event.value;
+ // Move the indicator arrow
+ this.moveIndicator(panel.id);
+ },
+ loadSearch: function() {
+ // Loads saved searches and trending topics
+ var Twitter = new TwitterAPI(this.user);
+ Twitter.trends(function(response){
+ var trends = response.responseJSON.trends;
+ this.trendingTopicsModel.items = trends;
+ this.controller.modelChanged(this.trendingTopicsModel);
+ }.bind(this));
- toggleAccountPanel: function(show){
- if (show){
- this.controller.get('accounts-panel').setStyle({
- 'left' : '0px'
- });
- this.accountPanel = true;
- }
- else{
- this.controller.get('accounts-panel').setStyle({
- 'left' : '-85px'
- });
- this.accountPanel = false;
- }
- },
- refreshAll: function(){
- //loads all timelines
- var i;
- this.loadingMore = false;
- var lastId = 0;
- for (i=0; i < this.panels.length; i++) {
- var panel = this.panels[i];
- if (panel.refresh){
- if (panel.model.items.length > 0){
- lastId = panel.model.items[0].id_str;
- }
- if (lastId === 0){
- this.getTweets(panel);
- }else{
- this.getTweets(panel, lastId);
+ Twitter.getSavedSearches(function(response){
+ var savedSearches = response.responseJSON;
+ if (savedSearches.length > 0) {
+ if (savedSearches.length === 1) {
+ this.controller.get('saved-searches').addClassName('single');
}
+ this.savedSearchesModel.items = savedSearches;
+ this.controller.modelChanged(this.savedSearchesModel);
+ this.controller.get('saved-searches').show();
+ this.savedSearchesLoaded = true;
}
- }
+ }.bind(this));
+ },
+ refreshAll: function() {
+ this.refreshPanel(this.panels[0]);
+ this.refreshPanel(this.panels[1]);
+ this.refreshPanel(this.panels[2]);
+ },
+ refresh: function() {
+ this.refreshPanel(this.panels[this.timeline]);
},
- refresh: function(){
- //refreshes the current timeline
+ refreshPanelId: function(id) {
+ this.refreshPanel(this.getPanel(id));
+ },
+ refreshPanel: function(panel) {
this.loadingMore = false;
var lastId = 0;
- var panel = this.panels[this.timeline];
- if (panel.refresh){
- if (panel.model.items.length > 0){
- var tweet = panel.model.items[0];
- if (tweet.is_rt){
- lastId = tweet.original_tweet.id_str;
+ if (panel.refresh) {
+ if (panel.model.items.length > 0) {
+ // grab the second tweet for gap detection
+ var tweet = panel.model.items[1];
+
+ if (tweet.is_rt) {
+ lastId = tweet.original_id;
}
else{
lastId = tweet.id_str;
}
}
- if (lastId === 0){
+ if (lastId === 0) {
this.getTweets(panel);
}else{
this.getTweets(panel, lastId);
}
}
+ else if (panel.id === 'search') {
+ this.loadSearch();
+ }
+ },
+ refreshAndScrollTo: function(id) {
+ var panel = this.getPanel(id);
+ this.refreshAll();
+ this.scrollTo(panel.index);
+ },
+ getUserAvatar: function() {
+ var Twitter = new TwitterAPI(this.user, this.controller.stageController);
+ Twitter.getUser(this.user.username, function(r) {
+ var img = r.responseJSON.profile_image_url.replace('_normal', '_bigger');
+ var cardHtml = Mojo.View.render({
+ object: {image: img},
+ template: 'templates/account-card'
+ });
+ this.controller.get('preload').src = img;
+ this.controller.get('account-shim').update(cardHtml);
+ }.bind(this));
+ },
+ getPanel: function(id) {
+ var panel;
+ for (var i=0; i < this.panels.length; i++) {
+ panel = this.panels[i];
+ if (panel.id === id) {
+ return panel;
+ }
+ }
},
- loadMore: function(timeline){
+ loadMore: function(timeline) {
this.loadingMore = true;
var model = this.panels[this.timeline].model;
var maxId = model.items[model.items.length - 1].id_str;
this.getTweets(this.panels[this.timeline], undefined, maxId);
},
- getTweets: function(panel, lastId, maxId){
- this.loading = true;
- var rh = new ResourceHelper();
- var url = rh.url(panel.resource); //using the resource helper to map endpoints
- var that = this;
- var message = {
- method: "GET",
- action: url,
- parameters: []
+ getTweets: function(panel, lastId, maxId) {
+ var args = {
+ 'count': this.count,
+ 'include_entities': 'true'
};
- var i;
- //when using OAuth, parameters must be included in the request body
- //and in the base signature of the Auth Header
- message.parameters.push(["include_entities","true"]);
- message.parameters.push(["count",this.count]);
- var params = "include_entities=true&count=" + this.count;
- if (typeof(lastId) !== "undefined" && lastId !== 0){
- params += "&since_id=" + lastId;
- message.parameters.push(["since_id",lastId]);
+
+ if (lastId) {
+ args.since_id = lastId;
}
- if (typeof(maxId) !== "undefined" && maxId !== 0){
- params += "&max_id=" + maxId;
- message.parameters.push(["max_id",maxId]);
+ if (maxId) {
+ args.max_id = maxId;
}
- OAuth.completeRequest(message, {
- consumerKey: twitter.key,
- consumerSecret: twitter.secret,
- token: currentUser.token,
- tokenSecret: currentUser.secret
- });
- var authHeader = OAuth.getAuthorizationHeader('https://api.twitter.com', message.parameters);
- this.controller.get("refresh").addClassName("spin");
- var req = new Ajax.Request(url, {
- method: "GET",
- requestHeaders: {
- Authorization: authHeader,
- Accept: 'application/json'
- },
- parameters: params,
- onSuccess: function(response){
- if (panel.id === "messages"){
- var tweets = response.responseJSON;
- for (i=0; i < tweets.length; i++) {
- tweets[i].user = tweets[i].sender;
- tweets[i].dm = true;
- //tweets[i] = this.processTweet(tweets[i]);
- }
- }
- that.gotItems(panel, response.responseJSON);
- },
- onFailure: function(transport){
- that.controller.get("refresh").removeClassName("spin");
- ex(transport.responseJSON.error);
- }
- });
+ var Twitter = new TwitterAPI(this.user);
+ Twitter.timeline(panel, this.gotItems.bind(this), args, this);
},
-
- gotItems: function(panel, items){
- //ideally this is a one-size-fits-all function
- //for handling timeline responses
+ fillGap: function(panel) {
+ var args = {
+ count: this.count,
+ include_entities: 'true',
+ max_id: panel.gapStart,
+ since_id: panel.gapEnd
+ };
+ var Twitter = new TwitterAPI(this.user);
+ Twitter.timeline(panel, this.gotGap.bind(this), args, this);
+ },
+ gotGap: function(response, meta) {
+ banner('Not done yet');
+ },
+ gotItems: function(response, meta) {
+ // one-size-fits-all function to handle timeline updates
+ // Does lots of looping to update relative times. Needs optimization
+
+ var panel = meta.panel;
var model = panel.model;
var scroller = panel.id + "-scroller";
var more = "more-" + panel.id;
-
- var xCount = items.length;
- var tweets = items;
+ var tweets = response.responseJSON;
+ var xCount = tweets.length;
+
var i;
- if (tweets.length > 0){
+
+ if (tweets.length > 1) {
var count = 0;
for (i=0; i < tweets.length; i++) {
- tweets[i] = this.processTweet(tweets[i]);
+ if (panel.id === 'messages') {
+ tweets[i].user = tweets[i].sender;
+ tweets[i].dm = true;
+ }
+ var th = new TweetHelper();
+ tweets[i] = th.process(tweets[i]);
}
+
+ if (!this.loadingMore) {
+ this.controller.get(panel.id + '-beacon').addClassName('show');
+ }
+ }
+ else {
+ this.controller.get(panel.id + '-beacon').removeClassName('show');
}
- var scrollId = "";
+ var scrollId = 0; // this is the INDEX (not ID, sorry) of the new tweet to scroll to
if (model.items.length > 0 && this.loadingMore) {
- //loading more items
+ //loading "more" items (not refreshing), so append to bottom
+
for (i=1; i < tweets.length; i++) {
//start the loop at i = 1 so tweets aren't duplicated
model.items.splice((model.items.length - 1) + i, 0, tweets[i]);
}
}
- else if (model.items.length > 0 && !this.loadingMore){
- //a typical refresh
+ else if (model.items.length > 0 && !this.loadingMore) {
+ // a typical refresh is being performed here (append to top)
var k;
+
+ // loop through old tweets
for (k=0; k < model.items.length; k++) {
- //clear any new tweets
- model.items[k].cssClass = "old-tweet";
+ // remove the tweet divider
+ if (model.items[k].cssClass === 'new-tweet'){
+ model.items[k].cssClass = "old-tweet";
+ }
+ }
+
+ var hasGap, loopCount;
+ var tweetCount = tweets.length;
+ if (tweets[tweets.length - 1].id_str === model.items[0].id_str) {
+ // There is no gap if the first tweet is included here
+ // Adjust loopCount to exclude this duplicate tweet from being included
+ hasGap = false;
+ loopCount = tweets.length - 2;
+ tweetCount--;
+ }
+ else {
+ hasGap = true;
+ loopCount = tweets.length - 1;
+ panel.gapStart = tweets[tweets.length - 1].id_str;
+ panel.gapEnd = model.items[0].id_str;
}
var j;
- for (j = tweets.length - 1; j >= 0; j--){
+ for (j = loopCount; j >= 0; j--) {
//doing a backwards (upwards?) loop to get the items in the right order
- if (j === tweets.length - 1){
- tweets[j].cssClass = "new-tweet";
+
+ if (j === loopCount) {
+ tweets[j].cssClass = 'new-tweet';
+
+ // These nouns are used in the "X New {Noun}" message
+ var nouns = {
+ 'home': 'Tweet',
+ 'mentions': 'Mention',
+ 'messages': 'Direct Message'
+ };
+
+ // TODO: Make this message tappable to load gaps
+ var msg = tweetCount + ' New ' + nouns[panel.id];
+ if (tweetCount > 1) {
+ msg += 's'; //pluralize
+ }
+
+ if (hasGap) {
+ msg += '<br /><span>Tap to load missing tweets</span>';
+ }
+
+ tweets[j].dividerMessage = msg;
}
model.items.splice(0,0,tweets[j]);
}
- scrollId = tweets.length;
+ scrollId = tweetCount; // set the index of the new tweet to auto-scroll to
}
else{
- model.items = tweets;
+ // the timeline was empty so do a 1:1 mirror of the tweets response
+ model.items = tweets;
+ }
+ // Write a few (10) of the latest tweets to the user's cache (async)
+ this.user[panel.id] = model.items.slice(0,10);
+ var account = new Account();
+ account.load(this.user);
+ account.save();
+
+ // Save the recent ids for notification checks
+ if (tweets.length > 0 && !this.loadingMore) {
+ var store = new LocalStorage();
+ store.write(this.user.id + '_' + panel.id, tweets[0].id_str);
}
- this.updateLists();
- if (scrollId != ""){
+ if (panel.update) {
+ for (i=0; i < model.items.length; i++) {
+ var tweet = model.items[i];
+ tweet.time_str = this.timeSince(tweet.created_at);
+ }
+ }
+
+ this.controller.modelChanged(panel.model);
+ if (scrollId !== 0) {
this.controller.get('list-' + panel.id).mojo.revealItem(scrollId, true);
}
- this.controller.get('refresh').removeClassName('spin');
- this.controller.get(more).show();
- this.loading = false;
- },
- processTweet: function(tweet){
- //takes a tweet and does all sorts of stuff to it
- if (!tweet.dm){
- if (typeof(tweet.retweeted_status) !== "undefined"){
- var orig = tweet;
- var retweeter = tweet.user;
- tweet = tweet.retweeted_status;
- tweet.retweeter = retweeter;
- tweet.original_tweet = orig;
- tweet.is_rt = true;
- tweet.footer = "<br />Retweeted by " + retweeter.screen_name;
- }
- else{
- tweet.is_rt = false;
- }
- //disable clickable source links
- tweet.source = "via " + tweet.source.replace('href="', 'href="#');
+ if (model.items.length === 0 || (this.loadingMore && tweets.length === 0)) {
+ this.controller.get(more).hide();
}
- //keep the plaintext version for quote-style RTs (so HTML doesn't get tossed in there)
- tweet.stripped = tweet.text;
- tweet.text = tweet.text.parseLinks();
- tweet.time_str = this.timeSince(tweet.created_at);
- return tweet;
+ this.loading = false;
},
- timeSince: function(time){
+ timeSince: function(time) {
//using a modified Date function in helpers/date.js
var d = new Date(time);
return d.toRelativeTime(1500);
},
- updateLists: function(){
- //updates the time on old tweets and notices new items
- var j;
- for (j=0; j < this.panels.length; j++) {
- var panel = this.panels[j];
- var mod = panel.model;
- var i;
- for (i=0; i < mod.items.length; i++) {
- var tweet = mod.items[i];
- tweet.time_str = this.timeSince(tweet.created_at);
- }
- this.controller.modelChanged(mod);
- // this.controller.get("list-" + panel.id).mojo.noticeUpdatedItems(0,mod.items);
- // this.controller.get("list-" + panel.id).mojo.setLength(mod.items.length);
- //this.controller.get(scroller).mojo.adjustBy(0,1); //move the scroller by 1px
- }
- },
- newTweet: function(event){
- //$("command-bar").setStyle({"bottom":"-100px"});
- if (!this.compose.visible){
- this.toggleCompose(true);
- }else{
- this.toggleCompose(false);
- }
- },
- toggleCompose: function(show, type){
- if (show){
- var bottom = "80px";
- var arrow = "240px";
- if (type === "reply"){
- this.controller.get("txtTweet").value = "@" + this.currentTweet.user.screen_name + " ";
- this.compose.reply_to = this.currentTweet.id_str;
- }
- else if (type === 'rt'){
- this.controller.get("txtTweet").value = "RT @" + this.currentTweet.user.screen_name + " - " + this.currentTweet.stripped;
- }
- else if (type === 'dm'){
- this.controller.get("txtTweet").value = "d " + this.currentTweet.user.screen_name + " ";
- }
- this.updateCounter();
- this.compose.visible = true;
- this.controller.get('submit-tweet').show();
- this.controller.get('new-tweet').hide();
- this.controller.get("compose").setStyle({"bottom": bottom});
- this.showTweetBar(false);
- }else{
- this.compose.visible = false;
- this.controller.get('submit-tweet').hide();
- this.controller.get('new-tweet').show();
- this.controller.get("compose").setStyle({"bottom":"-190px"});
- this.controller.get("txtTweet").value = "";
- this.compose.reply_to = null;
- }
- $('txtTweet').focus();
- },
- tweetTapped: function(event){
- if (!this.tweetBar){
- this.currentTweet = event.item;
- this.showTweetBar(true);
- }
- else{
- this.showTweetBar(false);
- if (this.rtBar){
- this.controller.get("rt-bar").setStyle({"bottom":"-200px"});
- }
- }
- },
- tweetBarButtonTapped: function(event){
- var id = event.srcElement.id;
- if (id === "reply"){
- this.toggleCompose(true, "reply");
- }
- else if (id === "retweet"){
- this.rtBar = true;
- $("tweet-bar").setStyle({"bottom":"-300px"});
- $("rt-bar").setStyle({"bottom":"0px"});
- }
- else if (id === "confirm-rt"){
- this.retweet(this.currentTweet.id_str);
- this.showTweetBar(false);
- }
- else if (id === "edit-rt"){
- this.toggleCompose(true, "rt");
- }
- else if (id === "favorite"){
- this.addFavorite(this.currentTweet.id_str);
- this.showTweetBar(false);
- }
- else if (id === "delete"){
- this.deleteTweet(this.currentTweet.id_str);
- }
- else if (id === 'dm'){
- this.toggleCompose(true, "dm");
- this.showTweetBar(false);
- }
- else if (id === 'convo'){
- //banner('Coming in the next version!');
- this.showConvo(this.currentTweet);
- }
- // else if (id === "more"){
- // //this.showTweetBar(false);
- // //this.showMoreMenu(event);
- // }
- // else if (id === "profile"){
- // this.showTweetBar(false);
- // // Mojo.Controller.stageController.pushScene({
- // // name: "profile",
- // // transition: Mojo.Transition.crossFade
- // // }, this.currentTweet.user);
- // }
- },
- showTweetBar: function(show){
-
- if (show){
- if (this.convo){
- this.hideConvo();
- }
- if (this.profile){
- this.hideProfile();
- }
- this.tweetBar = true;
- if (this.panels[this.timeline].id !== "messages"){
- if (this.currentTweet.user.id == currentUser.id){
- this.controller.get("retweet").hide();
- this.controller.get("favorite").hide();
- this.controller.get("reply").hide();
- this.controller.get("delete").show();
- }
- else{
- this.controller.get("retweet").show();
- this.controller.get("favorite").show();
- this.controller.get("reply").show();
- this.controller.get("delete").hide();
- }
- if (this.currentTweet.in_reply_to_status_id_str === null){
- this.controller.get("convo").hide();
- }else{
- this.controller.get("convo").show();
+ loadLists: function() {
+ var Twitter = new TwitterAPI(this.user);
+ Twitter.userLists({'user_id':this.user.id}, function(response){
+ var lists = response.responseJSON.lists;
+ if (lists.length > 0) {
+ if (lists.length === 1) {
+ this.controller.get('your-lists').addClassName('single');
}
- this.controller.get("dm").hide();
- }else{
- this.controller.get("dm").show();
- this.controller.get("reply").hide();
- this.controller.get("retweet").hide();
- this.controller.get("favorite").hide();
- this.controller.get("reply").hide();
- this.controller.get("convo").hide();
- this.controller.get("delete").hide();
- }
- var content = Mojo.View.render({
- object: this.currentTweet,
- template: 'templates/tweets/details'
- });
-
- this.controller.get("tweet-details").update(content);
- this.controller.get("shim").setStyle({"opacity":1, "display": "block"});
- this.controller.get("tweet-bar").setStyle({"bottom":"0px"});
- this.controller.get("command-bar").setStyle({"bottom":"-100px"});
- this.toggleCompose(false);
- this.toggleAccountPanel(false);
- }
- else{
- this.currentTweet = null;
- this.tweetBar = false;
- if (this.rtBar){
- $("rt-bar").setStyle({"bottom":"-200px"});
- this.rtBar = false;
+ this.listsModel.items = lists;
+ this.controller.modelChanged(this.listsModel);
+ this.controller.get('your-lists').show();
}
- this.controller.get("shim").setStyle({"opacity": 0, "display": "none"});
- this.controller.get("tweet-bar").setStyle({"bottom":"-480px"});
- this.controller.get("command-bar").setStyle({"bottom"