Moved the fetching task to a separate activity; changed the time attributes in StudIPEvent.kt to strings

This commit is contained in:
denizk0461
2023-04-12 18:58:10 +02:00
parent 4f78eb8373
commit d55a304cec
11 changed files with 131 additions and 29 deletions
+5 -1
View File
@@ -21,10 +21,14 @@
android:theme="@style/Theme.StudIPTimetable">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".activity.FetcherActivity"
android:exported="false"
android:theme="@style/Theme.StudIPTimetable">
</activity>
</application>
</manifest>
@@ -0,0 +1,68 @@
package com.denizk0461.studip.activity
import android.annotation.SuppressLint
import android.app.Activity
import android.os.Bundle
import android.webkit.WebResourceRequest
import android.webkit.WebView
import android.webkit.WebViewClient
import android.widget.Toast
import androidx.lifecycle.ViewModelProvider
import com.denizk0461.studip.R
import com.denizk0461.studip.data.StudIPParser
import com.denizk0461.studip.databinding.ActivityFetcherBinding
import com.denizk0461.studip.viewmodel.FetcherViewModel
import java.net.URLDecoder
class FetcherActivity : Activity() {
private lateinit var binding: ActivityFetcherBinding
private lateinit var viewModel: FetcherViewModel
/*
* Enabling JavaScript is necessary to get the HTML source in this context. As the HTML can only
* be accessed once the user has logged in, a simple HTML request would not suffice here.
*/
@SuppressLint("SetJavaScriptEnabled")
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
viewModel = ViewModelProvider.AndroidViewModelFactory(this.application).create(FetcherViewModel::class.java)
binding = ActivityFetcherBinding.inflate(layoutInflater)
setContentView(binding.root)
binding.webview.settings.apply {
javaScriptEnabled = true
}
binding.webview.webViewClient = object : WebViewClient() {
override fun shouldOverrideUrlLoading(
view: WebView,
request: WebResourceRequest
): Boolean {
return false
}
override fun onPageFinished(view: WebView, url: String) {
binding.webview.loadUrl(
"javascript:window.HtmlViewer.showHTML" +
"('<html>'+document.getElementsByTagName('html')[0].innerHTML+'</html>');"
)
}
}
binding.webview.loadUrl("https://elearning.uni-bremen.de/index.php?again=yes")
binding.fab.setOnClickListener { view ->
binding.webview.evaluateJavascript(
"(function(){return encodeURI(document.getElementsByTagName('html')[0].innerHTML)})();"
) { p0 ->
viewModel.nukeEvents()
StudIPParser().parse(URLDecoder.decode(p0, "UTF-8")) { events ->
viewModel.insertEvents(events)
Toast.makeText(this, R.string.toast_fetch_finished, Toast.LENGTH_SHORT).show()
finish()
}
}
}
}
}
@@ -4,15 +4,15 @@ import com.denizk0461.studip.model.StudIPEvent
object Misc {
val events: Array<StudIPEvent> = arrayOf(
StudIPEvent(1, "Literatures", "Nittel", "MZH 1380/1400", 0, 3, 1),
StudIPEvent(2, "Linguistics", "Du Bois", "SFG 1020", 1, 1, 1),
StudIPEvent(3, "System Erde", "Zolitschka, Labuhn-Deroubaix", "GW2 B1410", 1, 3, 1),
StudIPEvent(4, "Key Moments", "Esders-Angermund", "GW2 B2890", 2, 2, 1),
StudIPEvent(5, "ULS-1", "Herrmann", "GW2 B2890", 2, 3, 1),
StudIPEvent(6, "Gesellschaft und Raum", "Lossau, Mossig", "GW2 B1820", 3, 1, 1),
StudIPEvent(7, "Gesellschaft und Raum2", "Lossau, Mossig", "GW2 B1820", 4, 4, 2),
)
// val events: Array<StudIPEvent> = arrayOf(
// StudIPEvent(1, "Literatures", "Nittel", "MZH 1380/1400", 0, 3, 1),
// StudIPEvent(2, "Linguistics", "Du Bois", "SFG 1020", 1, 1, 1),
// StudIPEvent(3, "System Erde", "Zolitschka, Labuhn-Deroubaix", "GW2 B1410", 1, 3, 1),
// StudIPEvent(4, "Key Moments", "Esders-Angermund", "GW2 B2890", 2, 2, 1),
// StudIPEvent(5, "ULS-1", "Herrmann", "GW2 B2890", 2, 3, 1),
// StudIPEvent(6, "Gesellschaft und Raum", "Lossau, Mossig", "GW2 B1820", 3, 1, 1),
// StudIPEvent(7, "Gesellschaft und Raum2", "Lossau, Mossig", "GW2 B1820", 4, 4, 2),
// )
private val timeslotStartMap: Map<String, Int> = mapOf(
"6:00" to 0,
@@ -9,7 +9,7 @@ class StudIPParser {
var id = 0
val doc = Jsoup.parse(html)
val newEvents = mutableListOf<StudIPEvent>()
val columns = arrayOf(
val columns = arrayOf( // TODO THIS NEEDS TO BE DYNAMIC!
doc.getElementById("calendar_view_1_column_0"),
doc.getElementById("calendar_view_1_column_1"),
doc.getElementById("calendar_view_1_column_2"),
@@ -24,7 +24,8 @@ class StudIPParser {
val parsedLecturers = entryHeader.substring(delimiter + 1 until entryHeader.length - 1)
val entryInfos = entry.getElementsByTag("dd")[0].text().split(", ", limit = 2)
val timeSlot = Misc.parseTimeslot(entryInfos[0])
// val timeSlot = Misc.parseTimeslot(entryInfos[0])
val timeSlot = entryInfos[0].split(" - ")
val event = StudIPEvent(
id = id,
@@ -32,8 +33,8 @@ class StudIPParser {
lecturer = parsedLecturers,
room = entryInfos[1],
day = index,
timeslotStart = timeSlot.first,
timeslotEnd = timeSlot.second,
timeslotStart = timeSlot[0],
timeslotEnd = timeSlot[1],
)
newEvents.add(event)
id += 1
@@ -6,7 +6,7 @@ import androidx.room.Room
import androidx.room.RoomDatabase
import com.denizk0461.studip.model.StudIPEvent
@Database(entities = [StudIPEvent::class], version = 2)
@Database(entities = [StudIPEvent::class], version = 3)
abstract class EventDatabase : RoomDatabase() {
abstract fun dao(): EventDAO
@@ -1,5 +1,6 @@
package com.denizk0461.studip.fragment
import android.content.Intent
import android.os.Bundle
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
@@ -8,6 +9,7 @@ import android.view.ViewGroup
import androidx.fragment.app.viewModels
import androidx.navigation.fragment.NavHostFragment.Companion.findNavController
import com.denizk0461.studip.R
import com.denizk0461.studip.activity.FetcherActivity
import com.denizk0461.studip.adapter.StudIPEventPageAdapter
import com.denizk0461.studip.databinding.FragmentEventBinding
import com.denizk0461.studip.viewmodel.EventViewModel
@@ -90,7 +92,8 @@ class EventFragment : Fragment() {
}
private fun launchWebview() {
findNavController(this).navigate(R.id.action_FirstFragment_to_SecondFragment)
// findNavController(this).navigate(R.id.action_FirstFragment_to_SecondFragment)
startActivity(Intent(context, FetcherActivity::class.java))
}
/**
@@ -11,7 +11,7 @@ import androidx.fragment.app.Fragment
import androidx.fragment.app.viewModels
import com.denizk0461.studip.data.StudIPParser
import com.denizk0461.studip.databinding.FragmentParserBinding
import com.denizk0461.studip.viewmodel.ParserViewModel
import com.denizk0461.studip.viewmodel.FetcherViewModel
import java.net.URLDecoder
/**
@@ -19,14 +19,14 @@ import java.net.URLDecoder
*/
class ParserFragment : Fragment() {
private var _binding: FragmentParserBinding? = null
private var html = "" // temporary storage for the website HTML
private var _binding: FragmentParserBinding? = null
// This property is only valid between onCreateView and
// onDestroyView.
private val binding get() = _binding!!
private val viewModel: ParserViewModel by viewModels()
private val viewModel: FetcherViewModel by viewModels()
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
@@ -11,14 +11,14 @@ data class StudIPEvent(
val lecturer: String, // the lecturer(s)
val room: String, // the room the event takes place in
val day: Int, // 0 = Monday, 1 = Tuesday, 2 = Wednesday, 3 = Thursday, 4 = Friday
val timeslotStart: Int, // 1 = 08:15, 2 = 10:15, 3 = 12:15, 4 = 14:15, 5 = 16:15, 6 = 18:15
val timeslotEnd: Int, // 1 = 09:45 etc.
val timeslotStart: String, // the time the course starts
val timeslotEnd: String, // the time the course ends
) {
@Ignore private val timeSlotStartTimes: List<String> = listOf("06:15", "08:15", "10:15", "12:15", "14:15", "16:15", "18:15", "20:15")
@Ignore private val timeSlotEndTimes: List<String> = listOf("07:45", "09:45", "11:45", "13:45", "15:45", "17:45", "19:45", "21:45")
// @Ignore private val timeSlotStartTimes: List<String> = listOf("06:15", "08:15", "10:15", "12:15", "14:15", "16:15", "18:15", "20:15")
// @Ignore private val timeSlotEndTimes: List<String> = listOf("07:45", "09:45", "11:45", "13:45", "15:45", "17:45", "19:45", "21:45")
fun timeslot(): String = "${timeSlotStartTimes[timeslotStart]} ${timeSlotEndTimes[timeslotEnd]}"
fun timeslot(): String = "$timeslotStart $timeslotEnd"
override fun equals(other: Any?): Boolean {
if (this === other) return true
@@ -37,10 +37,8 @@ data class StudIPEvent(
result = 31 * result + lecturer.hashCode()
result = 31 * result + room.hashCode()
result = 31 * result + day
result = 31 * result + timeslotStart
result = 31 * result + timeslotEnd
result = 31 * result + timeSlotStartTimes.hashCode()
result = 31 * result + timeSlotEndTimes.hashCode()
result = 31 * result + timeslotStart.hashCode()
result = 31 * result + timeslotEnd.hashCode()
return result
}
}
@@ -3,7 +3,7 @@ package com.denizk0461.studip.viewmodel
import android.app.Application
import com.denizk0461.studip.model.StudIPEvent
class ParserViewModel(app: Application) : TemplateViewModel(app) {
class FetcherViewModel(app: Application) : TemplateViewModel(app) {
fun insertEvent(event: StudIPEvent) { repo.insertEvent(event) }
fun insertEvents(events: List<StudIPEvent>) { doAsync { repo.insertEvents(events) } }
@@ -0,0 +1,26 @@
<?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:layout_width="match_parent"
android:layout_height="match_parent">
<WebView
android:id="@+id/webview"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"/>
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
android:layout_marginEnd="@dimen/fab_margin"
android:layout_marginBottom="@dimen/fab_margin"
app:srcCompat="@drawable/check" />
</androidx.constraintlayout.widget.ConstraintLayout>
+2
View File
@@ -19,6 +19,8 @@
<string name="nav_food">Food</string>
<string name="nav_settings">Settings</string>
<string name="toast_fetch_finished">Your schedule has been refreshed!</string>
<string name="lorem_ipsum">
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam in scelerisque sem. Mauris
volutpat, dolor id interdum ullamcorper, risus dolor egestas lectus, sit amet mattis purus