Compare commits
	
		
			10 Commits
		
	
	
		
			v171810302
			...
			v171811307
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|  | fec6683701 | ||
|  | 1549edb647 | ||
|  | 3de48ba162 | ||
|  | a2a3d6f1a7 | ||
|  | ccab2c7648 | ||
|  | 880dd1db5c | ||
|  | ed18fea356 | ||
|  | 9816b20bf6 | ||
|  | 0bb2195bff | ||
|  | ab2d0c4036 | 
| @@ -4,6 +4,8 @@ | ||||
|  | ||||
| - Closing #228 by removing the list action bar. Action buttons are exclusively on the card view from now on. | ||||
|  | ||||
| - Closing #38. Only doing api calls on network available. | ||||
|  | ||||
| **1.6.x** | ||||
|  | ||||
| - Handling hidden tags. | ||||
|   | ||||
| @@ -160,6 +160,8 @@ dependencies { | ||||
|  | ||||
|     implementation "androidx.room:room-runtime:$room_version" | ||||
|     kapt "androidx.room:room-compiler:$room_version" | ||||
|  | ||||
|     implementation "android.arch.work:work-runtime-ktx:$work_version" | ||||
| } | ||||
|  | ||||
|  | ||||
|   | ||||
| @@ -3,6 +3,7 @@ | ||||
|     package="apps.amine.bou.readerforselfoss" | ||||
|     xmlns:tools="http://schemas.android.com/tools"> | ||||
|  | ||||
|     <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> | ||||
|     <uses-permission android:name="android.permission.INTERNET" /> | ||||
|  | ||||
|     <application | ||||
|   | ||||
| @@ -25,6 +25,11 @@ import android.view.View | ||||
| import android.widget.Toast | ||||
| import androidx.room.Room | ||||
| import androidx.room.RoomDatabase | ||||
| import androidx.work.Constraints | ||||
| import androidx.work.ExistingPeriodicWorkPolicy | ||||
| import androidx.work.OneTimeWorkRequestBuilder | ||||
| import androidx.work.PeriodicWorkRequestBuilder | ||||
| import androidx.work.WorkManager | ||||
| import apps.amine.bou.readerforselfoss.adapters.ItemCardAdapter | ||||
| import apps.amine.bou.readerforselfoss.adapters.ItemListAdapter | ||||
| import apps.amine.bou.readerforselfoss.adapters.ItemsAdapter | ||||
| @@ -34,6 +39,7 @@ import apps.amine.bou.readerforselfoss.api.selfoss.Source | ||||
| 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.background.LoadingWorker | ||||
| 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 | ||||
| @@ -47,6 +53,7 @@ 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.network.isNetworkAccessible | ||||
| import apps.amine.bou.readerforselfoss.utils.persistence.toEntity | ||||
| import apps.amine.bou.readerforselfoss.utils.persistence.toView | ||||
| import co.zsmb.materialdrawerkt.builders.accountHeader | ||||
| @@ -74,6 +81,7 @@ import org.acra.ACRA | ||||
| import retrofit2.Call | ||||
| import retrofit2.Callback | ||||
| import retrofit2.Response | ||||
| import java.util.concurrent.TimeUnit | ||||
| import kotlin.concurrent.thread | ||||
|  | ||||
| class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener { | ||||
| @@ -179,6 +187,8 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener { | ||||
|         handleDrawer() | ||||
|  | ||||
|         handleSwipeRefreshLayout() | ||||
|  | ||||
|         handleRecurringTask() | ||||
|     } | ||||
|  | ||||
|     private fun handleSwipeRefreshLayout() { | ||||
| @@ -203,7 +213,7 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener { | ||||
|                     recyclerView: RecyclerView, | ||||
|                     viewHolder: RecyclerView.ViewHolder | ||||
|                 ): Int = | ||||
|                     if (elementsShown != UNREAD_SHOWN) { | ||||
|                     if (elementsShown != UNREAD_SHOWN || !this@HomeActivity.isNetworkAccessible(null)) { | ||||
|                         0 | ||||
|                     } else { | ||||
|                         super.getSwipeDirs( | ||||
| @@ -333,7 +343,6 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener { | ||||
|  | ||||
|         getElementsAccordingToTab() | ||||
|  | ||||
|  | ||||
|         handleGDPRDialog(sharedPref.getBoolean("GDPR_shown", false)) | ||||
|     } | ||||
|  | ||||
| @@ -696,6 +705,7 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener { | ||||
|             var sources: List<Source>? | ||||
|  | ||||
|             fun sourcesApiCall() { | ||||
|                 if (this@HomeActivity.isNetworkAccessible(null)) { | ||||
|                     api.sources.enqueue(object : Callback<List<Source>> { | ||||
|                         override fun onResponse( | ||||
|                             call: Call<List<Source>>?, | ||||
| @@ -712,7 +722,9 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener { | ||||
|                         } | ||||
|                     }) | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             if (this@HomeActivity.isNetworkAccessible(null)) { | ||||
|                 api.tags.enqueue(object : Callback<List<Tag>> { | ||||
|                     override fun onResponse( | ||||
|                         call: Call<List<Tag>>, | ||||
| @@ -727,6 +739,7 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener { | ||||
|                     } | ||||
|                 }) | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         drawer.addItem( | ||||
|             PrimaryDrawerItem().withName(getString(R.string.drawer_loading)).withSelectable( | ||||
| @@ -817,12 +830,52 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener { | ||||
|             override fun onTabSelected(position: Int) { | ||||
|                 offset = 0 | ||||
|                 lastFetchDone = false | ||||
|  | ||||
|                 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 (position) { | ||||
|                                     0 -> ArrayList(dbItems.filter { it.unread }) | ||||
|                                     1 -> ArrayList(dbItems.filter { !it.unread }) | ||||
|                                     2 -> ArrayList(dbItems.filter { it.starred }) | ||||
|                                     else -> ArrayList(dbItems.filter { it.unread }) | ||||
|                                 } | ||||
|                                 handleListResult() | ||||
|                                 when (position) { | ||||
|                                     0 -> getUnRead() | ||||
|                                     1 -> getRead() | ||||
|                                     2 -> getStarred() | ||||
|                                     else -> Unit | ||||
|                                 } | ||||
|                             } else { | ||||
|                                 if (this@HomeActivity.isNetworkAccessible(this@HomeActivity.findViewById(R.id.coordLayout))) { | ||||
|                                     when (position) { | ||||
|                                         0 -> getUnRead() | ||||
|                                         1 -> getRead() | ||||
|                                         2 -> getStarred() | ||||
|                                         else -> Unit | ||||
|                                     } | ||||
|                                     getAndStoreAllItems() | ||||
|                                 } | ||||
|                             } | ||||
|                         } | ||||
|                     } | ||||
|  | ||||
|                 } else { | ||||
|                     when (position) { | ||||
|                         0 -> getUnRead() | ||||
|                         1 -> getRead() | ||||
|                         2 -> getStarred() | ||||
|                         else -> Unit | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|         }) | ||||
|     } | ||||
| @@ -899,11 +952,13 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener { | ||||
|                         handleListResult() | ||||
|                         doGetAccordingToTab() | ||||
|                     } else { | ||||
|                         if (this@HomeActivity.isNetworkAccessible(this@HomeActivity.findViewById(R.id.coordLayout))) { | ||||
|                             doGetAccordingToTab() | ||||
|                             getAndStoreAllItems() | ||||
|                         } | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|         } else { | ||||
|             doGetAccordingToTab() | ||||
| @@ -956,6 +1011,7 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener { | ||||
|             swipeRefreshLayout.post { swipeRefreshLayout.isRefreshing = true } | ||||
|         } | ||||
|  | ||||
|         if (this@HomeActivity.isNetworkAccessible(this@HomeActivity.findViewById(R.id.coordLayout))) { | ||||
|             call(maybeTagFilter?.tag, maybeSourceFilter?.id?.toLong(), maybeSearchFilter) | ||||
|                 .enqueue(object : Callback<List<Item>> { | ||||
|                     override fun onResponse( | ||||
| @@ -974,6 +1030,9 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener { | ||||
|                         ).show() | ||||
|                     } | ||||
|                 }) | ||||
|         } else { | ||||
|             swipeRefreshLayout.post { swipeRefreshLayout.isRefreshing = false } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     private fun getUnRead(appendResults: Boolean = false) { | ||||
| @@ -1082,7 +1141,7 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener { | ||||
|     } | ||||
|  | ||||
|     private fun reloadBadges() { | ||||
|         if (displayUnreadCount || displayAllCount) { | ||||
|         if (this@HomeActivity.isNetworkAccessible(null) && (displayUnreadCount || displayAllCount)) { | ||||
|             api.stats.enqueue(object : Callback<Stats> { | ||||
|                 override fun onResponse(call: Call<Stats>, response: Response<Stats>) { | ||||
|                     if (response.body() != null) { | ||||
| @@ -1188,6 +1247,7 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener { | ||||
|     override fun onOptionsItemSelected(item: MenuItem): Boolean { | ||||
|         when (item.itemId) { | ||||
|             R.id.refresh -> { | ||||
|                 if (this@HomeActivity.isNetworkAccessible(null)) { | ||||
|                     needsConfirmation(R.string.menu_home_refresh, R.string.refresh_dialog_message) { | ||||
|                         api.update().enqueue(object : Callback<String> { | ||||
|                             override fun onResponse( | ||||
| @@ -1212,9 +1272,12 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener { | ||||
|                         Toast.makeText(this, R.string.refresh_in_progress, Toast.LENGTH_SHORT).show() | ||||
|                     } | ||||
|                     return true | ||||
|                 } else { | ||||
|                     return false | ||||
|                 } | ||||
|             } | ||||
|             R.id.readAll -> { | ||||
|                 if (elementsShown == UNREAD_SHOWN) { | ||||
|                 if (elementsShown == UNREAD_SHOWN && this@HomeActivity.isNetworkAccessible(null)) { | ||||
|                     needsConfirmation(R.string.readAll, R.string.markall_dialog_message) { | ||||
|                         swipeRefreshLayout.isRefreshing = false | ||||
|                         val ids = allItems.map { it.id } | ||||
| @@ -1334,5 +1397,25 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener { | ||||
|             alertDialog.show() | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     private fun handleRecurringTask() { | ||||
|         // TODO: add network type | ||||
|         val myConstraints = Constraints.Builder() | ||||
|             .setRequiresBatteryNotLow(true) | ||||
|             .setRequiresStorageNotLow(true) | ||||
|             .build() | ||||
|  | ||||
|         // TODO: make the time variable from the settings. | ||||
|         val backgroundWork = | ||||
|             PeriodicWorkRequestBuilder<LoadingWorker>(4, TimeUnit.HOURS) | ||||
|                 .setConstraints(myConstraints) | ||||
|                 .addTag("selfoss-loading") | ||||
|                 .build() | ||||
|  | ||||
|  | ||||
|         WorkManager.getInstance().enqueueUniquePeriodicWork("selfoss-loading", ExistingPeriodicWorkPolicy.REPLACE, backgroundWork) | ||||
|  | ||||
|  | ||||
|     } | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -21,6 +21,7 @@ import apps.amine.bou.readerforselfoss.themes.AppColors | ||||
| import apps.amine.bou.readerforselfoss.utils.Config | ||||
| import apps.amine.bou.readerforselfoss.utils.isBaseUrlValid | ||||
| import apps.amine.bou.readerforselfoss.utils.maybeHandleSilentException | ||||
| import apps.amine.bou.readerforselfoss.utils.network.isNetworkAccessible | ||||
| import com.mikepenz.aboutlibraries.Libs | ||||
| import com.mikepenz.aboutlibraries.LibsBuilder | ||||
| import kotlinx.android.synthetic.main.activity_login.* | ||||
| @@ -196,6 +197,8 @@ class LoginActivity : AppCompatActivity() { | ||||
|                 isWithSelfSignedCert, | ||||
|                 isWithSelfSignedCert | ||||
|             ) | ||||
|  | ||||
|             if (this@LoginActivity.isNetworkAccessible(this@LoginActivity.findViewById(R.id.loginForm))) { | ||||
|                 api.login().enqueue(object : Callback<SuccessResponse> { | ||||
|                     private fun preferenceError(t: Throwable) { | ||||
|                         editor.remove("url") | ||||
| @@ -235,6 +238,9 @@ class LoginActivity : AppCompatActivity() { | ||||
|                         preferenceError(t) | ||||
|                     } | ||||
|                 }) | ||||
|             } else { | ||||
|                 showProgress(false) | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|   | ||||
| @@ -24,6 +24,7 @@ import apps.amine.bou.readerforselfoss.themes.AppColors | ||||
| import apps.amine.bou.readerforselfoss.themes.Toppings | ||||
| import apps.amine.bou.readerforselfoss.transformers.DepthPageTransformer | ||||
| import apps.amine.bou.readerforselfoss.utils.maybeHandleSilentException | ||||
| import apps.amine.bou.readerforselfoss.utils.network.isNetworkAccessible | ||||
| import apps.amine.bou.readerforselfoss.utils.persistence.toEntity | ||||
| import apps.amine.bou.readerforselfoss.utils.succeeded | ||||
| import apps.amine.bou.readerforselfoss.utils.toggleStar | ||||
| @@ -103,7 +104,8 @@ class ReaderActivity : AppCompatActivity() { | ||||
|  | ||||
|         readItem(allItems[currentItem]) | ||||
|  | ||||
|         pager.adapter = ScreenSlidePagerAdapter(supportFragmentManager, AppColors(this@ReaderActivity)) | ||||
|         pager.adapter = | ||||
|                 ScreenSlidePagerAdapter(supportFragmentManager, AppColors(this@ReaderActivity)) | ||||
|         pager.currentItem = currentItem | ||||
|     } | ||||
|  | ||||
| @@ -132,7 +134,7 @@ class ReaderActivity : AppCompatActivity() { | ||||
|     } | ||||
|  | ||||
|     fun readItem(item: Item) { | ||||
|         if (markOnScroll) { | ||||
|         if (this@ReaderActivity.isNetworkAccessible(this@ReaderActivity.findViewById(R.id.reader_activity_view)) && markOnScroll) { | ||||
|             thread { | ||||
|                 db.itemsDao().delete(item.toEntity()) | ||||
|             } | ||||
| @@ -164,7 +166,8 @@ class ReaderActivity : AppCompatActivity() { | ||||
|                             db.itemsDao().insertAllItems(item.toEntity()) | ||||
|                         } | ||||
|                         if (debugReadingItems) { | ||||
|                             ACRA.getErrorReporter().maybeHandleSilentException(t, this@ReaderActivity) | ||||
|                             ACRA.getErrorReporter() | ||||
|                                 .maybeHandleSilentException(t, this@ReaderActivity) | ||||
|                         } | ||||
|                     } | ||||
|                 } | ||||
| @@ -191,7 +194,6 @@ class ReaderActivity : AppCompatActivity() { | ||||
|     private inner class ScreenSlidePagerAdapter(fm: FragmentManager, val appColors: AppColors) : | ||||
|         FragmentStatePagerAdapter(fm) { | ||||
|  | ||||
|  | ||||
|         override fun getCount(): Int { | ||||
|             return allItems.size | ||||
|         } | ||||
| @@ -203,7 +205,12 @@ class ReaderActivity : AppCompatActivity() { | ||||
|         override fun startUpdate(container: ViewGroup) { | ||||
|             super.startUpdate(container) | ||||
|  | ||||
|             container.background = ColorDrawable(ContextCompat.getColor(this@ReaderActivity, appColors.colorBackground)) | ||||
|             container.background = ColorDrawable( | ||||
|                 ContextCompat.getColor( | ||||
|                     this@ReaderActivity, | ||||
|                     appColors.colorBackground | ||||
|                 ) | ||||
|             ) | ||||
|         } | ||||
|     } | ||||
|  | ||||
| @@ -228,6 +235,7 @@ class ReaderActivity : AppCompatActivity() { | ||||
|                 return true | ||||
|             } | ||||
|             R.id.save -> { | ||||
|                 if (this@ReaderActivity.isNetworkAccessible(null)) { | ||||
|                     api.starrItem(allItems[pager.currentItem].id) | ||||
|                         .enqueue(object : Callback<SuccessResponse> { | ||||
|                             override fun onResponse( | ||||
| @@ -251,7 +259,9 @@ class ReaderActivity : AppCompatActivity() { | ||||
|                             } | ||||
|                         }) | ||||
|                 } | ||||
|             } | ||||
|             R.id.unsave -> { | ||||
|                 if (this@ReaderActivity.isNetworkAccessible(null)) { | ||||
|                     api.unstarrItem(allItems[pager.currentItem].id) | ||||
|                         .enqueue(object : Callback<SuccessResponse> { | ||||
|                             override fun onResponse( | ||||
| @@ -276,6 +286,7 @@ class ReaderActivity : AppCompatActivity() { | ||||
|                         }) | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|         return super.onOptionsItemSelected(item) | ||||
|     } | ||||
|  | ||||
|   | ||||
| @@ -13,6 +13,7 @@ import apps.amine.bou.readerforselfoss.api.selfoss.SelfossApi | ||||
| import apps.amine.bou.readerforselfoss.api.selfoss.Source | ||||
| import apps.amine.bou.readerforselfoss.themes.AppColors | ||||
| import apps.amine.bou.readerforselfoss.themes.Toppings | ||||
| import apps.amine.bou.readerforselfoss.utils.network.isNetworkAccessible | ||||
| import com.ftinc.scoop.Scoop | ||||
| import kotlinx.android.synthetic.main.activity_sources.* | ||||
| import retrofit2.Call | ||||
| @@ -66,6 +67,7 @@ class SourcesActivity : AppCompatActivity() { | ||||
|         recyclerView.setHasFixedSize(true) | ||||
|         recyclerView.layoutManager = mLayoutManager | ||||
|  | ||||
|         if (this@SourcesActivity.isNetworkAccessible(this@SourcesActivity.findViewById(R.id.recyclerView))) { | ||||
|             api.sources.enqueue(object : Callback<List<Source>> { | ||||
|                 override fun onResponse( | ||||
|                     call: Call<List<Source>>, | ||||
| @@ -94,6 +96,7 @@ class SourcesActivity : AppCompatActivity() { | ||||
|                     ).show() | ||||
|                 } | ||||
|             }) | ||||
|         } | ||||
|  | ||||
|         fab.setOnClickListener { | ||||
|             startActivity(Intent(this@SourcesActivity, AddSourceActivity::class.java)) | ||||
|   | ||||
| @@ -16,10 +16,12 @@ import apps.amine.bou.readerforselfoss.api.selfoss.SelfossApi | ||||
| import apps.amine.bou.readerforselfoss.api.selfoss.SuccessResponse | ||||
| import apps.amine.bou.readerforselfoss.persistence.database.AppDatabase | ||||
| import apps.amine.bou.readerforselfoss.themes.AppColors | ||||
| import apps.amine.bou.readerforselfoss.utils.LinkOnTouchListener | ||||
| import apps.amine.bou.readerforselfoss.utils.buildCustomTabsIntent | ||||
| import apps.amine.bou.readerforselfoss.utils.customtabs.CustomTabActivityHelper | ||||
| import apps.amine.bou.readerforselfoss.utils.glide.bitmapCenterCrop | ||||
| import apps.amine.bou.readerforselfoss.utils.glide.circularBitmapDrawable | ||||
| import apps.amine.bou.readerforselfoss.utils.network.isNetworkAccessible | ||||
| import apps.amine.bou.readerforselfoss.utils.openInBrowserAsNewTask | ||||
| import apps.amine.bou.readerforselfoss.utils.openItemUrl | ||||
| import apps.amine.bou.readerforselfoss.utils.shareLink | ||||
| @@ -65,6 +67,7 @@ class ItemCardAdapter( | ||||
|  | ||||
|         holder.mView.favButton.isLiked = itm.starred | ||||
|         holder.mView.title.text = Html.fromHtml(itm.title) | ||||
|         holder.mView.title.setOnTouchListener(LinkOnTouchListener()) | ||||
|  | ||||
|         holder.mView.title.setLinkTextColor(appColors.colorAccent) | ||||
|  | ||||
| @@ -115,6 +118,7 @@ class ItemCardAdapter( | ||||
|  | ||||
|             mView.favButton.setOnLikeListener(object : OnLikeListener { | ||||
|                 override fun liked(likeButton: LikeButton) { | ||||
|                     if (c.isNetworkAccessible(null)) { | ||||
|                         val (id) = items[adapterPosition] | ||||
|                         api.starrItem(id).enqueue(object : Callback<SuccessResponse> { | ||||
|                             override fun onResponse( | ||||
| @@ -136,8 +140,10 @@ class ItemCardAdapter( | ||||
|                             } | ||||
|                         }) | ||||
|                     } | ||||
|                 } | ||||
|  | ||||
|                 override fun unLiked(likeButton: LikeButton) { | ||||
|                     if (c.isNetworkAccessible(null)) { | ||||
|                         val (id) = items[adapterPosition] | ||||
|                         api.unstarrItem(id).enqueue(object : Callback<SuccessResponse> { | ||||
|                             override fun onResponse( | ||||
| @@ -159,6 +165,7 @@ class ItemCardAdapter( | ||||
|                             } | ||||
|                         }) | ||||
|                     } | ||||
|                 } | ||||
|             }) | ||||
|  | ||||
|             mView.shareBtn.setOnClickListener { | ||||
|   | ||||
| @@ -5,10 +5,14 @@ import android.content.Context | ||||
| import androidx.constraintlayout.widget.ConstraintLayout | ||||
| import androidx.recyclerview.widget.RecyclerView | ||||
| import android.text.Html | ||||
| import android.text.Spannable | ||||
| import android.text.style.ClickableSpan | ||||
| import android.util.TypedValue | ||||
| import android.view.LayoutInflater | ||||
| import android.view.MotionEvent | ||||
| import android.view.View | ||||
| import android.view.ViewGroup | ||||
| import android.widget.TextView | ||||
| import android.widget.Toast | ||||
| import apps.amine.bou.readerforselfoss.R | ||||
| import apps.amine.bou.readerforselfoss.api.selfoss.Item | ||||
| @@ -16,6 +20,7 @@ import apps.amine.bou.readerforselfoss.api.selfoss.SelfossApi | ||||
| import apps.amine.bou.readerforselfoss.api.selfoss.SuccessResponse | ||||
| import apps.amine.bou.readerforselfoss.persistence.database.AppDatabase | ||||
| import apps.amine.bou.readerforselfoss.themes.AppColors | ||||
| import apps.amine.bou.readerforselfoss.utils.LinkOnTouchListener | ||||
| import apps.amine.bou.readerforselfoss.utils.buildCustomTabsIntent | ||||
| import apps.amine.bou.readerforselfoss.utils.customtabs.CustomTabActivityHelper | ||||
| import apps.amine.bou.readerforselfoss.utils.glide.bitmapCenterCrop | ||||
| @@ -67,6 +72,8 @@ class ItemListAdapter( | ||||
|  | ||||
|         holder.mView.title.text = Html.fromHtml(itm.title) | ||||
|  | ||||
|         holder.mView.title.setOnTouchListener(LinkOnTouchListener()) | ||||
|  | ||||
|         holder.mView.title.setLinkTextColor(appColors.colorAccent) | ||||
|  | ||||
|         holder.mView.sourceTitleAndDate.text = itm.sourceAndDateText() | ||||
|   | ||||
| @@ -13,6 +13,7 @@ import apps.amine.bou.readerforselfoss.api.selfoss.SuccessResponse | ||||
| import apps.amine.bou.readerforselfoss.persistence.database.AppDatabase | ||||
| import apps.amine.bou.readerforselfoss.themes.AppColors | ||||
| import apps.amine.bou.readerforselfoss.utils.maybeHandleSilentException | ||||
| import apps.amine.bou.readerforselfoss.utils.network.isNetworkAccessible | ||||
| import apps.amine.bou.readerforselfoss.utils.persistence.toEntity | ||||
| import apps.amine.bou.readerforselfoss.utils.succeeded | ||||
| import org.acra.ACRA | ||||
| @@ -45,6 +46,7 @@ abstract class ItemsAdapter<VH : RecyclerView.ViewHolder?> : RecyclerView.Adapte | ||||
|                 Snackbar.LENGTH_LONG | ||||
|             ) | ||||
|             .setAction(R.string.undo_string) { | ||||
|                 if (app.isNetworkAccessible(null)) { | ||||
|                     items.add(position, i) | ||||
|                     thread { | ||||
|                         db.itemsDao().insertAllItems(i.toEntity()) | ||||
| @@ -70,6 +72,7 @@ abstract class ItemsAdapter<VH : RecyclerView.ViewHolder?> : RecyclerView.Adapte | ||||
|                         } | ||||
|                     }) | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|         val view = s.view | ||||
|         val tv: TextView = view.findViewById(com.google.android.material.R.id.snackbar_text) | ||||
| @@ -78,7 +81,7 @@ abstract class ItemsAdapter<VH : RecyclerView.ViewHolder?> : RecyclerView.Adapte | ||||
|     } | ||||
|  | ||||
|     fun removeItemAtIndex(position: Int) { | ||||
|  | ||||
|         if (app.isNetworkAccessible(null)) { | ||||
|             val i = items[position] | ||||
|  | ||||
|             items.remove(i) | ||||
| @@ -133,6 +136,7 @@ abstract class ItemsAdapter<VH : RecyclerView.ViewHolder?> : RecyclerView.Adapte | ||||
|                 } | ||||
|             }) | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     fun addItemAtIndex(item: Item, position: Int) { | ||||
|         items.add(position, item) | ||||
|   | ||||
| @@ -13,6 +13,7 @@ import apps.amine.bou.readerforselfoss.api.selfoss.SelfossApi | ||||
| import apps.amine.bou.readerforselfoss.api.selfoss.Source | ||||
| import apps.amine.bou.readerforselfoss.api.selfoss.SuccessResponse | ||||
| import apps.amine.bou.readerforselfoss.utils.glide.circularBitmapDrawable | ||||
| import apps.amine.bou.readerforselfoss.utils.network.isNetworkAccessible | ||||
| import apps.amine.bou.readerforselfoss.utils.toTextDrawableString | ||||
| import com.amulyakhare.textdrawable.TextDrawable | ||||
| import com.amulyakhare.textdrawable.util.ColorGenerator | ||||
| @@ -70,6 +71,7 @@ class SourcesListAdapter( | ||||
|             val deleteBtn: Button = mView.findViewById(R.id.deleteBtn) | ||||
|  | ||||
|             deleteBtn.setOnClickListener { | ||||
|                 if (c.isNetworkAccessible(null)) { | ||||
|                     val (id) = items[adapterPosition] | ||||
|                     api.deleteSource(id).enqueue(object : Callback<SuccessResponse> { | ||||
|                         override fun onResponse( | ||||
| @@ -101,3 +103,4 @@ class SourcesListAdapter( | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -21,7 +21,7 @@ import java.util.concurrent.ConcurrentHashMap | ||||
|  | ||||
| class SelfossApi( | ||||
|     c: Context, | ||||
|     callingActivity: Activity, | ||||
|     callingActivity: Activity?, | ||||
|     isWithSelfSignedCert: Boolean, | ||||
|     shouldLog: Boolean | ||||
| ) { | ||||
| @@ -91,9 +91,11 @@ class SelfossApi( | ||||
|                     .build() | ||||
|             service = retrofit.create(SelfossService::class.java) | ||||
|         } catch (e: IllegalArgumentException) { | ||||
|             if (callingActivity != null) { | ||||
|                 Config.logoutAndRedirect(c, callingActivity, config.settings.edit(), baseUrlFail = true) | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     fun login(): Call<SuccessResponse> = | ||||
|         service.loginToSelfoss(config.userLogin, config.userPassword) | ||||
|   | ||||
| @@ -0,0 +1,82 @@ | ||||
| package apps.amine.bou.readerforselfoss.background | ||||
|  | ||||
| import android.content.Context | ||||
| import android.preference.PreferenceManager | ||||
| import androidx.room.Room | ||||
| import androidx.work.Worker | ||||
| import androidx.work.WorkerParameters | ||||
| import apps.amine.bou.readerforselfoss.api.selfoss.Item | ||||
| import apps.amine.bou.readerforselfoss.api.selfoss.SelfossApi | ||||
| import apps.amine.bou.readerforselfoss.persistence.database.AppDatabase | ||||
| import apps.amine.bou.readerforselfoss.persistence.migrations.MIGRATION_1_2 | ||||
| import apps.amine.bou.readerforselfoss.utils.Config | ||||
| import apps.amine.bou.readerforselfoss.utils.persistence.toEntity | ||||
| import retrofit2.Call | ||||
| import retrofit2.Callback | ||||
| import retrofit2.Response | ||||
| import kotlin.concurrent.thread | ||||
| import android.app.NotificationManager | ||||
| import android.app.NotificationChannel | ||||
| import android.util.Log | ||||
| import androidx.core.app.NotificationCompat | ||||
| import apps.amine.bou.readerforselfoss.R | ||||
|  | ||||
| class LoadingWorker(val context: Context, params: WorkerParameters) : Worker(context, params) { | ||||
|  | ||||
|     override fun doWork(): Result { | ||||
|         val notificationManager = | ||||
|             applicationContext.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager | ||||
|  | ||||
|         //If on Oreo then notification required a notification channel. | ||||
|         if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) { | ||||
|             val channel = | ||||
|                 NotificationChannel("default", "Default", NotificationManager.IMPORTANCE_DEFAULT) | ||||
|             notificationManager.createNotificationChannel(channel) | ||||
|         } | ||||
|  | ||||
|         val notification = NotificationCompat.Builder(applicationContext, "default") | ||||
|             .setContentTitle("Loading") | ||||
|             .setContentText("Loading new items") | ||||
|             .setOngoing(true) | ||||
|             .setSmallIcon(R.mipmap.ic_launcher) | ||||
|  | ||||
|         notificationManager.notify(1, notification.build()) | ||||
|  | ||||
|         val settings = this.context.getSharedPreferences(Config.settingsName, Context.MODE_PRIVATE) | ||||
|         val sharedPref = PreferenceManager.getDefaultSharedPreferences(this.context) | ||||
|         val shouldLogEverything = sharedPref.getBoolean("should_log_everything", false) | ||||
|  | ||||
|         val db = Room.databaseBuilder( | ||||
|             applicationContext, | ||||
|             AppDatabase::class.java, "selfoss-database" | ||||
|         ).addMigrations(MIGRATION_1_2).build() | ||||
|  | ||||
|         val api = SelfossApi( | ||||
|             this.context, | ||||
|             null, | ||||
|             settings.getBoolean("isSelfSignedCert", false), | ||||
|             shouldLogEverything | ||||
|         ) | ||||
|         api.allItems().enqueue(object : Callback<List<Item>> { | ||||
|             override fun onFailure(call: Call<List<Item>>, t: Throwable) { | ||||
|                 notificationManager.cancel(1) | ||||
|             } | ||||
|  | ||||
|             override fun onResponse( | ||||
|                 call: Call<List<Item>>, | ||||
|                 response: Response<List<Item>> | ||||
|             ) { | ||||
|                 thread { | ||||
|                     if (response.body() != null) { | ||||
|                         val apiItems = (response.body() as ArrayList<Item>) | ||||
|                         db.itemsDao().deleteAllItems() | ||||
|                         db.itemsDao() | ||||
|                             .insertAllItems(*(apiItems.map { it.toEntity() }).toTypedArray()) | ||||
|                     } | ||||
|                     notificationManager.cancel(1) | ||||
|                 } | ||||
|             } | ||||
|         }) | ||||
|         return Result.SUCCESS | ||||
|     } | ||||
| } | ||||
| @@ -29,6 +29,7 @@ import apps.amine.bou.readerforselfoss.utils.buildCustomTabsIntent | ||||
| import apps.amine.bou.readerforselfoss.utils.customtabs.CustomTabActivityHelper | ||||
| import apps.amine.bou.readerforselfoss.utils.isEmptyOrNullOrNullString | ||||
| import apps.amine.bou.readerforselfoss.utils.maybeHandleSilentException | ||||
| import apps.amine.bou.readerforselfoss.utils.network.isNetworkAccessible | ||||
| import apps.amine.bou.readerforselfoss.utils.openItemUrl | ||||
| import apps.amine.bou.readerforselfoss.utils.shareLink | ||||
| import apps.amine.bou.readerforselfoss.utils.sourceAndDateText | ||||
| @@ -135,7 +136,8 @@ class ArticleFragment : Fragment() { | ||||
|                             false, | ||||
|                             activity!! | ||||
|                         ) | ||||
|                         R.id.unread_action -> api.unmarkItem(allItems[pageNumber.toInt()].id).enqueue( | ||||
|                         R.id.unread_action -> if ((context != null && context!!.isNetworkAccessible(null)) || context == null) { | ||||
|                             api.unmarkItem(allItems[pageNumber.toInt()].id).enqueue( | ||||
|                                 object : Callback<SuccessResponse> { | ||||
|                                     override fun onResponse( | ||||
|                                         call: Call<SuccessResponse>, | ||||
| @@ -164,6 +166,7 @@ class ArticleFragment : Fragment() { | ||||
|                                     } | ||||
|                                 } | ||||
|                             ) | ||||
|                         } | ||||
|                         else -> Unit | ||||
|                     } | ||||
|                 } | ||||
| @@ -212,6 +215,7 @@ class ArticleFragment : Fragment() { | ||||
|         customTabsIntent: CustomTabsIntent, | ||||
|         prefs: SharedPreferences | ||||
|     ) { | ||||
|         if ((context != null && context!!.isNetworkAccessible(null)) || context == null) { | ||||
|             rootView.progressBar.visibility = View.VISIBLE | ||||
|             val parser = MercuryApi( | ||||
|                 prefs.getBoolean("should_log_everything", false) | ||||
| @@ -303,6 +307,7 @@ class ArticleFragment : Fragment() { | ||||
|                 } | ||||
|             ) | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     private fun htmlToWebview(c: String, prefs: SharedPreferences) { | ||||
|         val stringColor = String.format("#%06X", 0xFFFFFF and appColors.colorAccent) | ||||
|   | ||||
| @@ -6,8 +6,13 @@ import android.content.Context | ||||
| import android.content.Intent | ||||
| import android.graphics.BitmapFactory | ||||
| import android.net.Uri | ||||
| import android.text.Spannable | ||||
| import android.text.style.ClickableSpan | ||||
| import androidx.browser.customtabs.CustomTabsIntent | ||||
| import android.util.Patterns | ||||
| import android.view.MotionEvent | ||||
| import android.view.View | ||||
| import android.widget.TextView | ||||
| import android.widget.Toast | ||||
| import apps.amine.bou.readerforselfoss.R | ||||
| import apps.amine.bou.readerforselfoss.ReaderActivity | ||||
| @@ -146,3 +151,40 @@ fun Context.openInBrowserAsNewTask(i: Item) { | ||||
|     intent.data = Uri.parse(i.getLinkDecoded().toStringUriWithHttp()) | ||||
|     startActivity(intent) | ||||
| } | ||||
|  | ||||
| class LinkOnTouchListener: View.OnTouchListener { | ||||
|     override fun onTouch(v: View?, event: MotionEvent?): Boolean { | ||||
|         var ret = false | ||||
|         val widget: TextView = v as TextView | ||||
|         val text: CharSequence = widget.text | ||||
|         val stext = Spannable.Factory.getInstance().newSpannable(text) | ||||
|  | ||||
|         val action = event!!.action | ||||
|  | ||||
|         if (action == MotionEvent.ACTION_UP || | ||||
|             action == MotionEvent.ACTION_DOWN) { | ||||
|             var x: Float = event.x | ||||
|             var y: Float = event.y | ||||
|  | ||||
|             x -= widget.totalPaddingLeft | ||||
|             y -= widget.totalPaddingTop | ||||
|  | ||||
|             x += widget.scrollX | ||||
|             y += widget.scrollY | ||||
|  | ||||
|             val layout = widget.layout | ||||
|             val line = layout.getLineForVertical(y.toInt()) | ||||
|             val off = layout.getOffsetForHorizontal(line, x) | ||||
|  | ||||
|             val link = stext.getSpans(off, off, ClickableSpan::class.java) | ||||
|  | ||||
|             if (link.isNotEmpty()) { | ||||
|                 if (action == MotionEvent.ACTION_UP) { | ||||
|                     link[0].onClick(widget) | ||||
|                 } | ||||
|                 ret = true | ||||
|             } | ||||
|         } | ||||
|         return ret | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -0,0 +1,41 @@ | ||||
| package apps.amine.bou.readerforselfoss.utils.network | ||||
|  | ||||
| import android.content.Context | ||||
| import android.graphics.Color | ||||
| import android.net.ConnectivityManager | ||||
| import android.net.NetworkInfo | ||||
| import android.view.View | ||||
| import android.widget.TextView | ||||
| import apps.amine.bou.readerforselfoss.R | ||||
| import com.google.android.material.snackbar.Snackbar | ||||
|  | ||||
| var snackBarShown = false | ||||
| var view: View? = null | ||||
|  | ||||
| fun Context.isNetworkAccessible(v: View?): Boolean { | ||||
|     val cm = this.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager | ||||
|     val activeNetwork: NetworkInfo? = cm.activeNetworkInfo | ||||
|     val networkIsAccessible = activeNetwork != null && activeNetwork.isConnectedOrConnecting | ||||
|  | ||||
|     if (v != null && !networkIsAccessible && (!snackBarShown || v != view)) { | ||||
|         view = v | ||||
|         val s = Snackbar | ||||
|             .make( | ||||
|                 v, | ||||
|                 R.string.no_network_connectivity, | ||||
|                 Snackbar.LENGTH_INDEFINITE | ||||
|             ) | ||||
|  | ||||
|         s.setAction(android.R.string.ok) { | ||||
|             snackBarShown = false | ||||
|             s.dismiss() | ||||
|         } | ||||
|  | ||||
|         val view = s.view | ||||
|         val tv: TextView = view.findViewById(com.google.android.material.R.id.snackbar_text) | ||||
|         tv.setTextColor(Color.WHITE) | ||||
|         s.show() | ||||
|         snackBarShown = true | ||||
|     } | ||||
|     return networkIsAccessible | ||||
| } | ||||
| @@ -2,6 +2,7 @@ | ||||
| <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" | ||||
|     xmlns:app="http://schemas.android.com/apk/res-auto" | ||||
|     android:layout_width="match_parent" | ||||
|     android:id="@+id/reader_activity_view" | ||||
|     android:layout_height="match_parent"> | ||||
|  | ||||
|     <com.google.android.material.appbar.AppBarLayout | ||||
|   | ||||
| @@ -69,7 +69,6 @@ | ||||
|                 app:layout_constraintLeft_toRightOf="@+id/sourceImage" | ||||
|                 app:layout_constraintRight_toRightOf="parent" | ||||
|                 app:layout_constraintTop_toTopOf="@+id/sourceImage" | ||||
|                 android:autoLink="web" | ||||
|                 tools:text="Titre" /> | ||||
|  | ||||
|             <TextView | ||||
|   | ||||
| @@ -33,7 +33,6 @@ | ||||
|         app:layout_constraintHorizontal_bias="0.0" | ||||
|         app:layout_constraintStart_toEndOf="@+id/itemImage" | ||||
|         app:layout_constraintTop_toTopOf="parent" | ||||
|         android:autoLink="web" | ||||
|         tools:text="Titre" /> | ||||
|  | ||||
|     <TextView | ||||
|   | ||||
| @@ -152,4 +152,5 @@ | ||||
|     <string name="pref_switch_items_caching_off">Articles won\'t be saved to the device memory, and the app won\'t be usable offline.</string> | ||||
|     <string name="pref_switch_items_caching_on">Articles will be saved to the device memory and will be used for offline use.</string> | ||||
|     <string name="pref_switch_items_caching">Save items for offline use</string> | ||||
|     <string name="no_network_connectivity">Not connected !</string> | ||||
| </resources> | ||||
|   | ||||
| @@ -152,4 +152,5 @@ | ||||
|     <string name="pref_switch_items_caching_off">Articles won\'t be saved to the device memory, and the app won\'t be usable offline.</string> | ||||
|     <string name="pref_switch_items_caching_on">Articles will be saved to the device memory and will be used for offline use.</string> | ||||
|     <string name="pref_switch_items_caching">Save items for offline use</string> | ||||
|     <string name="no_network_connectivity">Not connected !</string> | ||||
| </resources> | ||||
|   | ||||
| @@ -152,4 +152,5 @@ | ||||
|     <string name="pref_switch_items_caching_off">Articles won\'t be saved to the device memory, and the app won\'t be usable offline.</string> | ||||
|     <string name="pref_switch_items_caching_on">Articles will be saved to the device memory and will be used for offline use.</string> | ||||
|     <string name="pref_switch_items_caching">Save items for offline use</string> | ||||
|     <string name="no_network_connectivity">Not connected !</string> | ||||
| </resources> | ||||
|   | ||||
| @@ -152,4 +152,5 @@ | ||||
|     <string name="pref_switch_items_caching_off">Articles won\'t be saved to the device memory, and the app won\'t be usable offline.</string> | ||||
|     <string name="pref_switch_items_caching_on">Articles will be saved to the device memory and will be used for offline use.</string> | ||||
|     <string name="pref_switch_items_caching">Save items for offline use</string> | ||||
|     <string name="no_network_connectivity">Not connected !</string> | ||||
| </resources> | ||||
|   | ||||
| @@ -152,4 +152,5 @@ | ||||
|     <string name="pref_switch_items_caching_off">Articles won\'t be saved to the device memory, and the app won\'t be usable offline.</string> | ||||
|     <string name="pref_switch_items_caching_on">Articles will be saved to the device memory and will be used for offline use.</string> | ||||
|     <string name="pref_switch_items_caching">Save items for offline use</string> | ||||
|     <string name="no_network_connectivity">Not connected !</string> | ||||
| </resources> | ||||
|   | ||||
| @@ -152,4 +152,5 @@ | ||||
|     <string name="pref_switch_items_caching_off">Articles won\'t be saved to the device memory, and the app won\'t be usable offline.</string> | ||||
|     <string name="pref_switch_items_caching_on">Articles will be saved to the device memory and will be used for offline use.</string> | ||||
|     <string name="pref_switch_items_caching">Save items for offline use</string> | ||||
|     <string name="no_network_connectivity">Not connected !</string> | ||||
| </resources> | ||||
|   | ||||
| @@ -152,4 +152,5 @@ | ||||
|     <string name="pref_switch_items_caching_off">Articles won\'t be saved to the device memory, and the app won\'t be usable offline.</string> | ||||
|     <string name="pref_switch_items_caching_on">Articles will be saved to the device memory and will be used for offline use.</string> | ||||
|     <string name="pref_switch_items_caching">Save items for offline use</string> | ||||
|     <string name="no_network_connectivity">Not connected !</string> | ||||
| </resources> | ||||
|   | ||||
| @@ -152,4 +152,5 @@ | ||||
|     <string name="pref_switch_items_caching_off">Los artículos no se guardarán en la memoria del dispositivo y la aplicación no se podrá utilizar sin conexión.</string> | ||||
|     <string name="pref_switch_items_caching_on">Los artículos se guardarán en la memoria del dispositivo y se utilizarán para el uso sin conexión.</string> | ||||
|     <string name="pref_switch_items_caching">Guardar elementos para uso sin conexión</string> | ||||
|     <string name="no_network_connectivity">Sin conexión!</string> | ||||
| </resources> | ||||
|   | ||||
| @@ -152,4 +152,5 @@ | ||||
|     <string name="pref_switch_items_caching_off">Articles won\'t be saved to the device memory, and the app won\'t be usable offline.</string> | ||||
|     <string name="pref_switch_items_caching_on">Articles will be saved to the device memory and will be used for offline use.</string> | ||||
|     <string name="pref_switch_items_caching">Save items for offline use</string> | ||||
|     <string name="no_network_connectivity">Not connected !</string> | ||||
| </resources> | ||||
|   | ||||
| @@ -150,6 +150,7 @@ | ||||
|     <string name="unmark">Marquer l\'article comme non lu</string> | ||||
|     <string name="pref_header_offline">Hors ligne et cache</string> | ||||
|     <string name="pref_switch_items_caching_off">Les articles ne seront pas enregistrés et l\'application ne sera pas utilisable hors ligne.</string> | ||||
|   <string name="pref_switch_items_caching_on">Les articles seront enregistrés et l\'application ne sera utilisable hors ligne.</string> | ||||
|     <string name="pref_switch_items_caching_on">Les articles seront enregistrés et l\'application sera utilisable hors ligne.</string> | ||||
|     <string name="pref_switch_items_caching">Sauvegarder les articles pour une utilisation hors ligne</string> | ||||
|     <string name="no_network_connectivity">Hors connexion !</string> | ||||
| </resources> | ||||
|   | ||||
| @@ -152,4 +152,5 @@ | ||||
|     <string name="pref_switch_items_caching_off">Os artigos non se gardaran na memoria do dispositivo e non se poderá utilizar a aplicación sen conexión.</string> | ||||
|     <string name="pref_switch_items_caching_on">Os artigos gardaranse na memoria do dispositivo e estarán dispoñibles sen conexión.</string> | ||||
|     <string name="pref_switch_items_caching">Gardar elementos para uso sen conexión</string> | ||||
|     <string name="no_network_connectivity">Non conectado!</string> | ||||
| </resources> | ||||
|   | ||||
| @@ -152,4 +152,5 @@ | ||||
|     <string name="pref_switch_items_caching_off">Articles won\'t be saved to the device memory, and the app won\'t be usable offline.</string> | ||||
|     <string name="pref_switch_items_caching_on">Articles will be saved to the device memory and will be used for offline use.</string> | ||||
|     <string name="pref_switch_items_caching">Save items for offline use</string> | ||||
|     <string name="no_network_connectivity">Not connected !</string> | ||||
| </resources> | ||||
|   | ||||
| @@ -152,4 +152,5 @@ | ||||
|     <string name="pref_switch_items_caching_off">Articles won\'t be saved to the device memory, and the app won\'t be usable offline.</string> | ||||
|     <string name="pref_switch_items_caching_on">Articles will be saved to the device memory and will be used for offline use.</string> | ||||
|     <string name="pref_switch_items_caching">Save items for offline use</string> | ||||
|     <string name="no_network_connectivity">Not connected !</string> | ||||
| </resources> | ||||
|   | ||||
| @@ -152,4 +152,5 @@ | ||||
|     <string name="pref_switch_items_caching_off">Articles won\'t be saved to the device memory, and the app won\'t be usable offline.</string> | ||||
|     <string name="pref_switch_items_caching_on">Articles will be saved to the device memory and will be used for offline use.</string> | ||||
|     <string name="pref_switch_items_caching">Save items for offline use</string> | ||||
|     <string name="no_network_connectivity">Not connected !</string> | ||||
| </resources> | ||||
|   | ||||
| @@ -152,4 +152,5 @@ | ||||
|     <string name="pref_switch_items_caching_off">Articles won\'t be saved to the device memory, and the app won\'t be usable offline.</string> | ||||
|     <string name="pref_switch_items_caching_on">Articles will be saved to the device memory and will be used for offline use.</string> | ||||
|     <string name="pref_switch_items_caching">Save items for offline use</string> | ||||
|     <string name="no_network_connectivity">Not connected !</string> | ||||
| </resources> | ||||
|   | ||||
| @@ -152,4 +152,5 @@ | ||||
|     <string name="pref_switch_items_caching_off">Articles won\'t be saved to the device memory, and the app won\'t be usable offline.</string> | ||||
|     <string name="pref_switch_items_caching_on">Articles will be saved to the device memory and will be used for offline use.</string> | ||||
|     <string name="pref_switch_items_caching">Save items for offline use</string> | ||||
|     <string name="no_network_connectivity">Not connected !</string> | ||||
| </resources> | ||||
|   | ||||
| @@ -152,4 +152,5 @@ | ||||
|     <string name="pref_switch_items_caching_off">Articles won\'t be saved to the device memory, and the app won\'t be usable offline.</string> | ||||
|     <string name="pref_switch_items_caching_on">Articles will be saved to the device memory and will be used for offline use.</string> | ||||
|     <string name="pref_switch_items_caching">Save items for offline use</string> | ||||
|     <string name="no_network_connectivity">Not connected !</string> | ||||
| </resources> | ||||
|   | ||||
| @@ -152,4 +152,5 @@ | ||||
|     <string name="pref_switch_items_caching_off">Articles won\'t be saved to the device memory, and the app won\'t be usable offline.</string> | ||||
|     <string name="pref_switch_items_caching_on">Articles will be saved to the device memory and will be used for offline use.</string> | ||||
|     <string name="pref_switch_items_caching">Save items for offline use</string> | ||||
|     <string name="no_network_connectivity">Not connected !</string> | ||||
| </resources> | ||||
|   | ||||
| @@ -152,4 +152,5 @@ | ||||
|     <string name="pref_switch_items_caching_off">Articles won\'t be saved to the device memory, and the app won\'t be usable offline.</string> | ||||
|     <string name="pref_switch_items_caching_on">Articles will be saved to the device memory and will be used for offline use.</string> | ||||
|     <string name="pref_switch_items_caching">Save items for offline use</string> | ||||
|     <string name="no_network_connectivity">Not connected !</string> | ||||
| </resources> | ||||
|   | ||||
| @@ -152,4 +152,5 @@ | ||||
|     <string name="pref_switch_items_caching_off">Articles won\'t be saved to the device memory, and the app won\'t be usable offline.</string> | ||||
|     <string name="pref_switch_items_caching_on">Articles will be saved to the device memory and will be used for offline use.</string> | ||||
|     <string name="pref_switch_items_caching">Save items for offline use</string> | ||||
|     <string name="no_network_connectivity">Not connected !</string> | ||||
| </resources> | ||||
|   | ||||
| @@ -152,4 +152,5 @@ | ||||
|     <string name="pref_switch_items_caching_off">Articles won\'t be saved to the device memory, and the app won\'t be usable offline.</string> | ||||
|     <string name="pref_switch_items_caching_on">Articles will be saved to the device memory and will be used for offline use.</string> | ||||
|     <string name="pref_switch_items_caching">Save items for offline use</string> | ||||
|     <string name="no_network_connectivity">Not connected !</string> | ||||
| </resources> | ||||
|   | ||||
| @@ -152,4 +152,5 @@ | ||||
|     <string name="pref_switch_items_caching_off">Articles won\'t be saved to the device memory, and the app won\'t be usable offline.</string> | ||||
|     <string name="pref_switch_items_caching_on">Articles will be saved to the device memory and will be used for offline use.</string> | ||||
|     <string name="pref_switch_items_caching">Save items for offline use</string> | ||||
|     <string name="no_network_connectivity">Not connected !</string> | ||||
| </resources> | ||||
|   | ||||
| @@ -152,4 +152,5 @@ | ||||
|     <string name="pref_switch_items_caching_off">Articles won\'t be saved to the device memory, and the app won\'t be usable offline.</string> | ||||
|     <string name="pref_switch_items_caching_on">Articles will be saved to the device memory and will be used for offline use.</string> | ||||
|     <string name="pref_switch_items_caching">Save items for offline use</string> | ||||
|     <string name="no_network_connectivity">Not connected !</string> | ||||
| </resources> | ||||
|   | ||||
| @@ -152,4 +152,5 @@ | ||||
|     <string name="pref_switch_items_caching_off">Articles won\'t be saved to the device memory, and the app won\'t be usable offline.</string> | ||||
|     <string name="pref_switch_items_caching_on">Articles will be saved to the device memory and will be used for offline use.</string> | ||||
|     <string name="pref_switch_items_caching">Save items for offline use</string> | ||||
|     <string name="no_network_connectivity">Not connected !</string> | ||||
| </resources> | ||||
|   | ||||
| @@ -152,4 +152,5 @@ | ||||
|     <string name="pref_switch_items_caching_off">Articles won\'t be saved to the device memory, and the app won\'t be usable offline.</string> | ||||
|     <string name="pref_switch_items_caching_on">Articles will be saved to the device memory and will be used for offline use.</string> | ||||
|     <string name="pref_switch_items_caching">Save items for offline use</string> | ||||
|     <string name="no_network_connectivity">Not connected !</string> | ||||
| </resources> | ||||
|   | ||||
| @@ -152,4 +152,5 @@ | ||||
|     <string name="pref_switch_items_caching_off">Articles won\'t be saved to the device memory, and the app won\'t be usable offline.</string> | ||||
|     <string name="pref_switch_items_caching_on">Articles will be saved to the device memory and will be used for offline use.</string> | ||||
|     <string name="pref_switch_items_caching">Save items for offline use</string> | ||||
|     <string name="no_network_connectivity">Not connected !</string> | ||||
| </resources> | ||||
|   | ||||
| @@ -152,4 +152,5 @@ | ||||
|     <string name="pref_switch_items_caching_off">Articles won\'t be saved to the device memory, and the app won\'t be usable offline.</string> | ||||
|     <string name="pref_switch_items_caching_on">Articles will be saved to the device memory and will be used for offline use.</string> | ||||
|     <string name="pref_switch_items_caching">Save items for offline use</string> | ||||
|     <string name="no_network_connectivity">Not connected !</string> | ||||
| </resources> | ||||
|   | ||||
| @@ -152,4 +152,5 @@ | ||||
|     <string name="pref_switch_items_caching_off">Articles won\'t be saved to the device memory, and the app won\'t be usable offline.</string> | ||||
|     <string name="pref_switch_items_caching_on">Articles will be saved to the device memory and will be used for offline use.</string> | ||||
|     <string name="pref_switch_items_caching">Save items for offline use</string> | ||||
|     <string name="no_network_connectivity">Not connected !</string> | ||||
| </resources> | ||||
|   | ||||
| @@ -152,4 +152,5 @@ | ||||
|     <string name="pref_switch_items_caching_off">Articles won\'t be saved to the device memory, and the app won\'t be usable offline.</string> | ||||
|     <string name="pref_switch_items_caching_on">Articles will be saved to the device memory and will be used for offline use.</string> | ||||
|     <string name="pref_switch_items_caching">Save items for offline use</string> | ||||
|     <string name="no_network_connectivity">Not connected !</string> | ||||
| </resources> | ||||
|   | ||||
| @@ -152,4 +152,5 @@ | ||||
|     <string name="pref_switch_items_caching_off">Articles won\'t be saved to the device memory, and the app won\'t be usable offline.</string> | ||||
|     <string name="pref_switch_items_caching_on">Articles will be saved to the device memory and will be used for offline use.</string> | ||||
|     <string name="pref_switch_items_caching">Save items for offline use</string> | ||||
|     <string name="no_network_connectivity">Not connected !</string> | ||||
| </resources> | ||||
|   | ||||
| @@ -152,4 +152,5 @@ | ||||
|     <string name="pref_switch_items_caching_off">Articles won\'t be saved to the device memory, and the app won\'t be usable offline.</string> | ||||
|     <string name="pref_switch_items_caching_on">Articles will be saved to the device memory and will be used for offline use.</string> | ||||
|     <string name="pref_switch_items_caching">Save items for offline use</string> | ||||
|     <string name="no_network_connectivity">Not connected !</string> | ||||
| </resources> | ||||
|   | ||||
| @@ -152,4 +152,5 @@ | ||||
|     <string name="pref_switch_items_caching_off">Articles won\'t be saved to the device memory, and the app won\'t be usable offline.</string> | ||||
|     <string name="pref_switch_items_caching_on">Articles will be saved to the device memory and will be used for offline use.</string> | ||||
|     <string name="pref_switch_items_caching">Save items for offline use</string> | ||||
|     <string name="no_network_connectivity">Not connected !</string> | ||||
| </resources> | ||||
|   | ||||
| @@ -6,6 +6,7 @@ buildscript { | ||||
|         android_version = '1.0.0' | ||||
|         lifecycle_version = '2.0.0' | ||||
|         room_version = '2.1.0-alpha01' | ||||
|         work_version = "1.0.0-alpha10" | ||||
|     } | ||||
|     repositories { | ||||
|         google() | ||||
|   | ||||
| @@ -1,14 +1 @@ | ||||
| include ':app' | ||||
|  | ||||
| ext.isCiServer = !!System.getProperty("CI") | ||||
|  | ||||
| buildCache { | ||||
|     local { | ||||
|         enabled = !isCiServer | ||||
|     } | ||||
|     remote(HttpBuildCache) { | ||||
|         // DO NOT COMMIT !!!!! | ||||
|         url = 'http://amine-bou.fr:8885/cache/' | ||||
|         push = isCiServer | ||||
|     } | ||||
| } | ||||
		Reference in New Issue
	
	Block a user