mobile app v1 + backend server

This commit is contained in:
Odweta
2024-01-26 16:08:27 +01:00
parent 860c4bf503
commit 8cedbc1c15
49 changed files with 765 additions and 741 deletions
+5 -3
View File
@@ -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.
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.
+3
View File
@@ -0,0 +1,3 @@
# Default ignored files
/shelf/
/workspace.xml
+1
View File
@@ -0,0 +1 @@
Solen
+123
View File
@@ -0,0 +1,123 @@
<component name="ProjectCodeStyleConfiguration">
<code_scheme name="Project" version="173">
<JetCodeStyleSettings>
<option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" />
</JetCodeStyleSettings>
<codeStyleSettings language="XML">
<option name="FORCE_REARRANGE_MODE" value="1" />
<indentOptions>
<option name="CONTINUATION_INDENT_SIZE" value="4" />
</indentOptions>
<arrangement>
<rules>
<section>
<rule>
<match>
<AND>
<NAME>xmlns:android</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>^$</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>xmlns:.*</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>^$</XML_NAMESPACE>
</AND>
</match>
<order>BY_NAME</order>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*:id</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*:name</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>name</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>^$</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>style</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>^$</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>^$</XML_NAMESPACE>
</AND>
</match>
<order>BY_NAME</order>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
</AND>
</match>
<order>ANDROID_ATTRIBUTE_ORDER</order>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>.*</XML_NAMESPACE>
</AND>
</match>
<order>BY_NAME</order>
</rule>
</section>
</rules>
</arrangement>
</codeStyleSettings>
<codeStyleSettings language="kotlin">
<option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" />
</codeStyleSettings>
</code_scheme>
</component>
+5
View File
@@ -0,0 +1,5 @@
<component name="ProjectCodeStyleConfiguration">
<state>
<option name="USE_PER_PROJECT_SETTINGS" value="true" />
</state>
</component>
+6
View File
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="CompilerConfiguration">
<bytecodeTargetLevel target="17" />
</component>
</project>
+10
View File
@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="deploymentTargetDropDown">
<value>
<entry key="app">
<State />
</entry>
</value>
</component>
</project>
+19
View File
@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="GradleMigrationSettings" migrationVersion="1" />
<component name="GradleSettings">
<option name="linkedExternalProjectsSettings">
<GradleProjectSettings>
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="gradleJvm" value="#GRADLE_LOCAL_JAVA_HOME" />
<option name="modules">
<set>
<option value="$PROJECT_DIR$" />
<option value="$PROJECT_DIR$/app" />
</set>
</option>
<option name="resolveExternalAnnotations" value="false" />
</GradleProjectSettings>
</option>
</component>
</project>
+6
View File
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="KotlinJpsPluginSettings">
<option name="version" value="1.9.22" />
</component>
</project>
+10
View File
@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectMigrations">
<option name="MigrateToGradleLocalJavaHome">
<set>
<option value="$PROJECT_DIR$" />
</set>
</option>
</component>
</project>
+9
View File
@@ -0,0 +1,9 @@
<project version="4">
<component name="ExternalStorageConfigurationManager" enabled="true" />
<component name="ProjectRootManager" version="2" languageLevel="JDK_17" default="true" project-jdk-name="jbr-17" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/build/classes" />
</component>
<component name="ProjectType">
<option name="id" value="Android" />
</component>
</project>
+6
View File
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$/.." vcs="Git" />
</component>
</project>
+5 -2
View File
@@ -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")
}
@@ -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)
}
}
+5 -2
View File
@@ -2,6 +2,8 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<uses-permission android:name="android.permission.INTERNET" />
<application
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
@@ -11,11 +13,12 @@
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.Solen"
tools:targetApi="31">
tools:targetApi="tiramisu"
android:usesCleartextTraffic="true"
android:enableOnBackInvokedCallback="true">
<activity
android:name=".MainActivity"
android:exported="true"
android:label="@string/app_name"
android:theme="@style/Theme.Solen.NoActionBar">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
@@ -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<Fragment>()
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<Subject> = mutableListOf()
}
@@ -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<Int, Day>()
val dateMap = mutableMapOf<String, Int>()
}
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<Day> {
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<Day>()
// Convert the JSON array to a list of JSON objects
val jsonObjectList = mutableListOf<JSONObject>()
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<Subject>()
val subjectJSONList = mutableListOf<JSONObject>()
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
}
}
@@ -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
}
}
@@ -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<String>().apply {
value = "This is gallery Fragment"
}
val text: LiveData<String> = _text
}
@@ -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
}
}
@@ -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<String>().apply {
value = "This is home Fragment"
}
val text: LiveData<String> = _text
}
@@ -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
}
}
@@ -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<String>().apply {
value = "This is slideshow Fragment"
}
val text: LiveData<String> = _text
}
@@ -1,170 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="108dp"
android:height="108dp"
android:viewportWidth="108"
android:viewportHeight="108">
<path
android:fillColor="#3DDC84"
android:pathData="M0,0h108v108h-108z" />
<path
android:fillColor="#00000000"
android:pathData="M9,0L9,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,0L19,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M29,0L29,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M39,0L39,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M49,0L49,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M59,0L59,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M69,0L69,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M79,0L79,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M89,0L89,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M99,0L99,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,9L108,9"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,19L108,19"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,29L108,29"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,39L108,39"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,49L108,49"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,59L108,59"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,69L108,69"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,79L108,79"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,89L108,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,99L108,99"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,29L89,29"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,39L89,39"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,49L89,49"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,59L89,59"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,69L89,69"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,79L89,79"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M29,19L29,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M39,19L39,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M49,19L49,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M59,19L59,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M69,19L69,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M79,19L79,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
</vector>
@@ -1,30 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:aapt="http://schemas.android.com/aapt"
android:width="108dp"
android:height="108dp"
android:viewportWidth="108"
android:viewportHeight="108">
<path android:pathData="M31,63.928c0,0 6.4,-11 12.1,-13.1c7.2,-2.6 26,-1.4 26,-1.4l38.1,38.1L107,108.928l-32,-1L31,63.928z">
<aapt:attr name="android:fillColor">
<gradient
android:endX="85.84757"
android:endY="92.4963"
android:startX="42.9492"
android:startY="49.59793"
android:type="linear">
<item
android:color="#44000000"
android:offset="0.0" />
<item
android:color="#00000000"
android:offset="1.0" />
</gradient>
</aapt:attr>
</path>
<path
android:fillColor="#FFFFFF"
android:fillType="nonZero"
android:pathData="M65.3,45.828l3.8,-6.6c0.2,-0.4 0.1,-0.9 -0.3,-1.1c-0.4,-0.2 -0.9,-0.1 -1.1,0.3l-3.9,6.7c-6.3,-2.8 -13.4,-2.8 -19.7,0l-3.9,-6.7c-0.2,-0.4 -0.7,-0.5 -1.1,-0.3C38.8,38.328 38.7,38.828 38.9,39.228l3.8,6.6C36.2,49.428 31.7,56.028 31,63.928h46C76.3,56.028 71.8,49.428 65.3,45.828zM43.4,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2c-0.3,-0.7 -0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C45.3,56.528 44.5,57.328 43.4,57.328L43.4,57.328zM64.6,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2s-0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C66.5,56.528 65.6,57.328 64.6,57.328L64.6,57.328z"
android:strokeWidth="1"
android:strokeColor="#00000000" />
</vector>
@@ -1,12 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FF000000"
android:pathData="M12,12m-3.2,0a3.2,3.2 0,1 1,6.4 0a3.2,3.2 0,1 1,-6.4 0" />
<path
android:fillColor="#FF000000"
android:pathData="M9,2L7.17,4H4c-1.1,0 -2,0.9 -2,2v12c0,1.1 0.9,2 2,2h16c1.1,0 2,-0.9 2,-2V6c0,-1.1 -0.9,-2 -2,-2h-3.17L15,2H9zm3,15c-2.76,0 -5,-2.24 -5,-5s2.24,-5 5,-5 5,2.24 5,5 -2.24,5 -5,5z" />
</vector>
@@ -1,9 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FF000000"
android:pathData="M22,16V4c0,-1.1 -0.9,-2 -2,-2H8c-1.1,0 -2,0.9 -2,2v12c0,1.1 0.9,2 2,2h12c1.1,0 2,-0.9 2,-2zm-11,-4l2.03,2.71L16,11l4,5H8l3,-4zM2,6v14c0,1.1 0.9,2 2,2h14v-2H4V6H2z" />
</vector>
@@ -1,9 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FF000000"
android:pathData="M4,6H2v14c0,1.1 0.9,2 2,2h14v-2H4V6zm16,-4H8c-1.1,0 -2,0.9 -2,2v12c0,1.1 0.9,2 2,2h12c1.1,0 2,-0.9 2,-2V4c0,-1.1 -0.9,-2 -2,-2zm-8,12.5v-9l6,4.5 -6,4.5z" />
</vector>
@@ -0,0 +1,5 @@
<!-- res/drawable/rounded_corner_background.xml -->
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<corners android:radius="20dp" /> <!-- Adjust the radius as needed -->
<solid android:color="#696969" /> <!-- Set the background color -->
</shape>
@@ -1,9 +0,0 @@
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<gradient
android:angle="135"
android:centerColor="#009688"
android:endColor="#00695C"
android:startColor="#4DB6AC"
android:type="linear" />
</shape>
@@ -0,0 +1,43 @@
<?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"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/cal_week_root"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<Button
android:id="@+id/refreshButton"
android:layout_width="105dp"
android:layout_height="53dp"
android:onClick="onLaunch"
android:text="Refresh"
app:layout_constraintBottom_toTopOf="@+id/dayPager"
app:layout_constraintEnd_toStartOf="@+id/dayPager"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.0" />
<androidx.viewpager2.widget.ViewPager2
android:id="@+id/dayPager"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<!--
<TextView
android:id="@+id/loadingTextView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:text="@string/cal_week_loading"
android:textAlignment="center"
android:textSize="34sp" />
-->
<FrameLayout
android:id="@+id/fragmentContainer"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
@@ -1,25 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.drawerlayout.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:openDrawer="start">
<include
android:id="@+id/app_bar_main"
layout="@layout/app_bar_main"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<com.google.android.material.navigation.NavigationView
android:id="@+id/nav_view"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
android:fitsSystemWindows="true"
app:headerLayout="@layout/nav_header_main"
app:menu="@menu/activity_main_drawer" />
</androidx.drawerlayout.widget.DrawerLayout>
@@ -1,34 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="@style/Theme.Solen.AppBarOverlay">
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:popupTheme="@style/Theme.Solen.PopupOverlay" />
</com.google.android.material.appbar.AppBarLayout>
<include layout="@layout/content_main" />
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|end"
android:layout_marginEnd="@dimen/fab_margin"
android:layout_marginBottom="16dp"
app:srcCompat="@android:drawable/ic_dialog_email" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>
@@ -1,20 +0,0 @@
<?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"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
tools:showIn="@layout/app_bar_main">
<fragment
android:id="@+id/nav_host_fragment_content_main"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:defaultNavHost="true"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:navGraph="@navigation/mobile_navigation" />
</androidx.constraintlayout.widget.ConstraintLayout>
@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:id="@+id/layoutDayMain"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
@@ -1,22 +0,0 @@
<?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"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ui.gallery.GalleryFragment">
<TextView
android:id="@+id/text_gallery"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:textAlignment="center"
android:textSize="20sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
@@ -1,22 +0,0 @@
<?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"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ui.home.HomeFragment">
<TextView
android:id="@+id/text_home"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:textAlignment="center"
android:textSize="20sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
@@ -1,22 +0,0 @@
<?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"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ui.slideshow.SlideshowFragment">
<TextView
android:id="@+id/text_slideshow"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:textAlignment="center"
android:textSize="20sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
@@ -1,35 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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="@dimen/nav_header_height"
android:background="@drawable/side_nav_bar"
android:gravity="bottom"
android:orientation="vertical"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingBottom="@dimen/activity_vertical_margin"
android:theme="@style/ThemeOverlay.AppCompat.Dark">
<ImageView
android:id="@+id/imageView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="@string/nav_header_desc"
android:paddingTop="@dimen/nav_header_vertical_spacing"
app:srcCompat="@mipmap/ic_launcher_round" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="@dimen/nav_header_vertical_spacing"
android:text="@string/nav_header_title"
android:textAppearance="@style/TextAppearance.AppCompat.Body1" />
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/nav_header_subtitle" />
</LinearLayout>
@@ -1,20 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
tools:showIn="navigation_view">
<group android:checkableBehavior="single">
<item
android:id="@+id/nav_home"
android:icon="@drawable/ic_menu_camera"
android:title="@string/menu_home" />
<item
android:id="@+id/nav_gallery"
android:icon="@drawable/ic_menu_gallery"
android:title="@string/menu_gallery" />
<item
android:id="@+id/nav_slideshow"
android:icon="@drawable/ic_menu_slideshow"
android:title="@string/menu_slideshow" />
</group>
</menu>
-9
View File
@@ -1,9 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/action_settings"
android:orderInCategory="100"
android:title="@string/action_settings"
app:showAsAction="never" />
</menu>
@@ -1,6 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@drawable/ic_launcher_background" />
<foreground android:drawable="@drawable/ic_launcher_foreground" />
<monochrome android:drawable="@drawable/ic_launcher_foreground" />
</adaptive-icon>
@@ -1,6 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@drawable/ic_launcher_background" />
<foreground android:drawable="@drawable/ic_launcher_foreground" />
<monochrome android:drawable="@drawable/ic_launcher_foreground" />
</adaptive-icon>
@@ -1,25 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/mobile_navigation"
app:startDestination="@+id/nav_home">
<fragment
android:id="@+id/nav_home"
android:name="com.odweta.solen.ui.home.HomeFragment"
android:label="@string/menu_home"
tools:layout="@layout/fragment_home" />
<fragment
android:id="@+id/nav_gallery"
android:name="com.odweta.solen.ui.gallery.GalleryFragment"
android:label="@string/menu_gallery"
tools:layout="@layout/fragment_gallery" />
<fragment
android:id="@+id/nav_slideshow"
android:name="com.odweta.solen.ui.slideshow.SlideshowFragment"
android:label="@string/menu_slideshow"
tools:layout="@layout/fragment_slideshow" />
</navigation>
+7 -5
View File
@@ -1,10 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="purple_200">#FFBB86FC</color>
<color name="purple_500">#FF6200EE</color>
<color name="purple_700">#FF3700B3</color>
<color name="teal_200">#FF03DAC5</color>
<color name="teal_700">#FF018786</color>
<color name="purple_200">#FFED7D31</color>
<color name="purple_500">#FF6C5F5B</color>
<color name="purple_700">#FF4F4A45</color>
<color name="teal_200">#FFF6F1EE</color>
<color name="teal_700">#FFF6F1EE</color>
<color name="black">#FF000000</color>
<color name="white">#FFFFFFFF</color>
<color name="cal_week_bg">#696969</color>
<color name="cal_week_subject">#f1f1f1</color>
</resources>
@@ -5,4 +5,6 @@
<dimen name="nav_header_vertical_spacing">8dp</dimen>
<dimen name="nav_header_height">176dp</dimen>
<dimen name="fab_margin">16dp</dimen>
<dimen name="cal_week_separator_height">20dp</dimen> <!-- Adjust the height as needed -->
<dimen name="corner_radius">8dp</dimen> <!-- Adjust the corner radius as needed -->
</resources>
+3 -2
View File
@@ -2,12 +2,13 @@
<string name="app_name">Solen</string>
<string name="navigation_drawer_open">Open navigation drawer</string>
<string name="navigation_drawer_close">Close navigation drawer</string>
<string name="nav_header_title">Android Studio</string>
<string name="nav_header_title">Solen</string>
<string name="nav_header_subtitle">android.studio@android.com</string>
<string name="nav_header_desc">Navigation header</string>
<string name="action_settings">Settings</string>
<string name="menu_cal_week">Calendar for this week</string>
<string name="menu_home">Home</string>
<string name="menu_gallery">Gallery</string>
<string name="menu_slideshow">Slideshow</string>
<string name="cal_week_loading">Loading the calendar for this week...</string>
</resources>
@@ -1,17 +0,0 @@
package com.odweta.solen
import org.junit.Test
import org.junit.Assert.*
/**
* Example local unit test, which will execute on the development machine (host).
*
* See [testing documentation](http://d.android.com/tools/testing).
*/
class ExampleUnitTest {
@Test
fun addition_isCorrect() {
assertEquals(4, 2 + 2)
}
}
+1 -1
View File
@@ -14,4 +14,4 @@ dependencyResolutionManagement {
}
rootProject.name = "Solen"
include(":app")
include(":app")