Skip to content

Commit

Permalink
Update code
Browse files Browse the repository at this point in the history
- Fetch clientVersion from X-Client-Version response header
- UX improvements
  • Loading branch information
lhwdev committed Mar 9, 2022
1 parent 3f85daf commit 964770f
Show file tree
Hide file tree
Showing 6 changed files with 87 additions and 89 deletions.
2 changes: 2 additions & 0 deletions api-base/src/jvmMain/kotlin/com/lhwdev/fetch/fetch.kt
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ interface FetchResult {
val responseCodeMessage: String
val rawResponse: InputStream

fun getHeader(key: String): String

fun close()
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package com.lhwdev.fetch.http

import com.lhwdev.fetch.*
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.runInterruptible
import kotlinx.coroutines.withContext
import java.io.*
import java.net.HttpURLConnection
Expand Down Expand Up @@ -34,7 +35,7 @@ fun interface HttpInterceptor : FetchInterceptor {
}

val HttpInterceptorImpl: HttpInterceptor = HttpInterceptor { url, method, headers, session, body ->
if(sDebugFetch) {
if(sDebugFetch) runInterruptible {
println("")

val lastCookieManager = threadLocalCookieHandler
Expand Down Expand Up @@ -141,7 +142,7 @@ val HttpInterceptorImpl: HttpInterceptor = HttpInterceptor { url, method, header
} finally {
if(session != null) setThreadLocalCookieHandler(lastCookieManager)
}
} else { // without debug logging
} else runInterruptible { // without debug logging
val lastCookieManager = threadLocalCookieHandler
if(session != null) setThreadLocalCookieHandler(session.cookieManager)

Expand Down Expand Up @@ -201,6 +202,8 @@ private class HttpResultImpl(val connection: HttpURLConnection) :
return connection.inputStream
}

override fun getHeader(key: String): String = connection.getHeaderField(key)

override fun close() {
connection.disconnect()
}
Expand Down
12 changes: 10 additions & 2 deletions api/src/main/kotlin/com/lhwdev/selfTestMacro/api/getUserGroup.kt
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,18 @@ data class User(
@SerialName("token") val token: UserToken
)

// a temporary hack to pass clientVersion where proper api design is not done
class UserGroup(val users: List<User>, val clientVersion: String) : List<User> by users

suspend fun Session.getUserGroup(institute: InstituteInfo, token: UsersToken): List<User> = fetch(

suspend fun Session.getUserGroup(institute: InstituteInfo, token: UsersToken): UserGroup = fetch(
institute.requestUrl["selectUserGroup"],
method = HttpMethod.post,
headers = sDefaultFakeHeader + mapOf("Content-Type" to ContentTypes.json, "Authorization" to token.token),
body = "{}"
).toJsonLoose(ListSerializer(User.serializer()))
).let {
UserGroup(
users = it.toJsonLoose(ListSerializer(User.serializer())),
clientVersion = it.getHeader("X-Client-Version")
)
}
2 changes: 1 addition & 1 deletion app/src/main/java/com/lhwdev/selfTestMacro/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ class MainActivity : AppCompatActivity() {
} else {
time.text = "시간 예약 안 됨"
}
updateTime(intent, reset = true)
updateTime(intent)
}

fun pickTime() {
Expand Down
113 changes: 50 additions & 63 deletions app/src/main/java/com/lhwdev/selfTestMacro/selfTestUtils.kt
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ import net.gotev.cookiestore.InMemoryCookieStore
import java.net.CookieManager
import java.net.CookiePolicy
import java.util.Calendar
import java.util.Date
import kotlin.random.Random


Expand All @@ -40,7 +39,7 @@ suspend fun Context.singleOfUserGroup(list: List<User>) = if(list.size == 1) lis
null
}

suspend fun Context.surveyData(user: User, usersIdentifier: UserIdentifier): SurveyData {
suspend fun Context.surveyData(user: User, usersIdentifier: UserIdentifier, clientVersion: String): SurveyData {
val pref = preferenceState

val quickTestNegative = pref.quickTest?.let {
Expand All @@ -53,8 +52,6 @@ suspend fun Context.surveyData(user: User, usersIdentifier: UserIdentifier): Sur
} ?: false
val isIsolated = pref.isIsolated

val clientVersion = pref.appMeta().hcsVersion

return SurveyData(
userToken = user.token,
upperUserName = usersIdentifier.mainUserName,
Expand Down Expand Up @@ -93,7 +90,7 @@ suspend fun Context.submitSuspend(session: Session, notification: Boolean = true

val users = session.getUserGroup(institute, usersToken)
val user = singleOfUserGroup(users) ?: return@trial
val surveyData = surveyData(user, usersIdentifier)
val surveyData = surveyData(user, usersIdentifier, users.clientVersion)

val result = session.registerSurvey(
pref.institute!!,
Expand All @@ -118,7 +115,7 @@ suspend fun Context.submitSuspend(session: Session, notification: Boolean = true
}
}

fun Context.updateTime(intent: PendingIntent, reset: Boolean = false) {
fun Context.updateTime(intent: PendingIntent) {
val preferenceState = preferenceState
val alarmManager = getSystemService(Context.ALARM_SERVICE) as AlarmManager
if(Build.VERSION.SDK_INT >= 21)
Expand All @@ -132,13 +129,9 @@ fun Context.updateTime(intent: PendingIntent, reset: Boolean = false) {
isRandom = preferenceState.isRandomEnabled,
nextDay = false
)

if(reset) preferenceState.lastSubmit = -1
}
}

private val random = Random

fun millisToDaysCumulative(millis: Long) =
// ms sec min hour day
millis / 1000 / 60 / 60 / 24
Expand All @@ -152,67 +145,61 @@ fun Context.scheduleNextAlarm(
nextDay: Boolean
) {
val pref = preferenceState
val currentTime: Long
val now = Calendar.getInstance()

var newTime = Calendar.getInstance().run {
currentTime = timeInMillis

val new = clone() as Calendar

// Submitted today
val last = pref.lastSubmit
val lastDay = millisToDaysCumulative(last)

val targetMin = hour * 60 + min
val currentMin = this[Calendar.HOUR_OF_DAY] * 60 + this[Calendar.MINUTE]

// update date
val quick = pref.quickTest

if(quick?.behavior == QuickTestInfo.Behavior.doNotSubmit && quick.days.size >= 7) {
// refuse to schedule
return
}

val newDay = millisToDaysCumulative(new.timeInMillis)
if(nextDay || lastDay == newDay) {
new.add(Calendar.DAY_OF_YEAR, 1)
}
val new = now.clone() as Calendar

// Submitted today
val last = pref.lastSubmit
val lastDay = millisToDaysCumulative(last)

// update date
val quick = pref.quickTest

if(quick?.behavior == QuickTestInfo.Behavior.doNotSubmit && quick.days.size >= 7) {
// refuse to schedule
return
}

if(nextDay || lastDay == millisToDaysCumulative(new.timeInMillis)) {
new.add(Calendar.DATE, 1)
}

var iteration = 0
while(iteration < 10) {
val days = millisToDaysCumulative(new.timeInMillis)
val day = new[Calendar.DAY_OF_WEEK]

var iteration = 0
while(iteration < 10) {
val days = millisToDaysCumulative(new.timeInMillis)
val day = new[Calendar.DAY_OF_WEEK]

when {
!pref.includeWeekend && (day == Calendar.SATURDAY || day == Calendar.SUNDAY) -> Unit
quick != null && quick.behavior == QuickTestInfo.Behavior.doNotSubmit && day in quick.days -> Unit
else -> break
}
new.add(Calendar.DAY_OF_YEAR, 1)
iteration++
}
if(iteration == 10) {
return
when {
!pref.includeWeekend && (day == Calendar.SATURDAY || day == Calendar.SUNDAY) -> Unit
quick != null && quick.behavior == QuickTestInfo.Behavior.doNotSubmit && day in quick.days -> Unit
else -> break
}

new[Calendar.HOUR_OF_DAY] = hour
new[Calendar.MINUTE] = min
new[Calendar.SECOND] = 0
new[Calendar.MILLISECOND] = 0
selfLog("schedule time selection (nextDay=$nextDay lastDay=$lastDay, current=$newDay)")
new
}.timeInMillis
new.add(Calendar.DAY_OF_WEEK, 1)
iteration++
}
if(iteration == 10) { // guard against looping forever
return
}

new[Calendar.HOUR_OF_DAY] = hour
new[Calendar.MINUTE] = min
new[Calendar.SECOND] = 0
new[Calendar.MILLISECOND] = 0
var newTime = new.timeInMillis

selfLog("schedule time selection (nextDay=$nextDay lastDay=$lastDay, newDay=${millisToDaysCumulative(newTime)})")

if(isRandom) {
newTime += 1000 * 60 * (Random.nextFloat() * 10 - 5).toInt()
if(newTime - currentTime < 10000) {
selfLog("scheduling: coerced time from $newTime")
newTime = currentTime + 10000
}
}

selfLog("scheduling next alarm at ${Date(newTime)}", force = true)
if(newTime - now.timeInMillis < 10000) {
selfLog("scheduling: coerced time from $newTime (diff = ${newTime - now.timeInMillis})")
newTime = now.timeInMillis + 10000
}

selfLog("scheduling next alarm at ${new.time}", force = true)

val alarmManager = getSystemService(Context.ALARM_SERVICE) as AlarmManager
if(Build.VERSION.SDK_INT < 21) {
Expand Down
40 changes: 19 additions & 21 deletions app/src/main/java/com/lhwdev/selfTestMacro/utils.kt
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ import androidx.core.view.doOnPreDraw
import androidx.core.view.setPadding
import com.google.android.material.snackbar.Snackbar
import com.lhwdev.fetch.http.Session
import com.lhwdev.fetch.http.fetch
import com.lhwdev.selfTestMacro.api.*
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.suspendCancellableCoroutine
Expand All @@ -29,7 +28,6 @@ import kotlinx.serialization.ExperimentalSerializationApi
import kotlinx.serialization.KSerializer
import kotlinx.serialization.Serializable
import kotlinx.serialization.json.Json
import java.net.URL
import java.util.WeakHashMap
import kotlin.coroutines.resume
import kotlin.properties.ReadWriteProperty
Expand Down Expand Up @@ -155,7 +153,7 @@ class PreferenceState(val pref: SharedPreferences) {
putLong("lastSubmit", value)
}

var appMeta: AppMeta? by pref.preferenceSerialized("appMeta", AppMeta.serializer())
// var appMeta: AppMeta? by pref.preferenceSerialized("appMeta", AppMeta.serializer())

var lastQuestion: String? by pref.preferenceString("lastQuestion")

Expand All @@ -171,24 +169,24 @@ class PreferenceState(val pref: SharedPreferences) {
}
}

suspend fun PreferenceState.appMeta(): AppMeta.Data {
val day = millisToDaysCumulative(System.currentTimeMillis())
val last = appMeta
if(last != null && last.at == day) return last.data

val data = fetch(URL("https://raw.githubusercontent.com/wiki/lhwdev/covid-selftest-macro/app_meta.json"))
.toJsonLoose(AppMeta.Data.serializer())
appMeta = AppMeta(data, at = day)
return data
}

@Serializable
class AppMeta(val data: Data, val at: Long) {
@Serializable
class Data(
val hcsVersion: String
)
}
// suspend fun PreferenceState.appMeta(): AppMeta.Data {
// val day = millisToDaysCumulative(System.currentTimeMillis())
// val last = appMeta
// if(last != null && last.at == day) return last.data
//
// val data = fetch(URL("https://raw.githubusercontent.com/wiki/lhwdev/covid-selftest-macro/app_meta.json"))
// .toJsonLoose(AppMeta.Data.serializer())
// appMeta = AppMeta(data, at = day)
// return data
// }

// @Serializable
// class AppMeta(val data: Data, val at: Long) {
// @Serializable
// class Data(
// val hcsVersion: String
// )
// }

@Serializable
data class QuickTestInfo(
Expand Down

0 comments on commit 964770f

Please sign in to comment.