main.qml 64 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755
  1. /*
  2. Copyright 2011 - Tommi Laukkanen (www.substanceofcode.com)
  3. This file is part of TwimGo.
  4. TwimGo is free software: you can redistribute it and/or modify
  5. it under the terms of the GNU Lesser General Public License as published by
  6. the Free Software Foundation, either version 3 of the License, or
  7. (at your option) any later version.
  8. TwimGo is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU Lesser General Public License for more details.
  12. You should have received a copy of the GNU Lesser General Public License
  13. along with TwimGo. If not, see <http://www.gnu.org/licenses/>.
  14. */
  15. import QtQuick 1.1 // 4.7
  16. import QtMobility.location 1.1
  17. //import QtMultimediaKit 1.1
  18. //import com.nokia.symbian 1.1
  19. //import com.nokia.meego 1.0
  20. import "js/script.js" as Script
  21. import "js/pocket.js" as Pocket
  22. import "js/twitter.js" as Twitter
  23. import "js/storage.js" as Storage
  24. import "js/translate.js" as AzureTranslate
  25. import "components"
  26. //PageStackWindow {
  27. // initialPage: window
  28. // showToolBar: false
  29. Rectangle {
  30. id: window
  31. width: 360 // 360 // 640 //800
  32. height: 640 // 640 // 360 //424
  33. anchors.fill: parent
  34. property int tweetHeight: 138 // 132 //180
  35. property int tweetFontSize: 17 // 16
  36. property int iconFontSize: 10
  37. property string token: ""
  38. property int iconSpacing: 17
  39. property int startup: 0
  40. property int timelineIndex: 0
  41. property int gridColumns: 2
  42. property string lat: ""
  43. property string lon: ""
  44. color: "#333"
  45. //property variant positionSource
  46. property bool locationAvailable: true
  47. PositionSource {
  48. id: positionSource
  49. updateInterval: 1500
  50. active: false
  51. }
  52. /* Audio {
  53. id: birdSound
  54. source: "sounds/Birds.wav"
  55. volume: 0
  56. muted: true
  57. }
  58. */
  59. Timer {
  60. id: autoRefreshTimer
  61. interval: 300000 // 5 minutes
  62. repeat: true
  63. onTriggered: {
  64. if(container.flipped==false &&
  65. statusDialog.state!="shown" &&
  66. searchDialog.state!="shown" &&
  67. mainMenu.state!="shown" &&
  68. listsDialog.state!="shown" &&
  69. searchesDialog.state!="shown" &&
  70. trendsDialog.state!="shown" ) {
  71. Script.autoFresh();
  72. }
  73. }
  74. }
  75. Timer {
  76. id: hideSplashTimer
  77. interval: 4000
  78. repeat: false
  79. onTriggered: {
  80. if(welcomePage.visible==true) {
  81. welcomePage.visible = false;
  82. authorizeWindow.visible = false;
  83. container.state = "shown";
  84. }
  85. }
  86. }
  87. Timer {
  88. id: locationTimer
  89. interval: 3000
  90. repeat: true
  91. onTriggered: {
  92. if(typeof(positionSource)!="undefined" &&
  93. typeof(positionSource.position.coordinate.latitude)!="undefined") {
  94. //console.log("Update locations");
  95. var coord = positionSource.position.coordinate;
  96. window.lat = String(coord.latitude);
  97. window.lon = String(coord.longitude);
  98. //console.log("LAT: " + window.lat);
  99. if(window.lat.length>0 && window.lat!="NaN") {
  100. Storage.setKeyValue("latitude", window.lat);
  101. Storage.setKeyValue("longitude", window.lon);
  102. }
  103. }
  104. }
  105. }
  106. Timer {
  107. id: screenSizeChecker
  108. interval: 2500
  109. repeat: false
  110. onTriggered: {
  111. var biggerSide = window.width;
  112. var smallerSide = window.height;
  113. if(smallerSide>window.width) {
  114. smallerSide = window.width;
  115. biggerSide = window.height;
  116. }
  117. if(windowHelper.isMaemo()) { // smallerSide>410) {
  118. // Maemo
  119. minimize.visible = true;
  120. window.tweetHeight = 170;
  121. window.iconSpacing = 38;
  122. window.tweetFontSize = 20;
  123. window.iconFontSize = 14;
  124. } else if(smallerSide>360 && smallerSide<500) {
  125. // Harmattan
  126. window.tweetHeight = 170;
  127. window.iconSpacing = 38;
  128. window.tweetFontSize = 22;
  129. window.iconFontSize = 14;
  130. } else if(smallerSide>500) {
  131. // Tablet
  132. window.gridColumns = 4;
  133. window.tweetFontSize = 16;
  134. } else if(smallerSide==480 && biggerSide==640) {
  135. // Symbian E6
  136. window.tweetHeight = 160;
  137. window.iconSpacing = 17;
  138. window.tweetFontSize = 20;
  139. window.iconFontSize = 14;
  140. }
  141. }
  142. }
  143. Component.onCompleted: {
  144. AzureTranslate.setComponents(
  145. waiting,
  146. waitingText,
  147. doneIndicator,
  148. errorIndicator);
  149. Pocket.setComponents(
  150. waiting,
  151. waitingText,
  152. doneIndicator,
  153. errorIndicator);
  154. Script.setComponents(
  155. waiting,
  156. doneIndicator,
  157. profileDialog,
  158. container,
  159. errorIndicator,
  160. welcomePage,
  161. homeIcon,
  162. mentionsIcon,
  163. mainMenu);
  164. Storage.setKeyValue("username", ":D");
  165. Storage.setKeyValue("password", ":)");
  166. Storage.getKeyValue("lastHomeID", window.valueLoaded);
  167. Storage.getKeyValue("lastMentionID", window.valueLoaded);
  168. Storage.getKeyValue("useListView", window.valueLoaded);
  169. Storage.getKeyValue("refresh", window.valueLoaded);
  170. Storage.getKeyValue("longitude", window.valueLoaded);
  171. Storage.getKeyValue("latitude", window.valueLoaded);
  172. Storage.getKeyValue("useLightTheme", window.valueLoaded);
  173. //Storage.getKeyValue("useSound", window.valueLoaded);
  174. Storage.getKeyValue("screenName", window.valueLoaded);
  175. Storage.getKeyValue("userId", window.valueLoaded);
  176. Storage.getKeyValue("pocketUsername", window.valueLoaded);
  177. Storage.getKeyValue("pocketPassword", window.valueLoaded);
  178. //createPositionSource();
  179. locationTimer.start();
  180. loadMoreTimer.start();
  181. screenSizeChecker.start();
  182. }
  183. function valueLoaded(key, value) {
  184. if(key=="latitude") {
  185. window.lat = value;
  186. } else if(key=="longitude") {
  187. window.lon = value;
  188. } else if(key=="pocketUsername") {
  189. settingsDialog.setPocketUsername(value);
  190. } else if(key=="pocketPassword") {
  191. settingsDialog.setPocketPassword(value);
  192. } else if(key=="lastHomeID") {
  193. Script.setLastHomeID(value);
  194. } else if(key=="lastMentionID") {
  195. Script.setLastMentionID(value);
  196. } else if(key=="useListView") {
  197. if(value=="yes") {
  198. settingsDialog.useList = true;
  199. } else {
  200. settingsDialog.useList = false;
  201. }
  202. } else if(key=="useLightTheme") {
  203. if(value=="yes") {
  204. settingsDialog.useLightTheme = true;
  205. theme.switchTheme();
  206. } else {
  207. settingsDialog.useLightTheme = false;
  208. }
  209. } else if(key=="useSound") {
  210. if(value=="yes") {
  211. settingsDialog.useSound = true;
  212. console.log("Sound activated");
  213. // birdSound.muted = false;
  214. // birdSound.volume = 0.4;
  215. } else {
  216. // birdSound.volume = 0;
  217. // birdSound.muted = true;
  218. console.log("Sound deactivated");
  219. settingsDialog.useSound = false;
  220. }
  221. } else if(key=="refresh") {
  222. try {
  223. settingsDialog.autoRefresh = value;
  224. if(value!="0") {
  225. autoRefreshTimer.interval = parseInt(value) * 1000 * 60;
  226. if(autoRefreshTimer.interval<59000) {
  227. autoRefreshTimer.interval = 300000;
  228. }
  229. autoRefreshTimer.start();
  230. }
  231. } catch(exp) {
  232. console.log("Error while starting auto refresh");
  233. }
  234. } else if(key=="screenName") {
  235. if((typeof(value)=="undefined" || value=="") && authorizeWindow.visible==false) {
  236. Script.resetTokens();
  237. Script.getTwitterTimeAndToken();
  238. //Script.requestToken();
  239. authorizeWindow.visible = true;
  240. } else {
  241. hideSplashTimer.start();
  242. Script.currentScreenName = value;
  243. Script.myUsername = value;
  244. Script.getTwitterTimeAndLogin();
  245. //Script.login();
  246. }
  247. } else if(key=="userId") {
  248. Script.currentUserID = value;
  249. }
  250. }
  251. function loadTimelineIndex() {
  252. if(window.timelineIndex==0) {
  253. Script.loadHome();
  254. } else if(window.timelineIndex==1) {
  255. Script.loadMentions();
  256. } else {
  257. Script.loadDirectMessages();
  258. }
  259. }
  260. function logout() {
  261. welcomePage.showButtons = false;
  262. Script.showLogin();
  263. }
  264. ListModel {
  265. id: tweetsModel
  266. }
  267. ListModel {
  268. id: hashtagActionsModel
  269. }
  270. Rectangle {
  271. id: container
  272. property bool flipped: false;
  273. property int angle: 180;
  274. property int xAxis: 0
  275. property int yAxis: 1
  276. x: 0
  277. y: -parent.height
  278. width: parent.width
  279. height: parent.height
  280. opacity: 1
  281. Rectangle {
  282. id: tweetsContainer
  283. color: "#333"
  284. anchors.fill: parent
  285. x: parent.width
  286. states:
  287. State {
  288. name: "shown"
  289. PropertyChanges {
  290. target: tweetsContainer
  291. x: 0
  292. }
  293. PropertyChanges {
  294. target: tweetsContainer
  295. opacity: 1
  296. }
  297. }
  298. transitions: Transition {
  299. SequentialAnimation {
  300. ScriptAction {
  301. script: {
  302. welcomePage.state = "hidden";
  303. }
  304. }
  305. PropertyAnimation {
  306. target: tweetsContainer
  307. properties: "x"
  308. duration: 600
  309. easing.type: "OutQuad"
  310. }
  311. }
  312. }
  313. Rectangle {
  314. width: parent.width
  315. height: parent.height //- 80
  316. color: theme.tweetsBackground // "#2d2f33" // "#3d3f48" // #444d50" // "#050505" // "#999999"
  317. Timer {
  318. id: loadMoreTimer
  319. interval: 555
  320. repeat: true
  321. onTriggered: {
  322. if((tweetsList.visible && tweetsList.atYEnd) || (tweetsGrid.visible && tweetsGrid.atYEnd)) {
  323. if(tweetsModel.count>0) {
  324. var last = tweetsModel.get(tweetsModel.count-1);
  325. if(last.status.indexOf("Load more...")>=0) {
  326. console.log("Triggered load more...");
  327. last.status = qsTr("Please wait...") + "<br/><br/><br/><br/>";
  328. Script.loadNextPage();
  329. }
  330. }
  331. }
  332. if(tweetsList.visible && tweetsList.atYBeginning) {
  333. if(!pullLabel.visible && tweetsList.contentY<-2) {
  334. pullLabel.visible = true;
  335. } else if(pullLabel.visible && tweetsList.contentY>=0) {
  336. pullLabel.text = qsTr("Pull down to refresh");
  337. pullLabel.visible = false;
  338. }
  339. if(tweetsList.contentY<-50) {
  340. pullLabel.text = qsTr("Release to refresh");
  341. }
  342. } else if(tweetsGrid.visible && tweetsGrid.atYBeginning) {
  343. if(!pullLabel.visible && tweetsGrid.contentY<-2) {
  344. pullLabel.visible = true;
  345. } else if(pullLabel.visible && tweetsGrid.contentY>=0) {
  346. pullLabel.text = qsTr("Pull down to refresh");
  347. pullLabel.visible = false;
  348. }
  349. if(tweetsGrid.contentY<-50) {
  350. pullLabel.text = qsTr("Release to refresh");
  351. }
  352. }
  353. }
  354. }
  355. Item {
  356. id: pullText
  357. width: window.width
  358. height: 0
  359. Text {
  360. id: pullLabel
  361. text: qsTr("Pull down to refresh")
  362. font.pixelSize: window.tweetFontSize
  363. font.bold: true
  364. visible: false
  365. width: window.width
  366. // anchors.top: window.top
  367. // anchors.horizontalCenter: window.horizontalCenter
  368. anchors.top: parent.top
  369. anchors.horizontalCenter: parent.horizontalCenter
  370. horizontalAlignment: Text.AlignHCenter
  371. color: theme.tweetTextColor
  372. }
  373. }
  374. ListView {
  375. id: tweetsList
  376. visible: settingsDialog.useList ? true : (parent.width>parent.height ? false : true)
  377. anchors.fill: parent
  378. model: tweetsModel
  379. delegate: tweetsDelegate
  380. header: pullText
  381. onMovingChanged: {
  382. if(tweetsList.atYBeginning && pullLabel.text==qsTr("Release to refresh")) {
  383. // Refresh
  384. pullLabel.text = qsTr("Pull to refresh");
  385. pullLabel.visible = false;
  386. Script.autoFresh();
  387. }
  388. }
  389. }
  390. GridView {
  391. id: tweetsGrid
  392. visible: settingsDialog.useList ? false : (parent.width>parent.height ? true : false)
  393. cellWidth: parent.width/window.gridColumns - 1
  394. cellHeight: window.tweetHeight;
  395. anchors.fill: parent
  396. model: tweetsModel
  397. delegate: tweetsDelegate
  398. header: pullText
  399. onMovementEnded: {
  400. if(tweetsGrid.atYBeginning && pullLabel.text==qsTr("Release to refresh")) {
  401. // Refresh
  402. pullLabel.text = qsTr("Pull to refresh");
  403. pullLabel.visible = false;
  404. Script.autoFresh();
  405. }
  406. }
  407. }
  408. // CustomGestureArea {
  409. // anchors.fill: parent
  410. // onSwipeRight: {
  411. // timelineIndex--;
  412. // if(timelineIndex<0) {
  413. // timelineIndex = 2;
  414. // }
  415. // loadTimelineIndex();
  416. // }
  417. // onSwipeLeft: {
  418. // timelineIndex++;
  419. // if(timelineIndex>2) {
  420. // timelineIndex = 0;
  421. // }
  422. // loadTimelineIndex();
  423. // }
  424. // }
  425. }
  426. StatusDialog {
  427. id: statusDialog
  428. height: 140
  429. onClicked: {
  430. console.log("Clicked, status: " + text);
  431. console.log("Clicked, replyID: " + reply);
  432. console.log("Clicked, DM: " + dm);
  433. Script.updateStatus(text, reply, dm, lat, lon);
  434. }
  435. }
  436. SearchDialog {
  437. id: searchDialog
  438. onClicked: {
  439. console.log("search for: " + searchText);
  440. if(searchDialog.saveSearch) {
  441. Script.saveSearch(query, lat, lon);
  442. } else {
  443. Script.doSearch(query, lat, lon);
  444. }
  445. }
  446. }
  447. ListsDialog {
  448. id: listsDialog
  449. onClicked: {
  450. console.log("list selected: " + action);
  451. Script.loadList(action);
  452. }
  453. }
  454. TrendsDialog {
  455. y: 0
  456. id: trendsDialog
  457. onClicked: {
  458. console.log("trend selected: " + action);
  459. Script.doSearch(action);
  460. }
  461. }
  462. SearchesDialog {
  463. id: searchesDialog
  464. onClicked: {
  465. console.log("search selected: " + action);
  466. Script.doSearch(action);
  467. }
  468. onRemoveSearch: {
  469. console.log("remove " + searchID);
  470. Script.removeSearch(searchID);
  471. }
  472. }
  473. Item {
  474. height: 50
  475. width: 50
  476. y: parent.height - height
  477. anchors.horizontalCenter: parent.horizontalCenter
  478. Image {
  479. id: showBarButton
  480. anchors.bottom: parent.bottom
  481. anchors.horizontalCenter: parent.horizontalCenter
  482. source: "pics/up.png"
  483. }
  484. MouseArea {
  485. id: showBarMouseArea
  486. anchors.fill: parent
  487. onClicked: {
  488. menubar.state = "shown";
  489. }
  490. }
  491. }
  492. CustomToolbar {
  493. id: menubar
  494. Row {
  495. y: 10
  496. anchors.horizontalCenter: parent.horizontalCenter
  497. spacing: window.iconSpacing
  498. CustomToolbarIcon {
  499. id: homeIcon
  500. iconImage: "../pics/toolbar/home_icon&32.png"
  501. iconText: qsTr("Home")
  502. showNewIndicator: false
  503. onClicked: {
  504. window.timelineIndex = 0;
  505. Script.loadHome();
  506. container.flipped = false;
  507. }
  508. }
  509. CustomToolbarIcon {
  510. id: mentionsIcon
  511. iconImage: "../pics/toolbar/mentions_icon&32.png"
  512. iconText: qsTr("Mentions")
  513. showNewIndicator: false
  514. onClicked: {
  515. window.timelineIndex = 1;
  516. Script.loadMentions();
  517. container.flipped = false;
  518. }
  519. }
  520. CustomToolbarIcon {
  521. id: directIcon
  522. iconImage: "../pics/toolbar/mail_2_icon&32.png"
  523. iconText: qsTr("Messages")
  524. onClicked: {
  525. window.timelineIndex = 2;
  526. Script.loadDirectMessages();
  527. }
  528. }
  529. CustomToolbarIcon {
  530. id: statusIcon
  531. iconImage: "../pics/toolbar/spechbubble_icon&32.png"
  532. iconText: qsTr("Status")
  533. onClicked: {
  534. if(statusDialog.state=="shown") {
  535. statusDialog.state = "hidden";
  536. } else {
  537. statusDialog.state = "shown";
  538. console.log("Resetting status text");
  539. statusDialog.statusText = "-";
  540. statusDialog.statusText = "";
  541. statusDialog.replyName = "";
  542. statusDialog.replyID = "";
  543. statusDialog.dmUserID = "";
  544. }
  545. }
  546. }
  547. Image {
  548. visible: (window.width>window.height ? true : false)
  549. source: "pics/down.png"
  550. opacity: !hideToolbarMouseArea.pressed ? 1 : 0.5
  551. anchors.verticalCenter: parent.verticalCenter
  552. MouseArea {
  553. id: hideToolbarMouseArea
  554. anchors.fill: parent
  555. onClicked: {
  556. menubar.state = "hidden";
  557. }
  558. }
  559. }
  560. CustomToolbarIcon {
  561. id: searchIcon
  562. visible: (window.width>window.height ? true : false)
  563. iconImage: "../pics/toolbar/zoom_icon&32.png"
  564. iconText: qsTr("Search")
  565. onClicked: {
  566. if(searchDialog.state == "Shown") {
  567. searchDialog.state = "hidden";
  568. } else {
  569. searchDialog.state = "Shown";
  570. }
  571. }
  572. Behavior on visible {
  573. ScriptAction {
  574. script: menubar.state = "shown";
  575. }
  576. }
  577. }
  578. CustomToolbarIcon {
  579. id: starIcon
  580. visible: (window.width>window.height ? true : false)
  581. iconImage: "../pics/toolbar/heart_icon&32.png"
  582. iconText: qsTr("Favourites")
  583. onClicked: Script.loadFavourites();
  584. }
  585. CustomToolbarIcon {
  586. visible: (window.width>window.height ? true : false)
  587. iconImage: "../pics/toolbar/refresh_icon&32.png"
  588. iconText: qsTr("Refresh")
  589. onClicked: {
  590. container.flipped = false;
  591. Script.autoFresh();
  592. }
  593. }
  594. CustomToolbarIcon {
  595. iconImage: "../pics/toolbar/align_just_icon&32.png"
  596. iconText: qsTr("More")
  597. onClicked: {
  598. container.flipped = false;
  599. if(mainMenu.state=="shown") {
  600. mainMenu.state = "hidden";
  601. } else {
  602. mainMenu.state = "shown";
  603. Script.loadRateLimit();
  604. }
  605. }
  606. }
  607. }
  608. } // Toolbar
  609. } // Tweets container
  610. states: [
  611. State {
  612. name: "initialized"
  613. PropertyChanges {
  614. target: container
  615. y: container.height
  616. }
  617. },
  618. State {
  619. name: "hidden"
  620. PropertyChanges {
  621. target: container
  622. x: 0 - container.width
  623. }
  624. PropertyChanges {
  625. target: container
  626. y: 0
  627. }
  628. PropertyChanges {
  629. target: detailsFlipable
  630. x: 0
  631. }
  632. },
  633. State {
  634. name: "shown"
  635. PropertyChanges {
  636. target: container
  637. x: 0
  638. y: 0
  639. }
  640. PropertyChanges {
  641. target: detailsFlipable
  642. x: container.width
  643. }
  644. //when: !detailsFlipable.flipped
  645. }
  646. ]
  647. transitions: Transition {
  648. SequentialAnimation {
  649. ScriptAction {
  650. script: welcomePage.visible = false;
  651. }
  652. ParallelAnimation {
  653. //NumberAnimation { target: welcomePage; property: "y"; duration: 400; }
  654. //NumberAnimation { target: containerRotation; property: "angle"; duration: 600; }
  655. //NumberAnimation { target: detailsShowRotation; property: "angle"; duration: 600; }
  656. NumberAnimation { target: container; property: "x"; duration: 600; easing.type: "InOutCubic" }
  657. NumberAnimation { target: container; property: "y"; duration: 10; easing.type: "InOutCubic" }
  658. NumberAnimation { target: detailsFlipable; property: "x"; duration: 600; easing.type: "InOutCubic" }
  659. }
  660. }
  661. }
  662. }
  663. CustomTheme {
  664. id: theme
  665. }
  666. Flipable {
  667. id: detailsFlipable
  668. width: parent.width
  669. height: parent.height
  670. property bool flipped: false
  671. x: parent.width
  672. front:
  673. Rectangle {
  674. anchors.fill: parent
  675. color: theme.detailBG // "#999"
  676. Flickable {
  677. //id: tweetDetailsContainer
  678. id: tweetDetailsFlickable
  679. anchors.fill: parent
  680. contentWidth: parent.width
  681. contentHeight: parent.height>detailsColumn.y + detailsColumn.height ? parent.height : detailsColumn.y + detailsColumn.height + 20
  682. //color: "#ddd"
  683. Rectangle {
  684. id: tweetDetailsContainer
  685. opacity: 1
  686. color: theme.detailBG
  687. width: parent.width
  688. height: parent.height>detailsColumn.y + detailsColumn.height ? parent.height : detailsColumn.y + detailsColumn.height + 20
  689. property string username: ""
  690. property string tweetID: ""
  691. property bool isFavourite: false
  692. property bool isMine: false
  693. property string replyID: ""
  694. property string replyBlock: ""
  695. Column {
  696. id: detailsColumn
  697. //anchors.fill: parent
  698. y: 20
  699. x: 10
  700. width: parent.width - 20
  701. /*height: backButton.y + backButton.height*/
  702. spacing: 20
  703. Row {
  704. spacing: 20
  705. width: parent.width
  706. Image {
  707. id: tweetProfileImage
  708. source: ""
  709. width: 72
  710. height: 72
  711. smooth: true
  712. }
  713. Column {
  714. anchors.verticalCenter: parent.verticalCenter
  715. width: parent.width - 102
  716. Text {
  717. id: selectedTweetSource
  718. width: parent.width
  719. color: theme.dialogTextColor // "#ddd"
  720. text: "..."
  721. wrapMode: Text.WordWrap
  722. font.pixelSize: 18
  723. }
  724. Text {
  725. id: selectedTweetAge
  726. color: theme.dialogTextColor // "#ddd"
  727. text: qsTr("Moment ago")
  728. wrapMode: Text.WordWrap
  729. font.pixelSize: 18
  730. }
  731. }
  732. }
  733. Rectangle {
  734. id: tweetTextContainer
  735. radius: 5
  736. width: parent.width
  737. height: tweetTextAndPreview.height + 20
  738. color: theme.dialogTextBG // "#eee"
  739. Column {
  740. id: tweetTextAndPreview
  741. width: parent.width
  742. spacing: 10
  743. y: 10
  744. anchors.horizontalCenter: parent.horizontalCenter
  745. Text {
  746. id: selectedTweetText
  747. font.pixelSize: 22
  748. textFormat: Text.PlainText
  749. text: "..."
  750. color: theme.dialogInfoTextColor // "#333"
  751. wrapMode: Text.Wrap
  752. x: parent.x + 4
  753. width: parent.width - 8
  754. }
  755. Image {
  756. id: previewImage
  757. source: ""
  758. width: 200
  759. height: 200
  760. anchors.horizontalCenter: parent.horizontalCenter
  761. }
  762. }
  763. }
  764. Rectangle {
  765. id: replyTextContainer
  766. radius: 5
  767. width: parent.width
  768. height: replyTextAndPreview.height + 20
  769. color: theme.dialogTextBG
  770. visible: false
  771. property string replyText: "Loading..."
  772. Column {
  773. id: replyTextAndPreview
  774. width: parent.width
  775. spacing: 10
  776. y: 10
  777. anchors.horizontalCenter: parent.horizontalCenter
  778. Text {
  779. id: replyTweetText
  780. font.pixelSize: 16
  781. //textFormat: Text..PlainText
  782. text: "<span><b>" + qsTr("In reply to") + " </b>" + replyTextContainer.replyText + "</span>"
  783. color: theme.dialogInfoTextColor // "#444"
  784. wrapMode: Text.Wrap
  785. x: parent.x + 4
  786. width: parent.width - 8
  787. }
  788. }
  789. }
  790. Rectangle {
  791. id: hashtagsContainer
  792. radius: 5
  793. color: theme.dialogButtonAreaBG // "#999"
  794. width: parent.width
  795. height: hashtagActions.height+10
  796. GridView {
  797. id: hashtagActions
  798. interactive: false
  799. x: 10
  800. y: 10
  801. cellWidth: (parent.width-10)/2
  802. cellHeight: 60
  803. model: hashtagActionsModel
  804. width: parent.width
  805. height: 100
  806. delegate: hashtagDelegate
  807. }
  808. }
  809. Rectangle {
  810. radius: 5
  811. color: theme.dialogButtonAreaBG //"#999"
  812. //y: tweetTextContainer.y + tweetTextContainer.height + 20
  813. width: parent.width
  814. height: tweetActions.height+10
  815. Column {
  816. id: tweetActions
  817. x: 10
  818. y: 10
  819. //spacing: 2
  820. width: parent.width - 10
  821. Row {
  822. width: parent.width
  823. height: 60
  824. spacing: 10
  825. visible: (tweetDetailsContainer.replyID.length>0 || tweetDetailsContainer.isMine)
  826. Button {
  827. id: showOriginalButton
  828. visible: tweetDetailsContainer.replyID.length>0 ? true : false
  829. label: qsTr("Show original")
  830. height: 50
  831. width: parent.width/2-10
  832. onClicked: {
  833. Script.loadSingleTweet( tweetDetailsContainer.replyID );
  834. }
  835. }
  836. Button {
  837. id: deleteMyTweetButton
  838. visible: tweetDetailsContainer.isMine
  839. opacity: tweetDetailsContainer.replyID.length>0 ? 1 : 0
  840. label: qsTr("Delete")
  841. height: 50
  842. width: parent.width/2-10
  843. onClicked: {
  844. Script.destroy(tweetDetailsContainer.tweetID);
  845. container.state = "shown";
  846. }
  847. }
  848. }
  849. Row {
  850. width: parent.width
  851. height: 60
  852. spacing: 10
  853. Button {
  854. label: qsTr("Translate to english")
  855. height: 50
  856. width: parent.width-10
  857. onClicked: {
  858. console.log("Translating...");
  859. AzureTranslate.translate(selectedTweetText.text, selectedTweetText);
  860. }
  861. }
  862. }
  863. }
  864. }
  865. }
  866. }
  867. }
  868. CustomToolbar {
  869. id: detailsToolbar
  870. Row {
  871. y: 10
  872. anchors.horizontalCenter: parent.horizontalCenter
  873. spacing: window.iconSpacing
  874. CustomToolbarIcon {
  875. id: detailsBackIcon
  876. iconImage: "../pics/toolbar/arrow_left_icon&32.png"
  877. iconText: qsTr("Back")
  878. onClicked: {
  879. container.state = "shown";
  880. }
  881. }
  882. CustomToolbarIcon {
  883. iconImage: "../pics/toolbar/spechbubble_2_icon&32.png"
  884. iconText: qsTr("Reply")
  885. onClicked: {
  886. container.state = "shown";
  887. statusDialog.statusText = Script.parseUsernames( "@" + tweetDetailsContainer.username + " " + selectedTweetText.text);
  888. statusDialog.replyName = "@" + tweetDetailsContainer.username;
  889. statusDialog.replyID = tweetDetailsContainer.tweetID;
  890. if(window.timelineIndex!=2) {
  891. statusDialog.dmUserID = "";
  892. } else {
  893. statusDialog.dmUserID = tweetDetailsContainer.username;
  894. }
  895. statusDialog.state = "shown";
  896. }
  897. }
  898. CustomToolbarIcon {
  899. iconImage: "../pics/toolbar/refresh_icon&32.png"
  900. iconText: qsTr("Retweet")
  901. onClicked: {
  902. retweetDialog.visible = true;
  903. }
  904. }
  905. CustomToolbarIcon {
  906. iconImage: "../pics/toolbar/star_fav_icon&32.png"
  907. iconText: tweetDetailsContainer.isFavourite ? qsTr("Unfavourite") : qsTr("Favourite")
  908. onClicked: {
  909. if(tweetDetailsContainer.isFavourite) {
  910. Script.unfavourite(tweetDetailsContainer.tweetID);
  911. } else {
  912. Script.favourite(tweetDetailsContainer.tweetID);
  913. }
  914. tweetDetailsContainer.isFavourite = false;
  915. }
  916. }
  917. CustomToolbarIcon {
  918. iconImage: "../pics/toolbar/user_icon&32.png"
  919. iconText: qsTr("Profile")
  920. onClicked: {
  921. // Show profile dialog
  922. profileDialog.userID = "";
  923. profileDialog.profileImageURL = "";
  924. profileDialog.username = "";
  925. profileDialog.userURL = "";
  926. profileDialog.userLocation = "";
  927. profileDialog.followersCount = "0"
  928. profileDialog.followingCount = "0"
  929. profileDialog.tweetCount = "0"
  930. detailsFlipable.flipped = true;
  931. Script.fillProfile();
  932. }
  933. }
  934. }
  935. } // Custom toolbar
  936. }
  937. back:
  938. ProfileDialog {
  939. id: profileDialog
  940. //transform: Scale { origin.x: width/2; origin.y: height/2; xScale: -1}
  941. onGoBack: {
  942. detailsFlipable.flipped = false;
  943. //container.state = "shown";
  944. }
  945. onShowTweets: {
  946. detailsFlipable.flipped = false;
  947. container.state = "shown";
  948. Script.loadCurrentUserTweets();
  949. }
  950. onFollow: {
  951. Script.follow();
  952. }
  953. onUnfollow: {
  954. Script.unfollow();
  955. }
  956. onDirectTweet: {
  957. console.log("DM to " + userID + " and " + username);
  958. detailsFlipable.flipped = false;
  959. container.state = "shown";
  960. statusDialog.statusText = Script.parseUsernames( "@" + username + " ");
  961. statusDialog.replyID = "";
  962. statusDialog.dmUserID = userID;
  963. statusDialog.state = "shown";
  964. }
  965. onSendMsg: {
  966. console.log("msg to " + userID + " and " + username);
  967. detailsFlipable.flipped = false;
  968. container.state = "shown";
  969. statusDialog.statusText = Script.parseUsernames( "@" + username + " ");
  970. statusDialog.replyID = "";
  971. statusDialog.state = "shown";
  972. }
  973. }
  974. transform: [
  975. Rotation {
  976. id: detailsFlipableRotation
  977. origin.x: detailsFlipable.width/2
  978. origin.y: detailsFlipable.height/2
  979. axis.x: 1; axis.y: 0; axis.z: 0 // set axis.y to 1 to rotate around y-axis
  980. angle: 0 // the default angle
  981. }
  982. ]
  983. states: State {
  984. name: "back"
  985. PropertyChanges { target: detailsFlipableRotation; angle: 180 }
  986. when: detailsFlipable.flipped
  987. }
  988. transitions: Transition {
  989. ParallelAnimation {
  990. NumberAnimation { target: detailsFlipableRotation; property: "angle"; duration: 800; easing.type: "InOutCubic" }
  991. SequentialAnimation {
  992. NumberAnimation { target: container; property: "scale"; to: 0.75; duration: 400 }
  993. NumberAnimation { target: container; property: "scale"; to: 1.0; duration: 400 }
  994. }
  995. }
  996. }
  997. }
  998. RetweetDialog {
  999. id: retweetDialog
  1000. visible: false
  1001. onRetweetWithEdit: {
  1002. container.state = "shown";
  1003. var txt = "RT @" + tweetDetailsContainer.username + " " + selectedTweetText.text;
  1004. console.log("Text: " + txt);
  1005. statusDialog.statusText = txt;
  1006. statusDialog.replyID = "";
  1007. statusDialog.dmUserID = "";
  1008. statusDialog.state = "shown";
  1009. }
  1010. onRetweetInstantly: {
  1011. Script.instantretweet(tweetDetailsContainer.tweetID);
  1012. }
  1013. }
  1014. MainMenu {
  1015. id: mainMenu
  1016. onClicked: {
  1017. if(action=="Search") {
  1018. searchDialog.state = "Shown";
  1019. } else if(action=="MyTweets") {
  1020. Script.loadUserTweets();
  1021. } else if(action=="Friends") {
  1022. Script.loadFriends();
  1023. } else if(action=="Direct") {
  1024. Script.loadDirectMessages();
  1025. } else if(action=="Followers") {
  1026. Script.loadFollowers();
  1027. } else if(action=="Retweets") {
  1028. Script.loadRetweets();
  1029. } else if(action=="Favourites") {
  1030. Script.loadFavourites();
  1031. } else if(action=="Lists") {
  1032. listsDialog.state = "Shown";
  1033. Script.loadAndShowLists(listsDialog.listModel);
  1034. } else if(action=="SavedSearches") {
  1035. searchesDialog.state = "Shown";
  1036. Script.loadSavedSearches(searchesDialog.searchesModel);
  1037. } else if(action=="Settings") {
  1038. settingsDialog.state = "Shown";
  1039. } else if(action=="Trends") {
  1040. trendsDialog.state = "Shown";
  1041. Script.loadTrends(trendsDialog.trendsModel);
  1042. } else if(action=="Logout") {
  1043. //container.state = "hidden";
  1044. container.visible = false;
  1045. tweetsModel.clear();
  1046. Script.showLogin();
  1047. } else {
  1048. console.log("Unknown action: " + action);
  1049. }
  1050. }
  1051. }
  1052. SettingsDialog {
  1053. id: settingsDialog
  1054. onClicked: {
  1055. console.log("Saving settings...");
  1056. var useList = "no";
  1057. if(settingsDialog.useList===true) {
  1058. useList = "yes";
  1059. }
  1060. var useSound = "no";
  1061. // birdSound.muted = true;
  1062. if(settingsDialog.useSound===true) {
  1063. useSound = "yes";
  1064. // birdSound.muted = false;
  1065. }
  1066. var useLightTheme = "no";
  1067. if(settingsDialog.useLightTheme===true) {
  1068. useLightTheme = "yes";
  1069. }
  1070. var refresh = settingsDialog.autoRefresh;
  1071. try {
  1072. if(refresh!="0") {
  1073. autoRefreshTimer.interval = parseInt(refresh) * 60 * 1000;
  1074. autoRefreshTimer.start();
  1075. } else {
  1076. autoRefreshTimer.stop();
  1077. }
  1078. } catch(exp) {
  1079. console.log("Error while starting auto refresh");
  1080. }
  1081. Storage.setKeyValue("pocketUsername", pocketUsername);
  1082. Storage.setKeyValue("pocketPassword", pocketPassword);
  1083. Storage.setKeyValue("useListView", useList);
  1084. Storage.setKeyValue("useLightTheme", useLightTheme);
  1085. Storage.setKeyValue("refresh", refresh);
  1086. Storage.setKeyValue("useSound", useSound);
  1087. }
  1088. }
  1089. Item {
  1090. id: minimize
  1091. height: 48
  1092. width: 48
  1093. MouseArea {
  1094. anchors.fill: parent
  1095. onClicked: {
  1096. console.log("Minimizing");
  1097. windowHelper.minimize();
  1098. }
  1099. }
  1100. }
  1101. LoginDialog {
  1102. id: welcomePage
  1103. onExit: {
  1104. Qt.quit();
  1105. }
  1106. }
  1107. Timer {
  1108. id: loginTimer
  1109. interval: 100
  1110. repeat: false
  1111. onTriggered: {
  1112. console.log("LoginTimer triggered...");
  1113. welcomePage.state = "hidden";
  1114. authorizeWindow.visible = false;
  1115. Script.login();
  1116. }
  1117. }
  1118. AuthorizeDialog {
  1119. id: authorizeWindow
  1120. visible: false
  1121. onFinished: {
  1122. console.log("Finished with URL " + url);
  1123. if(url.indexOf("/authorize?")<0) {
  1124. if(authorizeWindow.visible==true) {
  1125. console.log("Hiding authorize window...")
  1126. authorizeWindow.visible = false;
  1127. container.state = "shown";
  1128. container.visible = true;
  1129. loginTimer.start();
  1130. }
  1131. } else {
  1132. authorizeWindow.visible = true;
  1133. }
  1134. console.log("Authorize window visible=" + authorizeWindow.visible);
  1135. }
  1136. }
  1137. // Item { // Uncomment for MeeGo and Symbian
  1138. Rectangle { // Uncomment for Maemo
  1139. id: waiting
  1140. x: 0
  1141. y: 0
  1142. width: waitItems.width+20
  1143. height: waitItems.height+20
  1144. // Comment following
  1145. color: "#bbb" // Uncomment for Maemo
  1146. radius: 5 // Uncomment for Maemo
  1147. smooth: true
  1148. opacity: 0.9
  1149. state: "hidden"
  1150. // BusyIndicator { // Uncomment for MeeGo and Symbian
  1151. // id: busyIndicator
  1152. // running: true
  1153. // x: window.width/2 - width/2
  1154. // y: window.height/2
  1155. // // These are for Symbian
  1156. // //width: 100
  1157. // //height: 100
  1158. // // This is for MeeGo
  1159. // platformStyle: BusyIndicatorStyle { size: "large"; inverted: theme.isBlack; }
  1160. // }
  1161. Row {
  1162. id: waitItems
  1163. anchors.horizontalCenter: parent.horizontalCenter
  1164. anchors.verticalCenter: parent.verticalCenter
  1165. spacing: 10
  1166. // Hide if BusyIndicator is used (MeeGo and Symbian)
  1167. // visible: false
  1168. Image {
  1169. source: "pics/clock.png"
  1170. }
  1171. Text {
  1172. id: waitingText
  1173. text: qsTr("Please wait...")
  1174. color: "#000"
  1175. font.pixelSize: 22
  1176. anchors.verticalCenter: parent.verticalCenter
  1177. }
  1178. }
  1179. states:
  1180. State {
  1181. name: "hidden"
  1182. PropertyChanges {
  1183. target: waiting
  1184. y: 0 - waiting.height - 1
  1185. }
  1186. }
  1187. State {
  1188. name: "shown"
  1189. PropertyChanges {
  1190. target: waiting
  1191. y: 10
  1192. }
  1193. }
  1194. transitions: [
  1195. Transition {
  1196. SequentialAnimation {
  1197. // ScriptAction { // Uncomment for MeeGo
  1198. // script: {
  1199. // busyIndicator.visible = true;
  1200. // }
  1201. // }
  1202. PropertyAnimation { // Uncomment for Maemo
  1203. target: waiting
  1204. properties: "y"
  1205. duration: 100
  1206. easing.type: "InOutCubic"
  1207. }
  1208. }
  1209. },
  1210. Transition {
  1211. to: "hidden"
  1212. SequentialAnimation {
  1213. PropertyAnimation { // Uncomment for Maemo
  1214. target: waiting
  1215. properties: "y"
  1216. duration: 80
  1217. easing.type: "InOutCubic"
  1218. }
  1219. // ScriptAction { // Uncomment for MeeGo
  1220. // script: {
  1221. // waitingText.text = "Please wait...";
  1222. // busyIndicator.visible = false;
  1223. // }
  1224. // }
  1225. }
  1226. }
  1227. ]
  1228. }
  1229. Rectangle {
  1230. id: doneIndicator
  1231. x: 10
  1232. y: 10
  1233. width: doneItems.width+30
  1234. height: doneItems.height+20
  1235. color: "#555"
  1236. radius: 5
  1237. opacity: 0.9
  1238. smooth: true
  1239. state: "hidden"
  1240. Row {
  1241. id: doneItems
  1242. anchors.horizontalCenter: parent.horizontalCenter
  1243. anchors.verticalCenter: parent.verticalCenter
  1244. spacing: 10
  1245. Image {
  1246. source: "pics/accepted_48.png"
  1247. }
  1248. Text {
  1249. id: doneText
  1250. text: qsTr("Done")
  1251. color: "#eee"
  1252. font.pixelSize: 22
  1253. anchors.verticalCenter: parent.verticalCenter
  1254. }
  1255. }
  1256. states:
  1257. State {
  1258. name: "hidden"
  1259. PropertyChanges {
  1260. target: doneIndicator
  1261. y: 0 - doneIndicator.height - 1
  1262. }
  1263. }
  1264. State {
  1265. name: "shown"
  1266. PropertyChanges {
  1267. target: doneIndicator
  1268. y: 10
  1269. }
  1270. }
  1271. transitions: [
  1272. Transition {
  1273. SequentialAnimation {
  1274. PropertyAnimation {
  1275. target: doneIndicator
  1276. properties: "y"
  1277. duration: 200
  1278. easing.type: "InOutCubic"
  1279. }
  1280. PropertyAnimation {
  1281. target: doneIndicator
  1282. properties: "y"
  1283. duration: 2000
  1284. }
  1285. ScriptAction {
  1286. script: {
  1287. doneIndicator.state = "hidden";
  1288. }
  1289. }
  1290. }
  1291. }
  1292. ]
  1293. }
  1294. Rectangle {
  1295. id: errorIndicator
  1296. x: 10
  1297. y: 10
  1298. property string reason: ""
  1299. width: window.width - 20
  1300. height: errorItems.height+20
  1301. color: "#555"
  1302. radius: 5
  1303. smooth: true
  1304. state: "hidden"
  1305. Row {
  1306. id: errorItems
  1307. anchors.horizontalCenter: parent.horizontalCenter
  1308. anchors.verticalCenter: parent.verticalCenter
  1309. spacing: 10
  1310. width: parent.width
  1311. Image {
  1312. id: errIcon
  1313. source: "pics/error_48.png"
  1314. }
  1315. Column {
  1316. width: parent.width - errIcon.width - 30
  1317. spacing: 10
  1318. Text {
  1319. id: errorText
  1320. text: qsTr("Oops... Something unexpected happened.")
  1321. color: "#eee"
  1322. wrapMode: Text.WordWrap
  1323. font.pixelSize: 18
  1324. width: parent.width
  1325. }
  1326. Text {
  1327. text: errorIndicator.reason
  1328. color: "#ccc"
  1329. wrapMode: Text.WordWrap
  1330. font.pixelSize: 18
  1331. width: parent.width
  1332. }
  1333. }
  1334. }
  1335. states:
  1336. State {
  1337. name: "hidden"
  1338. PropertyChanges {
  1339. target: errorIndicator
  1340. y: 0 - errorIndicator.height - 1
  1341. }
  1342. }
  1343. State {
  1344. name: "shown"
  1345. PropertyChanges {
  1346. target: errorIndicator
  1347. y: 10
  1348. }
  1349. }
  1350. transitions: Transition {
  1351. SequentialAnimation {
  1352. ScriptAction {
  1353. script: {
  1354. waiting.state = "hidden";
  1355. doneIndicator.state = "hidden";
  1356. }
  1357. }
  1358. PropertyAnimation {
  1359. target: errorIndicator
  1360. properties: "y"
  1361. duration: 200
  1362. easing.type: "InOutCubic"
  1363. }
  1364. PropertyAnimation {
  1365. target: errorIndicator
  1366. properties: "y"
  1367. duration: 5000
  1368. }
  1369. ScriptAction {
  1370. script: {
  1371. errorIndicator.state = "hidden";
  1372. }
  1373. }
  1374. }
  1375. }
  1376. }
  1377. Component {
  1378. id: tweetsDelegate
  1379. Item {
  1380. //width: parent.width
  1381. //height: tweeter.height + tweetTitle.height + tweetDateLabel.height + 16//window.tweetHeight // tweeter.height + tweetTitle.height + tweetDateLabel.height + 16 // tweetSummary.height + 12 // (tweetTitle.height<42 ? tweeter.height + 42 + 20 : tweeter.height + tweetTitle.height + 20)
  1382. width: tweetsGrid.visible ? tweetsGrid.cellWidth : parent.width
  1383. height: tweetsGrid.visible ? window.tweetHeight : tweeter.height + tweetTitle.height + 18 // tweetSummary.height + 12 // (tweetTitle.height<42 ? tweeter.height + 42 + 20 : tweeter.height + tweetTitle.height + 20)
  1384. Rectangle {
  1385. id: feedsBackground
  1386. smooth: true
  1387. gradient: !tweetMouseArea.pressed ? (isForMe ? isForMeColor : (isMine ? isMineColor : idleColor)) : pressedColor
  1388. radius: 2
  1389. x: tweetsGrid.visible ? 1 : 0
  1390. y: 0
  1391. width: parent.width - x*2
  1392. height: parent.height - y*2 - 1
  1393. Row {
  1394. id: tweetSummary
  1395. spacing: 8
  1396. x: 8
  1397. y: 8
  1398. width: parent.width
  1399. //Column {
  1400. // width: 42
  1401. Item {
  1402. width: 42
  1403. height: 42
  1404. //x: parent.x
  1405. Image {
  1406. width: 42
  1407. height: 42
  1408. source: profileImageURL
  1409. }
  1410. Image {
  1411. width: 42
  1412. height: 42
  1413. visible: profileImageURL.length>0 && theme.isBlack
  1414. source: "pics/profile-round.png"
  1415. }
  1416. }
  1417. //}
  1418. Column {
  1419. id: tweetTexts
  1420. width: parent.width - 44
  1421. y: -4
  1422. spacing: 4
  1423. Text {
  1424. id: tweetTitle
  1425. color: theme.tweetTextColor
  1426. font.pixelSize: window.tweetFontSize
  1427. text: "<span>" + displayableStatus + "</span>"
  1428. wrapMode: Text.Wrap
  1429. width: feedsBackground.width - 58
  1430. }
  1431. Item {
  1432. width: feedsBackground.width - 64
  1433. //anchors.bottom: feedsBackground.bottom
  1434. //height: tweetsGrid.visible ? window.tweetHeight : tweeter.height
  1435. //x: -52
  1436. y: tweetsGrid.visible ? feedsBackground.height - tweeter.height - 8 : tweetTitle.y + tweetTitle.height + 2
  1437. Text {
  1438. id: tweeter
  1439. color: theme.tweetInfoTextColor // "#666"
  1440. opacity: 1
  1441. font.pixelSize: 16
  1442. font.bold: false
  1443. text: userName //+ replyBlock
  1444. wrapMode: Text.Wrap
  1445. width: parent.width
  1446. //x: (tweetTitle.height<42 && tweetsGrid.visible==false) ? 52 : 0
  1447. //x: 52
  1448. verticalAlignment: Text.AlignBottom
  1449. }
  1450. Text {
  1451. id: tweetDateLabel
  1452. color: theme.tweetInfoTextColor // "#666"
  1453. opacity: 1
  1454. font.pixelSize: 16
  1455. text: tweetDate
  1456. wrapMode: Text.Wrap
  1457. width: parent.width
  1458. horizontalAlignment: Text.AlignRight
  1459. verticalAlignment: Text.AlignBottom
  1460. }
  1461. }
  1462. }
  1463. } // Row
  1464. MouseArea {
  1465. id: tweetMouseArea
  1466. anchors.fill: parent
  1467. onClicked: {
  1468. if(status.indexOf("Load more...")>=0) {
  1469. tweetTitle.text = qsTr("Please wait...") + "<br/><br/><br/><br/>";
  1470. Script.loadNextPage();
  1471. } else {
  1472. tweetDetailsContainer.replyBlock = replyBlock;
  1473. tweetDetailsContainer.replyID = replyID;
  1474. tweetDetailsContainer.username = userName;
  1475. tweetDetailsContainer.tweetID = tweetID;
  1476. if(userName == Script.currentScreenName) {
  1477. tweetDetailsContainer.isMine = true;
  1478. } else {
  1479. tweetDetailsContainer.isMine = false;
  1480. }
  1481. if(isFavourite!=null) {
  1482. tweetDetailsContainer.isFavourite = isFavourite;
  1483. } else {
  1484. tweetDetailsContainer.isFavourite = false;
  1485. }
  1486. replyTextContainer.replyText = qsTr("Loading...");
  1487. if(replyID.length>0) {
  1488. Script.loadReplyText(replyID, replyTextContainer.replyText);
  1489. replyTextContainer.visible = true;
  1490. } else {
  1491. replyTextContainer.visible = false;
  1492. }
  1493. var plainSource = Script.removeHTMLTags(source);
  1494. selectedTweetSource.text = "<span>" + userName + " " + qsTr("from") + " " + plainSource + replyBlock + "</span>";
  1495. selectedTweetText.text = status;
  1496. tweetProfileImage.source = profileImageURL;
  1497. selectedTweetAge.text = tweetDate;
  1498. previewImage.source = imagePreviewURL;
  1499. if(imagePreviewURL.length==0) {
  1500. previewImage.height = 0;
  1501. } else {
  1502. previewImage.height = 200;
  1503. }
  1504. tweetDetailsFlickable.contentY = 0;
  1505. hashtagActionsModel.clear();
  1506. var tagCount = Script.GetHashTags(status, hashtagActionsModel, tweetID);
  1507. hashtagActions.height = Math.ceil(tagCount/2) * 60;
  1508. if(tagCount==0) {
  1509. hashtagsContainer.opacity = 0
  1510. } else {
  1511. hashtagsContainer.opacity = 1
  1512. }
  1513. Script.setSelectedTweet(tweetID);
  1514. Script.setSelectedUser(userName);
  1515. container.state = "hidden"; //.flipped = !container.flipped
  1516. }
  1517. }
  1518. }
  1519. }
  1520. }
  1521. }
  1522. Component {
  1523. id: hashtagDelegate
  1524. Item {
  1525. id: hashItem
  1526. property string buttonLabel: ""
  1527. width: hashtagActions.cellWidth - 10
  1528. height: 50
  1529. Component.onCompleted: {
  1530. hashItem.buttonLabel = actionName;
  1531. if(hashItem.buttonLabel.indexOf("/readitlaterlist.com/")>0) {
  1532. hashItem.buttonLabel = "Read it later...";
  1533. }
  1534. hashItem.buttonLabel = hashItem.buttonLabel.replace("http://", "");
  1535. hashItem.buttonLabel = hashItem.buttonLabel.replace("https://", "");
  1536. if(hashItem.buttonLabel.length>16) {
  1537. hashItem.buttonLabel = hashItem.buttonLabel.substring(0,16) + "..";
  1538. }
  1539. }
  1540. Button {
  1541. label: hashItem.buttonLabel
  1542. //label: actionName.replace("http://", "").length>16 ? actionName.replace("http://", "").substring(0,16) + ".." : actionName.replace("http://", "")
  1543. onClicked: {
  1544. if(actionName.indexOf("#")==0) {
  1545. Script.doSearch(actionName);
  1546. } else if(actionName.indexOf("@")==0){
  1547. detailsFlipable.flipped = true;
  1548. Script.setSelectedUser(actionName);
  1549. Script.fillProfile();
  1550. } else {
  1551. if(hashItem.buttonLabel.indexOf("Read it later...")>=0) {
  1552. if(settingsDialog.pocketUsername.length==0) {
  1553. settingsDialog.state = "shown";
  1554. } else {
  1555. Pocket.addLinkToPocket(actionName, settingsDialog.pocketUsername, settingsDialog.pocketPassword, tweetID);
  1556. }
  1557. } else {
  1558. Qt.openUrlExternally(actionName);
  1559. }
  1560. container.state = "shown";
  1561. }
  1562. }
  1563. }
  1564. }
  1565. }
  1566. Gradient {
  1567. id: pressedColor
  1568. GradientStop { position: 0.0; color: "#333" }
  1569. GradientStop { position: 0.1; color: "#222" }
  1570. GradientStop { position: 0.3; color: "#333" }
  1571. GradientStop { position: 1.0; color: "#444" }
  1572. }
  1573. Gradient {
  1574. id: idleColor
  1575. GradientStop { position: 0.0; color: theme.tweetTopColor }
  1576. GradientStop { position: 0.2; color: theme.tweetMiddleColor }
  1577. GradientStop { position: 1.0; color: theme.tweetBottomColor }
  1578. }
  1579. Gradient {
  1580. id: isMineColor
  1581. GradientStop { position: 0.0; color: theme.tweetTopColor }
  1582. GradientStop { position: 0.3; color: theme.tweetMiddleColor }
  1583. GradientStop { position: 0.8; color: theme.tweetMiddleColor }
  1584. GradientStop { position: 1.0; color: theme.tweetBottomMineColor }
  1585. }
  1586. Gradient {
  1587. id: isForMeColor
  1588. GradientStop { position: 0.0; color: theme.tweetTopColor }
  1589. GradientStop { position: 0.3; color: theme.tweetMiddleColor }
  1590. GradientStop { position: 0.8; color: theme.tweetMiddleColor }
  1591. GradientStop { position: 1.0; color: theme.tweetBottomForMeColor }
  1592. }
  1593. }
  1594. //} // Comment for Maemo