diff --git a/.gitignore b/.gitignore index 2842d7c..56b1517 100644 --- a/.gitignore +++ b/.gitignore @@ -216,6 +216,4 @@ gradle-app.setting release/ -crowdin.properties - -publish-version.sh \ No newline at end of file +crowdin.properties \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index b7840ec..62a0f72 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +**1.7.x** + +- Closing #1. Initial article caching. + **1.6.x** - Handling hidden tags. diff --git a/app/build.gradle b/app/build.gradle index 9ba9726..94449db 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -56,6 +56,13 @@ android { // tests testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" + + javaCompileOptions { + annotationProcessorOptions { + arguments = ["room.schemaLocation": + "$projectDir/schemas".toString()] + } + } } buildTypes { release { diff --git a/app/schemas/apps.amine.bou.readerforselfoss.persistence.database.AppDatabase/1.json b/app/schemas/apps.amine.bou.readerforselfoss.persistence.database.AppDatabase/1.json new file mode 100644 index 0000000..b478c9e --- /dev/null +++ b/app/schemas/apps.amine.bou.readerforselfoss.persistence.database.AppDatabase/1.json @@ -0,0 +1,96 @@ +{ + "formatVersion": 1, + "database": { + "version": 1, + "identityHash": "08ca537d7ac9d4dd216e8e395d70801a", + "entities": [ + { + "tableName": "tags", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`tag` TEXT NOT NULL, `color` TEXT NOT NULL, `unread` INTEGER NOT NULL, PRIMARY KEY(`tag`))", + "fields": [ + { + "fieldPath": "tag", + "columnName": "tag", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "color", + "columnName": "color", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "unread", + "columnName": "unread", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "tag" + ], + "autoGenerate": false + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "sources", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `title` TEXT NOT NULL, `tags` TEXT NOT NULL, `spout` TEXT NOT NULL, `error` TEXT NOT NULL, `icon` TEXT NOT NULL, PRIMARY KEY(`id`))", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "title", + "columnName": "title", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "tags", + "columnName": "tags", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "spout", + "columnName": "spout", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "error", + "columnName": "error", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "icon", + "columnName": "icon", + "affinity": "TEXT", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": false + }, + "indices": [], + "foreignKeys": [] + } + ], + "views": [], + "setupQueries": [ + "CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)", + "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, \"08ca537d7ac9d4dd216e8e395d70801a\")" + ] + } +} \ No newline at end of file diff --git a/app/schemas/apps.amine.bou.readerforselfoss.persistence.database.AppDatabase/2.json b/app/schemas/apps.amine.bou.readerforselfoss.persistence.database.AppDatabase/2.json new file mode 100644 index 0000000..c9d43bc --- /dev/null +++ b/app/schemas/apps.amine.bou.readerforselfoss.persistence.database.AppDatabase/2.json @@ -0,0 +1,176 @@ +{ + "formatVersion": 1, + "database": { + "version": 2, + "identityHash": "6fa6944b04100d68eab61039876a8804", + "entities": [ + { + "tableName": "tags", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`tag` TEXT NOT NULL, `color` TEXT NOT NULL, `unread` INTEGER NOT NULL, PRIMARY KEY(`tag`))", + "fields": [ + { + "fieldPath": "tag", + "columnName": "tag", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "color", + "columnName": "color", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "unread", + "columnName": "unread", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "tag" + ], + "autoGenerate": false + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "sources", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `title` TEXT NOT NULL, `tags` TEXT NOT NULL, `spout` TEXT NOT NULL, `error` TEXT NOT NULL, `icon` TEXT NOT NULL, PRIMARY KEY(`id`))", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "title", + "columnName": "title", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "tags", + "columnName": "tags", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "spout", + "columnName": "spout", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "error", + "columnName": "error", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "icon", + "columnName": "icon", + "affinity": "TEXT", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": false + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "items", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `datetime` TEXT NOT NULL, `title` TEXT NOT NULL, `content` TEXT NOT NULL, `unread` INTEGER NOT NULL, `starred` INTEGER NOT NULL, `thumbnail` TEXT NOT NULL, `icon` TEXT NOT NULL, `link` TEXT NOT NULL, `sourcetitle` TEXT NOT NULL, `tags` TEXT NOT NULL, PRIMARY KEY(`id`))", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "datetime", + "columnName": "datetime", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "title", + "columnName": "title", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "content", + "columnName": "content", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "unread", + "columnName": "unread", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "starred", + "columnName": "starred", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "thumbnail", + "columnName": "thumbnail", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "icon", + "columnName": "icon", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "link", + "columnName": "link", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "sourcetitle", + "columnName": "sourcetitle", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "tags", + "columnName": "tags", + "affinity": "TEXT", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": false + }, + "indices": [], + "foreignKeys": [] + } + ], + "views": [], + "setupQueries": [ + "CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)", + "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, \"6fa6944b04100d68eab61039876a8804\")" + ] + } +} \ No newline at end of file diff --git a/app/src/main/java/apps/amine/bou/readerforselfoss/HomeActivity.kt b/app/src/main/java/apps/amine/bou/readerforselfoss/HomeActivity.kt index 76590a0..7973ce9 100644 --- a/app/src/main/java/apps/amine/bou/readerforselfoss/HomeActivity.kt +++ b/app/src/main/java/apps/amine/bou/readerforselfoss/HomeActivity.kt @@ -35,6 +35,7 @@ import apps.amine.bou.readerforselfoss.api.selfoss.Stats import apps.amine.bou.readerforselfoss.api.selfoss.SuccessResponse import apps.amine.bou.readerforselfoss.api.selfoss.Tag import apps.amine.bou.readerforselfoss.persistence.database.AppDatabase +import apps.amine.bou.readerforselfoss.persistence.migrations.MIGRATION_1_2 import apps.amine.bou.readerforselfoss.settings.SettingsActivity import apps.amine.bou.readerforselfoss.themes.AppColors import apps.amine.bou.readerforselfoss.themes.Toppings @@ -45,6 +46,7 @@ import apps.amine.bou.readerforselfoss.utils.customtabs.CustomTabActivityHelper import apps.amine.bou.readerforselfoss.utils.drawer.CustomUrlPrimaryDrawerItem import apps.amine.bou.readerforselfoss.utils.flattenTags import apps.amine.bou.readerforselfoss.utils.longHash +import apps.amine.bou.readerforselfoss.utils.maybeHandleSilentException import apps.amine.bou.readerforselfoss.utils.persistence.toEntity import apps.amine.bou.readerforselfoss.utils.persistence.toView import co.zsmb.materialdrawerkt.builders.accountHeader @@ -68,6 +70,7 @@ import com.mikepenz.materialdrawer.model.PrimaryDrawerItem import com.mikepenz.materialdrawer.model.SecondaryDrawerItem import kotlinx.android.synthetic.main.activity_home.* import kotlinx.android.synthetic.main.fragment_article.* +import org.acra.ACRA import retrofit2.Call import retrofit2.Callback import retrofit2.Response @@ -104,6 +107,7 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener { private var displayAccountHeader: Boolean = false private var infiniteScroll: Boolean = false private var lastFetchDone: Boolean = false + private var itemsCaching: Boolean = false private var hiddenTags: List = emptyList() private lateinit var tabNewBadge: TextBadgeItem @@ -153,8 +157,8 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener { db = Room.databaseBuilder( applicationContext, - AppDatabase::class.java!!, "selfoss-database" - ).build() + AppDatabase::class.java, "selfoss-database" + ).addMigrations(MIGRATION_1_2).build() customTabActivityHelper = CustomTabActivityHelper() @@ -177,24 +181,6 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener { handleSwipeRefreshLayout() } - private fun handleGDPRDialog(GDPRShown: Boolean) { - val sharedEditor = sharedPref.edit() - if (!GDPRShown) { - val alertDialog = AlertDialog.Builder(this).create() - alertDialog.setTitle(getString(R.string.gdpr_dialog_title)) - alertDialog.setMessage(getString(R.string.gdpr_dialog_message)) - alertDialog.setButton( - AlertDialog.BUTTON_NEUTRAL, - "OK" - ) { dialog, _ -> - sharedEditor.putBoolean("GDPR_shown", true) - sharedEditor.commit() - dialog.dismiss() - } - alertDialog.show() - } - } - private fun handleSwipeRefreshLayout() { swipeRefreshLayout.setColorSchemeResources( R.color.refresh_progress_1, @@ -347,9 +333,33 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener { getElementsAccordingToTab() + handleGDPRDialog(sharedPref.getBoolean("GDPR_shown", false)) } + private fun getAndStoreAllItems() { + api.allItems().enqueue(object : Callback> { + override fun onFailure(call: Call>, t: Throwable) { + } + + override fun onResponse( + call: Call>, + response: Response> + ) { + thread { + if (response.body() != null) { + val apiItems = (response.body() as ArrayList).filter { + maybeTagFilter != null || filter(it.tags) + } as ArrayList + db.itemsDao().deleteAllItems() + db.itemsDao() + .insertAllItems(*(apiItems.map { it.toEntity() }).toTypedArray()) + } + } + } + }) + } + override fun onStop() { super.onStop() customTabActivityHelper.unbindCustomTabsService(this) @@ -368,6 +378,7 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener { userIdentifier = sharedPref.getString("unique_id", "") displayAccountHeader = sharedPref.getBoolean("account_header_displaying", false) infiniteScroll = sharedPref.getBoolean("infinite_loading", false) + itemsCaching = sharedPref.getBoolean("items_caching", false) hiddenTags = if (sharedPref.getString("hidden_tags", "").isNotEmpty()) { sharedPref.getString("hidden_tags", "").replace("\\s".toRegex(), "").split(",") } else { @@ -726,8 +737,10 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener { thread { var drawerData = DrawerData(db.drawerDataDao().tags().map { it.toView() }, db.drawerDataDao().sources().map { it.toView() }) - handleDrawerData(drawerData, loadedFromCache = true) - drawerApiCalls(drawerData) + runOnUiThread { + handleDrawerData(drawerData, loadedFromCache = true) + drawerApiCalls(drawerData) + } } } @@ -817,7 +830,7 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener { private fun handleInfiniteScroll() { recyclerViewScrollListener = object : RecyclerView.OnScrollListener() { override fun onScrolled(localRecycler: RecyclerView, dx: Int, dy: Int) { - if (localRecycler != null && dy > 0) { + if (dy > 0) { val manager = recyclerView.layoutManager val lastVisibleItem: Int = when (manager) { is StaggeredGridLayoutManager -> manager.findLastCompletelyVisibleItemPositions( @@ -851,6 +864,15 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener { appendResults: Boolean = false, offsetOverride: Int? = null ) { + fun doGetAccordingToTab() { + when (elementsShown) { + UNREAD_SHOWN -> getUnRead(appendResults) + READ_SHOWN -> getRead(appendResults) + FAV_SHOWN -> getStarred(appendResults) + else -> getUnRead(appendResults) + } + } + offset = if (appendResults && offsetOverride === null) { (offset + itemsNumber) } else { @@ -858,12 +880,35 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener { } firstVisible = if (appendResults) firstVisible else 0 - when (elementsShown) { - UNREAD_SHOWN -> getUnRead(appendResults) - READ_SHOWN -> getRead(appendResults) - FAV_SHOWN -> getStarred(appendResults) - else -> getUnRead(appendResults) + if (itemsCaching) { + + if (!swipeRefreshLayout.isRefreshing) { + swipeRefreshLayout.post { swipeRefreshLayout.isRefreshing = true } + } + + thread { + val dbItems = db.itemsDao().items().map { it.toView() } + runOnUiThread { + if (dbItems.isNotEmpty()) { + items = when (elementsShown) { + UNREAD_SHOWN -> ArrayList(dbItems.filter { it.unread }) + READ_SHOWN -> ArrayList(dbItems.filter { !it.unread }) + FAV_SHOWN -> ArrayList(dbItems.filter { it.starred }) + else -> ArrayList(dbItems.filter { it.unread }) + } + handleListResult() + doGetAccordingToTab() + } else { + doGetAccordingToTab() + getAndStoreAllItems() + } + } + } + + } else { + doGetAccordingToTab() } + } private fun filter(tags: String): Boolean { @@ -877,9 +922,10 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener { call: (String?, Long?, String?) -> Call> ) { fun handleItemsResponse(response: Response>) { - val shouldUpdate = (response.body() != items) + val shouldUpdate = (response.body()?.toSet() != items.toSet()) if (response.body() != null) { if (shouldUpdate) { + getAndStoreAllItems() items = response.body() as ArrayList items = items.filter { maybeTagFilter != null || filter(it.tags) @@ -899,9 +945,8 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener { allItems = ArrayList() } } - if (shouldUpdate) { - handleListResult(appendResults) - } + + handleListResult(appendResults) if (!appendResults) mayBeEmpty() swipeRefreshLayout.isRefreshing = false @@ -1178,7 +1223,7 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener { .toMap() fun readAllDebug(e: Throwable) { - // TODO: debug + ACRA.getErrorReporter().maybeHandleSilentException(e, this@HomeActivity) } if (ids.isNotEmpty()) { @@ -1266,8 +1311,26 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener { else -> badgeNew // if !elementsShown then unread are fetched. } - fun updateItems(adapterItems: ArrayList) { + private fun updateItems(adapterItems: ArrayList) { items = adapterItems } + + private fun handleGDPRDialog(GDPRShown: Boolean) { + val sharedEditor = sharedPref.edit() + if (!GDPRShown) { + val alertDialog = AlertDialog.Builder(this).create() + alertDialog.setTitle(getString(R.string.gdpr_dialog_title)) + alertDialog.setMessage(getString(R.string.gdpr_dialog_message)) + alertDialog.setButton( + AlertDialog.BUTTON_NEUTRAL, + "OK" + ) { dialog, _ -> + sharedEditor.putBoolean("GDPR_shown", true) + sharedEditor.commit() + dialog.dismiss() + } + alertDialog.show() + } + } } diff --git a/app/src/main/java/apps/amine/bou/readerforselfoss/api/selfoss/SelfossModels.kt b/app/src/main/java/apps/amine/bou/readerforselfoss/api/selfoss/SelfossModels.kt index 1b69670..edb8935 100644 --- a/app/src/main/java/apps/amine/bou/readerforselfoss/api/selfoss/SelfossModels.kt +++ b/app/src/main/java/apps/amine/bou/readerforselfoss/api/selfoss/SelfossModels.kt @@ -9,13 +9,13 @@ import apps.amine.bou.readerforselfoss.utils.Config import apps.amine.bou.readerforselfoss.utils.isEmptyOrNullOrNullString import com.google.gson.annotations.SerializedName -private fun constructUrl(config: Config?, path: String, file: String): String { - val baseUriBuilder = Uri.parse(config!!.baseUrl).buildUpon() - baseUriBuilder.appendPath(path).appendPath(file) - +private fun constructUrl(config: Config?, path: String, file: String?): String { return if (file.isEmptyOrNullOrNullString()) { "" } else { + val baseUriBuilder = Uri.parse(config!!.baseUrl).buildUpon() + baseUriBuilder.appendPath(path).appendPath(file) + baseUriBuilder.toString() } } diff --git a/app/src/main/java/apps/amine/bou/readerforselfoss/persistence/database/AppDatabase.kt b/app/src/main/java/apps/amine/bou/readerforselfoss/persistence/database/AppDatabase.kt index e8997da..f177ef5 100644 --- a/app/src/main/java/apps/amine/bou/readerforselfoss/persistence/database/AppDatabase.kt +++ b/app/src/main/java/apps/amine/bou/readerforselfoss/persistence/database/AppDatabase.kt @@ -8,7 +8,9 @@ import apps.amine.bou.readerforselfoss.persistence.entities.ItemEntity import apps.amine.bou.readerforselfoss.persistence.entities.SourceEntity import apps.amine.bou.readerforselfoss.persistence.entities.TagEntity -@Database(entities = [TagEntity::class, SourceEntity::class], version = 1) +@Database(entities = [TagEntity::class, SourceEntity::class, ItemEntity::class], version = 2) abstract class AppDatabase : RoomDatabase() { abstract fun drawerDataDao(): DrawerDataDao + + abstract fun itemsDao(): ItemsDao } \ No newline at end of file diff --git a/app/src/main/java/apps/amine/bou/readerforselfoss/persistence/migrations/migrations.kt b/app/src/main/java/apps/amine/bou/readerforselfoss/persistence/migrations/migrations.kt new file mode 100644 index 0000000..f939fbf --- /dev/null +++ b/app/src/main/java/apps/amine/bou/readerforselfoss/persistence/migrations/migrations.kt @@ -0,0 +1,10 @@ +package apps.amine.bou.readerforselfoss.persistence.migrations + +import androidx.sqlite.db.SupportSQLiteDatabase +import androidx.room.migration.Migration + +val MIGRATION_1_2: Migration = object : Migration(1, 2) { + override fun migrate(database: SupportSQLiteDatabase) { + database.execSQL("CREATE TABLE IF NOT EXISTS `items` (`id` TEXT NOT NULL, `datetime` TEXT NOT NULL, `title` TEXT NOT NULL, `content` TEXT NOT NULL, `unread` INTEGER NOT NULL, `starred` INTEGER NOT NULL, `thumbnail` TEXT NOT NULL, `icon` TEXT NOT NULL, `link` TEXT NOT NULL, `sourcetitle` TEXT NOT NULL, `tags` TEXT NOT NULL, PRIMARY KEY(`id`))") + } +} diff --git a/app/src/main/java/apps/amine/bou/readerforselfoss/settings/SettingsActivity.java b/app/src/main/java/apps/amine/bou/readerforselfoss/settings/SettingsActivity.java index ff1b573..69e8f48 100644 --- a/app/src/main/java/apps/amine/bou/readerforselfoss/settings/SettingsActivity.java +++ b/app/src/main/java/apps/amine/bou/readerforselfoss/settings/SettingsActivity.java @@ -135,6 +135,7 @@ public class SettingsActivity extends AppCompatPreferenceActivity { return PreferenceFragment.class.getName().equals(fragmentName) || GeneralPreferenceFragment.class.getName().equals(fragmentName) || ArticleViewerPreferenceFragment.class.getName().equals(fragmentName) + || OfflinePreferenceFragment.class.getName().equals(fragmentName) || DebugPreferenceFragment.class.getName().equals(fragmentName) || LinksPreferenceFragment.class.getName().equals(fragmentName) || ThemePreferenceFragment.class.getName().equals(fragmentName); @@ -363,6 +364,27 @@ public class SettingsActivity extends AppCompatPreferenceActivity { } } + @TargetApi(Build.VERSION_CODES.HONEYCOMB) + public static class OfflinePreferenceFragment extends PreferenceFragment { + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + addPreferencesFromResource(R.xml.pref_offline); + setHasOptionsMenu(true); + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + int id = item.getItemId(); + if (id == android.R.id.home) { + getActivity().finish(); + return true; + } + return super.onOptionsItemSelected(item); + } + } + + @Override public boolean onOptionsItemSelected(MenuItem item) { int id = item.getItemId(); diff --git a/app/src/main/res/drawable-hdpi/ic_signal_wifi_statusbar_not_connected.png b/app/src/main/res/drawable-hdpi/ic_signal_wifi_statusbar_not_connected.png new file mode 100644 index 0000000..f45bb36 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/ic_signal_wifi_statusbar_not_connected.png differ diff --git a/app/src/main/res/drawable-mdpi/ic_signal_wifi_statusbar_not_connected.png b/app/src/main/res/drawable-mdpi/ic_signal_wifi_statusbar_not_connected.png new file mode 100644 index 0000000..3f95269 Binary files /dev/null and b/app/src/main/res/drawable-mdpi/ic_signal_wifi_statusbar_not_connected.png differ diff --git a/app/src/main/res/drawable-xhdpi/ic_signal_wifi_statusbar_not_connected.png b/app/src/main/res/drawable-xhdpi/ic_signal_wifi_statusbar_not_connected.png new file mode 100644 index 0000000..7b965c1 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_signal_wifi_statusbar_not_connected.png differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_signal_wifi_statusbar_not_connected.png b/app/src/main/res/drawable-xxhdpi/ic_signal_wifi_statusbar_not_connected.png new file mode 100644 index 0000000..ea06e23 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_signal_wifi_statusbar_not_connected.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/ic_signal_wifi_statusbar_not_connected.png b/app/src/main/res/drawable-xxxhdpi/ic_signal_wifi_statusbar_not_connected.png new file mode 100644 index 0000000..b20c6d3 Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/ic_signal_wifi_statusbar_not_connected.png differ diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index f6dfdea..1ee6ad1 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -17,7 +17,6 @@ "Disconnect" "Settings" "General" - "Tap action on the articles" "Tag1, Tag2, Tag3" "Link" "Name" @@ -71,12 +70,8 @@ "Will use the internal browser instead of the article viewer" "Link handling" "Displaying" - "Actions" "The articles will be displayed as cards" "The articles will be displayed as a list" - "Displays the action bar under the article" - "When selecting an article it will open in your selected browser" "Update remote" "The remote is updated, you can now reload the articles list" Tags Sources edit - Couldn\'t cache your drawer data No tags loaded No sources loaded Loading … @@ -154,4 +148,8 @@ Enable logging Hidden Tags Mark item as unread + Offline and cache + Articles won\'t be saved to the device memory, and the app won\'t be usable offline. + Articles will be saved to the device memory and will be used for offline use. + Save items for offline use diff --git a/app/src/main/res/xml/pref_general.xml b/app/src/main/res/xml/pref_general.xml index fe807fb..10763e3 100644 --- a/app/src/main/res/xml/pref_general.xml +++ b/app/src/main/res/xml/pref_general.xml @@ -74,9 +74,5 @@ android:dependency="display_unread_count" android:key="display_other_count" android:title="@string/display_all_counts_title" /> - - - diff --git a/app/src/main/res/xml/pref_headers.xml b/app/src/main/res/xml/pref_headers.xml index 79c18aa..62fa491 100644 --- a/app/src/main/res/xml/pref_headers.xml +++ b/app/src/main/res/xml/pref_headers.xml @@ -11,6 +11,12 @@ android:icon="@drawable/ic_chrome_reader_mode_black_24" android:title="@string/pref_header_viewer"/> + +
+
+ + diff --git a/build.sh b/build.sh index 756d81b..b85d838 100755 --- a/build.sh +++ b/build.sh @@ -1,10 +1,15 @@ #!/bin/bash -BASE_VERSION="1.6" +BASE_VERSION="1.7" TODAYS_VERSION="1" VERSION="${BASE_VERSION//./}$(date '+%y%m%j')$TODAYS_VERSION" -./version.sh ${VERSION} $@ +./version.sh ${VERSION} $1 -./publish-version.sh ${VERSION} +if [[ "$@" == *'--publish'* ]] +then + ./publish-version.sh ${VERSION} +else + echo "Did not publish. If you wanted to do so, call the script with \"--publish\"." +fi diff --git a/publish-version.sh b/publish-version.sh new file mode 100755 index 0000000..c81add5 --- /dev/null +++ b/publish-version.sh @@ -0,0 +1,9 @@ +#!/bin/bash + +rm -f version.txt +printf "versionName=$1-github\nversionCode=$1" >> version.txt + +# You'll need to change server as your server and define a VERSION_PATH. +scp version.txt server:$VERSION_PATH + +rm version.txt