Ver código fonte

removed commented unused functions.

yattoz 4 anos atrás
pai
commit
4a2aedd57f

+ 0 - 228
app/src/main/java/fr/forum_thalie/tsumugi/playerstore/PlayerStore.kt Ver arquivo

@@ -6,13 +6,7 @@ import android.graphics.BitmapFactory
6 6
 import android.support.v4.media.session.PlaybackStateCompat
7 7
 import android.util.Log
8 8
 import androidx.lifecycle.MutableLiveData
9
-import androidx.lifecycle.ViewModel
10 9
 import fr.forum_thalie.tsumugi.*
11
-import org.json.JSONObject
12
-import java.io.IOException
13
-import java.io.InputStream
14
-import java.net.URL
15
-
16 10
 
17 11
 class PlayerStore {
18 12
 
@@ -49,113 +43,6 @@ class PlayerStore {
49 43
         listenersCount.value = 0
50 44
     }
51 45
 
52
-    // ##################################################
53
-    // ################# API FUNCTIONS ##################
54
-    // ##################################################
55
-
56
-    /*
57
-    private fun updateApi(resMain: JSONObject, isCompensatingLatency : Boolean = false) {
58
-        // If we're not in PLAYING state, update title / artist metadata. If we're playing, the ICY will take care of that.
59
-        if (playbackState.value != PlaybackStateCompat.STATE_PLAYING || currentSong.title.value.isNullOrEmpty()
60
-            || currentSong.title.value == noConnectionValue)
61
-            currentSong.setTitleArtist(resMain.getString("np"))
62
-
63
-        // only update the value if the song has changed. This avoids to trigger observers when they shouldn't be triggered
64
-        if (currentSong.startTime.value != resMain.getLong("start_time")*1000)
65
-            currentSong.startTime.value = resMain.getLong("start_time")*1000
66
-
67
-        // I noticed that the server has a big (3 to 9 seconds !!) offset for current time.
68
-        // we can measure it when the player is playing, to compensate it and have our progress bar perfectly timed
69
-        // latencyCompensator is set to null when beginPlaying() (we can't measure it at the moment we start playing, since we're in the middle of a song),
70
-        // at this moment, we set it to 0. Then, next time the updateApi is called when we're playing, we measure the latency and we set out latencyComparator.
71
-        if(isCompensatingLatency)
72
-        {
73
-            latencyCompensator = resMain.getLong("current")*1000 - (currentSong.startTime.value ?: resMain.getLong("current")*1000)
74
-            Log.d(tag, playerStoreTag +  "latency compensator set to ${(latencyCompensator).toFloat()/1000} s")
75
-        }
76
-        currentSong.stopTime.value = resMain.getLong("end_time")*1000
77
-        currentTime.value = (resMain.getLong("current"))*1000 - (latencyCompensator)
78
-
79
-        val newStreamer = resMain.getJSONObject("dj").getString("djname")
80
-        if (newStreamer != streamerName.value)
81
-        {
82
-            val streamerPictureUrl =
83
-                "${urlToScrape}/dj-image/${resMain.getJSONObject("dj").getString("djimage")}"
84
-            fetchPicture(streamerPictureUrl)
85
-            streamerName.value = newStreamer
86
-        }
87
-        val listeners = resMain.getInt("listeners")
88
-        listenersCount.value = listeners
89
-        Log.d(tag, playerStoreTag +  "store updated")
90
-    }
91
-
92
-    private val scrape : (Any?) -> String =
93
-    {
94
-        URL(urlToScrape).readText()
95
-    }
96
-
97
-    /* initApi is called :
98
-        - at startup
99
-        - when a streamer changes.
100
-        the idea is to fetch the queue when a streamer changes (potentially Hanyuu), and at startup.
101
-        The Last Played is only fetched if it's empty (so, only at startup), not when a streamer changes.
102
-     */
103
-    fun initApi()
104
-    {
105
-        val post : (parameter: Any?) -> Unit = {
106
-            val result = JSONObject(it as String)
107
-            if (result.has("main"))
108
-            {
109
-                val resMain = result.getJSONObject("main")
110
-                updateApi(resMain)
111
-                currentSongBackup.copy(currentSong)
112
-                queue.clear()
113
-                if (resMain.has("queue") && resMain.getBoolean("isafkstream"))
114
-                {
115
-                    val queueJSON =
116
-                        resMain.getJSONArray("queue")
117
-                    for (i in 0 until queueJSON.length())
118
-                    {
119
-                        val t = extractSong(queueJSON[i] as JSONObject)
120
-                        if (t != currentSong) // if the API is too slow and didn't remove the first song from queue...
121
-                            queue.add(queue.size, t)
122
-                    }
123
-                }
124
-                isQueueUpdated.value = true
125
-                Log.d(tag, playerStoreTag +  queue.toString())
126
-
127
-                if (resMain.has("lp"))
128
-                {
129
-                    val queueJSON =
130
-                        resMain.getJSONArray("lp")
131
-                    // if my stack is empty, I fill it entirely (startup)
132
-                    if (lp.isEmpty())
133
-                    {
134
-                        for (i in 0 until queueJSON.length())
135
-                            lp.add(lp.size, extractSong(queueJSON[i] as JSONObject))
136
-                    }
137
-                }
138
-                Log.d(tag, playerStoreTag +  lp.toString())
139
-                isLpUpdated.value = true
140
-            }
141
-            isInitialized = true
142
-        }
143
-        Async(scrape, post)
144
-    }
145
-
146
-    fun fetchApi(isCompensatingLatency: Boolean = false) {
147
-        val post: (parameter: Any?) -> Unit = {
148
-            val result = JSONObject(it as String)
149
-            if (!result.isNull("main"))
150
-            {
151
-                val res = result.getJSONObject("main")
152
-                updateApi(res, isCompensatingLatency)
153
-            }
154
-        }
155
-        Async(scrape, post)
156
-    }
157
-    */
158
-
159 46
     // ##################################################
160 47
     // ############## QUEUE / LP FUNCTIONS ##############
161 48
     // ##################################################
@@ -173,126 +60,11 @@ class PlayerStore {
173 60
         //}
174 61
     }
175 62
 
176
-    /*
177
-    fun updateQueue() {
178
-        if (queue.isNotEmpty()) {
179
-            queue.remove(queue.first())
180
-            Log.d(tag, playerStoreTag + queue.toString())
181
-            fetchLastRequest()
182
-            isQueueUpdated.value = true
183
-        } else if (isInitialized) {
184
-            fetchLastRequest()
185
-        } else {
186
-            Log.d(tag, playerStoreTag +  "queue is empty!")
187
-        }
188
-    }
189
-
190
-    private fun fetchLastRequest()
191
-    {
192
-        val sleepScrape: (Any?) -> String = {
193
-            /* we can maximize our chances to retrieve the last queued song by specifically waiting for the number of seconds we measure between ICY metadata and API change.
194
-             we add 2 seconds just to get a higher probability that the API has correctly updated. (the latency compensator can have a jitter of 1 second usually)
195
-             If, against all odds, the API hasn't updated yet, we will retry in the same amount of seconds. So we'll have the data anyway.
196
-            This way to fetch at the most probable time is a good compromise between fetch speed and fetch frequency
197
-            We don't fetch too often, and we start to fetch at the most *probable* time.
198
-            If there's no latencyCompensator measured yet, we only wait for 3 seconds.
199
-            If the song is the same, it will be called again. 3 seconds is a good compromise between speed and frequency:
200
-            it might be called twice, rarely 3 times, and it's only the 2 first songs ; after these, the latencyCompensator is set to fetch at the most probable time.
201
-             */
202
-            val sleepTime: Long = if (latencyCompensator > 0) latencyCompensator + 2000 else 3000
203
-            Thread.sleep(sleepTime) // we wait a bit (10s) for the API to get updated on R/a/dio side!
204
-            URL(urlToScrape).readText()
205
-        }
206
-
207
-        lateinit var post: (parameter: Any?) -> Unit
208
-
209
-        fun postFun(result: JSONObject)
210
-        {
211
-            if (result.has("main")) {
212
-                val resMain = result.getJSONObject("main")
213
-                if ((resMain.has("isafkstream") && !resMain.getBoolean("isafkstream")) &&
214
-                    queue.isNotEmpty())
215
-                {
216
-                    queue.clear() //we're not requesting anything anymore.
217
-                    isQueueUpdated.value = true
218
-                } else if (resMain.has("isafkstream") && resMain.getBoolean("isafkstream") &&
219
-                    queue.isEmpty())
220
-                {
221
-                    initApi()
222
-                } else if (resMain.has("queue") && queue.isNotEmpty()) {
223
-                    val queueJSON =
224
-                        resMain.getJSONArray("queue")
225
-                    val t = extractSong(queueJSON[4] as JSONObject)
226
-                    if (t == queue.last())
227
-                    {
228
-                        Log.d(tag, playerStoreTag +  "Song already in there: $t")
229
-                        Async(sleepScrape, post)
230
-                    } else {
231
-                        queue.add(queue.size, t)
232
-                        Log.d(tag, playerStoreTag +  "added last queue song: $t")
233
-                        isQueueUpdated.value = true
234
-                    }
235
-                }
236
-            }
237
-        }
238
-
239
-        post = {
240
-            val result = JSONObject(it as String)
241
-            /*  The goal is to pass the result to a function that will process it (postFun).
242
-                The magic trick is, under circumstances, the last queue song might not have been updated yet when we fetch it.
243
-                So if this is detected ==> if (t == queue.last() )
244
-                Then the function re-schedule an Async(sleepScrape, post).
245
-                To do that, the "post" must be defined BEFORE the function, but the function must be defined BEFORE the "post" value.
246
-                So I declare "post" as lateinit var, define the function, then define the "post" that calls the function. IT SHOULD WORK.
247
-             */
248
-            postFun(result)
249
-        }
250
-
251
-        Async(sleepScrape, post)
252
-    }
253
-
254
-    private fun extractSong(songJSON: JSONObject) : Song {
255
-        val song = Song()
256
-        song.setTitleArtist(songJSON.getString("meta"))
257
-        song.startTime.value = songJSON.getLong("timestamp")
258
-        song.stopTime.value = song.startTime.value
259
-        song.type.value = songJSON.getInt("type")
260
-        return song
261
-    }
262
-    */
263 63
 
264 64
     // ##################################################
265 65
     // ############## PICTURE FUNCTIONS #################
266 66
     // ##################################################
267 67
 
268
-    /*
269
-    private fun fetchPicture(fileUrl: String)
270
-    {
271
-        val scrape: (Any?) -> Bitmap? = {
272
-            var k: InputStream? = null
273
-            var pic: Bitmap? = null
274
-            try {
275
-                k = URL(fileUrl).content as InputStream
276
-                val options = BitmapFactory.Options()
277
-                options.inSampleSize = 1
278
-                // this makes 1/2 of origin image size from width and height.
279
-                // it alleviates the memory for API16-API19 especially
280
-                pic = BitmapFactory.decodeStream(k, null, options)
281
-                k.close()
282
-            } catch (e: IOException) {
283
-                e.printStackTrace()
284
-            } finally {
285
-                k?.close()
286
-            }
287
-            pic
288
-        }
289
-        val post : (parameter: Any?) -> Unit = {
290
-            streamerPicture.postValue(it as Bitmap?)
291
-        }
292
-        Async(scrape, post)
293
-    }
294
-     */
295
-
296 68
     fun initPicture(c: Context) {
297 69
         streamerPicture.value = BitmapFactory.decodeResource(c.resources,
298 70
             R.drawable.logo_roundsquare

+ 11 - 2
app/src/main/java/fr/forum_thalie/tsumugi/playerstore/Song.kt Ver arquivo

@@ -2,7 +2,7 @@ package fr.forum_thalie.tsumugi.playerstore
2 2
 
3 3
 import androidx.lifecycle.MutableLiveData
4 4
 
5
-class Song(artistTitle: String = "", _id : Int = 0, _isRequestable : Boolean = false) {
5
+class Song(artistTitle: String = "", _id : Int = 0) {
6 6
 
7 7
     // TODO : remove MutableLiveData, use a MutableLiveData Boolean on PlayerStore instead
8 8
     val title: MutableLiveData<String> = MutableLiveData()
@@ -11,7 +11,6 @@ class Song(artistTitle: String = "", _id : Int = 0, _isRequestable : Boolean = f
11 11
     val startTime: MutableLiveData<Long> = MutableLiveData()
12 12
     val stopTime: MutableLiveData<Long> = MutableLiveData()
13 13
     var id: Int? = _id
14
-    var isRequestable : Boolean = _isRequestable
15 14
 
16 15
     init {
17 16
         setTitleArtist(artistTitle)
@@ -55,4 +54,14 @@ class Song(artistTitle: String = "", _id : Int = 0, _isRequestable : Boolean = f
55 54
         this.stopTime.value = song.stopTime.value
56 55
         this.type.value = song.type.value
57 56
     }
57
+
58
+    override fun hashCode(): Int {
59
+        var result = title.hashCode()
60
+        result = 31 * result + artist.hashCode()
61
+        result = 31 * result + type.hashCode()
62
+        result = 31 * result + startTime.hashCode()
63
+        result = 31 * result + stopTime.hashCode()
64
+        result = 31 * result + (id ?: 0)
65
+        return result
66
+    }
58 67
 }

+ 2 - 1
app/src/main/java/fr/forum_thalie/tsumugi/ui/nowplaying/NowPlayingFragment.kt Ver arquivo

@@ -48,8 +48,9 @@ class NowPlayingFragment : Fragment() {
48 48
         val progressBar: ProgressBar = root.findViewById(R.id.progressBar)
49 49
         val volumeIconImage : ImageView = root.findViewById(R.id.volume_icon)
50 50
 
51
-        // Note: these values are not used in the generic app
52 51
         val streamerPictureImageView: ImageView = root.findViewById(R.id.streamerPicture)
52
+
53
+        // Note: these values are not used in the generic app, but if you want to, you can use them.
53 54
         /*
54 55
         val streamerNameText : TextView = root.findViewById(R.id.streamerName)
55 56
         val songTitleNextText: TextView = root.findViewById(R.id.text_song_title_next)

+ 15 - 0
app/src/main/res/layout-v21/fragment_news.xml Ver arquivo

@@ -0,0 +1,15 @@
1
+<?xml version="1.0" encoding="utf-8"?>
2
+<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
3
+    xmlns:android="http://schemas.android.com/apk/res/android"
4
+    android:layout_width="match_parent"
5
+    android:layout_height="match_parent" >
6
+
7
+    <androidx.recyclerview.widget.RecyclerView
8
+        android:layout_width="match_parent"
9
+        android:layout_height="match_parent"
10
+        android:id="@+id/news_recycler"
11
+        android:scrollbars="vertical"
12
+        >
13
+
14
+    </androidx.recyclerview.widget.RecyclerView>
15
+</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>

+ 19 - 0
app/src/main/res/layout/fragment_error_webview.xml Ver arquivo

@@ -0,0 +1,19 @@
1
+<?xml version="1.0" encoding="utf-8"?>
2
+<androidx.constraintlayout.widget.ConstraintLayout
3
+    xmlns:android="http://schemas.android.com/apk/res/android"
4
+    xmlns:app="http://schemas.android.com/apk/res-auto"
5
+    android:layout_width="match_parent"
6
+    android:layout_height="match_parent">
7
+
8
+    <TextView
9
+        android:id="@+id/textView"
10
+        android:layout_width="wrap_content"
11
+        android:layout_height="wrap_content"
12
+        android:text="@string/error_webView"
13
+        android:textSize="40sp"
14
+        android:gravity="center"
15
+        app:layout_constraintBottom_toBottomOf="parent"
16
+        app:layout_constraintEnd_toEndOf="parent"
17
+        app:layout_constraintStart_toStartOf="parent"
18
+        app:layout_constraintTop_toTopOf="parent" />
19
+</androidx.constraintlayout.widget.ConstraintLayout>