Skip to content
This repository has been archived by the owner on May 29, 2024. It is now read-only.

Commit

Permalink
Merge branch 'dev'
Browse files Browse the repository at this point in the history
  • Loading branch information
zexee24 committed Feb 8, 2023
2 parents 41e69dc + ccdcd7a commit 0d32966
Show file tree
Hide file tree
Showing 8 changed files with 133 additions and 64 deletions.
6 changes: 6 additions & 0 deletions app/src/main/java/com/otawilma/mobileclient/Exceptions.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package com.otawilma.mobileclient

class InvalidTokenNetworkException(override val message: String?) : Exception()
class OtaWilmaDownException(override val message: String) : Exception()
class WilmaDownException(override val message: String?) : Exception()
class NoStoredTokenException(override val message: String?) : Exception()
103 changes: 70 additions & 33 deletions app/src/main/java/com/otawilma/mobileclient/OtawilmaNetworking.kt
Original file line number Diff line number Diff line change
Expand Up @@ -31,20 +31,47 @@ interface OtawilmaNetworking : LessonParser, MessageParser {
context.startActivity(Intent(context, LoginActivity::class.java))
}

var token = getToken()
while (token == null){
delay(10)
token = getToken()
while (true){
try {return getToken()}
catch (_: NoStoredTokenException){
delay(10)
}
}
return token


}

suspend fun getToken() : String? {
suspend fun invalidateTokenAndGetNew(context: Context) : String {
tokenGlobal = null
encryptedPreferenceStorage.otaWilmaToken = null
return waitUntilToken(context)
}

suspend fun waitUntilToken(context: Context) : String{
while (true){
try {return getToken()}
catch (e: Exception){
when(e){
is NoStoredTokenException -> return handleInvalidToken(context)
is OtaWilmaDownException, is WilmaDownException -> delay(100)
else -> throw e
}
}
}
}

// Returns a token or gets one from the server
suspend fun getToken() : String {

// If we have a token, then very good
if (tokenGlobal != null) return tokenGlobal!!

if (testToken(encryptedPreferenceStorage.otaWilmaToken)) return encryptedPreferenceStorage.otaWilmaToken
// If we have a stored token, then still fairly good
val temp = encryptedPreferenceStorage.otaWilmaToken
if (temp != null) {
tokenGlobal = temp
return temp
}

// If we can automatically Login, then still good
val userName = encryptedPreferenceStorage.userName
Expand All @@ -53,24 +80,40 @@ interface OtawilmaNetworking : LessonParser, MessageParser {
Log.d("RequestTracking", "Another Login request")
tokenGlobal = login(userName, pwd)
encryptedPreferenceStorage.otaWilmaToken = tokenGlobal
return tokenGlobal
return tokenGlobal!!
}
// If we cant, then shit
return null
throw NoStoredTokenException("No token exists and one cannot be retried")
}

// Returns if the Otawilma-server can be reached
suspend fun testToken(token : String?) : Boolean{
fun checkCode(code : Int){
when (code) {
200 -> return
404, 500 -> throw OtaWilmaDownException("Otawilma is down")
501 -> throw WilmaDownException("Wilma is down")
401 -> throw InvalidTokenNetworkException("The token is invalid")
else -> throw Exception("Received unexpected code from server code: $code")

}
}

// Returns if the Otawilma-server can be reached and the token is valid
suspend fun testToken(token : String?) : Boolean {
if (token == null) return false
val request = Request.Builder().url("$OTAWILMA_API_URL/authenticate").header("token",token).post("".toRequestBody()).build()
client.newCall(request).execute().use {
return it.isSuccessful
if (it.isSuccessful){
return true
} else {
Log.d("Networking", "The request was no successful: ${it.message} with the code of ${it.code} ")
return false
}
}

}

// Returns if Otawilma can reach the wilma-server
suspend fun pingWilma():Boolean{
suspend fun pingWilma() : Boolean{
return false
}

Expand All @@ -88,23 +131,20 @@ interface OtawilmaNetworking : LessonParser, MessageParser {

client.newCall(request).execute().use {
//Log.d("Networking",it.body!!.string())
if (it.isSuccessful) {
return Gson().fromJson<Map<String, String>>(
it.body!!.string(),
Map::class.java
)["token"]
}
return null
checkCode(it.code)
return Gson().fromJson<Map<String, String>>(
it.body!!.string(),
Map::class.java
)["token"]
}


}

suspend fun logout (token: String) : Boolean{
val request = Request.Builder().url("$OTAWILMA_API_URL/logout").header("token",token).build()

client.newCall(request).execute().use {
return it.isSuccessful
checkCode(it.code)
return true
}
}

Expand All @@ -115,9 +155,7 @@ interface OtawilmaNetworking : LessonParser, MessageParser {
token).build()

client.newCall(request).execute().use {
if (!it.isSuccessful) {
return null
}
checkCode(it.code)
val body = it.body ?: return null
val bodyString = body.string()
Log.d("Networking", bodyString)
Expand Down Expand Up @@ -153,19 +191,19 @@ interface OtawilmaNetworking : LessonParser, MessageParser {
//suspend fun getNewMessages(limit: Int) : List<MessageItem>

// Get messages from the latest to until
suspend fun getMessages(token : String, until : Int) : Pair<Boolean,List<Message>>{
suspend fun getMessages(token : String, until : Int) : List<Message>{
val request = Request.Builder().url("$OTAWILMA_API_URL/messages/inbox?limit=$until").header("token", token).build()
client.newCall(request).execute().use {

// If it fails
if (!it.isSuccessful) return Pair(false, emptyList())
checkCode(it.code)

// If the body is empty then you must be very new
val body = it.body?.string() ?: return Pair(true, emptyList())
val body = it.body?.string() ?: return emptyList()

Log.d("Networking", body)

return Pair(true, parseMessageList(JSONArray(body)))
return parseMessageList(JSONArray(body))

}
}
Expand All @@ -179,10 +217,9 @@ interface OtawilmaNetworking : LessonParser, MessageParser {
val request = Request.Builder().url("$OTAWILMA_API_URL/messages/${message.id}").header("token", token).build()

client.newCall(request).execute().use {
if (!it.isSuccessful) return null
checkCode(it.code)
val body = it.body?.string() ?: return null

return makeMessageGoToGym(JSONArray(body)[0] as JSONObject, message)
return getMessageBody(JSONArray(body)[0] as JSONObject, message)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package com.otawilma.mobileclient
import android.content.Context


class PreferenceStorage(private val context: Context) {
class PreferenceStorage(context: Context) {

private val preferenceFileName = "com.otawilma.mobileclient.preferences"
private val sharedPreferences = context.getSharedPreferences(preferenceFileName, Context.MODE_PRIVATE)
Expand All @@ -13,6 +13,6 @@ class PreferenceStorage(private val context: Context) {
set(value) {sharedPreferences.edit().putBoolean("autoLogin",value).apply()}

var homePageDays
get() = sharedPreferences.getInt("homePageDays",2)
get() = sharedPreferences.getInt("homePageDays",3)
set(value) {sharedPreferences.edit().putInt("homePageDays",value).apply()}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,15 @@ import androidx.drawerlayout.widget.DrawerLayout
import androidx.navigation.NavController
import androidx.navigation.fragment.findNavController
import com.google.android.material.navigation.NavigationView
import com.otawilma.mobileclient.InvalidTokenNetworkException
import com.otawilma.mobileclient.OtawilmaNetworking
import com.otawilma.mobileclient.R
import com.otawilma.mobileclient.initAppData
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import java.net.SocketTimeoutException

class MainActivity : AppCompatActivity(), OtawilmaNetworking, NavigationView.OnNavigationItemSelectedListener {

Expand Down Expand Up @@ -69,7 +72,17 @@ class MainActivity : AppCompatActivity(), OtawilmaNetworking, NavigationView.OnN
when(item.itemId){
R.id.menuMainLogout ->{
CoroutineScope(Dispatchers.IO).launch {
logout(getToken()!!)
var token = waitUntilToken(applicationContext)
while (true) {
try {
logout(token)
break
} catch (e: InvalidTokenNetworkException) {
token = invalidateTokenAndGetNew(applicationContext)
} catch (e: SocketTimeoutException){
delay(100)
}
}
}
startActivity(Intent(this@MainActivity, LoginActivity::class.java).putExtra("loggedOut", true))
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,21 +8,19 @@ import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.otawilma.mobileclient.*
import com.otawilma.mobileclient.dataClasses.SchoolDay
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.cancel
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.launch
import java.net.SocketTimeoutException
import java.time.LocalDate

class FragmentHomePage:Fragment(R.layout.fragment_home_page), OtawilmaNetworking {

private lateinit var timeTableDayAdapter: TimeTableDayAdapter

private val coroutineScope = CoroutineScope(Dispatchers.IO)
private val coroutineScopeMain = CoroutineScope(Dispatchers.Main)
private val coroutineScopeMain = CoroutineScope(Dispatchers.Main )

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
Expand Down Expand Up @@ -52,15 +50,22 @@ class FragmentHomePage:Fragment(R.layout.fragment_home_page), OtawilmaNetworking

val listActual : MutableList<SchoolDay> = mutableListOf()
while (listActual.size < sharedPreferences.homePageDays && day <= LocalDate.now().plusDays(20)) {
val token = getToken() ?: handleInvalidToken(context!!)

val element = dayRepository.getFromServer(token, day)

if (element != null && element.items.isNotEmpty()){
listActual.add(element)
var token = waitUntilToken(context!!)

while (true) {
try {
val element = dayRepository.getFromServer(token, day)
if (element != null && element.items.isNotEmpty()) {
listActual.add(element)
}
day = day.plusDays(1)
break
} catch (e: InvalidTokenNetworkException) {
token = invalidateTokenAndGetNew(context!!)
} catch (e: SocketTimeoutException){
delay(100)
}
}

day = day.plusDays(1)
}
emit(listActual)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import androidx.fragment.app.Fragment
import androidx.recyclerview.widget.DividerItemDecoration
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.otawilma.mobileclient.InvalidTokenNetworkException
import com.otawilma.mobileclient.OtawilmaNetworking
import com.otawilma.mobileclient.R
import com.otawilma.mobileclient.dataClasses.Message
Expand All @@ -20,7 +21,9 @@ import com.otawilma.mobileclient.messaging.MessageAdapter
import com.otawilma.mobileclient.messaging.MessageClickListener
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import java.net.SocketTimeoutException


class FragmentMessages : Fragment(R.layout.fragment_messages), OtawilmaNetworking, MessageClickListener {
Expand All @@ -35,18 +38,21 @@ class FragmentMessages : Fragment(R.layout.fragment_messages), OtawilmaNetworkin

CoroutineScope(Dispatchers.IO).launch {

val token = getToken()
if (token == null) {
handleInvalidToken(context!!.applicationContext)
}

val messages = getMessages(token!!,100).second

CoroutineScope(Dispatchers.Main).launch {
messageAdapter.submitItems(messages)
var token = waitUntilToken(context!!)
while (true) {
try {
val messages = getMessages(token,500)
CoroutineScope(Dispatchers.Main).launch {
messageAdapter.submitItems(messages)
}
break
} catch (e: InvalidTokenNetworkException) {
token = invalidateTokenAndGetNew(context!!)
}catch (e: SocketTimeoutException){
delay(100)
}
}
}

}

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
Expand All @@ -63,7 +69,7 @@ class FragmentMessages : Fragment(R.layout.fragment_messages), OtawilmaNetworkin
Log.d("Messaging", "Clicked $messageItem")
CoroutineScope(Dispatchers.IO).launch {

val token = getToken() ?: handleInvalidToken(context!!)
val token = waitUntilToken(context!!)

val messageToDisplay = getMessageBody(token, messageItem as Message)

Expand All @@ -75,7 +81,7 @@ class FragmentMessages : Fragment(R.layout.fragment_messages), OtawilmaNetworkin
val popupWindow = PopupWindow(
popUpView,
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT
ViewGroup.LayoutParams.WRAP_CONTENT
)

val textTitle = popUpView.findViewById<TextView>(R.id.textViewPopupMessageTitle)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ interface MessageParser : PersonParser {
}

// Fetch the body for the message
fun makeMessageGoToGym(messageJson : JSONObject, message: Message) : Message{
fun getMessageBody(messageJson : JSONObject, message: Message) : Message{

val body: Spanned? = Html.fromHtml(getOrNull(messageJson, "content") as String,)

Expand Down
6 changes: 4 additions & 2 deletions app/src/main/res/layout/fragment_messages.xml
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,12 @@
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerViewMessagesMessages"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_height="0dp"
android:layout_marginTop="16dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textView" />
app:layout_constraintTop_toBottomOf="@+id/textView"
app:layout_constraintVertical_bias="0.0" />
</androidx.constraintlayout.widget.ConstraintLayout>

0 comments on commit 0d32966

Please sign in to comment.