diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 0ff7434..1655f92 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -21,10 +21,14 @@ android:theme="@style/Theme.StudIPTimetable"> - + + \ No newline at end of file diff --git a/app/src/main/java/com/denizk0461/studip/activity/FetcherActivity.kt b/app/src/main/java/com/denizk0461/studip/activity/FetcherActivity.kt new file mode 100644 index 0000000..a34c7ec --- /dev/null +++ b/app/src/main/java/com/denizk0461/studip/activity/FetcherActivity.kt @@ -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" + + "(''+document.getElementsByTagName('html')[0].innerHTML+'');" + ) + } + } + + 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() + } + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/denizk0461/studip/data/Misc.kt b/app/src/main/java/com/denizk0461/studip/data/Misc.kt index 8749843..f0cc058 100644 --- a/app/src/main/java/com/denizk0461/studip/data/Misc.kt +++ b/app/src/main/java/com/denizk0461/studip/data/Misc.kt @@ -4,15 +4,15 @@ import com.denizk0461.studip.model.StudIPEvent object Misc { - val events: Array = 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 = 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 = mapOf( "6:00" to 0, diff --git a/app/src/main/java/com/denizk0461/studip/data/StudIPParser.kt b/app/src/main/java/com/denizk0461/studip/data/StudIPParser.kt index 4357f6b..0c5fab2 100644 --- a/app/src/main/java/com/denizk0461/studip/data/StudIPParser.kt +++ b/app/src/main/java/com/denizk0461/studip/data/StudIPParser.kt @@ -9,7 +9,7 @@ class StudIPParser { var id = 0 val doc = Jsoup.parse(html) val newEvents = mutableListOf() - 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 diff --git a/app/src/main/java/com/denizk0461/studip/db/EventDatabase.kt b/app/src/main/java/com/denizk0461/studip/db/EventDatabase.kt index 2692e62..d61bede 100644 --- a/app/src/main/java/com/denizk0461/studip/db/EventDatabase.kt +++ b/app/src/main/java/com/denizk0461/studip/db/EventDatabase.kt @@ -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 diff --git a/app/src/main/java/com/denizk0461/studip/fragment/EventFragment.kt b/app/src/main/java/com/denizk0461/studip/fragment/EventFragment.kt index cc39019..aa88ddb 100644 --- a/app/src/main/java/com/denizk0461/studip/fragment/EventFragment.kt +++ b/app/src/main/java/com/denizk0461/studip/fragment/EventFragment.kt @@ -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)) } /** diff --git a/app/src/main/java/com/denizk0461/studip/fragment/ParserFragment.kt b/app/src/main/java/com/denizk0461/studip/fragment/ParserFragment.kt index 7a32e7d..3a92e63 100644 --- a/app/src/main/java/com/denizk0461/studip/fragment/ParserFragment.kt +++ b/app/src/main/java/com/denizk0461/studip/fragment/ParserFragment.kt @@ -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?, diff --git a/app/src/main/java/com/denizk0461/studip/model/StudIPEvent.kt b/app/src/main/java/com/denizk0461/studip/model/StudIPEvent.kt index 5b48027..856ae0f 100644 --- a/app/src/main/java/com/denizk0461/studip/model/StudIPEvent.kt +++ b/app/src/main/java/com/denizk0461/studip/model/StudIPEvent.kt @@ -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 = listOf("06:15", "08:15", "10:15", "12:15", "14:15", "16:15", "18:15", "20:15") - @Ignore private val timeSlotEndTimes: List = listOf("07:45", "09:45", "11:45", "13:45", "15:45", "17:45", "19:45", "21:45") +// @Ignore private val timeSlotStartTimes: List = listOf("06:15", "08:15", "10:15", "12:15", "14:15", "16:15", "18:15", "20:15") +// @Ignore private val timeSlotEndTimes: List = 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 } } diff --git a/app/src/main/java/com/denizk0461/studip/viewmodel/ParserViewModel.kt b/app/src/main/java/com/denizk0461/studip/viewmodel/FetcherViewModel.kt similarity index 83% rename from app/src/main/java/com/denizk0461/studip/viewmodel/ParserViewModel.kt rename to app/src/main/java/com/denizk0461/studip/viewmodel/FetcherViewModel.kt index 7b314f5..6aa5822 100644 --- a/app/src/main/java/com/denizk0461/studip/viewmodel/ParserViewModel.kt +++ b/app/src/main/java/com/denizk0461/studip/viewmodel/FetcherViewModel.kt @@ -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) { doAsync { repo.insertEvents(events) } } diff --git a/app/src/main/res/layout/activity_fetcher.xml b/app/src/main/res/layout/activity_fetcher.xml new file mode 100644 index 0000000..d10388d --- /dev/null +++ b/app/src/main/res/layout/activity_fetcher.xml @@ -0,0 +1,26 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 5aeea97..539cc5e 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -19,6 +19,8 @@ Food Settings + Your schedule has been refreshed! + 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