Start saving data to proto datastore from successful rest api requests
This commit is contained in:
parent
78a4b75acd
commit
ece116a411
14 changed files with 131 additions and 59 deletions
|
@ -111,13 +111,13 @@ async fn register_new_user_request(
|
||||||
|
|
||||||
UserRegistrationResponse {
|
UserRegistrationResponse {
|
||||||
user_id,
|
user_id,
|
||||||
expires_at,
|
expires_at: None,
|
||||||
session_token: None,
|
session_token: None,
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
UserRegistrationResponse {
|
UserRegistrationResponse {
|
||||||
user_id,
|
user_id,
|
||||||
expires_at,
|
expires_at: Some(expires_at),
|
||||||
session_token: Some(verification_token),
|
session_token: Some(verification_token),
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -11,7 +11,7 @@ pub struct UserRegistrationResponse {
|
||||||
pub user_id: i32,
|
pub user_id: i32,
|
||||||
|
|
||||||
#[serde(serialize_with = "humantime_serde::serialize")]
|
#[serde(serialize_with = "humantime_serde::serialize")]
|
||||||
pub expires_at: SystemTime,
|
pub expires_at: Option<SystemTime>,
|
||||||
|
|
||||||
pub session_token: Option<String>,
|
pub session_token: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,7 @@ import androidx.datastore.core.DataStore
|
||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
import ing.bikeshedengineer.debtpirate.PrefsDataStore
|
import ing.bikeshedengineer.debtpirate.AppDataStore
|
||||||
import ing.bikeshedengineer.debtpirate.app.screen.auth.usecase.SubmitNewUserVerificationRequestUseCase
|
import ing.bikeshedengineer.debtpirate.app.screen.auth.usecase.SubmitNewUserVerificationRequestUseCase
|
||||||
import ing.bikeshedengineer.debtpirate.navigation.Navigator
|
import ing.bikeshedengineer.debtpirate.navigation.Navigator
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
|
@ -16,7 +16,7 @@ import javax.inject.Inject
|
||||||
@HiltViewModel
|
@HiltViewModel
|
||||||
class ConfirmationScreenViewModel @Inject constructor(
|
class ConfirmationScreenViewModel @Inject constructor(
|
||||||
private val navigator: Navigator,
|
private val navigator: Navigator,
|
||||||
private val prefsStore: DataStore<PrefsDataStore>,
|
private val prefsStore: DataStore<AppDataStore>,
|
||||||
private val verifyNewUser: SubmitNewUserVerificationRequestUseCase
|
private val verifyNewUser: SubmitNewUserVerificationRequestUseCase
|
||||||
) : ViewModel() {
|
) : ViewModel() {
|
||||||
private var _isLoading = MutableStateFlow(true)
|
private var _isLoading = MutableStateFlow(true)
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
package ing.bikeshedengineer.debtpirate.app.screen.auth.presentation.login
|
package ing.bikeshedengineer.debtpirate.app.screen.auth.presentation.login
|
||||||
|
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
import android.util.Log
|
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import androidx.activity.ComponentActivity
|
import androidx.activity.ComponentActivity
|
||||||
import androidx.compose.foundation.background
|
import androidx.compose.foundation.background
|
||||||
|
@ -76,8 +75,10 @@ fun LoginScreen(
|
||||||
val toastMessages = viewModel.toastMessages.collectAsState("")
|
val toastMessages = viewModel.toastMessages.collectAsState("")
|
||||||
LaunchedEffect(toastMessages.value) {
|
LaunchedEffect(toastMessages.value) {
|
||||||
val message = toastMessages.value
|
val message = toastMessages.value
|
||||||
Log.d("LoginScreen", message)
|
|
||||||
Toast.makeText(context, message, Toast.LENGTH_SHORT).show()
|
if (message.isNotEmpty()) {
|
||||||
|
Toast.makeText(context, message, Toast.LENGTH_SHORT).show()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Scaffold(
|
Scaffold(
|
||||||
|
|
|
@ -1,16 +1,13 @@
|
||||||
package ing.bikeshedengineer.debtpirate.app.screen.auth.presentation.login
|
package ing.bikeshedengineer.debtpirate.app.screen.auth.presentation.login
|
||||||
|
|
||||||
import android.util.Log
|
|
||||||
import android.widget.Toast
|
|
||||||
import androidx.datastore.core.DataStore
|
|
||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
import ing.bikeshedengineer.debtpirate.PrefsDataStore
|
|
||||||
import ing.bikeshedengineer.debtpirate.app.screen.auth.usecase.LoginCredentialsValidationResult
|
import ing.bikeshedengineer.debtpirate.app.screen.auth.usecase.LoginCredentialsValidationResult
|
||||||
import ing.bikeshedengineer.debtpirate.app.screen.auth.usecase.SubmitLoginCredentialsUseCase
|
import ing.bikeshedengineer.debtpirate.app.screen.auth.usecase.SubmitLoginCredentialsUseCase
|
||||||
import ing.bikeshedengineer.debtpirate.app.screen.auth.usecase.ValidateLoginCredentialsUseCase
|
import ing.bikeshedengineer.debtpirate.app.screen.auth.usecase.ValidateLoginCredentialsUseCase
|
||||||
import ing.bikeshedengineer.debtpirate.domain.model.Token
|
import ing.bikeshedengineer.debtpirate.domain.repository.InvalidCredentialsException
|
||||||
|
import ing.bikeshedengineer.debtpirate.domain.usecase.UpdateStoreDataUseCase
|
||||||
import ing.bikeshedengineer.debtpirate.navigation.Destination
|
import ing.bikeshedengineer.debtpirate.navigation.Destination
|
||||||
import ing.bikeshedengineer.debtpirate.navigation.Navigator
|
import ing.bikeshedengineer.debtpirate.navigation.Navigator
|
||||||
import kotlinx.coroutines.flow.MutableSharedFlow
|
import kotlinx.coroutines.flow.MutableSharedFlow
|
||||||
|
@ -37,13 +34,12 @@ enum class InvalidReason {
|
||||||
PasswordTooShort
|
PasswordTooShort
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@HiltViewModel
|
@HiltViewModel
|
||||||
class LoginScreenViewModel @Inject constructor(
|
class LoginScreenViewModel @Inject constructor(
|
||||||
private val navigator: Navigator,
|
private val navigator: Navigator,
|
||||||
private val prefsStore: DataStore<PrefsDataStore>,
|
|
||||||
private val submitLoginCredentials: SubmitLoginCredentialsUseCase,
|
private val submitLoginCredentials: SubmitLoginCredentialsUseCase,
|
||||||
private val validateLoginCredentials: ValidateLoginCredentialsUseCase,
|
private val validateLoginCredentials: ValidateLoginCredentialsUseCase,
|
||||||
|
private val updateStoreData: UpdateStoreDataUseCase
|
||||||
) : ViewModel() {
|
) : ViewModel() {
|
||||||
private val _emailAddress = MutableStateFlow("")
|
private val _emailAddress = MutableStateFlow("")
|
||||||
val emailAddress = _emailAddress.asStateFlow()
|
val emailAddress = _emailAddress.asStateFlow()
|
||||||
|
@ -93,28 +89,23 @@ class LoginScreenViewModel @Inject constructor(
|
||||||
|
|
||||||
private suspend fun onSubmitLoginRequest(emailAddress: String, password: String) {
|
private suspend fun onSubmitLoginRequest(emailAddress: String, password: String) {
|
||||||
try {
|
try {
|
||||||
val result = submitLoginCredentials(emailAddress, password)
|
val (userId, auth, session) = submitLoginCredentials(emailAddress, password)
|
||||||
|
updateStoreData(
|
||||||
|
userId = userId,
|
||||||
|
authToken = auth.token,
|
||||||
|
authTokenExpiresAt = auth.expiresAt,
|
||||||
|
sessionToken = session.token,
|
||||||
|
sessionTokenExpiresAt = session.expiresAt
|
||||||
|
)
|
||||||
} catch (err: Exception) {
|
} catch (err: Exception) {
|
||||||
_toastMessages.emit("Invalid Email Address or Password")
|
when (err) {
|
||||||
}
|
is InvalidCredentialsException -> {
|
||||||
}
|
_toastMessages.emit("Invalid Email Address or Password")
|
||||||
|
}
|
||||||
|
|
||||||
fun storeAuthData(userId: Int, sessionToken: Token, authToken: Token) {
|
else -> {
|
||||||
viewModelScope.launch {
|
_toastMessages.emit("Cannot Login, Please Try Again Later")
|
||||||
prefsStore.updateData { currentPrefs ->
|
}
|
||||||
val updatedSessionToken = currentPrefs.sessionToken.toBuilder()
|
|
||||||
.setToken(sessionToken.token)
|
|
||||||
.setExpiresAt(sessionToken.expiresAt.toEpochSecond())
|
|
||||||
|
|
||||||
val updatedAuthToken = currentPrefs.authToken.toBuilder()
|
|
||||||
.setToken(authToken.token)
|
|
||||||
.setExpiresAt(authToken.expiresAt.toEpochSecond())
|
|
||||||
|
|
||||||
currentPrefs.toBuilder()
|
|
||||||
.setUserId(userId)
|
|
||||||
.setSessionToken(updatedSessionToken)
|
|
||||||
.setAuthToken(updatedAuthToken)
|
|
||||||
.build()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,7 @@ import androidx.compose.foundation.layout.fillMaxSize
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.rememberScrollState
|
import androidx.compose.foundation.rememberScrollState
|
||||||
|
import androidx.compose.foundation.text.KeyboardActions
|
||||||
import androidx.compose.foundation.text.KeyboardOptions
|
import androidx.compose.foundation.text.KeyboardOptions
|
||||||
import androidx.compose.foundation.verticalScroll
|
import androidx.compose.foundation.verticalScroll
|
||||||
import androidx.compose.material.icons.Icons
|
import androidx.compose.material.icons.Icons
|
||||||
|
@ -231,9 +232,19 @@ private fun RegistrationComponent(
|
||||||
keyboardOptions = KeyboardOptions(
|
keyboardOptions = KeyboardOptions(
|
||||||
capitalization = KeyboardCapitalization.None,
|
capitalization = KeyboardCapitalization.None,
|
||||||
keyboardType = KeyboardType.Password,
|
keyboardType = KeyboardType.Password,
|
||||||
imeAction = ImeAction.Done
|
imeAction = ImeAction.Send
|
||||||
),
|
),
|
||||||
onValueChange = { viewModel.onAction(RegistrationScreenAction.UpdateConfirmPassword(it)) },
|
onValueChange = { viewModel.onAction(RegistrationScreenAction.UpdateConfirmPassword(it)) },
|
||||||
|
keyboardActions = KeyboardActions(
|
||||||
|
onSend = {
|
||||||
|
viewModel.registerNewAccount(
|
||||||
|
emailAddress.value,
|
||||||
|
name.value,
|
||||||
|
password.value,
|
||||||
|
confirmPassword.value
|
||||||
|
)
|
||||||
|
}
|
||||||
|
),
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.padding(PaddingValues(top = 4.dp))
|
.padding(PaddingValues(top = 4.dp))
|
||||||
|
|
|
@ -6,6 +6,7 @@ import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
import ing.bikeshedengineer.debtpirate.app.screen.auth.usecase.NewAccountRegistrationValidationResult
|
import ing.bikeshedengineer.debtpirate.app.screen.auth.usecase.NewAccountRegistrationValidationResult
|
||||||
import ing.bikeshedengineer.debtpirate.app.screen.auth.usecase.SubmitAccountRegistrationRequestUseCase
|
import ing.bikeshedengineer.debtpirate.app.screen.auth.usecase.SubmitAccountRegistrationRequestUseCase
|
||||||
import ing.bikeshedengineer.debtpirate.app.screen.auth.usecase.ValidateNewAccountRegistrationUseCase
|
import ing.bikeshedengineer.debtpirate.app.screen.auth.usecase.ValidateNewAccountRegistrationUseCase
|
||||||
|
import ing.bikeshedengineer.debtpirate.domain.usecase.UpdateStoreDataUseCase
|
||||||
import ing.bikeshedengineer.debtpirate.navigation.Destination
|
import ing.bikeshedengineer.debtpirate.navigation.Destination
|
||||||
import ing.bikeshedengineer.debtpirate.navigation.Navigator
|
import ing.bikeshedengineer.debtpirate.navigation.Navigator
|
||||||
import kotlinx.coroutines.flow.MutableSharedFlow
|
import kotlinx.coroutines.flow.MutableSharedFlow
|
||||||
|
@ -21,6 +22,7 @@ class RegistrationScreenViewModel @Inject constructor(
|
||||||
private val navigator: Navigator,
|
private val navigator: Navigator,
|
||||||
private val validateNewAccount: ValidateNewAccountRegistrationUseCase,
|
private val validateNewAccount: ValidateNewAccountRegistrationUseCase,
|
||||||
private val submitAccountRegistrationRequest: SubmitAccountRegistrationRequestUseCase,
|
private val submitAccountRegistrationRequest: SubmitAccountRegistrationRequestUseCase,
|
||||||
|
private val updateStoreData: UpdateStoreDataUseCase,
|
||||||
) : ViewModel() {
|
) : ViewModel() {
|
||||||
fun navigateUp() {
|
fun navigateUp() {
|
||||||
viewModelScope.launch {
|
viewModelScope.launch {
|
||||||
|
@ -113,10 +115,17 @@ class RegistrationScreenViewModel @Inject constructor(
|
||||||
if (fieldsAreValid) {
|
if (fieldsAreValid) {
|
||||||
viewModelScope.launch {
|
viewModelScope.launch {
|
||||||
try {
|
try {
|
||||||
// TODO: Store the registration result data in the store
|
|
||||||
val result =
|
val result =
|
||||||
submitAccountRegistrationRequest(emailAddress, name, confirmPassword)
|
submitAccountRegistrationRequest(emailAddress, name, confirmPassword)
|
||||||
|
|
||||||
|
val (userId, expiresAt, sessionToken) = result
|
||||||
|
|
||||||
|
updateStoreData(
|
||||||
|
userId = result.userId,
|
||||||
|
sessionToken = sessionToken,
|
||||||
|
sessionTokenExpiresAt = expiresAt
|
||||||
|
)
|
||||||
|
|
||||||
_onRegistrationComplete.emit(Pair(emailAddress, confirmPassword))
|
_onRegistrationComplete.emit(Pair(emailAddress, confirmPassword))
|
||||||
} catch (err: Throwable) {
|
} catch (err: Throwable) {
|
||||||
// TODO...
|
// TODO...
|
||||||
|
|
|
@ -6,26 +6,26 @@ import androidx.datastore.core.DataStore
|
||||||
import androidx.datastore.core.Serializer
|
import androidx.datastore.core.Serializer
|
||||||
import androidx.datastore.dataStore
|
import androidx.datastore.dataStore
|
||||||
import com.google.protobuf.InvalidProtocolBufferException
|
import com.google.protobuf.InvalidProtocolBufferException
|
||||||
import ing.bikeshedengineer.debtpirate.PrefsDataStore
|
import ing.bikeshedengineer.debtpirate.AppDataStore
|
||||||
import java.io.InputStream
|
import java.io.InputStream
|
||||||
import java.io.OutputStream
|
import java.io.OutputStream
|
||||||
|
|
||||||
object PrefsDataStoreSerializer : Serializer<PrefsDataStore> {
|
object PrefsDataStoreSerializer : Serializer<AppDataStore> {
|
||||||
override val defaultValue: PrefsDataStore
|
override val defaultValue: AppDataStore
|
||||||
get() = PrefsDataStore.getDefaultInstance()
|
get() = AppDataStore.getDefaultInstance()
|
||||||
|
|
||||||
override suspend fun readFrom(input: InputStream): PrefsDataStore {
|
override suspend fun readFrom(input: InputStream): AppDataStore {
|
||||||
try {
|
try {
|
||||||
return PrefsDataStore.parseFrom(input)
|
return AppDataStore.parseFrom(input)
|
||||||
} catch (exception: InvalidProtocolBufferException) {
|
} catch (exception: InvalidProtocolBufferException) {
|
||||||
throw CorruptionException("Cannot read proto file.", exception)
|
throw CorruptionException("Cannot read proto file.", exception)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun writeTo(t: PrefsDataStore, output: OutputStream) = t.writeTo(output)
|
override suspend fun writeTo(t: AppDataStore, output: OutputStream) = t.writeTo(output)
|
||||||
}
|
}
|
||||||
|
|
||||||
val Context.prefsDataStore: DataStore<PrefsDataStore> by dataStore(
|
val Context.appDataStore: DataStore<AppDataStore> by dataStore(
|
||||||
fileName = "prefs_data_store.proto",
|
fileName = "app_data_store.proto",
|
||||||
serializer = PrefsDataStoreSerializer
|
serializer = PrefsDataStoreSerializer
|
||||||
)
|
)
|
|
@ -1,9 +1,16 @@
|
||||||
package ing.bikeshedengineer.debtpirate.data.remote.model.auth
|
package ing.bikeshedengineer.debtpirate.data.remote.model.auth
|
||||||
|
|
||||||
|
import com.google.gson.annotations.JsonAdapter
|
||||||
|
import ing.bikeshedengineer.debtpirate.domain.adapter.OffsetDateTimeAdapter
|
||||||
|
import java.time.OffsetDateTime
|
||||||
|
|
||||||
data class AuthLoginPostResponse(
|
data class AuthLoginPostResponse(
|
||||||
val userId: Int,
|
val userId: Int,
|
||||||
|
val auth: AuthLoginPostResponseTokenData,
|
||||||
val session: AuthLoginPostResponseTokenData,
|
val session: AuthLoginPostResponseTokenData,
|
||||||
val auth: AuthLoginPostResponseTokenData
|
|
||||||
)
|
)
|
||||||
|
|
||||||
data class AuthLoginPostResponseTokenData(val token: String, val expiresAt: String)
|
data class AuthLoginPostResponseTokenData(
|
||||||
|
val token: String,
|
||||||
|
@JsonAdapter(OffsetDateTimeAdapter::class) val expiresAt: OffsetDateTime
|
||||||
|
)
|
|
@ -7,6 +7,6 @@ import java.time.OffsetDateTime
|
||||||
data class UserCreatePostResponse(
|
data class UserCreatePostResponse(
|
||||||
val userId: Int,
|
val userId: Int,
|
||||||
@JsonAdapter(OffsetDateTimeAdapter::class)
|
@JsonAdapter(OffsetDateTimeAdapter::class)
|
||||||
val expiresAt: OffsetDateTime,
|
val expiresAt: OffsetDateTime? = null,
|
||||||
val sessionToken: String? = null
|
val sessionToken: String? = null
|
||||||
)
|
)
|
|
@ -6,17 +6,17 @@ import dagger.Module
|
||||||
import dagger.Provides
|
import dagger.Provides
|
||||||
import dagger.hilt.InstallIn
|
import dagger.hilt.InstallIn
|
||||||
import dagger.hilt.components.SingletonComponent
|
import dagger.hilt.components.SingletonComponent
|
||||||
import ing.bikeshedengineer.debtpirate.PrefsDataStore
|
import ing.bikeshedengineer.debtpirate.AppDataStore
|
||||||
import ing.bikeshedengineer.debtpirate.data.pref.prefsDataStore
|
import ing.bikeshedengineer.debtpirate.data.pref.appDataStore
|
||||||
import javax.inject.Singleton
|
import javax.inject.Singleton
|
||||||
|
|
||||||
@Module
|
@Module
|
||||||
@InstallIn(SingletonComponent::class)
|
@InstallIn(SingletonComponent::class)
|
||||||
object PrefsDataStoreProvider {
|
object AppDataStoreProvider {
|
||||||
|
|
||||||
@Provides
|
@Provides
|
||||||
@Singleton
|
@Singleton
|
||||||
fun providePrefsDataStore(application: Application): DataStore<PrefsDataStore> {
|
fun provideAppDataStore(application: Application): DataStore<AppDataStore> {
|
||||||
return application.prefsDataStore
|
return application.appDataStore
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
package ing.bikeshedengineer.debtpirate.di
|
||||||
|
|
||||||
|
import androidx.datastore.core.DataStore
|
||||||
|
import dagger.Module
|
||||||
|
import dagger.Provides
|
||||||
|
import dagger.hilt.InstallIn
|
||||||
|
import dagger.hilt.components.SingletonComponent
|
||||||
|
import ing.bikeshedengineer.debtpirate.AppDataStore
|
||||||
|
import ing.bikeshedengineer.debtpirate.domain.usecase.UpdateStoreDataUseCase
|
||||||
|
import javax.inject.Singleton
|
||||||
|
|
||||||
|
@Module
|
||||||
|
@InstallIn(SingletonComponent::class)
|
||||||
|
object UseCaseModule {
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
@Singleton
|
||||||
|
fun provideUpdateStoreDataUseCase(store: DataStore<AppDataStore>) = UpdateStoreDataUseCase(store)
|
||||||
|
}
|
|
@ -0,0 +1,35 @@
|
||||||
|
package ing.bikeshedengineer.debtpirate.domain.usecase
|
||||||
|
|
||||||
|
import androidx.datastore.core.DataStore
|
||||||
|
import ing.bikeshedengineer.debtpirate.AppDataStore
|
||||||
|
import java.time.OffsetDateTime
|
||||||
|
|
||||||
|
class UpdateStoreDataUseCase(val store: DataStore<AppDataStore>) {
|
||||||
|
suspend operator fun invoke(
|
||||||
|
userId: Int? = null,
|
||||||
|
authToken: String? = null,
|
||||||
|
authTokenExpiresAt: OffsetDateTime? = null,
|
||||||
|
sessionToken: String? = null,
|
||||||
|
sessionTokenExpiresAt: OffsetDateTime? = null
|
||||||
|
) {
|
||||||
|
store.updateData { currentStore ->
|
||||||
|
currentStore.toBuilder().apply {
|
||||||
|
if (userId != null) {
|
||||||
|
this.setUserId(userId)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (authToken != null && authTokenExpiresAt != null) {
|
||||||
|
this.authToken.toBuilder().setToken(authToken).setExpiresAt(authTokenExpiresAt.toEpochSecond())
|
||||||
|
.build()
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sessionToken != null && sessionTokenExpiresAt != null) {
|
||||||
|
this.sessionToken.toBuilder().setToken(sessionToken)
|
||||||
|
.setExpiresAt(sessionTokenExpiresAt.toEpochSecond()).build()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.build()
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -8,9 +8,8 @@ message Token {
|
||||||
int64 expires_at = 2;
|
int64 expires_at = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
message PrefsDataStore {
|
message AppDataStore {
|
||||||
string current_route = 1;
|
int32 user_id = 1;
|
||||||
int32 user_id = 2;
|
Token auth_token = 2;
|
||||||
Token auth_token = 3;
|
Token session_token = 3;
|
||||||
Token session_token = 4;
|
|
||||||
}
|
}
|
Loading…
Add table
Reference in a new issue