add swiperefreshlayout

This commit is contained in:
Josh Sharp 2020-07-30 16:15:51 +10:00
parent b01a859741
commit a4a60c596d
10 changed files with 191 additions and 25 deletions

View file

@ -40,11 +40,13 @@ dependencies {
implementation 'androidx.core:core-ktx:1.3.0'
implementation 'androidx.appcompat:appcompat:1.1.0'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
implementation "androidx.drawerlayout:drawerlayout:1.1.0"
implementation "com.squareup.okhttp3:okhttp:4.7.2"
implementation 'androidx.recyclerview:recyclerview:1.1.0'
implementation "io.coil-kt:coil:0.11.0"
implementation 'com.quiph.ui:recyclerviewfastscroller:0.1.3'
implementation 'com.quiph.ui:recyclerviewfastscroller:0.2.0'
implementation 'com.google.android.material:material:1.1.0'
implementation "androidx.swiperefreshlayout:swiperefreshlayout:1.1.0"
testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test.ext:junit:1.1.1'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'

View file

@ -15,6 +15,7 @@ class LoginActivity : AppCompatActivity() {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_login)
setSupportActionBar(toolbar)
supportActionBar?.title = "Login to Kobo to continue"
val cookieManager = CookieManager.getInstance()
@ -22,7 +23,6 @@ class LoginActivity : AppCompatActivity() {
cookieManager.setAcceptThirdPartyCookies(web, true)
web.settings.javaScriptEnabled = true;
web.loadUrl("https://www.kobo.com/account/wishlist")
web.webViewClient = object: WebViewClient() {
override fun onPageFinished(view: WebView?, url: String?) {
super.onPageFinished(view, url)
@ -38,6 +38,10 @@ class LoginActivity : AppCompatActivity() {
}
}
}
cookieManager.removeAllCookies {
web.loadUrl("https://www.kobo.com/account/wishlist")
}
}
fun getCookie(siteName: String, name: String): String? {

View file

@ -16,6 +16,7 @@ import android.view.ViewGroup
import android.widget.ImageView
import android.widget.TextView
import android.widget.Toast
import androidx.appcompat.app.ActionBarDrawerToggle
import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.widget.SearchView
import androidx.core.content.ContextCompat.startActivity
@ -38,12 +39,36 @@ class MainActivity : AppCompatActivity() {
var hasCookie = false
val viewAdapter = BookAdapter(ArrayList())
var totalPages = 1
var refreshing = false
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val app = application as WishkoboneApplication
setSupportActionBar(toolbar)
supportActionBar?.setDisplayHomeAsUpEnabled(true)
supportActionBar?.title = "Your wishlist"
val toggle =
ActionBarDrawerToggle(this, drawerlayout, toolbar, R.string.open, R.string.close)
drawerlayout.addDrawerListener(toggle)
toggle.isDrawerIndicatorEnabled = true
toggle.syncState()
navigation.setCheckedItem(R.id.home)
navigation.setNavigationItemSelectedListener {
if (it.itemId == R.id.logout) {
app.invalidateCookie()
hasCookie = false
drawerlayout.closeDrawers()
doLogin()
return@setNavigationItemSelectedListener true
}
false
}
val viewManager = LinearLayoutManager(this)
status_text.text = "Loading..."
@ -60,8 +85,33 @@ class MainActivity : AppCompatActivity() {
adapter = viewAdapter
}
fastscroller.setHandleStateListener(object : RecyclerViewFastScroller.HandleStateListener {
override fun onDragged(offset: Float, position: Int) {
Log.d("scroller", "dragged: $position")
super.onDragged(offset, position)
}
val app = application as WishkoboneApplication
override fun onEngaged() {
Log.d("scroller", "engaged")
super.onEngaged()
}
override fun onReleased() {
Log.d("scroller", "released")
super.onReleased()
}
})
refresher.setOnRefreshListener {
if (!refreshing) {
viewAdapter.books.clear()
viewAdapter.filteredBooks.clear()
viewAdapter.notifyDataSetChanged()
refresher.isRefreshing = false
loadBooks()
}
}
val cookie = app.getCookie()
if (cookie != null) {
@ -71,10 +121,9 @@ class MainActivity : AppCompatActivity() {
doLogin()
}
}
fun doLogin(){
fun doLogin() {
val login = Intent(this, LoginActivity::class.java)
startActivity(login);
}
@ -86,7 +135,7 @@ class MainActivity : AppCompatActivity() {
val app = application as WishkoboneApplication
val cookie = app.getCookie()
if (cookie != null) { // we just got this via login
viewAdapter.books.clear()
loadBooks()
}
}
@ -128,7 +177,9 @@ class MainActivity : AppCompatActivity() {
@SuppressLint("SetTextI18n")
private fun loadBooks(page: Int = 1) {
refreshing = true
runOnUiThread {
snackbar_spinner.visibility = View.VISIBLE
status.visibility = View.VISIBLE
status_text.text = "Loading page $page of $totalPages"
}
@ -145,7 +196,7 @@ class MainActivity : AppCompatActivity() {
}
override fun onResponse(call: Call, r: Response, response: JSONObject) {
if (!response.has("TotalNumPages")){
if (!response.has("TotalNumPages")) {
// must be unauthenticated
hasCookie = false
runOnUiThread {
@ -200,10 +251,20 @@ class MainActivity : AppCompatActivity() {
} else {
// the end!
runOnUiThread {
refreshing = false
snackbar_spinner.visibility = View.INVISIBLE
status_text.text =
"Load complete! ${viewAdapter.books.size} items shown."
status.postDelayed({
status.visibility = View.GONE
status.animate()
.translationY(status.height.toFloat())
.setDuration(500)
.withEndAction {
status.visibility = View.GONE
status.translationY = 0F
}
.start()
}, 3000)
}
}
@ -211,6 +272,7 @@ class MainActivity : AppCompatActivity() {
override fun onFailureResponse(call: Call, r: Response, response: JSONObject) {
hasCookie = false
refreshing = false
}
});
}
@ -222,7 +284,7 @@ class MainActivity : AppCompatActivity() {
// Complex data items may need more than one view per item, and
// you provide access to all the views for a data item in a view holder.
// Each data item is just a string in this case that is shown in a TextView.
private var filteredBooks: ArrayList<Book> = ArrayList()
var filteredBooks: ArrayList<Book> = ArrayList()
init {
filteredBooks.addAll(books)
@ -308,6 +370,7 @@ class MainActivity : AppCompatActivity() {
}
holder.itemView.setOnClickListener {
Log.d("click", book.url)
val intent = Intent(Intent.ACTION_VIEW, Uri.parse(book.url))
intent.addFlags(FLAG_ACTIVITY_NEW_TASK)
startActivity(it.context, intent, null)
@ -319,6 +382,7 @@ class MainActivity : AppCompatActivity() {
}
override fun onChange(position: Int): CharSequence {
Log.d("scroller", "$position")
return filteredBooks[position].formattedPrice()
}

View file

@ -4,8 +4,25 @@
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/coordinator"
tools:context=".LoginActivity">
<com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintTop_toTopOf="@id/coordinator"
android:id="@+id/appbar">
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light">
</androidx.appcompat.widget.Toolbar>
</com.google.android.material.appbar.AppBarLayout>
<WebView
android:layout_width="match_parent"
android:layout_height="match_parent"

View file

@ -1,36 +1,75 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
<androidx.drawerlayout.widget.DrawerLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/drawerlayout"
android:layout_height="match_parent"
android:layout_width="match_parent">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/coordinator"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<com.qtalk.recyclerviewfastscroller.RecyclerViewFastScroller
android:id="@+id/fastscroller"
<com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintTop_toTopOf="@id/coordinator"
android:id="@+id/appbar">
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light">
</androidx.appcompat.widget.Toolbar>
</com.google.android.material.appbar.AppBarLayout>
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
app:popupDrawable="@drawable/scroller_popup"
app:handleDrawable="@drawable/scroller_thumb"
app:layout_constraintBottom_toBottomOf="@id/coordinator"
app:handleHeight="32dp">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/list"
android:layout_marginTop="?attr/actionBarSize"
android:id="@+id/refresher">
<com.qtalk.recyclerviewfastscroller.RecyclerViewFastScroller
android:id="@+id/fastscroller"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scrollbars="none" />
</com.qtalk.recyclerviewfastscroller.RecyclerViewFastScroller>
app:popupDrawable="@drawable/scroller_popup"
app:handleDrawable="@drawable/scroller_thumb"
app:layout_constraintBottom_toBottomOf="@id/coordinator"
app:layout_constraintTop_toBottomOf="@id/appbar"
android:layout_marginTop="?attr/actionBarSize"
app:supportSwipeToRefresh="true"
app:handleHeight="32dp">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scrollbars="none" />
</com.qtalk.recyclerviewfastscroller.RecyclerViewFastScroller>
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/status"
app:layout_constraintBottom_toBottomOf="@id/coordinator"
android:orientation="horizontal"
android:background="@color/colorPrimaryDark"
android:background="@color/snackbar"
android:paddingVertical="12dp"
android:paddingHorizontal="15dp">
<ProgressBar
android:layout_width="20dp"
android:layout_height="20dp"
android:indeterminate="true"
android:layout_marginEnd="15dp"
android:id="@+id/snackbar_spinner"
android:indeterminateTint="@color/lineGrey"
/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
@ -39,4 +78,12 @@
android:textSize="15sp"
/>
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
<com.google.android.material.navigation.NavigationView
android:id="@+id/navigation"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start|left"
app:headerLayout="@layout/drawer_header"
app:menu="@menu/menu_nav" />
</androidx.drawerlayout.widget.DrawerLayout>

View file

@ -0,0 +1,24 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingHorizontal="15dp"
android:paddingVertical="30dp"
android:background="@color/snackbar">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="19sp"
android:textColor="@android:color/white"
android:textStyle="bold"
android:text="Wishkobone"
/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="17sp"
android:textColor="@color/lineGrey"
android:text="A wishlist app for Kobo."
/>
</LinearLayout>

View file

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@+id/home" android:title="Wishlist"/>
<item android:id="@+id/logout" android:title="Log out"/>
</menu>

View file

@ -2,7 +2,8 @@
<resources>
<color name="colorPrimary">#bf2026</color>
<color name="colorPrimaryDark">#ab1d22</color>
<color name="colorAccent">#4218bb</color>
<color name="colorAccent">#ab1d22</color>
<color name="lineGrey">#e0e0e0</color>
<color name="secondaryGrey">#888888</color>
<color name="snackbar">#444444</color>
</resources>

View file

@ -1,3 +1,5 @@
<resources>
<string name="app_name">Wishkobone</string>
<string name="open">Open drawer</string>
<string name="close">Close drawer</string>
</resources>

View file

@ -1,6 +1,6 @@
<resources>
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>