diff options
author | David Development <david-dev@live.de> | 2014-07-28 13:52:21 +0400 |
---|---|---|
committer | David Development <david-dev@live.de> | 2014-07-28 13:53:03 +0400 |
commit | d378e2bba063852a463c8a554afe1566043502ac (patch) | |
tree | 6b85c4b258ccdd86bfad718101df2bd704532951 /News-Android-App | |
parent | bffef458cb3079ef928486ab7e7b2fb4ef454b15 (diff) |
Update Backend to ORM/Remove abs -> appcompat
Diffstat (limited to 'News-Android-App')
83 files changed, 4020 insertions, 977 deletions
diff --git a/News-Android-App/News-Android-App-News-Android-App.iml b/News-Android-App/News-Android-App-News-Android-App.iml index 90d8c00b..009ef0ae 100644 --- a/News-Android-App/News-Android-App-News-Android-App.iml +++ b/News-Android-App/News-Android-App-News-Android-App.iml @@ -61,18 +61,19 @@ <orderEntry type="jdk" jdkName="Android API 20 Platform" jdkType="Android SDK" /> <orderEntry type="sourceFolder" forTests="false" /> <orderEntry type="library" exported="" name="library-2.0.1" level="project" /> + <orderEntry type="library" exported="" name="greendao-1.3.7" level="project" /> <orderEntry type="library" exported="" name="eventbus-2.2.1" level="project" /> <orderEntry type="library" exported="" name="gson-2.2.4" level="project" /> - <orderEntry type="library" exported="" name="extra-abs-0.9.9" level="project" /> - <orderEntry type="library" exported="" name="library-0.9.9" level="project" /> + <orderEntry type="library" exported="" name="greendao-generator-1.3.1" level="project" /> + <orderEntry type="library" exported="" name="appcompat-v7-20.0.0" level="project" /> <orderEntry type="library" exported="" name="butterknife-5.1.1" level="project" /> <orderEntry type="library" exported="" name="jsoup-1.7.2" level="project" /> - <orderEntry type="library" exported="" name="library-0.4.0" level="project" /> <orderEntry type="library" exported="" name="support-annotations-20.0.0" level="project" /> <orderEntry type="library" exported="" name="support-v4-20.0.0" level="project" /> <orderEntry type="library" exported="" name="library-2.4.0" level="project" /> - <orderEntry type="library" exported="" name="actionbarsherlock-4.4.0" level="project" /> + <orderEntry type="library" exported="" name="freemarker-2.3.18" level="project" /> <orderEntry type="library" exported="" name="picasso-2.3.1" level="project" /> + <orderEntry type="module" module-name="library" exported="" /> <orderEntry type="module" module-name="ownCloud-Account-Importer" exported="" /> <orderEntry type="module" module-name="MessageBar" exported="" /> <orderEntry type="module" module-name="ChangeLogLibrary" exported="" /> diff --git a/News-Android-App/build.gradle b/News-Android-App/build.gradle index 762253cb..3015deed 100644 --- a/News-Android-App/build.gradle +++ b/News-Android-App/build.gradle @@ -39,6 +39,7 @@ android { configurations.all { resolutionStrategy { force 'com.android.support:support-v4:20.+' + force 'com.android.support:appcompat-v7:20.+' } } @@ -52,11 +53,14 @@ dependencies { compile project(':Changeloglib:ChangeLogLibrary') compile project(':MessageBar') compile project(':ownCloud-Account-Importer') + compile project(':ShowcaseView:library') compile 'com.android.support:support-v4:20.+' + compile 'com.android.support:appcompat-v7:20.+' compile 'com.jakewharton:butterknife:5.1.+' compile 'com.squareup.picasso:picasso:2.3.1@jar' - compile 'com.actionbarsherlock:actionbarsherlock:4.4.0@aar' - compile 'com.github.chrisbanes.actionbarpulltorefresh:extra-abs:+' compile 'com.sothree.slidinguppanel:library:+' compile 'de.greenrobot:eventbus:2.2.1' + compile 'de.greenrobot:greendao:1.3.7@jar' + compile 'de.greenrobot:greendao-generator:1.3.1@jar' + compile 'org.freemarker:freemarker:2.3.18@jar' } diff --git a/News-Android-App/src/main/AndroidManifest.xml b/News-Android-App/src/main/AndroidManifest.xml index b9d7c538..e72646c8 100644 --- a/News-Android-App/src/main/AndroidManifest.xml +++ b/News-Android-App/src/main/AndroidManifest.xml @@ -1,8 +1,8 @@ <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="de.luhmer.owncloudnewsreader" - android:versionCode="60" - android:versionName="0.6.9.6" > + android:versionCode="63" + android:versionName="0.6.9.9" > <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> diff --git a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/Constants.java b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/Constants.java index 09bbd2f7..d83e578d 100644 --- a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/Constants.java +++ b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/Constants.java @@ -28,6 +28,11 @@ public class Constants { public static final String LAST_UPDATE_NEW_ITEMS_COUNT_STRING = "LAST_UPDATE_NEW_ITEMS_COUNT_STRING"; + + public static final String SHOW_CASE_PODCAST_ENABLED_SHOWN_BOOLEAN = "FIRST_TIME_PODCAST_ENABLED_BOOLEAN"; + public static final String SHOW_CASE_APP_STARTED_SHOWN_BOOLEAN = "FIRST_TIME_APP_STARTED_BOOLEAN"; + public static final String SHOW_CASE_PODCAST_AVAILABLE_INFO_SHOWN_BOOLEAN = "PODCAST_AVAILABLE_INFO_SHOWN_BOOLEAN"; + /* private static final String _P_KEY_PART1 = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAgNmCsMj6M4zkjpKRG8MG5+yIAyqSQE2etVkZsc3s"; private static final String _P_KEY_PART2 = "V5zLoQ/NUOVC0fS2tj8IWk6UYqQGk9rmVold3sDGiTCvWGFecjwel3qxzz23hKLlemrv2+0WPrZ5KOqiaCEMi"; diff --git a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/ListView/PodcastFeedArrayAdapter.java b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/ListView/PodcastFeedArrayAdapter.java index bc2a4360..d642f851 100644 --- a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/ListView/PodcastFeedArrayAdapter.java +++ b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/ListView/PodcastFeedArrayAdapter.java @@ -40,8 +40,8 @@ public class PodcastFeedArrayAdapter extends ArrayAdapter<PodcastFeedItem> { final PodcastFeedItem feedItem = getItem(position); - holder.tvTitle.setText(feedItem.title); - holder.tvBody.setText(feedItem.count + " Podcasts available"); + holder.tvTitle.setText(feedItem.mFeed.getFeedTitle()); + holder.tvBody.setText(feedItem.mPodcastCount + " Podcasts available"); view.setOnClickListener(new View.OnClickListener() { @Override diff --git a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/ListView/SubscriptionExpandableListAdapter.java b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/ListView/SubscriptionExpandableListAdapter.java index 1e1040f3..19129d4b 100644 --- a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/ListView/SubscriptionExpandableListAdapter.java +++ b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/ListView/SubscriptionExpandableListAdapter.java @@ -24,7 +24,6 @@ package de.luhmer.owncloudnewsreader.ListView; import android.annotation.TargetApi; import android.content.Context; import android.content.SharedPreferences; -import android.database.Cursor; import android.graphics.drawable.Drawable; import android.os.AsyncTask; import android.os.Build; @@ -44,12 +43,15 @@ import com.squareup.picasso.Picasso; import java.io.File; import java.util.ArrayList; +import java.util.List; import butterknife.ButterKnife; import butterknife.InjectView; import de.luhmer.owncloudnewsreader.R; import de.luhmer.owncloudnewsreader.SettingsActivity; -import de.luhmer.owncloudnewsreader.database.DatabaseConnection; +import de.luhmer.owncloudnewsreader.database.DatabaseConnectionOrm; +import de.luhmer.owncloudnewsreader.database.model.Feed; +import de.luhmer.owncloudnewsreader.database.model.Folder; import de.luhmer.owncloudnewsreader.helper.FavIconHandler; import de.luhmer.owncloudnewsreader.helper.FileUtils; import de.luhmer.owncloudnewsreader.helper.FontHelper; @@ -68,7 +70,7 @@ public class SubscriptionExpandableListAdapter extends BaseExpandableListAdapter //private static final String TAG = "SubscriptionExpandableListAdapter"; private Context mContext; - private DatabaseConnection dbConn; + private DatabaseConnectionOrm dbConn; FontHelper fHelper; ListView listView; @@ -91,6 +93,7 @@ public class SubscriptionExpandableListAdapter extends BaseExpandableListAdapter return id; } + public String getValueString() { return String.valueOf(id); } @@ -111,7 +114,7 @@ public class SubscriptionExpandableListAdapter extends BaseExpandableListAdapter //return (context.getResources().getConfiguration().screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK) >= Configuration.SCREENLAYOUT_SIZE_XLARGE; } - public SubscriptionExpandableListAdapter(Context mContext, DatabaseConnection dbConn, ListView listView) + public SubscriptionExpandableListAdapter(Context mContext, DatabaseConnectionOrm dbConn, ListView listView) { mIsTwoPane = isTwoPane(mContext); @@ -133,6 +136,7 @@ public class SubscriptionExpandableListAdapter extends BaseExpandableListAdapter unreadCountFeeds = new SparseArray<String>(); unreadCountFolders = new SparseArray<String>(); + starredCountFeeds = new SparseArray<String>(); mCategoriesArrayList = new ArrayList<AbstractItem>(); mItemsArrayList = new SparseArray<SparseArray<ConcreteFeedItem>>(); @@ -140,6 +144,7 @@ public class SubscriptionExpandableListAdapter extends BaseExpandableListAdapter this.listView = listView; } + /* private void AddEverythingInCursorFolderToSubscriptions(Cursor itemsCursor, ArrayList<AbstractItem> dest) { while (itemsCursor.moveToNext()) { @@ -163,6 +168,7 @@ public class SubscriptionExpandableListAdapter extends BaseExpandableListAdapter } itemsCursor.close(); } + */ @SuppressWarnings("deprecation") @Override @@ -204,8 +210,13 @@ public class SubscriptionExpandableListAdapter extends BaseExpandableListAdapter viewHolder.tV_HeaderText.setText(headerText); + String unreadCount = null; + if(item.idFolder == ALL_STARRED_ITEMS.getValue()) { + unreadCount = starredCountFeeds.get((int) item.id_database); + } else { + unreadCount = unreadCountFeeds.get((int) item.id_database); + } - String unreadCount = unreadCountFeeds.get((int) item.id_database); if(unreadCount != null) viewHolder.tV_UnreadCount.setText(unreadCount); else @@ -314,23 +325,24 @@ public class SubscriptionExpandableListAdapter extends BaseExpandableListAdapter @Override public void onClick(View v) { - String val = String.valueOf(group.id_database); + long idFeed = group.id_database; boolean skipFireEvent = false; if(group instanceof ConcreteFeedItem) { - fireListTextClicked(val, mContext, false, ITEMS_WITHOUT_FOLDER.getValueString()); + fireListTextClicked(idFeed, mContext, false, (long) ITEMS_WITHOUT_FOLDER.getValue()); skipFireEvent = true; } if(!skipFireEvent) - fireListTextClicked(val, mContext, true, ((FolderSubscribtionItem) group).idFolder); + fireListTextClicked(idFeed, mContext, true, ((FolderSubscribtionItem) group).idFolder); } }); viewHolder.txt_UnreadCount.setText(""); boolean skipGetUnread = false; - if(group.idFolder != null && group.idFolder.equals(ITEMS_WITHOUT_FOLDER.getValueString())) { + if(group.idFolder != null && group.idFolder == ITEMS_WITHOUT_FOLDER.getValue()) { + //if(group instanceof ConcreteFeedItem) { String unreadCount = unreadCountFeeds.get((int) group.id_database); if(unreadCount != null) @@ -342,8 +354,6 @@ public class SubscriptionExpandableListAdapter extends BaseExpandableListAdapter } */ - - skipGetUnread = true; } @@ -369,13 +379,13 @@ public class SubscriptionExpandableListAdapter extends BaseExpandableListAdapter if(group.idFolder != null) { - if(group.idFolder.equals(ITEMS_WITHOUT_FOLDER.getValueString())) + if(group.idFolder == ITEMS_WITHOUT_FOLDER.getValue()) { ConcreteFeedItem concreteFeedItem = ((ConcreteFeedItem) group); loadFavIconForFeed(concreteFeedItem.favIcon, viewHolder.imgView); } } else { - if(String.valueOf(group.id_database).equals(ALL_STARRED_ITEMS.getValueString())) { + if(group.id_database == ALL_STARRED_ITEMS.getValue()) { viewHolder.imgView.setVisibility(View.VISIBLE); //viewHolder.imgView.setImageResource(R.drawable.btn_rating_star_off_normal_holo_light); viewHolder.imgView.setImageDrawable(getBtn_rating_star_off_normal_holo_light(mContext)); @@ -504,42 +514,59 @@ public class SubscriptionExpandableListAdapter extends BaseExpandableListAdapter showOnlyUnread = mPrefs.getBoolean(SettingsActivity.CB_SHOWONLYUNREAD_STRING, false); mCategoriesArrayListAsync = new ArrayList<AbstractItem>(); - mCategoriesArrayListAsync.add(new FolderSubscribtionItem(mContext.getString(R.string.allUnreadFeeds), null, ALL_UNREAD_ITEMS.getValue(), null)); - mCategoriesArrayListAsync.add(new FolderSubscribtionItem(mContext.getString(R.string.starredFeeds), null, ALL_STARRED_ITEMS.getValue(), null)); + mCategoriesArrayListAsync.add(new FolderSubscribtionItem(mContext.getString(R.string.allUnreadFeeds), null, ALL_UNREAD_ITEMS.getValue())); + mCategoriesArrayListAsync.add(new FolderSubscribtionItem(mContext.getString(R.string.starredFeeds), null, ALL_STARRED_ITEMS.getValue())); + + List<Folder> folderList; + if(showOnlyUnread) + folderList = dbConn.getListOfFoldersWithUnreadItems(); + else + folderList = dbConn.getListOfFolders(); - //mCategoriesArrayList.add(new FolderSubscribtionItem(mContext.getString(R.string.starredFeeds), -11, null, null)); - AddEverythingInCursorFolderToSubscriptions(dbConn.getAllTopSubscriptions(showOnlyUnread), mCategoriesArrayListAsync); - AddEverythingInCursorFeedsToSubscriptions(dbConn.getAllTopSubscriptionsWithoutFolder(showOnlyUnread), mCategoriesArrayListAsync); + for(Folder folder : folderList) + mCategoriesArrayListAsync.add(new FolderSubscribtionItem(folder.getLabel(), null, folder.getId())); + + for(Feed feed : dbConn.getListOfFeedsWithoutFolders(showOnlyUnread)) + mCategoriesArrayListAsync.add(new ConcreteFeedItem(feed.getFeedTitle(), (long) ITEMS_WITHOUT_FOLDER.getValue(), feed.getId(), feed.getFaviconUrl(), feed.getId())); //AddEverythingInCursorToSubscriptions(dbConn.getAllTopSubscriptionsWithUnreadFeeds()); mItemsArrayListAsync = new SparseArray<SparseArray<ConcreteFeedItem>>(); - for(int groupPosition = 0; groupPosition < mCategoriesArrayListAsync.size(); groupPosition++) { //int parent_id = (int)getGroupId(groupPosition); int parent_id = (int) mCategoriesArrayListAsync.get(groupPosition).id_database; - String parentId = String.valueOf(parent_id); mItemsArrayListAsync.append(parent_id, new SparseArray<ConcreteFeedItem>()); - Cursor itemsCursor = dbConn.getAllSubscriptionForFolder(parentId, showOnlyUnread); - itemsCursor.requery(); + int childPosTemp = 0; - if (itemsCursor.moveToFirst()) - do { - long id_database = itemsCursor.getLong(0); - String name = itemsCursor.getString(itemsCursor.getColumnIndex(DatabaseConnection.SUBSCRIPTION_HEADERTEXT)); - String subscription_id = itemsCursor.getString(itemsCursor.getColumnIndex(DatabaseConnection.SUBSCRIPTION_ID)); - String urlFavicon = itemsCursor.getString(itemsCursor.getColumnIndex(DatabaseConnection.SUBSCRIPTION_FAVICON_URL)); - ConcreteFeedItem newItem = new ConcreteFeedItem(name, parentId, subscription_id, urlFavicon, id_database); + + List<Feed> feedItemList = null; + + if(parent_id == ALL_UNREAD_ITEMS.getValue()) { + feedItemList = dbConn.getAllFeedsWithUnreadRssItems(); + } else if(parent_id == ALL_STARRED_ITEMS.getValue()) { + feedItemList = dbConn.getAllFeedsWithStarredRssItems(); + } else { + for(Folder folder : folderList) {//Find the current selected folder + if (folder.getId() == parent_id) {//Current item + feedItemList = dbConn.getAllFeedsWithUnreadRssItemsForFolder(folder.getId(), showOnlyUnread);// folder.getFeedList(); + break; + } + } + } + + if(feedItemList != null) { + for (Feed feed : feedItemList) { + ConcreteFeedItem newItem = new ConcreteFeedItem(feed.getFeedTitle(), (long) parent_id, feed.getId(), feed.getFaviconUrl(), feed.getId()); mItemsArrayListAsync.get(parent_id).put(childPosTemp, newItem); childPosTemp++; - } while (itemsCursor.moveToNext()); - itemsCursor.close(); + } + } } } - + SparseArray<String> starredCountFeeds; SparseArray<String> unreadCountFolders; SparseArray<String> unreadCountFeeds; SparseArray<String> urlsToFavIcons; @@ -556,21 +583,29 @@ public class SubscriptionExpandableListAdapter extends BaseExpandableListAdapter private class NotifyDataSetChangedAsyncTask extends AsyncTask<Void, Void, Void> { + SparseArray<String> starredCountFeedsTemp; SparseArray<String> unreadCountFoldersTemp; SparseArray<String> unreadCountFeedsTemp; SparseArray<String> urlsToFavIconsTemp; @Override protected Void doInBackground(Void... voids) { - unreadCountFoldersTemp = dbConn.getUnreadItemCountForFolder(mContext); + unreadCountFoldersTemp = dbConn.getUnreadItemCountForFolder(); unreadCountFeedsTemp = dbConn.getUnreadItemCountForFeed(); + starredCountFeedsTemp = dbConn.getStarredItemCountForFeed(); + + /* + SparseArray<Integer>[] values = dbConn.getUnreadItemCount(); + unreadCountFoldersTemp = values[0]; + unreadCountFeedsTemp = values[1]; + */ urlsToFavIconsTemp = dbConn.getUrlsToFavIcons(); return null; } @Override protected void onPostExecute(Void aVoid) { - notifyCountDataSetChanged(unreadCountFoldersTemp, unreadCountFeedsTemp, urlsToFavIconsTemp); + notifyCountDataSetChanged(unreadCountFoldersTemp, unreadCountFeedsTemp, urlsToFavIconsTemp, starredCountFeedsTemp); super.onPostExecute(aVoid); } } @@ -623,10 +658,11 @@ public class SubscriptionExpandableListAdapter extends BaseExpandableListAdapter NotifyDataSetChangedAsync(); } - public void notifyCountDataSetChanged(SparseArray<String> unreadCountFolders, SparseArray<String> unreadCountFeeds, SparseArray<String> urlsToFavIcons) { + public void notifyCountDataSetChanged(SparseArray<String> unreadCountFolders, SparseArray<String> unreadCountFeeds, SparseArray<String> urlsToFavIcons, SparseArray<String> starredCountFeeds) { this.unreadCountFolders = unreadCountFolders; this.unreadCountFeeds = unreadCountFeeds; this.urlsToFavIcons = urlsToFavIcons; + this.starredCountFeeds = starredCountFeeds; BlockingExpandableListView bView = (BlockingExpandableListView) listView; @@ -651,9 +687,9 @@ public class SubscriptionExpandableListAdapter extends BaseExpandableListAdapter { eListTextClickHandler = listener; } - protected void fireListTextClicked(String idSubscription, Context context, boolean isFolder, String optional_folder_id) + protected void fireListTextClicked(long idFeed, Context context, boolean isFolder, Long optional_folder_id) { if(eListTextClickHandler != null) - eListTextClickHandler.onTextClicked(idSubscription, context, isFolder, optional_folder_id); + eListTextClickHandler.onTextClicked(idFeed, context, isFolder, optional_folder_id); } }
\ No newline at end of file diff --git a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/ListView/UnreadFeedCount.java b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/ListView/UnreadFeedCount.java index b308bfc3..0f16ec7d 100644 --- a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/ListView/UnreadFeedCount.java +++ b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/ListView/UnreadFeedCount.java @@ -26,6 +26,7 @@ import android.content.Context; import de.luhmer.owncloudnewsreader.async_tasks.IGetTextForTextViewAsyncTask; import de.luhmer.owncloudnewsreader.database.DatabaseConnection; +@Deprecated public class UnreadFeedCount implements IGetTextForTextViewAsyncTask { Context context; diff --git a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/ListView/UnreadFolderCount.java b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/ListView/UnreadFolderCount.java index b8cbaee8..f972bac2 100644 --- a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/ListView/UnreadFolderCount.java +++ b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/ListView/UnreadFolderCount.java @@ -26,6 +26,7 @@ import android.content.Context; import de.luhmer.owncloudnewsreader.async_tasks.IGetTextForTextViewAsyncTask; import de.luhmer.owncloudnewsreader.database.DatabaseConnection; +@Deprecated public class UnreadFolderCount implements IGetTextForTextViewAsyncTask { Context context; diff --git a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/LoginDialogFragment.java b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/LoginDialogFragment.java index 7f45d087..70af7914 100644 --- a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/LoginDialogFragment.java +++ b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/LoginDialogFragment.java @@ -30,6 +30,7 @@ import android.content.SharedPreferences.Editor; import android.os.AsyncTask; import android.os.Bundle; import android.preference.PreferenceManager; +import android.support.v4.app.DialogFragment; import android.text.TextUtils; import android.view.LayoutInflater; import android.view.View; @@ -38,8 +39,6 @@ import android.widget.CompoundButton; import android.widget.CompoundButton.OnCheckedChangeListener; import android.widget.EditText; -import com.actionbarsherlock.app.SherlockDialogFragment; - import java.net.MalformedURLException; import java.net.URL; @@ -51,7 +50,7 @@ import de.luhmer.owncloud.accountimporter.helper.AccountImporter; import de.luhmer.owncloud.accountimporter.helper.OwnCloudAccount; import de.luhmer.owncloud.accountimporter.interfaces.IAccountImport; import de.luhmer.owncloudnewsreader.authentication.AuthenticatorActivity; -import de.luhmer.owncloudnewsreader.database.DatabaseConnection; +import de.luhmer.owncloudnewsreader.database.DatabaseConnectionOrm; import de.luhmer.owncloudnewsreader.helper.FontHelper; import de.luhmer.owncloudnewsreader.reader.owncloud.OwnCloudReaderMethods; @@ -59,7 +58,7 @@ import de.luhmer.owncloudnewsreader.reader.owncloud.OwnCloudReaderMethods; * Activity which displays a login screen to the user, offering registration as * well. */ -public class LoginDialogFragment extends SherlockDialogFragment implements IAccountImport { +public class LoginDialogFragment extends DialogFragment implements IAccountImport { static LoginDialogFragment instance; public static LoginDialogFragment getInstance() { @@ -513,9 +512,9 @@ public class LoginDialogFragment extends SherlockDialogFragment implements IAcco ShowAlertDialog(getString(R.string.login_dialog_title_error), getString(R.string.login_dialog_text_something_went_wrong), getActivity()); } else { //Reset Database - DatabaseConnection dbConn = new DatabaseConnection(getActivity()); + DatabaseConnectionOrm dbConn = new DatabaseConnectionOrm(getActivity()); dbConn.resetDatabase(); - dbConn.closeDatabase(); + //dbConn.closeDatabase(); //LoginFragment.this.dismiss(); SharedPreferences mPrefs = PreferenceManager.getDefaultSharedPreferences(getActivity()); diff --git a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/MenuUtilsSherlockFragmentActivity.java b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/MenuUtilsFragmentActivity.java index cafc0807..2e7f6f92 100644 --- a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/MenuUtilsSherlockFragmentActivity.java +++ b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/MenuUtilsFragmentActivity.java @@ -24,22 +24,22 @@ package de.luhmer.owncloudnewsreader; import android.annotation.TargetApi; import android.os.Build; import android.preference.PreferenceManager; +import android.support.v4.app.DialogFragment; import android.support.v4.app.FragmentActivity; import android.util.Log; +import android.view.Menu; +import android.view.MenuInflater; +import android.view.MenuItem; import android.widget.Toast; -import com.actionbarsherlock.app.SherlockDialogFragment; -import com.actionbarsherlock.view.Menu; -import com.actionbarsherlock.view.MenuInflater; -import com.actionbarsherlock.view.MenuItem; - -import de.luhmer.owncloudnewsreader.database.DatabaseConnection; +import de.luhmer.owncloudnewsreader.database.DatabaseConnectionOrm; +import de.luhmer.owncloudnewsreader.database.model.RssItem; import de.luhmer.owncloudnewsreader.reader.IReader; import de.luhmer.owncloudnewsreader.reader.OnAsyncTaskCompletedListener; import de.luhmer.owncloudnewsreader.reader.owncloud.API; import de.luhmer.owncloudnewsreader.reader.owncloud.OwnCloud_Reader; -public class MenuUtilsSherlockFragmentActivity extends PodcastSherlockFragmentActivity { +public class MenuUtilsFragmentActivity extends PodcastFragmentActivity { protected static final String TAG = "MenuUtils"; @@ -105,7 +105,7 @@ public class MenuUtilsSherlockFragmentActivity extends PodcastSherlockFragmentAc public static boolean onOptionsItemSelected(MenuItem item, FragmentActivity activity) { switch (item.getItemId()) { case R.id.menu_About_Changelog: - SherlockDialogFragment dialog = new VersionInfoDialogFragment(); + DialogFragment dialog = new VersionInfoDialogFragment(); dialog.show(activity.getSupportFragmentManager(), "VersionChangelogDialogFragment"); return true; @@ -113,35 +113,16 @@ public class MenuUtilsSherlockFragmentActivity extends PodcastSherlockFragmentAc NewsReaderDetailFragment ndf = ((NewsReaderDetailFragment) activity.getSupportFragmentManager().findFragmentById(R.id.content_frame)); if(ndf != null) { - /* - for(int i = 0; i < ndf.getListView().getChildCount(); i++) - { - View view = ndf.getListView().getChildAt(i); - CheckBox cb = (CheckBox) view.findViewById(R.id.cb_lv_item_read); - if(!cb.isChecked()) - cb.setChecked(true); - } - */ - - DatabaseConnection dbConn = new DatabaseConnection(activity); - try { - /* - //dbConn.markAllItemsAsRead(ndf.getDatabaseIdsOfItems()); - List<Integer> items = new ArrayList<Integer>(); - - - Cursor cursor = ncla.getLvAdapter().getCursor(); - cursor.moveToFirst(); - do { - items.add(Integer.parseInt(cursor.getString(0))); - } while (cursor.moveToNext()); - dbConn.markAllItemsAsRead(items); - */ - dbConn.markAllItemsAsReadForCurrentView(); - } finally { - dbConn.closeDatabase(); + DatabaseConnectionOrm dbConn = new DatabaseConnectionOrm(activity); + //dbConn.markAllItemsAsReadForCurrentView(); + + for(int i = 0; i < ndf.getListAdapter().getCount(); i++) { + RssItem rssItem = (RssItem) ndf.getListAdapter().getItem(i); + rssItem.setRead_temp(true); + dbConn.updateRssItem(rssItem); } - ndf.UpdateCursor(); + + ndf.notifyDataSetChangedOnAdapter(); //If tablet view is enabled update the listview as well if(activity instanceof NewsReaderListActivity) @@ -159,27 +140,6 @@ public class MenuUtilsSherlockFragmentActivity extends PodcastSherlockFragmentAc private static void DownloadMoreItems() { - /* - DatabaseConnection dbConn = new DatabaseConnection(activity); - int count = dbConn.getCountFeedsForFolder(SubscriptionExpandableListAdapter.ALL_ITEMS, false); - if(count >= Constants.maxItemsCount) - { - String text = activity.getString(R.string.max_items_count_reached); - text = text.replace("XX", "" + Constants.maxItemsCount); - new AlertDialog.Builder(activity) - .setTitle(activity.getString(R.string.empty_view_header)) - .setMessage(text) - .setPositiveButton(activity.getString(android.R.string.ok), new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog,int id) { - - } - }) - .create() - .show(); - //Toast.makeText(activity, text, Toast.LENGTH_LONG).show(); - } - else - {*/ String username = PreferenceManager.getDefaultSharedPreferences(activity.getApplicationContext()).getString("edt_username", ""); String password = PreferenceManager.getDefaultSharedPreferences(activity.getApplicationContext()).getString("edt_password", ""); @@ -189,7 +149,6 @@ public class MenuUtilsSherlockFragmentActivity extends PodcastSherlockFragmentAc Toast.makeText(activity, activity.getString(R.string.toast_GettingMoreItems), Toast.LENGTH_SHORT).show(); } - //} } static OnAsyncTaskCompletedListener onAsyncTaskGetVersionFinished = new OnAsyncTaskCompletedListener() { @@ -212,7 +171,7 @@ public class MenuUtilsSherlockFragmentActivity extends PodcastSherlockFragmentAc public void onAsyncTaskCompleted(int task_id, Object task_result) { NewsReaderDetailFragment ndf = ((NewsReaderDetailFragment) activity.getSupportFragmentManager().findFragmentById(R.id.content_frame)); if(ndf != null) - ndf.UpdateCursor(); + ndf.UpdateCurrentRssView(activity, true); Log.d(TAG, "Finished Download extra items.."); } diff --git a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/NewFeedActivity.java b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/NewFeedActivity.java index 88e71308..1df0045d 100644 --- a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/NewFeedActivity.java +++ b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/NewFeedActivity.java @@ -8,8 +8,10 @@ import android.content.Intent; import android.os.AsyncTask; import android.os.Build; import android.os.Bundle; +import android.support.v7.app.ActionBarActivity; import android.text.TextUtils; import android.util.Log; +import android.view.MenuItem; import android.view.View; import android.view.View.OnClickListener; import android.view.inputmethod.InputMethodManager; @@ -18,20 +20,20 @@ import android.widget.Button; import android.widget.EditText; import android.widget.Spinner; -import com.actionbarsherlock.app.SherlockActivity; -import com.actionbarsherlock.view.MenuItem; import java.net.URL; -import java.util.HashMap; +import java.util.List; import butterknife.ButterKnife; import butterknife.InjectView; -import de.luhmer.owncloudnewsreader.database.DatabaseConnection; +import de.luhmer.owncloudnewsreader.database.DatabaseConnectionOrm; +import de.luhmer.owncloudnewsreader.database.model.Folder; +import de.luhmer.owncloudnewsreader.helper.ThemeChooser; import de.luhmer.owncloudnewsreader.reader.HttpJsonRequest; import de.luhmer.owncloudnewsreader.reader.owncloud.API; import de.luhmer.owncloudnewsreader.reader.owncloud.apiv2.APIv2; -public class NewFeedActivity extends SherlockActivity { +public class NewFeedActivity extends ActionBarActivity { /** * Keep track of the login task to ensure we can cancel it if requested. @@ -45,10 +47,11 @@ public class NewFeedActivity extends SherlockActivity { @InjectView(R.id.new_feed_form) View mLoginFormView; @InjectView(R.id.btn_addFeed) Button mAddFeedButton; - HashMap<String, String> folders; + List<Folder> folders; @Override protected void onCreate(Bundle savedInstanceState) { + ThemeChooser.chooseTheme(this); super.onCreate(savedInstanceState); setContentView(R.layout.activity_new_feed); @@ -56,13 +59,17 @@ public class NewFeedActivity extends SherlockActivity { getSupportActionBar().setDisplayHomeAsUpEnabled(true); - DatabaseConnection dbConn = new DatabaseConnection(this); + DatabaseConnectionOrm dbConn = new DatabaseConnectionOrm(this); folders = dbConn.getListOfFolders(); - folders.put("No folder", "0"); + folders.add(0, new Folder(0, "No folder")); + + String[] folderNames = new String[folders.size()]; + for(int i = 0; i < folders.size(); i++) { + folderNames[i] = folders.get(i).getLabel(); + } - String[] folderNames = folders.keySet().toArray(new String[folders.size()]); ArrayAdapter<String> spinnerArrayAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_dropdown_item, folderNames); mFolderView.setAdapter(spinnerArrayAdapter); @@ -92,7 +99,7 @@ public class NewFeedActivity extends SherlockActivity { return; } - String folderId = folders.get(mFolderView.getSelectedItem().toString()); + Folder folder = folders.get(mFolderView.getSelectedItemPosition()); // Reset errors. mFeedUrlView.setError(null); @@ -123,7 +130,7 @@ public class NewFeedActivity extends SherlockActivity { // Show a progress spinner, and kick off a background task to // perform the user login attempt. showProgress(true); - mAddFeedTask = new AddNewFeedTask(urlToFeed, folderId); + mAddFeedTask = new AddNewFeedTask(urlToFeed, folder.getId());//TODO needs testing! mAddFeedTask.execute((Void) null); } } @@ -186,10 +193,10 @@ public class NewFeedActivity extends SherlockActivity { public class AddNewFeedTask extends AsyncTask<Void, Void, Boolean> { private final String mUrlToFeed; - private final String mFolderId; + private final long mFolderId; - AddNewFeedTask(String urlToFeed, String folderId) { + AddNewFeedTask(String urlToFeed, long folderId) { this.mUrlToFeed = urlToFeed; this.mFolderId = folderId; } diff --git a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/NewsDetailActivity.java b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/NewsDetailActivity.java index 7f29f3fb..e44737a8 100644 --- a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/NewsDetailActivity.java +++ b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/NewsDetailActivity.java @@ -21,9 +21,10 @@ package de.luhmer.owncloudnewsreader; +import android.app.AlertDialog; +import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; -import android.database.Cursor; import android.graphics.Bitmap; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; @@ -38,25 +39,21 @@ import android.support.v4.view.ViewPager.OnPageChangeListener; import android.util.DisplayMetrics; import android.util.Log; import android.view.KeyEvent; +import android.view.Menu; +import android.view.MenuItem; -import com.actionbarsherlock.view.Menu; -import com.actionbarsherlock.view.MenuItem; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -import de.luhmer.owncloudnewsreader.database.DatabaseConnection; +import de.greenrobot.dao.query.LazyList; import de.luhmer.owncloudnewsreader.database.DatabaseConnection.SORT_DIRECTION; +import de.luhmer.owncloudnewsreader.database.DatabaseConnectionOrm; +import de.luhmer.owncloudnewsreader.database.model.RssItem; import de.luhmer.owncloudnewsreader.helper.PostDelayHandler; import de.luhmer.owncloudnewsreader.helper.ThemeChooser; -import de.luhmer.owncloudnewsreader.model.PodcastFeedItem; import de.luhmer.owncloudnewsreader.model.PodcastItem; import de.luhmer.owncloudnewsreader.reader.IReader; import de.luhmer.owncloudnewsreader.reader.owncloud.OwnCloud_Reader; import de.luhmer.owncloudnewsreader.widget.WidgetProvider; -public class NewsDetailActivity extends PodcastSherlockFragmentActivity { +public class NewsDetailActivity extends PodcastFragmentActivity { /** * The {@link android.support.v4.view.PagerAdapter} that will provide @@ -82,9 +79,9 @@ public class NewsDetailActivity extends PodcastSherlockFragmentActivity { IReader _Reader; //ArrayList<Integer> databaseItemIds; - DatabaseConnection dbConn; + DatabaseConnectionOrm dbConn; //public List<RssFile> rssFiles; - Cursor cursor; + LazyList<RssItem> rssItems; public static final String DATABASE_IDS_OF_ITEMS = "DATABASE_IDS_OF_ITEMS"; @@ -101,7 +98,7 @@ public class NewsDetailActivity extends PodcastSherlockFragmentActivity { pDelayHandler = new PostDelayHandler(this); _Reader = new OwnCloud_Reader(); - dbConn = new DatabaseConnection(this); + dbConn = new DatabaseConnectionOrm(this); Intent intent = getIntent(); //long subsciption_id = -1; @@ -125,25 +122,19 @@ public class NewsDetailActivity extends PodcastSherlockFragmentActivity { // databaseItemIds = intent.getIntegerArrayListExtra(DATABASE_IDS_OF_ITEMS); - SORT_DIRECTION sDirection = SORT_DIRECTION.asc; - String sortDirection = mPrefs.getString(SettingsActivity.SP_SORT_ORDER, "1"); - if(sortDirection.equals("1")) - sDirection = SORT_DIRECTION.desc; - cursor = dbConn.getCurrentSelectedRssItems(sDirection); + rssItems = dbConn.getCurrentRssItemView(getSortDirectionFromSettings(this)); //If the Activity gets started from the Widget, read the item id and get the selected index in the cursor. - if(intent.hasExtra(WidgetProvider.UID_TODO)) { - cursor.moveToFirst(); - String rss_item_id = intent.getExtras().getString(WidgetProvider.UID_TODO); - do { - String current_item_id = cursor.getString(cursor.getColumnIndex(DatabaseConnection.RSS_ITEM_RSSITEM_ID)); - if(rss_item_id.equals(current_item_id)) { - getSupportActionBar().setTitle(cursor.getString(cursor.getColumnIndex(DatabaseConnection.RSS_ITEM_TITLE))); + if(intent.hasExtra(WidgetProvider.RSS_ITEM_ID)) { + long rss_item_id = intent.getExtras().getLong(WidgetProvider.RSS_ITEM_ID); + for(RssItem rssItem : rssItems) { + if(rss_item_id == rssItem.getId()) { + getSupportActionBar().setTitle(rssItem.getTitle()); break; } else item_id++; - } while(cursor.moveToNext()); + } } // Create the adapter that will return a fragment for each of the three @@ -181,11 +172,17 @@ public class NewsDetailActivity extends PodcastSherlockFragmentActivity { }); } + public static SORT_DIRECTION getSortDirectionFromSettings(Context context) { + SORT_DIRECTION sDirection = SORT_DIRECTION.asc; + SharedPreferences mPrefs = PreferenceManager.getDefaultSharedPreferences(context); + String sortDirection = mPrefs.getString(SettingsActivity.SP_SORT_ORDER, "1"); + if (sortDirection.equals("1")) + sDirection = SORT_DIRECTION.desc; + return sDirection; + } @Override protected void onDestroy() { - if(dbConn != null) - dbConn.closeDatabase(); super.onDestroy(); } @@ -196,7 +193,7 @@ public class NewsDetailActivity extends PodcastSherlockFragmentActivity { { if ((keyCode == KeyEvent.KEYCODE_VOLUME_DOWN)) { - if(currentPosition < cursor.getCount() -1) + if(currentPosition < rssItems.size()-1) { mViewPager.setCurrentItem(currentPosition + 1, true); return true; @@ -237,34 +234,18 @@ public class NewsDetailActivity extends PodcastSherlockFragmentActivity { currentPosition = position; ResumeVideoPlayersOnCurrentPage(); - //String idFeed = String.valueOf(rssFiles.get(position).getDB_Id()); - String idFeed = getIdCurrentRssItem(currentPosition); - - if(!dbConn.isFeedUnreadStarred(idFeed, true)) + if(!rssItems.get(position).getRead_temp()) { - markItemAsReadUnread(idFeed, true); + markItemAsReadUnread(rssItems.get(position), true); pDelayHandler.DelayTimer(); - Log.d("PAGE CHANGED", "PAGE: " + position + " - IDFEED: " + idFeed); + Log.d("PAGE CHANGED", "PAGE: " + position + " - IDFEED: " + rssItems.get(position).getId()); } else //Only in else because the function markItemAsReas updates the ActionBar items as well UpdateActionBarIcons(); } - /** - * Returns the id of a feed. When the position is invalid, -1 is returned. - * @param position - * @return - */ - public String getIdCurrentRssItem(int position) { - if(position < cursor.getCount()) { - cursor.moveToPosition(position); - String idFeed = String.valueOf(cursor.getString(0)); - return idFeed; - } - return "-1"; - } private void ResumeVideoPlayersOnCurrentPage() { @@ -283,18 +264,40 @@ public class NewsDetailActivity extends PodcastSherlockFragmentActivity { public void UpdateActionBarIcons() { - String idRssItem = getIdCurrentRssItem(currentPosition); - boolean isStarred = false; - boolean isRead = false; + /* + if(menuItem_PlayPodcast == null + || menuItem_Read == null + || menuItem_Starred == null) + return; + */ + + RssItem rssItem = rssItems.get(currentPosition); + + boolean isStarred = rssItem.getStarred_temp(); + boolean isRead = rssItem.getRead_temp(); + + + PodcastItem podcastItem = DatabaseConnectionOrm.ParsePodcastItemFromRssItem(this, rssItem); + boolean podcastAvailable = !podcastItem.link.equals(""); + - if(idRssItem != "-1") { - isStarred = dbConn.isFeedUnreadStarred(idRssItem, false); - isRead = dbConn.isFeedUnreadStarred(idRssItem, true); + if(podcastAvailable && !PodcastFragmentActivity.IsPodcastViewEnabled(this)) { + SharedPreferences mPrefs = PreferenceManager.getDefaultSharedPreferences(this); + if(!mPrefs.getBoolean(Constants.SHOW_CASE_PODCAST_AVAILABLE_INFO_SHOWN_BOOLEAN, false)) { + mPrefs.edit().putBoolean(Constants.SHOW_CASE_PODCAST_AVAILABLE_INFO_SHOWN_BOOLEAN, true).commit(); - PodcastItem podcastItem = dbConn.getPodcastForItem(this, idRssItem); - menuItem_PlayPodcast.setVisible((podcastItem != null && PodcastSherlockFragmentActivity.IsPodcastViewEnabled(this))); + new AlertDialog.Builder(this) + .setTitle("Podcast detected") + .setMessage("You can enable the podcast support in the app settings") + .setNeutralButton(getString(android.R.string.ok), null) + .show(); + } } + if(menuItem_PlayPodcast != null) + menuItem_PlayPodcast.setVisible((podcastAvailable && PodcastFragmentActivity.IsPodcastViewEnabled(this))); + + //if(rssFiles.get(currentPosition).getStarred() && menuItem_Starred != null) if(isStarred && menuItem_Starred != null) @@ -346,7 +349,7 @@ public class NewsDetailActivity extends PodcastSherlockFragmentActivity { public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. //getMenuInflater().inflate(R.menu.news_detail, menu); - getSupportMenuInflater().inflate(R.menu.news_detail, menu); + getMenuInflater().inflate(R.menu.news_detail, menu); menuItem_Starred = menu.findItem(R.id.action_starred); menuItem_Read = menu.findItem(R.id.action_read); @@ -358,15 +361,7 @@ public class NewsDetailActivity extends PodcastSherlockFragmentActivity { @Override public boolean onOptionsItemSelected(MenuItem item) { - String idFeed = getIdCurrentRssItem(currentPosition); - Cursor cursor = dbConn.getArticleByID(idFeed); - - String currentUrl = ""; - if(cursor != null) - { - cursor.moveToFirst(); - currentUrl = cursor.getString(cursor.getColumnIndex(DatabaseConnection.RSS_ITEM_LINK)); - } + RssItem rssItem = rssItems.get(currentPosition); switch (item.getItemId()) { case android.R.id.home: @@ -377,25 +372,15 @@ public class NewsDetailActivity extends PodcastSherlockFragmentActivity { break; case R.id.action_read: - - if(cursor != null) - { - cursor.moveToFirst(); - String id = cursor.getString(0); - markItemAsReadUnread(id, !menuItem_Read.isChecked()); - cursor.close(); - } - + markItemAsReadUnread(rssItem, !menuItem_Read.isChecked()); UpdateActionBarIcons(); - pDelayHandler.DelayTimer(); - break; case R.id.action_starred: - Boolean curState = dbConn.isFeedUnreadStarred(idFeed, false); - - dbConn.updateIsStarredOfItem(idFeed, !curState); + Boolean curState = rssItem.getStarred_temp(); + rssItem.setStarred_temp(!curState); + dbConn.updateRssItem(rssItem); UpdateActionBarIcons(); @@ -410,12 +395,11 @@ public class NewsDetailActivity extends PodcastSherlockFragmentActivity { break; case R.id.action_openInBrowser: - //String link = rssFiles.get(currentPosition).getLink(); + String link = rssItem.getLink(); - //if(!link.isEmpty()) - if(currentUrl.trim().length() > 0) + if(link.length() > 0) { - Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(currentUrl)); + Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(link)); startActivity(browserIntent); } break; @@ -447,17 +431,14 @@ public class NewsDetailActivity extends PodcastSherlockFragmentActivity { */ case R.id.action_playPodcast: - PodcastItem podcastItem = dbConn.getPodcastForItem(this, idFeed); + PodcastItem podcastItem = DatabaseConnectionOrm.ParsePodcastItemFromRssItem(this, rssItem); PodcastFragment.OpenPodcast(NewsDetailActivity.this, podcastItem); break; case R.id.action_ShareItem: - String title = ""; - String content = currentUrl; - - if(cursor != null) - title = cursor.getString(cursor.getColumnIndex(DatabaseConnection.RSS_ITEM_TITLE)); + String title = rssItem.getTitle(); + String content = rssItem.getLink(); NewsDetailFragment fragment = (NewsDetailFragment) getSupportFragmentManager().findFragmentByTag("android:switcher:" + R.id.pager + ":" + currentPosition); if(fragment != null) { // could be null if not instantiated yet @@ -482,15 +463,13 @@ public class NewsDetailActivity extends PodcastSherlockFragmentActivity { } - if(cursor != null) - cursor.close(); - return super.onOptionsItemSelected(item); } - private void markItemAsReadUnread(String item_id, boolean read) { - dbConn.updateIsReadOfItem(item_id, read); + private void markItemAsReadUnread(RssItem item, boolean read) { + item.setRead_temp(read); + dbConn.updateRssItem(item); UpdateActionBarIcons(); } @@ -552,7 +531,8 @@ public class NewsDetailActivity extends PodcastSherlockFragmentActivity { @Override public int getCount() { - return cursor.getCount(); + //return cursor.getCount(); + return rssItems.size(); } @Override diff --git a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/NewsDetailFragment.java b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/NewsDetailFragment.java index ecf60179..2b04f019 100644 --- a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/NewsDetailFragment.java +++ b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/NewsDetailFragment.java @@ -24,10 +24,10 @@ package de.luhmer.owncloudnewsreader; import android.annotation.SuppressLint; import android.annotation.TargetApi; import android.content.Context; -import android.database.Cursor; import android.graphics.Color; import android.os.Build; import android.os.Bundle; +import android.support.v4.app.Fragment; import android.text.format.DateUtils; import android.view.LayoutInflater; import android.view.View; @@ -38,21 +38,19 @@ import android.webkit.WebView; import android.webkit.WebViewClient; import android.widget.ProgressBar; -import com.actionbarsherlock.app.SherlockFragment; - import java.io.File; import java.io.InputStream; import java.util.Date; import java.util.List; -import de.luhmer.owncloudnewsreader.database.DatabaseConnection; +import de.luhmer.owncloudnewsreader.database.model.RssItem; import de.luhmer.owncloudnewsreader.helper.FileUtils; import de.luhmer.owncloudnewsreader.helper.FontHelper; import de.luhmer.owncloudnewsreader.helper.ImageHandler; import de.luhmer.owncloudnewsreader.helper.ThemeChooser; import de.luhmer.owncloudnewsreader.interfaces.WebViewLinkLongClickInterface; -public class NewsDetailFragment extends SherlockFragment { +public class NewsDetailFragment extends Fragment { public static final String ARG_SECTION_NUMBER = "ARG_SECTION_NUMBER"; public static final String TAG = "NewsDetailFragment"; @@ -153,8 +151,10 @@ public class NewsDetailFragment extends SherlockFragment { init_webView(); NewsDetailActivity nrda = ((NewsDetailActivity)getActivity()); - String idItem = nrda.getIdCurrentRssItem(section_number - 1); - webview.loadDataWithBaseURL("", getHtmlPage(ndActivity, ndActivity.dbConn, Integer.parseInt(idItem)), "text/html", "UTF-8", ""); + RssItem rssItem = nrda.rssItems.get(section_number - 1); + + + webview.loadDataWithBaseURL("", getHtmlPage(ndActivity, rssItem), "text/html", "UTF-8", ""); } @SuppressLint("SetJavaScriptEnabled") @@ -242,7 +242,7 @@ public class NewsDetailFragment extends SherlockFragment { @SuppressLint("SimpleDateFormat") - public static String getHtmlPage(Context context, DatabaseConnection dbConn, int idItem) + public static String getHtmlPage(Context context, RssItem rssItem) { init_webTemplate(context); String htmlData = web_template; @@ -250,99 +250,70 @@ public class NewsDetailFragment extends SherlockFragment { //RssFile rssFile = ((NewsDetailActivity)getActivity()).rssFiles.get(section_number - 1); //int idItem = ndActivity.databaseItemIds.get(section_number - 1); - Cursor cursor = dbConn.getArticleByID(String.valueOf(idItem)); - cursor.moveToFirst(); - String favIconUrl = ""; + + String favIconUrl = rssItem.getFeed().getFaviconUrl(); try { - Cursor favIconCursor = dbConn.getFeedByDbID(cursor.getString(cursor.getColumnIndex(DatabaseConnection.RSS_ITEM_SUBSCRIPTION_ID))); - try - { - favIconCursor.moveToFirst(); - if(favIconCursor.getCount() > 0) - { - favIconUrl = favIconCursor.getString(favIconCursor.getColumnIndex(DatabaseConnection.SUBSCRIPTION_FAVICON_URL)); - if(favIconUrl != null) - { - File file = ImageHandler.getFullPathOfCacheFile(favIconUrl, FileUtils.getPathFavIcons(context)); - if(file.isFile()) - favIconUrl = "file://" + file.getAbsolutePath().toString(); - } - else - favIconUrl = "file:///android_res/drawable/default_feed_icon_light.png"; - } - } catch(Exception ex) { - ex.printStackTrace(); - } finally { - favIconCursor.close(); - } + if(favIconUrl != null) + { + File file = ImageHandler.getFullPathOfCacheFile(favIconUrl, FileUtils.getPathFavIcons(context)); + if(file.isFile()) + favIconUrl = "file://" + file.getAbsolutePath().toString(); + } + else { + favIconUrl = "file:///android_res/drawable/default_feed_icon_light.png"; + } + } catch(Exception ex) { + ex.printStackTrace(); + } - String divHeader = "<div id=\"header\">"; - StringBuilder sb = new StringBuilder(htmlData); - //htmlData = sb.insert(htmlData.indexOf(divHeader) + divHeader.length(), rssFile.getTitle().trim()).toString(); - String title = cursor.getString(cursor.getColumnIndex(DatabaseConnection.RSS_ITEM_TITLE)); - String linkToFeed = cursor.getString(cursor.getColumnIndex(DatabaseConnection.RSS_ITEM_LINK)); - title = "<a href=\"" + linkToFeed + "\">" + title + "</a>"; - htmlData = sb.insert(htmlData.indexOf(divHeader) + divHeader.length(), title.trim()).toString(); + String divHeader = "<div id=\"header\">"; + StringBuilder sb = new StringBuilder(htmlData); + //htmlData = sb.insert(htmlData.indexOf(divHeader) + divHeader.length(), rssFile.getTitle().trim()).toString(); + String title = rssItem.getTitle(); + String linkToFeed = rssItem.getLink(); + title = "<a href=\"" + linkToFeed + "\">" + title + "</a>"; + htmlData = sb.insert(htmlData.indexOf(divHeader) + divHeader.length(), title.trim()).toString(); - //String divSubscription = "<div id=\"subscription\">"; - //htmlData = sb.insert(htmlData.indexOf(divSubscription) + divSubscription.length(), rssFile.getStreamID().trim()).toString(); + //String divSubscription = "<div id=\"subscription\">"; + //htmlData = sb.insert(htmlData.indexOf(divSubscription) + divSubscription.length(), rssFile.getStreamID().trim()).toString(); - Date date = new Date(cursor.getLong(cursor.getColumnIndex(DatabaseConnection.RSS_ITEM_PUBDATE))); - if(date != null) - { - String divDate = "<div id=\"datetime\">"; - //SimpleDateFormat formater = new SimpleDateFormat(); - //String dateString = formater.format(date); - String dateString = (String) DateUtils.getRelativeTimeSpanString(date.getTime()); - htmlData = sb.insert(htmlData.indexOf(divDate) + divDate.length(), dateString).toString(); - } + Date date = rssItem.getPubDate(); + if(date != null) + { + String divDate = "<div id=\"datetime\">"; + //SimpleDateFormat formater = new SimpleDateFormat(); + //String dateString = formater.format(date); + String dateString = (String) DateUtils.getRelativeTimeSpanString(date.getTime()); + htmlData = sb.insert(htmlData.indexOf(divDate) + divDate.length(), dateString).toString(); + } - //String subscription = ((NewsDetailActivity) getActivity()).dbConn.getTitleOfSubscriptionByRowID(String.valueOf(rssFile.getFeedID_Db())); - //String subscription = dbConn.getTitleOfSubscriptionByDBItemID(String.valueOf(idItem)); - Cursor cursorFeed = dbConn.getFeedByDbID(cursor.getString(cursor.getColumnIndex(DatabaseConnection.RSS_ITEM_SUBSCRIPTION_ID))); - cursorFeed.moveToFirst(); - String subscription = cursorFeed.getString(cursorFeed.getColumnIndex(DatabaseConnection.SUBSCRIPTION_HEADERTEXT)).trim(); - cursorFeed.close(); - - String authorOfArticle = cursor.getString(cursor.getColumnIndex(DatabaseConnection.RSS_ITEM_AUTHOR)); - if(authorOfArticle != null) - if(!authorOfArticle.trim().equals("")) - subscription += " - " + authorOfArticle.trim(); - - String divSubscription = "<div id=\"subscription\">"; - int pos = htmlData.indexOf(divSubscription) + divSubscription.length(); - pos = htmlData.indexOf("/>", pos) + 2;//Wegen des Favicon <img /> - htmlData = sb.insert(pos, subscription.trim()).toString(); - - String divContent = "<div id=\"content\">"; - String description = cursor.getString(cursor.getColumnIndex(DatabaseConnection.RSS_ITEM_BODY)); - //htmlData = sb.insert(htmlData.indexOf(divContent) + divContent.length(), rssFile.getDescription().trim()).toString(); - htmlData = sb.insert(htmlData.indexOf(divContent) + divContent.length(), getDescriptionWithCachedImages(description, context).trim()).toString(); - - //String link = cursor.getString(cursor.getColumnIndex(DatabaseConnection.RSS_ITEM_LINK)); - //Uri uri = Uri.parse(rssFile.getLink()); - //Uri uri = Uri.parse(link); - //String domainName = uri.getHost(); - //String searchString = "http://s2.googleusercontent.com/s2/favicons?domain="; - //htmlData = sb.insert(htmlData.indexOf(searchString) + searchString.length(), domainName).toString(); - - String searchString = "<img id=\"imgFavicon\" src="; - htmlData = sb.insert(htmlData.indexOf(searchString) + searchString.length() + 1, favIconUrl).toString(); - - //htmlData = URLEncoder.encode(htmlData).replaceAll("\\+"," "); - - //webview.loadDataWithBaseURL("", htmlData, "text/html", "UTF-8", ""); - //webview.loadData(htmlData, "text/html; charset=UTF-8", "UTF-8"); - } catch (Exception e) { - e.printStackTrace(); - } finally { - cursor.close(); - } + //String subscription = ((NewsDetailActivity) getActivity()).dbConn.getTitleOfSubscriptionByRowID(String.valueOf(rssFile.getFeedID_Db())); + //String subscription = dbConn.getTitleOfSubscriptionByDBItemID(String.valueOf(idItem)); + + String feedTitle = rssItem.getFeed().getFeedTitle(); + + + String authorOfArticle = rssItem.getAuthor(); + if(authorOfArticle != null) + if(!authorOfArticle.trim().equals("")) + feedTitle += " - " + authorOfArticle.trim(); + + String divSubscription = "<div id=\"subscription\">"; + int pos = htmlData.indexOf(divSubscription) + divSubscription.length(); + pos = htmlData.indexOf("/>", pos) + 2;//Wegen des Favicon <img /> + htmlData = sb.insert(pos, feedTitle.trim()).toString(); + + String divContent = "<div id=\"content\">"; + String description = rssItem.getBody(); + htmlData = sb.insert(htmlData.indexOf(divContent) + divContent.length(), getDescriptionWithCachedImages(description, context).trim()).toString(); + + String searchString = "<img id=\"imgFavicon\" src="; + htmlData = sb.insert(htmlData.indexOf(searchString) + searchString.length() + 1, favIconUrl).toString(); return htmlData; } diff --git a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/NewsReaderDetailFragment.java b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/NewsReaderDetailFragment.java index 361abab7..33d99143 100644 --- a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/NewsReaderDetailFragment.java +++ b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/NewsReaderDetailFragment.java @@ -25,40 +25,42 @@ import android.app.Activity; import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; -import android.database.Cursor; -import android.database.sqlite.SQLiteCursor; import android.net.Uri; +import android.os.AsyncTask; import android.os.Bundle; import android.preference.PreferenceManager; -import android.support.v4.app.LoaderManager; -import android.support.v4.app.LoaderManager.LoaderCallbacks; -import android.support.v4.content.Loader; +import android.support.v4.app.FragmentActivity; +import android.support.v4.app.ListFragment; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.AbsListView; import android.widget.ListView; +import android.widget.ProgressBar; +import android.widget.TextView; -import com.actionbarsherlock.app.SherlockFragmentActivity; -import com.actionbarsherlock.app.SherlockListFragment; import com.devspark.robototextview.widget.RobotoCheckBox; import java.util.ArrayList; +import butterknife.ButterKnife; +import butterknife.InjectView; +import de.greenrobot.dao.query.LazyList; import de.luhmer.owncloudnewsreader.ListView.BlockingListView; import de.luhmer.owncloudnewsreader.ListView.SubscriptionExpandableListAdapter; +import de.luhmer.owncloudnewsreader.adapter.NewsListArrayAdapter; import de.luhmer.owncloudnewsreader.cursor.IOnStayUnread; import de.luhmer.owncloudnewsreader.cursor.NewsListCursorAdapter; -import de.luhmer.owncloudnewsreader.cursor.SimpleCursorLoader; -import de.luhmer.owncloudnewsreader.database.DatabaseConnection; import de.luhmer.owncloudnewsreader.database.DatabaseConnection.SORT_DIRECTION; +import de.luhmer.owncloudnewsreader.database.DatabaseConnectionOrm; +import de.luhmer.owncloudnewsreader.database.model.RssItem; /** * A fragment representing a single NewsReader detail screen. This fragment is * either contained in a {@link NewsReaderListActivity} in two-pane mode (on * tablets) or a {@link NewsReaderListActivity} on handsets. */ -public class NewsReaderDetailFragment extends SherlockListFragment implements IOnStayUnread { +public class NewsReaderDetailFragment extends ListFragment implements IOnStayUnread { /** * The fragment argument representing the item ID that this fragment * represents. @@ -67,7 +69,6 @@ public class NewsReaderDetailFragment extends SherlockListFragment implements IO protected static final String TAG = "NewsReaderDetailFragment"; - //private DatabaseConnection dbConn; //private boolean DialogShowedToMarkLastItemsAsRead = false; @@ -78,19 +79,19 @@ public class NewsReaderDetailFragment extends SherlockListFragment implements IO return lvAdapter; }*/ - String idFeed; + Long idFeed; /** * @return the idFeed */ - public String getIdFeed() { + public Long getIdFeed() { return idFeed; } - String idFolder; + Long idFolder; /** * @return the idFolder */ - public String getIdFolder() { + public Long getIdFolder() { return idFolder; } @@ -114,6 +115,9 @@ public class NewsReaderDetailFragment extends SherlockListFragment implements IO //private static ArrayList<Integer> databaseIdsOfItems; ArrayList<RobotoCheckBox> stayUnreadCheckboxes; + @InjectView(R.id.pb_loading) ProgressBar pbLoading; + @InjectView(R.id.tv_no_items_available) TextView tvNoItemsAvailable; + /** * Mandatory empty constructor for the fragment manager to instantiate the * fragment (e.g. upon screen orientation changes). @@ -139,22 +143,22 @@ public class NewsReaderDetailFragment extends SherlockListFragment implements IO public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - setRetainInstance(true); + //setRetainInstance(true); //dbConn = new DatabaseConnection(getActivity()); if(getArguments() != null) { - if (getArguments().containsKey(NewsReaderListActivity.SUBSCRIPTION_ID)) { - idFeed = getArguments().getString(NewsReaderListActivity.SUBSCRIPTION_ID); + if (getArguments().containsKey(NewsReaderListActivity.FEED_ID)) { + idFeed = getArguments().getLong(NewsReaderListActivity.FEED_ID); } if (getArguments().containsKey(NewsReaderListActivity.TITEL)) { titel = getArguments().getString(NewsReaderListActivity.TITEL); } if (getArguments().containsKey(NewsReaderListActivity.FOLDER_ID)) { - idFolder = getArguments().getString(NewsReaderListActivity.FOLDER_ID); + idFolder = getArguments().getLong(NewsReaderListActivity.FOLDER_ID); } - ((SherlockFragmentActivity) getActivity()).getSupportActionBar().setTitle(titel); + getActivity().getActionBar().setTitle(titel); UpdateMenuItemsState();//Is called on Tablets and Smartphones but on Smartphones the menuItemDownloadMoreItems is null. So it will be ignored @@ -162,27 +166,22 @@ public class NewsReaderDetailFragment extends SherlockListFragment implements IO //lvAdapter = null; - getActivity().getSupportLoaderManager().destroyLoader(0); - - if(reloadCursorOnStartUp) - UpdateCurrentRssView(getActivity()); - - UpdateCursor(); + //getActivity().getSupportLoaderManager().destroyLoader(0); } } public void UpdateMenuItemsState() { - if(MenuUtilsSherlockFragmentActivity.getMenuItemDownloadMoreItems() != null) + if(MenuUtilsFragmentActivity.getMenuItemDownloadMoreItems() != null) { if(idFolder != null) { - if(idFolder.equals(SubscriptionExpandableListAdapter.SPECIAL_FOLDERS.ALL_UNREAD_ITEMS.getValueString())) - MenuUtilsSherlockFragmentActivity.getMenuItemDownloadMoreItems().setEnabled(false); + if(idFolder == SubscriptionExpandableListAdapter.SPECIAL_FOLDERS.ALL_UNREAD_ITEMS.getValue()) + MenuUtilsFragmentActivity.getMenuItemDownloadMoreItems().setEnabled(false); else - MenuUtilsSherlockFragmentActivity.getMenuItemDownloadMoreItems().setEnabled(true); + MenuUtilsFragmentActivity.getMenuItemDownloadMoreItems().setEnabled(true); } else - MenuUtilsSherlockFragmentActivity.getMenuItemDownloadMoreItems().setEnabled(false); + MenuUtilsFragmentActivity.getMenuItemDownloadMoreItems().setEnabled(false); } } @@ -192,6 +191,7 @@ public class NewsReaderDetailFragment extends SherlockListFragment implements IO */ @Override public void onViewCreated(View view, Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); SharedPreferences mPrefs = PreferenceManager.getDefaultSharedPreferences(getActivity()); if(mPrefs.getBoolean(SettingsActivity.CB_MARK_AS_READ_WHILE_SCROLLING_STRING, false)) @@ -219,7 +219,12 @@ public class NewsReaderDetailFragment extends SherlockListFragment implements IO }); } - super.onViewCreated(view, savedInstanceState); + if(reloadCursorOnStartUp) + UpdateCurrentRssView(getActivity(), true); + else + UpdateCurrentRssView(getActivity(), false); + + //UpdateCursor(); } @@ -247,128 +252,130 @@ public class NewsReaderDetailFragment extends SherlockListFragment implements IO super.onDestroy(); } - public void UpdateCursor() + + + public void notifyDataSetChangedOnAdapter() { - try - { - LoaderManager loader = getActivity().getSupportLoaderManager(); - loader.initLoader(0, null, loaderCallbacks); - } - catch(Exception ex) - { - ex.printStackTrace(); - } + NewsListArrayAdapter nca = (NewsListArrayAdapter) getListAdapter(); + if(nca != null) + nca.notifyDataSetChanged(); + + //NewsListCursorAdapter nca = (NewsListCursorAdapter) getListAdapter(); + //if(nca != null) + //((NewsListCursorAdapter) getListAdapter()).notifyDataSetChanged(); } - public LoaderCallbacks<Cursor> loaderCallbacks = new LoaderCallbacks<Cursor>() { - @Override - public Loader<Cursor> onCreateLoader(int id, Bundle args) { - return new NewsDetailCursorLoader(getActivity(), idFolder, idFeed); - } + /** + * Updates the current RSS-View + * @param context + */ + public void UpdateCurrentRssView(Context context, boolean refreshCurrentRssView) { + new UpdateCurrentRssViewTask(context, refreshCurrentRssView).execute((Void) null);//TODO api level 11--> new method + } - @Override - public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) { - NewsListCursorAdapter nca = (NewsListCursorAdapter) getListAdapter(); + private class UpdateCurrentRssViewTask extends AsyncTask<Void, Void, LazyList<RssItem>> { - // Block children layout for now - BlockingListView bView = ((BlockingListView) getListView()); + Context context; + SORT_DIRECTION sortDirection; + boolean refreshCurrentRssView; - bView.setBlockLayoutChildren(true); + public UpdateCurrentRssViewTask(Context context, boolean refreshCurrentRssView) { + this.context = context; + this.refreshCurrentRssView = refreshCurrentRssView; + } - if(nca == null) { - NewsListCursorAdapter lvAdapter = new NewsListCursorAdapter(getActivity(), null, NewsReaderDetailFragment.this); - setListAdapter(lvAdapter); - nca = lvAdapter; - } - nca.swapCursor(cursor); - - if(cursor.getCount() <= 0) { - getListView().setVisibility(View.GONE); - getActivity().findViewById(R.id.tv_no_items_available).setVisibility(View.VISIBLE); - } else { - getListView().setVisibility(View.VISIBLE); - getActivity().findViewById(R.id.tv_no_items_available).setVisibility(View.GONE); - } + @Override + protected void onPreExecute() { + pbLoading.setVisibility(View.VISIBLE); + getListView().setVisibility(View.GONE); + tvNoItemsAvailable.setVisibility(View.GONE); - try { - if(mActivatedPosition != ListView.INVALID_POSITION && marginFromTop != ListView.INVALID_POSITION) - getListView().setSelectionFromTop(mActivatedPosition, marginFromTop); - else if(mActivatedPosition != ListView.INVALID_POSITION) - getListView().setSelection(mActivatedPosition); - } catch(Exception ex) { - ex.printStackTrace(); - } + sortDirection = getSortDirection(context); - bView.setBlockLayoutChildren(false); - //((NewsListCursorAdapter) getListAdapter()).changeCursor(cursor); + super.onPreExecute(); } @Override - public void onLoaderReset(Loader<Cursor> loader) { - NewsListCursorAdapter nca = (NewsListCursorAdapter) getListAdapter(); - if(nca != null) - ((NewsListCursorAdapter) getListAdapter()).swapCursor(null); + protected LazyList<RssItem> doInBackground(Void... urls) { + DatabaseConnectionOrm dbConn = new DatabaseConnectionOrm(context); + + if(refreshCurrentRssView) { + SharedPreferences mPrefs = PreferenceManager.getDefaultSharedPreferences(context); + boolean onlyUnreadItems = mPrefs.getBoolean(SettingsActivity.CB_SHOWONLYUNREAD_STRING, false); + boolean onlyStarredItems = false; + if (idFolder != null) + if (idFolder == SubscriptionExpandableListAdapter.SPECIAL_FOLDERS.ALL_STARRED_ITEMS.getValue()) + onlyStarredItems = true; + + String sqlSelectStatement = null; + if (idFeed != null) + sqlSelectStatement = dbConn.getAllItemsIdsForFeedSQL(idFeed, onlyUnreadItems, onlyStarredItems, sortDirection); + else if (idFolder != null) { + if (idFolder == SubscriptionExpandableListAdapter.SPECIAL_FOLDERS.ALL_STARRED_ITEMS.getValue()) + onlyUnreadItems = false; + sqlSelectStatement = dbConn.getAllItemsIdsForFolderSQL(idFolder, onlyUnreadItems, sortDirection); + } + if (sqlSelectStatement != null) { + dbConn.insertIntoRssCurrentViewTable(sqlSelectStatement); + } + } + return dbConn.getCurrentRssItemView(sortDirection); } - }; - public void notifyDataSetChangedOnAdapter() - { - NewsListCursorAdapter nca = (NewsListCursorAdapter) getListAdapter(); - if(nca != null) - ((NewsListCursorAdapter) getListAdapter()).notifyDataSetChanged(); - } + @Override + protected void onPostExecute(LazyList<RssItem> rssItemLazyList) { + try + { + // Block children layout for now + BlockingListView bView = ((BlockingListView) getListView()); - public void UpdateCurrentRssView(Context context) { - SharedPreferences mPrefs = PreferenceManager.getDefaultSharedPreferences(context); - boolean onlyUnreadItems = mPrefs.getBoolean(SettingsActivity.CB_SHOWONLYUNREAD_STRING, false); - boolean onlyStarredItems = false; - if(idFolder != null) - if(idFolder.equals(SubscriptionExpandableListAdapter.SPECIAL_FOLDERS.ALL_STARRED_ITEMS.getValueString())) - onlyStarredItems = true; - - DatabaseConnection dbConn = new DatabaseConnection(context); - - dbConn.clearDatabaseOverSize(); - - String sqlSelectStatement = null; - if(idFeed != null) - sqlSelectStatement = dbConn.getAllItemsIdsForFeedSQL(idFeed, onlyUnreadItems, onlyStarredItems, getSortDirection(context)); - else if(idFolder != null) - { - if(idFolder.equals(SubscriptionExpandableListAdapter.SPECIAL_FOLDERS.ALL_STARRED_ITEMS.getValueString())) - onlyUnreadItems = false; - sqlSelectStatement = dbConn.getAllItemsIdsForFolderSQL(idFolder, onlyUnreadItems, getSortDirection(context)); - } - if(sqlSelectStatement != null) { - dbConn.insertIntoRssCurrentViewTable(sqlSelectStatement); - } - } + bView.setBlockLayoutChildren(true); - public static SORT_DIRECTION getSortDirection(Context context) { - SharedPreferences mPrefs = PreferenceManager.getDefaultSharedPreferences(context); - SORT_DIRECTION sDirection = SORT_DIRECTION.asc; - String sortDirection = mPrefs.getString(SettingsActivity.SP_SORT_ORDER, "1"); - if(sortDirection.equals("1")) - sDirection = SORT_DIRECTION.desc; + NewsListArrayAdapter lvAdapter = new NewsListArrayAdapter(getActivity(), rssItemLazyList, NewsReaderDetailFragment.this); + setListAdapter(lvAdapter); - return sDirection; + pbLoading.setVisibility(View.GONE); + if(lvAdapter.getCount() <= 0) { + getListView().setVisibility(View.GONE); + tvNoItemsAvailable.setVisibility(View.VISIBLE); + } else { + getListView().setVisibility(View.VISIBLE); + tvNoItemsAvailable.setVisibility(View.GONE); + } + + try { + if(mActivatedPosition != ListView.INVALID_POSITION && marginFromTop != ListView.INVALID_POSITION) + getListView().setSelectionFromTop(mActivatedPosition, marginFromTop); + else if(mActivatedPosition != ListView.INVALID_POSITION) + getListView().setSelection(mActivatedPosition); + } catch(Exception ex) { + ex.printStackTrace(); + } + + bView.setBlockLayoutChildren(false); + } + catch(Exception ex) + { + ex.printStackTrace(); + } + } } - public static Cursor getRightCusor(Context context /*, String idFolder, String idFeed */) - { - DatabaseConnection dbConn = new DatabaseConnection(context); - return dbConn.getCurrentSelectedRssItems(getSortDirection(context)); + + public static SORT_DIRECTION getSortDirection(Context context) { + return NewsDetailActivity.getSortDirectionFromSettings(context); } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View rootView = inflater.inflate(R.layout.fragment_newsreader_detail, container, false); + ButterKnife.inject(this, rootView); return rootView; } - + /* public static class NewsDetailCursorLoader extends SimpleCursorLoader { String idFolder; String idFeed; @@ -381,17 +388,17 @@ public class NewsReaderDetailFragment extends SherlockListFragment implements IO @Override public Cursor loadInBackground() { - return getRightCusor(getContext() /*, idFolder, idFeed */); + return getRightCusor(getContext()); } } + */ @Override public void onListItemClick(ListView l, View v, int position, long id) { SharedPreferences mPrefs = PreferenceManager.getDefaultSharedPreferences(getActivity()); if(mPrefs.getBoolean(SettingsActivity.CB_SKIP_DETAILVIEW_AND_OPEN_BROWSER_DIRECTLY_STRING, false)) { - Cursor c = ((SQLiteCursor) l.getAdapter().getItem(position)); - String currentUrl = c.getString(c.getColumnIndex(DatabaseConnection.RSS_ITEM_LINK)); + String currentUrl = ((NewsListArrayAdapter) getListAdapter()).getItem(position).getLink(); Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(currentUrl)); startActivity(browserIntent); diff --git a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/NewsReaderListActivity.java b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/NewsReaderListActivity.java index 93848dde..5bdc6598 100644 --- a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/NewsReaderListActivity.java +++ b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/NewsReaderListActivity.java @@ -36,23 +36,28 @@ import android.support.v4.app.FragmentActivity; import android.support.v4.app.FragmentManager; import android.support.v4.widget.SlidingPaneLayout; import android.support.v4.widget.SlidingPaneLayout.PanelSlideListener; +import android.support.v4.widget.SwipeRefreshLayout; +import android.view.Menu; +import android.view.MenuItem; import android.view.View; -import com.actionbarsherlock.app.SherlockFragmentActivity; -import com.actionbarsherlock.view.Menu; -import com.actionbarsherlock.view.MenuItem; +import com.github.amlcurran.showcaseview.OnShowcaseEventListener; +import com.github.amlcurran.showcaseview.ShowcaseView; +import com.github.amlcurran.showcaseview.targets.ViewTarget; +import de.greenrobot.event.EventBus; import de.luhmer.owncloudnewsreader.ListView.SubscriptionExpandableListAdapter; import de.luhmer.owncloudnewsreader.LoginDialogFragment.LoginSuccessfullListener; +import de.luhmer.owncloudnewsreader.adapter.NewsListArrayAdapter; import de.luhmer.owncloudnewsreader.authentication.AccountGeneral; -import de.luhmer.owncloudnewsreader.cursor.NewsListCursorAdapter; -import de.luhmer.owncloudnewsreader.database.DatabaseConnection; +import de.luhmer.owncloudnewsreader.database.DatabaseConnectionOrm; +import de.luhmer.owncloudnewsreader.events.podcast.FeedPanelSlideEvent; import de.luhmer.owncloudnewsreader.helper.DatabaseUtils; import de.luhmer.owncloudnewsreader.helper.ImageHandler; +import de.luhmer.owncloudnewsreader.helper.ShowcaseDimHelper; import de.luhmer.owncloudnewsreader.helper.ThemeChooser; import de.luhmer.owncloudnewsreader.services.DownloadImagesService; import de.luhmer.owncloudnewsreader.services.IOwnCloudSyncService; -import uk.co.senab.actionbarpulltorefresh.extras.actionbarsherlock.PullToRefreshLayout; /** * An activity representing a list of NewsReader. This activity has different @@ -65,7 +70,7 @@ import uk.co.senab.actionbarpulltorefresh.extras.actionbarsherlock.PullToRefresh * {@link NewsReaderListFragment.Callbacks} interface to listen for item * selections. */ -public class NewsReaderListActivity extends MenuUtilsSherlockFragmentActivity implements +public class NewsReaderListActivity extends MenuUtilsFragmentActivity implements NewsReaderListFragment.Callbacks { SlidingPaneLayout mSlidingLayout; @@ -76,7 +81,7 @@ public class NewsReaderListActivity extends MenuUtilsSherlockFragmentActivity im //DrawerLayout drawerLayout; public static final String FOLDER_ID = "FOLDER_ID"; - public static final String SUBSCRIPTION_ID = "SUBSCRIPTION_ID"; + public static final String FEED_ID = "FEED_ID"; public static final String ITEM_ID = "ITEM_ID"; public static final String TITEL = "TITEL"; @@ -85,15 +90,15 @@ public class NewsReaderListActivity extends MenuUtilsSherlockFragmentActivity im @TargetApi(Build.VERSION_CODES.HONEYCOMB) @Override protected void onCreate(Bundle savedInstanceState) { - ThemeChooser.chooseTheme(this); - - //setTheme(R.style.Theme_Sherlock); - super.onCreate(savedInstanceState); setContentView(R.layout.activity_newsreader); + //DaoSession session = DatabaseHelperOrm.getDaoSession(this); + + + AccountManager mAccountManager = AccountManager.get(this); boolean isAccountThere = false; @@ -163,6 +168,8 @@ public class NewsReaderListActivity extends MenuUtilsSherlockFragmentActivity im getMenuItemUpdater().setVisible(true); StartDetailFragmentNow(); + + EventBus.getDefault().post(new FeedPanelSlideEvent(false)); } }); mSlidingLayout.openPane(); @@ -170,43 +177,53 @@ public class NewsReaderListActivity extends MenuUtilsSherlockFragmentActivity im + if(savedInstanceState == null)//When the app starts (no orientation change) + { + startDetailFHolder = new StartDetailFragmentHolder(SubscriptionExpandableListAdapter.SPECIAL_FOLDERS.ALL_UNREAD_ITEMS.getValue(), true, null, true); + StartDetailFragmentNow(); + } + ImageHandler.createNoMediaFile(this); + //AppRater.app_launched(this); + //AppRater.rateNow(this); + } + @TargetApi(Build.VERSION_CODES.HONEYCOMB) + public void showShowCaseViewForView(final View dimView, View targetView, String title, String text) { + if(!ShowcaseDimHelper.isHoneycombOrAbove())//Showcase View is only supported on API Level 11+ + return; + ShowcaseDimHelper.dimView(dimView); + ViewTarget target = new ViewTarget(targetView); + ShowcaseView sv = new ShowcaseView.Builder(this) + .setTarget(target) + .setContentTitle(title) + .setContentText(text) + .hideOnTouchOutside() + .build(); - /* - // Get a reference of the DrawerLayout - drawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout); - */ - - // Set a listener to be notified of drawer events. - //drawerLayout.setDrawerListener(drawerToggle); - - - //if(mPrefs.getBoolean(SettingsActivity.CB_SYNCONSTARTUP_STRING, false)) - // startSync(); + sv.setOnShowcaseEventListener(new OnShowcaseEventListener() { + @TargetApi(Build.VERSION_CODES.HONEYCOMB) + @Override + public void onShowcaseViewHide(ShowcaseView showcaseView) { + ShowcaseDimHelper.undoDimView(dimView); + } - /* - if(!shouldDrawerStayOpen()) { - getSupportActionBar().setDisplayHomeAsUpEnabled(true); - getSupportActionBar().setHomeButtonEnabled(true); - }*/ + @Override + public void onShowcaseViewDidHide(ShowcaseView showcaseView) { - if(savedInstanceState == null)//When the app starts (no orientation change) - { - startDetailFHolder = new StartDetailFragmentHolder(SubscriptionExpandableListAdapter.SPECIAL_FOLDERS.ALL_UNREAD_ITEMS.getValueString(), true, null, true); - StartDetailFragmentNow(); - } + } + @Override + public void onShowcaseViewShow(ShowcaseView showcaseView) { - ImageHandler.createNoMediaFile(this); - //AppRater.app_launched(this); - //AppRater.rateNow(this); + } + }); - //onTopItemClicked(SubscriptionExpandableListAdapter.ALL_UNREAD_ITEMS, true, null); + sv.show(); } @@ -229,17 +246,21 @@ public class NewsReaderListActivity extends MenuUtilsSherlockFragmentActivity im super.onSaveInstanceState(outState); } + public NewsReaderDetailFragment getNewsReaderDetailFragment() { + return ((NewsReaderDetailFragment) getSupportFragmentManager().findFragmentById(R.id.content_frame)); + } + private void safeInstanceState(Bundle outState) { - NewsReaderDetailFragment ndf = ((NewsReaderDetailFragment) getSupportFragmentManager().findFragmentById(R.id.content_frame)); + NewsReaderDetailFragment ndf = getNewsReaderDetailFragment(); if(ndf != null) { View v = ndf.getListView().getChildAt(0); int top = (v == null) ? 0 : v.getTop(); outState.putInt(FIRST_VISIBLE_DETAIL_ITEM_STRING, ndf.getListView().getFirstVisiblePosition()); outState.putInt(FIRST_VISIBLE_DETAIL_ITEM_MARGIN_TOP_STRING, top); - outState.putString(OPTIONAL_FOLDER_ID, ndf.getIdFeed() == null ? ndf.getIdFolder() : ndf.getIdFeed()); + outState.putLong(OPTIONAL_FOLDER_ID, ndf.getIdFeed() == null ? ndf.getIdFolder() : ndf.getIdFeed()); outState.putBoolean(IS_FOLDER_BOOLEAN, ndf.getIdFeed() == null); - outState.putString(ID_FEED_STRING, ndf.getIdFeed() != null ? ndf.getIdFolder() : ndf.getIdFeed()); + outState.putLong(ID_FEED_STRING, ndf.getIdFeed() != null ? ndf.getIdFeed() : ndf.getIdFolder()); } } @@ -250,9 +271,9 @@ public class NewsReaderListActivity extends MenuUtilsSherlockFragmentActivity im savedInstanceState.containsKey(OPTIONAL_FOLDER_ID)) { - startDetailFHolder = new StartDetailFragmentHolder(savedInstanceState.getString(OPTIONAL_FOLDER_ID), + startDetailFHolder = new StartDetailFragmentHolder(savedInstanceState.getLong(OPTIONAL_FOLDER_ID), savedInstanceState.getBoolean(IS_FOLDER_BOOLEAN), - savedInstanceState.getString(ID_FEED_STRING), + savedInstanceState.getLong(ID_FEED_STRING), false); NewsReaderDetailFragment ndf = StartDetailFragmentNow(); @@ -313,20 +334,20 @@ public class NewsReaderListActivity extends MenuUtilsSherlockFragmentActivity im private StartDetailFragmentHolder startDetailFHolder = null; private class StartDetailFragmentHolder { - String idSubscription; + long idFeed; boolean isFolder; - String optional_folder_id; + Long optional_folder_id; boolean updateListView; - public StartDetailFragmentHolder(String idSubscription, boolean isFolder, String optional_folder_id, boolean updateListView) { - this.idSubscription = idSubscription; + public StartDetailFragmentHolder(long idFeed, boolean isFolder, Long optional_folder_id, boolean updateListView) { + this.idFeed = idFeed; this.isFolder = isFolder; this.optional_folder_id = optional_folder_id; this.updateListView = updateListView; } public NewsReaderDetailFragment StartDetailFragment() { - return NewsReaderListActivity.this.StartDetailFragment(idSubscription, isFolder, optional_folder_id, updateListView); + return NewsReaderListActivity.this.StartDetailFragment(idFeed, isFolder, optional_folder_id, updateListView); } } @@ -335,49 +356,49 @@ public class NewsReaderListActivity extends MenuUtilsSherlockFragmentActivity im * that the item with the given ID was selected. */ @Override - public void onTopItemClicked(String idSubscription, boolean isFolder, String optional_folder_id) { + public void onTopItemClicked(long idFeed, boolean isFolder, Long optional_folder_id) { if(!shouldDrawerStayOpen()) mSlidingLayout.closePane(); - startDetailFHolder = new StartDetailFragmentHolder(idSubscription, isFolder, optional_folder_id, true); + startDetailFHolder = new StartDetailFragmentHolder(idFeed, isFolder, optional_folder_id, true); if(shouldDrawerStayOpen()) StartDetailFragmentNow(); } @Override - public void onChildItemClicked(String idSubscription, String optional_folder_id) { + public void onChildItemClicked(long idFeed, Long optional_folder_id) { if(!shouldDrawerStayOpen()) mSlidingLayout.closePane(); //StartDetailFragment(idSubscription, false, optional_folder_id); - startDetailFHolder = new StartDetailFragmentHolder(idSubscription, false, optional_folder_id, true); + startDetailFHolder = new StartDetailFragmentHolder(idFeed, false, optional_folder_id, true); if(shouldDrawerStayOpen()) StartDetailFragmentNow(); } - private NewsReaderDetailFragment StartDetailFragment(String id, Boolean folder, String optional_folder_id, boolean UpdateListView) + private NewsReaderDetailFragment StartDetailFragment(long id, Boolean folder, Long optional_folder_id, boolean UpdateListView) { if(super.getMenuItemDownloadMoreItems() != null) super.getMenuItemDownloadMoreItems().setEnabled(true); - DatabaseConnection dbConn = new DatabaseConnection(getApplicationContext()); + DatabaseConnectionOrm dbConn = new DatabaseConnectionOrm(getApplicationContext()); Intent intent = new Intent(); if(!folder) { - intent.putExtra(SUBSCRIPTION_ID, id); + intent.putExtra(FEED_ID, id); intent.putExtra(FOLDER_ID, optional_folder_id); - intent.putExtra(TITEL, dbConn.getTitleOfSubscriptionByRowID(id)); + intent.putExtra(TITEL, dbConn.getFeedById(id).getFeedTitle()); } else { intent.putExtra(FOLDER_ID, id); - int idFolder = Integer.valueOf(id); + int idFolder = (int) id; if(idFolder >= 0) - intent.putExtra(TITEL, dbConn.getTitleOfFolderByID(id)); + intent.putExtra(TITEL, dbConn.getFolderById(id).getLabel()); else if(idFolder == -10) intent.putExtra(TITEL, getString(R.string.allUnreadFeeds)); else if(idFolder == -11) @@ -394,8 +415,6 @@ public class NewsReaderListActivity extends MenuUtilsSherlockFragmentActivity im .replace(R.id.content_frame, fragment) .commit(); - dbConn.closeDatabase(); - return fragment; } @@ -404,7 +423,7 @@ public class NewsReaderListActivity extends MenuUtilsSherlockFragmentActivity im { NewsReaderDetailFragment nrD = (NewsReaderDetailFragment) getSupportFragmentManager().findFragmentById(R.id.content_frame); if(nrD != null) - ((NewsListCursorAdapter)nrD.getListAdapter()).notifyDataSetChanged(); + ((NewsListArrayAdapter)nrD.getListAdapter()).notifyDataSetChanged(); //nrD.UpdateCursor(); } @@ -425,7 +444,7 @@ public class NewsReaderListActivity extends MenuUtilsSherlockFragmentActivity im try { NewsReaderListFragment ndf = (NewsReaderListFragment) getSupportFragmentManager().findFragmentById(R.id.left_drawer); IOwnCloudSyncService _Reader = ndf._ownCloudSyncService; - PullToRefreshLayout pullToRefreshView = ndf.mPullToRefreshLayout; + SwipeRefreshLayout pullToRefreshView = ndf.mPullToRefreshLayout; if(_Reader != null) { if(_Reader.isSyncRunning()) @@ -439,7 +458,7 @@ public class NewsReaderListActivity extends MenuUtilsSherlockFragmentActivity im { super.getMenuItemUpdater().setActionView(null); if(pullToRefreshView != null) - pullToRefreshView.setRefreshComplete(); + pullToRefreshView.setRefreshing(false); } } } catch (RemoteException e) { @@ -456,7 +475,7 @@ public class NewsReaderListActivity extends MenuUtilsSherlockFragmentActivity im //getSupportMenuInflater().inflate(R.menu.news_reader, menu); - super.onCreateOptionsMenu(menu, getSupportMenuInflater(), this); + super.onCreateOptionsMenu(menu, getMenuInflater(), this); UpdateButtonSyncLayout(); @@ -517,16 +536,14 @@ public class NewsReaderListActivity extends MenuUtilsSherlockFragmentActivity im break; case R.id.menu_StartImageCaching: - DatabaseConnection dbConn = new DatabaseConnection(this); - try { - long highestItemId = dbConn.getLowestItemIdUnread(); - Intent service = new Intent(this, DownloadImagesService.class); - service.putExtra(DownloadImagesService.LAST_ITEM_ID, highestItemId); - //service.putExtra(DownloadImagesService.DOWNLOAD_FAVICONS_EXCLUSIVE, true); - startService(service); - } finally { - dbConn.closeDatabase(); - } + DatabaseConnectionOrm dbConn = new DatabaseConnectionOrm(this); + + long highestItemId = dbConn.getLowestRssItemIdUnread();//TODO needs testing! + Intent service = new Intent(this, DownloadImagesService.class); + service.putExtra(DownloadImagesService.LAST_ITEM_ID, highestItemId); + //service.putExtra(DownloadImagesService.DOWNLOAD_FAVICONS_EXCLUSIVE, true); + startService(service); + break; case R.id.menu_CreateDatabaseDump: @@ -557,7 +574,7 @@ public class NewsReaderListActivity extends MenuUtilsSherlockFragmentActivity im if(requestCode == RESULT_SETTINGS) { ((NewsReaderListFragment) getSupportFragmentManager().findFragmentById(R.id.left_drawer)).ReloadAdapter(); - ((NewsReaderDetailFragment) getSupportFragmentManager().findFragmentById(R.id.content_frame)).UpdateCursor(); + ((NewsReaderDetailFragment) getSupportFragmentManager().findFragmentById(R.id.content_frame)).UpdateCurrentRssView(this, false); //UpdatePodcastView(); @@ -575,7 +592,7 @@ public class NewsReaderListActivity extends MenuUtilsSherlockFragmentActivity im } - public static void StartLoginFragment(final SherlockFragmentActivity activity) + public static void StartLoginFragment(final FragmentActivity activity) { LoginDialogFragment dialog = LoginDialogFragment.getInstance(); dialog.setActivity(activity); diff --git a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/NewsReaderListFragment.java b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/NewsReaderListFragment.java index 6d9606ce..f24f6959 100644 --- a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/NewsReaderListFragment.java +++ b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/NewsReaderListFragment.java @@ -37,6 +37,10 @@ import android.os.Looper; import android.os.Parcelable; import android.os.RemoteException; import android.preference.PreferenceManager; +import android.support.v4.app.Fragment; +import android.support.v4.app.FragmentActivity; +import android.support.v4.widget.SwipeRefreshLayout; +import android.support.v7.app.ActionBarActivity; import android.util.Log; import android.view.LayoutInflater; import android.view.View; @@ -47,8 +51,6 @@ import android.widget.ExpandableListView.OnChildClickListener; import android.widget.ListView; import android.widget.Toast; -import com.actionbarsherlock.app.SherlockFragment; -import com.actionbarsherlock.app.SherlockFragmentActivity; import com.michaelflisar.messagebar.MessageBar; import com.michaelflisar.messagebar.messages.BaseMessage; import com.michaelflisar.messagebar.messages.TextMessage; @@ -56,10 +58,12 @@ import com.michaelflisar.messagebar.messages.TextMessage; import org.apache.http.client.HttpResponseException; import org.apache.http.conn.HttpHostConnectException; +import butterknife.ButterKnife; +import butterknife.InjectView; import de.luhmer.owncloudnewsreader.Constants.SYNC_TYPES; import de.luhmer.owncloudnewsreader.ListView.SubscriptionExpandableListAdapter; import de.luhmer.owncloudnewsreader.authentication.AccountGeneral; -import de.luhmer.owncloudnewsreader.database.DatabaseConnection; +import de.luhmer.owncloudnewsreader.database.DatabaseConnectionOrm; import de.luhmer.owncloudnewsreader.helper.AidlException; import de.luhmer.owncloudnewsreader.helper.PostDelayHandler; import de.luhmer.owncloudnewsreader.helper.ThemeChooser; @@ -68,9 +72,6 @@ import de.luhmer.owncloudnewsreader.model.FolderSubscribtionItem; import de.luhmer.owncloudnewsreader.services.IOwnCloudSyncService; import de.luhmer.owncloudnewsreader.services.IOwnCloudSyncServiceCallback; import de.luhmer.owncloudnewsreader.services.OwnCloudSyncService; -import uk.co.senab.actionbarpulltorefresh.extras.actionbarsherlock.PullToRefreshLayout; -import uk.co.senab.actionbarpulltorefresh.library.ActionBarPullToRefresh; -import uk.co.senab.actionbarpulltorefresh.library.listeners.OnRefreshListener; /** * A list fragment representing a list of NewsReader. This fragment also @@ -81,7 +82,7 @@ import uk.co.senab.actionbarpulltorefresh.library.listeners.OnRefreshListener; * Activities containing this fragment MUST implement the {@link Callbacks} * interface. */ -public class NewsReaderListFragment extends SherlockFragment implements OnCreateContextMenuListener, OnRefreshListener/* +public class NewsReaderListFragment extends Fragment implements OnCreateContextMenuListener, SwipeRefreshLayout.OnRefreshListener/* ExpandableListView.OnChildClickListener, ExpandableListView.OnGroupCollapseListener, ExpandableListView.OnGroupExpandListener*/ { @@ -183,10 +184,11 @@ public class NewsReaderListFragment extends SherlockFragment implements OnCreate * The fragment's current callback object, which is notified of list item * clicks. */ - private Callbacks mCallbacks = sExpListCallbacks; + private Callbacks mCallbacks = null; + @Override - public void onRefreshStarted(View view) { + public void onRefresh() { StartSync(); } @@ -204,31 +206,17 @@ public class NewsReaderListFragment extends SherlockFragment implements OnCreate /** * Callback for when an item has been selected. */ - public void onChildItemClicked(String idSubscription, String optional_folder_id); - public void onTopItemClicked(String idSubscription, boolean isFolder, String optional_folder_id); + public void onChildItemClicked(long idFeed, Long optional_folder_id); + public void onTopItemClicked(long idFeed, boolean isFolder, Long optional_folder_id); } - /** - * A dummy implementation of the {@link Callbacks} interface that does - * nothing. Used only when this fragment is not attached to an activity. - */ - private static Callbacks sExpListCallbacks = new Callbacks() { - @Override - public void onChildItemClicked(String idSubscription, String optional_folder_id) { - } - - @Override - public void onTopItemClicked(String idSubscription, boolean isFolder, String optional_folder_id) { - } - }; - DatabaseConnection dbConn; //SubscriptionExpandableListAdapter lvAdapter; private SubscriptionExpandableListAdapter lvAdapter; //ExpandableListView eListView; - ExpandableListView eListView; - View progressBar; - PullToRefreshLayout mPullToRefreshLayout; + @InjectView(R.id.expandableListView) ExpandableListView eListView; + @InjectView(R.id.pbProgress) View progressBar; + @InjectView(R.id.ptr_layout) SwipeRefreshLayout mPullToRefreshLayout; //public static IReader _Reader = null; //AsyncTask_GetGReaderTags asyncTask_GetUnreadFeeds = null; //public static String username; @@ -253,8 +241,6 @@ public class NewsReaderListFragment extends SherlockFragment implements OnCreate try { - dbConn = new DatabaseConnection(getActivity()); - //SettingsActivity.CheckForUnsycedChangesInDatabase(context); //dbConn.resetDatabase(); //dbConn.clearDatabaseOverSize(); @@ -272,16 +258,12 @@ public class NewsReaderListFragment extends SherlockFragment implements OnCreate { //Toast.makeText(getActivity(), "button 1 pressed", 3000).show(); + + //TODO needs testing! NewsReaderDetailFragment ndf = ((NewsReaderDetailFragment) getActivity().getSupportFragmentManager().findFragmentById(R.id.content_frame)); if(ndf != null) { - try { - ndf.UpdateCurrentRssView(getActivity()); - ndf.getLoaderManager().restartLoader(0, null, ndf.loaderCallbacks); - ndf.setActivatedPosition(0); - ndf.setMarginFromTop(0); - } catch(Exception ex) { - ex.printStackTrace(); - } + //ndf.reloadAdapterFromScratch(); + ndf.UpdateCurrentRssView(getActivity(), true); } } }; @@ -384,7 +366,7 @@ public class NewsReaderListFragment extends SherlockFragment implements OnCreate SharedPreferences mPrefs = PreferenceManager.getDefaultSharedPreferences(getActivity()); if(mPrefs.getString(SettingsActivity.EDT_OWNCLOUDROOTPATH_STRING, null) == null) - NewsReaderListActivity.StartLoginFragment((SherlockFragmentActivity) getActivity()); + NewsReaderListActivity.StartLoginFragment((FragmentActivity) getActivity()); else { try { if (!_ownCloudSyncService.isSyncRunning()) @@ -446,32 +428,25 @@ public class NewsReaderListFragment extends SherlockFragment implements OnCreate @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - View view = inflater.inflate(R.layout.expandable_list_layout, container, false); + View view = inflater.inflate(R.layout.fragment_newsreader_list, container, false); if(!ThemeChooser.isDarkTheme(getActivity())) { view.setBackgroundColor(getResources().getColor(R.color.slider_listview_background_color_light_theme)); } - progressBar = view.findViewById(R.id.pbProgress); + ButterKnife.inject(this, view); - eListView = (ExpandableListView) view.findViewById(R.id.expandableListView); - - lvAdapter = new SubscriptionExpandableListAdapter(getActivity(), dbConn, eListView); + lvAdapter = new SubscriptionExpandableListAdapter(getActivity(), new DatabaseConnectionOrm(getActivity()), eListView); lvAdapter.setHandlerListener(expListTextClickedListener); eListView.setGroupIndicator(null); - // Now find the PullToRefreshLayout to setup - mPullToRefreshLayout = (PullToRefreshLayout) view.findViewById(R.id.ptr_layout); + mPullToRefreshLayout.setOnRefreshListener(this); + mPullToRefreshLayout.setColorScheme(android.R.color.holo_blue_bright, + android.R.color.holo_green_light, + android.R.color.holo_orange_light, + android.R.color.holo_red_light); - // Now setup the PullToRefreshLayout - ActionBarPullToRefresh.from(getActivity()) - // Mark All Children as pullable - .allChildrenArePullable() - // Set the OnRefreshListener - .listener(this) - // Finally commit the setup to our PullToRefreshLayout - .setup(mPullToRefreshLayout); eListView.setOnChildClickListener(onChildClickListener); //eListView.setSmoothScrollbarEnabled(true); @@ -483,6 +458,14 @@ public class NewsReaderListFragment extends SherlockFragment implements OnCreate lvAdapter.notifyDataSetChanged(); ReloadAdapter(); + + SharedPreferences mPrefs = PreferenceManager.getDefaultSharedPreferences(getActivity()); + if(!mPrefs.getBoolean(Constants.SHOW_CASE_APP_STARTED_SHOWN_BOOLEAN, false)) { + mPrefs.edit().putBoolean(Constants.SHOW_CASE_APP_STARTED_SHOWN_BOOLEAN, true).commit(); + ((NewsReaderListActivity) getActivity()).showShowCaseViewForView(eListView, view, "Pull To Refresh", "Pull down the list to refresh your feeds"); + } + + return view; } @@ -504,17 +487,16 @@ public class NewsReaderListFragment extends SherlockFragment implements OnCreate public void onDetach() { super.onDetach(); - // Reset the active callbacks interface to the dummy implementation. - mCallbacks = sExpListCallbacks; + mCallbacks = null; } ExpListTextClicked expListTextClickedListener = new ExpListTextClicked() { @Override - public void onTextClicked(String idSubscription, Context context, boolean isFolder, String optional_folder_id) { - mCallbacks.onTopItemClicked(idSubscription, isFolder, optional_folder_id); + public void onTextClicked(long idFeed, Context context, boolean isFolder, Long optional_folder_id) { + mCallbacks.onTopItemClicked(idFeed, isFolder, optional_folder_id); } - }; + }; /* @Override @@ -537,12 +519,12 @@ public class NewsReaderListFragment extends SherlockFragment implements OnCreate long idItem = lvAdapter.getChildId(groupPosition, childPosition); - String optional_id_folder = null; + Long optional_id_folder = null; FolderSubscribtionItem groupItem = (FolderSubscribtionItem) lvAdapter.getGroup(groupPosition); if(groupItem != null) - optional_id_folder = String.valueOf(groupItem.id_database); + optional_id_folder = groupItem.id_database; - mCallbacks.onChildItemClicked(String.valueOf(idItem), optional_id_folder); + mCallbacks.onChildItemClicked(idItem, optional_id_folder); return false; } diff --git a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/PodcastFragment.java b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/PodcastFragment.java index 103874f9..48fcf669 100644 --- a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/PodcastFragment.java +++ b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/PodcastFragment.java @@ -3,8 +3,11 @@ package de.luhmer.owncloudnewsreader; import android.app.Activity; import android.content.Context; import android.content.Intent; +import android.content.SharedPreferences; import android.net.Uri; import android.os.Bundle; +import android.preference.PreferenceManager; +import android.support.v4.app.Fragment; import android.util.Log; import android.view.ContextThemeWrapper; import android.view.LayoutInflater; @@ -21,7 +24,6 @@ import android.widget.TextView; import android.widget.Toast; import android.widget.ViewSwitcher; -import com.actionbarsherlock.app.SherlockFragment; import com.sothree.slidinguppanel.SlidingUpPanelLayout; import java.io.File; @@ -34,8 +36,9 @@ import butterknife.OnClick; import de.greenrobot.event.EventBus; import de.luhmer.owncloudnewsreader.ListView.PodcastArrayAdapter; import de.luhmer.owncloudnewsreader.ListView.PodcastFeedArrayAdapter; -import de.luhmer.owncloudnewsreader.database.DatabaseConnection; +import de.luhmer.owncloudnewsreader.database.DatabaseConnectionOrm; import de.luhmer.owncloudnewsreader.events.podcast.AudioPodcastClicked; +import de.luhmer.owncloudnewsreader.events.podcast.FeedPanelSlideEvent; import de.luhmer.owncloudnewsreader.events.podcast.OpenPodcastEvent; import de.luhmer.owncloudnewsreader.events.podcast.PodcastFeedClicked; import de.luhmer.owncloudnewsreader.events.podcast.StartDownloadPodcast; @@ -50,7 +53,7 @@ import de.luhmer.owncloudnewsreader.view.PodcastSlidingUpPanelLayout; /** - * A simple {@link SherlockFragment} subclass. + * A simple {@link Fragment} subclass. * Activities that contain this fragment must implement the * {@link PodcastFragment.OnFragmentInteractionListener} interface * to handle interaction events. @@ -58,7 +61,7 @@ import de.luhmer.owncloudnewsreader.view.PodcastSlidingUpPanelLayout; * create an instance of this fragment. * */ -public class PodcastFragment extends SherlockFragment { +public class PodcastFragment extends Fragment { // TODO: Rename parameter arguments, choose names that match // the fragment initialization parameters, e.g. ARG_ITEM_NUMBER private static final String ARG_PARAM1 = "param1"; @@ -200,8 +203,8 @@ public class PodcastFragment extends SherlockFragment { } public void onEventMainThread(PodcastFeedClicked podcast) { - DatabaseConnection dbConn = new DatabaseConnection(getActivity()); - audioPodcasts = dbConn.getListOfAudioPodcastsForFeed(getActivity(), feedsWithAudioPodcasts.get(podcast.position).itemId); + DatabaseConnectionOrm dbConn = new DatabaseConnectionOrm(getActivity()); + audioPodcasts = dbConn.getListOfAudioPodcastsForFeed(getActivity(), feedsWithAudioPodcasts.get(podcast.position).mFeed.getId()); for(int i = 0; i < audioPodcasts.size(); i++) { @@ -381,7 +384,7 @@ public class PodcastFragment extends SherlockFragment { // create ContextThemeWrapper from the original Activity Context with the custom theme - Context context = new ContextThemeWrapper(getActivity(), R.style.Theme_Sherlock_Light_DarkActionBar); + Context context = new ContextThemeWrapper(getActivity(), R.style.Theme_AppCompat_Light_DarkActionBar); // clone the inflater using the ContextThemeWrapper LayoutInflater localInflater = inflater.cloneInContext(context); // inflate using the cloned inflater, not the passed in default @@ -392,8 +395,8 @@ public class PodcastFragment extends SherlockFragment { ButterKnife.inject(this, view); - if(getActivity() instanceof PodcastSherlockFragmentActivity) { - sliding_layout = ((PodcastSherlockFragmentActivity) getActivity()).getSlidingLayout(); + if(getActivity() instanceof PodcastFragmentActivity) { + sliding_layout = ((PodcastFragmentActivity) getActivity()).getSlidingLayout(); } if(sliding_layout != null) { @@ -407,7 +410,7 @@ public class PodcastFragment extends SherlockFragment { - DatabaseConnection dbConn = new DatabaseConnection(getActivity()); + DatabaseConnectionOrm dbConn = new DatabaseConnectionOrm(getActivity()); feedsWithAudioPodcasts = dbConn.getListOfFeedsWithAudioPodcasts(); PodcastFeedArrayAdapter mArrayAdapter = new PodcastFeedArrayAdapter(getActivity(), feedsWithAudioPodcasts.toArray(new PodcastFeedItem[feedsWithAudioPodcasts.size()])); if (podcastFeedList != null) { @@ -423,10 +426,24 @@ public class PodcastFragment extends SherlockFragment { sb_progress.setOnSeekBarChangeListener(onSeekBarChangeListener); + return view; } + public void onEvent(FeedPanelSlideEvent event){ + if(!event.isPanelOpen()) { + SharedPreferences mPrefs = PreferenceManager.getDefaultSharedPreferences(getActivity()); + if (!mPrefs.getBoolean(Constants.SHOW_CASE_PODCAST_ENABLED_SHOWN_BOOLEAN, false)) { + mPrefs.edit().putBoolean(Constants.SHOW_CASE_PODCAST_ENABLED_SHOWN_BOOLEAN, true).commit(); + + NewsReaderListActivity nrlActivity = ((NewsReaderListActivity) getActivity()); + nrlActivity.showShowCaseViewForView(nrlActivity.getNewsReaderDetailFragment().getView(), pb_progress, "Podcasts", "Click on this view or slide it up to open the podcast selector."); + } + } + } + + // TODO: Rename method, update argument and hook method into UI event public void onButtonPressed(Uri uri) { if (mListener != null) { @@ -483,8 +500,8 @@ public class PodcastFragment extends SherlockFragment { sliding_layout.setDragView(rlPodcastHeader); viewSwitcherProgress.setDisplayedChild(0); - if(getActivity() instanceof PodcastSherlockFragmentActivity) - ((PodcastSherlockFragmentActivity)getActivity()).togglePodcastVideoViewAnimation(); + if(getActivity() instanceof PodcastFragmentActivity) + ((PodcastFragmentActivity)getActivity()).togglePodcastVideoViewAnimation(); } @Override @@ -493,8 +510,8 @@ public class PodcastFragment extends SherlockFragment { sliding_layout.setDragView(viewSwitcherProgress); viewSwitcherProgress.setDisplayedChild(1); - if(getActivity() instanceof PodcastSherlockFragmentActivity) - ((PodcastSherlockFragmentActivity)getActivity()).togglePodcastVideoViewAnimation(); + if(getActivity() instanceof PodcastFragmentActivity) + ((PodcastFragmentActivity)getActivity()).togglePodcastVideoViewAnimation(); } @Override diff --git a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/PodcastSherlockFragmentActivity.java b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/PodcastFragmentActivity.java index 945f19f4..efa7b95d 100644 --- a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/PodcastSherlockFragmentActivity.java +++ b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/PodcastFragmentActivity.java @@ -8,6 +8,7 @@ import android.content.res.Resources; import android.os.Build; import android.os.Bundle; import android.preference.PreferenceManager; +import android.support.v7.app.ActionBarActivity; import android.util.Log; import android.util.TypedValue; import android.view.SurfaceView; @@ -15,7 +16,6 @@ import android.view.View; import android.view.animation.Animation; import android.widget.LinearLayout; -import com.actionbarsherlock.app.SherlockFragmentActivity; import com.nineoldandroids.view.ViewHelper; import butterknife.ButterKnife; @@ -26,14 +26,13 @@ import de.luhmer.owncloudnewsreader.events.podcast.RegisterVideoOutput; import de.luhmer.owncloudnewsreader.events.podcast.UpdatePodcastStatusEvent; import de.luhmer.owncloudnewsreader.events.podcast.VideoDoubleClicked; import de.luhmer.owncloudnewsreader.helper.SizeAnimator; -import de.luhmer.owncloudnewsreader.helper.ThemeChooser; import de.luhmer.owncloudnewsreader.view.PodcastSlidingUpPanelLayout; import de.luhmer.owncloudnewsreader.view.ZoomableRelativeLayout; /** * Created by David on 29.06.2014. */ -public class PodcastSherlockFragmentActivity extends SherlockFragmentActivity { +public class PodcastFragmentActivity extends ActionBarActivity { private static final String TAG = "PodcastSherlockFragmentActivity"; private PodcastFragment podcastFragment; diff --git a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/SettingsActivity.java b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/SettingsActivity.java index d611fe66..358b952a 100644 --- a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/SettingsActivity.java +++ b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/SettingsActivity.java @@ -42,15 +42,13 @@ import android.preference.PreferenceActivity; import android.preference.PreferenceCategory; import android.preference.PreferenceFragment; import android.preference.PreferenceManager; - -import com.actionbarsherlock.app.SherlockPreferenceActivity; -import com.actionbarsherlock.view.MenuItem; +import android.view.MenuItem; import java.io.File; import java.text.DecimalFormat; import java.util.List; -import de.luhmer.owncloudnewsreader.database.DatabaseConnection; +import de.luhmer.owncloudnewsreader.database.DatabaseConnectionOrm; import de.luhmer.owncloudnewsreader.helper.FileUtils; import de.luhmer.owncloudnewsreader.helper.ImageHandler; import de.luhmer.owncloudnewsreader.helper.PostDelayHandler; @@ -67,7 +65,7 @@ import de.luhmer.owncloudnewsreader.helper.ThemeChooser; * href="http://developer.android.com/guide/topics/ui/settings.html">Settings * API Guide</a> for more information on developing a Settings UI. */ -public class SettingsActivity extends SherlockPreferenceActivity { +public class SettingsActivity extends PreferenceActivity { /** * Determines whether to always show the simplified settings UI, where * settings are presented in a single list. When false, settings are shown @@ -115,7 +113,7 @@ public class SettingsActivity extends SherlockPreferenceActivity { super.onCreate(savedInstanceState); - getSupportActionBar().setDisplayHomeAsUpEnabled(true); + getActionBar().setDisplayHomeAsUpEnabled(true); } @Override @@ -506,15 +504,9 @@ public class SettingsActivity extends SherlockPreferenceActivity { public static void CheckForUnsycedChangesInDatabaseAndResetDatabase(final Context context) { - DatabaseConnection dbConn = new DatabaseConnection(context); + DatabaseConnectionOrm dbConn = new DatabaseConnectionOrm(context); boolean resetDatabase = true; - if(dbConn.getAllNewReadItems().size() > 0) - resetDatabase = false; - else if(dbConn.getAllNewUnreadItems().size() > 0) - resetDatabase = false; - else if(dbConn.getAllNewStarredItems().size() > 0) - resetDatabase = false; - else if(dbConn.getAllNewUnstarredItems().size() > 0) + if(dbConn.areThereAnyUnsavedChangesInDatabase()) resetDatabase = false; if(resetDatabase) { @@ -537,8 +529,6 @@ public class SettingsActivity extends SherlockPreferenceActivity { .create() .show(); } - - dbConn.closeDatabase(); } public static class ResetDatabaseAsyncTask extends AsyncTask<Void, Void, Boolean> { @@ -564,15 +554,11 @@ public class SettingsActivity extends SherlockPreferenceActivity { @Override protected Boolean doInBackground(Void... params) { - DatabaseConnection dbConn = new DatabaseConnection(_mActivity); - try { - dbConn.resetDatabase(); - boolean success = ImageHandler.clearCache(_mActivity); - new GetCacheSizeAsync().execute((Void)null); - return success; - } finally { - dbConn.closeDatabase(); - } + DatabaseConnectionOrm dbConn = new DatabaseConnectionOrm(_mActivity); + dbConn.resetDatabase(); + boolean success = ImageHandler.clearCache(_mActivity); + new GetCacheSizeAsync().execute((Void)null); + return success; } @Override diff --git a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/SyncIntervalSelectorActivity.java b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/SyncIntervalSelectorActivity.java index 59183efd..c3aee8bd 100644 --- a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/SyncIntervalSelectorActivity.java +++ b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/SyncIntervalSelectorActivity.java @@ -9,21 +9,21 @@ import android.content.SharedPreferences; import android.os.Build; import android.os.Bundle; import android.preference.PreferenceManager; +import android.support.v4.app.Fragment; +import android.support.v4.app.FragmentActivity; import android.view.LayoutInflater; +import android.view.Menu; +import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; import android.widget.ArrayAdapter; import android.widget.ListView; -import com.actionbarsherlock.app.SherlockFragment; -import com.actionbarsherlock.app.SherlockFragmentActivity; -import com.actionbarsherlock.view.Menu; -import com.actionbarsherlock.view.MenuItem; import de.luhmer.owncloudnewsreader.authentication.AccountGeneral; -public class SyncIntervalSelectorActivity extends SherlockFragmentActivity { +public class SyncIntervalSelectorActivity extends FragmentActivity { SharedPreferences mPrefs; PlaceholderFragment mFragment; @@ -51,8 +51,7 @@ public class SyncIntervalSelectorActivity extends SherlockFragmentActivity { public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. - getSupportMenuInflater() - .inflate(R.menu.sync_interval_selector, menu); + getMenuInflater().inflate(R.menu.sync_interval_selector, menu); return true; } @@ -116,7 +115,7 @@ public class SyncIntervalSelectorActivity extends SherlockFragmentActivity { //public static final long SYNC_INTERVAL_IN_MINUTES = 60L; public static final String SYNC_INTERVAL_IN_MINUTES_STRING = "SYNC_INTERVAL_IN_MINUTES_STRING"; - public static class PlaceholderFragment extends SherlockFragment { + public static class PlaceholderFragment extends Fragment { public ListView lvItems; diff --git a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/VersionInfoDialogFragment.java b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/VersionInfoDialogFragment.java index 28687eaa..44a605b9 100644 --- a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/VersionInfoDialogFragment.java +++ b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/VersionInfoDialogFragment.java @@ -28,20 +28,19 @@ import android.app.Dialog; import android.content.pm.PackageInfo; import android.os.Build; import android.os.Bundle; +import android.support.v4.app.DialogFragment; import android.view.LayoutInflater; import android.view.View; import android.view.WindowManager.LayoutParams; import android.widget.TextView; -import com.actionbarsherlock.app.SherlockDialogFragment; - import it.gmariotti.changelibs.library.view.ChangeLogListView; /** * Activity which displays a login screen to the user, offering registration as * well. */ -public class VersionInfoDialogFragment extends SherlockDialogFragment { +public class VersionInfoDialogFragment extends DialogFragment { @SuppressLint("SetJavaScriptEnabled") @Override diff --git a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/adapter/GreenDaoListAdapter.java b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/adapter/GreenDaoListAdapter.java new file mode 100644 index 00000000..c48cd450 --- /dev/null +++ b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/adapter/GreenDaoListAdapter.java @@ -0,0 +1,133 @@ +package de.luhmer.owncloudnewsreader.adapter; + +import android.content.Context; +import android.view.View; +import android.view.ViewGroup; +import android.widget.BaseAdapter; + +import de.greenrobot.dao.query.LazyList; + +/** + * Created by David on 18.07.2014. + */ +public abstract class GreenDaoListAdapter<T extends HasId<Long>> extends BaseAdapter { + + protected LazyList<T> lazyList; + protected Context context; + + public GreenDaoListAdapter(Context context, LazyList<T> lazyList) { + this.lazyList = lazyList; + this.context = context; + } + + /** + * Returns the list backing this adapter. + * + * @return the list. + */ + public LazyList<T> getLazyList() { + return lazyList; + } + + public void setLazyList( LazyList<T> lazyList ) { + this.lazyList = lazyList; + } + + /** + * @see android.widget.ListAdapter#getCount() + */ + @Override + public int getCount() { + return lazyList != null ? lazyList.size() : 0; + } + + /** + * @see android.widget.ListAdapter#getItem(int) + */ + @Override + public T getItem(int position) { + return lazyList != null ? lazyList.get(position) : null; + } + + /** + * @see android.widget.ListAdapter#getItemId(int) + */ + @Override + public long getItemId(int position) { + if (lazyList != null) { + T item = lazyList.get(position); + return item!=null ? item.getId() : 0; + } else { + return 0; + } + } + + @Override + public boolean hasStableIds() { + return true; + } + + /** + * @see android.widget.ListAdapter#getView(int, View, ViewGroup) + */ + public View getView(int position, View convertView, ViewGroup parent) { + + if (lazyList==null) { + throw new IllegalStateException("this should only be called when lazylist is populated"); + } + + T item = lazyList.get(position); + if (item == null) { + throw new IllegalStateException("Item at position " + position + " is null"); + } + + View v = convertView == null ? newView(context, item, parent) : convertView; + bindView(v, context, item); + return v; + } + + @Override + public View getDropDownView(int position, View convertView, ViewGroup parent) { + + if (lazyList!=null) { + T item = lazyList.get(position); + View v = convertView == null ? newDropDownView(context, item, parent) : convertView; + bindView(v, context, item); + return v; + } else { + return null; + } + } + + /** + * Makes a new view to hold the data contained in the item. + * + * @param context Interface to application's global information + * @param item The object that contains the data + * @param parent The parent to which the new view is attached to + * @return the newly created view. + */ + public abstract View newView(Context context, T item, ViewGroup parent); + + /** + * Makes a new drop down view to hold the data contained in the item. + * + * @param context Interface to application's global information + * @param item The object that contains the data + * @param parent The parent to which the new view is attached to + * @return the newly created view. + */ + public View newDropDownView(Context context, T item, ViewGroup parent) { + return newView(context, item, parent); + } + + /** + * Bind an existing view to the data data contained in the item. + * + * @param view Existing view, returned earlier by newView + * @param context Interface to application's global information + * @param item The object that contains the data + */ + public abstract void bindView(View view, Context context, T item); + +} diff --git a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/adapter/HasId.java b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/adapter/HasId.java new file mode 100644 index 00000000..c7d3a8e7 --- /dev/null +++ b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/adapter/HasId.java @@ -0,0 +1,8 @@ +package de.luhmer.owncloudnewsreader.adapter; + +/** + * Created by David on 18.07.2014. + */ +public interface HasId<T> { + public T getId(); +} diff --git a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/adapter/NewsListArrayAdapter.java b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/adapter/NewsListArrayAdapter.java new file mode 100644 index 00000000..ef6e62ae --- /dev/null +++ b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/adapter/NewsListArrayAdapter.java @@ -0,0 +1,387 @@ +package de.luhmer.owncloudnewsreader.adapter; + +import android.annotation.TargetApi; +import android.content.Context; +import android.content.SharedPreferences; +import android.os.Build; +import android.preference.PreferenceManager; +import android.support.v4.app.FragmentActivity; +import android.text.Html; +import android.text.Spannable; +import android.text.SpannableString; +import android.text.format.DateUtils; +import android.text.style.ForegroundColorSpan; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.view.animation.AccelerateInterpolator; +import android.view.animation.AlphaAnimation; +import android.view.animation.Animation; +import android.webkit.WebView; +import android.widget.CompoundButton; +import android.widget.LinearLayout; +import android.widget.TextView; + +import com.devspark.robototextview.widget.RobotoCheckBox; +import com.devspark.robototextview.widget.RobotoTextView; + +import butterknife.ButterKnife; +import butterknife.InjectView; +import de.greenrobot.dao.query.LazyList; +import de.luhmer.owncloudnewsreader.NewsDetailFragment; +import de.luhmer.owncloudnewsreader.NewsReaderListActivity; +import de.luhmer.owncloudnewsreader.R; +import de.luhmer.owncloudnewsreader.SettingsActivity; +import de.luhmer.owncloudnewsreader.async_tasks.IGetTextForTextViewAsyncTask; +import de.luhmer.owncloudnewsreader.cursor.IOnStayUnread; +import de.luhmer.owncloudnewsreader.database.DatabaseConnectionOrm; +import de.luhmer.owncloudnewsreader.database.model.RssItem; +import de.luhmer.owncloudnewsreader.helper.FillTextForTextViewHelper; +import de.luhmer.owncloudnewsreader.helper.FontHelper; +import de.luhmer.owncloudnewsreader.helper.PostDelayHandler; +import de.luhmer.owncloudnewsreader.helper.ThemeChooser; +import de.luhmer.owncloudnewsreader.reader.IReader; +import de.luhmer.owncloudnewsreader.reader.owncloud.OwnCloud_Reader; + +/** + * Created by David on 18.07.2014. + */ +public class NewsListArrayAdapter extends GreenDaoListAdapter<RssItem> { + + DatabaseConnectionOrm dbConn; + IReader _Reader; + final int LengthBody = 400; + ForegroundColorSpan bodyForegroundColor; + IOnStayUnread onStayUnread; + PostDelayHandler pDelayHandler; + int selectedDesign = 0; + Context mContext; + + public NewsListArrayAdapter(Context context, LazyList<RssItem> lazyList, IOnStayUnread onStayUnread) { + super(context, lazyList); + + mContext = context; + this.onStayUnread = onStayUnread; + + pDelayHandler = new PostDelayHandler(context); + + //simpleDateFormat = new SimpleDateFormat("EEE, d. MMM HH:mm:ss"); + bodyForegroundColor = new ForegroundColorSpan(context.getResources().getColor(android.R.color.secondary_text_dark)); + + _Reader = new OwnCloud_Reader(); + dbConn = new DatabaseConnectionOrm(context); + + SharedPreferences mPrefs = PreferenceManager.getDefaultSharedPreferences(context); + selectedDesign = Integer.valueOf(mPrefs.getString(SettingsActivity.SP_FEED_LIST_LAYOUT, "0")); + } + + @Override + public void bindView(final View view, final Context context, final RssItem item) { + + switch (selectedDesign) { + case 0: + setSimpleLayout(view, item); + break; + case 1: + setExtendedLayout(view, item); + break; + case 2: + setExtendedLayoutWebView(view, item); + break; + default: + break; + } + + RobotoCheckBox cbStarred = (RobotoCheckBox) view.findViewById(R.id.cb_lv_item_starred); + + FontHelper fHelper = new FontHelper(context); + fHelper.setFontForAllChildren(view, fHelper.getFont()); + + if(ThemeChooser.isDarkTheme(mContext)) + cbStarred.setBackgroundResource(R.drawable.checkbox_background_holo_dark); + /* + //The default is white so we don't need to set it here again.. + else + cbStarred.setBackgroundResource(R.drawable.checkbox_background_holo_light);*/ + + cbStarred.setOnCheckedChangeListener(null); + + cbStarred.setChecked(item.getStarred_temp()); + cbStarred.setClickable(true); + + cbStarred.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { + + @Override + public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { + item.setStarred_temp(isChecked); + dbConn.updateRssItem(item); + + if(isChecked) + UpdateIsReadCheckBox(buttonView, item); + + pDelayHandler.DelayTimer(); + } + }); + + + LinearLayout ll_cb_starred_wrapper = (LinearLayout) view.findViewById(R.id.ll_cb_starred_wrapper); + if(ll_cb_starred_wrapper != null) { + ll_cb_starred_wrapper.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + RobotoCheckBox cbStarred = (RobotoCheckBox) view.findViewById(R.id.cb_lv_item_starred); + cbStarred.setChecked(!cbStarred.isChecked()); + } + }); + } + + RobotoCheckBox cbRead = (RobotoCheckBox) view.findViewById(R.id.cb_lv_item_read); + cbRead.setTag(item.getId()); + cbRead.setOnCheckedChangeListener(null); + + Boolean isRead = item.getRead_temp(); + //Log.d("ISREAD", "" + isChecked + " - Cursor: " + cursor.getString(0)); + cbRead.setChecked(isRead); + if(!isRead) { + RobotoTextView textView = (RobotoTextView) view.findViewById(R.id.summary); + fHelper.setFontStyleForSingleView(textView, fHelper.getFontUnreadStyle()); + } + + + + cbRead.setClickable(true); + cbRead.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { + + @Override + public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { + ChangeReadStateOfItem((RobotoCheckBox) buttonView, view, isChecked, mContext); + } + }); + + + String colorString = item.getFeed().getAvgColour(); + View viewColor = view.findViewById(R.id.color_line_feed); + if(colorString != null) + viewColor.setBackgroundColor(Integer.parseInt(colorString)); + } + + public void ChangeReadStateOfItem(RobotoCheckBox checkBox, View parentView, boolean isChecked, Context context) { + + RssItem rssItem = dbConn.getRssItemById((Long)checkBox.getTag()); + rssItem.setRead_temp(isChecked); + dbConn.updateRssItem(rssItem); + + UpdateListCursor(mContext); + + pDelayHandler.DelayTimer(); + + RobotoTextView textView = (RobotoTextView) parentView.findViewById(R.id.summary); + if(textView != null && parentView.getTop() >= 0) + { + FontHelper fHelper = new FontHelper(context); + if(isChecked) + fHelper.setFontStyleForSingleView(textView, fHelper.getFont()); + else { + fHelper.setFontStyleForSingleView(textView, fHelper.getFontUnreadStyle()); + onStayUnread.stayUnread(checkBox); + } + + textView.invalidate(); + } + } + + public void setSimpleLayout(View view, RssItem rssItem) + { + SimpleLayout simpleLayout = new SimpleLayout(view); + + simpleLayout.textViewSummary.setText(Html.fromHtml(rssItem.getTitle()).toString()); + + long pubDate = rssItem.getPubDate().getTime(); + String dateString = (String) DateUtils.getRelativeTimeSpanString(pubDate); + simpleLayout.textViewItemDate.setText(dateString); + + simpleLayout.textViewTitle.setText(rssItem.getFeed().getFeedTitle()); + + if(!ThemeChooser.isDarkTheme(mContext)) { + simpleLayout.viewDivider.setBackgroundColor(mContext.getResources().getColor(R.color.divider_row_color_light_theme)); + } + } + + static class SimpleLayout { + @InjectView(R.id.divider) View viewDivider; + @InjectView(R.id.summary) TextView textViewSummary; + @InjectView(R.id.tv_item_date) TextView textViewItemDate; + @InjectView(R.id.tv_subscription) TextView textViewTitle; + + SimpleLayout(View view) { + ButterKnife.inject(this, view); + } + } + + + public void setExtendedLayout(View view, RssItem rssItem) + { + ExtendedLayout extendedLayout = new ExtendedLayout(view); + + extendedLayout.textViewSummary.setText(Html.fromHtml(rssItem.getTitle()).toString()); + + long pubDate = rssItem.getPubDate().getTime(); + //textViewItemDate.setText(simpleDateFormat.format(new Date(pubDate))); + String dateString = (String) DateUtils.getRelativeTimeSpanString(pubDate); + extendedLayout.textViewItemDate.setText(dateString); + + extendedLayout.textViewItemBody.setVisibility(View.INVISIBLE); + + IGetTextForTextViewAsyncTask iGetter = new DescriptionTextGetter(rssItem.getId()); + FillTextForTextViewHelper.FillTextForTextView(extendedLayout.textViewItemBody, iGetter, true);//TODO is this really needed any longer? direct insert text is also possible + + extendedLayout.textViewTitle.setText(rssItem.getFeed().getFeedTitle()); + + if(!ThemeChooser.isDarkTheme(mContext)) { + extendedLayout.textViewItemBody.setTextColor(mContext.getResources().getColor(R.color.extended_listview_item_body_text_color_light_theme)); + extendedLayout.viewDivider.setBackgroundColor(mContext.getResources().getColor(R.color.divider_row_color_light_theme)); + } + } + + + static class ExtendedLayout { + @InjectView(R.id.divider) View viewDivider; + @InjectView(R.id.summary) TextView textViewSummary; + @InjectView(R.id.tv_item_date) TextView textViewItemDate; + @InjectView(R.id.body) TextView textViewItemBody; + @InjectView(R.id.tv_subscription) TextView textViewTitle; + + ExtendedLayout(View view) { + ButterKnife.inject(this, view); + } + } + + + @TargetApi(Build.VERSION_CODES.HONEYCOMB) + public void setExtendedLayoutWebView(View view, RssItem rssItem) + { + WebView webViewContent = (WebView) view.findViewById(R.id.webView_body); + webViewContent.setClickable(false); + webViewContent.setFocusable(false); + //if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) + // webViewContent.setLayerType(View.LAYER_TYPE_SOFTWARE, null); + + webViewContent.loadDataWithBaseURL("", NewsDetailFragment.getHtmlPage(mContext, rssItem), "text/html", "UTF-8", ""); + } + + + + private void UpdateIsReadCheckBox(View view, RssItem item) + { + LinearLayout lLayout = (LinearLayout) view.getParent(); + Boolean read = item.getRead_temp(); + RobotoCheckBox cbRead = (RobotoCheckBox) lLayout.findViewById(R.id.cb_lv_item_read); + if(cbRead == null) {//In the default layout the star checkbox is nested two times. + lLayout = (LinearLayout) lLayout.getParent(); + cbRead = (RobotoCheckBox) lLayout.findViewById(R.id.cb_lv_item_read); + } + cbRead.setChecked(read); + } + + public static void ChangeCheckBoxState(RobotoCheckBox cb, boolean state, Context context) + { + if(cb != null && cb.isChecked() != state) + cb.setChecked(state); + } + + public static void UpdateListCursor(Context context) + { + FragmentActivity sfa = (FragmentActivity) context; + + if(sfa instanceof NewsReaderListActivity && ((NewsReaderListActivity) sfa).isSlidingPaneOpen()) + ((NewsReaderListActivity) sfa).updateAdapter(); + } + + + private String getBodyText(String body) + { + body = body.replaceAll("<img[^>]*>", ""); + body = body.replaceAll("<video[^>]*>", ""); + + SpannableString bodyStringSpannable = new SpannableString(Html.fromHtml(body)); + bodyStringSpannable.setSpan(bodyForegroundColor, 0, bodyStringSpannable.length(), Spannable.SPAN_INCLUSIVE_INCLUSIVE); + + String bodyString = bodyStringSpannable.toString().trim(); + + if(bodyString.length() > LengthBody) + bodyString = bodyString.substring(0, LengthBody); + + return bodyString; + } + + + @Override + public View newView(Context context, RssItem item, ViewGroup parent) { + // when the view will be created for first time, + // we need to tell the adapters, how each item will look + LayoutInflater inflater = LayoutInflater.from(parent.getContext()); + View retView = null; + + switch (selectedDesign) { + case 0: + retView = inflater.inflate(R.layout.subscription_detail_list_item_simple, parent, false); + break; + case 1: + retView = inflater.inflate(R.layout.subscription_detail_list_item_extended, parent, false); + break; + case 2: + retView = inflater.inflate(R.layout.subscription_detail_list_item_extended_webview, parent, false); + break; + } + + + if(retView != null) + retView.setTag(item.getId()); + + return retView; + } + + + + class DescriptionTextGetter implements IGetTextForTextViewAsyncTask { + + private Long idItemDb; + + public DescriptionTextGetter(Long idItemDb) { + this.idItemDb = idItemDb; + } + + @Override + public String getText() { + + DatabaseConnectionOrm dbConn = new DatabaseConnectionOrm(mContext); + + RssItem rssItem = dbConn.getRssItemById(idItemDb); + + String body = rssItem.getBody(); + String result = getBodyText(body); + + return result; + } + } + + + public static void FadeInTextView(final TextView textView) + { + Animation fadeOut = new AlphaAnimation(0, 1); + fadeOut.setInterpolator(new AccelerateInterpolator()); + fadeOut.setDuration(300); + + fadeOut.setAnimationListener(new Animation.AnimationListener() + { + public void onAnimationEnd(Animation animation) + { + textView.setVisibility(View.VISIBLE); + } + public void onAnimationRepeat(Animation animation) {} + public void onAnimationStart(Animation animation) {} + }); + + textView.startAnimation(fadeOut); + } +} diff --git a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/async_tasks/GetImageAsyncTask.java b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/async_tasks/GetImageAsyncTask.java index 5d9487f0..3e40bd2e 100644 --- a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/async_tasks/GetImageAsyncTask.java +++ b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/async_tasks/GetImageAsyncTask.java @@ -56,7 +56,7 @@ public class GetImageAsyncTask extends AsyncTask<Void, Void, String> private BitmapDrawableLruCache lruCache; - public String feedID = null; + public Long feedID = null; public boolean scaleImage = false; public int dstHeight; // height in pixels public int dstWidth; // width in pixels diff --git a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/authentication/AuthenticatorActivity.java b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/authentication/AuthenticatorActivity.java index 45adf219..1be288e1 100644 --- a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/authentication/AuthenticatorActivity.java +++ b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/authentication/AuthenticatorActivity.java @@ -1,13 +1,13 @@ package de.luhmer.owncloudnewsreader.authentication; import android.os.Bundle; +import android.support.v7.app.ActionBarActivity; -import com.actionbarsherlock.app.SherlockFragmentActivity; import de.luhmer.owncloudnewsreader.NewsReaderListActivity; import de.luhmer.owncloudnewsreader.R; -public class AuthenticatorActivity extends SherlockFragmentActivity { +public class AuthenticatorActivity extends ActionBarActivity { public final static String ARG_ACCOUNT_TYPE = "ACCOUNT_TYPE"; public final static String ARG_AUTH_TYPE = "AUTH_TYPE"; diff --git a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/cursor/NewsListCursorAdapter.java b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/cursor/NewsListCursorAdapter.java index 54e7fa53..ebc1e081 100644 --- a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/cursor/NewsListCursorAdapter.java +++ b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/cursor/NewsListCursorAdapter.java @@ -28,6 +28,7 @@ import android.content.SharedPreferences; import android.database.Cursor; import android.os.Build; import android.preference.PreferenceManager; +import android.support.v4.app.FragmentActivity; import android.support.v4.widget.CursorAdapter; import android.text.Html; import android.text.Spannable; @@ -46,13 +47,11 @@ import android.widget.CompoundButton.OnCheckedChangeListener; import android.widget.LinearLayout; import android.widget.TextView; -import com.actionbarsherlock.app.SherlockFragmentActivity; import com.devspark.robototextview.widget.RobotoCheckBox; import com.devspark.robototextview.widget.RobotoTextView; import butterknife.ButterKnife; import butterknife.InjectView; -import de.luhmer.owncloudnewsreader.NewsDetailFragment; import de.luhmer.owncloudnewsreader.NewsReaderListActivity; import de.luhmer.owncloudnewsreader.R; import de.luhmer.owncloudnewsreader.SettingsActivity; @@ -65,6 +64,7 @@ import de.luhmer.owncloudnewsreader.helper.ThemeChooser; import de.luhmer.owncloudnewsreader.reader.IReader; import de.luhmer.owncloudnewsreader.reader.owncloud.OwnCloud_Reader; +@Deprecated public class NewsListCursorAdapter extends CursorAdapter { //private static final String TAG = "NewsListCursorAdapter"; DatabaseConnection dbConn; @@ -287,9 +287,10 @@ public class NewsListCursorAdapter extends CursorAdapter { //if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) // webViewContent.setLayerType(View.LAYER_TYPE_SOFTWARE, null); - webViewContent.loadDataWithBaseURL("", NewsDetailFragment.getHtmlPage(mContext, dbConn , cursor.getInt(0)), "text/html", "UTF-8", ""); + //webViewContent.loadDataWithBaseURL("", NewsDetailFragment.getHtmlPage(mContext, dbConn , cursor.getInt(0)), "text/html", "UTF-8", ""); //This line is needed to run the adapter } + public void CloseDatabaseConnection() { if(dbConn != null) @@ -316,7 +317,7 @@ public class NewsListCursorAdapter extends CursorAdapter { public static void UpdateListCursor(Context context) { - SherlockFragmentActivity sfa = (SherlockFragmentActivity) context; + FragmentActivity sfa = (FragmentActivity) context; if(sfa instanceof NewsReaderListActivity && ((NewsReaderListActivity) sfa).isSlidingPaneOpen()) ((NewsReaderListActivity) sfa).updateAdapter(); diff --git a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/database/DatabaseConnection.java b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/database/DatabaseConnection.java index a5085f5c..b776e36d 100644 --- a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/database/DatabaseConnection.java +++ b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/database/DatabaseConnection.java @@ -145,7 +145,7 @@ public class DatabaseConnection { return openHelper; } - public void clearDatabaseOverSize() + public void getAllItemsIdsForFeedSQL() { //If i have 9023 rows in the database, when i run that query it should delete 8023 rows and leave me with 1000 //database.execSQL("DELETE FROM " + RSS_ITEM_TABLE + " WHERE " + + "ORDER BY rowid DESC LIMIT 1000 * @@ -952,11 +952,13 @@ public class DatabaseConnection { { cursor.moveToFirst(); do { + /* PodcastFeedItem podcastItem = new PodcastFeedItem(); podcastItem.itemId = cursor.getString(0); podcastItem.title = cursor.getString(1); podcastItem.count = cursor.getInt(2); result.add(podcastItem); + */ } while(cursor.moveToNext()); } } @@ -1018,7 +1020,7 @@ public class DatabaseConnection { public static PodcastItem ParsePodcastItemFromCursor(Context context, Cursor cursor) { PodcastItem podcastItem = new PodcastItem(); - podcastItem.itemId = cursor.getString(0); + podcastItem.itemId = cursor.getLong(0); podcastItem.title = cursor.getString(cursor.getColumnIndex(RSS_ITEM_TITLE)); //cursor.getString(1); podcastItem.link = cursor.getString(cursor.getColumnIndex(RSS_ITEM_ENC_LINK)); //cursor.getString(2); podcastItem.mimeType = cursor.getString(cursor.getColumnIndex(RSS_ITEM_ENC_MIME)); //cursor.getString(3); diff --git a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/database/DatabaseConnectionOrm.java b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/database/DatabaseConnectionOrm.java new file mode 100644 index 00000000..94cf4d7c --- /dev/null +++ b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/database/DatabaseConnectionOrm.java @@ -0,0 +1,616 @@ +package de.luhmer.owncloudnewsreader.database; + +import android.content.Context; +import android.database.Cursor; +import android.util.SparseArray; + +import java.io.File; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Iterator; +import java.util.List; + +import de.greenrobot.dao.query.LazyList; +import de.greenrobot.dao.query.WhereCondition; +import de.luhmer.owncloudnewsreader.Constants; +import de.luhmer.owncloudnewsreader.database.model.CurrentRssItemViewDao; +import de.luhmer.owncloudnewsreader.database.model.DaoSession; +import de.luhmer.owncloudnewsreader.database.model.Feed; +import de.luhmer.owncloudnewsreader.database.model.FeedDao; +import de.luhmer.owncloudnewsreader.database.model.Folder; +import de.luhmer.owncloudnewsreader.database.model.FolderDao; +import de.luhmer.owncloudnewsreader.database.model.RssItem; +import de.luhmer.owncloudnewsreader.database.model.RssItemDao; +import de.luhmer.owncloudnewsreader.model.PodcastFeedItem; +import de.luhmer.owncloudnewsreader.model.PodcastItem; +import de.luhmer.owncloudnewsreader.services.PodcastDownloadService; + +import static de.luhmer.owncloudnewsreader.ListView.SubscriptionExpandableListAdapter.SPECIAL_FOLDERS; +import static de.luhmer.owncloudnewsreader.ListView.SubscriptionExpandableListAdapter.SPECIAL_FOLDERS.ALL_ITEMS; +import static de.luhmer.owncloudnewsreader.ListView.SubscriptionExpandableListAdapter.SPECIAL_FOLDERS.ALL_STARRED_ITEMS; +import static de.luhmer.owncloudnewsreader.ListView.SubscriptionExpandableListAdapter.SPECIAL_FOLDERS.ALL_UNREAD_ITEMS; + +/** + * Created by David on 15.07.2014. + */ +public class DatabaseConnectionOrm { + + private static final List<String> ALLOWED_PODCASTS_TYPES = new ArrayList<String>() { + { + this.add("audio/mp3"); + this.add("audio/mpeg"); + this.add("audio/ogg"); + this.add("audio/opus"); + this.add("audio/ogg;codecs=opus"); + this.add("youtube"); + } + }; + + + + DaoSession daoSession; + + public void resetDatabase() { + daoSession.getRssItemDao().deleteAll(); + daoSession.getFeedDao().deleteAll(); + daoSession.getFolderDao().deleteAll(); + } + + public DatabaseConnectionOrm(Context context) { + daoSession = DatabaseHelperOrm.getDaoSession(context); + } + + public void insertNewFolder (Folder folder) { + daoSession.getFolderDao().insertOrReplace(folder); + } + + public void insertNewFeed (Feed feed) { + daoSession.getFeedDao().insertOrReplace(feed); + } + + public void insertNewItems(RssItem... items) { + daoSession.getRssItemDao().insertOrReplaceInTx(items); + } + + public List<Folder> getListOfFolders() { + return daoSession.getFolderDao().loadAll(); + } + + public List<Folder> getListOfFoldersWithUnreadItems() { + return daoSession.getFolderDao().queryBuilder().where( + new WhereCondition.StringCondition(FolderDao.Properties.Id.columnName + " IN " + + "(SELECT " + FeedDao.Properties.FolderId.columnName + " FROM " + FeedDao.TABLENAME + " feed " + + " JOIN " + RssItemDao.TABLENAME + " rss ON feed." + FeedDao.Properties.Id.columnName + " = rss." + RssItemDao.Properties.FeedId.columnName + + " WHERE rss." + RssItemDao.Properties.Read_temp.columnName + " != 1)") + ).list(); + } + + public List<Feed> getListOfFeeds() { + return daoSession.getFeedDao().loadAll(); + } + + public List<Feed> getListOfFeedsWithUnreadItems() { + List<Feed> feedsWithUnreadItems = new ArrayList<Feed>(); + + for(Feed feed : getListOfFeeds()) { + for(RssItem rssItem : feed.getRssItemList()) { + if (!rssItem.getRead_temp()) { + feedsWithUnreadItems.add(feed); + break; + } + } + } + return feedsWithUnreadItems; + } + + public Folder getFolderById(long folderId) { + return daoSession.getFolderDao().queryBuilder().where(FolderDao.Properties.Id.eq(folderId)).unique(); + } + + public Feed getFeedById(long feedId) { + return daoSession.getFeedDao().queryBuilder().where(FeedDao.Properties.Id.eq(feedId)).unique(); + } + + public List<Feed> getListOfFeedsWithFolders() { + return daoSession.getFeedDao().queryBuilder().where(FeedDao.Properties.FolderId.isNotNull()).list(); + } + + public List<Feed> getListOfFeedsWithoutFolders(boolean onlyWithUnreadRssItems) { + if(onlyWithUnreadRssItems) { + return daoSession.getFeedDao().queryBuilder().where(FeedDao.Properties.FolderId.eq(0L), + new WhereCondition.StringCondition(FeedDao.Properties.Id.columnName + " IN " + "(SELECT " + RssItemDao.Properties.FeedId.columnName + " FROM " + RssItemDao.TABLENAME + " WHERE " + RssItemDao.Properties.Read_temp.columnName + " != 1)")).list(); + } else { + return daoSession.getFeedDao().queryBuilder().where(FeedDao.Properties.FolderId.eq(0L)).list(); + } + } + + public List<Feed> getAllFeedsWithUnreadRssItems() { + return daoSession.getFeedDao().queryBuilder().where( + new WhereCondition.StringCondition(FeedDao.Properties.Id.columnName + " IN " + "(SELECT " + RssItemDao.Properties.FeedId.columnName + " FROM " + RssItemDao.TABLENAME + " WHERE " + RssItemDao.Properties.Read_temp.columnName + " != 1)")).list(); + } + + public List<Feed> getAllFeedsWithUnreadRssItemsForFolder(long folderId, boolean onlyUnread) { + if(onlyUnread) { + String whereConditionString = " IN " + "(SELECT " + RssItemDao.Properties.FeedId.columnName + " FROM " + RssItemDao.TABLENAME + " WHERE " + RssItemDao.Properties.Read_temp.columnName + " != 1)"; + WhereCondition whereCondition = new WhereCondition.StringCondition(FeedDao.Properties.Id.columnName + whereConditionString); + return daoSession.getFeedDao().queryBuilder().where(whereCondition, FeedDao.Properties.FolderId.eq(folderId)).list(); + } else { + return daoSession.getFeedDao().queryBuilder().where(FeedDao.Properties.FolderId.eq(folderId)).list(); + } + } + + public List<Feed> getAllFeedsWithStarredRssItems() { + return daoSession.getFeedDao().queryBuilder().where( + new WhereCondition.StringCondition(FeedDao.Properties.Id.columnName + " IN " + "(SELECT " + RssItemDao.Properties.FeedId.columnName + " FROM " + RssItemDao.TABLENAME + " WHERE " + RssItemDao.Properties.Starred_temp.columnName + " = 1)")).list(); + } + + public List<PodcastFeedItem> getListOfFeedsWithAudioPodcasts() { + WhereCondition whereCondition = new WhereCondition.StringCondition(FeedDao.Properties.Id.columnName + " IN " + "(SELECT " + RssItemDao.Properties.FeedId.columnName + " FROM " + RssItemDao.TABLENAME + " WHERE " + RssItemDao.Properties.EnclosureMime.columnName + " IN(\"" + join(ALLOWED_PODCASTS_TYPES, "\",\"") + "\"))"); + List<Feed> feedsWithPodcast = daoSession.getFeedDao().queryBuilder().where(whereCondition).list(); + + List<PodcastFeedItem> podcastFeedItemsList = new ArrayList<PodcastFeedItem>(feedsWithPodcast.size()); + for(Feed feed : feedsWithPodcast) { + int podcastCount = 0; + for(RssItem rssItem : feed.getRssItemList()) { + if(ALLOWED_PODCASTS_TYPES.contains(rssItem.getEnclosureMime())) + podcastCount++; + } + + podcastFeedItemsList.add(new PodcastFeedItem(feed, podcastCount)); + } + return podcastFeedItemsList; + } + + public List<PodcastItem> getListOfAudioPodcastsForFeed(Context context, long feedId) { + List<PodcastItem> result = new ArrayList<PodcastItem>(); + + for(RssItem rssItem : daoSession.getRssItemDao().queryBuilder() + .where(RssItemDao.Properties.EnclosureMime.in(ALLOWED_PODCASTS_TYPES), RssItemDao.Properties.FeedId.eq(feedId)) + .orderDesc(RssItemDao.Properties.PubDate).list()) { + PodcastItem podcastItem = ParsePodcastItemFromRssItem(context, rssItem); + result.add(podcastItem); + } + + return result; + } + + public boolean areThereAnyUnsavedChangesInDatabase() { + long countUnreadRead = daoSession.getRssItemDao().queryBuilder().where(RssItemDao.Properties.Read_temp.notEq(RssItemDao.Properties.Read)).count(); + long countStarredUnstarred = daoSession.getRssItemDao().queryBuilder().where(RssItemDao.Properties.Starred_temp.notEq(RssItemDao.Properties.Starred)).count(); + + return (countUnreadRead + countStarredUnstarred) > 0 ? true : false; + } + + + public void updateFeed(Feed feed) { + daoSession.getFeedDao().update(feed); + } + + + public long getLowestRssItemIdUnread() { + return daoSession.getRssItemDao().queryBuilder().where(RssItemDao.Properties.Read_temp.eq(false)).orderAsc(RssItemDao.Properties.Id).limit(1).unique().getId(); + } + + public RssItem getLowestRssItemIdByFeed(long idFeed) { + return daoSession.getRssItemDao().queryBuilder().where(RssItemDao.Properties.FeedId.eq(idFeed)).orderAsc(RssItemDao.Properties.Id).limit(1).unique(); + } + + public RssItem getRssItemById(long rssItemId) { + return daoSession.getRssItemDao().queryBuilder().where(RssItemDao.Properties.Id.eq(rssItemId)).unique(); + } + + + /** + * Changes the read unread state of the item. This is NOT the temp value!!! + * @param itemIds + * @param markAsRead + */ + public void change_readUnreadStateOfItem(List<String> itemIds, boolean markAsRead) + { + if(itemIds != null) + for(String idItem : itemIds) + updateIsReadOfRssItem(idItem, markAsRead); + } + + /** + * Changes the starred unstarred state of the item. This is NOT the temp value!!! + * @param itemIds + * @param markAsStarred + */ + public void change_starrUnstarrStateOfItem(List<String> itemIds, boolean markAsStarred) + { + if(itemIds != null) + for(String idItem : itemIds) + updateIsStarredOfRssItem(idItem, markAsStarred); + } + + public void updateIsReadOfRssItem(String ITEM_ID, Boolean isRead) { + RssItem rssItem = daoSession.getRssItemDao().queryBuilder().where(RssItemDao.Properties.Id.eq(ITEM_ID)).unique(); + + rssItem.setRead(isRead); + rssItem.setRead_temp(isRead); + + daoSession.getRssItemDao().update(rssItem); + } + + public void updateIsStarredOfRssItem(String ITEM_ID, Boolean isStarred) { + RssItem rssItem = daoSession.getRssItemDao().queryBuilder().where(RssItemDao.Properties.Id.eq(ITEM_ID)).unique(); + + rssItem.setStarred(isStarred); + rssItem.setStarred_temp(isStarred); + + daoSession.getRssItemDao().update(rssItem); + } + + public List<String> getRssItemsIdsFromList(List<RssItem> rssItemList) { + List<String> itemIds = new ArrayList<String>(); + for(RssItem rssItem : rssItemList) { + itemIds.add(String.valueOf(rssItem.getId())); + } + return itemIds; + } + + public List<RssItem> getAllNewReadRssItems() { + return daoSession.getRssItemDao().queryBuilder().where(RssItemDao.Properties.Read.eq(false), RssItemDao.Properties.Read_temp.eq(true)).list(); + } + + public List<RssItem> getAllNewUnreadRssItems() { + return daoSession.getRssItemDao().queryBuilder().where(RssItemDao.Properties.Read.eq(true), RssItemDao.Properties.Read_temp.eq(false)).list(); + } + + public List<RssItem> getAllNewStarredRssItems() { + return daoSession.getRssItemDao().queryBuilder().where(RssItemDao.Properties.Starred.eq(false), RssItemDao.Properties.Starred_temp.eq(true)).list(); + } + + public List<RssItem> getAllNewUnstarredRssItems() { + return daoSession.getRssItemDao().queryBuilder().where(RssItemDao.Properties.Starred.eq(true), RssItemDao.Properties.Starred_temp.eq(false)).list(); + } + + + + + + public int getCountOfAllItems(boolean execludeStarred) {//TODO needs testing! + long count; + if(execludeStarred) + count = daoSession.getRssItemDao().queryBuilder().where(RssItemDao.Properties.Starred_temp.notEq(true)).count(); + else + count = daoSession.getRssItemDao().count(); + return (int) count; + } + + public List<RssItem> getAllItemsWithIdHigher(long id) {//TODO needs testing! + return daoSession.getRssItemDao().queryBuilder().where(RssItemDao.Properties.Id.ge(id)).list(); + } + + public void updateRssItem(RssItem rssItem) { + daoSession.getRssItemDao().update(rssItem); + } + + public boolean doesRssItemAlreadyExsists (long feedId) { + List<RssItem> feeds = daoSession.getRssItemDao().queryBuilder().where(RssItemDao.Properties.Id.eq(feedId)).list(); + return (feeds.size() <= 0) ? false : true; + } + + + public void removeFeedById(long feedId) { + daoSession.getFeedDao().deleteByKey(feedId); + } + + + + + public SparseArray<String> getUrlsToFavIcons() { + SparseArray<String> favIconUrls = new SparseArray<String>(); + + for(Feed feed : getListOfFeeds()) + favIconUrls.put((int) feed.getId(), feed.getFaviconUrl()); + + return favIconUrls; + } + + + public LazyList<RssItem> getCurrentRssItemView(DatabaseConnection.SORT_DIRECTION sortDirection) { + WhereCondition whereCondition = new WhereCondition.StringCondition(RssItemDao.Properties.Id.columnName + " IN " + + "(SELECT " + CurrentRssItemViewDao.Properties.RssItemId.columnName + " FROM " + CurrentRssItemViewDao.TABLENAME + ")"); + + if(sortDirection.equals(DatabaseConnection.SORT_DIRECTION.asc)) + return daoSession.getRssItemDao().queryBuilder().where(whereCondition).orderAsc(RssItemDao.Properties.PubDate).listLazy(); + else + return daoSession.getRssItemDao().queryBuilder().where(whereCondition).orderDesc(RssItemDao.Properties.PubDate).listLazy(); + } + + /* + public void markAllItemsAsReadForCurrentView() + { + String sql = "UPDATE " + RssItemDao.TABLENAME + " SET " + RssItemDao.Properties.Read_temp.columnName + " = 1 WHERE " + RssItemDao.Properties.Id.columnName + + " IN (SELECT " + CurrentRssItemViewDao.Properties.RssItemId.columnName + " FROM " + CurrentRssItemViewDao.TABLENAME + ")"; + daoSession.getDatabase().execSQL(sql); + } + */ + + public static PodcastItem ParsePodcastItemFromRssItem(Context context, RssItem rssItem) { + PodcastItem podcastItem = new PodcastItem(); + podcastItem.itemId = rssItem.getId(); + podcastItem.title = rssItem.getTitle(); + podcastItem.link = rssItem.getEnclosureLink(); + podcastItem.mimeType = rssItem.getEnclosureMime(); + + File file = new File(PodcastDownloadService.getUrlToPodcastFile(context, podcastItem.link, false)); + podcastItem.offlineCached = file.exists(); + + return podcastItem; + } + + + public String getAllItemsIdsForFeedSQL(long idFeed, boolean onlyUnread, boolean onlyStarredItems, DatabaseConnection.SORT_DIRECTION sortDirection) { + + String buildSQL = "SELECT " + RssItemDao.Properties.Id.columnName + + " FROM " + RssItemDao.TABLENAME + + " WHERE " + RssItemDao.Properties.FeedId.columnName + " IN " + + "(SELECT " + FeedDao.Properties.Id.columnName + + " FROM " + FeedDao.TABLENAME + + " WHERE " + FeedDao.Properties.Id.columnName + " = " + idFeed + ")"; + + if(onlyUnread && !onlyStarredItems) + buildSQL += " AND " + RssItemDao.Properties.Read_temp.columnName + " != 1"; + else if(onlyStarredItems) + buildSQL += " AND " + RssItemDao.Properties.Starred_temp.columnName + " = 1"; + + buildSQL += " ORDER BY " + RssItemDao.Properties.PubDate.columnName + " " + sortDirection.toString(); + + return buildSQL; + } + + + public Long getLowestItemIdByFolder(Long id_folder) { + WhereCondition whereCondition = new WhereCondition.StringCondition(RssItemDao.Properties.FeedId.columnName + " IN " + + "(SELECT " + FeedDao.Properties.Id.columnName + + " FROM " + FeedDao.TABLENAME + + " WHERE " + FeedDao.Properties.FolderId.columnName + " = " + id_folder + ")"); + + RssItem rssItem = daoSession.getRssItemDao().queryBuilder().orderAsc(RssItemDao.Properties.Id).where(whereCondition).limit(1).unique(); + return (rssItem != null) ? rssItem.getId() : 0; + } + + public List<RssItem> getListOfAllItemsForFolder(long ID_FOLDER, boolean onlyUnread, DatabaseConnection.SORT_DIRECTION sortDirection) {//TODO needs testing! + String whereStatement = getAllItemsIdsForFolderSQL(ID_FOLDER, onlyUnread, sortDirection); + whereStatement = whereStatement.replace("SELECT " + RssItemDao.Properties.Id.columnName + " FROM " + RssItemDao.TABLENAME, ""); + return daoSession.getRssItemDao().queryRaw(whereStatement, null); + } + + public String getAllItemsIdsForFolderSQL(long ID_FOLDER, boolean onlyUnread, DatabaseConnection.SORT_DIRECTION sortDirection) { + String buildSQL = "SELECT " + RssItemDao.Properties.Id.columnName + + " FROM " + RssItemDao.TABLENAME; + + if(!(ID_FOLDER == ALL_UNREAD_ITEMS.getValue() || ID_FOLDER == ALL_STARRED_ITEMS.getValue()) || ID_FOLDER == ALL_ITEMS.getValue())//Wenn nicht Alle Artikel ausgewaehlt wurde (-10) oder (-11) fuer Starred Feeds + { + buildSQL += " WHERE " + RssItemDao.Properties.FeedId.columnName + " IN " + + "(SELECT sc." + FeedDao.Properties.Id.columnName + + " FROM " + FeedDao.TABLENAME + " sc " + + " JOIN " + FolderDao.TABLENAME + " f ON sc." + FeedDao.Properties.FolderId.columnName + " = f." + FolderDao.Properties.Id.columnName + + " WHERE f." + FolderDao.Properties.Id.columnName + " = " + ID_FOLDER + ")"; + + if(onlyUnread) + buildSQL += " AND " + RssItemDao.Properties.Read_temp.columnName + " != 1"; + } + else if(ID_FOLDER == ALL_UNREAD_ITEMS.getValue()) + buildSQL += " WHERE " + RssItemDao.Properties.Read_temp.columnName + " != 1"; + else if(ID_FOLDER == ALL_STARRED_ITEMS.getValue()) + buildSQL += " WHERE " + RssItemDao.Properties.Starred_temp.columnName + " = 1"; + + + buildSQL += " ORDER BY " + RssItemDao.Properties.PubDate.columnName + " " + sortDirection.toString(); + + + return buildSQL; + } + + public void insertIntoRssCurrentViewTable(String SQL_SELECT) { + SQL_SELECT = "INSERT INTO " + CurrentRssItemViewDao.TABLENAME + + " (" + CurrentRssItemViewDao.Properties.RssItemId.columnName + ") " + SQL_SELECT; + daoSession.getCurrentRssItemViewDao().deleteAll(); + daoSession.getDatabase().execSQL(SQL_SELECT); + } + + public SparseArray<String> getUnreadItemCountForFolder() { + String buildSQL = "SELECT f." + FolderDao.Properties.Id.columnName + ", COUNT(rss." + RssItemDao.Properties.Id.columnName + ")" + + " FROM " + RssItemDao.TABLENAME + " rss " + + " JOIN " + FeedDao.TABLENAME + " feed ON rss." + RssItemDao.Properties.FeedId.columnName + " = feed." + FeedDao.Properties.Id.columnName + + " JOIN " + FolderDao.TABLENAME + " f ON feed." + FeedDao.Properties.FolderId.columnName + " = f." + FolderDao.Properties.Id.columnName + + " WHERE " + RssItemDao.Properties.Read_temp.columnName + " != 1 " + + " GROUP BY f." + FolderDao.Properties.Id.columnName; + + SparseArray<String> values = getStringSparseArrayFromSQL(buildSQL, 0, 1); + + values.put(SPECIAL_FOLDERS.ALL_UNREAD_ITEMS.getValue(), getUnreadItemsCountForSpecificFolder(SPECIAL_FOLDERS.ALL_UNREAD_ITEMS)); + values.put(SPECIAL_FOLDERS.ALL_STARRED_ITEMS.getValue(), getUnreadItemsCountForSpecificFolder(SPECIAL_FOLDERS.ALL_STARRED_ITEMS)); + + + return values; + } + + public String getUnreadItemsCountForSpecificFolder(SPECIAL_FOLDERS specialFolder) { + String buildSQL = "SELECT COUNT(rss." + RssItemDao.Properties.Id.columnName + ")" + + " FROM " + RssItemDao.TABLENAME + " rss "; + + if(specialFolder != null && specialFolder.equals(SPECIAL_FOLDERS.ALL_STARRED_ITEMS)) { + buildSQL += " WHERE " + RssItemDao.Properties.Starred_temp.columnName + " = 1 "; + } else { + buildSQL += " WHERE " + RssItemDao.Properties.Read_temp.columnName + " != 1 "; + } + + SparseArray<String> values = getStringSparseArrayFromSQL(buildSQL, 0, 0); + return values.valueAt(0); + } + + public SparseArray<String> getUnreadItemCountForFeed() { + String buildSQL = "SELECT " + RssItemDao.Properties.FeedId.columnName + ", COUNT(" + RssItemDao.Properties.Id.columnName + ")" + // rowid as _id, + " FROM " + RssItemDao.TABLENAME + + " WHERE " + RssItemDao.Properties.Read_temp.columnName + " != 1 " + + " GROUP BY " + RssItemDao.Properties.FeedId.columnName; + + return getStringSparseArrayFromSQL(buildSQL, 0, 1); + } + + public SparseArray<String> getStarredItemCountForFeed() { + String buildSQL = "SELECT " + RssItemDao.Properties.FeedId.columnName + ", COUNT(" + RssItemDao.Properties.Id.columnName + ")" + // rowid as _id, + " FROM " + RssItemDao.TABLENAME + + " WHERE " + RssItemDao.Properties.Starred_temp.columnName + " = 1 " + + " GROUP BY " + RssItemDao.Properties.FeedId.columnName; + + return getStringSparseArrayFromSQL(buildSQL, 0, 1); + } + + public void clearDatabaseOverSize() + { + //If i have 9023 rows in the database, when i run that query it should delete 8023 rows and leave me with 1000 + //database.execSQL("DELETE FROM " + RSS_ITEM_TABLE + " WHERE " + + "ORDER BY rowid DESC LIMIT 1000 * + + //Let's say it said 1005 - you need to delete 5 rows. + //DELETE FROM table ORDER BY dateRegistered ASC LIMIT 5 + + + int max = Constants.maxItemsCount; + int total = (int) getLongValueBySQL("SELECT COUNT(*) FROM " + RssItemDao.TABLENAME); + int unread = (int) getLongValueBySQL("SELECT COUNT(*) FROM " + RssItemDao.TABLENAME + " WHERE " + RssItemDao.Properties.Read_temp.columnName + " != 1"); + int read = total - unread; + + if(total > max) + { + int overSize = total - max; + //Soll verhindern, dass ungelesene Artikel gelöscht werden + if(overSize > read) + overSize = read; + + String sqlStatement = "DELETE FROM " + RssItemDao.TABLENAME + " WHERE " + RssItemDao.Properties.Id.columnName + + " IN (SELECT " + RssItemDao.Properties.Id.columnName + " FROM " + RssItemDao.TABLENAME + + " WHERE " + RssItemDao.Properties.Read_temp.columnName + " = 1 AND " + RssItemDao.Properties.Starred_temp.columnName + " != 1 " + + " ORDER BY " + RssItemDao.Properties.Id.columnName + " asc LIMIT " + overSize + ")"; + daoSession.getDatabase().execSQL(sqlStatement); + /* SELECT * FROM rss_item WHERE read_temp = 1 ORDER BY rowid asc LIMIT 3; */ + } + } + + public long getLastModified() + { + List<RssItem> rssItemList = daoSession.getRssItemDao().queryBuilder().orderDesc(RssItemDao.Properties.LastModified).limit(1).list(); + + if(rssItemList.size() > 0) + return rssItemList.get(0).getLastModified().getTime(); + return 0; + } + + public long getLowestItemId(boolean onlyStarred) + { + List<RssItem> rssItemList; + + if(onlyStarred) + rssItemList = daoSession.getRssItemDao().queryBuilder().orderDesc(RssItemDao.Properties.Starred_temp).orderAsc(RssItemDao.Properties.Id).limit(1).list(); + else + rssItemList = daoSession.getRssItemDao().queryBuilder().orderAsc(RssItemDao.Properties.Id).limit(1).list(); + + if(rssItemList.size() > 0) + return rssItemList.get(0).getId(); + return 0; + } + + public long getHighestItemId() + { + List<RssItem> rssItemList = daoSession.getRssItemDao().queryBuilder().orderDesc(RssItemDao.Properties.Id).limit(1).list(); + + if(rssItemList.size() > 0) + return rssItemList.get(0).getId(); + return 0; + } + + + + + + + + + public long getLongValueBySQL(String buildSQL) + { + long result = -1; + + Cursor cursor = daoSession.getDatabase().rawQuery(buildSQL, null); + try + { + if(cursor != null) + { + if(cursor.moveToFirst()) + result = cursor.getLong(0); + } + } finally { + cursor.close(); + } + + return result; + } + + public SparseArray<Integer> getIntegerSparseArrayFromSQL(String buildSQL, int indexKey, int indexValue) { + SparseArray<Integer> result = new SparseArray<Integer>(); + + Cursor cursor = daoSession.getDatabase().rawQuery(buildSQL, null); + try + { + if(cursor != null) + { + if(cursor.getCount() > 0) + { + cursor.moveToFirst(); + do { + int key = cursor.getInt(indexKey); + Integer value = cursor.getInt(indexValue); + result.put(key, value); + } while(cursor.moveToNext()); + } + } + } finally { + cursor.close(); + } + + return result; + } + + public SparseArray<String> getStringSparseArrayFromSQL(String buildSQL, int indexKey, int indexValue) { + SparseArray<String> result = new SparseArray<String>(); + + Cursor cursor = daoSession.getDatabase().rawQuery(buildSQL, null); + try + { + if(cursor != null) + { + if(cursor.getCount() > 0) + { + cursor.moveToFirst(); + do { + int key = cursor.getInt(indexKey); + String value = cursor.getString(indexValue); + result.put(key, value); + } while(cursor.moveToNext()); + } + } + } finally { + cursor.close(); + } + + return result; + } + + + + public static String join(Collection<?> col, String delim) { + StringBuilder sb = new StringBuilder(); + Iterator<?> iter = col.iterator(); + if (iter.hasNext()) + sb.append(iter.next().toString()); + while (iter.hasNext()) { + sb.append(delim); + sb.append(iter.next().toString()); + } + return sb.toString(); + } +} diff --git a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/database/DatabaseHelperOrm.java b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/database/DatabaseHelperOrm.java new file mode 100644 index 00000000..1ca1ca14 --- /dev/null +++ b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/database/DatabaseHelperOrm.java @@ -0,0 +1,51 @@ +/** + * Android ownCloud News + * + * @author David Luhmer + * @copyright 2013 David Luhmer david-dev@live.de + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE + * License as published by the Free Software Foundation; either + * version 3 of the License, or any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU AFFERO GENERAL PUBLIC LICENSE for more details. + * + * You should have received a copy of the GNU Affero General Public + * License along with this library. If not, see <http://www.gnu.org/licenses/>. + * + */ + +package de.luhmer.owncloudnewsreader.database; + +import android.content.Context; +import android.database.sqlite.SQLiteDatabase; + +import de.luhmer.owncloudnewsreader.database.model.DaoMaster; +import de.luhmer.owncloudnewsreader.database.model.DaoSession; + +public class DatabaseHelperOrm { + public static final String DATABASE_NAME_ORM = "OwncloudNewsReaderOrm.db"; + + + private static DaoSession daoSession; + + + public static synchronized DaoSession getDaoSession(Context context) + { + if(daoSession == null) { + // As we are in development we will use the DevOpenHelper which drops the database on a schema update + DaoMaster.DevOpenHelper helper = new DaoMaster.DevOpenHelper(context, DATABASE_NAME_ORM, null); + // Access the database using the helper + SQLiteDatabase db = helper.getWritableDatabase(); + // Construct the DaoMaster which brokers DAOs for the Domain Objects + DaoMaster daoMaster = new DaoMaster(db); + // Create the session which is a container for the DAO layer and has a cache which will return handles to the same object across multiple queries + daoSession = daoMaster.newSession(); + } + return daoSession; + } +} diff --git a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/database/generator/DatabaseOrmGenerator.java b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/database/generator/DatabaseOrmGenerator.java new file mode 100644 index 00000000..685b9477 --- /dev/null +++ b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/database/generator/DatabaseOrmGenerator.java @@ -0,0 +1,76 @@ +package de.luhmer.owncloudnewsreader.database.generator; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import de.greenrobot.daogenerator.DaoGenerator; + +/** + * Created by David on 15.07.2014. + */ +public class DatabaseOrmGenerator { + private static final String SCHEMA_OUTPUT_DIR = "./News-Android-App/src/main/java/"; + + + /** + * Generator main application which builds all of the schema versions + * (including older versions used for migration test purposes) and ensures + * business rules are met; these include ensuring we only have a single + * current schema instance and the version numbering is correct. + * + * @param args + * + * @throws Exception + * @throws IOException + */ + public static void main(String[] args) throws IOException, Exception { + List<SchemaVersion> versions = new ArrayList<SchemaVersion>(); + + versions.add(new Version3(true)); + + validateSchemas(versions); + + for (SchemaVersion version : versions) { + // NB: Test output creates stubs, we have an established testing + // standard which should be followed in preference to generating + // these stubs. + new DaoGenerator().generateAll(version.getSchema(), + SCHEMA_OUTPUT_DIR); + } + } + + /** + * Validate the schema, throws + * + * @param versions + * @throws IllegalArgumentException + * if data is invalid + */ + public static void validateSchemas(List<SchemaVersion> versions) + throws IllegalArgumentException { + int numCurrent = 0; + Set<Integer> versionNumbers = new HashSet<Integer>(); + + for (SchemaVersion version : versions) { + if (version.isCurrent()) { + numCurrent++; + } + + int versionNumber = version.getVersionNumber(); + if (versionNumbers.contains(versionNumber)) { + throw new IllegalArgumentException( + "Unable to process schema versions, multiple instances with version number : " + + version.getVersionNumber()); + } + versionNumbers.add(versionNumber); + } + + if (numCurrent != 1) { + throw new IllegalArgumentException( + "Unable to generate schema, exactly one schema marked as current is required."); + } + } +} diff --git a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/database/generator/SchemaVersion.java b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/database/generator/SchemaVersion.java new file mode 100644 index 00000000..e7573585 --- /dev/null +++ b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/database/generator/SchemaVersion.java @@ -0,0 +1,51 @@ +package de.luhmer.owncloudnewsreader.database.generator; + +import de.greenrobot.daogenerator.Schema; + +/** + * Created by David on 18.07.2014. + */ +public abstract class SchemaVersion { + + public static final String CURRENT_SCHEMA_PACKAGE = "de.luhmer.owncloudnewsreader.database.model"; + + + private final Schema schema; + + private final boolean current; + + /** + * Constructor + * + * @param current indicating if this is the current schema. + */ + public SchemaVersion(boolean current) { + int version = getVersionNumber(); + String packageName = CURRENT_SCHEMA_PACKAGE; + if (!current) { + packageName += ".v" + version; + } + this.schema = new Schema(version, packageName); + this.schema.enableKeepSectionsByDefault(); + this.current = current; + } + + /** + * @return the GreenDAO schema. + */ + protected Schema getSchema() { + return schema; + } + + /** + * @return boolean indicating if this is the highest or current schema version. + */ + public boolean isCurrent() { + return current; + } + + /** + * @return unique integer schema version identifier. + */ + public abstract int getVersionNumber(); +} diff --git a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/database/generator/Version3.java b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/database/generator/Version3.java new file mode 100644 index 00000000..dedc535b --- /dev/null +++ b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/database/generator/Version3.java @@ -0,0 +1,96 @@ +package de.luhmer.owncloudnewsreader.database.generator; + +/** + * Created by David on 18.07.2014. + */ + +import de.greenrobot.daogenerator.Entity; +import de.greenrobot.daogenerator.Property; +import de.greenrobot.daogenerator.Schema; + +/** + * Version 1 of the Schema definition + * + * @author Jeremy + */ +public class Version3 extends SchemaVersion { + + /** + * Constructor + * + * @param current + */ + public Version3(boolean current) { + super(current); + + Schema schema = getSchema(); + addEntitysToSchema(schema); + } + + /** + * {@inheritDoc} + */ + @Override + public int getVersionNumber() { + return 3; + } + + private static void addEntitysToSchema(Schema schema) { + + /* Folder */ + Entity folder = schema.addEntity("Folder"); + Property folderId = folder.addIdProperty().notNull().getProperty(); + folder.addStringProperty("label").notNull(); + + /* Feed */ + Entity feed = schema.addEntity("Feed"); + Property feedId = feed.addIdProperty().notNull().getProperty(); + Property folderIdProperty = feed.addLongProperty("folderId").getProperty(); + + feed.addStringProperty("feedTitle").notNull(); + feed.addStringProperty("faviconUrl"); + feed.addStringProperty("link"); + feed.addStringProperty("avgColour"); + + + + /* RSS Item */ + Entity rssItem = schema.addEntity("RssItem"); + Property rssItemId = rssItem.addIdProperty().notNull().getProperty(); + Property rssItemFeedId = rssItem.addLongProperty("feedId").notNull().getProperty(); + + rssItem.addStringProperty("link"); + rssItem.addStringProperty("title"); + rssItem.addStringProperty("body"); + rssItem.addBooleanProperty("read"); + rssItem.addBooleanProperty("starred"); + rssItem.addStringProperty("author").notNull(); + rssItem.addStringProperty("guid").notNull(); + rssItem.addStringProperty("guidHash").notNull(); + rssItem.addBooleanProperty("read_temp"); + rssItem.addBooleanProperty("starred_temp"); + rssItem.addDateProperty("lastModified"); + rssItem.addDateProperty("pubDate"); + + + rssItem.addStringProperty("enclosureLink"); + rssItem.addStringProperty("enclosureMime"); + + + feed.addToOne(folder, folderIdProperty); + folder.addToMany(feed, folderIdProperty); + + feed.addToMany(rssItem, rssItemFeedId); + rssItem.addToOne(feed, rssItemFeedId); + + + + + Entity rssItemView = schema.addEntity("CurrentRssItemView"); + rssItemView.addIdProperty().notNull(); + rssItemView.addLongProperty("rssItemId").notNull(); + + + rssItem.implementsInterface("HasId<Long>"); + } +} diff --git a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/database/model/CurrentRssItemView.java b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/database/model/CurrentRssItemView.java new file mode 100644 index 00000000..c87a740b --- /dev/null +++ b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/database/model/CurrentRssItemView.java @@ -0,0 +1,49 @@ +package de.luhmer.owncloudnewsreader.database.model; + +// THIS CODE IS GENERATED BY greenDAO, EDIT ONLY INSIDE THE "KEEP"-SECTIONS + +// KEEP INCLUDES - put your custom includes here +// KEEP INCLUDES END +/** + * Entity mapped to table CURRENT_RSS_ITEM_VIEW. + */ +public class CurrentRssItemView { + + private long id; + private long rssItemId; + + // KEEP FIELDS - put your custom fields here + // KEEP FIELDS END + + public CurrentRssItemView() { + } + + public CurrentRssItemView(long id) { + this.id = id; + } + + public CurrentRssItemView(long id, long rssItemId) { + this.id = id; + this.rssItemId = rssItemId; + } + + public long getId() { + return id; + } + + public void setId(long id) { + this.id = id; + } + + public long getRssItemId() { + return rssItemId; + } + + public void setRssItemId(long rssItemId) { + this.rssItemId = rssItemId; + } + + // KEEP METHODS - put your custom methods here + // KEEP METHODS END + +} diff --git a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/database/model/CurrentRssItemViewDao.java b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/database/model/CurrentRssItemViewDao.java new file mode 100644 index 00000000..dc2a8680 --- /dev/null +++ b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/database/model/CurrentRssItemViewDao.java @@ -0,0 +1,105 @@ +package de.luhmer.owncloudnewsreader.database.model; + +import android.database.Cursor; +import android.database.sqlite.SQLiteDatabase; +import android.database.sqlite.SQLiteStatement; + +import de.greenrobot.dao.AbstractDao; +import de.greenrobot.dao.Property; +import de.greenrobot.dao.internal.DaoConfig; + +// THIS CODE IS GENERATED BY greenDAO, DO NOT EDIT. +/** + * DAO for table CURRENT_RSS_ITEM_VIEW. +*/ +public class CurrentRssItemViewDao extends AbstractDao<CurrentRssItemView, Long> { + + public static final String TABLENAME = "CURRENT_RSS_ITEM_VIEW"; + + /** + * Properties of entity CurrentRssItemView.<br/> + * Can be used for QueryBuilder and for referencing column names. + */ + public static class Properties { + public final static Property Id = new Property(0, long.class, "id", true, "_id"); + public final static Property RssItemId = new Property(1, long.class, "rssItemId", false, "RSS_ITEM_ID"); + }; + + + public CurrentRssItemViewDao(DaoConfig config) { + super(config); + } + + public CurrentRssItemViewDao(DaoConfig config, DaoSession daoSession) { + super(config, daoSession); + } + + /** Creates the underlying database table. */ + public static void createTable(SQLiteDatabase db, boolean ifNotExists) { + String constraint = ifNotExists? "IF NOT EXISTS ": ""; + db.execSQL("CREATE TABLE " + constraint + "'CURRENT_RSS_ITEM_VIEW' (" + // + "'_id' INTEGER PRIMARY KEY NOT NULL ," + // 0: id + "'RSS_ITEM_ID' INTEGER NOT NULL );"); // 1: rssItemId + } + + /** Drops the underlying database table. */ + public static void dropTable(SQLiteDatabase db, boolean ifExists) { + String sql = "DROP TABLE " + (ifExists ? "IF EXISTS " : "") + "'CURRENT_RSS_ITEM_VIEW'"; + db.execSQL(sql); + } + + /** @inheritdoc */ + @Override + protected void bindValues(SQLiteStatement stmt, CurrentRssItemView entity) { + stmt.clearBindings(); + stmt.bindLong(1, entity.getId()); + stmt.bindLong(2, entity.getRssItemId()); + } + + /** @inheritdoc */ + @Override + public Long readKey(Cursor cursor, int offset) { + return cursor.getLong(offset + 0); + } + + /** @inheritdoc */ + @Override + public CurrentRssItemView readEntity(Cursor cursor, int offset) { + CurrentRssItemView entity = new CurrentRssItemView( // + cursor.getLong(offset + 0), // id + cursor.getLong(offset + 1) // rssItemId + ); + return entity; + } + + /** @inheritdoc */ + @Override + public void readEntity(Cursor cursor, CurrentRssItemView entity, int offset) { + entity.setId(cursor.getLong(offset + 0)); + entity.setRssItemId(cursor.getLong(offset + 1)); + } + + /** @inheritdoc */ + @Override + protected Long updateKeyAfterInsert(CurrentRssItemView entity, long rowId) { + entity.setId(rowId); + return rowId; + } + + /** @inheritdoc */ + @Override + public Long getKey(CurrentRssItemView entity) { + if(entity != null) { + return entity.getId(); + } else { + return null; + } + } + + /** @inheritdoc */ + @Override + protected boolean isEntityUpdateable() { + return true; + } + +} diff --git a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/database/model/DaoMaster.java b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/database/model/DaoMaster.java new file mode 100644 index 00000000..af494042 --- /dev/null +++ b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/database/model/DaoMaster.java @@ -0,0 +1,78 @@ +package de.luhmer.owncloudnewsreader.database.model; + +import android.content.Context; +import android.database.sqlite.SQLiteDatabase; +import android.database.sqlite.SQLiteDatabase.CursorFactory; +import android.database.sqlite.SQLiteOpenHelper; +import android.util.Log; + +import de.greenrobot.dao.AbstractDaoMaster; +import de.greenrobot.dao.identityscope.IdentityScopeType; + +// THIS CODE IS GENERATED BY greenDAO, DO NOT EDIT. +/** + * Master of DAO (schema version 3): knows all DAOs. +*/ +public class DaoMaster extends AbstractDaoMaster { + public static final int SCHEMA_VERSION = 3; + + /** Creates underlying database table using DAOs. */ + public static void createAllTables(SQLiteDatabase db, boolean ifNotExists) { + FolderDao.createTable(db, ifNotExists); + FeedDao.createTable(db, ifNotExists); + RssItemDao.createTable(db, ifNotExists); + CurrentRssItemViewDao.createTable(db, ifNotExists); + } + + /** Drops underlying database table using DAOs. */ + public static void dropAllTables(SQLiteDatabase db, boolean ifExists) { + FolderDao.dropTable(db, ifExists); + FeedDao.dropTable(db, ifExists); + RssItemDao.dropTable(db, ifExists); + CurrentRssItemViewDao.dropTable(db, ifExists); + } + + public static abstract class OpenHelper extends SQLiteOpenHelper { + + public OpenHelper(Context context, String name, CursorFactory factory) { + super(context, name, factory, SCHEMA_VERSION); + } + + @Override + public void onCreate(SQLiteDatabase db) { + Log.i("greenDAO", "Creating tables for schema version " + SCHEMA_VERSION); + createAllTables(db, false); + } + } + + /** WARNING: Drops all table on Upgrade! Use only during development. */ + public static class DevOpenHelper extends OpenHelper { + public DevOpenHelper(Context context, String name, CursorFactory factory) { + super(context, name, factory); + } + + @Override + public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { + Log.i("greenDAO", "Upgrading schema from version " + oldVersion + " to " + newVersion + " by dropping all tables"); + dropAllTables(db, true); + onCreate(db); + } + } + + public DaoMaster(SQLiteDatabase db) { + super(db, SCHEMA_VERSION); + registerDaoClass(FolderDao.class); + registerDaoClass(FeedDao.class); + registerDaoClass(RssItemDao.class); + registerDaoClass(CurrentRssItemViewDao.class); + } + + public DaoSession newSession() { + return new DaoSession(db, IdentityScopeType.Session, daoConfigMap); + } + + public DaoSession newSession(IdentityScopeType type) { + return new DaoSession(db, type, daoConfigMap); + } + +} diff --git a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/database/model/DaoSession.java b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/database/model/DaoSession.java new file mode 100644 index 00000000..12933605 --- /dev/null +++ b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/database/model/DaoSession.java @@ -0,0 +1,81 @@ +package de.luhmer.owncloudnewsreader.database.model; + +import android.database.sqlite.SQLiteDatabase; + +import java.util.Map; + +import de.greenrobot.dao.AbstractDao; +import de.greenrobot.dao.AbstractDaoSession; +import de.greenrobot.dao.identityscope.IdentityScopeType; +import de.greenrobot.dao.internal.DaoConfig; + +// THIS CODE IS GENERATED BY greenDAO, DO NOT EDIT. + +/** + * {@inheritDoc} + * + * @see de.greenrobot.dao.AbstractDaoSession + */ +public class DaoSession extends AbstractDaoSession { + + private final DaoConfig folderDaoConfig; + private final DaoConfig feedDaoConfig; + private final DaoConfig rssItemDaoConfig; + private final DaoConfig currentRssItemViewDaoConfig; + + private final FolderDao folderDao; + private final FeedDao feedDao; + private final RssItemDao rssItemDao; + private final CurrentRssItemViewDao currentRssItemViewDao; + + public DaoSession(SQLiteDatabase db, IdentityScopeType type, Map<Class<? extends AbstractDao<?, ?>>, DaoConfig> + daoConfigMap) { + super(db); + + folderDaoConfig = daoConfigMap.get(FolderDao.class).clone(); + folderDaoConfig.initIdentityScope(type); + + feedDaoConfig = daoConfigMap.get(FeedDao.class).clone(); + feedDaoConfig.initIdentityScope(type); + + rssItemDaoConfig = daoConfigMap.get(RssItemDao.class).clone(); + rssItemDaoConfig.initIdentityScope(type); + + currentRssItemViewDaoConfig = daoConfigMap.get(CurrentRssItemViewDao.class).clone(); + currentRssItemViewDaoConfig.initIdentityScope(type); + + folderDao = new FolderDao(folderDaoConfig, this); + feedDao = new FeedDao(feedDaoConfig, this); + rssItemDao = new RssItemDao(rssItemDaoConfig, this); + currentRssItemViewDao = new CurrentRssItemViewDao(currentRssItemViewDaoConfig, this); + + registerDao(Folder.class, folderDao); + registerDao(Feed.class, feedDao); + registerDao(RssItem.class, rssItemDao); + registerDao(CurrentRssItemView.class, currentRssItemViewDao); + } + + public void clear() { + folderDaoConfig.getIdentityScope().clear(); + feedDaoConfig.getIdentityScope().clear(); + rssItemDaoConfig.getIdentityScope().clear(); + currentRssItemViewDaoConfig.getIdentityScope().clear(); + } + + public FolderDao getFolderDao() { + return folderDao; + } + + public FeedDao getFeedDao() { + return feedDao; + } + + public RssItemDao getRssItemDao() { + return rssItemDao; + } + + public CurrentRssItemViewDao getCurrentRssItemViewDao() { + return currentRssItemViewDao; + } + +} diff --git a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/database/model/Feed.java b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/database/model/Feed.java new file mode 100644 index 00000000..ac60553e --- /dev/null +++ b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/database/model/Feed.java @@ -0,0 +1,184 @@ +package de.luhmer.owncloudnewsreader.database.model; + +import java.util.List; + +import de.greenrobot.dao.DaoException; + +// THIS CODE IS GENERATED BY greenDAO, EDIT ONLY INSIDE THE "KEEP"-SECTIONS + +// KEEP INCLUDES - put your custom includes here +// KEEP INCLUDES END +/** + * Entity mapped to table FEED. + */ +public class Feed { + + private long id; + private Long folderId; + /** Not-null value. */ + private String feedTitle; + private String faviconUrl; + private String link; + private String avgColour; + + /** Used to resolve relations */ + private transient DaoSession daoSession; + + /** Used for active entity operations. */ + private transient FeedDao myDao; + + private Folder folder; + private Long folder__resolvedKey; + + private List<RssItem> rssItemList; + + // KEEP FIELDS - put your custom fields here + // KEEP FIELDS END + + public Feed() { + } + + public Feed(long id) { + this.id = id; + } + + public Feed(long id, Long folderId, String feedTitle, String faviconUrl, String link, String avgColour) { + this.id = id; + this.folderId = folderId; + this.feedTitle = feedTitle; + this.faviconUrl = faviconUrl; + this.link = link; + this.avgColour = avgColour; + } + + /** called by internal mechanisms, do not call yourself. */ + public void __setDaoSession(DaoSession daoSession) { + this.daoSession = daoSession; + myDao = daoSession != null ? daoSession.getFeedDao() : null; + } + + public long getId() { + return id; + } + + public void setId(long id) { + this.id = id; + } + + public Long getFolderId() { + return folderId; + } + + public void setFolderId(Long folderId) { + this.folderId = folderId; + } + + /** Not-null value. */ + public String getFeedTitle() { + return feedTitle; + } + + /** Not-null value; ensure this value is available before it is saved to the database. */ + public void setFeedTitle(String feedTitle) { + this.feedTitle = feedTitle; + } + + public String getFaviconUrl() { + return faviconUrl; + } + + public void setFaviconUrl(String faviconUrl) { + this.faviconUrl = faviconUrl; + } + + public String getLink() { + return link; + } + + public void setLink(String link) { + this.link = link; + } + + public String getAvgColour() { + return avgColour; + } + + public void setAvgColour(String avgColour) { + this.avgColour = avgColour; + } + + /** To-one relationship, resolved on first access. */ + public Folder getFolder() { + Long __key = this.folderId; + if (folder__resolvedKey == null || !folder__resolvedKey.equals(__key)) { + if (daoSession == null) { + throw new DaoException("Entity is detached from DAO context"); + } + FolderDao targetDao = daoSession.getFolderDao(); + Folder folderNew = targetDao.load(__key); + synchronized (this) { + folder = folderNew; + folder__resolvedKey = __key; + } + } + return folder; + } + + public void setFolder(Folder folder) { + synchronized (this) { + this.folder = folder; + folderId = folder == null ? null : folder.getId(); + folder__resolvedKey = folderId; + } + } + + /** To-many relationship, resolved on first access (and after reset). Changes to to-many relations are not persisted, make changes to the target entity. */ + public List<RssItem> getRssItemList() { + if (rssItemList == null) { + if (daoSession == null) { + throw new DaoException("Entity is detached from DAO context"); + } + RssItemDao targetDao = daoSession.getRssItemDao(); + List<RssItem> rssItemListNew = targetDao._queryFeed_RssItemList(id); + synchronized (this) { + if(rssItemList == null) { + rssItemList = rssItemListNew; + } + } + } + return rssItemList; + } + + /** Resets a to-many relationship, making the next get call to query for a fresh result. */ + public synchronized void resetRssItemList() { + rssItemList = null; + } + + /** Convenient call for {@link AbstractDao#delete(Object)}. Entity must attached to an entity context. */ + public void delete() { + if (myDao == null) { + throw new DaoException("Entity is detached from DAO context"); + } + myDao.delete(this); + } + + /** Convenient call for {@link AbstractDao#update(Object)}. Entity must attached to an entity context. */ + public void update() { + if (myDao == null) { + throw new DaoException("Entity is detached from DAO context"); + } + myDao.update(this); + } + + /** Convenient call for {@link AbstractDao#refresh(Object)}. Entity must attached to an entity context. */ + public void refresh() { + if (myDao == null) { + throw new DaoException("Entity is detached from DAO context"); + } + myDao.refresh(this); + } + + // KEEP METHODS - put your custom methods here + // KEEP METHODS END + +} diff --git a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/database/model/FeedDao.java b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/database/model/FeedDao.java new file mode 100644 index 00000000..5b011d19 --- /dev/null +++ b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/database/model/FeedDao.java @@ -0,0 +1,262 @@ +package de.luhmer.owncloudnewsreader.database.model; + +import android.database.Cursor; +import android.database.sqlite.SQLiteDatabase; +import android.database.sqlite.SQLiteStatement; + +import java.util.ArrayList; +import java.util.List; + +import de.greenrobot.dao.AbstractDao; +import de.greenrobot.dao.Property; +import de.greenrobot.dao.internal.DaoConfig; +import de.greenrobot.dao.internal.SqlUtils; +import de.greenrobot.dao.query.Query; +import de.greenrobot.dao.query.QueryBuilder; + +// THIS CODE IS GENERATED BY greenDAO, DO NOT EDIT. +/** + * DAO for table FEED. +*/ +public class FeedDao extends AbstractDao<Feed, Long> { + + public static final String TABLENAME = "FEED"; + + /** + * Properties of entity Feed.<br/> + * Can be used for QueryBuilder and for referencing column names. + */ + public static class Properties { + public final static Property Id = new Property(0, long.class, "id", true, "_id"); + public final static Property FolderId = new Property(1, Long.class, "folderId", false, "FOLDER_ID"); + public final static Property FeedTitle = new Property(2, String.class, "feedTitle", false, "FEED_TITLE"); + public final static Property FaviconUrl = new Property(3, String.class, "faviconUrl", false, "FAVICON_URL"); + public final static Property Link = new Property(4, String.class, "link", false, "LINK"); + public final static Property AvgColour = new Property(5, String.class, "avgColour", false, "AVG_COLOUR"); + }; + + private DaoSession daoSession; + + private Query<Feed> folder_FeedListQuery; + + public FeedDao(DaoConfig config) { + super(config); + } + + public FeedDao(DaoConfig config, DaoSession daoSession) { + super(config, daoSession); + this.daoSession = daoSession; + } + + /** Creates the underlying database table. */ + public static void createTable(SQLiteDatabase db, boolean ifNotExists) { + String constraint = ifNotExists? "IF NOT EXISTS ": ""; + db.execSQL("CREATE TABLE " + constraint + "'FEED' (" + // + "'_id' INTEGER PRIMARY KEY NOT NULL ," + // 0: id + "'FOLDER_ID' INTEGER," + // 1: folderId + "'FEED_TITLE' TEXT NOT NULL ," + // 2: feedTitle + "'FAVICON_URL' TEXT," + // 3: faviconUrl + "'LINK' TEXT," + // 4: link + "'AVG_COLOUR' TEXT);"); // 5: avgColour + } + + /** Drops the underlying database table. */ + public static void dropTable(SQLiteDatabase db, boolean ifExists) { + String sql = "DROP TABLE " + (ifExists ? "IF EXISTS " : "") + "'FEED'"; + db.execSQL(sql); + } + + /** @inheritdoc */ + @Override + protected void bindValues(SQLiteStatement stmt, Feed entity) { + stmt.clearBindings(); + stmt.bindLong(1, entity.getId()); + + Long folderId = entity.getFolderId(); + if (folderId != null) { + stmt.bindLong(2, folderId); + } + stmt.bindString(3, entity.getFeedTitle()); + + String faviconUrl = entity.getFaviconUrl(); + if (faviconUrl != null) { + stmt.bindString(4, faviconUrl); + } + + String link = entity.getLink(); + if (link != null) { + stmt.bindString(5, link); + } + + String avgColour = entity.getAvgColour(); + if (avgColour != null) { + stmt.bindString(6, avgColour); + } + } + + @Override + protected void attachEntity(Feed entity) { + super.attachEntity(entity); + entity.__setDaoSession(daoSession); + } + + /** @inheritdoc */ + @Override + public Long readKey(Cursor cursor, int offset) { + return cursor.getLong(offset + 0); + } + + /** @inheritdoc */ + @Override + public Feed readEntity(Cursor cursor, int offset) { + Feed entity = new Feed( // + cursor.getLong(offset + 0), // id + cursor.isNull(offset + 1) ? null : cursor.getLong(offset + 1), // folderId + cursor.getString(offset + 2), // feedTitle + cursor.isNull(offset + 3) ? null : cursor.getString(offset + 3), // faviconUrl + cursor.isNull(offset + 4) ? null : cursor.getString(offset + 4), // link + cursor.isNull(offset + 5) ? null : cursor.getString(offset + 5) // avgColour + ); + return entity; + } + + /** @inheritdoc */ + @Override + public void readEntity(Cursor cursor, Feed entity, int offset) { + entity.setId(cursor.getLong(offset + 0)); + entity.setFolderId(cursor.isNull(offset + 1) ? null : cursor.getLong(offset + 1)); + entity.setFeedTitle(cursor.getString(offset + 2)); + entity.setFaviconUrl(cursor.isNull(offset + 3) ? null : cursor.getString(offset + 3)); + entity.setLink(cursor.isNull(offset + 4) ? null : cursor.getString(offset + 4)); + entity.setAvgColour(cursor.isNull(offset + 5) ? null : cursor.getString(offset + 5)); + } + + /** @inheritdoc */ + @Override + protected Long updateKeyAfterInsert(Feed entity, long rowId) { + entity.setId(rowId); + return rowId; + } + + /** @inheritdoc */ + @Override + public Long getKey(Feed entity) { + if(entity != null) { + return entity.getId(); + } else { + return null; + } + } + + /** @inheritdoc */ + @Override + protected boolean isEntityUpdateable() { + return true; + } + + /** Internal query to resolve the "feedList" to-many relationship of Folder. */ + public List<Feed> _queryFolder_FeedList(Long folderId) { + synchronized (this) { + if (folder_FeedListQuery == null) { + QueryBuilder<Feed> queryBuilder = queryBuilder(); + queryBuilder.where(Properties.FolderId.eq(null)); + folder_FeedListQuery = queryBuilder.build(); + } + } + Query<Feed> query = folder_FeedListQuery.forCurrentThread(); + query.setParameter(0, folderId); + return query.list(); + } + + private String selectDeep; + + protected String getSelectDeep() { + if (selectDeep == null) { + StringBuilder builder = new StringBuilder("SELECT "); + SqlUtils.appendColumns(builder, "T", getAllColumns()); + builder.append(','); + SqlUtils.appendColumns(builder, "T0", daoSession.getFolderDao().getAllColumns()); + builder.append(" FROM FEED T"); + builder.append(" LEFT JOIN FOLDER T0 ON T.'FOLDER_ID'=T0.'_id'"); + builder.append(' '); + selectDeep = builder.toString(); + } + return selectDeep; + } + + protected Feed loadCurrentDeep(Cursor cursor, boolean lock) { + Feed entity = loadCurrent(cursor, 0, lock); + int offset = getAllColumns().length; + + Folder folder = loadCurrentOther(daoSession.getFolderDao(), cursor, offset); + entity.setFolder(folder); + + return entity; + } + + public Feed loadDeep(Long key) { + assertSinglePk(); + if (key == null) { + return null; + } + + StringBuilder builder = new StringBuilder(getSelectDeep()); + builder.append("WHERE "); + SqlUtils.appendColumnsEqValue(builder, "T", getPkColumns()); + String sql = builder.toString(); + + String[] keyArray = new String[] { key.toString() }; + Cursor cursor = db.rawQuery(sql, keyArray); + + try { + boolean available = cursor.moveToFirst(); + if (!available) { + return null; + } else if (!cursor.isLast()) { + throw new IllegalStateException("Expected unique result, but count was " + cursor.getCount()); + } + return loadCurrentDeep(cursor, true); + } finally { + cursor.close(); + } + } + + /** Reads all available rows from the given cursor and returns a list of new ImageTO objects. */ + public List<Feed> loadAllDeepFromCursor(Cursor cursor) { + int count = cursor.getCount(); + List<Feed> list = new ArrayList<Feed>(count); + + if (cursor.moveToFirst()) { + if (identityScope != null) { + identityScope.lock(); + identityScope.reserveRoom(count); + } + try { + do { + list.add(loadCurrentDeep(cursor, false)); + } while (cursor.moveToNext()); + } finally { + if (identityScope != null) { + identityScope.unlock(); + } + } + } + return list; + } + + protected List<Feed> loadDeepAllAndCloseCursor(Cursor cursor) { + try { + return loadAllDeepFromCursor(cursor); + } finally { + cursor.close(); + } + } + + + /** A raw-style query where you can pass any WHERE clause and arguments. */ + public List<Feed> queryDeep(String where, String... selectionArg) { + Cursor cursor = db.rawQuery(getSelectDeep() + where, selectionArg); + return loadDeepAllAndCloseCursor(cursor); + } + +} diff --git a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/database/model/Folder.java b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/database/model/Folder.java new file mode 100644 index 00000000..ea5cf36d --- /dev/null +++ b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/database/model/Folder.java @@ -0,0 +1,116 @@ +package de.luhmer.owncloudnewsreader.database.model; + +import java.util.List; + +import de.greenrobot.dao.DaoException; + +// THIS CODE IS GENERATED BY greenDAO, EDIT ONLY INSIDE THE "KEEP"-SECTIONS + +// KEEP INCLUDES - put your custom includes here +// KEEP INCLUDES END +/** + * Entity mapped to table FOLDER. + */ +public class Folder { + + private long id; + /** Not-null value. */ + private String label; + + /** Used to resolve relations */ + private transient DaoSession daoSession; + + /** Used for active entity operations. */ + private transient FolderDao myDao; + + private List<Feed> feedList; + + // KEEP FIELDS - put your custom fields here + // KEEP FIELDS END + + public Folder() { + } + + public Folder(long id) { + this.id = id; + } + + public Folder(long id, String label) { + this.id = id; + this.label = label; + } + + /** called by internal mechanisms, do not call yourself. */ + public void __setDaoSession(DaoSession daoSession) { + this.daoSession = daoSession; + myDao = daoSession != null ? daoSession.getFolderDao() : null; + } + + public long getId() { + return id; + } + + public void setId(long id) { + this.id = id; + } + + /** Not-null value. */ + public String getLabel() { + return label; + } + + /** Not-null value; ensure this value is available before it is saved to the database. */ + public void setLabel(String label) { + this.label = label; + } + + /** To-many relationship, resolved on first access (and after reset). Changes to to-many relations are not persisted, make changes to the target entity. */ + public List<Feed> getFeedList() { + if (feedList == null) { + if (daoSession == null) { + throw new DaoException("Entity is detached from DAO context"); + } + FeedDao targetDao = daoSession.getFeedDao(); + List<Feed> feedListNew = targetDao._queryFolder_FeedList(id); + synchronized (this) { + if(feedList == null) { + feedList = feedListNew; + } + } + } + return feedList; + } + + /** Resets a to-many relationship, making the next get call to query for a fresh result. */ + public synchronized void resetFeedList() { + feedList = null; + } + + /** Convenient call for {@link AbstractDao#delete(Object)}. Entity must attached to an entity context. */ + public void delete() { + if (myDao == null) { + throw new DaoException("Entity is detached from DAO context"); + } + myDao.delete(this); + } + + /** Convenient call for {@link AbstractDao#update(Object)}. Entity must attached to an entity context. */ + public void update() { + if (myDao == null) { + throw new DaoException("Entity is detached from DAO context"); + } + myDao.update(this); + } + + /** Convenient call for {@link AbstractDao#refresh(Object)}. Entity must attached to an entity context. */ + public void refresh() { + if (myDao == null) { + throw new DaoException("Entity is detached from DAO context"); + } + myDao.refresh(this); + } + + // KEEP METHODS - put your custom methods here + // KEEP METHODS END + +} diff --git a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/database/model/FolderDao.java b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/database/model/FolderDao.java new file mode 100644 index 00000000..f94c8ce0 --- /dev/null +++ b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/database/model/FolderDao.java @@ -0,0 +1,114 @@ +package de.luhmer.owncloudnewsreader.database.model; + +import android.database.Cursor; +import android.database.sqlite.SQLiteDatabase; +import android.database.sqlite.SQLiteStatement; + +import de.greenrobot.dao.AbstractDao; +import de.greenrobot.dao.Property; +import de.greenrobot.dao.internal.DaoConfig; + +// THIS CODE IS GENERATED BY greenDAO, DO NOT EDIT. +/** + * DAO for table FOLDER. +*/ +public class FolderDao extends AbstractDao<Folder, Long> { + + public static final String TABLENAME = "FOLDER"; + + /** + * Properties of entity Folder.<br/> + * Can be used for QueryBuilder and for referencing column names. + */ + public static class Properties { + public final static Property Id = new Property(0, long.class, "id", true, "_id"); + public final static Property Label = new Property(1, String.class, "label", false, "LABEL"); + }; + + private DaoSession daoSession; + + + public FolderDao(DaoConfig config) { + super(config); + } + + public FolderDao(DaoConfig config, DaoSession daoSession) { + super(config, daoSession); + this.daoSession = daoSession; + } + + /** Creates the underlying database table. */ + public static void createTable(SQLiteDatabase db, boolean ifNotExists) { + String constraint = ifNotExists? "IF NOT EXISTS ": ""; + db.execSQL("CREATE TABLE " + constraint + "'FOLDER' (" + // + "'_id' INTEGER PRIMARY KEY NOT NULL ," + // 0: id + "'LABEL' TEXT NOT NULL );"); // 1: label + } + + /** Drops the underlying database table. */ + public static void dropTable(SQLiteDatabase db, boolean ifExists) { + String sql = "DROP TABLE " + (ifExists ? "IF EXISTS " : "") + "'FOLDER'"; + db.execSQL(sql); + } + + /** @inheritdoc */ + @Override + protected void bindValues(SQLiteStatement stmt, Folder entity) { + stmt.clearBindings(); + stmt.bindLong(1, entity.getId()); + stmt.bindString(2, entity.getLabel()); + } + + @Override + protected void attachEntity(Folder entity) { + super.attachEntity(entity); + entity.__setDaoSession(daoSession); + } + + /** @inheritdoc */ + @Override + public Long readKey(Cursor cursor, int offset) { + return cursor.getLong(offset + 0); + } + + /** @inheritdoc */ + @Override + public Folder readEntity(Cursor cursor, int offset) { + Folder entity = new Folder( // + cursor.getLong(offset + 0), // id + cursor.getString(offset + 1) // label + ); + return entity; + } + + /** @inheritdoc */ + @Override + public void readEntity(Cursor cursor, Folder entity, int offset) { + entity.setId(cursor.getLong(offset + 0)); + entity.setLabel(cursor.getString(offset + 1)); + } + + /** @inheritdoc */ + @Override + protected Long updateKeyAfterInsert(Folder entity, long rowId) { + entity.setId(rowId); + return rowId; + } + + /** @inheritdoc */ + @Override + public Long getKey(Folder entity) { + if(entity != null) { + return entity.getId(); + } else { + return null; + } + } + + /** @inheritdoc */ + @Override + protected boolean isEntityUpdateable() { + return true; + } + +} diff --git a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/database/model/RssItem.java b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/database/model/RssItem.java new file mode 100644 index 00000000..9bfb859b --- /dev/null +++ b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/database/model/RssItem.java @@ -0,0 +1,269 @@ +package de.luhmer.owncloudnewsreader.database.model; + +import de.greenrobot.dao.DaoException; +import de.luhmer.owncloudnewsreader.adapter.HasId; + +// THIS CODE IS GENERATED BY greenDAO, EDIT ONLY INSIDE THE "KEEP"-SECTIONS + +// KEEP INCLUDES - put your custom includes here +// KEEP INCLUDES END +/** + * Entity mapped to table RSS_ITEM. + */ +public class RssItem implements HasId<Long> { + + private long id; + private long feedId; + private String link; + private String title; + private String body; + private Boolean read; + private Boolean starred; + /** Not-null value. */ + private String author; + /** Not-null value. */ + private String guid; + /** Not-null value. */ + private String guidHash; + private Boolean read_temp; + private Boolean starred_temp; + private java.util.Date lastModified; + private java.util.Date pubDate; + private String enclosureLink; + private String enclosureMime; + + /** Used to resolve relations */ + private transient DaoSession daoSession; + + /** Used for active entity operations. */ + private transient RssItemDao myDao; + + private Feed feed; + private Long feed__resolvedKey; + + + // KEEP FIELDS - put your custom fields here + // KEEP FIELDS END + + public RssItem() { + } + + public RssItem(long id) { + this.id = id; + } + + public RssItem(long id, long feedId, String link, String title, String body, Boolean read, Boolean starred, String author, String guid, String guidHash, Boolean read_temp, Boolean starred_temp, java.util.Date lastModified, java.util.Date pubDate, String enclosureLink, String enclosureMime) { + this.id = id; + this.feedId = feedId; + this.link = link; + this.title = title; + this.body = body; + this.read = read; + this.starred = starred; + this.author = author; + this.guid = guid; + this.guidHash = guidHash; + this.read_temp = read_temp; + this.starred_temp = starred_temp; + this.lastModified = lastModified; + this.pubDate = pubDate; + this.enclosureLink = enclosureLink; + this.enclosureMime = enclosureMime; + } + + /** called by internal mechanisms, do not call yourself. */ + public void __setDaoSession(DaoSession daoSession) { + this.daoSession = daoSession; + myDao = daoSession != null ? daoSession.getRssItemDao() : null; + } + + public Long getId() { + return id; + } + + public void setId(long id) { + this.id = id; + } + + public long getFeedId() { + return feedId; + } + + public void setFeedId(long feedId) { + this.feedId = feedId; + } + + public String getLink() { + return link; + } + + public void setLink(String link) { + this.link = link; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public String getBody() { + return body; + } + + public void setBody(String body) { + this.body = body; + } + + public Boolean getRead() { + return read; + } + + public void setRead(Boolean read) { + this.read = read; + } + + public Boolean getStarred() { + return starred; + } + + public void setStarred(Boolean starred) { + this.starred = starred; + } + + /** Not-null value. */ + public String getAuthor() { + return author; + } + + /** Not-null value; ensure this value is available before it is saved to the database. */ + public void setAuthor(String author) { + this.author = author; + } + + /** Not-null value. */ + public String getGuid() { + return guid; + } + + /** Not-null value; ensure this value is available before it is saved to the database. */ + public void setGuid(String guid) { + this.guid = guid; + } + + /** Not-null value. */ + public String getGuidHash() { + return guidHash; + } + + /** Not-null value; ensure this value is available before it is saved to the database. */ + public void setGuidHash(String guidHash) { + this.guidHash = guidHash; + } + + public Boolean getRead_temp() { + return read_temp; + } + + public void setRead_temp(Boolean read_temp) { + this.read_temp = read_temp; + } + + public Boolean getStarred_temp() { + return starred_temp; + } + + public void setStarred_temp(Boolean starred_temp) { + this.starred_temp = starred_temp; + } + + public java.util.Date getLastModified() { + return lastModified; + } + + public void setLastModified(java.util.Date lastModified) { + this.lastModified = lastModified; + } + + public java.util.Date getPubDate() { + return pubDate; + } + + public void setPubDate(java.util.Date pubDate) { + this.pubDate = pubDate; + } + + public String getEnclosureLink() { + return enclosureLink; + } + + public void setEnclosureLink(String enclosureLink) { + this.enclosureLink = enclosureLink; + } + + public String getEnclosureMime() { + return enclosureMime; + } + + public void setEnclosureMime(String enclosureMime) { + this.enclosureMime = enclosureMime; + } + + /** To-one relationship, resolved on first access. */ + public Feed getFeed() { + long __key = this.feedId; + if (feed__resolvedKey == null || !feed__resolvedKey.equals(__key)) { + if (daoSession == null) { + throw new DaoException("Entity is detached from DAO context"); + } + FeedDao targetDao = daoSession.getFeedDao(); + Feed feedNew = targetDao.load(__key); + synchronized (this) { + feed = feedNew; + feed__resolvedKey = __key; + } + } + return feed; + } + + public void setFeed(Feed feed) { + if (feed == null) { + throw new DaoException("To-one property 'feedId' has not-null constraint; cannot set to-one to null"); + } + synchronized (this) { + this.feed = feed; + feedId = feed.getId(); + feed__resolvedKey = feedId; + } + } + + /** Convenient call for {@link AbstractDao#delete(Object)}. Entity must attached to an entity context. */ + public void delete() { + if (myDao == null) { + throw new DaoException("Entity is detached from DAO context"); + } + myDao.delete(this); + } + + /** Convenient call for {@link AbstractDao#update(Object)}. Entity must attached to an entity context. */ + public void update() { + if (myDao == null) { + throw new DaoException("Entity is detached from DAO context"); + } + myDao.update(this); + } + + /** Convenient call for {@link AbstractDao#refresh(Object)}. Entity must attached to an entity context. */ + public void refresh() { + if (myDao == null) { + throw new DaoException("Entity is detached from DAO context"); + } + myDao.refresh(this); + } + + // KEEP METHODS - put your custom methods here + // KEEP METHODS END + +} diff --git a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/database/model/RssItemDao.java b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/database/model/RssItemDao.java new file mode 100644 index 00000000..4739d5f9 --- /dev/null +++ b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/database/model/RssItemDao.java @@ -0,0 +1,342 @@ +package de.luhmer.owncloudnewsreader.database.model; + +import android.database.Cursor; +import android.database.sqlite.SQLiteDatabase; +import android.database.sqlite.SQLiteStatement; + +import java.util.ArrayList; +import java.util.List; + +import de.greenrobot.dao.AbstractDao; +import de.greenrobot.dao.Property; +import de.greenrobot.dao.internal.DaoConfig; +import de.greenrobot.dao.internal.SqlUtils; +import de.greenrobot.dao.query.Query; +import de.greenrobot.dao.query.QueryBuilder; + +// THIS CODE IS GENERATED BY greenDAO, DO NOT EDIT. +/** + * DAO for table RSS_ITEM. +*/ +public class RssItemDao extends AbstractDao<RssItem, Long> { + + public static final String TABLENAME = "RSS_ITEM"; + + /** + * Properties of entity RssItem.<br/> + * Can be used for QueryBuilder and for referencing column names. + */ + public static class Properties { + public final static Property Id = new Property(0, long.class, "id", true, "_id"); + public final static Property FeedId = new Property(1, long.class, "feedId", false, "FEED_ID"); + public final static Property Link = new Property(2, String.class, "link", false, "LINK"); + public final static Property Title = new Property(3, String.class, "title", false, "TITLE"); + public final static Property Body = new Property(4, String.class, "body", false, "BODY"); + public final static Property Read = new Property(5, Boolean.class, "read", false, "READ"); + public final static Property Starred = new Property(6, Boolean.class, "starred", false, "STARRED"); + public final static Property Author = new Property(7, String.class, "author", false, "AUTHOR"); + public final static Property Guid = new Property(8, String.class, "guid", false, "GUID"); + public final static Property GuidHash = new Property(9, String.class, "guidHash", false, "GUID_HASH"); + public final static Property Read_temp = new Property(10, Boolean.class, "read_temp", false, "READ_TEMP"); + public final static Property Starred_temp = new Property(11, Boolean.class, "starred_temp", false, "STARRED_TEMP"); + public final static Property LastModified = new Property(12, java.util.Date.class, "lastModified", false, "LAST_MODIFIED"); + public final static Property PubDate = new Property(13, java.util.Date.class, "pubDate", false, "PUB_DATE"); + public final static Property EnclosureLink = new Property(14, String.class, "enclosureLink", false, "ENCLOSURE_LINK"); + public final static Property EnclosureMime = new Property(15, String.class, "enclosureMime", false, "ENCLOSURE_MIME"); + }; + + private DaoSession daoSession; + + private Query<RssItem> feed_RssItemListQuery; + + public RssItemDao(DaoConfig config) { + super(config); + } + + public RssItemDao(DaoConfig config, DaoSession daoSession) { + super(config, daoSession); + this.daoSession = daoSession; + } + + /** Creates the underlying database table. */ + public static void createTable(SQLiteDatabase db, boolean ifNotExists) { + String constraint = ifNotExists? "IF NOT EXISTS ": ""; + db.execSQL("CREATE TABLE " + constraint + "'RSS_ITEM' (" + // + "'_id' INTEGER PRIMARY KEY NOT NULL ," + // 0: id + "'FEED_ID' INTEGER NOT NULL ," + // 1: feedId + "'LINK' TEXT," + // 2: link + "'TITLE' TEXT," + // 3: title + "'BODY' TEXT," + // 4: body + "'READ' INTEGER," + // 5: read + "'STARRED' INTEGER," + // 6: starred + "'AUTHOR' TEXT NOT NULL ," + // 7: author + "'GUID' TEXT NOT NULL ," + // 8: guid + "'GUID_HASH' TEXT NOT NULL ," + // 9: guidHash + "'READ_TEMP' INTEGER," + // 10: read_temp + "'STARRED_TEMP' INTEGER," + // 11: starred_temp + "'LAST_MODIFIED' INTEGER," + // 12: lastModified + "'PUB_DATE' INTEGER," + // 13: pubDate + "'ENCLOSURE_LINK' TEXT," + // 14: enclosureLink + "'ENCLOSURE_MIME' TEXT);"); // 15: enclosureMime + } + + /** Drops the underlying database table. */ + public static void dropTable(SQLiteDatabase db, boolean ifExists) { + String sql = "DROP TABLE " + (ifExists ? "IF EXISTS " : "") + "'RSS_ITEM'"; + db.execSQL(sql); + } + + /** @inheritdoc */ + @Override + protected void bindValues(SQLiteStatement stmt, RssItem entity) { + stmt.clearBindings(); + stmt.bindLong(1, entity.getId()); + stmt.bindLong(2, entity.getFeedId()); + + String link = entity.getLink(); + if (link != null) { + stmt.bindString(3, link); + } + + String title = entity.getTitle(); + if (title != null) { + stmt.bindString(4, title); + } + + String body = entity.getBody(); + if (body != null) { + stmt.bindString(5, body); + } + + Boolean read = entity.getRead(); + if (read != null) { + stmt.bindLong(6, read ? 1l: 0l); + } + + Boolean starred = entity.getStarred(); + if (starred != null) { + stmt.bindLong(7, starred ? 1l: 0l); + } + stmt.bindString(8, entity.getAuthor()); + stmt.bindString(9, entity.getGuid()); + stmt.bindString(10, entity.getGuidHash()); + + Boolean read_temp = entity.getRead_temp(); + if (read_temp != null) { + stmt.bindLong(11, read_temp ? 1l: 0l); + } + + Boolean starred_temp = entity.getStarred_temp(); + if (starred_temp != null) { + stmt.bindLong(12, starred_temp ? 1l: 0l); + } + + java.util.Date lastModified = entity.getLastModified(); + if (lastModified != null) { + stmt.bindLong(13, lastModified.getTime()); + } + + java.util.Date pubDate = entity.getPubDate(); + if (pubDate != null) { + stmt.bindLong(14, pubDate.getTime()); + } + + String enclosureLink = entity.getEnclosureLink(); + if (enclosureLink != null) { + stmt.bindString(15, enclosureLink); + } + + String enclosureMime = entity.getEnclosureMime(); + if (enclosureMime != null) { + stmt.bindString(16, enclosureMime); + } + } + + @Override + protected void attachEntity(RssItem entity) { + super.attachEntity(entity); + entity.__setDaoSession(daoSession); + } + + /** @inheritdoc */ + @Override + public Long readKey(Cursor cursor, int offset) { + return cursor.getLong(offset + 0); + } + + /** @inheritdoc */ + @Override + public RssItem readEntity(Cursor cursor, int offset) { + RssItem entity = new RssItem( // + cursor.getLong(offset + 0), // id + cursor.getLong(offset + 1), // feedId + cursor.isNull(offset + 2) ? null : cursor.getString(offset + 2), // link + cursor.isNull(offset + 3) ? null : cursor.getString(offset + 3), // title + cursor.isNull(offset + 4) ? null : cursor.getString(offset + 4), // body + cursor.isNull(offset + 5) ? null : cursor.getShort(offset + 5) != 0, // read + cursor.isNull(offset + 6) ? null : cursor.getShort(offset + 6) != 0, // starred + cursor.getString(offset + 7), // author + cursor.getString(offset + 8), // guid + cursor.getString(offset + 9), // guidHash + cursor.isNull(offset + 10) ? null : cursor.getShort(offset + 10) != 0, // read_temp + cursor.isNull(offset + 11) ? null : cursor.getShort(offset + 11) != 0, // starred_temp + cursor.isNull(offset + 12) ? null : new java.util.Date(cursor.getLong(offset + 12)), // lastModified + cursor.isNull(offset + 13) ? null : new java.util.Date(cursor.getLong(offset + 13)), // pubDate + cursor.isNull(offset + 14) ? null : cursor.getString(offset + 14), // enclosureLink + cursor.isNull(offset + 15) ? null : cursor.getString(offset + 15) // enclosureMime + ); + return entity; + } + + /** @inheritdoc */ + @Override + public void readEntity(Cursor cursor, RssItem entity, int offset) { + entity.setId(cursor.getLong(offset + 0)); + entity.setFeedId(cursor.getLong(offset + 1)); + entity.setLink(cursor.isNull(offset + 2) ? null : cursor.getString(offset + 2)); + entity.setTitle(cursor.isNull(offset + 3) ? null : cursor.getString(offset + 3)); + entity.setBody(cursor.isNull(offset + 4) ? null : cursor.getString(offset + 4)); + entity.setRead(cursor.isNull(offset + 5) ? null : cursor.getShort(offset + 5) != 0); + entity.setStarred(cursor.isNull(offset + 6) ? null : cursor.getShort(offset + 6) != 0); + entity.setAuthor(cursor.getString(offset + 7)); + entity.setGuid(cursor.getString(offset + 8)); + entity.setGuidHash(cursor.getString(offset + 9)); + entity.setRead_temp(cursor.isNull(offset + 10) ? null : cursor.getShort(offset + 10) != 0); + entity.setStarred_temp(cursor.isNull(offset + 11) ? null : cursor.getShort(offset + 11) != 0); + entity.setLastModified(cursor.isNull(offset + 12) ? null : new java.util.Date(cursor.getLong(offset + 12))); + entity.setPubDate(cursor.isNull(offset + 13) ? null : new java.util.Date(cursor.getLong(offset + 13))); + entity.setEnclosureLink(cursor.isNull(offset + 14) ? null : cursor.getString(offset + 14)); + entity.setEnclosureMime(cursor.isNull(offset + 15) ? null : cursor.getString(offset + 15)); + } + + /** @inheritdoc */ + @Override + protected Long updateKeyAfterInsert(RssItem entity, long rowId) { + entity.setId(rowId); + return rowId; + } + + /** @inheritdoc */ + @Override + public Long getKey(RssItem entity) { + if(entity != null) { + return entity.getId(); + } else { + return null; + } + } + + /** @inheritdoc */ + @Override + protected boolean isEntityUpdateable() { + return true; + } + + /** Internal query to resolve the "rssItemList" to-many relationship of Feed. */ + public List<RssItem> _queryFeed_RssItemList(long feedId) { + synchronized (this) { + if (feed_RssItemListQuery == null) { + QueryBuilder<RssItem> queryBuilder = queryBuilder(); + queryBuilder.where(Properties.FeedId.eq(null)); + feed_RssItemListQuery = queryBuilder.build(); + } + } + Query<RssItem> query = feed_RssItemListQuery.forCurrentThread(); + query.setParameter(0, feedId); + return query.list(); + } + + private String selectDeep; + + protected String getSelectDeep() { + if (selectDeep == null) { + StringBuilder builder = new StringBuilder("SELECT "); + SqlUtils.appendColumns(builder, "T", getAllColumns()); + builder.append(','); + SqlUtils.appendColumns(builder, "T0", daoSession.getFeedDao().getAllColumns()); + builder.append(" FROM RSS_ITEM T"); + builder.append(" LEFT JOIN FEED T0 ON T.'FEED_ID'=T0.'_id'"); + builder.append(' '); + selectDeep = builder.toString(); + } + return selectDeep; + } + + protected RssItem loadCurrentDeep(Cursor cursor, boolean lock) { + RssItem entity = loadCurrent(cursor, 0, lock); + int offset = getAllColumns().length; + + Feed feed = loadCurrentOther(daoSession.getFeedDao(), cursor, offset); + if(feed != null) { + entity.setFeed(feed); + } + + return entity; + } + + public RssItem loadDeep(Long key) { + assertSinglePk(); + if (key == null) { + return null; + } + + StringBuilder builder = new StringBuilder(getSelectDeep()); + builder.append("WHERE "); + SqlUtils.appendColumnsEqValue(builder, "T", getPkColumns()); + String sql = builder.toString(); + + String[] keyArray = new String[] { key.toString() }; + Cursor cursor = db.rawQuery(sql, keyArray); + + try { + boolean available = cursor.moveToFirst(); + if (!available) { + return null; + } else if (!cursor.isLast()) { + throw new IllegalStateException("Expected unique result, but count was " + cursor.getCount()); + } + return loadCurrentDeep(cursor, true); + } finally { + cursor.close(); + } + } + + /** Reads all available rows from the given cursor and returns a list of new ImageTO objects. */ + public List<RssItem> loadAllDeepFromCursor(Cursor cursor) { + int count = cursor.getCount(); + List<RssItem> list = new ArrayList<RssItem>(count); + + if (cursor.moveToFirst()) { + if (identityScope != null) { + identityScope.lock(); + identityScope.reserveRoom(count); + } + try { + do { + list.add(loadCurrentDeep(cursor, false)); + } while (cursor.moveToNext()); + } finally { + if (identityScope != null) { + identityScope.unlock(); + } + } + } + return list; + } + + protected List<RssItem> loadDeepAllAndCloseCursor(Cursor cursor) { + try { + return loadAllDeepFromCursor(cursor); + } finally { + cursor.close(); + } + } + + + /** A raw-style query where you can pass any WHERE clause and arguments. */ + public List<RssItem> queryDeep(String where, String... selectionArg) { + Cursor cursor = db.rawQuery(getSelectDeep() + where, selectionArg); + return loadDeepAllAndCloseCursor(cursor); + } + +} diff --git a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/events/podcast/FeedPanelSlideEvent.java b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/events/podcast/FeedPanelSlideEvent.java new file mode 100644 index 00000000..8aa66428 --- /dev/null +++ b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/events/podcast/FeedPanelSlideEvent.java @@ -0,0 +1,17 @@ +package de.luhmer.owncloudnewsreader.events.podcast; + +/** + * Created by David on 20.07.2014. + */ +public class FeedPanelSlideEvent { + + public FeedPanelSlideEvent(boolean panelOpen) { + this.panelOpen = panelOpen; + } + + public boolean isPanelOpen() { + return panelOpen; + } + + boolean panelOpen; +} diff --git a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/helper/BitmapDrawableLruCache.java b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/helper/BitmapDrawableLruCache.java index ca5b50c4..e8de025e 100644 --- a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/helper/BitmapDrawableLruCache.java +++ b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/helper/BitmapDrawableLruCache.java @@ -28,7 +28,7 @@ import android.support.v4.util.LruCache; -public class BitmapDrawableLruCache extends LruCache<String, BitmapDrawable> { +public class BitmapDrawableLruCache extends LruCache<Long, BitmapDrawable> { public static int getDefaultLruCacheSize() { final int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024); final int cacheSize = maxMemory / 8; @@ -45,7 +45,7 @@ public class BitmapDrawableLruCache extends LruCache<String, BitmapDrawable> { @TargetApi(Build.VERSION_CODES.HONEYCOMB_MR1) @Override - protected int sizeOf(String key, BitmapDrawable bitmap) { + protected int sizeOf(Long key, BitmapDrawable bitmap) { if(Build.VERSION.SDK_INT > Build.VERSION_CODES.HONEYCOMB_MR1) return bitmap.getBitmap().getByteCount() / 1024; else diff --git a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/helper/FavIconHandler.java b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/helper/FavIconHandler.java index 0dbadfba..0a3642f2 100644 --- a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/helper/FavIconHandler.java +++ b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/helper/FavIconHandler.java @@ -37,12 +37,13 @@ import java.lang.ref.WeakReference; import de.luhmer.owncloudnewsreader.R; import de.luhmer.owncloudnewsreader.async_tasks.GetImageAsyncTask; -import de.luhmer.owncloudnewsreader.database.DatabaseConnection; +import de.luhmer.owncloudnewsreader.database.DatabaseConnectionOrm; +import de.luhmer.owncloudnewsreader.database.model.Feed; public class FavIconHandler { private static final String TAG = "FavIconHandler"; - public static Drawable GetFavIconFromCache(String URL_TO_PAGE, Context context, String feedID) + public static Drawable GetFavIconFromCache(String URL_TO_PAGE, Context context, Long feedID) { try { @@ -50,16 +51,14 @@ public class FavIconHandler { if(favIconFile.isFile() && favIconFile.length() > 0) { if(feedID != null) { - DatabaseConnection dbConn = new DatabaseConnection(context); - try { - if(dbConn.getAvgColourOfFeedByDbId(feedID) == null) { - Bitmap bitmap = BitmapFactory.decodeFile(favIconFile.getAbsolutePath()); - String avg = ColourCalculator.ColourHexFromBitmap(bitmap); - dbConn.setAvgColourOfFeedByDbId(feedID, avg); - } - } finally { - dbConn.closeDatabase(); - } + DatabaseConnectionOrm dbConn = new DatabaseConnectionOrm(context); + Feed feed = dbConn.getFeedById(feedID); + Bitmap bitmap = BitmapFactory.decodeFile(favIconFile.getAbsolutePath()); + String avg = ColourCalculator.ColourHexFromBitmap(bitmap); + + feed.setAvgColour(avg); + dbConn.updateFeed(feed); + //dbConn.setAvgColourOfFeedByDbId(feedID, avg); } return Drawable.createFromPath(favIconFile.getPath()); @@ -68,7 +67,7 @@ public class FavIconHandler { catch(Exception ex) { //Log.d(TAG, ex.getMessage()); - //ex.printStackTrace(); + ex.printStackTrace(); } return null; } @@ -83,16 +82,16 @@ public class FavIconHandler { } static SparseArray<FavIconCache> imageViewReferences = new SparseArray<FavIconCache>(); - String feedID; + Long feedID; static SparseArray<FavIconCache> favIconToFeedId = new SparseArray<FavIconCache>(); - public static void PreCacheFavIcon(String WEB_URL_TO_FILE, Context context, String feedID) { + public static void PreCacheFavIcon(String WEB_URL_TO_FILE, Context context, Long feedID) { FavIconCache favIconCache = new FavIconCache(); favIconCache.context = context; favIconCache.WEB_URL_TO_FILE = WEB_URL_TO_FILE; - int key = Integer.parseInt(feedID); + int key = feedID.intValue(); favIconToFeedId.put(key, favIconCache); GetImageAsyncTask giAsync = new GetImageAsyncTask(WEB_URL_TO_FILE, favIconDownloadFinished, key, FileUtils.getPathFavIcons(context), context, null); giAsync.scaleImage = true; @@ -112,14 +111,14 @@ public class FavIconHandler { @Override public void DownloadFinished(int AsynkTaskId, String fileCachePath, BitmapDrawableLruCache lruCache) { FavIconCache favIconCache = favIconToFeedId.get(AsynkTaskId); - FavIconHandler.GetFavIconFromCache(favIconCache.WEB_URL_TO_FILE, favIconCache.context, String.valueOf(AsynkTaskId)); + FavIconHandler.GetFavIconFromCache(favIconCache.WEB_URL_TO_FILE, favIconCache.context, (long) AsynkTaskId); imageViewReferences.remove(AsynkTaskId); } }; @TargetApi(Build.VERSION_CODES.HONEYCOMB) - public void GetImageAsync(ImageView imageView, String WEB_URL_TO_FILE, Context context, String feedID, BitmapDrawableLruCache lruCache) + public void GetImageAsync(ImageView imageView, String WEB_URL_TO_FILE, Context context, Long feedID, BitmapDrawableLruCache lruCache) { this.feedID = feedID; @@ -151,10 +150,8 @@ public class FavIconHandler { giAsync.dstHeight = 2*32; giAsync.dstWidth = 2*32; giAsync.feedID = feedID; - //giAsync.execute((Void)null); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) - // Execute in parallel giAsync.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, ((Void)null)); else giAsync.execute((Void)null); diff --git a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/helper/ShowcaseDimHelper.java b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/helper/ShowcaseDimHelper.java new file mode 100644 index 00000000..835b6622 --- /dev/null +++ b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/helper/ShowcaseDimHelper.java @@ -0,0 +1,32 @@ +package de.luhmer.owncloudnewsreader.helper; + +import android.annotation.TargetApi; +import android.os.Build; +import android.view.View; + +/** + * Created by David on 06.04.2014. + */ +public class ShowcaseDimHelper { + + private static final float ALPHA_DIM_VALUE = 0.1f; + + @TargetApi(Build.VERSION_CODES.HONEYCOMB) + public static void dimView(View view) { + if (isHoneycombOrAbove()) { + view.setAlpha(ALPHA_DIM_VALUE); + } + } + + @TargetApi(Build.VERSION_CODES.HONEYCOMB) + public static void undoDimView(View view) { + if (isHoneycombOrAbove()) { + view.setAlpha(1f); + } + } + + public static boolean isHoneycombOrAbove() { + return Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB; + } + +} diff --git a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/helper/ThemeChooser.java b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/helper/ThemeChooser.java index 4831444d..88cd1f87 100644 --- a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/helper/ThemeChooser.java +++ b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/helper/ThemeChooser.java @@ -42,13 +42,13 @@ public class ThemeChooser { // act.setTheme(android.R.style.Theme_Holo); //else //act.setTheme(R.style.Sherlock___Theme); - act.setTheme(R.style.Theme_Sherlock); + act.setTheme(R.style.Theme_AppCompat); } else { //if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) // act.setTheme(android.R.style.Theme_Holo_Light_DarkActionBar); //else //act.setTheme(R.style.Sherlock___Theme_DarkActionBar); - act.setTheme(R.style.Theme_Sherlock_Light_DarkActionBar); + act.setTheme(R.style.Theme_AppCompat_Light_DarkActionBar); } } diff --git a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/interfaces/ExpListTextClicked.java b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/interfaces/ExpListTextClicked.java index 7954d714..efe8a7bb 100644 --- a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/interfaces/ExpListTextClicked.java +++ b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/interfaces/ExpListTextClicked.java @@ -24,5 +24,5 @@ package de.luhmer.owncloudnewsreader.interfaces; import android.content.Context; public interface ExpListTextClicked { - void onTextClicked(String idSubscription, Context context, boolean isFolder, String optional_folder_id); + void onTextClicked(long idFeed, Context context, boolean isFolder, Long optional_folder_id); } diff --git a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/model/AbstractItem.java b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/model/AbstractItem.java index 130e59a5..259cba8b 100644 --- a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/model/AbstractItem.java +++ b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/model/AbstractItem.java @@ -24,9 +24,9 @@ package de.luhmer.owncloudnewsreader.model; public abstract class AbstractItem { public long id_database; public String header; - public String idFolder; + public Long idFolder; - AbstractItem(long id_database, String header, String idFolder) + AbstractItem(long id_database, String header, Long idFolder) { this.id_database = id_database; this.header = header; diff --git a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/model/ConcreteFeedItem.java b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/model/ConcreteFeedItem.java index 20b0ae49..24f73a89 100644 --- a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/model/ConcreteFeedItem.java +++ b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/model/ConcreteFeedItem.java @@ -23,14 +23,14 @@ package de.luhmer.owncloudnewsreader.model; public class ConcreteFeedItem extends AbstractItem { - public String subscription_id; + public long feedId; public String favIcon; - public ConcreteFeedItem(String header, String folder_id, String subscription_id, String favIcon, long id_database/*, String parent_title*/) { + public ConcreteFeedItem(String header, Long folder_id, long feedId, String favIcon, long id_database/*, String parent_title*/) { super(id_database, header, folder_id); - this.subscription_id = subscription_id; + this.feedId = feedId; this.favIcon = favIcon; this.id_database = id_database; } diff --git a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/model/FolderSubscribtionItem.java b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/model/FolderSubscribtionItem.java index b1150311..c628a5dd 100644 --- a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/model/FolderSubscribtionItem.java +++ b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/model/FolderSubscribtionItem.java @@ -25,8 +25,8 @@ public class FolderSubscribtionItem extends AbstractItem { - public FolderSubscribtionItem(String headerFolder, String idFolder, long idFolder_database, String idSubscription) { - super(idFolder_database, headerFolder, String.valueOf(idFolder_database)); + public FolderSubscribtionItem(String headerFolder, Long idFolder, long idFolder_database) { + super(idFolder_database, headerFolder, idFolder_database); this.idFolder = idFolder; } diff --git a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/model/PodcastFeedItem.java b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/model/PodcastFeedItem.java index ba9ba19e..0ed97891 100644 --- a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/model/PodcastFeedItem.java +++ b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/model/PodcastFeedItem.java @@ -1,12 +1,18 @@ package de.luhmer.owncloudnewsreader.model; +import de.luhmer.owncloudnewsreader.database.model.Feed; + /** * Created by David on 21.06.2014. */ public class PodcastFeedItem { - public String itemId; - public String title; - public int count; + public PodcastFeedItem(Feed feed, int podcastCount) { + this.mFeed = feed; + this.mPodcastCount = podcastCount; + } + + public Feed mFeed; + public int mPodcastCount; } diff --git a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/model/PodcastItem.java b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/model/PodcastItem.java index 544b91c2..411b4cbf 100644 --- a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/model/PodcastItem.java +++ b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/model/PodcastItem.java @@ -11,7 +11,7 @@ public class PodcastItem implements Serializable { } - public PodcastItem(String itemId, String title, String link, String mimeType, boolean offlineCached) { + public PodcastItem(long itemId, String title, String link, String mimeType, boolean offlineCached) { this.itemId = itemId; this.title = title; this.link = link; @@ -19,7 +19,7 @@ public class PodcastItem implements Serializable { this.offlineCached = offlineCached; } - public String itemId; + public long itemId; public String title; public String link; public String mimeType; diff --git a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/reader/HttpJsonRequest.java b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/reader/HttpJsonRequest.java index c2b39ae5..726ba58e 100644 --- a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/reader/HttpJsonRequest.java +++ b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/reader/HttpJsonRequest.java @@ -181,10 +181,10 @@ public class HttpJsonRequest { } */ - public static int performCreateFeedRequest(String urlString, String username, String password, Context context, String feedUrl, String folderId) throws Exception { + public static int performCreateFeedRequest(String urlString, String username, String password, Context context, String feedUrl, long folderId) throws Exception { List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(); nameValuePairs.add(new BasicNameValuePair("url", feedUrl)); - nameValuePairs.add(new BasicNameValuePair("folderId", folderId)); + nameValuePairs.add(new BasicNameValuePair("folderId", String.valueOf(folderId))); if(nameValuePairs != null) urlString += "&" + URLEncodedUtils.format(nameValuePairs, "utf-8"); diff --git a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/reader/IReader.java b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/reader/IReader.java index bbed1a3f..9aac0189 100644 --- a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/reader/IReader.java +++ b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/reader/IReader.java @@ -33,7 +33,7 @@ public interface IReader { public void attachToRunningTask(int task_id, Activity activity, OnAsyncTaskCompletedListener listener); public void Start_AsyncTask_GetItems(final int task_id, final Context context, final OnAsyncTaskCompletedListener listener, FeedItemTags.TAGS tag); - public void Start_AsyncTask_GetOldItems(final int task_id, final Context context, final OnAsyncTaskCompletedListener listener, String feed_id, String folder_id); + public void Start_AsyncTask_GetOldItems(final int task_id, final Context context, final OnAsyncTaskCompletedListener listener, Long feed_id, Long folder_id); public void Start_AsyncTask_GetFolder(final int task_id, final Context context, final OnAsyncTaskCompletedListener listener); public void Start_AsyncTask_GetFeeds(final int task_id, final Context context, final OnAsyncTaskCompletedListener listener); diff --git a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/reader/InsertIntoDatabase.java b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/reader/InsertIntoDatabase.java index fe5dff0d..74c714b0 100644 --- a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/reader/InsertIntoDatabase.java +++ b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/reader/InsertIntoDatabase.java @@ -27,9 +27,10 @@ import android.util.Log; import java.util.ArrayList; import java.util.List; -import de.luhmer.owncloudnewsreader.database.DatabaseConnection; -import de.luhmer.owncloudnewsreader.model.ConcreteFeedItem; -import de.luhmer.owncloudnewsreader.model.RssFile; +import de.luhmer.owncloudnewsreader.database.DatabaseConnectionOrm; +import de.luhmer.owncloudnewsreader.database.model.Feed; +import de.luhmer.owncloudnewsreader.database.model.Folder; +import de.luhmer.owncloudnewsreader.database.model.RssItem; /** * Created by David on 24.05.13. @@ -37,49 +38,52 @@ import de.luhmer.owncloudnewsreader.model.RssFile; public class InsertIntoDatabase { private static final String TAG = "InsertIntoDatabase"; - public static void InsertFoldersIntoDatabase(List<String[]> tags, DatabaseConnection dbConn) + public static void InsertFoldersIntoDatabase(List<Folder> folderList, DatabaseConnectionOrm dbConn) { - //DatabaseConnection dbConn = new DatabaseConnection(activity); + List<Feed> feeds = dbConn.getListOfFeeds(); + + List<String> tagsAvailable = new ArrayList<String>(feeds.size()); + for(int i = 0; i < feeds.size(); i++) + tagsAvailable.add(feeds.get(i).getFeedTitle()); - //List<String[]> tags = (List<String[]>) task_result; - List<String> tagsAvailable = dbConn.convertCursorToStringArray(dbConn.getAllTopSubscriptions(false), 1); //dbConn.getDatabase().beginTransaction(); try { - if(tags != null) + if(folderList != null) { - List<String> tagsToAdd = new ArrayList<String>(); - for(String[] t : tags) + int addedCount = 0; + int removedCount = 0; + + for(Folder folder : folderList) { - String label = t[0]; - String label_path = t[1]; - if(!tagsAvailable.contains(label)) + if(!tagsAvailable.contains(folder.getLabel())) { - tagsToAdd.add(label); - dbConn.insertNewFolder(label, label_path); - } + addedCount++; + dbConn.insertNewFolder(folder); + } } - List<String> tagsToRemove = new ArrayList<String>(); - - List<String> newLabelList = new ArrayList<String>(); - for(String[] subTag : tags) + //List<String> newLabelList = new ArrayList<String>(); + /* + for(String[] subTag : tags) newLabelList.add(subTag[0]); + */ + /* for(String tag : tagsAvailable) { if(!newLabelList.contains(tag)) { - tagsToRemove.add(tag); - int result = dbConn.removeFolderByFolderLabel(tag); + int result = dbConn.removeFolderByFolderLabel(tag);//TODO this line is needed!!!! Log.d(TAG, "Result delete: " + result); } } + */ - Log.d("ADD", ""+ tagsToAdd.size()); - Log.d("REMOVE", ""+ tagsToRemove.size()); + Log.d("ADD", ""+ addedCount); + Log.d("REMOVE", ""+ removedCount++); } //dbConn.getDatabase().setTransactionSuccessful(); } finally { @@ -90,38 +94,44 @@ public class InsertIntoDatabase { //dbConn.closeDatabase(); } - public static void InsertSubscriptionsIntoDatabase(ArrayList<ConcreteFeedItem> tags, DatabaseConnection dbConn) + public static void InsertFeedsIntoDatabase(ArrayList<Feed> newFeeds, DatabaseConnectionOrm dbConn) { - //DatabaseConnection dbConn = new DatabaseConnection(activity); - - List<String> tagsAvailable = dbConn.convertCursorToStringArray(dbConn.getAllSubSubscriptions(), 1); + List<Feed> oldFeeds = dbConn.getListOfFeeds(); - //dbConn.getDatabase().beginTransaction(); try { - if(tags != null) + if(newFeeds != null) { - for(ConcreteFeedItem tag : tags) + for(Feed feed : newFeeds) + dbConn.insertNewFeed(feed); + + /* + for(Feed feed : newFeeds) { + + + long folderID_db = dbConn.getIdOfFolderFeedId(String.valueOf(feed.getId())).getFeedList(); + Feed feed = new Feed() + if(!tagsAvailable.contains(tag.header)) { - String folderID_db = dbConn.getIdOfFolderByLabelPath(String.valueOf(tag.idFolder)); dbConn.insertNewFeed(tag.header, folderID_db, tag.subscription_id, tag.favIcon); + Log.d(TAG, "Insert Rows: " + result); } else { - String folderID_db = dbConn.getIdOfFolderByLabelPath(String.valueOf(tag.idFolder)); int result = dbConn.updateFeed(tag.header, folderID_db, tag.subscription_id, tag.favIcon); - Log.d(TAG, "Affected Rows: " + result); + Log.d(TAG, "Updated Rows: " + result); } + } + */ - //tags.clear(); - for(String tag : tagsAvailable) + for(Feed feed : oldFeeds) { boolean found = false; - for(int i = 0; i < tags.size(); i++) + for(int i = 0; i < oldFeeds.size(); i++) { - if(tags.get(i).header.contains(tag)) + if(oldFeeds.get(i).getFeedTitle().equals(feed.getFeedTitle())) { found = true; break; @@ -129,11 +139,12 @@ public class InsertIntoDatabase { } if(!found) { - int result = dbConn.removeTopSubscriptionItemByTag(tag); - Log.d(TAG, "Remove Subscription: " + result); + dbConn.removeFeedById(feed.getId()); + Log.d(TAG, "Remove Subscription: " + feed.getFeedTitle()); } } + //lvAdapter.notifyDataSetChanged(); //lvAdapter = new SubscriptionExpandableListAdapter(getActivity(), dbConn); @@ -146,16 +157,21 @@ public class InsertIntoDatabase { } - public static void InsertFeedItemsIntoDatabase(List<RssFile> files, Activity activity) + public static void InsertRssItemsIntoDatabase(List<RssItem> files, Activity activity) { - DatabaseConnection dbConn = new DatabaseConnection(activity); + DatabaseConnectionOrm dbConn = new DatabaseConnectionOrm(activity); + if(files != null) { + dbConn.insertNewItems(files.toArray(new RssItem[files.size()])); + } + + /* dbConn.getDatabase().beginTransaction(); try { if(files != null) { - for (RssFile rssFile : files) + for (RssItem rssFile : files) InsertSingleFeedItemIntoDatabase(rssFile, dbConn); } dbConn.getDatabase().setTransactionSuccessful(); @@ -164,26 +180,19 @@ public class InsertIntoDatabase { } dbConn.closeDatabase(); + */ } - public static boolean InsertSingleFeedItemIntoDatabase(RssFile rssFile, DatabaseConnection dbConn) + public static boolean InsertSingleFeedItemIntoDatabase(RssItem rssFile, DatabaseConnectionOrm dbConn) { boolean newItem = false; if(rssFile != null) { - Boolean isFeedAlreadyInDatabase = dbConn.doesRssItemAlreadyExsists(rssFile.getItem_Id()); - - String FeedId_Db = dbConn.getRowIdBySubscriptionID(String.valueOf(rssFile.getFeedID())); - //String IdSubscription = dbConn.getIdSubscriptionByStreamID(rssFile.getFeedID()); - if(FeedId_Db != null) - { - rssFile.setFeedID_Db(FeedId_Db); - - dbConn.insertNewItem(rssFile, !isFeedAlreadyInDatabase); + //Boolean isFeedAlreadyInDatabase = dbConn.doesRssItemAlreadyExsists(rssFile.getId()); - newItem = !rssFile.getRead(); - } + dbConn.insertNewItems(rssFile); + newItem = !rssFile.getRead(); } return newItem; } diff --git a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/reader/owncloud/API.java b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/reader/owncloud/API.java index 1f3d57ff..65f9d84a 100644 --- a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/reader/owncloud/API.java +++ b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/reader/owncloud/API.java @@ -100,8 +100,8 @@ public abstract class API { return OwnCloudReaderMethods.GetFolderTags(cont, api); } - public int GetItems(TAGS tag, Context cont, String offset, boolean getRead, String id, String type, API api) throws Exception { - return OwnCloudReaderMethods.GetItems(tag, cont, offset, getRead, id, type, api); + public int GetItems(TAGS tag, Context cont, String offset, boolean getRead, int id, String type, API api) throws Exception { + return OwnCloudReaderMethods.GetItems(tag, cont, offset, getRead, String.valueOf(id), type, api); } public int[] GetUpdatedItems(TAGS tag, Context cont, long lastSync, API api) throws Exception { diff --git a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/reader/owncloud/AsyncTask_GetItems.java b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/reader/owncloud/AsyncTask_GetItems.java index f22cfd40..faefd5fa 100644 --- a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/reader/owncloud/AsyncTask_GetItems.java +++ b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/reader/owncloud/AsyncTask_GetItems.java @@ -37,7 +37,7 @@ import de.luhmer.owncloudnewsreader.Constants; import de.luhmer.owncloudnewsreader.DownloadImagesActivity; import de.luhmer.owncloudnewsreader.R; import de.luhmer.owncloudnewsreader.SettingsActivity; -import de.luhmer.owncloudnewsreader.database.DatabaseConnection; +import de.luhmer.owncloudnewsreader.database.DatabaseConnectionOrm; import de.luhmer.owncloudnewsreader.helper.NetworkConnection; import de.luhmer.owncloudnewsreader.reader.AsyncTask_Reader; import de.luhmer.owncloudnewsreader.reader.FeedItemTags.TAGS; @@ -65,8 +65,10 @@ public class AsyncTask_GetItems extends AsyncTask_Reader { @Override protected Exception doInBackground(Object... params) { - DatabaseConnection dbConn = new DatabaseConnection(context); + DatabaseConnectionOrm dbConn = new DatabaseConnectionOrm(context); try { + dbConn.clearDatabaseOverSize(); + //String authKey = AuthenticationManager.getGoogleAuthKey(username, password); //SharedPreferences mPrefs = PreferenceManager.getDefaultSharedPreferences(context); //int maxItemsInDatabase = Integer.parseInt(mPrefs.getString(SettingsActivity.SP_MAX_ITEMS_SYNC, "200")); @@ -90,7 +92,7 @@ public class AsyncTask_GetItems extends AsyncTask_Reader { int maxItemsInDatabase = Constants.maxItemsCount; do { - requestCount = api.GetItems(TAGS.ALL, context, String.valueOf(offset), false, "0", "3", api); + requestCount = api.GetItems(TAGS.ALL, context, String.valueOf(offset), false, 0, "3", api); if(requestCount > 0) offset = dbConn.getLowestItemId(false); totalCount += requestCount; @@ -102,7 +104,7 @@ public class AsyncTask_GetItems extends AsyncTask_Reader { do { offset = dbConn.getLowestItemId(true); - requestCount = api.GetItems(TAGS.ALL_STARRED, context, String.valueOf(offset), true, "0", "2", api); + requestCount = api.GetItems(TAGS.ALL_STARRED, context, String.valueOf(offset), true, 0, "2", api); //if(requestCount > 0) // offset = dbConn.getLowestItemId(true); totalCount += requestCount; @@ -116,9 +118,10 @@ public class AsyncTask_GetItems extends AsyncTask_Reader { //OwnCloudReaderMethods.GetUpdatedItems(TAGS.ALL, context, lastModified, api); } } catch (Exception ex) { + ex.printStackTrace(); return ex; } finally { - dbConn.closeDatabase(); + //dbConn.closeDatabase(); } return null; } @@ -130,35 +133,30 @@ public class AsyncTask_GetItems extends AsyncTask_Reader { listenerInstance.onAsyncTaskCompleted(task_id, ex); } - SharedPreferences mPrefs = PreferenceManager.getDefaultSharedPreferences(context); - if(mPrefs.getBoolean(SettingsActivity.CB_CACHE_IMAGES_OFFLINE_STRING, false)) - { - if(!NetworkConnection.isWLANConnected(context) && NetworkConnection.isNetworkAvailable(context)) - ShowDownloadImageWithoutWifiQuestion(); - else if(NetworkConnection.isNetworkAvailable(context)) - StartDownloadingImages(context, highestItemIdBeforeSync, false); - } else { - StartDownloadingImages(context, highestItemIdBeforeSync, true); + if(ex != null) { + SharedPreferences mPrefs = PreferenceManager.getDefaultSharedPreferences(context); + if (mPrefs.getBoolean(SettingsActivity.CB_CACHE_IMAGES_OFFLINE_STRING, false)) { + if (!NetworkConnection.isWLANConnected(context) && NetworkConnection.isNetworkAvailable(context)) + ShowDownloadImageWithoutWifiQuestion(); + else if (NetworkConnection.isNetworkAvailable(context)) + StartDownloadingImages(context, highestItemIdBeforeSync, false); + } else { + StartDownloadingImages(context, highestItemIdBeforeSync, true); + } } - detach(); } public static void StartDownloadingImages(Context context, long highestItemIdBeforeSync, boolean favIconsExclusive) { - DatabaseConnection dbConn = new DatabaseConnection(context); - try { - Intent service = new Intent(context, DownloadImagesService.class); - service.putExtra(DownloadImagesService.LAST_ITEM_ID, highestItemIdBeforeSync); - - if(favIconsExclusive) - service.putExtra(DownloadImagesService.DOWNLOAD_FAVICONS_EXCLUSIVE, true); - - context.startService(service); - } finally { - dbConn.closeDatabase(); - } + Intent service = new Intent(context, DownloadImagesService.class); + service.putExtra(DownloadImagesService.LAST_ITEM_ID, highestItemIdBeforeSync); + + if(favIconsExclusive) + service.putExtra(DownloadImagesService.DOWNLOAD_FAVICONS_EXCLUSIVE, true); + + context.startService(service); } diff --git a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/reader/owncloud/AsyncTask_GetOldItems.java b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/reader/owncloud/AsyncTask_GetOldItems.java index 2e50f814..d59b35fe 100644 --- a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/reader/owncloud/AsyncTask_GetOldItems.java +++ b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/reader/owncloud/AsyncTask_GetOldItems.java @@ -22,15 +22,14 @@ package de.luhmer.owncloudnewsreader.reader.owncloud; import android.content.Context; -import android.util.Log; import android.widget.Toast; -import de.luhmer.owncloudnewsreader.Constants; import de.luhmer.owncloudnewsreader.ListView.SubscriptionExpandableListAdapter; import de.luhmer.owncloudnewsreader.NewsReaderDetailFragment; import de.luhmer.owncloudnewsreader.NewsReaderListActivity; import de.luhmer.owncloudnewsreader.R; -import de.luhmer.owncloudnewsreader.database.DatabaseConnection; +import de.luhmer.owncloudnewsreader.database.DatabaseConnectionOrm; +import de.luhmer.owncloudnewsreader.database.model.RssItem; import de.luhmer.owncloudnewsreader.reader.AsyncTask_Reader; import de.luhmer.owncloudnewsreader.reader.FeedItemTags.TAGS; import de.luhmer.owncloudnewsreader.reader.OnAsyncTaskCompletedListener; @@ -38,12 +37,12 @@ import de.luhmer.owncloudnewsreader.reader.OnAsyncTaskCompletedListener; public class AsyncTask_GetOldItems extends AsyncTask_Reader { private static final String TAG = "AsyncTask_GetOldItems"; - public String feed_id; - public String folder_id; + public Long feed_id; + public Long folder_id; private int downloadedItemsCount = 0; private API api; - public AsyncTask_GetOldItems(final int task_id, final Context context, final OnAsyncTaskCompletedListener[] listener, String feed_id, String folder_id, API api) { + public AsyncTask_GetOldItems(final int task_id, final Context context, final OnAsyncTaskCompletedListener[] listener, Long feed_id, Long folder_id, API api) { super(task_id, context, listener); this.feed_id = feed_id; @@ -53,37 +52,39 @@ public class AsyncTask_GetOldItems extends AsyncTask_Reader { @Override protected Exception doInBackground(Object... params) { - DatabaseConnection dbConn = new DatabaseConnection(context); + DatabaseConnectionOrm dbConn = new DatabaseConnectionOrm(context); try { long offset = 0; //int requestCount = 0; //int maxSyncSize = Integer.parseInt(OwnCloudReaderMethods.maxSizePerSync); - String id = null; + Long id = null; String type = null; if(feed_id != null) { - offset = dbConn.getLowestItemIdByFeed(feed_id); - id = dbConn.getSubscriptionIdByRowID(feed_id); + RssItem rssItem = dbConn.getLowestRssItemIdByFeed(feed_id); + offset = rssItem.getId();//TODO needs testing! + id = feed_id; type = "0"; } else if(folder_id != null) { - if(folder_id.equals(SubscriptionExpandableListAdapter.SPECIAL_FOLDERS.ALL_STARRED_ITEMS.getValueString())) + if(folder_id == SubscriptionExpandableListAdapter.SPECIAL_FOLDERS.ALL_STARRED_ITEMS.getValue())//TODO needs testing! { - offset = dbConn.getLowestItemIdStarred(); - id = "0"; + offset = dbConn.getLowestItemId(true); + id = 0L; type = "2"; } else { - offset = dbConn.getLowestItemIdByFolder(folder_id); - id = dbConn.getIdOfFolderByLabelPath(folder_id); + offset = dbConn.getLowestItemIdByFolder(folder_id); + id = folder_id;//dbConn.getIdOfFolderByLabelPath(folder_id); type = "1"; } } - downloadedItemsCount = api.GetItems(TAGS.ALL, context, String.valueOf(offset), true, id, type, api); + downloadedItemsCount = api.GetItems(TAGS.ALL, context, String.valueOf(offset), true, id.intValue(), type, api); + /* int totalCount = dbConn.getCountOfAllItems(false); //If the number of items in the database is bigger than the maximum allowed number of items @@ -92,20 +93,10 @@ public class AsyncTask_GetOldItems extends AsyncTask_Reader { dbConn.removeXLatestItems(totalCount - Constants.maxItemsCount, feedIdDb); Log.d(TAG, "Deleted starred-items in order to free up enough space for the read items"); } - - //downloadedItemsCount = OwnCloudReaderMethods.GetItems(TAGS.ALL, context, String.valueOf(offset), true, id, type, api); - - - //do { - //requestCount = OwnCloudReaderMethods.GetItems(TAGS.ALL, context, String.valueOf(offset), true, feed_id); - // if(requestCount > 0) - // offset = dbConn.getLowestItemIdByFeed(feed_id); - //} while(requestCount == maxSyncSize); + */ } catch (Exception ex) { return ex; - } finally { - dbConn.closeDatabase(); } return null; } @@ -131,23 +122,9 @@ public class AsyncTask_GetOldItems extends AsyncTask_Reader { NewsReaderListActivity activity = (NewsReaderListActivity) context; NewsReaderDetailFragment nrD = (NewsReaderDetailFragment) activity.getSupportFragmentManager().findFragmentById(R.id.content_frame); if(nrD != null) - nrD.UpdateCurrentRssView(context); + nrD.UpdateCurrentRssView(context, true); } - - - - /* - DatabaseConnection dbConn = new DatabaseConnection(context); - try { - Intent service = new Intent(context, DownloadImagesService.class); - service.putExtra(DownloadImagesService.LAST_ITEM_ID, highestItemIdBeforeSync); - context.startService(service); - } finally { - dbConn.closeDatabase(); - } - */ - detach(); } } diff --git a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/reader/owncloud/AsyncTask_PerformItemStateChange.java b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/reader/owncloud/AsyncTask_PerformItemStateChange.java index 85d9cd30..5be0de7d 100644 --- a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/reader/owncloud/AsyncTask_PerformItemStateChange.java +++ b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/reader/owncloud/AsyncTask_PerformItemStateChange.java @@ -26,7 +26,7 @@ import android.content.Context; import java.util.ArrayList; import java.util.List; -import de.luhmer.owncloudnewsreader.database.DatabaseConnection; +import de.luhmer.owncloudnewsreader.database.DatabaseConnectionOrm; import de.luhmer.owncloudnewsreader.reader.AsyncTask_Reader; import de.luhmer.owncloudnewsreader.reader.FeedItemTags.TAGS; import de.luhmer.owncloudnewsreader.reader.OnAsyncTaskCompletedListener; @@ -46,37 +46,37 @@ public class AsyncTask_PerformItemStateChange extends AsyncTask_Reader List<Boolean> succeeded = new ArrayList<Boolean>(); try { - DatabaseConnection dbConn = new DatabaseConnection(context); + DatabaseConnectionOrm dbConn = new DatabaseConnectionOrm(context); try { //Mark as READ - List<String> itemIds = dbConn.getAllNewReadItems(); + List<String> itemIds = dbConn.getRssItemsIdsFromList(dbConn.getAllNewReadRssItems()); boolean result = api.PerformTagExecution(itemIds, TAGS.MARK_ITEM_AS_READ, context, api); if(result) dbConn.change_readUnreadStateOfItem(itemIds, true); succeeded.add(result); //Mark as UNREAD - itemIds = dbConn.getAllNewUnreadItems(); + itemIds = dbConn.getRssItemsIdsFromList(dbConn.getAllNewUnreadRssItems()); result = api.PerformTagExecution(itemIds, TAGS.MARK_ITEM_AS_UNREAD, context, api); if(result) dbConn.change_readUnreadStateOfItem(itemIds, false); succeeded.add(result); //Mark as STARRED - itemIds = dbConn.getAllNewStarredItems(); + itemIds = dbConn.getRssItemsIdsFromList(dbConn.getAllNewStarredRssItems()); result = api.PerformTagExecution(itemIds, TAGS.MARK_ITEM_AS_STARRED, context, api); if(result) dbConn.change_starrUnstarrStateOfItem(itemIds, true); succeeded.add(result); //Mark as UNSTARRED - itemIds = dbConn.getAllNewUnstarredItems(); + itemIds = dbConn.getRssItemsIdsFromList(dbConn.getAllNewUnstarredRssItems()); result = api.PerformTagExecution(itemIds, TAGS.MARK_ITEM_AS_UNSTARRED, context, api); if(result) dbConn.change_starrUnstarrStateOfItem(itemIds, false); succeeded.add(result); } finally { - dbConn.closeDatabase(); + //dbConn.closeDatabase(); } } catch (Exception e) { e.printStackTrace(); diff --git a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/reader/owncloud/InsertFeedIntoDatabase.java b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/reader/owncloud/InsertFeedIntoDatabase.java index 22feaebe..afe51b34 100644 --- a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/reader/owncloud/InsertFeedIntoDatabase.java +++ b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/reader/owncloud/InsertFeedIntoDatabase.java @@ -25,37 +25,43 @@ import org.json.JSONObject; import java.util.ArrayList; -import de.luhmer.owncloudnewsreader.database.DatabaseConnection; -import de.luhmer.owncloudnewsreader.model.ConcreteFeedItem; +import de.luhmer.owncloudnewsreader.database.DatabaseConnectionOrm; +import de.luhmer.owncloudnewsreader.database.model.Feed; import de.luhmer.owncloudnewsreader.reader.InsertIntoDatabase; public class InsertFeedIntoDatabase implements IHandleJsonObject{ - DatabaseConnection dbConn; - ArrayList<ConcreteFeedItem> feeds = new ArrayList<ConcreteFeedItem>(); + DatabaseConnectionOrm dbConn; + ArrayList<Feed> feeds = new ArrayList<Feed>(); - public InsertFeedIntoDatabase(DatabaseConnection dbConn) { + public InsertFeedIntoDatabase(DatabaseConnectionOrm dbConn) { this.dbConn = dbConn; } - private static ConcreteFeedItem parseFeed(JSONObject e) + private static Feed parseFeed(JSONObject e) { String faviconLink = e.optString("faviconLink"); if(faviconLink != null) if(faviconLink.equals("null") || faviconLink.trim().equals("")) faviconLink = null; - return new ConcreteFeedItem(e.optString("title"), e.optString("folderId"), e.optString("id"), faviconLink, -1); + Feed feed = new Feed(); + feed.setId(e.optLong("id")); + feed.setFeedTitle(e.optString("title")); + feed.setFolderId(e.optLong("folderId")); + feed.setFaviconUrl(faviconLink); + + return feed; } @Override public boolean performAction(JSONObject jObj) { - ConcreteFeedItem rssFeed = parseFeed(jObj); + Feed rssFeed = parseFeed(jObj); feeds.add(rssFeed); return true; } public void WriteAllToDatabaseNow() { - InsertIntoDatabase.InsertSubscriptionsIntoDatabase(feeds, dbConn); + InsertIntoDatabase.InsertFeedsIntoDatabase(feeds, dbConn); } } diff --git a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/reader/owncloud/InsertFolderIntoDatabase.java b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/reader/owncloud/InsertFolderIntoDatabase.java index 2c7feb39..0dc0ed7c 100644 --- a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/reader/owncloud/InsertFolderIntoDatabase.java +++ b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/reader/owncloud/InsertFolderIntoDatabase.java @@ -25,21 +25,22 @@ import org.json.JSONObject; import java.util.ArrayList; -import de.luhmer.owncloudnewsreader.database.DatabaseConnection; +import de.luhmer.owncloudnewsreader.database.DatabaseConnectionOrm; +import de.luhmer.owncloudnewsreader.database.model.Folder; import de.luhmer.owncloudnewsreader.reader.InsertIntoDatabase; public class InsertFolderIntoDatabase implements IHandleJsonObject{ + + DatabaseConnectionOrm dbConn; + ArrayList<Folder> folders = new ArrayList<Folder>(); - DatabaseConnection dbConn; - ArrayList<String[]> folders = new ArrayList<String[]>(); - - public InsertFolderIntoDatabase(DatabaseConnection dbConn) { + public InsertFolderIntoDatabase(DatabaseConnectionOrm dbConn) { this.dbConn = dbConn; } - private static String[] parseFolder(JSONObject e) + private static Folder parseFolder(JSONObject e) { - return new String[] { e.optString("name"), e.optString("id") }; + return new Folder(e.optLong("id"), e.optString("name")); } @Override diff --git a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/reader/owncloud/InsertItemIntoDatabase.java b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/reader/owncloud/InsertItemIntoDatabase.java index 6a372f9a..8f614a11 100644 --- a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/reader/owncloud/InsertItemIntoDatabase.java +++ b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/reader/owncloud/InsertItemIntoDatabase.java @@ -21,33 +21,34 @@ package de.luhmer.owncloudnewsreader.reader.owncloud; -import android.util.SparseArray; - +import org.json.JSONException; import org.json.JSONObject; +import java.util.ArrayList; import java.util.Date; +import java.util.List; -import de.luhmer.owncloudnewsreader.database.DatabaseConnection; -import de.luhmer.owncloudnewsreader.model.RssFile; +import de.luhmer.owncloudnewsreader.database.DatabaseConnectionOrm; +import de.luhmer.owncloudnewsreader.database.model.RssItem; public class InsertItemIntoDatabase implements IHandleJsonObject { - DatabaseConnection dbConn; - RssFile[] buffer; + DatabaseConnectionOrm dbConn; + List<RssItem> buffer; static final short bufferSize = 200; int index = 0; - SparseArray<String> feedIds; + //List<Feed> feeds; - public InsertItemIntoDatabase(DatabaseConnection dbConn) { + public InsertItemIntoDatabase(DatabaseConnectionOrm dbConn) { this.dbConn = dbConn; - buffer = new RssFile[bufferSize]; + //buffer = new RssItem[bufferSize]; + buffer = new ArrayList<RssItem>(bufferSize); - feedIds = dbConn.getFeedIds(); + //feeds = dbConn.getListOfFeeds(); } - private static RssFile parseItem(JSONObject e) - { - Date date = new Date(e.optLong("pubDate") * 1000); + private static RssItem parseItem(JSONObject e) throws JSONException { + Date pubDate = new Date(e.optLong("pubDate") * 1000); String content = e.optString("body"); content = content.replaceAll("<img[^>]*feedsportal.com.*>", ""); @@ -65,8 +66,27 @@ public class InsertItemIntoDatabase implements IHandleJsonObject { enclosureMime = "youtube"; } - - return new RssFile(0, e.optString("id"), + RssItem rssItem = new RssItem(); + rssItem.setId(e.getLong("id")); + rssItem.setFeedId(e.optLong("feedId")); + rssItem.setLink(url); + rssItem.setTitle(e.optString("title")); + rssItem.setGuid(guid); + rssItem.setGuidHash(e.optString("guidHash")); + rssItem.setBody(content); + rssItem.setAuthor(e.optString("author")); + rssItem.setLastModified(new Date(e.optLong("lastModified"))); + rssItem.setEnclosureLink(enclosureLink); + rssItem.setEnclosureMime(enclosureMime); + rssItem.setRead(!e.optBoolean("unread")); + rssItem.setRead_temp(rssItem.getRead()); + rssItem.setStarred(e.optBoolean("starred")); + rssItem.setStarred_temp(rssItem.getStarred()); + rssItem.setPubDate(pubDate); + + return rssItem; + /* + new RssItem(0, e.optString("id"), e.optString("title"), url, content, !e.optBoolean("unread"), null, @@ -78,24 +98,29 @@ public class InsertItemIntoDatabase implements IHandleJsonObject { e.optString("author"), enclosureLink, enclosureMime); + */ } @Override public boolean performAction(JSONObject jObj) { boolean result = false; - RssFile rssFile = parseItem(jObj); - buffer[index] = rssFile; - index++; + try { + RssItem rssFile = parseItem(jObj); + //buffer[index] = rssFile; + buffer.add(rssFile); + index++; - String FeedId_Db = feedIds.get(Integer.parseInt(rssFile.getFeedID())); - if(FeedId_Db != null) { - rssFile.setFeedID_Db(FeedId_Db); - result = !rssFile.getRead(); - } - if(index >= bufferSize) { - performDatabaseBatchInsert(); + if (rssFile != null) + result = !rssFile.getRead(); + + //if (index >= bufferSize) { + if (buffer.size() >= bufferSize) { + performDatabaseBatchInsert(); + } + } catch(Exception ex) { + ex.printStackTrace(); } return result; @@ -104,9 +129,12 @@ public class InsertItemIntoDatabase implements IHandleJsonObject { public boolean performDatabaseBatchInsert() { if(index > 0) { - dbConn.insertNewItems(buffer); + //dbConn.insertNewItems(buffer); + dbConn.insertNewItems(buffer.toArray(new RssItem[buffer.size()])); + index = 0; - buffer = new RssFile[bufferSize]; + //buffer = new RssItem[bufferSize]; + buffer = new ArrayList<RssItem>(bufferSize); } return true; diff --git a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/reader/owncloud/OwnCloudReaderMethods.java b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/reader/owncloud/OwnCloudReaderMethods.java index 58a215d4..8fcc31e5 100644 --- a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/reader/owncloud/OwnCloudReaderMethods.java +++ b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/reader/owncloud/OwnCloudReaderMethods.java @@ -22,7 +22,6 @@ package de.luhmer.owncloudnewsreader.reader.owncloud; import android.content.Context; -import android.database.Cursor; import com.google.gson.stream.JsonReader; import com.google.gson.stream.JsonToken; @@ -42,7 +41,8 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -import de.luhmer.owncloudnewsreader.database.DatabaseConnection; +import de.luhmer.owncloudnewsreader.database.DatabaseConnectionOrm; +import de.luhmer.owncloudnewsreader.database.model.RssItem; import de.luhmer.owncloudnewsreader.reader.FeedItemTags; import de.luhmer.owncloudnewsreader.reader.FeedItemTags.TAGS; import de.luhmer.owncloudnewsreader.reader.HttpJsonRequest; @@ -72,7 +72,7 @@ public class OwnCloudReaderMethods { InputStream is = HttpJsonRequest.PerformJsonRequest(api.getItemUpdatedUrl(), nVPairs, api.getUsername(), api.getPassword(), cont); - DatabaseConnection dbConn = new DatabaseConnection(cont); + DatabaseConnectionOrm dbConn = new DatabaseConnectionOrm(cont); try { if(api instanceof APIv1) @@ -80,7 +80,7 @@ public class OwnCloudReaderMethods { else if(api instanceof APIv2) return readJsonStreamV2(is, new InsertItemIntoDatabase(dbConn)); } finally { - dbConn.closeDatabase(); + //dbConn.closeDatabase();//TODO this line is needed is.close(); } return new int[] { 0, 0 }; @@ -110,7 +110,7 @@ public class OwnCloudReaderMethods { InputStream is = HttpJsonRequest.PerformJsonRequest(api.getItemUrl(), nVPairs, api.getUsername(), api.getPassword(), cont); - DatabaseConnection dbConn = new DatabaseConnection(cont); + DatabaseConnectionOrm dbConn = new DatabaseConnectionOrm(cont); try { if(api instanceof APIv1) @@ -118,7 +118,7 @@ public class OwnCloudReaderMethods { else if(api instanceof APIv2) return readJsonStreamV2(is, new InsertItemIntoDatabase(dbConn))[0]; } finally { - dbConn.closeDatabase(); + //dbConn.closeDatabase();//TODO this line is needed is.close(); } return 0; @@ -128,7 +128,7 @@ public class OwnCloudReaderMethods { public static int GetFolderTags(Context cont, API api) throws Exception { InputStream is = HttpJsonRequest.PerformJsonRequest(api.getFolderUrl(), null, api.getUsername(), api.getPassword(), cont); - DatabaseConnection dbConn = new DatabaseConnection(cont); + DatabaseConnectionOrm dbConn = new DatabaseConnectionOrm(cont); int[] result = new int[2]; try { @@ -141,7 +141,7 @@ public class OwnCloudReaderMethods { ifid.WriteAllToDatabaseNow(); } finally { - dbConn.closeDatabase(); + //dbConn.closeDatabase();//TODO this line is needed is.close(); } @@ -152,7 +152,7 @@ public class OwnCloudReaderMethods { { InputStream inputStream = HttpJsonRequest.PerformJsonRequest(api.getFeedUrl() , null, api.getUsername(), api.getPassword(), cont); - DatabaseConnection dbConn = new DatabaseConnection(cont); + DatabaseConnectionOrm dbConn = new DatabaseConnectionOrm(cont); int result[] = new int[2]; try { InsertFeedIntoDatabase ifid = new InsertFeedIntoDatabase(dbConn); @@ -164,7 +164,7 @@ public class OwnCloudReaderMethods { ifid.WriteAllToDatabaseNow(); } finally { - dbConn.closeDatabase(); + //dbConn.closeDatabase();//TODO this line is needed inputStream.close(); } return result; @@ -349,26 +349,14 @@ public class OwnCloudReaderMethods { else url += "unread/multiple"; } else { - DatabaseConnection dbConn = new DatabaseConnection(context); + DatabaseConnectionOrm dbConn = new DatabaseConnectionOrm(context); HashMap<String, String> items = new HashMap<String, String>(); for(String idItem : itemIds) { - Cursor cursor = dbConn.getArticleByID(dbConn.getRowIdOfFeedByItemID(idItem)); - //Cursor cursor = dbConn.getFeedByID itemID); - cursor.moveToFirst(); - - String idSubscription = cursor.getString(cursor.getColumnIndex(DatabaseConnection.RSS_ITEM_SUBSCRIPTION_ID)); - String guidHash = cursor.getString(cursor.getColumnIndex(DatabaseConnection.RSS_ITEM_GUIDHASH)); - - cursor.close(); - - String subscription_id = dbConn.getSubscriptionIdByRowID(idSubscription); - //url += subscription_id; - - items.put(guidHash, subscription_id); + RssItem rssItem = dbConn.getRssItemById(Long.parseLong(idItem)); + items.put(rssItem.getGuidHash(), String.valueOf(rssItem.getFeedId())); } - dbConn.closeDatabase(); jsonIds = buildIdsToJSONArrayWithGuid(items); /* @@ -420,21 +408,14 @@ public class OwnCloudReaderMethods { else url += itemId + "/unread"; } else { - DatabaseConnection dbConn = new DatabaseConnection(context); - - Cursor cursor = dbConn.getArticleByID(dbConn.getRowIdOfFeedByItemID(itemId)); - cursor.moveToFirst(); + DatabaseConnectionOrm dbConn = new DatabaseConnectionOrm(context); - String idSubscription = cursor.getString(cursor.getColumnIndex(DatabaseConnection.RSS_ITEM_SUBSCRIPTION_ID)); - String guidHash = cursor.getString(cursor.getColumnIndex(DatabaseConnection.RSS_ITEM_GUIDHASH)); - cursor.close(); + RssItem rssItem = dbConn.getRssItemById(Long.parseLong(itemId)); - String subscription_id = dbConn.getSubscriptionIdByRowID(idSubscription); - url += subscription_id; + url += rssItem.getFeedId(); - dbConn.closeDatabase(); - url += "/" + guidHash; + url += "/" + rssItem.getGuidHash(); if(tag.equals(TAGS.MARK_ITEM_AS_STARRED)) url += "/star"; else if(tag.equals(TAGS.MARK_ITEM_AS_UNSTARRED)) diff --git a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/reader/owncloud/OwnCloud_Reader.java b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/reader/owncloud/OwnCloud_Reader.java index 777bebfb..731064ee 100644 --- a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/reader/owncloud/OwnCloud_Reader.java +++ b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/reader/owncloud/OwnCloud_Reader.java @@ -49,7 +49,7 @@ public class OwnCloud_Reader implements IReader { @Override public void Start_AsyncTask_GetOldItems(int task_id, - Context context, OnAsyncTaskCompletedListener listener, String feed_id, String folder_id) { + Context context, OnAsyncTaskCompletedListener listener, Long feed_id, Long folder_id) { setSyncRunning(true); AsyncTasksRunning.append(task_id, (AsyncTask_Reader) new AsyncTask_GetOldItems(task_id, context, new OnAsyncTaskCompletedListener[] { AsyncTask_finished, listener }, feed_id, folder_id, api).execute()); } diff --git a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/reader/owncloud/apiv2/AsyncTask_TriggerOcUpdate.java b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/reader/owncloud/apiv2/AsyncTask_TriggerOcUpdate.java index 8f82020e..cafa7e55 100644 --- a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/reader/owncloud/apiv2/AsyncTask_TriggerOcUpdate.java +++ b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/reader/owncloud/apiv2/AsyncTask_TriggerOcUpdate.java @@ -2,11 +2,13 @@ package de.luhmer.owncloudnewsreader.reader.owncloud.apiv2; import android.content.Context; import android.content.SharedPreferences; -import android.database.Cursor; import android.preference.PreferenceManager; +import java.util.List; + import de.luhmer.owncloudnewsreader.SettingsActivity; -import de.luhmer.owncloudnewsreader.database.DatabaseConnection; +import de.luhmer.owncloudnewsreader.database.DatabaseConnectionOrm; +import de.luhmer.owncloudnewsreader.database.model.Feed; import de.luhmer.owncloudnewsreader.reader.AsyncTask_Reader; import de.luhmer.owncloudnewsreader.reader.OnAsyncTaskCompletedListener; import de.luhmer.owncloudnewsreader.reader.owncloud.OwnCloudConstants; @@ -32,8 +34,8 @@ public class AsyncTask_TriggerOcUpdate extends AsyncTask_Reader { SharedPreferences mPrefs = PreferenceManager.getDefaultSharedPreferences(context); String oc_path = mPrefs.getString(SettingsActivity.EDT_OWNCLOUDROOTPATH_STRING, "") + OwnCloudConstants.ROOT_PATH_APIv2 + "feeds/update" + OwnCloudConstants.JSON_FORMAT; - DatabaseConnection dbConn = new DatabaseConnection(context); - Cursor cursor = dbConn.getAllSubSubscriptions(); + DatabaseConnectionOrm dbConn = new DatabaseConnectionOrm(context); + List<Feed> feedList = dbConn.getListOfFeeds(); /* @@ -51,7 +53,6 @@ public class AsyncTask_TriggerOcUpdate extends AsyncTask_Reader { } while(cursor.moveToNext()); } */ - dbConn.closeDatabase(); return true; } catch (Exception ex) { diff --git a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/services/DownloadImagesService.java b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/services/DownloadImagesService.java index 79100813..1e0d09e7 100644 --- a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/services/DownloadImagesService.java +++ b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/services/DownloadImagesService.java @@ -28,7 +28,6 @@ import android.app.PendingIntent; import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; -import android.database.Cursor; import android.preference.PreferenceManager; import android.support.v4.app.NotificationCompat; import android.util.SparseArray; @@ -46,7 +45,8 @@ import de.luhmer.owncloudnewsreader.NewsReaderListActivity; import de.luhmer.owncloudnewsreader.R; import de.luhmer.owncloudnewsreader.SettingsActivity; import de.luhmer.owncloudnewsreader.async_tasks.GetImageAsyncTask; -import de.luhmer.owncloudnewsreader.database.DatabaseConnection; +import de.luhmer.owncloudnewsreader.database.DatabaseConnectionOrm; +import de.luhmer.owncloudnewsreader.database.model.RssItem; import de.luhmer.owncloudnewsreader.helper.BitmapDrawableLruCache; import de.luhmer.owncloudnewsreader.helper.FavIconHandler; import de.luhmer.owncloudnewsreader.helper.FileUtils; @@ -106,7 +106,7 @@ public class DownloadImagesService extends IntentService { protected void onHandleIntent(Intent intent) { boolean downloadFavIconsExclusive = intent.getBooleanExtra(DOWNLOAD_FAVICONS_EXCLUSIVE, false); - DatabaseConnection dbConn = new DatabaseConnection(this); + DatabaseConnectionOrm dbConn = new DatabaseConnectionOrm(this); Notification notify = BuildNotification(); SparseArray<String> linksFavIcons = dbConn.getUrlsToFavIcons(); @@ -116,29 +116,21 @@ public class DownloadImagesService extends IntentService { for(int i = 0; i < linksFavIcons.size(); i++) { int key = linksFavIcons.keyAt(i); String link = linksFavIcons.get(i); - FavIconHandler.PreCacheFavIcon(link, this, String.valueOf(key)); + FavIconHandler.PreCacheFavIcon(link, this, (long) key); } if(!downloadFavIconsExclusive) { - String lastId = String.valueOf(intent.getLongExtra(LAST_ITEM_ID, 0)); - Cursor cursor = dbConn.getAllItemsWithIdHigher(lastId); + long lastId = intent.getLongExtra(LAST_ITEM_ID, 0); + List<RssItem> rssItemList = dbConn.getAllItemsWithIdHigher(lastId); List<String> links = new ArrayList<String>(); - try { - if (cursor != null) { - while (cursor.moveToNext()) { - String body = cursor.getString(cursor.getColumnIndex(DatabaseConnection.RSS_ITEM_BODY)); - links.addAll(ImageHandler.getImageLinksFromText(body)); - } - } - } catch (Exception ex) { - ex.printStackTrace(); - } finally { - cursor.close(); - dbConn.closeDatabase(); + for(RssItem rssItem : rssItemList) { + String body = rssItem.getBody(); + links.addAll(ImageHandler.getImageLinksFromText(body)); } + maxCount = links.size(); if (maxCount > 0) diff --git a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/ssl/MemorizingDialogFragment.java b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/ssl/MemorizingDialogFragment.java index 632f09f9..56d752c1 100644 --- a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/ssl/MemorizingDialogFragment.java +++ b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/ssl/MemorizingDialogFragment.java @@ -31,13 +31,12 @@ import android.content.DialogInterface.OnCancelListener; import android.content.DialogInterface.OnClickListener; import android.content.Intent; import android.os.Bundle; +import android.support.v4.app.DialogFragment; import android.util.Log; -import com.actionbarsherlock.app.SherlockDialogFragment; - import de.luhmer.owncloudnewsreader.R; -public class MemorizingDialogFragment extends SherlockDialogFragment +public class MemorizingDialogFragment extends DialogFragment implements OnClickListener,OnCancelListener { final static String TAG = "MemorizingDialogFragment"; diff --git a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/ssl/MemorizingTrustManager.java b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/ssl/MemorizingTrustManager.java index 399b0bfd..5a2376d6 100644 --- a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/ssl/MemorizingTrustManager.java +++ b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/ssl/MemorizingTrustManager.java @@ -41,13 +41,12 @@ import android.graphics.BitmapFactory; import android.net.Uri; import android.os.Bundle; import android.os.Handler; +import android.support.v4.app.DialogFragment; import android.support.v4.app.FragmentActivity; import android.support.v4.app.NotificationCompat; import android.util.Log; import android.util.SparseArray; -import com.actionbarsherlock.app.SherlockDialogFragment; - import java.io.File; import java.security.KeyStore; import java.security.KeyStoreException; @@ -423,7 +422,7 @@ public class MemorizingTrustManager implements X509TrustManager { bundle.putInt(DECISION_INTENT_ID, myId); bundle.putString(DECISION_INTENT_CERT, certMessage); - SherlockDialogFragment dialog = new MemorizingDialogFragment(); + DialogFragment dialog = new MemorizingDialogFragment(); dialog.setArguments(bundle); try { dialog.show(((FragmentActivity) getUI()).getSupportFragmentManager(), "NoticeDialogFragment"); diff --git a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/widget/WidgetProvider.java b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/widget/WidgetProvider.java index 00f1902b..0578fbe9 100644 --- a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/widget/WidgetProvider.java +++ b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/widget/WidgetProvider.java @@ -46,7 +46,7 @@ public class WidgetProvider extends AppWidgetProvider { public static final String ACTION_WIDGET_CONFIGURE = "ConfigureWidget"; public static final String ACTION_WIDGET_RECEIVER = "ActionReceiverWidget"; public static final String ACTION_LIST_CLICK = "ACTION_LIST_CLICK"; - public static final String UID_TODO = "UID_TODO"; + public static final String RSS_ITEM_ID = "RSS_ITEM_ID"; public static final String EXTRA_ITEM = null; private static final String TAG = "WidgetProvider"; @@ -82,15 +82,15 @@ public class WidgetProvider extends AppWidgetProvider { } */else if (action.equals(ACTION_LIST_CLICK)) { try { - String uid = intent.getExtras().getString(UID_TODO); + Long rssItemId = intent.getExtras().getLong(RSS_ITEM_ID); //Intent intentToDoListAct = new Intent(context, TodoListActivity.class); Intent intentToDoListAct = new Intent(context, NewsDetailActivity.class); - intentToDoListAct.putExtra(UID_TODO, uid); + intentToDoListAct.putExtra(RSS_ITEM_ID, rssItemId); intentToDoListAct.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); context.startActivity(intentToDoListAct); if(Constants.debugModeWidget) - Log.d(TAG, "ListItem Clicked Starting Activity for Item: " + uid); + Log.d(TAG, "ListItem Clicked Starting Activity for Item: " + rssItemId); } catch(Exception ex) { diff --git a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/widget/WidgetTodoViewsFactory.java b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/widget/WidgetTodoViewsFactory.java index b4e45b91..91d4f424 100644 --- a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/widget/WidgetTodoViewsFactory.java +++ b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/widget/WidgetTodoViewsFactory.java @@ -26,7 +26,6 @@ import android.annotation.TargetApi; import android.appwidget.AppWidgetManager; import android.content.Context; import android.content.Intent; -import android.database.Cursor; import android.os.Build; import android.text.Html; import android.util.Log; @@ -35,19 +34,21 @@ import android.widget.RemoteViewsService; import java.text.SimpleDateFormat; import java.util.Date; +import java.util.List; import de.luhmer.owncloudnewsreader.Constants; import de.luhmer.owncloudnewsreader.ListView.SubscriptionExpandableListAdapter; import de.luhmer.owncloudnewsreader.R; -import de.luhmer.owncloudnewsreader.database.DatabaseConnection; import de.luhmer.owncloudnewsreader.database.DatabaseConnection.SORT_DIRECTION; +import de.luhmer.owncloudnewsreader.database.DatabaseConnectionOrm; +import de.luhmer.owncloudnewsreader.database.model.RssItem; @TargetApi(Build.VERSION_CODES.HONEYCOMB) public class WidgetTodoViewsFactory implements RemoteViewsService.RemoteViewsFactory { private static final String TAG = "WidgetTodoViewsFactory"; - DatabaseConnection dbConn; - Cursor cursor; + DatabaseConnectionOrm dbConn; + List<RssItem> rssItems; private Context context = null; private int appWidgetId; @@ -65,19 +66,19 @@ public class WidgetTodoViewsFactory implements RemoteViewsService.RemoteViewsFac if(Constants.debugModeWidget) Log.d(TAG, "onCreate"); - dbConn = new DatabaseConnection(context); + dbConn = new DatabaseConnectionOrm(context); //onDataSetChanged(); } @Override public void onDestroy() { - if(dbConn != null) - dbConn.closeDatabase(); + //if(dbConn != null) + //dbConn.closeDatabase(); } @Override public int getCount() { - return cursor.getCount(); + return rssItems.size(); } // Given the position (index) of a WidgetItem in the array, use the item's text value in @@ -86,25 +87,22 @@ public class WidgetTodoViewsFactory implements RemoteViewsService.RemoteViewsFac public RemoteViews getViewAt(int position) { //RemoteViews rv = new RemoteViews(context.getPackageName(), android.R.layout.simple_list_item_2); RemoteViews rv = new RemoteViews(context.getPackageName(), R.layout.widget_item); - cursor.moveToPosition(position); + RssItem rssItem = rssItems.get(position); try { - //Cursor feedCursor = dbConn.getFeedByFeedID(cursor.getString(cursor.getColumnIndex(DatabaseConnection.RSS_ITEM_RSSITEM_ID))); - Cursor feedCursor = dbConn.getFeedByDbID(cursor.getString(cursor.getColumnIndex(DatabaseConnection.RSS_ITEM_SUBSCRIPTION_ID))); - feedCursor.moveToFirst(); - String header = feedCursor.getString(feedCursor.getColumnIndex(DatabaseConnection.SUBSCRIPTION_HEADERTEXT)).trim(); - String colorString = dbConn.getAvgColourOfFeedByDbId(cursor.getString(cursor.getColumnIndex(DatabaseConnection.RSS_ITEM_SUBSCRIPTION_ID))); - feedCursor.close(); - - String authorOfArticle = cursor.getString(cursor.getColumnIndex(DatabaseConnection.RSS_ITEM_AUTHOR)); + + String header = rssItem.getFeed().getFeedTitle(); + String colorString = rssItem.getFeed().getAvgColour(); + + String authorOfArticle = rssItem.getAuthor(); header += authorOfArticle == null ? "" : " - " + authorOfArticle.trim(); - String title = Html.fromHtml(cursor.getString(cursor.getColumnIndex(DatabaseConnection.RSS_ITEM_TITLE))).toString().trim(); - String id = cursor.getString(cursor.getColumnIndex(DatabaseConnection.RSS_ITEM_RSSITEM_ID)); + String title = Html.fromHtml(rssItem.getTitle()).toString(); + long id = rssItem.getId(); //rv.setTextViewText(android.R.id.text1, header); //rv.setTextViewText(android.R.id.text2, title); - Date date = new Date(cursor.getLong(cursor.getColumnIndex(DatabaseConnection.RSS_ITEM_PUBDATE))); + Date date = rssItem.getPubDate(); String dateString = ""; if(date != null) { @@ -126,7 +124,7 @@ public class WidgetTodoViewsFactory implements RemoteViewsService.RemoteViewsFac //Get a fresh new intent Intent ei = new Intent(); //Load it with whatever extra you want - ei.putExtra(WidgetProvider.UID_TODO, id); + ei.putExtra(WidgetProvider.RSS_ITEM_ID, id); //Set it on the list remote view rv.setOnClickFillInIntent(R.id.ll_root_view_widget_row, ei); } catch(Exception ex) { @@ -164,7 +162,6 @@ public class WidgetTodoViewsFactory implements RemoteViewsService.RemoteViewsFac Log.d(TAG, "DataSetChanged - WidgetID: " + appWidgetId); - cursor = dbConn.getAllItemsForFolder(SubscriptionExpandableListAdapter.SPECIAL_FOLDERS.ALL_UNREAD_ITEMS.getValueString(), false, SORT_DIRECTION.desc); - cursor.moveToFirst(); + rssItems = dbConn.getListOfAllItemsForFolder(SubscriptionExpandableListAdapter.SPECIAL_FOLDERS.ALL_UNREAD_ITEMS.getValue(), false, SORT_DIRECTION.desc); } } diff --git a/News-Android-App/src/main/res/drawable-hdpi/content_discard.png b/News-Android-App/src/main/res/drawable-hdpi/content_discard.png Binary files differnew file mode 100644 index 00000000..e9ce89e0 --- /dev/null +++ b/News-Android-App/src/main/res/drawable-hdpi/content_discard.png diff --git a/News-Android-App/src/main/res/drawable-mdpi/content_discard.png b/News-Android-App/src/main/res/drawable-mdpi/content_discard.png Binary files differnew file mode 100644 index 00000000..cedb1085 --- /dev/null +++ b/News-Android-App/src/main/res/drawable-mdpi/content_discard.png diff --git a/News-Android-App/src/main/res/drawable-xhdpi/content_discard.png b/News-Android-App/src/main/res/drawable-xhdpi/content_discard.png Binary files differnew file mode 100644 index 00000000..98c73da1 --- /dev/null +++ b/News-Android-App/src/main/res/drawable-xhdpi/content_discard.png diff --git a/News-Android-App/src/main/res/layout/activity_new_feed.xml b/News-Android-App/src/main/res/layout/activity_new_feed.xml index fa80b4cc..f01d5996 100644 --- a/News-Android-App/src/main/res/layout/activity_new_feed.xml +++ b/News-Android-App/src/main/res/layout/activity_new_feed.xml @@ -23,8 +23,7 @@ <ScrollView android:id="@+id/feed_form" android:layout_width="match_parent" - android:layout_height="match_parent" - > + android:layout_height="match_parent"> <LinearLayout android:id="@+id/new_feed_form" diff --git a/News-Android-App/src/main/res/layout/fragment_newsreader_detail.xml b/News-Android-App/src/main/res/layout/fragment_newsreader_detail.xml index 7b822971..91cac5aa 100644 --- a/News-Android-App/src/main/res/layout/fragment_newsreader_detail.xml +++ b/News-Android-App/src/main/res/layout/fragment_newsreader_detail.xml @@ -2,6 +2,16 @@ android:layout_width="match_parent" android:layout_height="match_parent"> + + <de.luhmer.owncloudnewsreader.ListView.BlockingListView + android:id="@android:id/list" + style="?android:attr/textAppearanceLarge" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:divider="@null" + android:visibility="gone" + android:dividerHeight="0dp" /> + <TextView android:id="@+id/tv_no_items_available" android:layout_width="match_parent" @@ -11,15 +21,17 @@ android:visibility="gone" android:textSize="18sp" /> - <de.luhmer.owncloudnewsreader.ListView.BlockingListView - android:id="@android:id/list" - style="?android:attr/textAppearanceLarge" - android:layout_width="match_parent" - android:layout_height="match_parent" - android:divider="@null" - android:dividerHeight="0dp" /> - <!-- android:textIsSelectable="true" --> + <ProgressBar + android:id="@+id/pb_loading" + style="?android:attr/progressBarStyleLarge" + android:layout_width="60dp" + android:layout_height="wrap_content" + android:layout_gravity="center" + android:indeterminate="true" /> + + + <!-- android:textIsSelectable="true" --> <!-- android:padding="16dp" --> </FrameLayout> diff --git a/News-Android-App/src/main/res/layout/expandable_list_layout.xml b/News-Android-App/src/main/res/layout/fragment_newsreader_list.xml index d3ce8e1d..d8a39d4f 100644 --- a/News-Android-App/src/main/res/layout/expandable_list_layout.xml +++ b/News-Android-App/src/main/res/layout/fragment_newsreader_list.xml @@ -15,7 +15,7 @@ - <uk.co.senab.actionbarpulltorefresh.extras.actionbarsherlock.PullToRefreshLayout + <android.support.v4.widget.SwipeRefreshLayout android:id="@+id/ptr_layout" android:layout_width="match_parent" android:layout_height="match_parent"> @@ -37,7 +37,7 @@ --> - </uk.co.senab.actionbarpulltorefresh.extras.actionbarsherlock.PullToRefreshLayout> + </android.support.v4.widget.SwipeRefreshLayout> <!-- </com.handmark.pulltorefresh.library.PullToRefreshScrollView>--> <RelativeLayout diff --git a/News-Android-App/src/main/res/layout/subscription_detail_list_item_extended.xml b/News-Android-App/src/main/res/layout/subscription_detail_list_item_extended.xml index fc48887f..09eb0a49 100644 --- a/News-Android-App/src/main/res/layout/subscription_detail_list_item_extended.xml +++ b/News-Android-App/src/main/res/layout/subscription_detail_list_item_extended.xml @@ -13,7 +13,7 @@ android:id="@+id/color_line_feed" android:layout_width="@dimen/color_bar_of_feeds" android:layout_height="match_parent" - android:background="@color/abs__background_holo_dark"/> + android:background="@color/slider_listview_background_color_dark_theme"/> <LinearLayout diff --git a/News-Android-App/src/main/res/layout/subscription_detail_list_item_extended_webview.xml b/News-Android-App/src/main/res/layout/subscription_detail_list_item_extended_webview.xml index bf7da059..eb70ae2a 100644 --- a/News-Android-App/src/main/res/layout/subscription_detail_list_item_extended_webview.xml +++ b/News-Android-App/src/main/res/layout/subscription_detail_list_item_extended_webview.xml @@ -20,7 +20,7 @@ android:id="@+id/color_line_feed" android:layout_width="@dimen/color_bar_of_feeds" android:layout_height="fill_parent" - android:background="@color/abs__background_holo_dark"/> + android:background="@color/slider_listview_background_color_dark_theme"/> <com.devspark.robototextview.widget.RobotoTextView android:id="@+id/tv_clickHereToOpen" diff --git a/News-Android-App/src/main/res/layout/subscription_detail_list_item_simple.xml b/News-Android-App/src/main/res/layout/subscription_detail_list_item_simple.xml index 44f0eede..38c6c0d6 100644 --- a/News-Android-App/src/main/res/layout/subscription_detail_list_item_simple.xml +++ b/News-Android-App/src/main/res/layout/subscription_detail_list_item_simple.xml @@ -10,7 +10,7 @@ android:id="@+id/color_line_feed" android:layout_width="@dimen/color_bar_of_feeds" android:layout_height="match_parent" - android:background="@color/abs__background_holo_dark"/> + android:background="@color/slider_listview_background_color_dark_theme"/> <LinearLayout android:layout_width="match_parent" diff --git a/News-Android-App/src/main/res/menu/news_reader.xml b/News-Android-App/src/main/res/menu/news_reader.xml index 2ae6ef77..4b988925 100644 --- a/News-Android-App/src/main/res/menu/news_reader.xml +++ b/News-Android-App/src/main/res/menu/news_reader.xml @@ -1,61 +1,62 @@ -<menu xmlns:android="http://schemas.android.com/apk/res/android" > +<menu xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:app="http://schemas.android.com/apk/res-auto"> <item android:id="@+id/menu_update" android:title="@string/menu_update" android:icon="@drawable/ic_menu_refresh" - android:showAsAction="always" /> + app:showAsAction="always" /> <item android:id="@+id/menu_StartImageCaching" android:title="@string/menu_StartImageCaching" android:orderInCategory="95" - android:showAsAction="never" /> + app:showAsAction="never" /> <item android:id="@+id/menu_markAllAsRead" - android:showAsAction="never" + app:showAsAction="never" android:orderInCategory="96" android:title="@string/menu_markAllAsRead"/> <item android:id="@+id/menu_downloadMoreItems" - android:showAsAction="never" + app:showAsAction="never" android:orderInCategory="97" android:title="@string/menu_downloadMoreItems"/> <item android:id="@+id/action_settings" android:orderInCategory="98" - android:showAsAction="never" + app:showAsAction="never" android:title="@string/action_settings"/> <item android:id="@+id/action_sync_settings" android:orderInCategory="99" - android:showAsAction="never" + app:showAsAction="never" android:title="@string/action_sync_settings"/> <item android:id="@+id/action_login" android:orderInCategory="100" - android:showAsAction="never" + app:showAsAction="never" android:title="@string/action_login"/> <item android:id="@+id/action_add_new_feed" android:orderInCategory="101" - android:showAsAction="never" + app:showAsAction="never" android:title="@string/action_add_new_feed"/> <item android:id="@+id/menu_About_Changelog" - android:showAsAction="never" + app:showAsAction="never" android:orderInCategory="102" android:title="@string/menu_About_Changelog"/> <item android:id="@+id/menu_CreateDatabaseDump" - android:showAsAction="never" + app:showAsAction="never" android:orderInCategory="103" android:title="Create Database Dump" android:visible="false"/> diff --git a/News-Android-App/src/main/res/values/styles.xml b/News-Android-App/src/main/res/values/styles.xml index 4bc862e8..404a6b74 100644 --- a/News-Android-App/src/main/res/values/styles.xml +++ b/News-Android-App/src/main/res/values/styles.xml @@ -17,10 +17,10 @@ <!-- <style name="AppBaseTheme" parent="android:Theme.Light"></style> --> <!-- <style name="AppBaseTheme" parent="@style/android:Theme.Material"></style> --> - <style name="AppBaseTheme" parent="@style/Theme.Sherlock"></style> <!-- Application theme. --> - <style name="AppTheme" parent="AppBaseTheme"> + <!-- Base application theme. --> + <style name="AppTheme" parent="@style/Theme.AppCompat.Light.DarkActionBar"> <!-- All customizations that are NOT specific to a particular API-level can go here. --> </style> |