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 {
|
||||
alias(libs.plugins.android.application)
|
||||
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 {
|
||||
@@ -33,6 +39,10 @@ android {
|
||||
kotlinOptions {
|
||||
jvmTarget = "11"
|
||||
}
|
||||
|
||||
buildFeatures {
|
||||
compose = true
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
@@ -43,4 +53,22 @@ dependencies {
|
||||
testImplementation(libs.junit)
|
||||
androidTestImplementation(libs.androidx.junit)
|
||||
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"
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
|
||||
<application
|
||||
android:allowBackup="true"
|
||||
android:dataExtractionRules="@xml/data_extraction_rules"
|
||||
@@ -11,6 +13,19 @@
|
||||
android:roundIcon="@mipmap/ic_launcher_round"
|
||||
android:supportsRtl="true"
|
||||
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>
|
||||
@@ -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 {
|
||||
alias(libs.plugins.android.application) 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"
|
||||
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]
|
||||
androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" }
|
||||
junit = { group = "junit", name = "junit", version.ref = "junit" }
|
||||
@@ -19,4 +38,4 @@ material = { group = "com.google.android.material", name = "material", version.r
|
||||
[plugins]
|
||||
android-application = { id = "com.android.application", version.ref = "agp" }
|
||||
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