diff --git a/README.md b/README.md index 8dbfcf1..f5fcb2e 100755 --- a/README.md +++ b/README.md @@ -2,9 +2,11 @@ An enhanced version of the ŠkolaOnLine (ŠOL) online school system. -It aims to provide more readable data than the web version and remove some of the annoyances of the mobile app. It is intended to be an Android app in the future, but so far it is **only for Linux** (not tested anywhere else). +It aims to provide more readable data than the web version and remove some of the annoyances of the mobile app. It is intended to be an Android app in the future, but so far it is **only for Linux** (not tested anywhere else). (Android app development in progress though!) Insiration was taken from [@JakubAndrysek](https://github.com/JakubAndrysek)'s [skola-online-stahovani-znamek](https://github.com/JakubAndrysek/skola-online-stahovani-znamek) project. +# PC Python version + # Features + Shows the schedule for the current week @@ -46,7 +48,7 @@ I am currently working on the Android app, but the implementation is unfortunate The implementation consists of a local (or maybe remote in the future) server which does the webscraping and session stuff and the actual Android app which shows the data. -To start, you need to set the server up (guide in the /server directory of this repo) on localhost (127.0.0.1) on port 8080 using Termux (tested like that, maybe you can find an another way to host a server on mobile) and it needs to be serving the file fetch.php. +To start, you need to set the server up on localhost (127.0.0.1) on port 8080 using Termux (tested like that, maybe you can find an another way to host a server on mobile) and it needs to be serving the file fetch.php. To set the server up, run the `run_server.sh` script found in the /server directory. @@ -54,4 +56,4 @@ It needs to be running all the time, otherwise, the Android app won't be able to After setting up the server, you can start the app. You will be greeted with the weekly calendar. -There is currently no way of logging into the app though... This is a quite important issue, so I have it at the top of my TODO list. \ No newline at end of file +There is currently no way of logging into the app though... This is a quite important issue, so I have it at the top of my TODO list. diff --git a/mobile/.idea/.gitignore b/mobile/.idea/.gitignore new file mode 100644 index 0000000..26d3352 --- /dev/null +++ b/mobile/.idea/.gitignore @@ -0,0 +1,3 @@ +# Default ignored files +/shelf/ +/workspace.xml diff --git a/mobile/.idea/.name b/mobile/.idea/.name new file mode 100644 index 0000000..8f0d358 --- /dev/null +++ b/mobile/.idea/.name @@ -0,0 +1 @@ +Solen \ No newline at end of file diff --git a/mobile/.idea/codeStyles/Project.xml b/mobile/.idea/codeStyles/Project.xml new file mode 100644 index 0000000..7643783 --- /dev/null +++ b/mobile/.idea/codeStyles/Project.xml @@ -0,0 +1,123 @@ + + + + + + + + + + \ No newline at end of file diff --git a/mobile/.idea/codeStyles/codeStyleConfig.xml b/mobile/.idea/codeStyles/codeStyleConfig.xml new file mode 100644 index 0000000..79ee123 --- /dev/null +++ b/mobile/.idea/codeStyles/codeStyleConfig.xml @@ -0,0 +1,5 @@ + + + + \ No newline at end of file diff --git a/mobile/.idea/compiler.xml b/mobile/.idea/compiler.xml new file mode 100644 index 0000000..b589d56 --- /dev/null +++ b/mobile/.idea/compiler.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/mobile/.idea/deploymentTargetDropDown.xml b/mobile/.idea/deploymentTargetDropDown.xml new file mode 100644 index 0000000..0c0c338 --- /dev/null +++ b/mobile/.idea/deploymentTargetDropDown.xml @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file diff --git a/mobile/.idea/gradle.xml b/mobile/.idea/gradle.xml new file mode 100644 index 0000000..0897082 --- /dev/null +++ b/mobile/.idea/gradle.xml @@ -0,0 +1,19 @@ + + + + + + + \ No newline at end of file diff --git a/mobile/.idea/kotlinc.xml b/mobile/.idea/kotlinc.xml new file mode 100644 index 0000000..8d81632 --- /dev/null +++ b/mobile/.idea/kotlinc.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/mobile/.idea/migrations.xml b/mobile/.idea/migrations.xml new file mode 100644 index 0000000..f8051a6 --- /dev/null +++ b/mobile/.idea/migrations.xml @@ -0,0 +1,10 @@ + + + + + + \ No newline at end of file diff --git a/mobile/.idea/misc.xml b/mobile/.idea/misc.xml new file mode 100644 index 0000000..8978d23 --- /dev/null +++ b/mobile/.idea/misc.xml @@ -0,0 +1,9 @@ + + + + + + + + \ No newline at end of file diff --git a/mobile/.idea/vcs.xml b/mobile/.idea/vcs.xml new file mode 100644 index 0000000..6c0b863 --- /dev/null +++ b/mobile/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/mobile/app/build.gradle.kts b/mobile/app/build.gradle.kts index 225d18c..291a796 100644 --- a/mobile/app/build.gradle.kts +++ b/mobile/app/build.gradle.kts @@ -45,7 +45,10 @@ dependencies { implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:2.6.1") implementation("androidx.navigation:navigation-fragment-ktx:2.6.0") implementation("androidx.navigation:navigation-ui-ktx:2.6.0") - testImplementation("junit:junit:4.13.2") - androidTestImplementation("androidx.test.ext:junit:1.1.5") + implementation("androidx.lifecycle:lifecycle-livedata-ktx:2.4.0") + implementation("com.squareup.okhttp3:okhttp:4.12.0") + implementation("androidx.viewpager2:viewpager2:1.0.0") androidTestImplementation("androidx.test.espresso:espresso-core:3.5.1") + androidTestImplementation("androidx.test.ext:junit:1.1.5") + testImplementation("junit:junit:4.13.2") } \ No newline at end of file diff --git a/mobile/app/src/androidTest/java/com/odweta/solen/ExampleInstrumentedTest.kt b/mobile/app/src/androidTest/java/com/odweta/solen/ExampleInstrumentedTest.kt deleted file mode 100644 index 7af0737..0000000 --- a/mobile/app/src/androidTest/java/com/odweta/solen/ExampleInstrumentedTest.kt +++ /dev/null @@ -1,24 +0,0 @@ -package com.odweta.solen - -import androidx.test.platform.app.InstrumentationRegistry -import androidx.test.ext.junit.runners.AndroidJUnit4 - -import org.junit.Test -import org.junit.runner.RunWith - -import org.junit.Assert.* - -/** - * Instrumented test, which will execute on an Android device. - * - * See [testing documentation](http://d.android.com/tools/testing). - */ -@RunWith(AndroidJUnit4::class) -class ExampleInstrumentedTest { - @Test - fun useAppContext() { - // Context of the app under test. - val appContext = InstrumentationRegistry.getInstrumentation().targetContext - assertEquals("com.odweta.solen", appContext.packageName) - } -} \ No newline at end of file diff --git a/mobile/app/src/main/AndroidManifest.xml b/mobile/app/src/main/AndroidManifest.xml index f8a6ccc..76dbfea 100644 --- a/mobile/app/src/main/AndroidManifest.xml +++ b/mobile/app/src/main/AndroidManifest.xml @@ -2,6 +2,8 @@ + + + tools:targetApi="tiramisu" + android:usesCleartextTraffic="true" + android:enableOnBackInvokedCallback="true"> diff --git a/mobile/app/src/main/java/com/odweta/solen/CalWeekFragment.kt b/mobile/app/src/main/java/com/odweta/solen/CalWeekFragment.kt new file mode 100644 index 0000000..dc0689a --- /dev/null +++ b/mobile/app/src/main/java/com/odweta/solen/CalWeekFragment.kt @@ -0,0 +1,341 @@ +package com.odweta.solen + +import android.annotation.SuppressLint +import android.content.res.Resources +import android.graphics.Typeface +import android.graphics.drawable.GradientDrawable +import android.os.Bundle +import android.view.Gravity +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.view.ViewTreeObserver +import android.widget.FrameLayout +import android.widget.LinearLayout +import android.widget.RelativeLayout +import android.widget.ScrollView +import android.widget.Space +import android.widget.TextView +import androidx.core.content.ContextCompat +import androidx.fragment.app.Fragment +import androidx.fragment.app.FragmentManager +import androidx.lifecycle.Lifecycle +import androidx.viewpager2.adapter.FragmentStateAdapter +import androidx.viewpager2.widget.ViewPager2 +import java.util.Calendar + +interface MainActivityListener { + fun onLaunch(view: View) +} + +class CalWeekFragment : Fragment() { + private var mainActivityListener: MainActivityListener? = null + + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle? + ): View? { + val view = inflater.inflate(R.layout.activity_cal_week, container, false) + + val viewPager: ViewPager2 = view.findViewById(R.id.dayPager) + val adapter = DayPagerAdapter(childFragmentManager, viewLifecycleOwner.lifecycle) + + for (i in 0 until adapter.itemCount) { + childFragmentManager.beginTransaction().remove(requireActivity().findViewById(adapter.getItemId(i) + .toInt())).commit() + } + + for (i in 0 until 5) { + adapter.addFragment(DayFragment(i)) + } + + viewPager.adapter = adapter + // set the correct day to display as default + val day = Calendar.getInstance().get(Calendar.DAY_OF_WEEK) + if (day in Calendar.MONDAY..Calendar.FRIDAY) { + viewPager.currentItem = day - 2 + } else { + viewPager.currentItem = 4 + } + + return view + } +} + +class DayPagerAdapter(fragmentManager: FragmentManager, lifecycle: Lifecycle) : + FragmentStateAdapter(fragmentManager, lifecycle) { + + private val fragmentList = mutableListOf() + + fun addFragment(fragment: Fragment) { + fragmentList.add(fragment) + } + + override fun getItemCount(): Int { + return fragmentList.size + } + + override fun createFragment(position: Int): Fragment { + return fragmentList[position] + } +} + +class DayFragment(private val position: Int) : Fragment(R.layout.fragment_day) { + @SuppressLint("ClickableViewAccessibility") + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle? + ): View? { + val view = inflater.inflate(R.layout.fragment_day, container, false) + + val dayLayout: LinearLayout = view.findViewById(R.id.layoutDayMain) + MainActivity.dayMap[position]?.let { createDayView(it, dayLayout, resources) } + + return view + } + private fun createDayView(day: Day, rootLayout: LinearLayout, resources: Resources) { + val scrollView = ScrollView(requireContext()) + + val dayLayout = LinearLayout(requireContext()) + dayLayout.orientation = LinearLayout.VERTICAL + + val nameDateTextView = TextView(requireContext()) + val nameDateString = day.name + " " + day.date + nameDateTextView.text = nameDateString + nameDateTextView.textSize = 30f + nameDateTextView.setPadding(10, 10, 10, 40) + nameDateTextView.gravity = Gravity.CENTER_HORIZONTAL + + rootLayout.addView(nameDateTextView) + + for (subj in day.subjects) { + val subjectDrawable = GradientDrawable() + subjectDrawable.shape = GradientDrawable.RECTANGLE + subjectDrawable.cornerRadius = + resources.getDimension(R.dimen.corner_radius) // Specify corner radius in resources + subjectDrawable.setColor( + ContextCompat.getColor( + requireContext(), + R.color.cal_week_subject + ) + ) // Use your desired background color + + val subjectLayout = LinearLayout(requireContext()) + subjectLayout.orientation = LinearLayout.HORIZONTAL + subjectLayout.gravity = Gravity.CENTER_VERTICAL + subjectLayout.background = subjectDrawable + + val subjectRelativeLayout = RelativeLayout(requireContext()) + subjectRelativeLayout.layoutParams = RelativeLayout.LayoutParams( + RelativeLayout.LayoutParams.MATCH_PARENT, + RelativeLayout.LayoutParams.MATCH_PARENT + ) + + val subjectNumberDrawable = GradientDrawable() + subjectNumberDrawable.shape = GradientDrawable.RECTANGLE + subjectNumberDrawable.cornerRadius = resources.getDimension((R.dimen.corner_radius)) + subjectNumberDrawable.setColor( + ContextCompat.getColor( + requireContext(), + R.color.cal_week_bg + ) + ) + + val subjectNumberTextView = TextView(requireContext()) + subjectNumberTextView.text = subj.number + subjectNumberTextView.textSize = 30f + subjectNumberTextView.setPadding(20, 20, 20, 20) + subjectNumberTextView.gravity = Gravity.CENTER_VERTICAL // Center text vertically + subjectNumberTextView.setTextColor( + ContextCompat.getColor( + requireContext(), + R.color.white + ) + ) + subjectNumberTextView.background = subjectNumberDrawable + + val frameLayout = FrameLayout(requireContext()) + val layoutParams = LinearLayout.LayoutParams( + FrameLayout.LayoutParams.WRAP_CONTENT, + FrameLayout.LayoutParams.MATCH_PARENT, + ) + frameLayout.layoutParams = layoutParams + + frameLayout.addView(subjectNumberTextView) + + subjectLayout.addView(frameLayout) + + val subjectNameTextView = TextView(requireContext()) + if (subj.name != "Volno") { + subjectNameTextView.text = subj.name.uppercase() + } + subjectNameTextView.textSize = 27f + subjectNameTextView.setPadding(60, 35, 20, 35) + subjectNameTextView.textAlignment = View.TEXT_ALIGNMENT_CENTER + subjectNameTextView.gravity = Gravity.CENTER_VERTICAL + if (subj.name != "Volno") { + subjectNameTextView.setTypeface(null, Typeface.BOLD) + } + subjectNameTextView.setTextColor( + ContextCompat.getColor( + requireContext(), + R.color.black + ) + ) + + if (subj.name == "Volno") { + subjectNameTextView.setPadding(260, 35, 20, 35) + } + + subjectLayout.addView(subjectNameTextView) + + val subjectPlaceTextView = TextView(requireContext()) + subjectPlaceTextView.text = subj.place + if (subj.name == "Volno") { + // underline + subjectPlaceTextView.setTypeface(null, Typeface.ITALIC) + } + subjectPlaceTextView.textSize = 22f + subjectPlaceTextView.gravity = Gravity.CENTER_VERTICAL + subjectPlaceTextView.setTextColor( + ContextCompat.getColor( + requireContext(), + R.color.black + ) + ) + + subjectLayout.addView(subjectPlaceTextView) + + val params = LinearLayout.LayoutParams( + LinearLayout.LayoutParams.MATCH_PARENT, + LinearLayout.LayoutParams.MATCH_PARENT + ) + params.gravity = Gravity.END + + val timeTeacherLayout = LinearLayout(requireContext()) + timeTeacherLayout.orientation = LinearLayout.VERTICAL + timeTeacherLayout.layoutParams = params + timeTeacherLayout.gravity = Gravity.CENTER_VERTICAL + + val subjectTimeTextView = TextView(requireContext()) + val subjectTimeString = subj.start + " - " + subj.end + subjectTimeTextView.text = subjectTimeString + subjectTimeTextView.textSize = 20f + subjectTimeTextView.setPadding(10, 10, 20, 10) + subjectTimeTextView.textAlignment = View.TEXT_ALIGNMENT_TEXT_END + subjectTimeTextView.setTextColor( + ContextCompat.getColor( + requireContext(), + R.color.black + ) + ) + + val subjectTeacherTextView = TextView(requireContext()) + subjectTeacherTextView.text = subj.teacher + subjectTeacherTextView.textSize = 15f + subjectTeacherTextView.setPadding(10, 10, 20, 10) + subjectTeacherTextView.textAlignment = View.TEXT_ALIGNMENT_TEXT_END + subjectTeacherTextView.setTextColor( + ContextCompat.getColor( + requireContext(), + R.color.black + ) + ) + + timeTeacherLayout.addView(subjectTimeTextView) + if (subj.name != "Volno") { + timeTeacherLayout.addView(subjectTeacherTextView) + } + + subjectLayout.addView(timeTeacherLayout) + + val subjectSeparator = Space(requireContext()) + subjectSeparator.layoutParams = LinearLayout.LayoutParams( + LinearLayout.LayoutParams.MATCH_PARENT, + resources.getDimensionPixelSize(R.dimen.cal_week_separator_height) // Specify separator height in resources + ) + + // Attach an OnPreDrawListener to the rootLayout's ViewTreeObserver + rootLayout.viewTreeObserver.addOnPreDrawListener(object : ViewTreeObserver.OnPreDrawListener { + override fun onPreDraw(): Boolean { + // Remove the listener to avoid multiple callbacks + rootLayout.viewTreeObserver.removeOnPreDrawListener(this) + + // Call your function or perform an action here + subjectPlaceTextView.setPadding(400-frameLayout.width-subjectNameTextView.width, 20, 20, 20) + + // Return true to continue with the drawing, or false to cancel + return true + } + }) + + val subjectLayoutParams = LinearLayout.LayoutParams( + LinearLayout.LayoutParams.MATCH_PARENT, + LinearLayout.LayoutParams.WRAP_CONTENT + ) + subjectLayoutParams.setMargins(20, 0, 20, 0) + subjectLayout.layoutParams = subjectLayoutParams + dayLayout.addView(subjectLayout) + dayLayout.addView(subjectSeparator) + } + + val dayEndTextView = TextView(requireContext()) + val endTime = day.subjects[day.subjects.size - 1].end + val dayEndString = "Day ends at $endTime" + dayEndTextView.text = dayEndString + dayEndTextView.textSize = 20f + dayEndTextView.setPadding(0, 30, 0, 30) + dayEndTextView.textAlignment = View.TEXT_ALIGNMENT_CENTER + dayEndTextView.gravity = Gravity.CENTER + dayEndTextView.setTextColor(ContextCompat.getColor(requireContext(), R.color.white)) + + val dayEndDrawable = GradientDrawable() + dayEndDrawable.shape = GradientDrawable.RECTANGLE + dayEndDrawable.cornerRadius = resources.getDimension((R.dimen.corner_radius)) + dayEndDrawable.setColor( + ContextCompat.getColor( + requireContext(), + R.color.cal_week_bg + ) + ) + dayEndTextView.background = dayEndDrawable + + val dayEndSeparator = Space(requireContext()) + dayEndSeparator.layoutParams = LinearLayout.LayoutParams( + LinearLayout.LayoutParams.MATCH_PARENT, + resources.getDimensionPixelSize(R.dimen.cal_week_separator_height) // Specify separator height in resources + ) + + val endParams = LinearLayout.LayoutParams( + LinearLayout.LayoutParams.MATCH_PARENT, + LinearLayout.LayoutParams.WRAP_CONTENT + ) + endParams.setMargins(20, 0, 20, 0) + dayEndTextView.layoutParams = endParams + + dayLayout.addView(dayEndSeparator) + dayLayout.addView(dayEndTextView) + + scrollView.addView(dayLayout) + + rootLayout.addView(scrollView) + } +} + +class Subject { + var name: String = "" + var place: String = "" + var teacher: String = "" + var substitute: String = "" + var number: String = "" + var start: String = "" + var end: String = "" +} + +class Day { + var name: String = "" + var date: String = "" + var subjects: List = mutableListOf() +} \ No newline at end of file diff --git a/mobile/app/src/main/java/com/odweta/solen/MainActivity.kt b/mobile/app/src/main/java/com/odweta/solen/MainActivity.kt index 6b08a45..59fd399 100644 --- a/mobile/app/src/main/java/com/odweta/solen/MainActivity.kt +++ b/mobile/app/src/main/java/com/odweta/solen/MainActivity.kt @@ -1,54 +1,155 @@ package com.odweta.solen import android.os.Bundle -import android.view.Menu -import com.google.android.material.snackbar.Snackbar -import com.google.android.material.navigation.NavigationView -import androidx.navigation.findNavController -import androidx.navigation.ui.AppBarConfiguration -import androidx.navigation.ui.navigateUp -import androidx.navigation.ui.setupActionBarWithNavController -import androidx.navigation.ui.setupWithNavController -import androidx.drawerlayout.widget.DrawerLayout +import android.util.Log +import android.view.View import androidx.appcompat.app.AppCompatActivity -import com.odweta.solen.databinding.ActivityMainBinding +import androidx.lifecycle.lifecycleScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext +import okhttp3.FormBody +import okhttp3.OkHttpClient +import okhttp3.Request +import org.json.JSONObject +import java.io.IOException +import java.text.SimpleDateFormat +import java.util.Calendar +import java.util.Date +import java.util.Locale -class MainActivity : AppCompatActivity() { +class MainActivity : AppCompatActivity(), MainActivityListener { + companion object { + val dayMap = mutableMapOf() + val dateMap = mutableMapOf() + } - private lateinit var appBarConfiguration: AppBarConfiguration - private lateinit var binding: ActivityMainBinding + private val username = "x" + private val password = "y" override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) + setContentView(R.layout.activity_cal_week) - binding = ActivityMainBinding.inflate(layoutInflater) - setContentView(binding.root) + launch() + } - setSupportActionBar(binding.appBarMain.toolbar) + override fun onLaunch(view: View) { + launch() + } - binding.appBarMain.fab.setOnClickListener { view -> - Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG) - .setAction("Action", null).show() + private fun launch() { + lifecycleScope.launch { + val week = parseJSON(getCalWeekJSON(username, password)) + for ((i, day) in week.withIndex()) { + dayMap[i] = day + } + + val currentDate = SimpleDateFormat("d.M.", Locale.getDefault()).format(Date()) + val dayOfWeek = Calendar.DAY_OF_WEEK + dateMap[currentDate] = dayOfWeek - 2 + + val mainFragment = CalWeekFragment() + supportFragmentManager.beginTransaction() + .replace(R.id.fragmentContainer, mainFragment) + .commit() } - val drawerLayout: DrawerLayout = binding.drawerLayout - val navView: NavigationView = binding.navView - val navController = findNavController(R.id.nav_host_fragment_content_main) - // Passing each menu ID as a set of Ids because each - // menu should be considered as top level destinations. - appBarConfiguration = AppBarConfiguration(setOf( - R.id.nav_home, R.id.nav_gallery, R.id.nav_slideshow), drawerLayout) - setupActionBarWithNavController(navController, appBarConfiguration) - navView.setupWithNavController(navController) } - override fun onCreateOptionsMenu(menu: Menu): Boolean { - // Inflate the menu; this adds items to the action bar if it is present. - menuInflater.inflate(R.menu.main, menu) - return true + private suspend fun getCalWeekJSON(username: String, password: String): String { + val url = "http://127.0.0.1:8080/fetch.php" + val client = OkHttpClient() + + return withContext(Dispatchers.IO) { + val request = Request.Builder() + .url(url) + .post( + FormBody.Builder() + .add("username", username) + .add("password", password) + .add("cal_week", "true") + .build() + ) + .build() + + try { + val resp = client.newCall(request).execute() + resp.body?.string() + } catch (e: IOException) { + """{ + "body": [ + { + "name": "Login failed", + "date": "Login failed", + "subjects": [ + "name": "Login failed", + "place": "Login failed", + "teacher": "Login failed", + "is_substitute": "Login failed", + "number": 0, + "start": "Login failed", + "end": "Login failed" + ] + } + ], + "status_code": 1 + }""".trimMargin() + } + }.toString() } - override fun onSupportNavigateUp(): Boolean { - val navController = findNavController(R.id.nav_host_fragment_content_main) - return navController.navigateUp(appBarConfiguration) || super.onSupportNavigateUp() + private fun parseJSON(jsonString: String): List { + val jsonObject = JSONObject(jsonString) + + /* + * return a List that looks like this: + * ["Po", "8.1.", ["D", "207", "Strakova S.", 0, 1, "08:00", "08:45"]] + */ + + // Access the "body" array from the main JSON object + val bodyArray = jsonObject.getJSONArray("body") + + val week = mutableListOf() + + // Convert the JSON array to a list of JSON objects + val jsonObjectList = mutableListOf() + for (i in 0 until bodyArray.length()) { + val nestedJsonObject = bodyArray.getJSONObject(i) + jsonObjectList.add(nestedJsonObject) + } + + for (obj in jsonObjectList) { + val name = obj.get("name").toString() + val date = obj.get("date").toString() + val subjects = mutableListOf() + + val subjectJSONList = mutableListOf() + val subjectArray = obj.getJSONArray("subjects") + for (i in 0 until subjectArray.length()) { + subjectJSONList.add(subjectArray.getJSONObject(i)) + } + + for (subj in subjectJSONList) { + val subject = Subject() + subject.name = subj.get("name").toString() + subject.place = subj.get("place").toString() + subject.teacher = subj.get("teacher").toString() + subject.substitute = subj.get("is_substitute").toString() + subject.number = subj.get("number").toString() + subject.start = subj.get("start").toString() + subject.end = subj.get("end").toString() + + subjects.add(subject) + } + + val day = Day() + day.name = name + day.date = date + day.subjects = subjects + + week.add(day) + } + + return week } } \ No newline at end of file diff --git a/mobile/app/src/main/java/com/odweta/solen/ui/gallery/GalleryFragment.kt b/mobile/app/src/main/java/com/odweta/solen/ui/gallery/GalleryFragment.kt deleted file mode 100644 index 3a3416e..0000000 --- a/mobile/app/src/main/java/com/odweta/solen/ui/gallery/GalleryFragment.kt +++ /dev/null @@ -1,42 +0,0 @@ -package com.odweta.solen.ui.gallery - -import android.os.Bundle -import android.view.LayoutInflater -import android.view.View -import android.view.ViewGroup -import android.widget.TextView -import androidx.fragment.app.Fragment -import androidx.lifecycle.ViewModelProvider -import com.odweta.solen.databinding.FragmentGalleryBinding - -class GalleryFragment : Fragment() { - - private var _binding: FragmentGalleryBinding? = null - - // This property is only valid between onCreateView and - // onDestroyView. - private val binding get() = _binding!! - - override fun onCreateView( - inflater: LayoutInflater, - container: ViewGroup?, - savedInstanceState: Bundle? - ): View { - val galleryViewModel = - ViewModelProvider(this).get(GalleryViewModel::class.java) - - _binding = FragmentGalleryBinding.inflate(inflater, container, false) - val root: View = binding.root - - val textView: TextView = binding.textGallery - galleryViewModel.text.observe(viewLifecycleOwner) { - textView.text = it - } - return root - } - - override fun onDestroyView() { - super.onDestroyView() - _binding = null - } -} \ No newline at end of file diff --git a/mobile/app/src/main/java/com/odweta/solen/ui/gallery/GalleryViewModel.kt b/mobile/app/src/main/java/com/odweta/solen/ui/gallery/GalleryViewModel.kt deleted file mode 100644 index c628a78..0000000 --- a/mobile/app/src/main/java/com/odweta/solen/ui/gallery/GalleryViewModel.kt +++ /dev/null @@ -1,13 +0,0 @@ -package com.odweta.solen.ui.gallery - -import androidx.lifecycle.LiveData -import androidx.lifecycle.MutableLiveData -import androidx.lifecycle.ViewModel - -class GalleryViewModel : ViewModel() { - - private val _text = MutableLiveData().apply { - value = "This is gallery Fragment" - } - val text: LiveData = _text -} \ No newline at end of file diff --git a/mobile/app/src/main/java/com/odweta/solen/ui/home/HomeFragment.kt b/mobile/app/src/main/java/com/odweta/solen/ui/home/HomeFragment.kt deleted file mode 100644 index 65ff036..0000000 --- a/mobile/app/src/main/java/com/odweta/solen/ui/home/HomeFragment.kt +++ /dev/null @@ -1,42 +0,0 @@ -package com.odweta.solen.ui.home - -import android.os.Bundle -import android.view.LayoutInflater -import android.view.View -import android.view.ViewGroup -import android.widget.TextView -import androidx.fragment.app.Fragment -import androidx.lifecycle.ViewModelProvider -import com.odweta.solen.databinding.FragmentHomeBinding - -class HomeFragment : Fragment() { - - private var _binding: FragmentHomeBinding? = null - - // This property is only valid between onCreateView and - // onDestroyView. - private val binding get() = _binding!! - - override fun onCreateView( - inflater: LayoutInflater, - container: ViewGroup?, - savedInstanceState: Bundle? - ): View { - val homeViewModel = - ViewModelProvider(this).get(HomeViewModel::class.java) - - _binding = FragmentHomeBinding.inflate(inflater, container, false) - val root: View = binding.root - - val textView: TextView = binding.textHome - homeViewModel.text.observe(viewLifecycleOwner) { - textView.text = it - } - return root - } - - override fun onDestroyView() { - super.onDestroyView() - _binding = null - } -} \ No newline at end of file diff --git a/mobile/app/src/main/java/com/odweta/solen/ui/home/HomeViewModel.kt b/mobile/app/src/main/java/com/odweta/solen/ui/home/HomeViewModel.kt deleted file mode 100644 index fa424c0..0000000 --- a/mobile/app/src/main/java/com/odweta/solen/ui/home/HomeViewModel.kt +++ /dev/null @@ -1,13 +0,0 @@ -package com.odweta.solen.ui.home - -import androidx.lifecycle.LiveData -import androidx.lifecycle.MutableLiveData -import androidx.lifecycle.ViewModel - -class HomeViewModel : ViewModel() { - - private val _text = MutableLiveData().apply { - value = "This is home Fragment" - } - val text: LiveData = _text -} \ No newline at end of file diff --git a/mobile/app/src/main/java/com/odweta/solen/ui/slideshow/SlideshowFragment.kt b/mobile/app/src/main/java/com/odweta/solen/ui/slideshow/SlideshowFragment.kt deleted file mode 100644 index 1910270..0000000 --- a/mobile/app/src/main/java/com/odweta/solen/ui/slideshow/SlideshowFragment.kt +++ /dev/null @@ -1,42 +0,0 @@ -package com.odweta.solen.ui.slideshow - -import android.os.Bundle -import android.view.LayoutInflater -import android.view.View -import android.view.ViewGroup -import android.widget.TextView -import androidx.fragment.app.Fragment -import androidx.lifecycle.ViewModelProvider -import com.odweta.solen.databinding.FragmentSlideshowBinding - -class SlideshowFragment : Fragment() { - - private var _binding: FragmentSlideshowBinding? = null - - // This property is only valid between onCreateView and - // onDestroyView. - private val binding get() = _binding!! - - override fun onCreateView( - inflater: LayoutInflater, - container: ViewGroup?, - savedInstanceState: Bundle? - ): View { - val slideshowViewModel = - ViewModelProvider(this).get(SlideshowViewModel::class.java) - - _binding = FragmentSlideshowBinding.inflate(inflater, container, false) - val root: View = binding.root - - val textView: TextView = binding.textSlideshow - slideshowViewModel.text.observe(viewLifecycleOwner) { - textView.text = it - } - return root - } - - override fun onDestroyView() { - super.onDestroyView() - _binding = null - } -} \ No newline at end of file diff --git a/mobile/app/src/main/java/com/odweta/solen/ui/slideshow/SlideshowViewModel.kt b/mobile/app/src/main/java/com/odweta/solen/ui/slideshow/SlideshowViewModel.kt deleted file mode 100644 index 88fa0b5..0000000 --- a/mobile/app/src/main/java/com/odweta/solen/ui/slideshow/SlideshowViewModel.kt +++ /dev/null @@ -1,13 +0,0 @@ -package com.odweta.solen.ui.slideshow - -import androidx.lifecycle.LiveData -import androidx.lifecycle.MutableLiveData -import androidx.lifecycle.ViewModel - -class SlideshowViewModel : ViewModel() { - - private val _text = MutableLiveData().apply { - value = "This is slideshow Fragment" - } - val text: LiveData = _text -} \ No newline at end of file diff --git a/mobile/app/src/main/res/drawable/ic_launcher_background.xml b/mobile/app/src/main/res/drawable/ic_launcher_background.xml deleted file mode 100644 index 07d5da9..0000000 --- a/mobile/app/src/main/res/drawable/ic_launcher_background.xml +++ /dev/null @@ -1,170 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/mobile/app/src/main/res/drawable/ic_launcher_foreground.xml b/mobile/app/src/main/res/drawable/ic_launcher_foreground.xml deleted file mode 100644 index 2b068d1..0000000 --- a/mobile/app/src/main/res/drawable/ic_launcher_foreground.xml +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/mobile/app/src/main/res/drawable/ic_menu_camera.xml b/mobile/app/src/main/res/drawable/ic_menu_camera.xml deleted file mode 100644 index 634fe92..0000000 --- a/mobile/app/src/main/res/drawable/ic_menu_camera.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - diff --git a/mobile/app/src/main/res/drawable/ic_menu_gallery.xml b/mobile/app/src/main/res/drawable/ic_menu_gallery.xml deleted file mode 100644 index 03c7709..0000000 --- a/mobile/app/src/main/res/drawable/ic_menu_gallery.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - diff --git a/mobile/app/src/main/res/drawable/ic_menu_slideshow.xml b/mobile/app/src/main/res/drawable/ic_menu_slideshow.xml deleted file mode 100644 index 5e9e163..0000000 --- a/mobile/app/src/main/res/drawable/ic_menu_slideshow.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - diff --git a/mobile/app/src/main/res/drawable/rounded_corner_background.xml b/mobile/app/src/main/res/drawable/rounded_corner_background.xml new file mode 100644 index 0000000..24bb4d5 --- /dev/null +++ b/mobile/app/src/main/res/drawable/rounded_corner_background.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/mobile/app/src/main/res/drawable/side_nav_bar.xml b/mobile/app/src/main/res/drawable/side_nav_bar.xml deleted file mode 100644 index 6d81870..0000000 --- a/mobile/app/src/main/res/drawable/side_nav_bar.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - \ No newline at end of file diff --git a/mobile/app/src/main/res/layout/activity_cal_week.xml b/mobile/app/src/main/res/layout/activity_cal_week.xml new file mode 100644 index 0000000..fb00d86 --- /dev/null +++ b/mobile/app/src/main/res/layout/activity_cal_week.xml @@ -0,0 +1,43 @@ + + + +