Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,11 @@ import androidx.compose.ui.unit.dp
import androidx.navigation.NavHostController
import androidx.navigation.compose.rememberNavController
import io.writeopia.account.ui.SettingsDialog
import io.writeopia.auth.core.di.AuthCoreInjectionNeo
import io.writeopia.common.utils.Destinations
import io.writeopia.common.utils.NotesNavigation
import io.writeopia.common.utils.NotesNavigationType
import io.writeopia.di.AppConnectionInjection
import io.writeopia.documents.graph.di.DocumentsGraphInjection
import io.writeopia.editor.di.EditorKmpInjector
import io.writeopia.features.search.di.KmpSearchInjection
Expand Down Expand Up @@ -81,6 +83,12 @@ fun DesktopApp(
WriteopiaDbInjector.initialize(writeopiaDb)
}

LaunchedEffect("JWTToken") {
AuthCoreInjectionNeo.singleton().provideAuthRepository().getAuthToken()?.let { token ->
AppConnectionInjection.singleton().setJwtToken(token)
}
}

val editorInjector = remember {
EditorKmpInjector.desktop(
selectionState = selectionState,
Expand Down Expand Up @@ -233,10 +241,16 @@ fun DesktopApp(
deleteModel = globalShellViewModel::deleteModel,
signIn = navigateToRegister,
resetPassword = navigateToResetPassword,
logout = globalShellViewModel::logout,
logout = {
globalShellViewModel.logout(sideEffect = navigateToRegister)
},
showDeleteConfirm = globalShellViewModel::showDeleteConfirm,
dismissDeleteConfirm = globalShellViewModel::dismissDeleteConfirm,
deleteAccount = globalShellViewModel::deleteAccount
deleteAccount = {
globalShellViewModel.deleteAccount(
sideEffect = navigateToRegister
)
}
)
}

Expand Down
1 change: 0 additions & 1 deletion application/composeApp/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@ kotlin {
implementation(project(":writeopia_models"))

implementation(project(":application:core:persistence_sqldelight"))
implementation(project(":application:core:theme"))
implementation(project(":application:core:utils"))
implementation(project(":application:core:navigation"))
implementation(project(":application:core:documents"))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material.CircularProgressIndicator
import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.collectAsState
Expand All @@ -24,11 +25,13 @@ import androidx.navigation.compose.rememberNavController
import io.github.kdroidfilter.platformtools.darkmodedetector.isSystemInDarkMode
import io.github.kdroidfilter.platformtools.darkmodedetector.windows.setWindowsAdaptiveTitleBar
import io.writeopia.auth.di.AuthInjection
import io.writeopia.auth.menu.AuthMenuViewModel
import io.writeopia.auth.navigation.authNavigation
import io.writeopia.common.utils.Destinations
import io.writeopia.common.utils.keyboard.KeyboardCommands
import io.writeopia.common.utils.keyboard.isMultiSelectionTrigger
import io.writeopia.common.utils.ui.GlobalToastBox
import io.writeopia.model.ColorThemeOption
import io.writeopia.model.isDarkTheme
import io.writeopia.notemenu.di.UiConfigurationInjector
import io.writeopia.notes.desktop.components.DesktopApp
Expand Down Expand Up @@ -210,6 +213,8 @@ private fun ApplicationScope.App(onCloseRequest: () -> Unit = ::exitApplication)
WriteopiaDbInjector.initialize(database)
WriteopiaConnectionInjector.setBaseUrl("http://localhost:8080")

val authInjection = AuthInjection()

val uiConfigurationInjector = UiConfigurationInjector.singleton()

val uiConfigurationViewModel = uiConfigurationInjector
Expand All @@ -230,13 +235,34 @@ private fun ApplicationScope.App(onCloseRequest: () -> Unit = ::exitApplication)
startDestination = Destinations.START_APP.id
) {
composable(route = Destinations.START_APP.id) {
val authMenuViewModel: AuthMenuViewModel =
authInjection.provideAuthMenuViewModel()

IntroScreen(colorTheme.value)

LaunchedEffect(Unit) {
authMenuViewModel.isLoggedIn().collect { loggedIn ->
delay(300)
navigationController.navigate(
if (loggedIn) {
Destinations.CHOOSE_NOTE.id
} else {
Destinations.AUTH_MENU_INNER_NAVIGATION.id
}
)
}
}
}

composable(route = Destinations.CHOOSE_NOTE.id) {
DesktopApp(
writeopiaDb = database,
selectionState = selectionState,
keyboardEventFlow = keyboardEventFlow.filterNotNull(),
coroutineScope = coroutineScope,
colorThemeOption = colorTheme,
selectColorTheme = uiConfigurationViewModel::changeColorTheme,
selectColorTheme =
uiConfigurationViewModel::changeColorTheme,
toggleMaxScreen = topDoubleBarClick,
navigateToRegister = {
navigationController.navigate(
Expand All @@ -253,10 +279,10 @@ private fun ApplicationScope.App(onCloseRequest: () -> Unit = ::exitApplication)

authNavigation(
navController = navigationController,
authInjection = AuthInjection(),
authInjection = authInjection,
colorThemeOption = colorTheme
) {
navigationController.navigate(Destinations.START_APP.id)
navigationController.navigate(Destinations.CHOOSE_NOTE.id)
}
}
}
Expand All @@ -277,3 +303,21 @@ private fun ScreenLoading() {
CircularProgressIndicator(modifier = Modifier.align(Alignment.Center))
}
}

@Composable
private fun IntroScreen(colorThemeOption: ColorThemeOption?) {
WrieopiaTheme(darkTheme = colorThemeOption.isDarkTheme()) {
Box(
modifier = Modifier
.fillMaxSize()
.background(
WriteopiaTheme.colorScheme.globalBackground
)
) {
CircularProgressIndicator(
modifier = Modifier.align(Alignment.Center),
color = MaterialTheme.colorScheme.onBackground
)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,7 @@ internal class SqlDelightRepository(
?.toModel()
?: WriteopiaUser.disconnectedUser()

override suspend fun isLoggedIn(): Boolean =
writeopiaDb?.writeopiaUserEntityQueries
?.selectCurrentUser()
?.executeAsOneOrNull()
?.toModel() == null
override suspend fun isLoggedIn(): Boolean = getAuthToken() != null

override suspend fun logout(): ResultData<Boolean> {
getUser().let { user ->
Expand All @@ -31,6 +27,7 @@ internal class SqlDelightRepository(
name = user.name,
email = user.email,
selected = 0,
tier = user.tier.name
)
}

Expand All @@ -44,6 +41,7 @@ internal class SqlDelightRepository(
name = user.name,
email = user.email,
selected = selected.toLong(),
tier = user.tier.tierName()
)
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
package io.writeopia.auth.core.utils

import io.writeopia.app.sql.Writeopia_user_entity
import io.writeopia.sdk.models.user.Tier
import io.writeopia.sdk.models.user.WriteopiaUser

fun Writeopia_user_entity.toModel(): WriteopiaUser {
return WriteopiaUser(
id = this.id,
email = this.email,
name = this.name,
tier = Tier.valueOf(this.tier)
)
}
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
package io.writeopia.di

import io.ktor.client.HttpClient
import io.ktor.client.plugins.DefaultRequest
import io.ktor.client.plugins.HttpTimeout
import io.ktor.client.plugins.contentnegotiation.ContentNegotiation
import io.ktor.client.plugins.logging.DEFAULT
import io.ktor.client.plugins.logging.LogLevel
import io.ktor.client.plugins.logging.Logger
import io.ktor.client.plugins.logging.Logging
import io.ktor.client.request.header
import io.ktor.http.HttpHeaders
import io.ktor.serialization.kotlinx.json.json
import kotlinx.serialization.json.Json
Expand All @@ -20,9 +22,17 @@ class AppConnectionInjection private constructor(
},
private val apiLogger: Logger = Logger.DEFAULT
) {
private var _tokenJwt: String? = null
private fun token() = _tokenJwt

fun setJwtToken(token: String) {
_tokenJwt = token
}

fun provideJson() = json

fun provideHttpClient(): HttpClient = ApiInjectorDefaults.httpClient(json, apiLogger)
fun provideHttpClient(): HttpClient =
ApiInjectorDefaults.httpClient(json, apiLogger, token() ?: "")

companion object {
private var instance: AppConnectionInjection? = null
Expand All @@ -37,12 +47,18 @@ object ApiInjectorDefaults {
fun httpClient(
json: Json,
apiLogger: Logger,
tokenJwt: String
) = HttpClient {
install(HttpTimeout) {
requestTimeoutMillis = 300000
socketTimeoutMillis = 300000
}

install(DefaultRequest) {
println("Bearer $tokenJwt")
header(HttpHeaders.Authorization, "Bearer $tokenJwt")
}

install(ContentNegotiation) {
json(json = json)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,14 @@ import io.writeopia.sdk.models.document.Document
import io.writeopia.sdk.serialization.data.DocumentApi
import io.writeopia.sdk.serialization.extensions.toApi
import io.writeopia.sdk.serialization.extensions.toModel
import io.writeopia.sdk.serialization.json.SendDocumentsRequest
import kotlinx.datetime.Instant

class DocumentsApi(private val client: HttpClient, private val baseUrl: String) {

suspend fun getNewDocuments(folderId: String, lastSync: Instant): ResultData<List<Document>> {
println("get new documents. $lastSync")

val response = client.post("$baseUrl/api/document/folder/diff") {
contentType(ContentType.Application.Json)
setBody(FolderDiffRequest(folderId, lastSync.toEpochMilliseconds()))
Expand All @@ -34,7 +37,7 @@ class DocumentsApi(private val client: HttpClient, private val baseUrl: String)
suspend fun sendDocuments(documents: List<Document>): ResultData<Unit> {
val response = client.post("$baseUrl/api/document") {
contentType(ContentType.Application.Json)
setBody(documents.map { it.toApi() })
setBody(SendDocumentsRequest(documents.map { it.toApi() }))
}

return if (response.status.isSuccess()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ CREATE TABLE writeopia_user_entity (
id TEXT PRIMARY KEY,
name TEXT NOT NULL,
email TEXT NOT NULL,
selected INTEGER NOT NULL
selected INTEGER NOT NULL,
tier TEXT NOT NULL
);

selectUserByEmail:
Expand All @@ -18,10 +19,10 @@ WHERE selected = 1
LIMIT 1;

insertUser:
INSERT INTO writeopia_user_entity(id, name, email, selected)
VALUES (?, ?, ?, ?)
INSERT INTO writeopia_user_entity(id, name, email, selected, tier)
VALUES (?, ?, ?, ?, ?)
ON CONFLICT(id) DO
UPDATE SET id=excluded.id, name=excluded.name, email=excluded.email, selected=excluded.selected;
UPDATE SET id=excluded.id, name=excluded.name, email=excluded.email, selected=excluded.selected, tier=excluded.tier;

deleteUser:
DELETE
Expand Down
1 change: 1 addition & 0 deletions application/features/auth/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ kotlin {
implementation(project(":writeopia_models"))
implementation(project(":application:core:utils"))
implementation(project(":application:core:navigation"))
implementation(project(":application:core:connection"))
implementation(project(":application:core:auth_core"))
implementation(project(":application:core:persistence_bridge"))
implementation(project(":application:core:theme"))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ class AuthInjection(
): ResetPasswordViewModel = viewModel { ResetPasswordViewModel(authApi, authRepository) }

@Composable
internal fun provideAuthMenuViewModel(
fun provideAuthMenuViewModel(
authManager: AuthRepository = authCoreInjection.provideAuthRepository(),
authApi: AuthApi = authCoreInjection.provideAuthApi()
): AuthMenuViewModel = viewModel { AuthMenuViewModel(authManager, authApi) }
Expand Down
Loading