Add loading indications, refactor fragments into common parent class
This commit is contained in:
parent
55cb729a2d
commit
0a3cd85d83
@ -6,6 +6,7 @@ import android.content.Intent
|
||||
import android.content.SharedPreferences
|
||||
import android.net.Uri
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.browser.customtabs.CustomTabsIntent
|
||||
import com.h.pixeldroid.api.PixelfedAPI
|
||||
@ -42,20 +43,26 @@ class LoginActivity : AppCompatActivity() {
|
||||
|
||||
val url = intent.data
|
||||
|
||||
//Check if the activity was started after the authentication
|
||||
if (url == null || !url.toString().startsWith("$OAUTH_SCHEME://$PACKAGE_ID")) return
|
||||
|
||||
loadingAnimation(true)
|
||||
|
||||
val code = url.getQueryParameter("code")
|
||||
authenticate(code)
|
||||
|
||||
}
|
||||
|
||||
override fun onStop() {
|
||||
super.onStop()
|
||||
loadingAnimation(false)
|
||||
}
|
||||
|
||||
override fun onBackPressed() {
|
||||
}
|
||||
|
||||
private fun onClickConnect() {
|
||||
|
||||
connect_instance_button.isEnabled = false
|
||||
|
||||
val normalizedDomain = normalizeDomain(editText.text.toString())
|
||||
|
||||
try{
|
||||
@ -64,6 +71,8 @@ class LoginActivity : AppCompatActivity() {
|
||||
return failedRegistration(getString(R.string.invalid_domain))
|
||||
}
|
||||
|
||||
loadingAnimation(true)
|
||||
|
||||
preferences.edit()
|
||||
.putString("domain", "https://$normalizedDomain")
|
||||
.apply()
|
||||
@ -125,7 +134,6 @@ class LoginActivity : AppCompatActivity() {
|
||||
return failedRegistration(getString(R.string.browser_launch_failed))
|
||||
}
|
||||
}
|
||||
connect_instance_button.isEnabled = true
|
||||
}
|
||||
|
||||
private fun authenticate(code: String?) {
|
||||
@ -169,8 +177,19 @@ class LoginActivity : AppCompatActivity() {
|
||||
|
||||
private fun failedRegistration(message: String =
|
||||
getString(R.string.registration_failed)){
|
||||
connect_instance_button.isEnabled = true
|
||||
loadingAnimation(false)
|
||||
editText.error = message
|
||||
}
|
||||
|
||||
private fun loadingAnimation(on: Boolean){
|
||||
if(on) {
|
||||
domainTextInputLayout.visibility = View.GONE
|
||||
progressLayout.visibility = View.VISIBLE
|
||||
}
|
||||
else {
|
||||
domainTextInputLayout.visibility = View.VISIBLE
|
||||
progressLayout.visibility = View.GONE
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -17,9 +17,9 @@ import com.google.android.material.navigation.NavigationView
|
||||
import com.google.android.material.tabs.TabLayout
|
||||
import com.google.android.material.tabs.TabLayoutMediator
|
||||
import com.h.pixeldroid.fragments.CameraFragment
|
||||
import com.h.pixeldroid.fragments.HomeFragment
|
||||
import com.h.pixeldroid.fragments.feeds.HomeFragment
|
||||
import com.h.pixeldroid.fragments.MyProfileFragment
|
||||
import com.h.pixeldroid.fragments.NotificationsFragment
|
||||
import com.h.pixeldroid.fragments.feeds.NotificationsFragment
|
||||
|
||||
|
||||
class MainActivity : AppCompatActivity(), NavigationView.OnNavigationItemSelectedListener {
|
||||
@ -46,10 +46,11 @@ class MainActivity : AppCompatActivity(), NavigationView.OnNavigationItemSelecte
|
||||
val navigationView: NavigationView = findViewById(R.id.nav_view)
|
||||
navigationView.setNavigationItemSelectedListener(this)
|
||||
|
||||
val tabs = arrayOf(HomeFragment(),
|
||||
val tabs = arrayOf(
|
||||
HomeFragment(),
|
||||
Fragment(),
|
||||
CameraFragment(),
|
||||
NotificationsFragment(),
|
||||
NotificationsFragment(),
|
||||
MyProfileFragment())
|
||||
|
||||
setupTabs(tabs)
|
||||
|
@ -3,8 +3,8 @@ package com.h.pixeldroid
|
||||
import android.os.Bundle
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import com.h.pixeldroid.fragments.PostFragment
|
||||
import com.h.pixeldroid.models.Post
|
||||
import com.h.pixeldroid.models.Post.Companion.POST_TAG
|
||||
import com.h.pixeldroid.objects.Status.Companion.POST_TAG
|
||||
import com.h.pixeldroid.objects.Status
|
||||
|
||||
|
||||
class PostActivity : AppCompatActivity() {
|
||||
@ -14,11 +14,11 @@ class PostActivity : AppCompatActivity() {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.activity_post)
|
||||
|
||||
val post = intent.getSerializableExtra(POST_TAG) as Post
|
||||
val status = intent.getSerializableExtra(POST_TAG) as Status
|
||||
|
||||
postFragment = PostFragment()
|
||||
val arguments = Bundle()
|
||||
arguments.putSerializable(POST_TAG, post)
|
||||
arguments.putSerializable(POST_TAG, status)
|
||||
postFragment.arguments = arguments
|
||||
|
||||
supportFragmentManager.beginTransaction()
|
||||
|
@ -1,78 +0,0 @@
|
||||
package com.h.pixeldroid.fragments
|
||||
|
||||
import android.content.Context
|
||||
import android.content.SharedPreferences
|
||||
import android.os.Bundle
|
||||
import android.util.Log
|
||||
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.h.pixeldroid.BuildConfig
|
||||
import com.h.pixeldroid.R
|
||||
import com.h.pixeldroid.api.PixelfedAPI
|
||||
import com.h.pixeldroid.models.Post
|
||||
import com.h.pixeldroid.objects.Status
|
||||
import retrofit2.Call
|
||||
import retrofit2.Callback
|
||||
import retrofit2.Response
|
||||
|
||||
|
||||
class HomeFragment : Fragment() {
|
||||
private lateinit var preferences: SharedPreferences
|
||||
private lateinit var feed : RecyclerView
|
||||
private lateinit var adapter : FeedRecyclerViewAdapter
|
||||
private lateinit var posts : List<Post>
|
||||
|
||||
fun setContent(newPosts : ArrayList<Post>) {
|
||||
posts = newPosts
|
||||
adapter.addPosts(posts)
|
||||
}
|
||||
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater, container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
): View? {
|
||||
val view = inflater.inflate(R.layout.fragment_home, container, false)
|
||||
preferences = this.activity!!.getSharedPreferences(
|
||||
"${BuildConfig.APPLICATION_ID}.pref", Context.MODE_PRIVATE
|
||||
)
|
||||
feed = view.findViewById(R.id.feedList)
|
||||
feed.layoutManager = LinearLayoutManager(context)
|
||||
adapter = FeedRecyclerViewAdapter(context!!)
|
||||
feed.adapter = adapter
|
||||
return view
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
val pixelfedAPI = PixelfedAPI.create("${preferences.getString("domain", "")}")
|
||||
val accessToken = preferences.getString("accessToken", "")
|
||||
var statuses: ArrayList<Status>? = null
|
||||
val newPosts = ArrayList<Post>()
|
||||
|
||||
pixelfedAPI.timelineHome("Bearer $accessToken")
|
||||
.enqueue(object : Callback<List<Status>> {
|
||||
override fun onResponse(call: Call<List<Status>>, response: Response<List<Status>>) {
|
||||
if (response.code() == 200) {
|
||||
statuses = response.body() as ArrayList<Status>?
|
||||
if(!statuses.isNullOrEmpty()) {
|
||||
for (status in statuses!!) {
|
||||
newPosts.add(Post(status))
|
||||
}
|
||||
setContent(newPosts)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
override fun onFailure(call: Call<List<Status>>, t: Throwable) {
|
||||
Log.e("HomeFragment", t.toString())
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
@ -1,99 +0,0 @@
|
||||
package com.h.pixeldroid.fragments
|
||||
|
||||
import android.content.Context
|
||||
import android.content.SharedPreferences
|
||||
import android.os.Bundle
|
||||
import android.util.Log
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.Toast
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout
|
||||
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout.OnRefreshListener
|
||||
import com.h.pixeldroid.BuildConfig
|
||||
import com.h.pixeldroid.R
|
||||
import com.h.pixeldroid.api.PixelfedAPI
|
||||
import com.h.pixeldroid.objects.Notification
|
||||
import kotlinx.android.synthetic.main.fragment_notifications_list.*
|
||||
import kotlinx.android.synthetic.main.fragment_notifications_list.view.*
|
||||
import kotlinx.android.synthetic.main.fragment_notifications_list.view.swipeRefreshLayout
|
||||
import retrofit2.Call
|
||||
import retrofit2.Callback
|
||||
import retrofit2.Response
|
||||
|
||||
/**
|
||||
* A fragment representing a list of Items.
|
||||
*/
|
||||
class NotificationsFragment : Fragment() {
|
||||
private lateinit var preferences: SharedPreferences
|
||||
private lateinit var list : RecyclerView
|
||||
private lateinit var adapter : NotificationsRecyclerViewAdapter
|
||||
private lateinit var swipeRefreshLayout: SwipeRefreshLayout
|
||||
var notifications : List<Notification> = ArrayList()
|
||||
|
||||
private lateinit var pixelfedAPI: PixelfedAPI
|
||||
private var accessToken: String? = null
|
||||
|
||||
|
||||
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater, container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
): View? {
|
||||
val view = inflater.inflate(R.layout.fragment_notifications_list, container, false)
|
||||
preferences = activity!!.getSharedPreferences(
|
||||
"${BuildConfig.APPLICATION_ID}.pref", Context.MODE_PRIVATE
|
||||
)
|
||||
pixelfedAPI = PixelfedAPI.create("${preferences.getString("domain", "")}")
|
||||
accessToken = preferences.getString("accessToken", "")
|
||||
|
||||
swipeRefreshLayout = view.findViewById(R.id.swipeRefreshLayout)
|
||||
list = swipeRefreshLayout.list
|
||||
|
||||
// Set the adapter
|
||||
list.layoutManager = LinearLayoutManager(context)
|
||||
adapter = NotificationsRecyclerViewAdapter()
|
||||
list.adapter = adapter
|
||||
|
||||
|
||||
|
||||
swipeRefreshLayout.setOnRefreshListener {
|
||||
doRequest()
|
||||
}
|
||||
|
||||
return view
|
||||
}
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
doRequest()
|
||||
}
|
||||
fun setContent(notifications : ArrayList<Notification>) {
|
||||
this.notifications = notifications
|
||||
adapter.initializeWith(notifications)
|
||||
}
|
||||
|
||||
private fun doRequest(){
|
||||
val call = pixelfedAPI.notifications("Bearer $accessToken", min_id="1")
|
||||
call.enqueue(object : Callback<List<Notification>> {
|
||||
override fun onResponse(call: Call<List<Notification>>, response: Response<List<Notification>>) {
|
||||
if (response.code() == 200) {
|
||||
val notifications = response.body()!! as ArrayList<Notification>
|
||||
setContent(notifications)
|
||||
} else{
|
||||
Toast.makeText(context,"Something went wrong while refreshing", Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
swipeRefreshLayout.isRefreshing = false
|
||||
}
|
||||
|
||||
override fun onFailure(call: Call<List<Notification>>, t: Throwable) {
|
||||
Toast.makeText(context,"Could not get notifications", Toast.LENGTH_SHORT).show()
|
||||
Log.e("Notifications", t.toString())
|
||||
}
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -6,8 +6,8 @@ import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import com.h.pixeldroid.R
|
||||
import com.h.pixeldroid.models.Post
|
||||
import com.h.pixeldroid.models.Post.Companion.POST_TAG
|
||||
import com.h.pixeldroid.objects.Status.Companion.POST_TAG
|
||||
import com.h.pixeldroid.objects.Status
|
||||
|
||||
|
||||
class PostFragment : Fragment() {
|
||||
@ -16,9 +16,9 @@ class PostFragment : Fragment() {
|
||||
inflater: LayoutInflater, container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
): View? {
|
||||
val post = arguments?.getSerializable(POST_TAG) as Post?
|
||||
val status = arguments?.getSerializable(POST_TAG) as Status?
|
||||
val root = inflater.inflate(R.layout.post_fragment, container, false)
|
||||
post?.setupPost(this, root)
|
||||
status?.setupPost(this, root)
|
||||
return root
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,98 @@
|
||||
package com.h.pixeldroid.fragments.feeds
|
||||
|
||||
import android.content.Context
|
||||
import android.content.SharedPreferences
|
||||
import android.os.Bundle
|
||||
import android.util.Log
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.Toast
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout
|
||||
import com.h.pixeldroid.BuildConfig
|
||||
import com.h.pixeldroid.R
|
||||
import com.h.pixeldroid.api.PixelfedAPI
|
||||
import kotlinx.android.synthetic.main.fragment_feed.*
|
||||
import kotlinx.android.synthetic.main.fragment_feed.view.*
|
||||
import retrofit2.Call
|
||||
import retrofit2.Callback
|
||||
import retrofit2.Response
|
||||
|
||||
open class FeedFragment<T, VH: RecyclerView.ViewHolder?>: Fragment() {
|
||||
|
||||
var content : List<T> = ArrayList()
|
||||
|
||||
protected var accessToken: String? = null
|
||||
protected lateinit var pixelfedAPI: PixelfedAPI
|
||||
protected lateinit var preferences: SharedPreferences
|
||||
|
||||
protected lateinit var list : RecyclerView
|
||||
protected lateinit var adapter : FeedsRecyclerViewAdapter<T, VH>
|
||||
private lateinit var swipeRefreshLayout: SwipeRefreshLayout
|
||||
|
||||
protected fun doRequest(call: Call<List<T>>){
|
||||
call.enqueue(object : Callback<List<T>> {
|
||||
override fun onResponse(call: Call<List<T>>, response: Response<List<T>>) {
|
||||
if (response.code() == 200) {
|
||||
val notifications = response.body()!! as ArrayList<T>
|
||||
setContent(notifications)
|
||||
} else{
|
||||
Toast.makeText(context,"Something went wrong while loading", Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
swipeRefreshLayout.isRefreshing = false
|
||||
progressBar.visibility = View.GONE
|
||||
}
|
||||
|
||||
override fun onFailure(call: Call<List<T>>, t: Throwable) {
|
||||
Toast.makeText(context,"Could not get feed", Toast.LENGTH_SHORT).show()
|
||||
Log.e("FeedFragment", t.toString())
|
||||
}
|
||||
})
|
||||
|
||||
}
|
||||
protected fun setContent(content : ArrayList<T>) {
|
||||
this.content = content
|
||||
adapter.initializeWith(content)
|
||||
}
|
||||
|
||||
|
||||
protected fun onCreateView(inflater: LayoutInflater, container: ViewGroup?): View? {
|
||||
val view = inflater.inflate(R.layout.fragment_feed, container, false)
|
||||
swipeRefreshLayout = view.findViewById(R.id.swipeRefreshLayout)
|
||||
list = swipeRefreshLayout.list
|
||||
// Set the adapter
|
||||
list.layoutManager = LinearLayoutManager(context)
|
||||
|
||||
return view
|
||||
}
|
||||
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
preferences = activity!!.getSharedPreferences(
|
||||
"${BuildConfig.APPLICATION_ID}.pref", Context.MODE_PRIVATE
|
||||
)
|
||||
|
||||
pixelfedAPI = PixelfedAPI.create("${preferences.getString("domain", "")}")
|
||||
accessToken = preferences.getString("accessToken", "")
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
abstract class FeedsRecyclerViewAdapter<T, VH : RecyclerView.ViewHolder?>: RecyclerView.Adapter<VH>() {
|
||||
|
||||
protected val feedContent: ArrayList<T> = arrayListOf()
|
||||
protected lateinit var context: Context
|
||||
|
||||
override fun getItemCount(): Int = feedContent.size
|
||||
|
||||
open fun initializeWith(content: List<T>){
|
||||
feedContent.clear()
|
||||
feedContent.addAll(content)
|
||||
notifyDataSetChanged()
|
||||
}
|
||||
}
|
@ -0,0 +1,34 @@
|
||||
package com.h.pixeldroid.fragments.feeds
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import com.h.pixeldroid.objects.Status
|
||||
import kotlinx.android.synthetic.main.fragment_home.*
|
||||
|
||||
|
||||
class HomeFragment : FeedFragment<Status, HomeRecyclerViewAdapter.ViewHolder>() {
|
||||
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater, container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
): View? {
|
||||
val view = super.onCreateView(inflater, container)
|
||||
adapter = HomeRecyclerViewAdapter()
|
||||
list.adapter = adapter
|
||||
return view
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
|
||||
swipeRefreshLayout.setOnRefreshListener {
|
||||
val call = pixelfedAPI.timelineHome("Bearer $accessToken")
|
||||
doRequest(call)
|
||||
}
|
||||
val call = pixelfedAPI.timelineHome("Bearer $accessToken")
|
||||
doRequest(call)
|
||||
}
|
||||
}
|
@ -1,6 +1,5 @@
|
||||
package com.h.pixeldroid.fragments
|
||||
package com.h.pixeldroid.fragments.feeds
|
||||
|
||||
import android.content.Context
|
||||
import android.graphics.Typeface
|
||||
import android.util.DisplayMetrics
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
@ -10,29 +9,20 @@ import android.view.ViewGroup
|
||||
import android.widget.ImageView
|
||||
import android.widget.TextView
|
||||
import com.h.pixeldroid.R
|
||||
import com.h.pixeldroid.models.Post
|
||||
import com.h.pixeldroid.objects.Status
|
||||
import com.h.pixeldroid.utils.ImageConverter.Companion.setDefaultImage
|
||||
import com.h.pixeldroid.utils.ImageConverter.Companion.setImageViewFromURL
|
||||
import com.h.pixeldroid.utils.ImageConverter.Companion.setRoundImageFromURL
|
||||
import java.util.ArrayList
|
||||
|
||||
/**
|
||||
* [RecyclerView.Adapter] that can display a list of [Post]s
|
||||
* [RecyclerView.Adapter] that can display a list of Posts
|
||||
*/
|
||||
class FeedRecyclerViewAdapter(
|
||||
private val context : Context
|
||||
) : RecyclerView.Adapter<FeedRecyclerViewAdapter.ViewHolder>() {
|
||||
private val posts: ArrayList<Post> = ArrayList<Post>()
|
||||
|
||||
fun addPosts(newPosts : List<Post>) {
|
||||
val size = posts.size
|
||||
posts.addAll(newPosts)
|
||||
notifyItemRangeInserted(size, newPosts.size)
|
||||
}
|
||||
class HomeRecyclerViewAdapter() : FeedsRecyclerViewAdapter<Status, HomeRecyclerViewAdapter.ViewHolder>() {
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
|
||||
val inflater = LayoutInflater.from(context)
|
||||
val view = inflater.inflate(R.layout.post_fragment, parent, false)
|
||||
val view = LayoutInflater.from(parent.context)
|
||||
.inflate(R.layout.post_fragment, parent, false)
|
||||
context = view.context
|
||||
return ViewHolder(view)
|
||||
}
|
||||
|
||||
@ -40,7 +30,7 @@ class FeedRecyclerViewAdapter(
|
||||
* Binds the different elements of the Post Model to the view holder
|
||||
*/
|
||||
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
|
||||
val post = posts[position]
|
||||
val post = feedContent[position]
|
||||
val metrics = DisplayMetrics()
|
||||
|
||||
//Limit the height of the different images
|
||||
@ -72,7 +62,7 @@ class FeedRecyclerViewAdapter(
|
||||
holder.nshares.setTypeface(null, Typeface.BOLD)
|
||||
}
|
||||
|
||||
override fun getItemCount(): Int = posts.size
|
||||
override fun getItemCount(): Int = feedContent.size
|
||||
|
||||
/**
|
||||
* Represents the posts that will be contained within the feed
|
@ -0,0 +1,44 @@
|
||||
package com.h.pixeldroid.fragments.feeds
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import com.h.pixeldroid.R
|
||||
import com.h.pixeldroid.objects.Notification
|
||||
import kotlinx.android.synthetic.main.fragment_feed.*
|
||||
|
||||
/**
|
||||
* A fragment representing a list of Items.
|
||||
*/
|
||||
class NotificationsFragment : FeedFragment<Notification, NotificationsRecyclerViewAdapter.ViewHolder>() {
|
||||
|
||||
|
||||
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater, container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
): View? {
|
||||
|
||||
val view = super.onCreateView(inflater, container)
|
||||
|
||||
adapter = NotificationsRecyclerViewAdapter()
|
||||
list.adapter = adapter
|
||||
|
||||
|
||||
return view
|
||||
}
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
|
||||
swipeRefreshLayout.setOnRefreshListener {
|
||||
val call = pixelfedAPI.notifications("Bearer $accessToken", min_id="1")
|
||||
doRequest(call)
|
||||
}
|
||||
val call = pixelfedAPI.notifications("Bearer $accessToken", min_id="1")
|
||||
doRequest(call)
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
package com.h.pixeldroid.fragments
|
||||
package com.h.pixeldroid.fragments.feeds
|
||||
|
||||
|
||||
import android.content.Context
|
||||
@ -16,17 +16,14 @@ import com.bumptech.glide.Glide
|
||||
import com.bumptech.glide.request.RequestOptions
|
||||
import com.h.pixeldroid.PostActivity
|
||||
import com.h.pixeldroid.R
|
||||
import com.h.pixeldroid.models.Post
|
||||
import com.h.pixeldroid.models.Post.Companion.POST_TAG
|
||||
import com.h.pixeldroid.objects.Status.Companion.POST_TAG
|
||||
import com.h.pixeldroid.objects.Notification
|
||||
import kotlinx.android.synthetic.main.fragment_notifications.view.*
|
||||
|
||||
/**
|
||||
* [RecyclerView.Adapter] that can display a [Notification]
|
||||
*/
|
||||
class NotificationsRecyclerViewAdapter: RecyclerView.Adapter<NotificationsRecyclerViewAdapter.ViewHolder>() {
|
||||
private val notifications: ArrayList<Notification> = arrayListOf()
|
||||
private lateinit var context: Context
|
||||
class NotificationsRecyclerViewAdapter: FeedsRecyclerViewAdapter<Notification, NotificationsRecyclerViewAdapter.ViewHolder>() {
|
||||
|
||||
private val mOnClickListener: View.OnClickListener
|
||||
|
||||
@ -41,7 +38,7 @@ class NotificationsRecyclerViewAdapter: RecyclerView.Adapter<NotificationsRecycl
|
||||
when (notification.type){
|
||||
Notification.NotificationType.mention, Notification.NotificationType.favourite-> {
|
||||
intent = Intent(context, PostActivity::class.java)
|
||||
intent.putExtra(POST_TAG, Post(notification.status))
|
||||
intent.putExtra(POST_TAG, notification.status)
|
||||
}
|
||||
Notification.NotificationType.reblog-> {
|
||||
Toast.makeText(context,"Can't see shares yet, sorry!",Toast.LENGTH_SHORT).show()
|
||||
@ -55,14 +52,9 @@ class NotificationsRecyclerViewAdapter: RecyclerView.Adapter<NotificationsRecycl
|
||||
context.startActivity(intent)
|
||||
}
|
||||
|
||||
fun initializeWith(newNotifications: List<Notification>){
|
||||
notifications.clear()
|
||||
notifications.addAll(newNotifications)
|
||||
notifyDataSetChanged()
|
||||
}
|
||||
fun addNotifications(newNotifications: List<Notification>){
|
||||
val oldSize = notifications.size
|
||||
notifications.addAll(newNotifications)
|
||||
val oldSize = feedContent.size
|
||||
feedContent.addAll(newNotifications)
|
||||
notifyItemRangeInserted(oldSize, newNotifications.size)
|
||||
}
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
|
||||
@ -74,11 +66,11 @@ class NotificationsRecyclerViewAdapter: RecyclerView.Adapter<NotificationsRecycl
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
|
||||
val notification = notifications[position]
|
||||
val notification = feedContent[position]
|
||||
Glide.with(holder.mView).load(notification.account.avatar_static).apply(RequestOptions().circleCrop())
|
||||
.placeholder(R.drawable.ic_default_user).into(holder.avatar)
|
||||
|
||||
val previewUrl = notification.status?.media_attachments?.get(0)?.preview_url
|
||||
val previewUrl = notification.status?.media_attachments?.getOrNull(0)?.preview_url
|
||||
if(!previewUrl.isNullOrBlank()){
|
||||
Glide.with(holder.mView).load(previewUrl)
|
||||
.placeholder(R.drawable.ic_picture_fallback).into(holder.photoThumbnail)
|
||||
@ -125,7 +117,6 @@ class NotificationsRecyclerViewAdapter: RecyclerView.Adapter<NotificationsRecycl
|
||||
return Pair(context.getString(format), context.getDrawable(drawable))
|
||||
}
|
||||
|
||||
override fun getItemCount(): Int = notifications.size
|
||||
|
||||
inner class ViewHolder(val mView: View) : RecyclerView.ViewHolder(mView) {
|
||||
val notificationType: TextView = mView.notification_type
|
@ -1,86 +0,0 @@
|
||||
package com.h.pixeldroid.models
|
||||
|
||||
import android.content.Context
|
||||
import android.graphics.Typeface
|
||||
import android.view.View
|
||||
import android.widget.TextView
|
||||
import androidx.core.content.ContextCompat.startActivity
|
||||
import androidx.fragment.app.Fragment
|
||||
import com.h.pixeldroid.R
|
||||
import com.h.pixeldroid.objects.Status
|
||||
import com.h.pixeldroid.utils.ImageConverter
|
||||
import java.io.Serializable
|
||||
|
||||
class Post(private val status: Status?) : Serializable {
|
||||
companion object {
|
||||
const val POST_TAG = "postTag"
|
||||
const val POST_FRAG_TAG = "postFragTag"
|
||||
}
|
||||
|
||||
fun getPostUrl() : String? = status?.media_attachments?.get(0)?.url
|
||||
fun getProfilePicUrl() : String? = status?.account?.avatar
|
||||
|
||||
fun getDescription() : CharSequence {
|
||||
val description = status?.content as CharSequence
|
||||
if(description.isEmpty()) {
|
||||
return "No description"
|
||||
}
|
||||
return description
|
||||
}
|
||||
|
||||
fun getUsername() : CharSequence {
|
||||
var name = status?.account?.username
|
||||
if (name.isNullOrEmpty()) {
|
||||
name = status?.account?.display_name
|
||||
}
|
||||
return name!!
|
||||
}
|
||||
fun getUsernameDescription() : CharSequence {
|
||||
return status?.account?.display_name ?: ""
|
||||
}
|
||||
|
||||
fun getNLikes() : CharSequence {
|
||||
val nLikes : Int = status?.favourites_count ?: 0
|
||||
return "$nLikes Likes"
|
||||
}
|
||||
|
||||
fun getNShares() : CharSequence {
|
||||
val nShares : Int = status?.reblogs_count ?: 0
|
||||
return "$nShares Shares"
|
||||
}
|
||||
|
||||
fun setupPost(fragment: Fragment, rootView : View) {
|
||||
//Setup username as a button that opens the profile
|
||||
val username = rootView.findViewById<TextView>(R.id.username)
|
||||
username.text = this.getUsername()
|
||||
username.setTypeface(null, Typeface.BOLD)
|
||||
|
||||
val usernameDesc = rootView.findViewById<TextView>(R.id.usernameDesc)
|
||||
usernameDesc.text = this.getUsernameDescription()
|
||||
usernameDesc.setTypeface(null, Typeface.BOLD)
|
||||
|
||||
val description = rootView.findViewById<TextView>(R.id.description)
|
||||
description.text = this.getDescription()
|
||||
|
||||
val nlikes = rootView.findViewById<TextView>(R.id.nlikes)
|
||||
nlikes.text = this.getNLikes()
|
||||
nlikes.setTypeface(null, Typeface.BOLD)
|
||||
|
||||
val nshares = rootView.findViewById<TextView>(R.id.nshares)
|
||||
nshares.text = this.getNShares()
|
||||
nshares.setTypeface(null, Typeface.BOLD)
|
||||
|
||||
//Setup post and profile images
|
||||
ImageConverter.setImageViewFromURL(
|
||||
fragment,
|
||||
getPostUrl(),
|
||||
rootView.findViewById(R.id.postPicture)
|
||||
)
|
||||
ImageConverter.setImageViewFromURL(
|
||||
fragment,
|
||||
getProfilePicUrl(),
|
||||
rootView.findViewById(R.id.profilePic)
|
||||
)
|
||||
}
|
||||
|
||||
}
|
@ -1,5 +1,11 @@
|
||||
package com.h.pixeldroid.objects
|
||||
|
||||
import android.graphics.Typeface
|
||||
import android.view.View
|
||||
import android.widget.TextView
|
||||
import androidx.fragment.app.Fragment
|
||||
import com.h.pixeldroid.R
|
||||
import com.h.pixeldroid.utils.ImageConverter
|
||||
import java.io.Serializable
|
||||
|
||||
/*
|
||||
@ -43,6 +49,77 @@ data class Status(
|
||||
val pinned: Boolean
|
||||
) : Serializable
|
||||
{
|
||||
|
||||
companion object {
|
||||
const val POST_TAG = "postTag"
|
||||
const val POST_FRAG_TAG = "postFragTag"
|
||||
}
|
||||
|
||||
fun getPostUrl() : String? = media_attachments?.getOrNull(0)?.url
|
||||
fun getProfilePicUrl() : String? = account?.avatar
|
||||
|
||||
fun getDescription() : CharSequence {
|
||||
val description = content as CharSequence
|
||||
if(description.isEmpty()) {
|
||||
return "No description"
|
||||
}
|
||||
return description
|
||||
}
|
||||
|
||||
fun getUsername() : CharSequence {
|
||||
var name = account?.username
|
||||
if (name.isNullOrEmpty()) {
|
||||
name = account?.display_name
|
||||
}
|
||||
return name!!
|
||||
}
|
||||
fun getUsernameDescription() : CharSequence {
|
||||
return account?.display_name ?: ""
|
||||
}
|
||||
|
||||
fun getNLikes() : CharSequence {
|
||||
val nLikes : Int = favourites_count ?: 0
|
||||
return "$nLikes Likes"
|
||||
}
|
||||
|
||||
fun getNShares() : CharSequence {
|
||||
val nShares : Int = reblogs_count ?: 0
|
||||
return "$nShares Shares"
|
||||
}
|
||||
|
||||
fun setupPost(fragment: Fragment, rootView : View) {
|
||||
//Setup username as a button that opens the profile
|
||||
val username = rootView.findViewById<TextView>(R.id.username)
|
||||
username.text = this.getUsername()
|
||||
username.setTypeface(null, Typeface.BOLD)
|
||||
|
||||
val usernameDesc = rootView.findViewById<TextView>(R.id.usernameDesc)
|
||||
usernameDesc.text = this.getUsernameDescription()
|
||||
usernameDesc.setTypeface(null, Typeface.BOLD)
|
||||
|
||||
val description = rootView.findViewById<TextView>(R.id.description)
|
||||
description.text = this.getDescription()
|
||||
|
||||
val nlikes = rootView.findViewById<TextView>(R.id.nlikes)
|
||||
nlikes.text = this.getNLikes()
|
||||
nlikes.setTypeface(null, Typeface.BOLD)
|
||||
|
||||
val nshares = rootView.findViewById<TextView>(R.id.nshares)
|
||||
nshares.text = this.getNShares()
|
||||
nshares.setTypeface(null, Typeface.BOLD)
|
||||
|
||||
//Setup post and profile images
|
||||
ImageConverter.setImageViewFromURL(
|
||||
fragment,
|
||||
getPostUrl(),
|
||||
rootView.findViewById(R.id.postPicture)
|
||||
)
|
||||
ImageConverter.setImageViewFromURL(
|
||||
fragment,
|
||||
getProfilePicUrl(),
|
||||
rootView.findViewById(R.id.profilePic)
|
||||
)
|
||||
}
|
||||
enum class Visibility : Serializable {
|
||||
public, unlisted, private, direct
|
||||
}
|
||||
|
@ -8,7 +8,6 @@ import androidx.fragment.app.FragmentActivity
|
||||
import com.bumptech.glide.Glide
|
||||
import com.bumptech.glide.request.RequestOptions
|
||||
import com.h.pixeldroid.R
|
||||
import com.h.pixeldroid.models.Post
|
||||
|
||||
class ImageConverter {
|
||||
companion object {
|
||||
|
@ -6,34 +6,58 @@
|
||||
android:layout_height="match_parent"
|
||||
tools:context=".LoginActivity">
|
||||
|
||||
<Button
|
||||
android:id="@+id/connect_instance_button"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="36dp"
|
||||
android:text="Connect"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintHorizontal_bias="0.498"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/domainTextInputLayout" />
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:id="@+id/domainTextInputLayout"
|
||||
android:layout_width="250dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:hint="Domain of your instance"
|
||||
app:errorEnabled="true"
|
||||
<ScrollView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:fillViewport="true"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintVertical_bias="0.40">
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:id="@+id/editText"
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:ems="10"
|
||||
android:inputType="textUri" />
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
android:gravity="center"
|
||||
android:orientation="vertical">
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:id="@+id/domainTextInputLayout"
|
||||
android:layout_width="250dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center"
|
||||
android:hint="Domain of your instance"
|
||||
app:errorEnabled="true">
|
||||
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:id="@+id/editText"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:ems="10"
|
||||
android:inputType="textUri" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/connect_instance_button"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="36dp"
|
||||
android:text="Connect" />
|
||||
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/progressLayout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:gravity="center"
|
||||
android:orientation="vertical"
|
||||
android:visibility="gone">
|
||||
|
||||
<ProgressBar
|
||||
style="?android:attr/progressBarStyle"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content" />
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
</ScrollView>
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
27
app/src/main/res/layout/fragment_feed.xml
Normal file
27
app/src/main/res/layout/fragment_feed.xml
Normal file
@ -0,0 +1,27 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
|
||||
android:id="@+id/swipeRefreshLayout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_behavior="com.google.android.material.appbar.AppBarLayout$ScrollingViewBehavior">
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/list"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginLeft="16dp"
|
||||
android:layout_marginRight="16dp"
|
||||
app:layoutManager="LinearLayoutManager" />
|
||||
|
||||
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/progressBar"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center" />
|
||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
@ -4,7 +4,12 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
tools:context=".fragments.HomeFragment">
|
||||
tools:context=".fragments.feeds.HomeFragment">
|
||||
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
|
||||
android:id="@+id/swipeRefreshLayout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_behavior="com.google.android.material.appbar.AppBarLayout$ScrollingViewBehavior">
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/feedList"
|
||||
@ -16,10 +21,11 @@
|
||||
app:layoutManager="LinearLayoutManager"
|
||||
tools:listitem="@layout/post_fragment" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
android:gravity="center"/>
|
||||
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
|
||||
<ProgressBar
|
||||
android:id="@+id/progressBar"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center" />
|
||||
|
||||
</FrameLayout>
|
@ -1,21 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:id="@+id/swipeRefreshLayout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_behavior="com.google.android.material.appbar.AppBarLayout$ScrollingViewBehavior">
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/list"
|
||||
android:name="com.h.pixeldroid.fragments.NotificationsFragment"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginLeft="16dp"
|
||||
android:layout_marginRight="16dp"
|
||||
app:layoutManager="LinearLayoutManager"
|
||||
tools:context=".fragments.NotificationsFragment"
|
||||
tools:listitem="@layout/fragment_notifications" />
|
||||
|
||||
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
|
@ -1,6 +1,5 @@
|
||||
package com.h.pixeldroid
|
||||
|
||||
import com.h.pixeldroid.models.Post
|
||||
import com.h.pixeldroid.objects.*
|
||||
import org.junit.Assert
|
||||
import org.junit.Test
|
||||
@ -26,45 +25,42 @@ class PostUnitTest {
|
||||
tags= listOf(Tag(name="hiking", url="https://pixelfed.de/discover/tags/hiking", history=null), Tag(name="nature", url="https://pixelfed.de/discover/tags/nature", history=null), Tag(name="rotavicentina", url="https://pixelfed.de/discover/tags/rotavicentina", history=null)),
|
||||
emojis= emptyList(), reblogs_count=0, favourites_count=0, replies_count=0, url="https://pixelfed.de/p/Miike/140364967936397312",
|
||||
in_reply_to_id=null, in_reply_to_account=null, reblog=null, poll=null, card=null, language=null, text=null, favourited=false, reblogged=false, muted=false, bookmarked=false, pinned=false)
|
||||
private val post = Post(status)
|
||||
|
||||
@Test
|
||||
fun getPostUrlReturnsAValidURL() = Assert.assertNotNull(post.getPostUrl())
|
||||
fun getPostUrlReturnsAValidURL() = Assert.assertNotNull(status.getPostUrl())
|
||||
|
||||
@Test
|
||||
fun getProfilePicUrlReturnsAValidURL() = Assert.assertNotNull(post.getProfilePicUrl())
|
||||
fun getProfilePicUrlReturnsAValidURL() = Assert.assertNotNull(status.getProfilePicUrl())
|
||||
|
||||
@Test
|
||||
fun getDescriptionReturnsDefaultIfEmpty() {
|
||||
val emptyDescStatus = status.copy(content = "")
|
||||
val emptyDescPost = Post(emptyDescStatus)
|
||||
Assert.assertEquals( "No description", emptyDescPost.getDescription())
|
||||
Assert.assertEquals( "No description", emptyDescStatus.getDescription())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun getDescriptionReturnsAValidDesc() = Assert.assertNotNull(post.getDescription())
|
||||
fun getDescriptionReturnsAValidDesc() = Assert.assertNotNull(status.getDescription())
|
||||
|
||||
@Test
|
||||
fun getDescriptionReturnsACorrectDesc() = Assert.assertEquals(status.content, post.getDescription())
|
||||
fun getDescriptionReturnsACorrectDesc() = Assert.assertEquals(status.content, status.getDescription())
|
||||
|
||||
@Test
|
||||
fun getUsernameReturnsACorrectName() = Assert.assertEquals(status.account.username, post.getUsername())
|
||||
fun getUsernameReturnsACorrectName() = Assert.assertEquals(status.account.username, status.getUsername())
|
||||
|
||||
@Test
|
||||
fun getUsernameReturnsOtherNameIfUsernameIsNull() {
|
||||
val emptyDescStatus = status.copy(account = status.account.copy(username = ""))
|
||||
val spePost = Post(emptyDescStatus)
|
||||
Assert.assertEquals(status.account.display_name, spePost.getUsername())
|
||||
Assert.assertEquals(status.account.display_name, emptyDescStatus.getUsername())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun getNLikesReturnsCorrectFormat() {
|
||||
Assert.assertEquals("${status.favourites_count} Likes", post.getNLikes())
|
||||
Assert.assertEquals("${status.favourites_count} Likes", status.getNLikes())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun getNSharesReturnsCorrectFormat() {
|
||||
Assert.assertEquals("${status.reblogs_count} Shares", post.getNShares())
|
||||
Assert.assertEquals("${status.reblogs_count} Shares", status.getNShares())
|
||||
}
|
||||
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user