added programme fragment with simple RecyclerView

remotes/origin/devel
yattoz 2019-12-18 00:42:03 +01:00
parent 5214a20173
commit c20727fca7
11 changed files with 189 additions and 29 deletions

View File

@ -3,15 +3,17 @@ package fr.forum_thalie.tsumugi.planning
import android.content.Context import android.content.Context
import androidx.lifecycle.MutableLiveData import androidx.lifecycle.MutableLiveData
import fr.forum_thalie.tsumugi.Async import fr.forum_thalie.tsumugi.Async
import fr.forum_thalie.tsumugi.weekdays
import org.json.JSONObject import org.json.JSONObject
import java.io.IOException import java.io.IOException
import java.net.URL import java.net.URL
class Planning { class Planning {
private val programmes: ArrayList<Programme> = ArrayList() val programmes: ArrayList<Programme> = ArrayList()
private var regularProgramme: String? = null private var regularProgramme: String? = null
val currentProgramme: MutableLiveData<String> = MutableLiveData() val currentProgramme: MutableLiveData<String> = MutableLiveData()
val isProgrammeUpdated: MutableLiveData<Boolean> = MutableLiveData()
private fun findCurrentProgramme(): String private fun findCurrentProgramme(): String
{ {
@ -59,7 +61,18 @@ class Planning {
for (i in 0 until programList.length()) for (i in 0 until programList.length())
{ {
val item = programList[i] as JSONObject val item = programList[i] as JSONObject
val periodicity = item.getInt("periodicity") var periodicityDec = item.getInt("periodicity")
var periodicity = 0b0000000
var po = 1000000
for (j in 0 until weekdays.size)
{
if (periodicityDec / (po) > 0)
{
periodicityDec -= po
periodicity += 1 shl (weekdays.size-1 - j)
}
po /= 10
}
val hourBeginS = item.getString("hour_begin").split(":") val hourBeginS = item.getString("hour_begin").split(":")
val hourBegin = hourBeginS.first().toInt()*60 + hourBeginS.last().toInt() val hourBegin = hourBeginS.first().toInt()*60 + hourBeginS.last().toInt()
val hourEndS = item.getString("hour_end").split(":") val hourEndS = item.getString("hour_end").split(":")
@ -70,6 +83,7 @@ class Planning {
} }
if (result.has("regular_programme")) if (result.has("regular_programme"))
regularProgramme = result.getString("regular_programme") regularProgramme = result.getString("regular_programme")
isProgrammeUpdated.value = true
} }
Async(scrape, post) Async(scrape, post)
} }

View File

@ -2,11 +2,13 @@ package fr.forum_thalie.tsumugi.planning
import android.util.Log import android.util.Log
import fr.forum_thalie.tsumugi.tag import fr.forum_thalie.tsumugi.tag
import fr.forum_thalie.tsumugi.weekdays
import java.util.* import java.util.*
import kotlin.collections.ArrayList
class Programme (val title: String, private val periodicity: Int, private val hourBegin: Int, private val hourEnd: Int) { class Programme (val title: String, private val periodicity: Int, private val hourBegin: Int, private val hourEnd: Int) {
fun isCurrent(): Boolean { fun isCurrent(): Boolean {
val now = Calendar.getInstance() val now = Calendar.getInstance(TimeZone.getTimeZone("GMT+1"))
val currentDay = val currentDay =
if (now.get(Calendar.DAY_OF_WEEK) - 1 == 0) 6 else now.get(Calendar.DAY_OF_WEEK) - 2 if (now.get(Calendar.DAY_OF_WEEK) - 1 == 0) 6 else now.get(Calendar.DAY_OF_WEEK) - 2
// 0 (Monday) to 5 (Saturday) + 6 (Sunday) // 0 (Monday) to 5 (Saturday) + 6 (Sunday)
@ -16,9 +18,9 @@ class Programme (val title: String, private val periodicity: Int, private val ho
// OR // OR
// - Yesterday is flagged in the "periodicity" bit array AND the program does span over 2 days (night programs). // - Yesterday is flagged in the "periodicity" bit array AND the program does span over 2 days (night programs).
// We'll check a after this whether the current hour is within the span. // We'll check a after this whether the current hour is within the span.
val isToday: Boolean = ((((1000000 shr currentDay) and (periodicity)) != 0)) val isToday: Boolean = (((0b1000000 shr currentDay) and (periodicity)) != 0)
val isSpanningOverNight = val isSpanningOverNight =
(((1000000 shr ((currentDay - 1) % 7) and (periodicity)) != 0) && hourEnd < hourBegin) (((0b1000000 shr ((currentDay - 1) % 7) and (periodicity)) != 0) && hourEnd < hourBegin)
Log.d(tag, "$title is today: $isToday or spanning $isSpanningOverNight") Log.d(tag, "$title is today: $isToday or spanning $isSpanningOverNight")
// shr = shift-right. It's a binary mask. // shr = shift-right. It's a binary mask.
@ -44,6 +46,26 @@ class Programme (val title: String, private val periodicity: Int, private val ho
return "Title: $title, time info (periodicity, begin, end): $periodicity, $hourBegin, $hourEnd" return "Title: $title, time info (periodicity, begin, end): $periodicity, $hourBegin, $hourEnd"
} }
fun begin(): String {
return "%02d:%02d".format(hourBegin/60, hourBegin%60)
}
fun end(): String {
return "%02d:%02d".format(hourEnd/60, hourEnd%60)
}
fun days(): String {
val res = ArrayList<String>()
for (i in 0 until weekdays.size) {
if (((0b1000000 shr i) and (periodicity)) != 0)
{
res.add(weekdays[i])
}
}
return res.toString().drop(1).dropLast(1) // drop '[' and ']'
}
init { init {
Log.d(tag, this.toString()) Log.d(tag, this.toString())
} }

View File

@ -54,7 +54,7 @@ class NowPlayingFragment : Fragment() {
// Note: these values are not used in the generic app, but if you want to, you can use them. // Note: these values are not used in the generic app, but if you want to, you can use them.
val songTitleNextText: TextView = root.findViewById(R.id.text_song_title_next) val songTitleNextText: TextView = root.findViewById(R.id.text_song_title_next)
val songArtistNextText: TextView = root.findViewById(R.id.text_song_artist_next) //val songArtistNextText: TextView = root.findViewById(R.id.text_song_artist_next)
/* /*
val streamerNameText : TextView = root.findViewById(R.id.streamerName) val streamerNameText : TextView = root.findViewById(R.id.streamerName)

View File

@ -10,6 +10,7 @@ import androidx.fragment.app.FragmentPagerAdapter
import androidx.viewpager.widget.ViewPager import androidx.viewpager.widget.ViewPager
import com.google.android.material.tabs.TabLayout import com.google.android.material.tabs.TabLayout
import fr.forum_thalie.tsumugi.R import fr.forum_thalie.tsumugi.R
import fr.forum_thalie.tsumugi.ui.songs.programme.ProgrammeFragment
import fr.forum_thalie.tsumugi.ui.songs.queuelp.LastPlayedFragment import fr.forum_thalie.tsumugi.ui.songs.queuelp.LastPlayedFragment
class SongsFragment : Fragment() { class SongsFragment : Fragment() {
@ -32,14 +33,12 @@ class SongsFragment : Fragment() {
// You can add more fragments to the adapter, to display more information (for example with R/a/dio, queue, request, faves...) // You can add more fragments to the adapter, to display more information (for example with R/a/dio, queue, request, faves...)
adapter.addFragment(ProgrammeFragment.newInstance(), getString(R.string.programme)) adapter.addFragment(ProgrammeFragment.newInstance(), getString(R.string.programme))
viewPager.adapter = adapter viewPager.adapter = adapter
val tabLayout : TabLayout = root.findViewById(R.id.tabLayout) val tabLayout : TabLayout = root.findViewById(R.id.tabLayout)
tabLayout.setupWithViewPager(viewPager) tabLayout.setupWithViewPager(viewPager)
Log.d(tag, "SongFragment view created") Log.d(tag, "SongFragment view created")
return root return root
} }

View File

@ -0,0 +1,61 @@
package fr.forum_thalie.tsumugi.ui.songs.programme
import android.annotation.SuppressLint
import android.util.Log
import android.view.LayoutInflater
import android.view.ViewGroup
import android.widget.TextView
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.recyclerview.widget.RecyclerView
import fr.forum_thalie.tsumugi.R
import fr.forum_thalie.tsumugi.colorBlue
import fr.forum_thalie.tsumugi.colorWhited
import fr.forum_thalie.tsumugi.planning.Programme
import fr.forum_thalie.tsumugi.tag
import kotlinx.android.synthetic.main.programme_view.view.*
import kotlinx.android.synthetic.main.song_view.view.*
class ProgrammeAdapter(private val dataSet: ArrayList<Programme>
/*,
context: Context,
resource: Int,
objects: Array<out Song>*/
) : RecyclerView.Adapter<ProgrammeAdapter.MyViewHolder>() /*ArrayAdapter<Song>(context, resource, objects)*/ {
class MyViewHolder(view: ConstraintLayout) : RecyclerView.ViewHolder(view)
// Create new views (invoked by the layout manager)
override fun onCreateViewHolder(parent: ViewGroup,
viewType: Int): MyViewHolder {
// create a new view
val view = LayoutInflater.from(parent.context)
.inflate(R.layout.programme_view, parent, false) as ConstraintLayout
return MyViewHolder(view)
}
// Replace the contents of a view (invoked by the layout manager)
@SuppressLint("SetTextI18n")
override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
val programmeStart = holder.itemView.findViewById<TextView>(R.id.programme_start)
val programmeEnd = holder.itemView.findViewById<TextView>(R.id.programme_end)
val programmeName = holder.itemView.findViewById<TextView>(R.id.programme_name)
val programmeDays = holder.itemView.findViewById<TextView>(R.id.programme_days)
programmeStart.text = dataSet[position].begin()
programmeName.text = dataSet[position].title
programmeEnd.text = dataSet[position].end()
programmeDays.text = dataSet[position].days()
}
// Return the size of your dataset (invoked by the layout manager)
override fun getItemCount() = dataSet.size
/*
override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {
// create a new view
val view = LayoutInflater.from(parent.context)
.inflate(R.layout.song_view, parent, false) as ConstraintLayout
}
*/
}

View File

@ -1,13 +1,15 @@
package fr.forum_thalie.tsumugi.ui.songs package fr.forum_thalie.tsumugi.ui.songs.programme
import android.os.Bundle import android.os.Bundle
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.lifecycle.Observer
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import fr.forum_thalie.tsumugi.R import fr.forum_thalie.tsumugi.R
import fr.forum_thalie.tsumugi.planning.Planning
import fr.forum_thalie.tsumugi.playerstore.PlayerStore import fr.forum_thalie.tsumugi.playerstore.PlayerStore
import fr.forum_thalie.tsumugi.ui.songs.queuelp.LastPlayedFragment import fr.forum_thalie.tsumugi.ui.songs.queuelp.LastPlayedFragment
import fr.forum_thalie.tsumugi.ui.songs.queuelp.SongAdaptater import fr.forum_thalie.tsumugi.ui.songs.queuelp.SongAdaptater
@ -24,34 +26,30 @@ class ProgrammeFragment : Fragment() {
): View? { ): View? {
// Inflate the layout for this fragment // Inflate the layout for this fragment
val root = inflater.inflate(R.layout.fragment_programme, container, false) val root = inflater.inflate(R.layout.fragment_programme, container, false)
/*
viewManager = LinearLayoutManager(context) viewManager = LinearLayoutManager(context)
viewAdapter = SongAdaptater(PlayerStore.instance.lp) viewAdapter = ProgrammeAdapter(Planning.instance.programmes)
recyclerView = root.findViewById<RecyclerView>(R.id.programme_recycler).apply {
recyclerView = root.findViewById<RecyclerView>(R.id.queue_lp_recycler).apply {
// use this setting to improve performance if you know that changes // use this setting to improve performance if you know that changes
// in content do not change the layout size of the RecyclerView // in content do not change the layout size of the RecyclerView
setHasFixedSize(true) setHasFixedSize(true)
// use a linear layout manager
layoutManager = viewManager layoutManager = viewManager
// specify an viewAdapter (see also next example)
adapter = viewAdapter adapter = viewAdapter
} }
Planning.instance.isProgrammeUpdated.observeForever(isProgrammeUpdatedObserver)
*/
return root return root
} }
private val isProgrammeUpdatedObserver = Observer<Boolean> {
viewAdapter.notifyDataSetChanged()
}
override fun onDestroyView() { override fun onDestroyView() {
super.onDestroyView() super.onDestroyView()
Planning.instance.isProgrammeUpdated.removeObserver(isProgrammeUpdatedObserver)
} }
companion object { companion object {
@JvmStatic @JvmStatic
fun newInstance() = LastPlayedFragment() fun newInstance() = ProgrammeFragment()
} }
} }

View File

@ -2,6 +2,7 @@ package fr.forum_thalie.tsumugi.ui.songs.queuelp
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.graphics.Color import android.graphics.Color
import android.util.Log
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.ViewGroup import android.view.ViewGroup
import androidx.constraintlayout.widget.ConstraintLayout import androidx.constraintlayout.widget.ConstraintLayout
@ -11,6 +12,7 @@ import fr.forum_thalie.tsumugi.R
import fr.forum_thalie.tsumugi.colorBlue import fr.forum_thalie.tsumugi.colorBlue
import fr.forum_thalie.tsumugi.colorWhited import fr.forum_thalie.tsumugi.colorWhited
import fr.forum_thalie.tsumugi.playerstore.Song import fr.forum_thalie.tsumugi.playerstore.Song
import fr.forum_thalie.tsumugi.tag
import kotlinx.android.synthetic.main.song_view.view.* import kotlinx.android.synthetic.main.song_view.view.*
import kotlin.collections.ArrayList import kotlin.collections.ArrayList

View File

@ -1,12 +1,12 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" <LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:layout_margin="8dp" android:layout_margin="8dp"
tools:context=".ui.songs.queuelp.LastPlayedFragment"> tools:context=".ui.songs.queuelp.LastPlayedFragment">
<!-- TODO: Update blank fragment layout -->
<androidx.recyclerview.widget.RecyclerView <androidx.recyclerview.widget.RecyclerView
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"

View File

@ -1,7 +1,19 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout <LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android" xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent" xmlns:tools="http://schemas.android.com/tools"
android:layout_height="match_parent"> android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="8dp"
tools:context=".ui.songs.programme.ProgrammeFragment">
</androidx.constraintlayout.widget.ConstraintLayout> <androidx.recyclerview.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/programme_recycler"
android:scrollbars="vertical"
>
</androidx.recyclerview.widget.RecyclerView>
</LinearLayout>

View File

@ -0,0 +1,52 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="8dp">
<TextView
android:id="@+id/programme_days"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
/>
<TextView
android:id="@+id/programme_start"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintTop_toBottomOf="@id/programme_days"
app:layout_constraintStart_toStartOf="parent"
/>
<TextView
android:id="@+id/programme_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintTop_toBottomOf="@id/programme_start"
app:layout_constraintStart_toStartOf="parent"
/>
<TextView
android:id="@+id/programme_end"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintTop_toBottomOf="@id/programme_name"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
/>
<View
android:id="@+id/divider"
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="?android:attr/listDivider"
app:layout_constraintTop_toBottomOf="@id/programme_end"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -14,7 +14,7 @@
<string name="volume">Volume: </string> <string name="volume">Volume: </string>
<string name="up_next">Up next:</string> <string name="up_next">Émission en cours :</string>
<string name="now_streaming">Now streaming</string> <string name="now_streaming">Now streaming</string>
<string name="error_webView">Error loading WebView. Try downloading Google Chrome on Google Play, or enabling it if you disabled it.</string> <string name="error_webView">Error loading WebView. Try downloading Google Chrome on Google Play, or enabling it if you disabled it.</string>
<string name="action_settings">Settings</string> <string name="action_settings">Settings</string>