Skip to content

Commit

Permalink
fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
Tiebe committed Feb 10, 2024
1 parent cb49dac commit 59d661d
Show file tree
Hide file tree
Showing 14 changed files with 129 additions and 35 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,13 @@ import android.content.Intent
import com.google.android.gms.wearable.MessageEvent
import com.google.android.gms.wearable.WearableListenerService


class WearListener : WearableListenerService() {
override fun onMessageReceived(messageEvent: MessageEvent) {
val intent = Intent(applicationContext, WearLoginActivity::class.java)
intent.putExtra("uri", messageEvent.data)
intent.putExtra("node", messageEvent.sourceNodeId)
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK)

startActivity(intent)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,9 @@ class WearLoginActivity : AppCompatActivity() {
val checkUrl = webResourceRequest.url.toString()

if (checkUrl.startsWith("m6loapp://oauth2redirect")) {
println("sending....")
Wearable.getMessageClient(applicationContext).sendMessage(node, "/login_completed", checkUrl.toByteArray())
Wearable.getMessageClient(applicationContext).sendMessage(node, "/login_completed", checkUrl.toByteArray()).addOnCompleteListener { task ->
getActivity(it)?.finishAfterTransition()
}
return true
}

Expand All @@ -53,7 +54,9 @@ class WearLoginActivity : AppCompatActivity() {
request: WebResourceRequest?
): WebResourceResponse? {
if (request?.url.toString().contains("playconsolelogin")) {
Wearable.getMessageClient(applicationContext).sendMessage(node, "/login_bypass", null)
Wearable.getMessageClient(applicationContext).sendMessage(node, "/login_bypass", null).addOnCompleteListener { task ->
getActivity(it)?.finishAfterTransition()
}
}
return super.shouldInterceptRequest(view, request)
}
Expand Down
4 changes: 2 additions & 2 deletions iosApp/iosApp/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@
<key>ITSAppUsesNonExemptEncryption</key>
<false/>
<key>CFBundleShortVersionString</key>
<string>4.0.0</string>
<string>4.1.0</string>
<key>CFBundleVersion</key>
<string>4.0.0</string>
<string>4.1.0</string>
<key>BGTaskSchedulerPermittedIdentifiers</key>
<array>
<string>nl.tiebe.otarium.graderefresh</string>
Expand Down
14 changes: 8 additions & 6 deletions libs.versions.toml
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
[versions]
app-version-string = "4.0.0"
app-version-code = "40"
app-version-string = "4.1.0"
app-version-code = "43"

android_sdk-min = "21"
android_sdk-compile = "34"
wear_sdk-min = "30"
wear_sdk-compile = "33"

ios_target = "11.0"

Expand Down Expand Up @@ -33,10 +35,7 @@ complete-kotlin = "1.1.0"
colormath = "3.4.0"

kotlin-datetime = "0.5.0"

# --- IDEA ---
# Make navigation between agenda and grades screen like spotify. That means first page is agenda, second page is grades. You can only swipe to exit on the agenda page.

horologist = "0.5.21"
skiko = "0.7.85.4"
agp = "8.2.2"
kotlin190 = "1.9.0"
Expand Down Expand Up @@ -105,6 +104,9 @@ compose-foundation = { group = "androidx.wear.compose", name = "compose-foundati
core-splashscreen = { group = "androidx.core", name = "core-splashscreen", version.ref = "core-splashscreen" }
androidx-wear-phone-interactions = { group = "androidx.wear", name = "wear-phone-interactions", version.ref = "wear-phone-interactions" }

horologist-compose-layout = { group = "com.google.android.horologist", name = "horologist-compose-layout", version.ref = "horologist" }
horologist-compose-material = { group = "com.google.android.horologist", name = "horologist-compose-material", version.ref = "horologist" }

[plugins]
mokoresources = { id = "dev.icerock.mobile.multiplatform-resources", version.ref = "moko" }
complete_kotlin = { id = "com.louiscad.complete-kotlin", version.ref = "complete-kotlin" }
Expand Down
2 changes: 1 addition & 1 deletion shared/shared.podspec
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Pod::Spec.new do |spec|
spec.name = 'shared'
spec.version = '4.0.0'
spec.version = '4.1.0'
spec.homepage = 'https://otarium.groosman.nl'
spec.source = { :http=> ''}
spec.authors = ''
Expand Down
22 changes: 13 additions & 9 deletions wearApp/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@ android {

defaultConfig {
applicationId = "nl.tiebe.otarium"
minSdk = 30
targetSdk = libs.versions.android.sdk.compile.get().toInt()
versionCode = libs.versions.app.version.code.get().toInt()
minSdk = libs.versions.wear.sdk.min.get().toInt()
targetSdk = libs.versions.wear.sdk.compile.get().toInt()
versionCode = libs.versions.app.version.code.get().toInt() + 100
versionName = libs.versions.app.version.string.get()
vectorDrawables {
useSupportLibrary = true
Expand All @@ -22,14 +22,14 @@ android {
}

buildTypes {
release {
isMinifyEnabled = false
proguardFiles(
getDefaultProguardFile("proguard-android-optimize.txt"),
"proguard-rules.pro"
)
getByName("release") {
isMinifyEnabled = true
isShrinkResources = true
proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro")
signingConfig = signingConfigs.getByName("debug")
}
}

compileOptions {
sourceCompatibility = JavaVersion.VERSION_11
targetCompatibility = JavaVersion.VERSION_11
Expand Down Expand Up @@ -58,6 +58,10 @@ dependencies {
implementation(libs.compose.activity)
implementation(libs.core.splashscreen)
implementation(libs.androidx.wear.phone.interactions)

implementation(libs.horologist.compose.material)
implementation(libs.horologist.compose.layout)

debugImplementation(libs.ui.tooling)
debugImplementation(libs.ui.test.manifest)

Expand Down
6 changes: 5 additions & 1 deletion wearApp/proguard-rules.pro
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,8 @@

# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile
#-renamesourcefileattribute SourceFile

-printmapping build/outputs/mapping/release/mapping.txt

-dontwarn org.slf4j.impl.StaticLoggerBinder
5 changes: 5 additions & 0 deletions wearApp/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,11 @@
android:name="com.google.android.wearable"
android:required="true" />

<activity
android:name="androidx.wear.activity.ConfirmationActivity"
android:excludeFromRecents="true"
android:noHistory="true" />

<meta-data
android:name="com.google.android.wearable.standalone"
android:value="true" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,11 @@ import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.pager.HorizontalPager
import androidx.compose.foundation.pager.rememberPagerState
import androidx.compose.runtime.Composable
import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.wear.compose.material.Scaffold
import androidx.wear.compose.material.TimeText
import androidx.wear.compose.material3.ExperimentalWearMaterial3Api
import androidx.wear.compose.material3.HorizontalPageIndicator
import androidx.wear.compose.material3.rememberPageIndicatorState
Expand All @@ -26,12 +29,14 @@ internal fun HomeScreen(componentContext: ComponentContext) {
Scaffold(
pageIndicator = {
HorizontalPageIndicator(pageIndicatorState = pageIndicatorState)
}, timeText = {
TimeText()
}
) {
HorizontalPager(state = pagerState, modifier = Modifier.fillMaxSize(), outOfBoundsPageCount = pagerState.pageCount - 1) {
when (it) {
0 -> TimetableRootScreen(DefaultTimetableRootComponent(componentContext))
1 -> GradeScreen(DefaultRecentGradesComponent(componentContext))
0 -> TimetableRootScreen(DefaultTimetableRootComponent(componentContext), remember { derivedStateOf { pagerState.currentPage == 0 } })
1 -> GradeScreen(DefaultRecentGradesComponent(componentContext), remember { derivedStateOf { pagerState.currentPage == 1 } })
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package nl.tiebe.otarium.wear.ui.home.grades
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.State
import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember
Expand All @@ -13,25 +14,35 @@ import androidx.wear.compose.material3.ListHeader
import androidx.wear.compose.material3.Text
import androidx.wear.compose.material3.TitleCard
import com.arkivanov.decompose.extensions.compose.jetbrains.subscribeAsState
import com.google.android.horologist.annotations.ExperimentalHorologistApi
import com.google.android.horologist.compose.rotaryinput.rotaryWithScroll
import dev.tiebe.magisterapi.response.general.year.grades.RecentGrade
import nl.tiebe.otarium.MR
import nl.tiebe.otarium.logic.root.home.children.grades.RecentGradesComponent
import nl.tiebe.otarium.utils.ui.getLocalizedString
import nl.tiebe.otarium.wear.ui.utils.conditional

@OptIn(ExperimentalHorologistApi::class)
@Composable
fun GradeScreen(component: RecentGradesComponent) {
fun GradeScreen(component: RecentGradesComponent, scrollEnabled: State<Boolean>) {
component.refreshGrades()
val grades = component.grades.subscribeAsState().value

val listState = rememberScalingLazyListState()

val reachedEnd by remember { derivedStateOf { listState.centerItemIndex >= (grades.size * 0.5).toInt() } }

LaunchedEffect(reachedEnd) {
if (!component.refreshState.value)
component.loadNextGrades()
}

ScalingLazyColumn(modifier = Modifier.fillMaxSize(), state = listState) {
ScalingLazyColumn(
modifier = Modifier
.fillMaxSize()
.conditional(scrollEnabled.value) { rotaryWithScroll(scrollableState = listState) },
state = listState
) {
item { ListHeader {
Text(text = getLocalizedString(MR.strings.gradesItem))
} }
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
package nl.tiebe.otarium.wear.ui.home.timetable

import androidx.compose.runtime.Composable
import androidx.compose.runtime.State
import nl.tiebe.otarium.logic.root.home.children.timetable.TimetableRootComponent
import nl.tiebe.otarium.wear.ui.utils.SwipeToDismissBox

@Composable
fun TimetableRootScreen(component: TimetableRootComponent) {
fun TimetableRootScreen(component: TimetableRootComponent, scrollEnabled: State<Boolean>) {
SwipeToDismissBox(stack = component.childStack, onDismissed = { component.back() }) {
when (val instance = it.instance) {
is TimetableRootComponent.Child.TimetableChild -> TimetableScreen(component.timetableComponent)
is TimetableRootComponent.Child.TimetableChild -> TimetableScreen(component.timetableComponent, scrollEnabled)
is TimetableRootComponent.Child.TimetablePopupChild -> TimetableItemPopup(instance.agendaItem)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package nl.tiebe.otarium.wear.ui.home.timetable

import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.runtime.Composable
import androidx.compose.runtime.State
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.toArgb
import androidx.wear.compose.foundation.lazy.ScalingLazyColumn
Expand All @@ -11,6 +12,8 @@ import androidx.wear.compose.material3.MaterialTheme
import androidx.wear.compose.material3.Text
import androidx.wear.compose.material3.TitleCard
import com.arkivanov.decompose.extensions.compose.jetbrains.subscribeAsState
import com.google.android.horologist.annotations.ExperimentalHorologistApi
import com.google.android.horologist.compose.rotaryinput.rotaryWithScroll
import kotlinx.datetime.Clock
import kotlinx.datetime.DatePeriod
import kotlinx.datetime.TimeZone
Expand All @@ -20,19 +23,27 @@ import nl.tiebe.otarium.logic.root.home.children.timetable.children.timetable.Ti
import nl.tiebe.otarium.magister.AgendaItemWithAbsence
import nl.tiebe.otarium.ui.utils.HtmlView
import nl.tiebe.otarium.utils.toFormattedStringTime
import nl.tiebe.otarium.wear.ui.utils.conditional
import java.time.format.TextStyle
import java.util.Locale

@OptIn(ExperimentalHorologistApi::class)
@Composable
fun TimetableScreen(component: TimetableComponent) {
fun TimetableScreen(component: TimetableComponent, scrollEnabled: State<Boolean>) {
val today = Clock.System.now().toLocalDateTime(TimeZone.currentSystemDefault()).date

component.refreshTimetable(today, today + DatePeriod(days = 31))

val listState = rememberScalingLazyListState()

val items = component.timetable.subscribeAsState().value.groupBy { it.start.toLocalDateTime(TimeZone.currentSystemDefault()).date }

ScalingLazyColumn(modifier = Modifier.fillMaxSize(), state = listState) {
ScalingLazyColumn(
modifier = Modifier
.fillMaxSize()
.conditional(scrollEnabled.value) { rotaryWithScroll(scrollableState = listState) },
state = listState
) {
for ((day, timetableItems) in items) {
item { ListHeader {
Text(day.dayOfWeek.getDisplayName(TextStyle.FULL, Locale.getDefault()) + " ${day.dayOfMonth}-${day.monthNumber}")
Expand All @@ -48,5 +59,5 @@ fun TimetableItem(item: AgendaItemWithAbsence, onClick: () -> Unit) {
Text(text = item.agendaItem.subjects.firstOrNull()?.name?.replaceFirstChar { if (it.isLowerCase()) it.titlecase() else it.toString() } ?: item.agendaItem.description ?: "No description")
}, subtitle = {
if (item.agendaItem.content != null) HtmlView(html = item.agendaItem.content!!, maxLines = 1, backgroundColor = -1, textColor = MaterialTheme.colorScheme.onSurface.toArgb())
}, time = { Text("${item.start.toFormattedStringTime(false)} - ${item.end.toFormattedStringTime(false)}") })
}, time = { Text("${item.start.toFormattedStringTime(false)} - ${item.end.toFormattedStringTime(false)} in ${item.agendaItem.classrooms.joinToString(", ")}") })
}
Original file line number Diff line number Diff line change
@@ -1,15 +1,31 @@
package nl.tiebe.otarium.wear.ui.login

import android.content.Intent
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.text.style.TextAlign
import androidx.core.content.ContextCompat.startActivity
import androidx.wear.activity.ConfirmationActivity
import androidx.wear.compose.material3.Text
import com.google.android.gms.tasks.Tasks
import com.google.android.gms.wearable.Wearable
import nl.tiebe.otarium.logic.root.login.LoginComponent


@Composable
internal fun LoginScreen(component: LoginComponent) {
val context = LocalContext.current

var text by remember { mutableStateOf("Waiting for sign in on phone...") }

Thread {
Wearable.getMessageClient(context).addListener {
println("Got message! ")
Expand All @@ -20,14 +36,35 @@ internal fun LoginScreen(component: LoginComponent) {
}
}

val node = Tasks.await(
var node = Tasks.await(
Wearable.getNodeClient(context).connectedNodes
).first()
).firstOrNull()

while (node == null) {
text = "No connected phones..."

node = Tasks.await(
Wearable.getNodeClient(context).connectedNodes
).firstOrNull()
}

text = "Waiting for sign in on phone..."

Wearable.getMessageClient(context).sendMessage(node.id, "/wear_login", component.loginUrl.url.toByteArray())

}.start()

val intent = Intent(context, ConfirmationActivity::class.java)

intent.putExtra(
ConfirmationActivity.EXTRA_ANIMATION_TYPE,
ConfirmationActivity.OPEN_ON_PHONE_ANIMATION
)

startActivity(context, intent, null)

Box(modifier = Modifier.fillMaxSize()) {
Text(text, modifier = Modifier.align(Alignment.Center), textAlign = TextAlign.Center)
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -109,4 +109,14 @@ private fun RetainStates(holder: SaveableStateHolder, currentKeys: Set<String>)
}
}

private class Keys(var set: Set<String>)
private class Keys(var set: Set<String>)


@Composable
fun Modifier.conditional(condition : Boolean, modifier : @Composable Modifier.() -> Modifier) : Modifier {
return if (condition) {
then(modifier(Modifier))
} else {
this
}
}

0 comments on commit 59d661d

Please sign in to comment.