mobile base
This commit is contained in:
10
AndroidApp/.idea/deploymentTargetSelector.xml
generated
Normal file
10
AndroidApp/.idea/deploymentTargetSelector.xml
generated
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="deploymentTargetSelector">
|
||||||
|
<selectionStates>
|
||||||
|
<SelectionState runConfigName="app">
|
||||||
|
<option name="selectionMode" value="DROPDOWN" />
|
||||||
|
</SelectionState>
|
||||||
|
</selectionStates>
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
193
AndroidApp/.kotlin/errors/errors-1770819867596.log
Normal file
193
AndroidApp/.kotlin/errors/errors-1770819867596.log
Normal file
@@ -0,0 +1,193 @@
|
|||||||
|
kotlin version: 2.0.21
|
||||||
|
error message: org.jetbrains.kotlin.backend.common.BackendException: Backend Internal error: Exception during IR lowering
|
||||||
|
File being compiled: /Volumes/SED/Code/OpenTimeTracker/AndroidApp/app/src/main/java/com/opentimetracker/MainActivity.kt
|
||||||
|
The root cause java.lang.RuntimeException was thrown at: org.jetbrains.kotlin.backend.jvm.codegen.FunctionCodegen.generate(FunctionCodegen.kt:47)
|
||||||
|
at org.jetbrains.kotlin.backend.common.CodegenUtil.reportBackendException(CodegenUtil.kt:253)
|
||||||
|
at org.jetbrains.kotlin.backend.common.CodegenUtil.reportBackendException$default(CodegenUtil.kt:236)
|
||||||
|
at org.jetbrains.kotlin.backend.common.phaser.PerformByIrFilePhase.invokeSequential(performByIrFile.kt:65)
|
||||||
|
at org.jetbrains.kotlin.backend.common.phaser.PerformByIrFilePhase.invoke(performByIrFile.kt:52)
|
||||||
|
at org.jetbrains.kotlin.backend.common.phaser.PerformByIrFilePhase.invoke(performByIrFile.kt:38)
|
||||||
|
at org.jetbrains.kotlin.backend.common.phaser.NamedCompilerPhase.phaseBody(CompilerPhase.kt:166)
|
||||||
|
at org.jetbrains.kotlin.backend.common.phaser.AbstractNamedCompilerPhase.invoke(CompilerPhase.kt:113)
|
||||||
|
at org.jetbrains.kotlin.backend.common.phaser.CompositePhase.invoke(PhaseBuilders.kt:27)
|
||||||
|
at org.jetbrains.kotlin.backend.common.phaser.CompositePhase.invoke(PhaseBuilders.kt:14)
|
||||||
|
at org.jetbrains.kotlin.backend.common.phaser.NamedCompilerPhase.phaseBody(CompilerPhase.kt:166)
|
||||||
|
at org.jetbrains.kotlin.backend.common.phaser.AbstractNamedCompilerPhase.invoke(CompilerPhase.kt:113)
|
||||||
|
at org.jetbrains.kotlin.backend.common.phaser.CompilerPhaseKt.invokeToplevel(CompilerPhase.kt:62)
|
||||||
|
at org.jetbrains.kotlin.backend.jvm.JvmIrCodegenFactory.invokeCodegen(JvmIrCodegenFactory.kt:371)
|
||||||
|
at org.jetbrains.kotlin.codegen.CodegenFactory.generateModule(CodegenFactory.kt:47)
|
||||||
|
at org.jetbrains.kotlin.backend.jvm.JvmIrCodegenFactory.generateModuleInFrontendIRMode(JvmIrCodegenFactory.kt:433)
|
||||||
|
at org.jetbrains.kotlin.cli.jvm.compiler.pipeline.JvmCompilerPipelineKt.generateCodeFromIr(jvmCompilerPipeline.kt:246)
|
||||||
|
at org.jetbrains.kotlin.cli.jvm.compiler.pipeline.JvmCompilerPipelineKt.compileModulesUsingFrontendIrAndLightTree(jvmCompilerPipeline.kt:142)
|
||||||
|
at org.jetbrains.kotlin.cli.jvm.K2JVMCompiler.doExecute(K2JVMCompiler.kt:148)
|
||||||
|
at org.jetbrains.kotlin.cli.jvm.K2JVMCompiler.doExecute(K2JVMCompiler.kt:43)
|
||||||
|
at org.jetbrains.kotlin.cli.common.CLICompiler.execImpl(CLICompiler.kt:103)
|
||||||
|
at org.jetbrains.kotlin.cli.common.CLICompiler.execImpl(CLICompiler.kt:49)
|
||||||
|
at org.jetbrains.kotlin.cli.common.CLITool.exec(CLITool.kt:101)
|
||||||
|
at org.jetbrains.kotlin.incremental.IncrementalJvmCompilerRunner.runCompiler(IncrementalJvmCompilerRunner.kt:464)
|
||||||
|
at org.jetbrains.kotlin.incremental.IncrementalJvmCompilerRunner.runCompiler(IncrementalJvmCompilerRunner.kt:73)
|
||||||
|
at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.doCompile(IncrementalCompilerRunner.kt:506)
|
||||||
|
at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.compileImpl(IncrementalCompilerRunner.kt:423)
|
||||||
|
at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.compileNonIncrementally(IncrementalCompilerRunner.kt:301)
|
||||||
|
at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.compile(IncrementalCompilerRunner.kt:129)
|
||||||
|
at org.jetbrains.kotlin.daemon.CompileServiceImplBase.execIncrementalCompiler(CompileServiceImpl.kt:675)
|
||||||
|
at org.jetbrains.kotlin.daemon.CompileServiceImplBase.access$execIncrementalCompiler(CompileServiceImpl.kt:92)
|
||||||
|
at org.jetbrains.kotlin.daemon.CompileServiceImpl.compile(CompileServiceImpl.kt:1660)
|
||||||
|
at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(Unknown Source)
|
||||||
|
at java.base/java.lang.reflect.Method.invoke(Unknown Source)
|
||||||
|
at java.rmi/sun.rmi.server.UnicastServerRef.dispatch(Unknown Source)
|
||||||
|
at java.rmi/sun.rmi.transport.Transport$1.run(Unknown Source)
|
||||||
|
at java.rmi/sun.rmi.transport.Transport$1.run(Unknown Source)
|
||||||
|
at java.base/java.security.AccessController.doPrivileged(Unknown Source)
|
||||||
|
at java.rmi/sun.rmi.transport.Transport.serviceCall(Unknown Source)
|
||||||
|
at java.rmi/sun.rmi.transport.tcp.TCPTransport.handleMessages(Unknown Source)
|
||||||
|
at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(Unknown Source)
|
||||||
|
at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$0(Unknown Source)
|
||||||
|
at java.base/java.security.AccessController.doPrivileged(Unknown Source)
|
||||||
|
at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(Unknown Source)
|
||||||
|
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
|
||||||
|
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
|
||||||
|
at java.base/java.lang.Thread.run(Unknown Source)
|
||||||
|
Caused by: java.lang.RuntimeException: Exception while generating code for:
|
||||||
|
FUN name:LoginScreen visibility:public modality:FINAL <> (viewModel:com.opentimetracker.ui.AuthViewModel, onLoginSuccess:kotlin.Function0<kotlin.Unit>) returnType:kotlin.Unit
|
||||||
|
annotations:
|
||||||
|
Composable
|
||||||
|
VALUE_PARAMETER name:viewModel index:0 type:com.opentimetracker.ui.AuthViewModel
|
||||||
|
VALUE_PARAMETER name:onLoginSuccess index:1 type:kotlin.Function0<kotlin.Unit>
|
||||||
|
BLOCK_BODY
|
||||||
|
WHEN type=kotlin.Unit origin=IF
|
||||||
|
BRANCH
|
||||||
|
if: CALL 'public abstract fun <get-value> (): T of androidx.compose.runtime.MutableState declared in androidx.compose.runtime.MutableState' type=kotlin.Boolean origin=GET_PROPERTY
|
||||||
|
$this: CALL 'public final fun <get-isLoggedIn> (): androidx.compose.runtime.MutableState<kotlin.Boolean> declared in com.opentimetracker.ui.AuthViewModel' type=androidx.compose.runtime.MutableState<kotlin.Boolean> origin=GET_PROPERTY
|
||||||
|
$this: GET_VAR 'viewModel: com.opentimetracker.ui.AuthViewModel declared in com.opentimetracker.MainActivityKt.LoginScreen' type=com.opentimetracker.ui.AuthViewModel origin=null
|
||||||
|
then: BLOCK type=kotlin.Unit origin=null
|
||||||
|
CALL 'public final fun LaunchedEffect (key1: kotlin.Any?, block: @[ExtensionFunctionType] kotlin.coroutines.SuspendFunction1<kotlinx.coroutines.CoroutineScope, kotlin.Unit>): kotlin.Unit declared in androidx.compose.runtime.EffectsKt' type=kotlin.Unit origin=null
|
||||||
|
key1: GET_FIELD 'FIELD FIELD_FOR_OBJECT_INSTANCE name:INSTANCE type:kotlin.Unit visibility:public [final,static] declared in kotlin.Unit' type=kotlin.Unit origin=null
|
||||||
|
block: BLOCK type=com.opentimetracker.MainActivityKt.LoginScreen.<no name provided> origin=null
|
||||||
|
CLASS SUSPEND_LAMBDA CLASS name:<no name provided> modality:FINAL visibility:public/*package*/ superTypes:[kotlin.coroutines.jvm.internal.SuspendLambda; kotlin.jvm.functions.Function2<kotlinx.coroutines.CoroutineScope, kotlin.coroutines.Continuation<kotlin.Unit>?, kotlin.Any?>]
|
||||||
|
$this: VALUE_PARAMETER INSTANCE_RECEIVER name:<this> type:com.opentimetracker.MainActivityKt.LoginScreen.<no name provided>
|
||||||
|
FIELD name:label type:kotlin.Int visibility:public/*package*/
|
||||||
|
CONSTRUCTOR SUSPEND_LAMBDA visibility:public/*package*/ <> ($onLoginSuccess:kotlin.Function0<kotlin.Unit>, $completion:kotlin.coroutines.Continuation<com.opentimetracker.MainActivityKt.LoginScreen.<no name provided>>?) returnType:com.opentimetracker.MainActivityKt.LoginScreen.<no name provided> [primary]
|
||||||
|
VALUE_PARAMETER BOUND_VALUE_PARAMETER name:$onLoginSuccess index:0 type:kotlin.Function0<kotlin.Unit>
|
||||||
|
VALUE_PARAMETER name:$completion index:1 type:kotlin.coroutines.Continuation<com.opentimetracker.MainActivityKt.LoginScreen.<no name provided>>?
|
||||||
|
BLOCK_BODY
|
||||||
|
SET_FIELD 'FIELD FIELD_FOR_CAPTURED_VALUE name:$onLoginSuccess type:kotlin.Function0<kotlin.Unit> visibility:public/*package*/ [final] declared in com.opentimetracker.MainActivityKt.LoginScreen.<no name provided>' type=kotlin.Unit origin=INITIALIZER_OF_FIELD_FOR_CAPTURED_VALUE
|
||||||
|
receiver: GET_VAR '<this>: com.opentimetracker.MainActivityKt.LoginScreen.<no name provided> declared in com.opentimetracker.MainActivityKt.LoginScreen.<no name provided>' type=com.opentimetracker.MainActivityKt.LoginScreen.<no name provided> origin=null
|
||||||
|
value: GET_VAR '$onLoginSuccess: kotlin.Function0<kotlin.Unit> declared in com.opentimetracker.MainActivityKt.LoginScreen.<no name provided>.<init>' type=kotlin.Function0<kotlin.Unit> origin=null
|
||||||
|
DELEGATING_CONSTRUCTOR_CALL 'public constructor <init> (arity: kotlin.Int, $completion: kotlin.coroutines.Continuation<kotlin.Any?>?) declared in kotlin.coroutines.jvm.internal.SuspendLambda'
|
||||||
|
arity: CONST Int type=kotlin.Int value=2
|
||||||
|
$completion: GET_VAR '$completion: kotlin.coroutines.Continuation<com.opentimetracker.MainActivityKt.LoginScreen.<no name provided>>? declared in com.opentimetracker.MainActivityKt.LoginScreen.<no name provided>.<init>' type=kotlin.coroutines.Continuation<com.opentimetracker.MainActivityKt.LoginScreen.<no name provided>>? origin=null
|
||||||
|
BLOCK type=kotlin.Unit origin=null
|
||||||
|
FUN name:invokeSuspend visibility:public modality:FINAL <> ($this:com.opentimetracker.MainActivityKt.LoginScreen.<no name provided>, $result:kotlin.Result<kotlin.Any?>) returnType:kotlin.Any?
|
||||||
|
overridden:
|
||||||
|
protected abstract fun invokeSuspend ($result: kotlin.Result<kotlin.Any?>): kotlin.Any? declared in kotlin.coroutines.jvm.internal.SuspendLambda
|
||||||
|
$this: VALUE_PARAMETER INSTANCE_RECEIVER name:<this> type:com.opentimetracker.MainActivityKt.LoginScreen.<no name provided>
|
||||||
|
VALUE_PARAMETER name:$result index:0 type:kotlin.Result<kotlin.Any?>
|
||||||
|
BLOCK_BODY
|
||||||
|
CALL 'public abstract fun invoke (): R of kotlin.Function0 [operator] declared in kotlin.Function0' type=kotlin.Unit origin=INVOKE
|
||||||
|
$this: GET_FIELD 'FIELD FIELD_FOR_CAPTURED_VALUE name:$onLoginSuccess type:kotlin.Function0<kotlin.Unit> visibility:public/*package*/ [final] declared in com.opentimetracker.MainActivityKt.LoginScreen.<no name provided>' type=kotlin.Function0<kotlin.Unit> origin=null
|
||||||
|
receiver: GET_VAR '<this>: com.opentimetracker.MainActivityKt.LoginScreen.<no name provided> declared in com.opentimetracker.MainActivityKt.LoginScreen.<no name provided>.invokeSuspend' type=com.opentimetracker.MainActivityKt.LoginScreen.<no name provided> origin=null
|
||||||
|
FUN name:create visibility:public modality:FINAL <> ($this:com.opentimetracker.MainActivityKt.LoginScreen.<no name provided>, value:kotlin.Any?, $completion:kotlin.coroutines.Continuation<kotlin.Nothing>) returnType:kotlin.coroutines.Continuation<kotlin.Unit>
|
||||||
|
overridden:
|
||||||
|
public open fun create (value: kotlin.Any?, $completion: kotlin.coroutines.Continuation<kotlin.Nothing>): kotlin.coroutines.Continuation<kotlin.Unit> declared in kotlin.coroutines.jvm.internal.SuspendLambda
|
||||||
|
$this: VALUE_PARAMETER INSTANCE_RECEIVER name:<this> type:com.opentimetracker.MainActivityKt.LoginScreen.<no name provided>
|
||||||
|
VALUE_PARAMETER name:value index:0 type:kotlin.Any?
|
||||||
|
VALUE_PARAMETER name:$completion index:1 type:kotlin.coroutines.Continuation<kotlin.Nothing>
|
||||||
|
BLOCK_BODY
|
||||||
|
RETURN type=kotlin.Nothing from='public final fun create (value: kotlin.Any?, $completion: kotlin.coroutines.Continuation<kotlin.Nothing>): kotlin.coroutines.Continuation<kotlin.Unit> declared in com.opentimetracker.MainActivityKt.LoginScreen.<no name provided>'
|
||||||
|
CONSTRUCTOR_CALL 'public/*package*/ constructor <init> ($onLoginSuccess: kotlin.Function0<kotlin.Unit>, $completion: kotlin.coroutines.Continuation<com.opentimetracker.MainActivityKt.LoginScreen.<no name provided>>?) [primary] declared in com.opentimetracker.MainActivityKt.LoginScreen.<no name provided>' type=com.opentimetracker.MainActivityKt.LoginScreen.<no name provided> origin=null
|
||||||
|
$onLoginSuccess: GET_FIELD 'FIELD FIELD_FOR_CAPTURED_VALUE name:$onLoginSuccess type:kotlin.Function0<kotlin.Unit> visibility:public/*package*/ [final] declared in com.opentimetracker.MainActivityKt.LoginScreen.<no name provided>' type=kotlin.Function0<kotlin.Unit> origin=null
|
||||||
|
receiver: GET_VAR '<this>: com.opentimetracker.MainActivityKt.LoginScreen.<no name provided> declared in com.opentimetracker.MainActivityKt.LoginScreen.<no name provided>.create' type=com.opentimetracker.MainActivityKt.LoginScreen.<no name provided> origin=null
|
||||||
|
$completion: GET_VAR '$completion: kotlin.coroutines.Continuation<kotlin.Nothing> declared in com.opentimetracker.MainActivityKt.LoginScreen.<no name provided>.create' type=kotlin.coroutines.Continuation<kotlin.Nothing> origin=null
|
||||||
|
FUN name:invoke visibility:public modality:FINAL <> ($this:com.opentimetracker.MainActivityKt.LoginScreen.<no name provided>, p1:kotlinx.coroutines.CoroutineScope, p2:kotlin.coroutines.Continuation<kotlin.Unit>?) returnType:kotlin.Any?
|
||||||
|
overridden:
|
||||||
|
public abstract fun invoke (p1: P1 of kotlin.jvm.functions.Function2, p2: P2 of kotlin.jvm.functions.Function2): R of kotlin.jvm.functions.Function2 declared in kotlin.jvm.functions.Function2
|
||||||
|
$this: VALUE_PARAMETER INSTANCE_RECEIVER name:<this> type:com.opentimetracker.MainActivityKt.LoginScreen.<no name provided>
|
||||||
|
VALUE_PARAMETER name:p1 index:0 type:kotlinx.coroutines.CoroutineScope
|
||||||
|
VALUE_PARAMETER name:p2 index:1 type:kotlin.coroutines.Continuation<kotlin.Unit>?
|
||||||
|
BLOCK_BODY
|
||||||
|
RETURN type=kotlin.Nothing from='public final fun invoke (p1: kotlinx.coroutines.CoroutineScope, p2: kotlin.coroutines.Continuation<kotlin.Unit>?): kotlin.Any? declared in com.opentimetracker.MainActivityKt.LoginScreen.<no name provided>'
|
||||||
|
CALL 'public final fun invokeSuspend ($result: kotlin.Result<kotlin.Any?>): kotlin.Any? declared in com.opentimetracker.MainActivityKt.LoginScreen.<no name provided>' type=kotlin.Any? origin=null
|
||||||
|
$this: TYPE_OP type=com.opentimetracker.MainActivityKt.LoginScreen.<no name provided> origin=IMPLICIT_CAST typeOperand=com.opentimetracker.MainActivityKt.LoginScreen.<no name provided>
|
||||||
|
CALL 'public final fun create (value: kotlin.Any?, $completion: kotlin.coroutines.Continuation<kotlin.Nothing>): kotlin.coroutines.Continuation<kotlin.Unit> declared in com.opentimetracker.MainActivityKt.LoginScreen.<no name provided>' type=kotlin.coroutines.Continuation<kotlin.Unit> origin=null
|
||||||
|
$this: GET_VAR '<this>: com.opentimetracker.MainActivityKt.LoginScreen.<no name provided> declared in com.opentimetracker.MainActivityKt.LoginScreen.<no name provided>.invoke' type=com.opentimetracker.MainActivityKt.LoginScreen.<no name provided> origin=null
|
||||||
|
value: GET_VAR 'p1: kotlinx.coroutines.CoroutineScope declared in com.opentimetracker.MainActivityKt.LoginScreen.<no name provided>.invoke' type=kotlinx.coroutines.CoroutineScope origin=null
|
||||||
|
$completion: GET_VAR 'p2: kotlin.coroutines.Continuation<kotlin.Unit>? declared in com.opentimetracker.MainActivityKt.LoginScreen.<no name provided>.invoke' type=kotlin.coroutines.Continuation<kotlin.Unit>? origin=null
|
||||||
|
$result: CALL 'public final fun <unsafe-coerce> <T, R> (v: T of kotlin.jvm.internal.<unsafe-coerce>): R of kotlin.jvm.internal.<unsafe-coerce> declared in kotlin.jvm.internal' type=kotlin.Result<kotlin.Any?> origin=null
|
||||||
|
<T>: kotlin.Any?
|
||||||
|
<R>: kotlin.Result<kotlin.Any?>
|
||||||
|
v: GET_FIELD 'FIELD FIELD_FOR_OBJECT_INSTANCE name:INSTANCE type:kotlin.Unit visibility:public [final,static] declared in kotlin.Unit' type=kotlin.Unit origin=null
|
||||||
|
FIELD FIELD_FOR_CAPTURED_VALUE name:$onLoginSuccess type:kotlin.Function0<kotlin.Unit> visibility:public/*package*/ [final]
|
||||||
|
FUN BRIDGE name:invoke visibility:public modality:OPEN <> ($this:com.opentimetracker.MainActivityKt.LoginScreen.<no name provided>, p1:kotlin.Any?, p2:kotlin.Any?) returnType:kotlin.Any?
|
||||||
|
$this: VALUE_PARAMETER INSTANCE_RECEIVER name:<this> type:com.opentimetracker.MainActivityKt.LoginScreen.<no name provided>
|
||||||
|
VALUE_PARAMETER BRIDGE name:p1 index:0 type:kotlin.Any?
|
||||||
|
VALUE_PARAMETER BRIDGE name:p2 index:1 type:kotlin.Any?
|
||||||
|
EXPRESSION_BODY
|
||||||
|
RETURN type=kotlin.Nothing from='public open fun invoke (p1: kotlin.Any?, p2: kotlin.Any?): kotlin.Any? declared in com.opentimetracker.MainActivityKt.LoginScreen.<no name provided>'
|
||||||
|
CALL 'public final fun invoke (p1: kotlinx.coroutines.CoroutineScope, p2: kotlin.coroutines.Continuation<kotlin.Unit>?): kotlin.Any? declared in com.opentimetracker.MainActivityKt.LoginScreen.<no name provided>' type=kotlin.Any? origin=BRIDGE_DELEGATION
|
||||||
|
$this: GET_VAR '<this>: com.opentimetracker.MainActivityKt.LoginScreen.<no name provided> declared in com.opentimetracker.MainActivityKt.LoginScreen.<no name provided>.invoke' type=com.opentimetracker.MainActivityKt.LoginScreen.<no name provided> origin=null
|
||||||
|
p1: TYPE_OP type=kotlinx.coroutines.CoroutineScope origin=IMPLICIT_CAST typeOperand=kotlinx.coroutines.CoroutineScope
|
||||||
|
GET_VAR 'p1: kotlin.Any? declared in com.opentimetracker.MainActivityKt.LoginScreen.<no name provided>.invoke' type=kotlin.Any? origin=null
|
||||||
|
p2: TYPE_OP type=kotlin.coroutines.Continuation<*> origin=IMPLICIT_CAST typeOperand=kotlin.coroutines.Continuation<*>
|
||||||
|
GET_VAR 'p2: kotlin.Any? declared in com.opentimetracker.MainActivityKt.LoginScreen.<no name provided>.invoke' type=kotlin.Any? origin=null
|
||||||
|
CONSTRUCTOR_CALL 'public/*package*/ constructor <init> ($onLoginSuccess: kotlin.Function0<kotlin.Unit>, $completion: kotlin.coroutines.Continuation<com.opentimetracker.MainActivityKt.LoginScreen.<no name provided>>?) [primary] declared in com.opentimetracker.MainActivityKt.LoginScreen.<no name provided>' type=com.opentimetracker.MainActivityKt.LoginScreen.<no name provided> origin=null
|
||||||
|
$onLoginSuccess: GET_VAR 'onLoginSuccess: kotlin.Function0<kotlin.Unit> declared in com.opentimetracker.MainActivityKt.LoginScreen' type=kotlin.Function0<kotlin.Unit> origin=null
|
||||||
|
$completion: CONST Null type=kotlin.Nothing? value=null
|
||||||
|
CALL 'public final fun Column (modifier: androidx.compose.ui.Modifier, verticalArrangement: androidx.compose.foundation.layout.Arrangement.Vertical, horizontalAlignment: androidx.compose.ui.Alignment.Horizontal, content: @[Composable] @[ExtensionFunctionType] kotlin.Function1<androidx.compose.foundation.layout.ColumnScope, kotlin.Unit>): kotlin.Unit [inline] declared in androidx.compose.foundation.layout.ColumnKt' type=kotlin.Unit origin=null
|
||||||
|
modifier: CALL 'public final fun padding-3ABfNKs (all: androidx.compose.ui.unit.Dp): androidx.compose.ui.Modifier declared in androidx.compose.foundation.layout.PaddingKt' type=androidx.compose.ui.Modifier origin=null
|
||||||
|
$receiver: CALL 'public final fun fillMaxSize$default (fraction: kotlin.Float, $mask0: kotlin.Int, $handler: kotlin.Any?): androidx.compose.ui.Modifier declared in androidx.compose.foundation.layout.SizeKt' type=androidx.compose.ui.Modifier origin=DEFAULT_DISPATCH_CALL
|
||||||
|
$receiver: GET_FIELD 'FIELD FIELD_FOR_OBJECT_INSTANCE name:Companion type:androidx.compose.ui.Modifier.Companion visibility:public [final,static] declared in androidx.compose.ui.Modifier' type=androidx.compose.ui.Modifier.Companion origin=null
|
||||||
|
fraction: COMPOSITE type=kotlin.Float origin=DEFAULT_VALUE
|
||||||
|
CONST Float type=kotlin.Float value=0.0
|
||||||
|
$mask0: CONST Int type=kotlin.Int value=1
|
||||||
|
$handler: CONST Null type=kotlin.Any? value=null
|
||||||
|
all: CALL 'public final fun <get-dp> (): androidx.compose.ui.unit.Dp [inline] declared in androidx.compose.ui.unit.DpKt' type=androidx.compose.ui.unit.Dp origin=GET_PROPERTY
|
||||||
|
$receiver: CONST Int type=kotlin.Int value=16
|
||||||
|
verticalArrangement: CALL 'public final fun <get-Center> (): androidx.compose.foundation.layout.Arrangement.HorizontalOrVertical declared in androidx.compose.foundation.layout.Arrangement' type=androidx.compose.foundation.layout.Arrangement.HorizontalOrVertical origin=GET_PROPERTY
|
||||||
|
$this: GET_FIELD 'FIELD FIELD_FOR_OBJECT_INSTANCE name:INSTANCE type:androidx.compose.foundation.layout.Arrangement visibility:public [final,static] declared in androidx.compose.foundation.layout.Arrangement' type=androidx.compose.foundation.layout.Arrangement origin=null
|
||||||
|
horizontalAlignment: CALL 'public final fun <get-CenterHorizontally> (): androidx.compose.ui.Alignment.Horizontal declared in androidx.compose.ui.Alignment.Companion' type=androidx.compose.ui.Alignment.Horizontal origin=GET_PROPERTY
|
||||||
|
$this: GET_FIELD 'FIELD FIELD_FOR_OBJECT_INSTANCE name:Companion type:androidx.compose.ui.Alignment.Companion visibility:public [final,static] declared in androidx.compose.ui.Alignment' type=androidx.compose.ui.Alignment.Companion origin=null
|
||||||
|
content: BLOCK type=@[ExtensionFunctionType] kotlin.Function1<androidx.compose.foundation.layout.ColumnScope, kotlin.Unit> origin=LAMBDA
|
||||||
|
COMPOSITE type=kotlin.Unit origin=null
|
||||||
|
FUNCTION_REFERENCE 'private final fun LoginScreen$lambda$14 ($viewModel: com.opentimetracker.ui.AuthViewModel): kotlin.Unit declared in com.opentimetracker.MainActivityKt' type=@[ExtensionFunctionType] kotlin.Function1<androidx.compose.foundation.layout.ColumnScope, kotlin.Unit> origin=INLINE_LAMBDA reflectionTarget=null
|
||||||
|
$viewModel: GET_VAR 'viewModel: com.opentimetracker.ui.AuthViewModel declared in com.opentimetracker.MainActivityKt.LoginScreen' type=com.opentimetracker.ui.AuthViewModel origin=null
|
||||||
|
|
||||||
|
at org.jetbrains.kotlin.backend.jvm.codegen.FunctionCodegen.generate(FunctionCodegen.kt:47)
|
||||||
|
at org.jetbrains.kotlin.backend.jvm.codegen.FunctionCodegen.generate$default(FunctionCodegen.kt:40)
|
||||||
|
at org.jetbrains.kotlin.backend.jvm.codegen.ClassCodegen.generateMethodNode(ClassCodegen.kt:406)
|
||||||
|
at org.jetbrains.kotlin.backend.jvm.codegen.ClassCodegen.generateMethod(ClassCodegen.kt:423)
|
||||||
|
at org.jetbrains.kotlin.backend.jvm.codegen.ClassCodegen.generate(ClassCodegen.kt:168)
|
||||||
|
at org.jetbrains.kotlin.backend.jvm.FileCodegen.lower(JvmPhases.kt:39)
|
||||||
|
at org.jetbrains.kotlin.backend.common.phaser.PhaseFactoriesKt.createFilePhase$lambda$4(PhaseFactories.kt:71)
|
||||||
|
at org.jetbrains.kotlin.backend.common.phaser.PhaseBuildersKt$createSimpleNamedCompilerPhase$1.phaseBody(PhaseBuilders.kt:69)
|
||||||
|
at org.jetbrains.kotlin.backend.common.phaser.SimpleNamedCompilerPhase.phaseBody(CompilerPhase.kt:226)
|
||||||
|
at org.jetbrains.kotlin.backend.common.phaser.AbstractNamedCompilerPhase.invoke(CompilerPhase.kt:113)
|
||||||
|
at org.jetbrains.kotlin.backend.common.phaser.PerformByIrFilePhase.invokeSequential(performByIrFile.kt:62)
|
||||||
|
... 43 more
|
||||||
|
Caused by: org.jetbrains.kotlin.codegen.CompilationException: Back-end (JVM) Internal error: Couldn't inline method call: CALL 'public final fun Column (modifier: androidx.compose.ui.Modifier, verticalArrangement: androidx.compose.foundation.layout.Arrangement.Vertical, horizontalAlignment: androidx.compose.ui.Alignment.Horizontal, content: @[Composable] @[ExtensionFunctionType] kotlin.Function1<androidx.compose.foundation.layout.ColumnScope, kotlin.Unit>): kotlin.Unit [inline] declared in androidx.compose.foundation.layout.ColumnKt' type=kotlin.Unit origin=null
|
||||||
|
Method: null
|
||||||
|
File is unknown
|
||||||
|
The root cause java.lang.IllegalStateException was thrown at: org.jetbrains.kotlin.codegen.inline.SourceCompilerForInlineKt.getMethodNode(SourceCompilerForInline.kt:118)
|
||||||
|
at org.jetbrains.kotlin.codegen.inline.InlineCodegen.performInline(InlineCodegen.kt:65)
|
||||||
|
at org.jetbrains.kotlin.backend.jvm.codegen.IrInlineCodegen.genInlineCall(IrInlineCodegen.kt:163)
|
||||||
|
at org.jetbrains.kotlin.backend.jvm.codegen.IrInlineCallGenerator.genCall(IrInlineCallGenerator.kt:36)
|
||||||
|
at org.jetbrains.kotlin.backend.jvm.codegen.ExpressionCodegen.visitCall(ExpressionCodegen.kt:653)
|
||||||
|
at org.jetbrains.kotlin.backend.jvm.codegen.ExpressionCodegen.visitCall(ExpressionCodegen.kt:138)
|
||||||
|
at org.jetbrains.kotlin.ir.expressions.IrCall.accept(IrCall.kt:24)
|
||||||
|
at org.jetbrains.kotlin.backend.jvm.codegen.ExpressionCodegen.visitStatementContainer(ExpressionCodegen.kt:579)
|
||||||
|
at org.jetbrains.kotlin.backend.jvm.codegen.ExpressionCodegen.visitBlockBody(ExpressionCodegen.kt:584)
|
||||||
|
at org.jetbrains.kotlin.backend.jvm.codegen.ExpressionCodegen.visitBlockBody(ExpressionCodegen.kt:138)
|
||||||
|
at org.jetbrains.kotlin.ir.expressions.IrBlockBody.accept(IrBlockBody.kt:20)
|
||||||
|
at org.jetbrains.kotlin.backend.jvm.codegen.ExpressionCodegen.generate(ExpressionCodegen.kt:240)
|
||||||
|
at org.jetbrains.kotlin.backend.jvm.codegen.FunctionCodegen.doGenerate(FunctionCodegen.kt:123)
|
||||||
|
at org.jetbrains.kotlin.backend.jvm.codegen.FunctionCodegen.generate(FunctionCodegen.kt:44)
|
||||||
|
... 53 more
|
||||||
|
Caused by: java.lang.IllegalStateException: couldn't find inline method Landroidx/compose/foundation/layout/ColumnKt;.Column(Landroidx/compose/ui/Modifier;Landroidx/compose/foundation/layout/Arrangement$Vertical;Landroidx/compose/ui/Alignment$Horizontal;Lkotlin/jvm/functions/Function1;)V
|
||||||
|
at org.jetbrains.kotlin.codegen.inline.SourceCompilerForInlineKt.getMethodNode(SourceCompilerForInline.kt:118)
|
||||||
|
at org.jetbrains.kotlin.codegen.inline.SourceCompilerForInlineKt.loadCompiledInlineFunction(SourceCompilerForInline.kt:96)
|
||||||
|
at org.jetbrains.kotlin.backend.jvm.codegen.IrSourceCompilerForInline.compileInlineFunction(IrSourceCompilerForInline.kt:91)
|
||||||
|
at org.jetbrains.kotlin.codegen.inline.InlineCodegen.compileInline(InlineCodegen.kt:43)
|
||||||
|
at org.jetbrains.kotlin.codegen.inline.InlineCodegen.performInline(InlineCodegen.kt:51)
|
||||||
|
... 65 more
|
||||||
|
|
||||||
|
|
||||||
193
AndroidApp/.kotlin/errors/errors-1770819878847.log
Normal file
193
AndroidApp/.kotlin/errors/errors-1770819878847.log
Normal file
@@ -0,0 +1,193 @@
|
|||||||
|
kotlin version: 2.0.21
|
||||||
|
error message: org.jetbrains.kotlin.backend.common.BackendException: Backend Internal error: Exception during IR lowering
|
||||||
|
File being compiled: /Volumes/SED/Code/OpenTimeTracker/AndroidApp/app/src/main/java/com/opentimetracker/MainActivity.kt
|
||||||
|
The root cause java.lang.RuntimeException was thrown at: org.jetbrains.kotlin.backend.jvm.codegen.FunctionCodegen.generate(FunctionCodegen.kt:47)
|
||||||
|
at org.jetbrains.kotlin.backend.common.CodegenUtil.reportBackendException(CodegenUtil.kt:253)
|
||||||
|
at org.jetbrains.kotlin.backend.common.CodegenUtil.reportBackendException$default(CodegenUtil.kt:236)
|
||||||
|
at org.jetbrains.kotlin.backend.common.phaser.PerformByIrFilePhase.invokeSequential(performByIrFile.kt:65)
|
||||||
|
at org.jetbrains.kotlin.backend.common.phaser.PerformByIrFilePhase.invoke(performByIrFile.kt:52)
|
||||||
|
at org.jetbrains.kotlin.backend.common.phaser.PerformByIrFilePhase.invoke(performByIrFile.kt:38)
|
||||||
|
at org.jetbrains.kotlin.backend.common.phaser.NamedCompilerPhase.phaseBody(CompilerPhase.kt:166)
|
||||||
|
at org.jetbrains.kotlin.backend.common.phaser.AbstractNamedCompilerPhase.invoke(CompilerPhase.kt:113)
|
||||||
|
at org.jetbrains.kotlin.backend.common.phaser.CompositePhase.invoke(PhaseBuilders.kt:27)
|
||||||
|
at org.jetbrains.kotlin.backend.common.phaser.CompositePhase.invoke(PhaseBuilders.kt:14)
|
||||||
|
at org.jetbrains.kotlin.backend.common.phaser.NamedCompilerPhase.phaseBody(CompilerPhase.kt:166)
|
||||||
|
at org.jetbrains.kotlin.backend.common.phaser.AbstractNamedCompilerPhase.invoke(CompilerPhase.kt:113)
|
||||||
|
at org.jetbrains.kotlin.backend.common.phaser.CompilerPhaseKt.invokeToplevel(CompilerPhase.kt:62)
|
||||||
|
at org.jetbrains.kotlin.backend.jvm.JvmIrCodegenFactory.invokeCodegen(JvmIrCodegenFactory.kt:371)
|
||||||
|
at org.jetbrains.kotlin.codegen.CodegenFactory.generateModule(CodegenFactory.kt:47)
|
||||||
|
at org.jetbrains.kotlin.backend.jvm.JvmIrCodegenFactory.generateModuleInFrontendIRMode(JvmIrCodegenFactory.kt:433)
|
||||||
|
at org.jetbrains.kotlin.cli.jvm.compiler.pipeline.JvmCompilerPipelineKt.generateCodeFromIr(jvmCompilerPipeline.kt:246)
|
||||||
|
at org.jetbrains.kotlin.cli.jvm.compiler.pipeline.JvmCompilerPipelineKt.compileModulesUsingFrontendIrAndLightTree(jvmCompilerPipeline.kt:142)
|
||||||
|
at org.jetbrains.kotlin.cli.jvm.K2JVMCompiler.doExecute(K2JVMCompiler.kt:148)
|
||||||
|
at org.jetbrains.kotlin.cli.jvm.K2JVMCompiler.doExecute(K2JVMCompiler.kt:43)
|
||||||
|
at org.jetbrains.kotlin.cli.common.CLICompiler.execImpl(CLICompiler.kt:103)
|
||||||
|
at org.jetbrains.kotlin.cli.common.CLICompiler.execImpl(CLICompiler.kt:49)
|
||||||
|
at org.jetbrains.kotlin.cli.common.CLITool.exec(CLITool.kt:101)
|
||||||
|
at org.jetbrains.kotlin.incremental.IncrementalJvmCompilerRunner.runCompiler(IncrementalJvmCompilerRunner.kt:464)
|
||||||
|
at org.jetbrains.kotlin.incremental.IncrementalJvmCompilerRunner.runCompiler(IncrementalJvmCompilerRunner.kt:73)
|
||||||
|
at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.doCompile(IncrementalCompilerRunner.kt:506)
|
||||||
|
at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.compileImpl(IncrementalCompilerRunner.kt:423)
|
||||||
|
at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.compileNonIncrementally(IncrementalCompilerRunner.kt:301)
|
||||||
|
at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.compile(IncrementalCompilerRunner.kt:129)
|
||||||
|
at org.jetbrains.kotlin.daemon.CompileServiceImplBase.execIncrementalCompiler(CompileServiceImpl.kt:675)
|
||||||
|
at org.jetbrains.kotlin.daemon.CompileServiceImplBase.access$execIncrementalCompiler(CompileServiceImpl.kt:92)
|
||||||
|
at org.jetbrains.kotlin.daemon.CompileServiceImpl.compile(CompileServiceImpl.kt:1660)
|
||||||
|
at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(Unknown Source)
|
||||||
|
at java.base/java.lang.reflect.Method.invoke(Unknown Source)
|
||||||
|
at java.rmi/sun.rmi.server.UnicastServerRef.dispatch(Unknown Source)
|
||||||
|
at java.rmi/sun.rmi.transport.Transport$1.run(Unknown Source)
|
||||||
|
at java.rmi/sun.rmi.transport.Transport$1.run(Unknown Source)
|
||||||
|
at java.base/java.security.AccessController.doPrivileged(Unknown Source)
|
||||||
|
at java.rmi/sun.rmi.transport.Transport.serviceCall(Unknown Source)
|
||||||
|
at java.rmi/sun.rmi.transport.tcp.TCPTransport.handleMessages(Unknown Source)
|
||||||
|
at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(Unknown Source)
|
||||||
|
at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$0(Unknown Source)
|
||||||
|
at java.base/java.security.AccessController.doPrivileged(Unknown Source)
|
||||||
|
at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(Unknown Source)
|
||||||
|
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
|
||||||
|
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
|
||||||
|
at java.base/java.lang.Thread.run(Unknown Source)
|
||||||
|
Caused by: java.lang.RuntimeException: Exception while generating code for:
|
||||||
|
FUN name:LoginScreen visibility:public modality:FINAL <> (viewModel:com.opentimetracker.ui.AuthViewModel, onLoginSuccess:kotlin.Function0<kotlin.Unit>) returnType:kotlin.Unit
|
||||||
|
annotations:
|
||||||
|
Composable
|
||||||
|
VALUE_PARAMETER name:viewModel index:0 type:com.opentimetracker.ui.AuthViewModel
|
||||||
|
VALUE_PARAMETER name:onLoginSuccess index:1 type:kotlin.Function0<kotlin.Unit>
|
||||||
|
BLOCK_BODY
|
||||||
|
WHEN type=kotlin.Unit origin=IF
|
||||||
|
BRANCH
|
||||||
|
if: CALL 'public abstract fun <get-value> (): T of androidx.compose.runtime.MutableState declared in androidx.compose.runtime.MutableState' type=kotlin.Boolean origin=GET_PROPERTY
|
||||||
|
$this: CALL 'public final fun <get-isLoggedIn> (): androidx.compose.runtime.MutableState<kotlin.Boolean> declared in com.opentimetracker.ui.AuthViewModel' type=androidx.compose.runtime.MutableState<kotlin.Boolean> origin=GET_PROPERTY
|
||||||
|
$this: GET_VAR 'viewModel: com.opentimetracker.ui.AuthViewModel declared in com.opentimetracker.MainActivityKt.LoginScreen' type=com.opentimetracker.ui.AuthViewModel origin=null
|
||||||
|
then: BLOCK type=kotlin.Unit origin=null
|
||||||
|
CALL 'public final fun LaunchedEffect (key1: kotlin.Any?, block: @[ExtensionFunctionType] kotlin.coroutines.SuspendFunction1<kotlinx.coroutines.CoroutineScope, kotlin.Unit>): kotlin.Unit declared in androidx.compose.runtime.EffectsKt' type=kotlin.Unit origin=null
|
||||||
|
key1: GET_FIELD 'FIELD FIELD_FOR_OBJECT_INSTANCE name:INSTANCE type:kotlin.Unit visibility:public [final,static] declared in kotlin.Unit' type=kotlin.Unit origin=null
|
||||||
|
block: BLOCK type=com.opentimetracker.MainActivityKt.LoginScreen.<no name provided> origin=null
|
||||||
|
CLASS SUSPEND_LAMBDA CLASS name:<no name provided> modality:FINAL visibility:public/*package*/ superTypes:[kotlin.coroutines.jvm.internal.SuspendLambda; kotlin.jvm.functions.Function2<kotlinx.coroutines.CoroutineScope, kotlin.coroutines.Continuation<kotlin.Unit>?, kotlin.Any?>]
|
||||||
|
$this: VALUE_PARAMETER INSTANCE_RECEIVER name:<this> type:com.opentimetracker.MainActivityKt.LoginScreen.<no name provided>
|
||||||
|
FIELD name:label type:kotlin.Int visibility:public/*package*/
|
||||||
|
CONSTRUCTOR SUSPEND_LAMBDA visibility:public/*package*/ <> ($onLoginSuccess:kotlin.Function0<kotlin.Unit>, $completion:kotlin.coroutines.Continuation<com.opentimetracker.MainActivityKt.LoginScreen.<no name provided>>?) returnType:com.opentimetracker.MainActivityKt.LoginScreen.<no name provided> [primary]
|
||||||
|
VALUE_PARAMETER BOUND_VALUE_PARAMETER name:$onLoginSuccess index:0 type:kotlin.Function0<kotlin.Unit>
|
||||||
|
VALUE_PARAMETER name:$completion index:1 type:kotlin.coroutines.Continuation<com.opentimetracker.MainActivityKt.LoginScreen.<no name provided>>?
|
||||||
|
BLOCK_BODY
|
||||||
|
SET_FIELD 'FIELD FIELD_FOR_CAPTURED_VALUE name:$onLoginSuccess type:kotlin.Function0<kotlin.Unit> visibility:public/*package*/ [final] declared in com.opentimetracker.MainActivityKt.LoginScreen.<no name provided>' type=kotlin.Unit origin=INITIALIZER_OF_FIELD_FOR_CAPTURED_VALUE
|
||||||
|
receiver: GET_VAR '<this>: com.opentimetracker.MainActivityKt.LoginScreen.<no name provided> declared in com.opentimetracker.MainActivityKt.LoginScreen.<no name provided>' type=com.opentimetracker.MainActivityKt.LoginScreen.<no name provided> origin=null
|
||||||
|
value: GET_VAR '$onLoginSuccess: kotlin.Function0<kotlin.Unit> declared in com.opentimetracker.MainActivityKt.LoginScreen.<no name provided>.<init>' type=kotlin.Function0<kotlin.Unit> origin=null
|
||||||
|
DELEGATING_CONSTRUCTOR_CALL 'public constructor <init> (arity: kotlin.Int, $completion: kotlin.coroutines.Continuation<kotlin.Any?>?) declared in kotlin.coroutines.jvm.internal.SuspendLambda'
|
||||||
|
arity: CONST Int type=kotlin.Int value=2
|
||||||
|
$completion: GET_VAR '$completion: kotlin.coroutines.Continuation<com.opentimetracker.MainActivityKt.LoginScreen.<no name provided>>? declared in com.opentimetracker.MainActivityKt.LoginScreen.<no name provided>.<init>' type=kotlin.coroutines.Continuation<com.opentimetracker.MainActivityKt.LoginScreen.<no name provided>>? origin=null
|
||||||
|
BLOCK type=kotlin.Unit origin=null
|
||||||
|
FUN name:invokeSuspend visibility:public modality:FINAL <> ($this:com.opentimetracker.MainActivityKt.LoginScreen.<no name provided>, $result:kotlin.Result<kotlin.Any?>) returnType:kotlin.Any?
|
||||||
|
overridden:
|
||||||
|
protected abstract fun invokeSuspend ($result: kotlin.Result<kotlin.Any?>): kotlin.Any? declared in kotlin.coroutines.jvm.internal.SuspendLambda
|
||||||
|
$this: VALUE_PARAMETER INSTANCE_RECEIVER name:<this> type:com.opentimetracker.MainActivityKt.LoginScreen.<no name provided>
|
||||||
|
VALUE_PARAMETER name:$result index:0 type:kotlin.Result<kotlin.Any?>
|
||||||
|
BLOCK_BODY
|
||||||
|
CALL 'public abstract fun invoke (): R of kotlin.Function0 [operator] declared in kotlin.Function0' type=kotlin.Unit origin=INVOKE
|
||||||
|
$this: GET_FIELD 'FIELD FIELD_FOR_CAPTURED_VALUE name:$onLoginSuccess type:kotlin.Function0<kotlin.Unit> visibility:public/*package*/ [final] declared in com.opentimetracker.MainActivityKt.LoginScreen.<no name provided>' type=kotlin.Function0<kotlin.Unit> origin=null
|
||||||
|
receiver: GET_VAR '<this>: com.opentimetracker.MainActivityKt.LoginScreen.<no name provided> declared in com.opentimetracker.MainActivityKt.LoginScreen.<no name provided>.invokeSuspend' type=com.opentimetracker.MainActivityKt.LoginScreen.<no name provided> origin=null
|
||||||
|
FUN name:create visibility:public modality:FINAL <> ($this:com.opentimetracker.MainActivityKt.LoginScreen.<no name provided>, value:kotlin.Any?, $completion:kotlin.coroutines.Continuation<kotlin.Nothing>) returnType:kotlin.coroutines.Continuation<kotlin.Unit>
|
||||||
|
overridden:
|
||||||
|
public open fun create (value: kotlin.Any?, $completion: kotlin.coroutines.Continuation<kotlin.Nothing>): kotlin.coroutines.Continuation<kotlin.Unit> declared in kotlin.coroutines.jvm.internal.SuspendLambda
|
||||||
|
$this: VALUE_PARAMETER INSTANCE_RECEIVER name:<this> type:com.opentimetracker.MainActivityKt.LoginScreen.<no name provided>
|
||||||
|
VALUE_PARAMETER name:value index:0 type:kotlin.Any?
|
||||||
|
VALUE_PARAMETER name:$completion index:1 type:kotlin.coroutines.Continuation<kotlin.Nothing>
|
||||||
|
BLOCK_BODY
|
||||||
|
RETURN type=kotlin.Nothing from='public final fun create (value: kotlin.Any?, $completion: kotlin.coroutines.Continuation<kotlin.Nothing>): kotlin.coroutines.Continuation<kotlin.Unit> declared in com.opentimetracker.MainActivityKt.LoginScreen.<no name provided>'
|
||||||
|
CONSTRUCTOR_CALL 'public/*package*/ constructor <init> ($onLoginSuccess: kotlin.Function0<kotlin.Unit>, $completion: kotlin.coroutines.Continuation<com.opentimetracker.MainActivityKt.LoginScreen.<no name provided>>?) [primary] declared in com.opentimetracker.MainActivityKt.LoginScreen.<no name provided>' type=com.opentimetracker.MainActivityKt.LoginScreen.<no name provided> origin=null
|
||||||
|
$onLoginSuccess: GET_FIELD 'FIELD FIELD_FOR_CAPTURED_VALUE name:$onLoginSuccess type:kotlin.Function0<kotlin.Unit> visibility:public/*package*/ [final] declared in com.opentimetracker.MainActivityKt.LoginScreen.<no name provided>' type=kotlin.Function0<kotlin.Unit> origin=null
|
||||||
|
receiver: GET_VAR '<this>: com.opentimetracker.MainActivityKt.LoginScreen.<no name provided> declared in com.opentimetracker.MainActivityKt.LoginScreen.<no name provided>.create' type=com.opentimetracker.MainActivityKt.LoginScreen.<no name provided> origin=null
|
||||||
|
$completion: GET_VAR '$completion: kotlin.coroutines.Continuation<kotlin.Nothing> declared in com.opentimetracker.MainActivityKt.LoginScreen.<no name provided>.create' type=kotlin.coroutines.Continuation<kotlin.Nothing> origin=null
|
||||||
|
FUN name:invoke visibility:public modality:FINAL <> ($this:com.opentimetracker.MainActivityKt.LoginScreen.<no name provided>, p1:kotlinx.coroutines.CoroutineScope, p2:kotlin.coroutines.Continuation<kotlin.Unit>?) returnType:kotlin.Any?
|
||||||
|
overridden:
|
||||||
|
public abstract fun invoke (p1: P1 of kotlin.jvm.functions.Function2, p2: P2 of kotlin.jvm.functions.Function2): R of kotlin.jvm.functions.Function2 declared in kotlin.jvm.functions.Function2
|
||||||
|
$this: VALUE_PARAMETER INSTANCE_RECEIVER name:<this> type:com.opentimetracker.MainActivityKt.LoginScreen.<no name provided>
|
||||||
|
VALUE_PARAMETER name:p1 index:0 type:kotlinx.coroutines.CoroutineScope
|
||||||
|
VALUE_PARAMETER name:p2 index:1 type:kotlin.coroutines.Continuation<kotlin.Unit>?
|
||||||
|
BLOCK_BODY
|
||||||
|
RETURN type=kotlin.Nothing from='public final fun invoke (p1: kotlinx.coroutines.CoroutineScope, p2: kotlin.coroutines.Continuation<kotlin.Unit>?): kotlin.Any? declared in com.opentimetracker.MainActivityKt.LoginScreen.<no name provided>'
|
||||||
|
CALL 'public final fun invokeSuspend ($result: kotlin.Result<kotlin.Any?>): kotlin.Any? declared in com.opentimetracker.MainActivityKt.LoginScreen.<no name provided>' type=kotlin.Any? origin=null
|
||||||
|
$this: TYPE_OP type=com.opentimetracker.MainActivityKt.LoginScreen.<no name provided> origin=IMPLICIT_CAST typeOperand=com.opentimetracker.MainActivityKt.LoginScreen.<no name provided>
|
||||||
|
CALL 'public final fun create (value: kotlin.Any?, $completion: kotlin.coroutines.Continuation<kotlin.Nothing>): kotlin.coroutines.Continuation<kotlin.Unit> declared in com.opentimetracker.MainActivityKt.LoginScreen.<no name provided>' type=kotlin.coroutines.Continuation<kotlin.Unit> origin=null
|
||||||
|
$this: GET_VAR '<this>: com.opentimetracker.MainActivityKt.LoginScreen.<no name provided> declared in com.opentimetracker.MainActivityKt.LoginScreen.<no name provided>.invoke' type=com.opentimetracker.MainActivityKt.LoginScreen.<no name provided> origin=null
|
||||||
|
value: GET_VAR 'p1: kotlinx.coroutines.CoroutineScope declared in com.opentimetracker.MainActivityKt.LoginScreen.<no name provided>.invoke' type=kotlinx.coroutines.CoroutineScope origin=null
|
||||||
|
$completion: GET_VAR 'p2: kotlin.coroutines.Continuation<kotlin.Unit>? declared in com.opentimetracker.MainActivityKt.LoginScreen.<no name provided>.invoke' type=kotlin.coroutines.Continuation<kotlin.Unit>? origin=null
|
||||||
|
$result: CALL 'public final fun <unsafe-coerce> <T, R> (v: T of kotlin.jvm.internal.<unsafe-coerce>): R of kotlin.jvm.internal.<unsafe-coerce> declared in kotlin.jvm.internal' type=kotlin.Result<kotlin.Any?> origin=null
|
||||||
|
<T>: kotlin.Any?
|
||||||
|
<R>: kotlin.Result<kotlin.Any?>
|
||||||
|
v: GET_FIELD 'FIELD FIELD_FOR_OBJECT_INSTANCE name:INSTANCE type:kotlin.Unit visibility:public [final,static] declared in kotlin.Unit' type=kotlin.Unit origin=null
|
||||||
|
FIELD FIELD_FOR_CAPTURED_VALUE name:$onLoginSuccess type:kotlin.Function0<kotlin.Unit> visibility:public/*package*/ [final]
|
||||||
|
FUN BRIDGE name:invoke visibility:public modality:OPEN <> ($this:com.opentimetracker.MainActivityKt.LoginScreen.<no name provided>, p1:kotlin.Any?, p2:kotlin.Any?) returnType:kotlin.Any?
|
||||||
|
$this: VALUE_PARAMETER INSTANCE_RECEIVER name:<this> type:com.opentimetracker.MainActivityKt.LoginScreen.<no name provided>
|
||||||
|
VALUE_PARAMETER BRIDGE name:p1 index:0 type:kotlin.Any?
|
||||||
|
VALUE_PARAMETER BRIDGE name:p2 index:1 type:kotlin.Any?
|
||||||
|
EXPRESSION_BODY
|
||||||
|
RETURN type=kotlin.Nothing from='public open fun invoke (p1: kotlin.Any?, p2: kotlin.Any?): kotlin.Any? declared in com.opentimetracker.MainActivityKt.LoginScreen.<no name provided>'
|
||||||
|
CALL 'public final fun invoke (p1: kotlinx.coroutines.CoroutineScope, p2: kotlin.coroutines.Continuation<kotlin.Unit>?): kotlin.Any? declared in com.opentimetracker.MainActivityKt.LoginScreen.<no name provided>' type=kotlin.Any? origin=BRIDGE_DELEGATION
|
||||||
|
$this: GET_VAR '<this>: com.opentimetracker.MainActivityKt.LoginScreen.<no name provided> declared in com.opentimetracker.MainActivityKt.LoginScreen.<no name provided>.invoke' type=com.opentimetracker.MainActivityKt.LoginScreen.<no name provided> origin=null
|
||||||
|
p1: TYPE_OP type=kotlinx.coroutines.CoroutineScope origin=IMPLICIT_CAST typeOperand=kotlinx.coroutines.CoroutineScope
|
||||||
|
GET_VAR 'p1: kotlin.Any? declared in com.opentimetracker.MainActivityKt.LoginScreen.<no name provided>.invoke' type=kotlin.Any? origin=null
|
||||||
|
p2: TYPE_OP type=kotlin.coroutines.Continuation<*> origin=IMPLICIT_CAST typeOperand=kotlin.coroutines.Continuation<*>
|
||||||
|
GET_VAR 'p2: kotlin.Any? declared in com.opentimetracker.MainActivityKt.LoginScreen.<no name provided>.invoke' type=kotlin.Any? origin=null
|
||||||
|
CONSTRUCTOR_CALL 'public/*package*/ constructor <init> ($onLoginSuccess: kotlin.Function0<kotlin.Unit>, $completion: kotlin.coroutines.Continuation<com.opentimetracker.MainActivityKt.LoginScreen.<no name provided>>?) [primary] declared in com.opentimetracker.MainActivityKt.LoginScreen.<no name provided>' type=com.opentimetracker.MainActivityKt.LoginScreen.<no name provided> origin=null
|
||||||
|
$onLoginSuccess: GET_VAR 'onLoginSuccess: kotlin.Function0<kotlin.Unit> declared in com.opentimetracker.MainActivityKt.LoginScreen' type=kotlin.Function0<kotlin.Unit> origin=null
|
||||||
|
$completion: CONST Null type=kotlin.Nothing? value=null
|
||||||
|
CALL 'public final fun Column (modifier: androidx.compose.ui.Modifier, verticalArrangement: androidx.compose.foundation.layout.Arrangement.Vertical, horizontalAlignment: androidx.compose.ui.Alignment.Horizontal, content: @[Composable] @[ExtensionFunctionType] kotlin.Function1<androidx.compose.foundation.layout.ColumnScope, kotlin.Unit>): kotlin.Unit [inline] declared in androidx.compose.foundation.layout.ColumnKt' type=kotlin.Unit origin=null
|
||||||
|
modifier: CALL 'public final fun padding-3ABfNKs (all: androidx.compose.ui.unit.Dp): androidx.compose.ui.Modifier declared in androidx.compose.foundation.layout.PaddingKt' type=androidx.compose.ui.Modifier origin=null
|
||||||
|
$receiver: CALL 'public final fun fillMaxSize$default (fraction: kotlin.Float, $mask0: kotlin.Int, $handler: kotlin.Any?): androidx.compose.ui.Modifier declared in androidx.compose.foundation.layout.SizeKt' type=androidx.compose.ui.Modifier origin=DEFAULT_DISPATCH_CALL
|
||||||
|
$receiver: GET_FIELD 'FIELD FIELD_FOR_OBJECT_INSTANCE name:Companion type:androidx.compose.ui.Modifier.Companion visibility:public [final,static] declared in androidx.compose.ui.Modifier' type=androidx.compose.ui.Modifier.Companion origin=null
|
||||||
|
fraction: COMPOSITE type=kotlin.Float origin=DEFAULT_VALUE
|
||||||
|
CONST Float type=kotlin.Float value=0.0
|
||||||
|
$mask0: CONST Int type=kotlin.Int value=1
|
||||||
|
$handler: CONST Null type=kotlin.Any? value=null
|
||||||
|
all: CALL 'public final fun <get-dp> (): androidx.compose.ui.unit.Dp [inline] declared in androidx.compose.ui.unit.DpKt' type=androidx.compose.ui.unit.Dp origin=GET_PROPERTY
|
||||||
|
$receiver: CONST Int type=kotlin.Int value=16
|
||||||
|
verticalArrangement: CALL 'public final fun <get-Center> (): androidx.compose.foundation.layout.Arrangement.HorizontalOrVertical declared in androidx.compose.foundation.layout.Arrangement' type=androidx.compose.foundation.layout.Arrangement.HorizontalOrVertical origin=GET_PROPERTY
|
||||||
|
$this: GET_FIELD 'FIELD FIELD_FOR_OBJECT_INSTANCE name:INSTANCE type:androidx.compose.foundation.layout.Arrangement visibility:public [final,static] declared in androidx.compose.foundation.layout.Arrangement' type=androidx.compose.foundation.layout.Arrangement origin=null
|
||||||
|
horizontalAlignment: CALL 'public final fun <get-CenterHorizontally> (): androidx.compose.ui.Alignment.Horizontal declared in androidx.compose.ui.Alignment.Companion' type=androidx.compose.ui.Alignment.Horizontal origin=GET_PROPERTY
|
||||||
|
$this: GET_FIELD 'FIELD FIELD_FOR_OBJECT_INSTANCE name:Companion type:androidx.compose.ui.Alignment.Companion visibility:public [final,static] declared in androidx.compose.ui.Alignment' type=androidx.compose.ui.Alignment.Companion origin=null
|
||||||
|
content: BLOCK type=@[ExtensionFunctionType] kotlin.Function1<androidx.compose.foundation.layout.ColumnScope, kotlin.Unit> origin=LAMBDA
|
||||||
|
COMPOSITE type=kotlin.Unit origin=null
|
||||||
|
FUNCTION_REFERENCE 'private final fun LoginScreen$lambda$14 ($viewModel: com.opentimetracker.ui.AuthViewModel): kotlin.Unit declared in com.opentimetracker.MainActivityKt' type=@[ExtensionFunctionType] kotlin.Function1<androidx.compose.foundation.layout.ColumnScope, kotlin.Unit> origin=INLINE_LAMBDA reflectionTarget=null
|
||||||
|
$viewModel: GET_VAR 'viewModel: com.opentimetracker.ui.AuthViewModel declared in com.opentimetracker.MainActivityKt.LoginScreen' type=com.opentimetracker.ui.AuthViewModel origin=null
|
||||||
|
|
||||||
|
at org.jetbrains.kotlin.backend.jvm.codegen.FunctionCodegen.generate(FunctionCodegen.kt:47)
|
||||||
|
at org.jetbrains.kotlin.backend.jvm.codegen.FunctionCodegen.generate$default(FunctionCodegen.kt:40)
|
||||||
|
at org.jetbrains.kotlin.backend.jvm.codegen.ClassCodegen.generateMethodNode(ClassCodegen.kt:406)
|
||||||
|
at org.jetbrains.kotlin.backend.jvm.codegen.ClassCodegen.generateMethod(ClassCodegen.kt:423)
|
||||||
|
at org.jetbrains.kotlin.backend.jvm.codegen.ClassCodegen.generate(ClassCodegen.kt:168)
|
||||||
|
at org.jetbrains.kotlin.backend.jvm.FileCodegen.lower(JvmPhases.kt:39)
|
||||||
|
at org.jetbrains.kotlin.backend.common.phaser.PhaseFactoriesKt.createFilePhase$lambda$4(PhaseFactories.kt:71)
|
||||||
|
at org.jetbrains.kotlin.backend.common.phaser.PhaseBuildersKt$createSimpleNamedCompilerPhase$1.phaseBody(PhaseBuilders.kt:69)
|
||||||
|
at org.jetbrains.kotlin.backend.common.phaser.SimpleNamedCompilerPhase.phaseBody(CompilerPhase.kt:226)
|
||||||
|
at org.jetbrains.kotlin.backend.common.phaser.AbstractNamedCompilerPhase.invoke(CompilerPhase.kt:113)
|
||||||
|
at org.jetbrains.kotlin.backend.common.phaser.PerformByIrFilePhase.invokeSequential(performByIrFile.kt:62)
|
||||||
|
... 43 more
|
||||||
|
Caused by: org.jetbrains.kotlin.codegen.CompilationException: Back-end (JVM) Internal error: Couldn't inline method call: CALL 'public final fun Column (modifier: androidx.compose.ui.Modifier, verticalArrangement: androidx.compose.foundation.layout.Arrangement.Vertical, horizontalAlignment: androidx.compose.ui.Alignment.Horizontal, content: @[Composable] @[ExtensionFunctionType] kotlin.Function1<androidx.compose.foundation.layout.ColumnScope, kotlin.Unit>): kotlin.Unit [inline] declared in androidx.compose.foundation.layout.ColumnKt' type=kotlin.Unit origin=null
|
||||||
|
Method: null
|
||||||
|
File is unknown
|
||||||
|
The root cause java.lang.IllegalStateException was thrown at: org.jetbrains.kotlin.codegen.inline.SourceCompilerForInlineKt.getMethodNode(SourceCompilerForInline.kt:118)
|
||||||
|
at org.jetbrains.kotlin.codegen.inline.InlineCodegen.performInline(InlineCodegen.kt:65)
|
||||||
|
at org.jetbrains.kotlin.backend.jvm.codegen.IrInlineCodegen.genInlineCall(IrInlineCodegen.kt:163)
|
||||||
|
at org.jetbrains.kotlin.backend.jvm.codegen.IrInlineCallGenerator.genCall(IrInlineCallGenerator.kt:36)
|
||||||
|
at org.jetbrains.kotlin.backend.jvm.codegen.ExpressionCodegen.visitCall(ExpressionCodegen.kt:653)
|
||||||
|
at org.jetbrains.kotlin.backend.jvm.codegen.ExpressionCodegen.visitCall(ExpressionCodegen.kt:138)
|
||||||
|
at org.jetbrains.kotlin.ir.expressions.IrCall.accept(IrCall.kt:24)
|
||||||
|
at org.jetbrains.kotlin.backend.jvm.codegen.ExpressionCodegen.visitStatementContainer(ExpressionCodegen.kt:579)
|
||||||
|
at org.jetbrains.kotlin.backend.jvm.codegen.ExpressionCodegen.visitBlockBody(ExpressionCodegen.kt:584)
|
||||||
|
at org.jetbrains.kotlin.backend.jvm.codegen.ExpressionCodegen.visitBlockBody(ExpressionCodegen.kt:138)
|
||||||
|
at org.jetbrains.kotlin.ir.expressions.IrBlockBody.accept(IrBlockBody.kt:20)
|
||||||
|
at org.jetbrains.kotlin.backend.jvm.codegen.ExpressionCodegen.generate(ExpressionCodegen.kt:240)
|
||||||
|
at org.jetbrains.kotlin.backend.jvm.codegen.FunctionCodegen.doGenerate(FunctionCodegen.kt:123)
|
||||||
|
at org.jetbrains.kotlin.backend.jvm.codegen.FunctionCodegen.generate(FunctionCodegen.kt:44)
|
||||||
|
... 53 more
|
||||||
|
Caused by: java.lang.IllegalStateException: couldn't find inline method Landroidx/compose/foundation/layout/ColumnKt;.Column(Landroidx/compose/ui/Modifier;Landroidx/compose/foundation/layout/Arrangement$Vertical;Landroidx/compose/ui/Alignment$Horizontal;Lkotlin/jvm/functions/Function1;)V
|
||||||
|
at org.jetbrains.kotlin.codegen.inline.SourceCompilerForInlineKt.getMethodNode(SourceCompilerForInline.kt:118)
|
||||||
|
at org.jetbrains.kotlin.codegen.inline.SourceCompilerForInlineKt.loadCompiledInlineFunction(SourceCompilerForInline.kt:96)
|
||||||
|
at org.jetbrains.kotlin.backend.jvm.codegen.IrSourceCompilerForInline.compileInlineFunction(IrSourceCompilerForInline.kt:91)
|
||||||
|
at org.jetbrains.kotlin.codegen.inline.InlineCodegen.compileInline(InlineCodegen.kt:43)
|
||||||
|
at org.jetbrains.kotlin.codegen.inline.InlineCodegen.performInline(InlineCodegen.kt:51)
|
||||||
|
... 65 more
|
||||||
|
|
||||||
|
|
||||||
@@ -1,6 +1,12 @@
|
|||||||
plugins {
|
plugins {
|
||||||
alias(libs.plugins.android.application)
|
alias(libs.plugins.android.application)
|
||||||
alias(libs.plugins.kotlin.android)
|
alias(libs.plugins.kotlin.android)
|
||||||
|
// Kotlin 2.0+ requires the dedicated Compose Compiler plugin
|
||||||
|
id("org.jetbrains.kotlin.plugin.compose")
|
||||||
|
// Version constraint removed to allow sync with main Kotlin version (2.0.0+)
|
||||||
|
id("org.jetbrains.kotlin.plugin.serialization")
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
android {
|
android {
|
||||||
@@ -33,6 +39,10 @@ android {
|
|||||||
kotlinOptions {
|
kotlinOptions {
|
||||||
jvmTarget = "11"
|
jvmTarget = "11"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
buildFeatures {
|
||||||
|
compose = true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
@@ -43,4 +53,22 @@ dependencies {
|
|||||||
testImplementation(libs.junit)
|
testImplementation(libs.junit)
|
||||||
androidTestImplementation(libs.androidx.junit)
|
androidTestImplementation(libs.androidx.junit)
|
||||||
androidTestImplementation(libs.androidx.espresso.core)
|
androidTestImplementation(libs.androidx.espresso.core)
|
||||||
|
|
||||||
|
// Networking
|
||||||
|
implementation("com.squareup.retrofit2:retrofit:2.9.0")
|
||||||
|
implementation("com.jakewharton.retrofit:retrofit2-kotlinx-serialization-converter:1.0.0")
|
||||||
|
implementation("com.squareup.okhttp3:okhttp:4.11.0")
|
||||||
|
implementation("com.squareup.okhttp3:logging-interceptor:4.11.0")
|
||||||
|
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.6.0")
|
||||||
|
|
||||||
|
// Storage
|
||||||
|
implementation("androidx.datastore:datastore-preferences:1.0.0")
|
||||||
|
|
||||||
|
// Navigation
|
||||||
|
implementation("androidx.navigation:navigation-compose:2.7.7")
|
||||||
|
|
||||||
|
// Compose
|
||||||
|
implementation(platform("androidx.compose:compose-bom:2024.02.01"))
|
||||||
|
implementation("androidx.compose.ui:ui")
|
||||||
|
implementation("androidx.compose.material3:material3")
|
||||||
}
|
}
|
||||||
@@ -2,6 +2,8 @@
|
|||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:tools="http://schemas.android.com/tools">
|
xmlns:tools="http://schemas.android.com/tools">
|
||||||
|
|
||||||
|
<uses-permission android:name="android.permission.INTERNET" />
|
||||||
|
|
||||||
<application
|
<application
|
||||||
android:allowBackup="true"
|
android:allowBackup="true"
|
||||||
android:dataExtractionRules="@xml/data_extraction_rules"
|
android:dataExtractionRules="@xml/data_extraction_rules"
|
||||||
@@ -11,6 +13,19 @@
|
|||||||
android:roundIcon="@mipmap/ic_launcher_round"
|
android:roundIcon="@mipmap/ic_launcher_round"
|
||||||
android:supportsRtl="true"
|
android:supportsRtl="true"
|
||||||
android:theme="@style/Theme.OpenTimeTracker"
|
android:theme="@style/Theme.OpenTimeTracker"
|
||||||
tools:targetApi="31" />
|
tools:targetApi="31">
|
||||||
|
|
||||||
|
<activity
|
||||||
|
android:name="MainActivity"
|
||||||
|
android:exported="true"
|
||||||
|
android:label="@string/app_name"
|
||||||
|
android:theme="@style/Theme.OpenTimeTracker">
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.intent.action.MAIN" />
|
||||||
|
<category android:name="android.intent.category.LAUNCHER" />
|
||||||
|
</intent-filter>
|
||||||
|
</activity>
|
||||||
|
|
||||||
|
</application>
|
||||||
|
|
||||||
</manifest>
|
</manifest>
|
||||||
@@ -0,0 +1,236 @@
|
|||||||
|
package calvin.erfmann.opentimetracker
|
||||||
|
|
||||||
|
import android.os.Bundle
|
||||||
|
import androidx.activity.ComponentActivity
|
||||||
|
import androidx.activity.compose.setContent
|
||||||
|
import androidx.compose.foundation.clickable
|
||||||
|
import androidx.compose.foundation.layout.*
|
||||||
|
import androidx.compose.foundation.lazy.LazyColumn
|
||||||
|
import androidx.compose.foundation.lazy.grid.GridCells
|
||||||
|
import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
|
||||||
|
import androidx.compose.foundation.lazy.grid.items
|
||||||
|
import androidx.compose.foundation.lazy.items
|
||||||
|
import androidx.compose.material3.*
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
|
import androidx.compose.runtime.remember
|
||||||
|
import androidx.compose.ui.Alignment
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.graphics.Color
|
||||||
|
import androidx.compose.ui.text.input.PasswordVisualTransformation
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import androidx.lifecycle.ViewModel
|
||||||
|
import androidx.lifecycle.ViewModelProvider
|
||||||
|
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||||
|
import androidx.navigation.compose.NavHost
|
||||||
|
import androidx.navigation.compose.composable
|
||||||
|
import androidx.navigation.compose.rememberNavController
|
||||||
|
import calvin.erfmann.opentimetracker.data.Activity
|
||||||
|
import calvin.erfmann.opentimetracker.data.UserPreferences
|
||||||
|
import calvin.erfmann.opentimetracker.di.NetworkModule
|
||||||
|
import calvin.erfmann.opentimetracker.ui.AuthViewModel
|
||||||
|
import calvin.erfmann.opentimetracker.ui.DashboardViewModel
|
||||||
|
|
||||||
|
class MainActivity : ComponentActivity() {
|
||||||
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
super.onCreate(savedInstanceState)
|
||||||
|
val prefs = UserPreferences(this)
|
||||||
|
|
||||||
|
setContent {
|
||||||
|
MaterialTheme {
|
||||||
|
AppNavigation(prefs)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun AppNavigation(prefs: UserPreferences) {
|
||||||
|
val navController = rememberNavController()
|
||||||
|
|
||||||
|
NavHost(navController = navController, startDestination = "login") {
|
||||||
|
composable("login") {
|
||||||
|
LoginScreen(
|
||||||
|
viewModel = viewModel(factory = object : ViewModelProvider.Factory {
|
||||||
|
@Suppress("UNCHECKED_CAST")
|
||||||
|
override fun <T : ViewModel> create(modelClass: Class<T>): T {
|
||||||
|
return AuthViewModel(prefs) as T
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
onLoginSuccess = { navController.navigate("dashboard") {
|
||||||
|
popUpTo("login") { inclusive = true }
|
||||||
|
}}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
composable("dashboard") {
|
||||||
|
// Using remember to avoid recreating the API definition
|
||||||
|
val api = remember { NetworkModule.provideApiService(prefs) }
|
||||||
|
|
||||||
|
// CORRECT: Using viewModel factory to keep the instance alive across recompositions
|
||||||
|
// This prevents the infinite loop of API requests
|
||||||
|
val viewModel: DashboardViewModel = viewModel(
|
||||||
|
factory = object : ViewModelProvider.Factory {
|
||||||
|
@Suppress("UNCHECKED_CAST")
|
||||||
|
override fun <T : ViewModel> create(modelClass: Class<T>): T {
|
||||||
|
return DashboardViewModel(api) as T
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
DashboardScreen(viewModel = viewModel)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun LoginScreen(viewModel: AuthViewModel, onLoginSuccess: () -> Unit) {
|
||||||
|
|
||||||
|
if (viewModel.isLoggedIn.value) {
|
||||||
|
LaunchedEffect(Unit) { onLoginSuccess() }
|
||||||
|
}
|
||||||
|
|
||||||
|
Column(
|
||||||
|
modifier = Modifier.fillMaxSize().padding(16.dp),
|
||||||
|
verticalArrangement = Arrangement.Center,
|
||||||
|
horizontalAlignment = Alignment.CenterHorizontally
|
||||||
|
) {
|
||||||
|
Text("Open Time Tracker", style = MaterialTheme.typography.headlineMedium)
|
||||||
|
Spacer(Modifier.height(32.dp))
|
||||||
|
|
||||||
|
OutlinedTextField(
|
||||||
|
value = viewModel.baseUrlInput.value,
|
||||||
|
onValueChange = { viewModel.baseUrlInput.value = it },
|
||||||
|
label = { Text("Server URL (Self-hosted)") },
|
||||||
|
modifier = Modifier.fillMaxWidth()
|
||||||
|
)
|
||||||
|
Spacer(Modifier.height(8.dp))
|
||||||
|
OutlinedTextField(
|
||||||
|
value = viewModel.username.value,
|
||||||
|
onValueChange = { viewModel.username.value = it },
|
||||||
|
label = { Text("Username") },
|
||||||
|
modifier = Modifier.fillMaxWidth()
|
||||||
|
)
|
||||||
|
Spacer(Modifier.height(8.dp))
|
||||||
|
OutlinedTextField(
|
||||||
|
value = viewModel.password.value,
|
||||||
|
onValueChange = { viewModel.password.value = it },
|
||||||
|
label = { Text("Password") },
|
||||||
|
modifier = Modifier.fillMaxWidth(),
|
||||||
|
visualTransformation = PasswordVisualTransformation()
|
||||||
|
)
|
||||||
|
Spacer(Modifier.height(16.dp))
|
||||||
|
|
||||||
|
if (viewModel.error.value != null) {
|
||||||
|
Text(viewModel.error.value!!, color = Color.Red)
|
||||||
|
Spacer(Modifier.height(8.dp))
|
||||||
|
}
|
||||||
|
|
||||||
|
Button(
|
||||||
|
onClick = { viewModel.login() },
|
||||||
|
enabled = !viewModel.isLoading.value,
|
||||||
|
modifier = Modifier.fillMaxWidth()
|
||||||
|
) {
|
||||||
|
Text(if (viewModel.isLoading.value) "Logging in..." else "Login")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun DashboardScreen(viewModel: DashboardViewModel) {
|
||||||
|
val state = viewModel.state.value
|
||||||
|
|
||||||
|
Column(modifier = Modifier.fillMaxSize().padding(16.dp)) {
|
||||||
|
// --- Timer Section ---
|
||||||
|
Card(
|
||||||
|
modifier = Modifier.fillMaxWidth(),
|
||||||
|
colors = CardDefaults.cardColors(containerColor = MaterialTheme.colorScheme.primaryContainer)
|
||||||
|
) {
|
||||||
|
Column(
|
||||||
|
modifier = Modifier.padding(24.dp).fillMaxWidth(),
|
||||||
|
horizontalAlignment = Alignment.CenterHorizontally
|
||||||
|
) {
|
||||||
|
if (state?.isTracking == true) {
|
||||||
|
val activityName = state.activities.find { it.id == state.entry?.activityId }?.name ?: "Unknown"
|
||||||
|
Text(activityName, style = MaterialTheme.typography.titleMedium)
|
||||||
|
if (!state.entry?.subcategory.isNullOrEmpty()) {
|
||||||
|
SuggestionChip(onClick = {}, label = { Text(state.entry?.subcategory!!) })
|
||||||
|
}
|
||||||
|
Text(viewModel.elapsedTime.value, style = MaterialTheme.typography.displayLarge)
|
||||||
|
Spacer(Modifier.height(16.dp))
|
||||||
|
Button(
|
||||||
|
onClick = { viewModel.stopActivity() },
|
||||||
|
colors = ButtonDefaults.buttonColors(containerColor = MaterialTheme.colorScheme.error)
|
||||||
|
) {
|
||||||
|
Text("STOP")
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Text("Ready to work?", style = MaterialTheme.typography.headlineSmall)
|
||||||
|
Text("Select an activity below", style = MaterialTheme.typography.bodyMedium)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Spacer(Modifier.height(24.dp))
|
||||||
|
|
||||||
|
// --- Content Switching ---
|
||||||
|
// Always show Active Tasks if present
|
||||||
|
if (!state?.activeTasks.isNullOrEmpty()) {
|
||||||
|
Text("Active Tasks", style = MaterialTheme.typography.titleMedium)
|
||||||
|
LazyColumn(modifier = Modifier.heightIn(max = 200.dp)) { // Limit height to not push activities off screen
|
||||||
|
items(state!!.activeTasks) { task ->
|
||||||
|
Row(verticalAlignment = Alignment.CenterVertically) {
|
||||||
|
Checkbox(
|
||||||
|
checked = task.status == "completed",
|
||||||
|
onCheckedChange = { /* Call toggle api */ })
|
||||||
|
Text(task.name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Spacer(Modifier.height(16.dp))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Always show Activities Grid
|
||||||
|
Text("Activities", style = MaterialTheme.typography.titleMedium)
|
||||||
|
Spacer(Modifier.height(8.dp))
|
||||||
|
|
||||||
|
// Show loading or empty state if null
|
||||||
|
if (state == null) {
|
||||||
|
Box(modifier = Modifier.fillMaxWidth().height(100.dp), contentAlignment = Alignment.Center) {
|
||||||
|
CircularProgressIndicator()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
LazyVerticalGrid(
|
||||||
|
columns = GridCells.Fixed(2),
|
||||||
|
horizontalArrangement = Arrangement.spacedBy(8.dp),
|
||||||
|
verticalArrangement = Arrangement.spacedBy(8.dp),
|
||||||
|
modifier = Modifier.weight(1f) // Fill remaining space
|
||||||
|
) {
|
||||||
|
items(state.activities) { activity ->
|
||||||
|
ActivityCard(activity) { viewModel.startActivity(activity.id) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun ActivityCard(activity: Activity, onClick: () -> Unit) {
|
||||||
|
// Parse hex color lightly
|
||||||
|
val color = try {
|
||||||
|
Color(android.graphics.Color.parseColor(activity.color))
|
||||||
|
} catch (e: Exception) { Color.Gray }
|
||||||
|
|
||||||
|
Card(
|
||||||
|
modifier = Modifier
|
||||||
|
.height(100.dp)
|
||||||
|
.clickable { onClick() },
|
||||||
|
colors = CardDefaults.cardColors(containerColor = color)
|
||||||
|
) {
|
||||||
|
Box(contentAlignment = Alignment.Center, modifier = Modifier.fillMaxSize()) {
|
||||||
|
Text(
|
||||||
|
activity.name,
|
||||||
|
color = Color.White,
|
||||||
|
style = MaterialTheme.typography.titleMedium
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
package calvin.erfmann.opentimetracker.data
|
||||||
|
|
||||||
|
import retrofit2.http.*
|
||||||
|
|
||||||
|
interface ApiService {
|
||||||
|
// Auth
|
||||||
|
@POST("api/login")
|
||||||
|
suspend fun login(@Body request: LoginRequest): AuthResponse
|
||||||
|
|
||||||
|
// Dashboard
|
||||||
|
@GET("api/status")
|
||||||
|
suspend fun getStatus(): StatusResponse
|
||||||
|
|
||||||
|
@POST("api/timer/start/{activity_id}")
|
||||||
|
suspend fun startActivity(@Path("activity_id") activityId: String): StartTimerResponse
|
||||||
|
|
||||||
|
@POST("api/timer/stop")
|
||||||
|
suspend fun stopActivity()
|
||||||
|
|
||||||
|
@POST("api/tasks/toggle")
|
||||||
|
suspend fun toggleTask(@Body body: Map<String, Any>): Any // Simplified
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,64 @@
|
|||||||
|
package calvin.erfmann.opentimetracker.data
|
||||||
|
|
||||||
|
import kotlinx.serialization.ExperimentalSerializationApi
|
||||||
|
import kotlinx.serialization.InternalSerializationApi
|
||||||
|
import kotlinx.serialization.SerialName
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class AuthResponse(
|
||||||
|
val token: String
|
||||||
|
)
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class LoginRequest(
|
||||||
|
val username: String,
|
||||||
|
val password: String
|
||||||
|
)
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class StatusResponse(
|
||||||
|
@SerialName("is_tracking") val isTracking: Boolean = false,
|
||||||
|
val entry: TimeEntry? = null,
|
||||||
|
@SerialName("active_tasks") val activeTasks: List<Task> = emptyList(),
|
||||||
|
val activities: List<Activity> = emptyList()
|
||||||
|
)
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class TimeEntry(
|
||||||
|
val id: String,
|
||||||
|
@SerialName("start_time") val startTime: String,
|
||||||
|
val note: String? = null,
|
||||||
|
val subcategory: String? = null,
|
||||||
|
@SerialName("activity_id") val activityId: String? = null,
|
||||||
|
@SerialName("activity_name") val activityName: String? = null,
|
||||||
|
@SerialName("activity_color") val activityColor: String? = null
|
||||||
|
)
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class Activity(
|
||||||
|
val id: String,
|
||||||
|
val name: String,
|
||||||
|
val color: String,
|
||||||
|
val subcategories: List<String> = emptyList()
|
||||||
|
)
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class Task(
|
||||||
|
val id: String,
|
||||||
|
val name: String,
|
||||||
|
val status: String = "open", // Werte vom Server: "open" oder "completed"
|
||||||
|
val subcategory: String? = null,
|
||||||
|
@SerialName("activity_id") val activityId: String? = null,
|
||||||
|
@SerialName("completed_at") val completedAt: String? = null,
|
||||||
|
@SerialName("due_date") val dueDate: String? = null
|
||||||
|
)
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class StartTimerResponse(
|
||||||
|
val id: String,
|
||||||
|
@SerialName("start_time") val startTime: String
|
||||||
|
)
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
package calvin.erfmann.opentimetracker.data
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import androidx.datastore.preferences.core.edit
|
||||||
|
import androidx.datastore.preferences.core.stringPreferencesKey
|
||||||
|
import androidx.datastore.preferences.preferencesDataStore
|
||||||
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
import kotlinx.coroutines.flow.map
|
||||||
|
|
||||||
|
private val Context.dataStore by preferencesDataStore(name = "settings")
|
||||||
|
|
||||||
|
class UserPreferences(private val context: Context) {
|
||||||
|
companion object {
|
||||||
|
val KEY_BASE_URL = stringPreferencesKey("base_url")
|
||||||
|
val KEY_JWT = stringPreferencesKey("jwt")
|
||||||
|
const val DEFAULT_URL = "https://opentimetracker.app/"
|
||||||
|
}
|
||||||
|
|
||||||
|
val baseUrl: Flow<String> = context.dataStore.data.map { it[KEY_BASE_URL] ?: DEFAULT_URL }
|
||||||
|
val authToken: Flow<String?> = context.dataStore.data.map { it[KEY_JWT] }
|
||||||
|
|
||||||
|
suspend fun saveBaseUrl(url: String) {
|
||||||
|
// Ensure trailing slash
|
||||||
|
val formattedUrl = if (url.endsWith("/")) url else "$url/"
|
||||||
|
context.dataStore.edit { it[KEY_BASE_URL] = formattedUrl }
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun saveToken(token: String) {
|
||||||
|
context.dataStore.edit { it[KEY_JWT] = token }
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun clearToken() {
|
||||||
|
context.dataStore.edit { it.remove(KEY_JWT) }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,53 @@
|
|||||||
|
package calvin.erfmann.opentimetracker.di
|
||||||
|
|
||||||
|
import com.jakewharton.retrofit2.converter.kotlinx.serialization.asConverterFactory
|
||||||
|
import calvin.erfmann.opentimetracker.data.ApiService
|
||||||
|
import kotlinx.serialization.json.Json
|
||||||
|
import okhttp3.MediaType.Companion.toMediaType
|
||||||
|
import okhttp3.OkHttpClient
|
||||||
|
import okhttp3.Interceptor
|
||||||
|
import kotlinx.coroutines.flow.first
|
||||||
|
import kotlinx.coroutines.runBlocking
|
||||||
|
import calvin.erfmann.opentimetracker.data.UserPreferences
|
||||||
|
import retrofit2.Retrofit
|
||||||
|
import java.util.concurrent.TimeUnit
|
||||||
|
import kotlinx.serialization.ExperimentalSerializationApi
|
||||||
|
import kotlinx.serialization.InternalSerializationApi
|
||||||
|
|
||||||
|
object NetworkModule {
|
||||||
|
|
||||||
|
private val json = Json {
|
||||||
|
ignoreUnknownKeys = true
|
||||||
|
isLenient = true
|
||||||
|
coerceInputValues = true
|
||||||
|
}
|
||||||
|
|
||||||
|
@OptIn(InternalSerializationApi::class, ExperimentalSerializationApi::class)
|
||||||
|
fun provideApiService(preferences: UserPreferences): ApiService {
|
||||||
|
val authInterceptor = Interceptor { chain ->
|
||||||
|
val token = runBlocking { preferences.authToken.first() }
|
||||||
|
val requestBuilder = chain.request().newBuilder()
|
||||||
|
if (token != null) {
|
||||||
|
requestBuilder.addHeader("Authorization", "Bearer $token")
|
||||||
|
}
|
||||||
|
chain.proceed(requestBuilder.build())
|
||||||
|
}
|
||||||
|
|
||||||
|
val client = OkHttpClient.Builder()
|
||||||
|
.addInterceptor(authInterceptor)
|
||||||
|
.connectTimeout(10, TimeUnit.SECONDS)
|
||||||
|
.build()
|
||||||
|
|
||||||
|
// Note: For dynamic Base URL changes in a real App, you'd reimplement this
|
||||||
|
// to rebuild Retrofit when prefs change, or use an OkHttp Interceptor to switch Host.
|
||||||
|
// For simplicity, we assume URL is set before Login and app restarts or re-initis logic.
|
||||||
|
val currentUrl = runBlocking { preferences.baseUrl.first() }
|
||||||
|
|
||||||
|
return Retrofit.Builder()
|
||||||
|
.baseUrl(currentUrl)
|
||||||
|
.client(client)
|
||||||
|
.addConverterFactory(json.asConverterFactory("application/json".toMediaType()))
|
||||||
|
.build()
|
||||||
|
.create(ApiService::class.java)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
package calvin.erfmann.opentimetracker.ui
|
||||||
|
|
||||||
|
import androidx.compose.runtime.mutableStateOf
|
||||||
|
import androidx.lifecycle.ViewModel
|
||||||
|
import androidx.lifecycle.viewModelScope
|
||||||
|
import calvin.erfmann.opentimetracker.data.LoginRequest
|
||||||
|
import calvin.erfmann.opentimetracker.data.UserPreferences
|
||||||
|
import calvin.erfmann.opentimetracker.di.NetworkModule
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
|
class AuthViewModel(private val prefs: UserPreferences) : ViewModel() {
|
||||||
|
var baseUrlInput = mutableStateOf(UserPreferences.DEFAULT_URL)
|
||||||
|
var username = mutableStateOf("")
|
||||||
|
var password = mutableStateOf("")
|
||||||
|
var isLoading = mutableStateOf(false)
|
||||||
|
var error = mutableStateOf<String?>(null)
|
||||||
|
var isLoggedIn = mutableStateOf(false)
|
||||||
|
|
||||||
|
init {
|
||||||
|
viewModelScope.launch {
|
||||||
|
prefs.baseUrl.collect { baseUrlInput.value = it }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun login() {
|
||||||
|
viewModelScope.launch {
|
||||||
|
try {
|
||||||
|
isLoading.value = true
|
||||||
|
error.value = null
|
||||||
|
// 1. Save URL first so NetworkModule picks it up
|
||||||
|
prefs.saveBaseUrl(baseUrlInput.value)
|
||||||
|
|
||||||
|
// 2. Create temp service
|
||||||
|
val api = NetworkModule.provideApiService(prefs)
|
||||||
|
|
||||||
|
// 3. Call Login
|
||||||
|
val response = api.login(LoginRequest(username.value, password.value))
|
||||||
|
prefs.saveToken(response.token)
|
||||||
|
isLoggedIn.value = true
|
||||||
|
} catch (e: Exception) {
|
||||||
|
error.value = "Login failed: ${e.message}"
|
||||||
|
} finally {
|
||||||
|
isLoading.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,87 @@
|
|||||||
|
package calvin.erfmann.opentimetracker.ui
|
||||||
|
|
||||||
|
import androidx.compose.runtime.mutableStateOf
|
||||||
|
import androidx.lifecycle.ViewModel
|
||||||
|
import androidx.lifecycle.viewModelScope
|
||||||
|
import calvin.erfmann.opentimetracker.data.ApiService
|
||||||
|
import calvin.erfmann.opentimetracker.data.StatusResponse
|
||||||
|
import kotlinx.coroutines.delay
|
||||||
|
import kotlinx.coroutines.isActive
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
import java.time.Duration
|
||||||
|
import java.time.Instant
|
||||||
|
|
||||||
|
class DashboardViewModel(private val api: ApiService) : ViewModel() {
|
||||||
|
|
||||||
|
var state = mutableStateOf<StatusResponse?>(null)
|
||||||
|
var elapsedTime = mutableStateOf("00:00:00")
|
||||||
|
|
||||||
|
init {
|
||||||
|
startPolling()
|
||||||
|
startLocalTimer()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun startPolling() {
|
||||||
|
viewModelScope.launch {
|
||||||
|
while (isActive) {
|
||||||
|
try {
|
||||||
|
val status = api.getStatus()
|
||||||
|
state.value = status
|
||||||
|
} catch (e: Exception) {
|
||||||
|
// Handle error (e.g., 401 -> Logout)
|
||||||
|
e.printStackTrace()
|
||||||
|
}
|
||||||
|
delay(3000) // Poll every 3 seconds
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun startLocalTimer() {
|
||||||
|
viewModelScope.launch {
|
||||||
|
while (isActive) {
|
||||||
|
state.value?.entry?.startTime?.let { isoTime ->
|
||||||
|
try {
|
||||||
|
// Assuming ISO format like "2023-10-27T10:00:00Z"
|
||||||
|
val start = Instant.parse(isoTime)
|
||||||
|
val now = Instant.now()
|
||||||
|
val seconds = Duration.between(start, now).seconds
|
||||||
|
if (seconds >= 0) {
|
||||||
|
val h = seconds / 3600
|
||||||
|
val m = (seconds % 3600) / 60
|
||||||
|
val s = seconds % 60
|
||||||
|
elapsedTime.value = String.format("%02d:%02d:%02d", h, m, s)
|
||||||
|
}
|
||||||
|
} catch (e: Exception) {
|
||||||
|
elapsedTime.value = "--:--"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
delay(1000)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun startActivity(activityId: String) {
|
||||||
|
viewModelScope.launch {
|
||||||
|
// Optimistic UI Update possible here
|
||||||
|
try {
|
||||||
|
api.startActivity(activityId)
|
||||||
|
// Polling will update the full state shortly
|
||||||
|
} catch (e: Exception) {
|
||||||
|
e.printStackTrace()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun stopActivity() {
|
||||||
|
viewModelScope.launch {
|
||||||
|
try {
|
||||||
|
api.stopActivity()
|
||||||
|
// Explicitly refresh state immediately for better UX
|
||||||
|
state.value = api.getStatus()
|
||||||
|
} catch (e: Exception) {
|
||||||
|
e.printStackTrace()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -2,4 +2,6 @@
|
|||||||
plugins {
|
plugins {
|
||||||
alias(libs.plugins.android.application) apply false
|
alias(libs.plugins.android.application) apply false
|
||||||
alias(libs.plugins.kotlin.android) apply false
|
alias(libs.plugins.kotlin.android) apply false
|
||||||
|
alias(libs.plugins.kotlin.compose)
|
||||||
|
kotlin("plugin.serialization") version "2.1.20"
|
||||||
}
|
}
|
||||||
@@ -8,6 +8,25 @@ espressoCore = "3.5.1"
|
|||||||
appcompat = "1.6.1"
|
appcompat = "1.6.1"
|
||||||
material = "1.10.0"
|
material = "1.10.0"
|
||||||
|
|
||||||
|
lifecycleRuntimeKtx = "2.6.1"
|
||||||
|
activityCompose = "1.8.0"
|
||||||
|
composeBom = "2024.04.01"
|
||||||
|
navigationRuntimeKtx = "2.8.8"
|
||||||
|
navigationCompose = "2.8.8"
|
||||||
|
places = "4.1.0"
|
||||||
|
okhttp = "4.12.0"
|
||||||
|
streamLog = "1.1.4"
|
||||||
|
landscapist = "2.4.6"
|
||||||
|
webrtc = "1.3.6"
|
||||||
|
kotlinxSerializationJson = "1.7.3"
|
||||||
|
ktlint = "0.43.0"
|
||||||
|
|
||||||
|
retrofit = "2.11.0"
|
||||||
|
retrofitResultAdapter = "1.0.10"
|
||||||
|
retrofitKotlinxSerializationJson = "1.0.0"
|
||||||
|
spotless = "6.7.0"
|
||||||
|
credentials = "1.5.0"
|
||||||
|
|
||||||
[libraries]
|
[libraries]
|
||||||
androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" }
|
androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" }
|
||||||
junit = { group = "junit", name = "junit", version.ref = "junit" }
|
junit = { group = "junit", name = "junit", version.ref = "junit" }
|
||||||
@@ -19,4 +38,4 @@ material = { group = "com.google.android.material", name = "material", version.r
|
|||||||
[plugins]
|
[plugins]
|
||||||
android-application = { id = "com.android.application", version.ref = "agp" }
|
android-application = { id = "com.android.application", version.ref = "agp" }
|
||||||
kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }
|
kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }
|
||||||
|
kotlin-compose = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "kotlin" }
|
||||||
|
|||||||
Reference in New Issue
Block a user