Archived
Moved the fetching task to a separate activity; changed the time attributes in StudIPEvent.kt to strings
This commit is contained in:
@@ -21,10 +21,14 @@
|
|||||||
android:theme="@style/Theme.StudIPTimetable">
|
android:theme="@style/Theme.StudIPTimetable">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.MAIN" />
|
<action android:name="android.intent.action.MAIN" />
|
||||||
|
|
||||||
<category android:name="android.intent.category.LAUNCHER" />
|
<category android:name="android.intent.category.LAUNCHER" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</activity>
|
</activity>
|
||||||
|
<activity
|
||||||
|
android:name=".activity.FetcherActivity"
|
||||||
|
android:exported="false"
|
||||||
|
android:theme="@style/Theme.StudIPTimetable">
|
||||||
|
</activity>
|
||||||
</application>
|
</application>
|
||||||
|
|
||||||
</manifest>
|
</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 {
|
object Misc {
|
||||||
|
|
||||||
val events: Array<StudIPEvent> = arrayOf(
|
// val events: Array<StudIPEvent> = arrayOf(
|
||||||
StudIPEvent(1, "Literatures", "Nittel", "MZH 1380/1400", 0, 3, 1),
|
// StudIPEvent(1, "Literatures", "Nittel", "MZH 1380/1400", 0, 3, 1),
|
||||||
StudIPEvent(2, "Linguistics", "Du Bois", "SFG 1020", 1, 1, 1),
|
// StudIPEvent(2, "Linguistics", "Du Bois", "SFG 1020", 1, 1, 1),
|
||||||
StudIPEvent(3, "System Erde", "Zolitschka, Labuhn-Deroubaix", "GW2 B1410", 1, 3, 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(4, "Key Moments", "Esders-Angermund", "GW2 B2890", 2, 2, 1),
|
||||||
StudIPEvent(5, "ULS-1", "Herrmann", "GW2 B2890", 2, 3, 1),
|
// StudIPEvent(5, "ULS-1", "Herrmann", "GW2 B2890", 2, 3, 1),
|
||||||
StudIPEvent(6, "Gesellschaft und Raum", "Lossau, Mossig", "GW2 B1820", 3, 1, 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),
|
// StudIPEvent(7, "Gesellschaft und Raum2", "Lossau, Mossig", "GW2 B1820", 4, 4, 2),
|
||||||
)
|
// )
|
||||||
|
|
||||||
private val timeslotStartMap: Map<String, Int> = mapOf(
|
private val timeslotStartMap: Map<String, Int> = mapOf(
|
||||||
"6:00" to 0,
|
"6:00" to 0,
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ class StudIPParser {
|
|||||||
var id = 0
|
var id = 0
|
||||||
val doc = Jsoup.parse(html)
|
val doc = Jsoup.parse(html)
|
||||||
val newEvents = mutableListOf<StudIPEvent>()
|
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_0"),
|
||||||
doc.getElementById("calendar_view_1_column_1"),
|
doc.getElementById("calendar_view_1_column_1"),
|
||||||
doc.getElementById("calendar_view_1_column_2"),
|
doc.getElementById("calendar_view_1_column_2"),
|
||||||
@@ -24,7 +24,8 @@ class StudIPParser {
|
|||||||
val parsedLecturers = entryHeader.substring(delimiter + 1 until entryHeader.length - 1)
|
val parsedLecturers = entryHeader.substring(delimiter + 1 until entryHeader.length - 1)
|
||||||
|
|
||||||
val entryInfos = entry.getElementsByTag("dd")[0].text().split(", ", limit = 2)
|
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(
|
val event = StudIPEvent(
|
||||||
id = id,
|
id = id,
|
||||||
@@ -32,8 +33,8 @@ class StudIPParser {
|
|||||||
lecturer = parsedLecturers,
|
lecturer = parsedLecturers,
|
||||||
room = entryInfos[1],
|
room = entryInfos[1],
|
||||||
day = index,
|
day = index,
|
||||||
timeslotStart = timeSlot.first,
|
timeslotStart = timeSlot[0],
|
||||||
timeslotEnd = timeSlot.second,
|
timeslotEnd = timeSlot[1],
|
||||||
)
|
)
|
||||||
newEvents.add(event)
|
newEvents.add(event)
|
||||||
id += 1
|
id += 1
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import androidx.room.Room
|
|||||||
import androidx.room.RoomDatabase
|
import androidx.room.RoomDatabase
|
||||||
import com.denizk0461.studip.model.StudIPEvent
|
import com.denizk0461.studip.model.StudIPEvent
|
||||||
|
|
||||||
@Database(entities = [StudIPEvent::class], version = 2)
|
@Database(entities = [StudIPEvent::class], version = 3)
|
||||||
abstract class EventDatabase : RoomDatabase() {
|
abstract class EventDatabase : RoomDatabase() {
|
||||||
|
|
||||||
abstract fun dao(): EventDAO
|
abstract fun dao(): EventDAO
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package com.denizk0461.studip.fragment
|
package com.denizk0461.studip.fragment
|
||||||
|
|
||||||
|
import android.content.Intent
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
@@ -8,6 +9,7 @@ import android.view.ViewGroup
|
|||||||
import androidx.fragment.app.viewModels
|
import androidx.fragment.app.viewModels
|
||||||
import androidx.navigation.fragment.NavHostFragment.Companion.findNavController
|
import androidx.navigation.fragment.NavHostFragment.Companion.findNavController
|
||||||
import com.denizk0461.studip.R
|
import com.denizk0461.studip.R
|
||||||
|
import com.denizk0461.studip.activity.FetcherActivity
|
||||||
import com.denizk0461.studip.adapter.StudIPEventPageAdapter
|
import com.denizk0461.studip.adapter.StudIPEventPageAdapter
|
||||||
import com.denizk0461.studip.databinding.FragmentEventBinding
|
import com.denizk0461.studip.databinding.FragmentEventBinding
|
||||||
import com.denizk0461.studip.viewmodel.EventViewModel
|
import com.denizk0461.studip.viewmodel.EventViewModel
|
||||||
@@ -90,7 +92,8 @@ class EventFragment : Fragment() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun launchWebview() {
|
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 androidx.fragment.app.viewModels
|
||||||
import com.denizk0461.studip.data.StudIPParser
|
import com.denizk0461.studip.data.StudIPParser
|
||||||
import com.denizk0461.studip.databinding.FragmentParserBinding
|
import com.denizk0461.studip.databinding.FragmentParserBinding
|
||||||
import com.denizk0461.studip.viewmodel.ParserViewModel
|
import com.denizk0461.studip.viewmodel.FetcherViewModel
|
||||||
import java.net.URLDecoder
|
import java.net.URLDecoder
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -19,14 +19,14 @@ import java.net.URLDecoder
|
|||||||
*/
|
*/
|
||||||
class ParserFragment : Fragment() {
|
class ParserFragment : Fragment() {
|
||||||
|
|
||||||
private var _binding: FragmentParserBinding? = null
|
|
||||||
private var html = "" // temporary storage for the website HTML
|
private var html = "" // temporary storage for the website HTML
|
||||||
|
|
||||||
|
private var _binding: FragmentParserBinding? = null
|
||||||
// This property is only valid between onCreateView and
|
// This property is only valid between onCreateView and
|
||||||
// onDestroyView.
|
// onDestroyView.
|
||||||
private val binding get() = _binding!!
|
private val binding get() = _binding!!
|
||||||
|
|
||||||
private val viewModel: ParserViewModel by viewModels()
|
private val viewModel: FetcherViewModel by viewModels()
|
||||||
|
|
||||||
override fun onCreateView(
|
override fun onCreateView(
|
||||||
inflater: LayoutInflater, container: ViewGroup?,
|
inflater: LayoutInflater, container: ViewGroup?,
|
||||||
|
|||||||
@@ -11,14 +11,14 @@ data class StudIPEvent(
|
|||||||
val lecturer: String, // the lecturer(s)
|
val lecturer: String, // the lecturer(s)
|
||||||
val room: String, // the room the event takes place in
|
val room: String, // the room the event takes place in
|
||||||
val day: Int, // 0 = Monday, 1 = Tuesday, 2 = Wednesday, 3 = Thursday, 4 = Friday
|
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 timeslotStart: String, // the time the course starts
|
||||||
val timeslotEnd: Int, // 1 = 09:45 etc.
|
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 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 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 {
|
override fun equals(other: Any?): Boolean {
|
||||||
if (this === other) return true
|
if (this === other) return true
|
||||||
@@ -37,10 +37,8 @@ data class StudIPEvent(
|
|||||||
result = 31 * result + lecturer.hashCode()
|
result = 31 * result + lecturer.hashCode()
|
||||||
result = 31 * result + room.hashCode()
|
result = 31 * result + room.hashCode()
|
||||||
result = 31 * result + day
|
result = 31 * result + day
|
||||||
result = 31 * result + timeslotStart
|
result = 31 * result + timeslotStart.hashCode()
|
||||||
result = 31 * result + timeslotEnd
|
result = 31 * result + timeslotEnd.hashCode()
|
||||||
result = 31 * result + timeSlotStartTimes.hashCode()
|
|
||||||
result = 31 * result + timeSlotEndTimes.hashCode()
|
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -3,7 +3,7 @@ package com.denizk0461.studip.viewmodel
|
|||||||
import android.app.Application
|
import android.app.Application
|
||||||
import com.denizk0461.studip.model.StudIPEvent
|
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 insertEvent(event: StudIPEvent) { repo.insertEvent(event) }
|
||||||
fun insertEvents(events: List<StudIPEvent>) { doAsync { repo.insertEvents(events) } }
|
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>
|
||||||
@@ -19,6 +19,8 @@
|
|||||||
<string name="nav_food">Food</string>
|
<string name="nav_food">Food</string>
|
||||||
<string name="nav_settings">Settings</string>
|
<string name="nav_settings">Settings</string>
|
||||||
|
|
||||||
|
<string name="toast_fetch_finished">Your schedule has been refreshed!</string>
|
||||||
|
|
||||||
<string name="lorem_ipsum">
|
<string name="lorem_ipsum">
|
||||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam in scelerisque sem. Mauris
|
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
|
volutpat, dolor id interdum ullamcorper, risus dolor egestas lectus, sit amet mattis purus
|
||||||
|
|||||||
Reference in New Issue
Block a user