From 305acc87e762919d0d3c4305087e832a3b07fa7d Mon Sep 17 00:00:00 2001 From: ivan agosto Date: Thu, 7 Feb 2019 08:27:25 -0600 Subject: [PATCH 01/10] Nsfw content blocked by default --- app/src/main/java/org/libre/agosto/p2play/ManagerSingleton.kt | 1 + app/src/main/java/org/libre/agosto/p2play/SplashActivity.kt | 3 ++- app/src/main/java/org/libre/agosto/p2play/ajax/Videos.kt | 4 +++- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/org/libre/agosto/p2play/ManagerSingleton.kt b/app/src/main/java/org/libre/agosto/p2play/ManagerSingleton.kt index 65b9e60..5c9ef84 100644 --- a/app/src/main/java/org/libre/agosto/p2play/ManagerSingleton.kt +++ b/app/src/main/java/org/libre/agosto/p2play/ManagerSingleton.kt @@ -9,6 +9,7 @@ object ManagerSingleton { var url: String?= null var user: UserModel = UserModel() var token: TokenModel = TokenModel() + var nfsw: Boolean = false // var keys: fun Toast(text: String?) { diff --git a/app/src/main/java/org/libre/agosto/p2play/SplashActivity.kt b/app/src/main/java/org/libre/agosto/p2play/SplashActivity.kt index fc5845c..9291f83 100644 --- a/app/src/main/java/org/libre/agosto/p2play/SplashActivity.kt +++ b/app/src/main/java/org/libre/agosto/p2play/SplashActivity.kt @@ -24,8 +24,9 @@ class SplashActivity : AppCompatActivity() { settings = PreferenceManager.getDefaultSharedPreferences(this) - editor = settings.edit() + ManagerSingleton.context = this + ManagerSingleton.nfsw = settings.getBoolean("show_nfsw", false) val host = settings.getString("hostP2play","") val lastHost = settings.getString("last_host","") diff --git a/app/src/main/java/org/libre/agosto/p2play/ajax/Videos.kt b/app/src/main/java/org/libre/agosto/p2play/ajax/Videos.kt index bd3f5b1..486e1d8 100644 --- a/app/src/main/java/org/libre/agosto/p2play/ajax/Videos.kt +++ b/app/src/main/java/org/libre/agosto/p2play/ajax/Videos.kt @@ -3,6 +3,7 @@ package org.libre.agosto.p2play.ajax import android.util.JsonReader import android.util.JsonToken import android.util.Log +import org.libre.agosto.p2play.ManagerSingleton import org.libre.agosto.p2play.models.VideoModel import java.io.InputStreamReader @@ -92,7 +93,8 @@ class Videos: Client() { } private fun getVideos(start:Int, count:Int, sort:String = "-publishedAt", filter:String = ""):ArrayList{ - var params = "start=$start&count=$count&sort=$sort" + val nfsw = ManagerSingleton.nfsw + var params = "start=$start&count=$count&sort=$sort&nsfw=$nfsw" if(filter != "") params+="&filter=$filter" var con=this._newCon("videos?$params","GET") From c07c15c766dd32e25150546732d603f0067293e3 Mon Sep 17 00:00:00 2001 From: ivan agosto Date: Sat, 9 Feb 2019 14:56:56 -0600 Subject: [PATCH 02/10] Search videos and infinite scroll --- .../org/libre/agosto/p2play/MainActivity.kt | 124 +++++++++++++++--- .../agosto/p2play/ReproductorActivity.kt | 1 + .../agosto/p2play/adapters/VideosAdapter.kt | 33 ++++- .../org/libre/agosto/p2play/ajax/Videos.kt | 35 ++++- .../res/drawable/ic_search_black_24dp.xml | 9 ++ .../main/res/layout/activity_reproductor.xml | 30 ++++- app/src/main/res/layout/nav_header_main.xml | 4 +- app/src/main/res/layout/view_video.xml | 7 +- app/src/main/res/menu/main.xml | 6 + app/src/main/res/values-es/strings.xml | 4 +- app/src/main/res/values/strings.xml | 4 +- 11 files changed, 216 insertions(+), 41 deletions(-) create mode 100644 app/src/main/res/drawable/ic_search_black_24dp.xml diff --git a/app/src/main/java/org/libre/agosto/p2play/MainActivity.kt b/app/src/main/java/org/libre/agosto/p2play/MainActivity.kt index 3ceb1a9..7143899 100644 --- a/app/src/main/java/org/libre/agosto/p2play/MainActivity.kt +++ b/app/src/main/java/org/libre/agosto/p2play/MainActivity.kt @@ -15,6 +15,7 @@ import android.view.Menu import android.view.MenuInflater import android.view.MenuItem import android.widget.ImageView +import android.widget.SearchView import com.squareup.picasso.Picasso import kotlinx.android.synthetic.main.activity_main.* import kotlinx.android.synthetic.main.app_bar_main.* @@ -26,7 +27,7 @@ import org.libre.agosto.p2play.models.VideoModel class MainActivity : AppCompatActivity(), NavigationView.OnNavigationItemSelectedListener { private lateinit var recyclerView: RecyclerView - private lateinit var viewAdapter: RecyclerView.Adapter<*> + private lateinit var viewAdapter: RecyclerView.Adapter private lateinit var viewManager: RecyclerView.LayoutManager private val client: Videos = Videos() private lateinit var lastItem: MenuItem @@ -34,6 +35,8 @@ class MainActivity : AppCompatActivity(), NavigationView.OnNavigationItemSelecte lateinit var myMenu: Menu private val _db = Database(this) var section: String = "" + var searchVal: String = "" + var pagination = 0 override fun onCreate(savedInstanceState: Bundle?) { @@ -46,11 +49,13 @@ class MainActivity : AppCompatActivity(), NavigationView.OnNavigationItemSelecte .setAction("Action", null).show() } */ - val toggle = ActionBarDrawerToggle( - this, drawer_layout, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close) + val toggle = ActionBarDrawerToggle(this, drawer_layout, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close) drawer_layout.addDrawerListener(toggle) toggle.syncState() + // Search bar + + // Context for ManagerSingleton ManagerSingleton.context = this @@ -58,8 +63,8 @@ class MainActivity : AppCompatActivity(), NavigationView.OnNavigationItemSelecte viewManager = LinearLayoutManager(this) - // Set data for RecyclerView - this.setData(arrayListOf()) + // Init RecyclerView + this.initRecycler() this.getLastVideos() @@ -74,7 +79,8 @@ class MainActivity : AppCompatActivity(), NavigationView.OnNavigationItemSelecte } // Generic function for set data to RecyclerView - private fun setData(data:ArrayList){ + private fun initRecycler(){ + val data = arrayListOf() viewAdapter = VideosAdapter(data) recyclerView = findViewById(R.id.list).apply { @@ -87,17 +93,48 @@ class MainActivity : AppCompatActivity(), NavigationView.OnNavigationItemSelecte // specify an viewAdapter (see also next example) adapter = viewAdapter + + this.addOnScrollListener(object : RecyclerView.OnScrollListener() { + override fun onScrolled(recyclerView: RecyclerView?, dx: Int, dy: Int) { + super.onScrolled(recyclerView, dx, dy) + + if(!swipeContainer.isRefreshing){ + if(!canScrollVertically(1)){ + loadMore() + } + } + } + }) } - swipeContainer.isRefreshing = false + // swipeContainer.isRefreshing = false + } + + private fun addVideos(videos: ArrayList){ + this.swipeContainer.isRefreshing = true + + try { + if(this.pagination == 0){ + (viewAdapter as VideosAdapter)?.clearData() + recyclerView.scrollToPosition(0) + } + (viewAdapter as VideosAdapter)?.addData(videos) + }catch (err: Exception){ + err.printStackTrace() + ManagerSingleton.Toast(getString(R.string.errorMsg)) + } + + this.swipeContainer.isRefreshing = false } private fun refresh(){ swipeContainer.isRefreshing = true + this.pagination = 0 when(section){ "local" -> this.getLocalVideos() "popular" -> this.getPopularVideos() "last" -> this.getLastVideos() "sub" -> this.getSubscriptionVideos() + "search" -> this.searchVideos() "my_videos" -> { if(ManagerSingleton.token.token != "") this.getMyVideos() @@ -117,9 +154,9 @@ class MainActivity : AppCompatActivity(), NavigationView.OnNavigationItemSelecte section = "sub" setTitle(R.string.title_subscriptions) AsyncTask.execute { - val videos = client.videoSubscriptions(ManagerSingleton.token.token) + val videos = client.videoSubscriptions(ManagerSingleton.token.token, this.pagination) runOnUiThread { - this.setData(videos) + this.addVideos(videos) } } } @@ -130,9 +167,9 @@ class MainActivity : AppCompatActivity(), NavigationView.OnNavigationItemSelecte section = "last" setTitle(R.string.title_recent) AsyncTask.execute { - val videos = client.getLastVideos() + val videos = client.getLastVideos(this.pagination) runOnUiThread { - this.setData(videos) + this.addVideos(videos) } } } @@ -143,9 +180,9 @@ class MainActivity : AppCompatActivity(), NavigationView.OnNavigationItemSelecte section = "popular" setTitle(R.string.title_popular) AsyncTask.execute { - val videos = client.getPopularVideos() + val videos = client.getPopularVideos(this.pagination) runOnUiThread { - this.setData(videos) + this.addVideos(videos) } } } @@ -156,9 +193,9 @@ class MainActivity : AppCompatActivity(), NavigationView.OnNavigationItemSelecte section = "local" setTitle(R.string.title_local) AsyncTask.execute { - val videos = client.getLocalVideos() + val videos = client.getLocalVideos(this.pagination) runOnUiThread { - this.setData(videos) + this.addVideos(videos) } } } @@ -169,9 +206,9 @@ class MainActivity : AppCompatActivity(), NavigationView.OnNavigationItemSelecte section = "my_videos" setTitle(R.string.title_myVideos) AsyncTask.execute { - val videos = client.myVideos(ManagerSingleton.token.token) + val videos = client.myVideos(ManagerSingleton.token.token, this.pagination) runOnUiThread { - this.setData(videos) + this.addVideos(videos) } } } @@ -187,6 +224,26 @@ class MainActivity : AppCompatActivity(), NavigationView.OnNavigationItemSelecte override fun onCreateOptionsMenu(menu: Menu): Boolean { // Inflate the menu; this adds items to the action bar if it is present. menuInflater.inflate(R.menu.main, menu) + + val searchItem = menu.findItem(R.id.app_bar_search) + val searchView = searchItem.actionView as SearchView + + searchView.setOnQueryTextListener(object : SearchView.OnQueryTextListener{ + override fun onQueryTextChange(p0: String?): Boolean { + return true + } + + override fun onQueryTextSubmit(p0: String?): Boolean { + if(!p0.isNullOrBlank()){ + searchVal = p0 + searchVideos() + } + return true + } + + }) + + myMenu = menu setSideData() return true @@ -228,6 +285,9 @@ class MainActivity : AppCompatActivity(), NavigationView.OnNavigationItemSelecte // lastItem.isChecked = false // } lastItem = item + + + // item.isChecked = true when (item.itemId) { R.id.nav_subscriptions->{ @@ -293,5 +353,35 @@ class MainActivity : AppCompatActivity(), NavigationView.OnNavigationItemSelecte } + private fun loadMore(){ + swipeContainer.isRefreshing = true + this.pagination += 30 + + when(section){ + "local" -> this.getLocalVideos() + "popular" -> this.getPopularVideos() + "last" -> this.getLastVideos() + "sub" -> this.getSubscriptionVideos() + "search" -> this.searchVideos() + "my_videos" -> { + if(ManagerSingleton.token.token != "") + this.getMyVideos() + else + this.getLastVideos() + } + } + } + + private fun searchVideos(){ + swipeContainer.isRefreshing = true + section = "search" + setTitle(this.searchVal) + AsyncTask.execute { + val videos = client.search(this.searchVal, this.pagination) + runOnUiThread { + this.addVideos(videos) + } + } + } } diff --git a/app/src/main/java/org/libre/agosto/p2play/ReproductorActivity.kt b/app/src/main/java/org/libre/agosto/p2play/ReproductorActivity.kt index 206642e..afabc49 100644 --- a/app/src/main/java/org/libre/agosto/p2play/ReproductorActivity.kt +++ b/app/src/main/java/org/libre/agosto/p2play/ReproductorActivity.kt @@ -52,6 +52,7 @@ class ReproductorActivity : AppCompatActivity() { viewsTxt.text = this.video.views.toString() + ' ' + getString(R.string.view_text) userTxt.text = this.video.username descriptionVideoTxt.text = this.video.description.toString() + hostTxt.text = this.video.userHost.toString() // Check if user had profile image if(this.video.userImageUrl!="") diff --git a/app/src/main/java/org/libre/agosto/p2play/adapters/VideosAdapter.kt b/app/src/main/java/org/libre/agosto/p2play/adapters/VideosAdapter.kt index a5bae25..5653c66 100644 --- a/app/src/main/java/org/libre/agosto/p2play/adapters/VideosAdapter.kt +++ b/app/src/main/java/org/libre/agosto/p2play/adapters/VideosAdapter.kt @@ -20,6 +20,7 @@ import org.libre.agosto.p2play.models.VideoModel import java.io.InputStream import java.io.Serializable import java.net.URL +import java.util.concurrent.TimeUnit class VideosAdapter(private val myDataset: ArrayList) : RecyclerView.Adapter() { @@ -66,14 +67,40 @@ class VideosAdapter(private val myDataset: ArrayList) : ManagerSingleton.context!!.startActivity(intent) } if(myDataset[position].userImageUrl!="") - Picasso.get().load("https://"+ManagerSingleton.url+myDataset[position].userImageUrl).into(holder.userImg); + Picasso.get().load("https://"+ManagerSingleton.url+myDataset[position].userImageUrl).into(holder.userImg) + else + Picasso.get().load(R.drawable.default_avatar).into(holder.userImg) val viewsText = ManagerSingleton.context!!.getString(R.string.view_text) - val timeText = ManagerSingleton.context!!.getString(R.string.time_text) - holder.description.text = myDataset[position].username+" - "+myDataset[position].views+" "+viewsText+" - "+myDataset[position].duration+" "+timeText + var timeText = ManagerSingleton.context!!.getString(R.string.timeSec_text) + var timeString = myDataset[position].duration.toString() + val seconds = myDataset[position].duration.toInt(); + if(seconds > 60 && seconds < (60 * 60)){ + timeText = ManagerSingleton.context!!.getString(R.string.timeMin_text) + timeString = (seconds / 60).toString() + ":" + (seconds % 60).toString() + } + else if(seconds > (60 * 60)){ + timeText = ManagerSingleton.context!!.getString(R.string.timeHrs_text) + timeString = (seconds / 60 / 60).toString() + ":" + (seconds / 60 % 60).toString() + } + + holder.description.text = myDataset[position].username+" - "+myDataset[position].views+" "+viewsText+" - "+timeString+" "+timeText } // Return the size of your dataset (invoked by the layout manager) override fun getItemCount() = myDataset.size + + fun clearData(){ + myDataset.clear() + notifyDataSetChanged() + } + + fun addData(newItems: ArrayList){ + val lastPos = myDataset.size - 1 + myDataset.addAll(newItems) + notifyItemRangeInserted(lastPos, newItems.size) + } + + } \ No newline at end of file diff --git a/app/src/main/java/org/libre/agosto/p2play/ajax/Videos.kt b/app/src/main/java/org/libre/agosto/p2play/ajax/Videos.kt index 486e1d8..ed077f6 100644 --- a/app/src/main/java/org/libre/agosto/p2play/ajax/Videos.kt +++ b/app/src/main/java/org/libre/agosto/p2play/ajax/Videos.kt @@ -9,7 +9,7 @@ import java.io.InputStreamReader class Videos: Client() { - fun parseVideos(data: JsonReader): ArrayList{ + private fun parseVideos(data: JsonReader): ArrayList{ var videos = arrayListOf() data.beginObject() while (data.hasNext()){ @@ -93,8 +93,8 @@ class Videos: Client() { } private fun getVideos(start:Int, count:Int, sort:String = "-publishedAt", filter:String = ""):ArrayList{ - val nfsw = ManagerSingleton.nfsw - var params = "start=$start&count=$count&sort=$sort&nsfw=$nfsw" + val nsfw = ManagerSingleton.nfsw + var params = "start=$start&count=$count&sort=$sort&nsfw=$nsfw" if(filter != "") params+="&filter=$filter" var con=this._newCon("videos?$params","GET") @@ -125,8 +125,9 @@ class Videos: Client() { return this.getVideos(start, count,"-publishedAt", "local") } - fun myVideos(token: String): ArrayList{ - var con=this._newCon("users/me/videos","GET", token) + fun myVideos(token: String, start: Int = 0, count: Int = 30): ArrayList{ + val params = "start=$start&count=$count" + var con=this._newCon("users/me/videos?$params","GET", token) var videos = arrayListOf() try { if (con.responseCode == 200) { @@ -142,8 +143,28 @@ class Videos: Client() { return videos } - fun videoSubscriptions(token: String): ArrayList{ - var con=this._newCon("users/me/subscriptions/videos","GET", token) + fun videoSubscriptions(token: String, start: Int = 0, count: Int = 30): ArrayList{ + val params = "start=$start&count=$count" + var con=this._newCon("users/me/subscriptions/videos?$params","GET", token) + var videos = arrayListOf() + try { + if (con.responseCode == 200) { + var response = InputStreamReader(con.inputStream) + var data = JsonReader(response) + videos = parseVideos(data) + } + } catch(err:Exception){ + err?.printStackTrace() + Log.d("TypeErr",err?.message ,err.cause) + Log.d("Error","fallo la coneccion") + } + return videos + } + + fun search(text: String, start: Int = 0, count: Int = 30): ArrayList{ + val nsfw = ManagerSingleton.nfsw + val params = "search=$text&start=$start&count=$count&nsfw=$nsfw" + var con=this._newCon("search/videos?$params","GET") var videos = arrayListOf() try { if (con.responseCode == 200) { diff --git a/app/src/main/res/drawable/ic_search_black_24dp.xml b/app/src/main/res/drawable/ic_search_black_24dp.xml new file mode 100644 index 0000000..affc7ba --- /dev/null +++ b/app/src/main/res/drawable/ic_search_black_24dp.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/layout/activity_reproductor.xml b/app/src/main/res/layout/activity_reproductor.xml index 1abc106..7930406 100644 --- a/app/src/main/res/layout/activity_reproductor.xml +++ b/app/src/main/res/layout/activity_reproductor.xml @@ -37,6 +37,7 @@ android:layout_height="wrap_content" android:paddingStart="5dp" android:textAppearance="@android:style/TextAppearance.Material.Large" + android:textSize="18sp" android:textStyle="bold" /> - + android:orientation="vertical"> + + + + + +