From a98780bc62149dbd1af317b9296fa9a63bf024f6 Mon Sep 17 00:00:00 2001 From: Andrew Dolgov Date: Mon, 5 Dec 2011 18:05:11 +0300 Subject: [PATCH] implement basic downloading of stuff for offline mode switch --- res/drawable-hdpi/ic_menu_clock.png | Bin 0 -> 3106 bytes res/drawable-hdpi/ic_menu_cloud.png | Bin 0 -> 1911 bytes res/menu/main_menu.xml | 19 ++-- res/values/strings.xml | 5 +- src/org/fox/ttrss/MainActivity.java | 158 ++++++++++++++++++++++++---- 5 files changed, 152 insertions(+), 30 deletions(-) create mode 100644 res/drawable-hdpi/ic_menu_clock.png create mode 100644 res/drawable-hdpi/ic_menu_cloud.png diff --git a/res/drawable-hdpi/ic_menu_clock.png b/res/drawable-hdpi/ic_menu_clock.png new file mode 100644 index 0000000000000000000000000000000000000000..824f688ea3d34cea09089a52a69d527a91462fd3 GIT binary patch literal 3106 zcmV+-4BhjIP))R zrQpU9-n$!n_x{cFVRy{+;-CGwOHye+>598}?%Z>}J?G4sb7p}ST4 zGa8MaG7RJRwr$(SnlJTDASjc`Jdn%f_DxSucXQ4`DTStK&~+V}ra@IzD2f6_Q9wvZ z93cdJ--qw}a9tOU^Ywf_|BLDA=?4Ko z*L9et3DY!T7zQ*=17mE4n7J%S66JXw9LGViSVW;vK%r28ZQB5VNF?&-cs%~}(9qC( z&Cnxsg7)vN%WO8g6@X%zCgSlpqR}XHU7xWSLdcB8$orrL$t(C-T9j?un3|eG zKA%USPyhhGt*z}f#@G*c?AT$4sZXc`WipwLTrPK}SSWr00 zBIG?G1d5`}{GD?S-}h&c1YqW#a}L*aQ79CU&*zcP=ixXG48ypPNF=^JG&D3GmQJA& zl*wf7o1C0H#W`Odi^Y&kCJ~85plKQ?rL#y0f>H`aQNS1zjIr|o;CbFE&+~}y`!@t@ z2_XbH=WrYc)6>(iEDN7~_8BOpS5v9f#-X91cf!ys6oN)ZMm9}OP97tKn8{=k$z&3S zVSq6~N((>iY2fMqw{{;YJV`E>rdiCm2&+}HuSTrAm5b!(?#bObbWx=v6 z2q6loRO@$!`$BU7fTAccO%th93hnLfV2qjBZ1z|tlew=^{Td>u9CJ=F z#>`YIg|@af=(;`=OBPZrNRq0mM*!FW-123ss(NHGa)KmLN}=mI+S=NXN~ORUGjqAz zsZ1u*(TI+9yV(By`}Jb6c#d=4lT0R&NF<JF>Lmv#5hKZ&>vN5BA-IBa&U-x1 z8?8$))Jf3D$jD09b+<+$5yazhsHzH}I+vQyMdm^y^Qo$ecs!0sBm&oUw~maAtgJ^@ zR?kC@%L`M(0#j6|qMR{``fvAUS_|zXu^iUsDJg9UZ-mQhJXpRfHvc`MM#25~ccdXzvJA z4DJ~n9lb4df_&famzBRTzuEFCs02wW-z#CPkikpJ@B4m#wR+dGirvK+o3+ns1ac=& z2=U8uZ~$^r0)SCUeIbM*YeS8qTseU2x_4FmOtk|UV;#Y|aigG=f>MfTH2Um(W1`XM zvvOP*kZ#5pt9k=l^_vMH%YpEgULgc1rHA_Z`d$X$;kxypeDC%3^}S3fJrsNN1-S8i5OaygqZ_DZ#7j~Ym73PBw}cmdP*{fSMRHeCeZ6GCn% zYn1=b-?VAdMc?-)LL_HKm(U0jLQqO632Rj;w{oTdcyp0cL6YbD{xjCqwE*g9RT>bB6L1c~bj+?B9mfONB|si~j5_~MJb z^SyW9zJ1>+7K=LxA&5jGds3;?Hbqg~pcU0A!<7o%>L;iSLMaW+f&j?wDzhx>Ps78* z`}XeLyHvjHrI%h>wrkg}pIer7R?{@5Y1(^h*RCCTJy-C`I9+S=L>kH`OU z>#esw5sgOk0C-eoYqaytihE2LEeW& zk}PJ)ett5UL^K)&0PWLHKmE<_-McpgbEUFU9spZWl!L)T4pppPvvjCR=PJhu0NgN) zGhvq?0*c>|=eVw`WwY7iFTC)=cZ0%6k}S*Op64yvo|f++gupP2GnidDXq+JFW}7!} zzCZ|hH*AvTQid@md;F?pS;wA#{`p5MWym~ zi^YZk_+?$HLQPAO5P|_PjvP61((}9r7COHZ281XbZJC;yLN=Sl^z<}js-bBblF1}e zsT6cwujc>aQ2fct3z5A;hazhFbe#9Dtinr-vsdChiwP(8bR0Gzysx$itt-Vi5pf znkHhgm@LH4`D`Gr@pL*pj8d9V(>GdkQX{SC=+UDY*L4Ry&qG)x(FNWK&N)2Ko3S9q z7-R`}F6#+Y5232+(ZRvNA=GF+Kz)Z7d;m^wZ|`%I(y>N2kJSckLdZ-5P&O{-+inC2 zqLhyH_Vzx9QljbCs%*^!$tAX{tIJxkV#Q;W((#)`l2m-5cU6!xzGB6S$GW<@ERflIFXDE3mPt|o=;zO$ z|MG_)e)yW_c`M~l2!h*yFd<`+YzCGIx_IZEcWzy^YSq6{>X!J8kOPEtPP$AI1)zWY z@yBiF&Yj!iIL;Q%ISrerxrm{Za!u2YuU@_SxjXK-Ba1m&Np-)k(FuYOrA~ngz&v~Q z>^H{8$A?|ly2&&y_3PLF4JB8S31HnvhZjOq zla>mi7)oTZx8HvI_A6Jetn+>UtDN%=&iOJS#8M%|5&$5COb|jop_Kl&oQQtZ+1Yuv zx3~8)O2sm#{BP5Uk+>;YU4SSV%q3w;`J#cp1Er)+=30LFl7z@&S5t|Rxan!HxZaBj wl2$2Cw9o?ZKWoyva7~I1PzGP$(Sqp=pn!^f4Hdyj<^E(z`R^ zpgjt?6vxPxBH7yPYIkR+577!I7n+qN$1>dy41(3n?CMf)D~lQIO4M|1mN$@|_bWPW-dqwhWX&Gcz;UYPI^uTCMgb02qb=(=@>t zLn@U5r4(Tp!uNf+t_#O;VB0oa*M*`eZlO?^Jbn7~FZ&ry8!ph*t5;P*$m?Mk?viEs zlcAxZ_l_MqWNLg#@MIB z!^6L`ZF_2RaxyHJ%WPp`;X~JTU(V%n7#<#mVHl9*$HfTwteHZH&adZrSXo)Y^71lP zS67kEX5T(@=FGSH;YZ&Ex_j1=kPoa(R0%@KhEWH z-?wf1XP)OB&FAyT<#Nz84TO+q3iB+45a67{aU3i!FQd_DAfL~F`{c=!f9lnrz6x~Z z%9WQNJb3Vd>$*ldokk{;0b>lZEJKncgkgvv2;evl8jS{4R#w0{7rL&KQmKS|KHm{% zJ%nKh+qO}uRM2X*mh<`iYZDU_)n0s(pPwZjlarHDqtUnlz$leU$mMd-b-g1_MAX_t zLqm~BB%Mwpo6RDXN_FzA2SNyRT}L*X#nRGJesy)V44|j3COtn(JQ!nVgCKaLSS+Gc zD#0{OD2nogIKX2kWLZW!okpQhz|NgJQ7jfakt2lYDM^w9!!Tf37J?u+QZAQSFMjnc zf?BQC4@}cUCX;z068={-$g4QWhQnT4arBWF`c<|up?c2Bi+-*Hw33UGa z`B$pd>Psi`+y*S(y{WQb*1106MM zi4N5$rSLpY1+Y9fH}`Jb^08;JR;%?r#+bwydtytl6(EElolb*u4%c;$1Ne2^va!1u zA>=i~FuGbP4@v?aFC5#O=PzEqd|B_SKtc#f)3jH&qBv_sQWOP@F~S&oMFe|sOvfuMY((E(4pS~@Zw%B#uA7S5(04c?Ah~kO6k81!-!tkmviKen${_$ zP*oM}^_#za`}UtO#_EKS*b&stc@Qs^N|kIj`{P=z_KswV7&9`TFea?3)iCKD-KGG`j2ZeILH> zBU%Q$XpsmZoq@Q0k{F#&*}AU(;>eLBGXR?1L=Uizi^H}^seAYC74O`+b1n#iW0E8d z+^)6VKz|z@9sSYn-Mi-jIPIaLE7s*$w0H!-Zr!@|l}4lSHO~2$g%Dp7LW}{}jMFng z2>A~o5b2RMLWZCX#%tfg;`w8a`2 xHtLJBgoK2IgoK2IgoK2IgoK2IgoOWV{tGvO`4K}P=1~9u002ovPDHLkV1jNti>Uwr literal 0 HcmV?d00001 diff --git a/res/menu/main_menu.xml b/res/menu/main_menu.xml index ab25e60c..531c6b98 100644 --- a/res/menu/main_menu.xml +++ b/res/menu/main_menu.xml @@ -1,5 +1,18 @@ + + + + @@ -22,12 +35,6 @@ android:showAsAction="" android:title="@string/update_feeds"/> - - Error: invalid API URL Displays full article text inline, instead of a separate panel Combined mode - Sync offline + Go offline + Go online + Preparing offline mode... + Failed to prepare offline mode (see log) \ No newline at end of file diff --git a/src/org/fox/ttrss/MainActivity.java b/src/org/fox/ttrss/MainActivity.java index 011d379e..bd0fe8ca 100644 --- a/src/org/fox/ttrss/MainActivity.java +++ b/src/org/fox/ttrss/MainActivity.java @@ -406,13 +406,42 @@ public class MainActivity extends FragmentActivity implements FeedsFragment.OnFe public synchronized SQLiteDatabase getWritableDb() { return m_writableDb; } + + //private boolean m_canGetMoreArticles = true; + private int m_articleOffset = 0; + + @SuppressWarnings("unchecked") + public void offlineGetArticles() { + Log.d(TAG, "offline: downloading articles... offset=" + m_articleOffset); + + OfflineArticlesRequest req = new OfflineArticlesRequest(this); + + HashMap map = new HashMap() { + { + put("op", "getHeadlines"); + put("sid", m_sessionId); + put("feed_id", "-4"); + put("view_mode", "unread"); + put("show_content", "true"); + put("skip", String.valueOf(m_articleOffset)); + put("limit", "30"); + } + }; + + req.execute(map); + } @SuppressWarnings("unchecked") - public void offlineSync() { - Log.d(TAG, "Starting offlineSync"); + public void switchOffline() { + Log.d(TAG, "offline: starting"); if (m_sessionId != null) { + findViewById(R.id.loading_container).setVisibility(View.VISIBLE); + findViewById(R.id.main).setVisibility(View.INVISIBLE); + + setLoadingStatus(R.string.offline_downloading, true); + // TODO upload updated stuff here // Download feeds @@ -424,29 +453,38 @@ public class MainActivity extends FragmentActivity implements FeedsFragment.OnFe protected void onPostExecute(JsonElement content) { if (content != null) { - Type listType = new TypeToken>() {}.getType(); - List feeds = new Gson().fromJson(content, listType); + try { + Type listType = new TypeToken>() {}.getType(); + List feeds = new Gson().fromJson(content, listType); + + SQLiteStatement stmtInsert = getWritableDb().compileStatement("INSERT INTO feeds " + + "("+BaseColumns._ID+", title, feed_url, has_icon, cat_id) " + + "VALUES (?, ?, ?, ?, ?);"); + + for (Feed feed : feeds) { + stmtInsert.bindLong(1, feed.id); + stmtInsert.bindString(2, feed.title); + stmtInsert.bindString(3, feed.feed_url); + stmtInsert.bindLong(4, feed.has_icon ? 1 : 0); + stmtInsert.bindLong(5, feed.cat_id); + + stmtInsert.execute(); + } - SQLiteStatement stmtInsert = getWritableDb().compileStatement("INSERT INTO feeds " + - "("+BaseColumns._ID+", title, feed_url, has_icon, cat_id) " + - "VALUES (?, ?, ?, ?, ?);"); - - for (Feed feed : feeds) { - stmtInsert.bindLong(1, feed.id); - stmtInsert.bindString(2, feed.title); - stmtInsert.bindString(3, feed.feed_url); - stmtInsert.bindLong(4, feed.has_icon ? 1 : 0); - stmtInsert.bindLong(5, feed.cat_id); - - stmtInsert.execute(); + Log.d(TAG, "offline: done downloading feeds"); + + m_articleOffset = 0; + + getWritableDb().execSQL("DELETE FROM articles;"); + + offlineGetArticles(); + } catch (Exception e) { + e.printStackTrace(); + setLoadingStatus(R.string.offline_switch_error, false); } - Log.d(TAG, "offlineSync: done downloading feeds"); - - // TODO download fresh articles - } else { - Log.d(TAG, "offlineSync failed: " + getErrorMessage()); + setLoadingStatus(getErrorMessage(), false); // TODO error, could not download feeds, properly report API error (toast) } } @@ -638,8 +676,8 @@ public class MainActivity extends FragmentActivity implements FeedsFragment.OnFe case R.id.login: login(); return true; - case R.id.initiate_sync: - offlineSync(); + case R.id.go_offline: + switchOffline(); return true; case R.id.close_article: closeArticle(); @@ -1449,4 +1487,78 @@ public class MainActivity extends FragmentActivity implements FeedsFragment.OnFe viewCategory(cat, browse && cat.id >= 0); } + + public class OfflineArticlesRequest extends ApiRequest { + public OfflineArticlesRequest(Context context) { + super(context); + } + + @Override + protected void onPostExecute(JsonElement content) { + if (content != null) { + try { + Type listType = new TypeToken>() {}.getType(); + List
articles = new Gson().fromJson(content, listType); + + SQLiteStatement stmtInsert = getWritableDb().compileStatement("INSERT INTO articles " + + "("+BaseColumns._ID+", unread, marked, published, updated, is_updated, title, link, feed_id, tags, content) " + + "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);"); + + for (Article article : articles) { + + String tagsString = ""; + + for (String t : article.tags) { + tagsString += t + ", "; + } + + tagsString.replaceAll("/, $/", ""); + + stmtInsert.bindLong(1, article.id); + stmtInsert.bindLong(2, article.unread ? 1 : 0); + stmtInsert.bindLong(3, article.marked ? 1 : 0); + stmtInsert.bindLong(4, article.published ? 1 : 0); + stmtInsert.bindLong(5, article.updated); + stmtInsert.bindLong(6, article.is_updated ? 1 : 0); + stmtInsert.bindString(7, article.title); + stmtInsert.bindString(8, article.link); + stmtInsert.bindLong(9, article.feed_id); + stmtInsert.bindString(10, tagsString); // comma-separated tags + stmtInsert.bindString(11, article.content); + + try { + stmtInsert.execute(); + } catch (Exception e) { + e.printStackTrace(); + } + + } + + //m_canGetMoreArticles = articles.size() == 30; + m_articleOffset += articles.size(); + + Log.d(TAG, "offline: received " + articles.size() + " articles"); + + if (articles.size() == 30 && m_articleOffset < 500) { + offlineGetArticles(); + } else { + logout(); + setLoadingStatus(R.string.blank, false); + + } + + return; + + } catch (Exception e) { + setLoadingStatus(R.string.offline_switch_error, false); + Log.d(TAG, "offline: failed: exception when loading articles"); + e.printStackTrace(); + } + + } else { + Log.d(TAG, "offline: failed: " + getErrorMessage()); + setLoadingStatus(getErrorMessage(), false); + } + } + } } \ No newline at end of file