Remove the authentication requirment to read the spreadsheets.
This commit is contained in:
parent
b6c7009697
commit
c82ea04375
16 changed files with 86 additions and 95 deletions
|
|
@ -7,7 +7,7 @@
|
|||
"client": [
|
||||
{
|
||||
"client_info": {
|
||||
"mobilesdk_app_id": "1:62913404482:android:25aff6034a72116b7c57db",
|
||||
"mobilesdk_app_id": "1:62913404482:android:c504d0b32647de717c57db",
|
||||
"android_client_info": {
|
||||
"package_name": "com.pixelized.rplexicon"
|
||||
}
|
||||
|
|
@ -20,15 +20,11 @@
|
|||
"package_name": "com.pixelized.rplexicon",
|
||||
"certificate_hash": "39ee1766d2225263052d4a4e82182d1c3e886f35"
|
||||
}
|
||||
},
|
||||
{
|
||||
"client_id": "62913404482-ergqkjiuvint49q8lm555j21vvb6af7s.apps.googleusercontent.com",
|
||||
"client_type": 3
|
||||
}
|
||||
],
|
||||
"api_key": [
|
||||
{
|
||||
"current_key": "AIzaSyB2Gkrisrjk1s-5U1ufXGambFRBbFFfLuo"
|
||||
"current_key": "AIzaSyAsRKJD63wwyr8x_l-n7Hv5T7GZ2M8AT-Q"
|
||||
}
|
||||
],
|
||||
"services": {
|
||||
|
|
@ -44,7 +40,7 @@
|
|||
},
|
||||
{
|
||||
"client_info": {
|
||||
"mobilesdk_app_id": "1:62913404482:android:8d40bf56f21618e27c57db",
|
||||
"mobilesdk_app_id": "1:62913404482:android:4de84922f319d24d7c57db",
|
||||
"android_client_info": {
|
||||
"package_name": "com.pixelized.rplexicon.dev"
|
||||
}
|
||||
|
|
@ -57,15 +53,11 @@
|
|||
"package_name": "com.pixelized.rplexicon.dev",
|
||||
"certificate_hash": "b5bd860f1f89de118613c3e94b3f6c8cbd6d876a"
|
||||
}
|
||||
},
|
||||
{
|
||||
"client_id": "62913404482-ergqkjiuvint49q8lm555j21vvb6af7s.apps.googleusercontent.com",
|
||||
"client_type": 3
|
||||
}
|
||||
],
|
||||
"api_key": [
|
||||
{
|
||||
"current_key": "AIzaSyB2Gkrisrjk1s-5U1ufXGambFRBbFFfLuo"
|
||||
"current_key": "AIzaSyAsRKJD63wwyr8x_l-n7Hv5T7GZ2M8AT-Q"
|
||||
}
|
||||
],
|
||||
"services": {
|
||||
|
|
|
|||
|
|
@ -1,12 +1,11 @@
|
|||
package com.pixelized.rplexicon.repository
|
||||
|
||||
import androidx.compose.runtime.derivedStateOf
|
||||
import androidx.compose.runtime.getValue
|
||||
import android.app.Application
|
||||
import com.google.api.client.extensions.android.http.AndroidHttp
|
||||
import com.google.api.client.http.HttpRequest
|
||||
import com.google.api.client.json.gson.GsonFactory
|
||||
import com.google.api.services.sheets.v4.Sheets
|
||||
import com.pixelized.rplexicon.repository.authentication.AuthenticationRepository
|
||||
import com.pixelized.rplexicon.utilitary.exceptions.ServiceNotReady
|
||||
import com.pixelized.rplexicon.R
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.withContext
|
||||
|
|
@ -15,31 +14,27 @@ import javax.inject.Singleton
|
|||
|
||||
@Singleton
|
||||
class GoogleSheetServiceRepository @Inject constructor(
|
||||
authenticationRepository: AuthenticationRepository,
|
||||
application: Application,
|
||||
) {
|
||||
private val service: Sheets? by derivedStateOf {
|
||||
when (authenticationRepository.isAuthenticated.value) {
|
||||
true -> Sheets
|
||||
private val service: Sheets = Sheets
|
||||
.Builder(
|
||||
AndroidHttp.newCompatibleTransport(),
|
||||
GsonFactory(),
|
||||
authenticationRepository.credential,
|
||||
) { request: HttpRequest? ->
|
||||
request?.url?.set(
|
||||
API_PARAM_KEY,
|
||||
application.getString(R.string.google_spreadsheet_api_key)
|
||||
)
|
||||
}
|
||||
.build()
|
||||
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
|
||||
@Throws(ServiceNotReady::class)
|
||||
suspend fun fetch(
|
||||
lambda: suspend CoroutineScope.(service: Sheets.Spreadsheets.Values) -> Unit,
|
||||
) {
|
||||
when (val service = service) {
|
||||
null -> throw ServiceNotReady()
|
||||
else -> withContext(Dispatchers.IO) {
|
||||
): Unit = withContext(Dispatchers.IO) {
|
||||
lambda(service.spreadsheets().values())
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val API_PARAM_KEY = "key"
|
||||
}
|
||||
}
|
||||
|
|
@ -4,7 +4,6 @@ import com.pixelized.rplexicon.repository.parser.AttackParser
|
|||
import com.pixelized.rplexicon.model.Attack
|
||||
import com.pixelized.rplexicon.repository.GoogleSheetServiceRepository
|
||||
import com.pixelized.rplexicon.utilitary.exceptions.IncompatibleSheetStructure
|
||||
import com.pixelized.rplexicon.utilitary.exceptions.ServiceNotReady
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import javax.inject.Inject
|
||||
|
|
@ -23,7 +22,7 @@ class ActionRepository @Inject constructor(
|
|||
return name?.let { _data.value[it] }
|
||||
}
|
||||
|
||||
@Throws(ServiceNotReady::class, IncompatibleSheetStructure::class, Exception::class)
|
||||
@Throws(IncompatibleSheetStructure::class, Exception::class)
|
||||
suspend fun fetchActions() {
|
||||
googleRepository.fetch { sheet ->
|
||||
val request = sheet.get(Sheet.Character.ID, Sheet.Character.ATTACK)
|
||||
|
|
|
|||
|
|
@ -8,7 +8,6 @@ import com.pixelized.rplexicon.model.Counter
|
|||
import com.pixelized.rplexicon.model.Property
|
||||
import com.pixelized.rplexicon.repository.GoogleSheetServiceRepository
|
||||
import com.pixelized.rplexicon.utilitary.exceptions.IncompatibleSheetStructure
|
||||
import com.pixelized.rplexicon.utilitary.exceptions.ServiceNotReady
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import javax.inject.Inject
|
||||
|
|
@ -44,7 +43,7 @@ class AlterationRepository @Inject constructor(
|
|||
return name?.let { counter.value[it] }
|
||||
}
|
||||
|
||||
@Throws(ServiceNotReady::class, IncompatibleSheetStructure::class, Exception::class)
|
||||
@Throws(IncompatibleSheetStructure::class, Exception::class)
|
||||
suspend fun fetchAlterationSheet() {
|
||||
googleRepository.fetch { sheet ->
|
||||
val request = sheet.get(Sheet.Character.ID, Sheet.Character.ALTERATION)
|
||||
|
|
@ -53,7 +52,7 @@ class AlterationRepository @Inject constructor(
|
|||
}
|
||||
}
|
||||
|
||||
@Throws(ServiceNotReady::class, IncompatibleSheetStructure::class, Exception::class)
|
||||
@Throws(IncompatibleSheetStructure::class, Exception::class)
|
||||
suspend fun fetchStatusSheet() {
|
||||
googleRepository.fetch { sheet ->
|
||||
val request = sheet.get(Sheet.Character.ID, Sheet.Character.STATUS)
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@ import com.pixelized.rplexicon.repository.parser.CharacterSheetParser
|
|||
import com.pixelized.rplexicon.model.CharacterSheet
|
||||
import com.pixelized.rplexicon.repository.GoogleSheetServiceRepository
|
||||
import com.pixelized.rplexicon.utilitary.exceptions.IncompatibleSheetStructure
|
||||
import com.pixelized.rplexicon.utilitary.exceptions.ServiceNotReady
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import javax.inject.Inject
|
||||
|
|
@ -22,7 +21,7 @@ class CharacterSheetRepository @Inject constructor(
|
|||
return name?.let { _data.value[name] }
|
||||
}
|
||||
|
||||
@Throws(ServiceNotReady::class, IncompatibleSheetStructure::class, Exception::class)
|
||||
@Throws(IncompatibleSheetStructure::class, Exception::class)
|
||||
suspend fun fetchCharacterSheet() {
|
||||
googleRepository.fetch { sheet ->
|
||||
val request = sheet.get(Sheet.Character.ID, Sheet.Character.CHARACTER)
|
||||
|
|
@ -30,8 +29,4 @@ class CharacterSheetRepository @Inject constructor(
|
|||
_data.emit(data)
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val TAG = "CharacterSheetRepository"
|
||||
}
|
||||
}
|
||||
|
|
@ -4,7 +4,6 @@ import com.pixelized.rplexicon.repository.parser.LexiconParser
|
|||
import com.pixelized.rplexicon.model.Lexicon
|
||||
import com.pixelized.rplexicon.repository.GoogleSheetServiceRepository
|
||||
import com.pixelized.rplexicon.utilitary.exceptions.IncompatibleSheetStructure
|
||||
import com.pixelized.rplexicon.utilitary.exceptions.ServiceNotReady
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import javax.inject.Inject
|
||||
|
|
@ -22,7 +21,7 @@ class LexiconRepository @Inject constructor(
|
|||
return name?.let { _data.value.firstOrNull { item -> item.name == it }?.id }
|
||||
}
|
||||
|
||||
@Throws(ServiceNotReady::class, IncompatibleSheetStructure::class, Exception::class)
|
||||
@Throws(IncompatibleSheetStructure::class, Exception::class)
|
||||
suspend fun fetchLexicon() {
|
||||
googleRepository.fetch { sheet ->
|
||||
val request = sheet.get(Sheet.Lexicon.ID, Sheet.Lexicon.LEXICON)
|
||||
|
|
@ -30,9 +29,4 @@ class LexiconRepository @Inject constructor(
|
|||
_data.tryEmit(data)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
companion object {
|
||||
const val TAG = "LexiconRepository"
|
||||
}
|
||||
}
|
||||
|
|
@ -6,7 +6,6 @@ import com.pixelized.rplexicon.repository.parser.MarqueeParser
|
|||
import com.pixelized.rplexicon.model.Location
|
||||
import com.pixelized.rplexicon.repository.GoogleSheetServiceRepository
|
||||
import com.pixelized.rplexicon.utilitary.exceptions.IncompatibleSheetStructure
|
||||
import com.pixelized.rplexicon.utilitary.exceptions.ServiceNotReady
|
||||
import kotlinx.coroutines.async
|
||||
import kotlinx.coroutines.awaitAll
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
|
|
@ -27,7 +26,7 @@ class LocationRepository @Inject constructor(
|
|||
return name?.let { _data.value.firstOrNull { item -> item.name == it }?.id }
|
||||
}
|
||||
|
||||
@Throws(ServiceNotReady::class, IncompatibleSheetStructure::class, Exception::class)
|
||||
@Throws(IncompatibleSheetStructure::class, Exception::class)
|
||||
suspend fun fetchLocation() {
|
||||
googleRepository.fetch { sheet ->
|
||||
val (map, marquee) = awaitAll(
|
||||
|
|
@ -59,7 +58,6 @@ class LocationRepository @Inject constructor(
|
|||
}
|
||||
|
||||
companion object {
|
||||
private const val TAG = "LocationRepository"
|
||||
const val SHEET_URL =
|
||||
"https://docs.google.com/spreadsheets/d/${Sheet.Lexicon.ID}/edit#gid=1985553511"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@ import com.pixelized.rplexicon.repository.parser.QuestParser
|
|||
import com.pixelized.rplexicon.model.Quest
|
||||
import com.pixelized.rplexicon.repository.GoogleSheetServiceRepository
|
||||
import com.pixelized.rplexicon.utilitary.exceptions.IncompatibleSheetStructure
|
||||
import com.pixelized.rplexicon.utilitary.exceptions.ServiceNotReady
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import javax.inject.Inject
|
||||
|
|
@ -19,7 +18,7 @@ class QuestRepository @Inject constructor(
|
|||
private val _data = MutableStateFlow<List<Quest>>(emptyList())
|
||||
val data: StateFlow<List<Quest>> get() = _data
|
||||
|
||||
@Throws(ServiceNotReady::class, IncompatibleSheetStructure::class, Exception::class)
|
||||
@Throws(IncompatibleSheetStructure::class, Exception::class)
|
||||
suspend fun fetchQuests() {
|
||||
googleRepository.fetch { sheet ->
|
||||
val request = sheet.get(Sheet.Lexicon.ID, Sheet.Lexicon.QUEST_JOURNAL)
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@ import com.pixelized.rplexicon.model.AssignedSpell
|
|||
import com.pixelized.rplexicon.model.Spell
|
||||
import com.pixelized.rplexicon.repository.GoogleSheetServiceRepository
|
||||
import com.pixelized.rplexicon.utilitary.exceptions.IncompatibleSheetStructure
|
||||
import com.pixelized.rplexicon.utilitary.exceptions.ServiceNotReady
|
||||
import kotlinx.coroutines.async
|
||||
import kotlinx.coroutines.awaitAll
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
|
|
@ -32,7 +31,7 @@ class SpellRepository @Inject constructor(
|
|||
return character?.let { _spells.value[it]?.find { assigned -> assigned.spell.name == spell } }
|
||||
}
|
||||
|
||||
@Throws(ServiceNotReady::class, IncompatibleSheetStructure::class, Exception::class)
|
||||
@Throws(IncompatibleSheetStructure::class, Exception::class)
|
||||
suspend fun fetchSpells() {
|
||||
googleRepository.fetch { sheet ->
|
||||
val (lexicon, magic) = awaitAll(
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ import androidx.navigation.NavOptionsBuilder
|
|||
import androidx.navigation.compose.NavHost
|
||||
import androidx.navigation.compose.rememberNavController
|
||||
import com.pixelized.rplexicon.ui.navigation.screens.AUTHENTICATION_ROUTE
|
||||
import com.pixelized.rplexicon.ui.navigation.screens.HOME_ROUTE
|
||||
import com.pixelized.rplexicon.ui.navigation.screens.composableAuthentication
|
||||
import com.pixelized.rplexicon.ui.navigation.screens.composableCharacterSheet
|
||||
import com.pixelized.rplexicon.ui.navigation.screens.composableHome
|
||||
|
|
@ -26,7 +27,7 @@ val LocalScreenNavHost = staticCompositionLocalOf<NavHostController> {
|
|||
@Composable
|
||||
fun ScreenNavHost(
|
||||
navHostController: NavHostController = rememberNavController(),
|
||||
startDestination: String = AUTHENTICATION_ROUTE,
|
||||
startDestination: String = HOME_ROUTE,
|
||||
) {
|
||||
val lexiconListState = rememberLazyListState()
|
||||
val questListState = rememberLazyListState()
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ import androidx.compose.material3.Surface
|
|||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.Stable
|
||||
import androidx.compose.runtime.State
|
||||
import androidx.compose.runtime.derivedStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
|
|
@ -37,6 +38,7 @@ import androidx.compose.ui.graphics.Brush
|
|||
import androidx.compose.ui.graphics.ColorFilter
|
||||
import androidx.compose.ui.graphics.ColorMatrix
|
||||
import androidx.compose.ui.layout.ContentScale
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.AnnotatedString
|
||||
|
|
@ -49,10 +51,10 @@ import androidx.compose.ui.unit.Dp
|
|||
import androidx.compose.ui.unit.dp
|
||||
import androidx.hilt.navigation.compose.hiltViewModel
|
||||
import com.pixelized.rplexicon.LocalActivity
|
||||
import com.pixelized.rplexicon.LocalSnack
|
||||
import com.pixelized.rplexicon.R
|
||||
import com.pixelized.rplexicon.ui.navigation.LocalScreenNavHost
|
||||
import com.pixelized.rplexicon.ui.navigation.rootOption
|
||||
import com.pixelized.rplexicon.ui.navigation.screens.navigateToCharacterSheet
|
||||
import com.pixelized.rplexicon.ui.navigation.screens.navigateToHome
|
||||
import com.pixelized.rplexicon.ui.theme.LexiconTheme
|
||||
import com.pixelized.rplexicon.ui.theme.colors.GoogleColorPalette
|
||||
|
|
@ -63,13 +65,27 @@ import kotlin.math.max
|
|||
import kotlin.math.min
|
||||
import kotlin.math.pow
|
||||
|
||||
@Stable
|
||||
sealed class AuthenticationStateUio {
|
||||
@Stable
|
||||
data object Initial : AuthenticationStateUio()
|
||||
|
||||
@Stable
|
||||
data object Success : AuthenticationStateUio()
|
||||
|
||||
@Stable
|
||||
data class Failure(val exception: Exception?) : AuthenticationStateUio()
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun AuthenticationScreen(
|
||||
authenticationVM: AuthenticationViewModel = hiltViewModel(),
|
||||
versionVM: VersionViewModel = hiltViewModel(),
|
||||
) {
|
||||
val screen = LocalScreenNavHost.current
|
||||
val snack = LocalSnack.current
|
||||
val context = LocalContext.current
|
||||
val activity = LocalActivity.current
|
||||
val screen = LocalScreenNavHost.current
|
||||
val state = authenticationVM.rememberAuthenticationState()
|
||||
|
||||
Surface {
|
||||
|
|
@ -91,18 +107,33 @@ fun AuthenticationScreen(
|
|||
onSignIn = {
|
||||
screen.navigateToHome(option = rootOption())
|
||||
},
|
||||
onSignInError = {
|
||||
snack.showSnackbar(
|
||||
message = it?.message ?: context.getString(R.string.error_generic)
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun HandleAuthenticationState(
|
||||
state: State<AuthenticationViewModel.Authentication>,
|
||||
onSignIn: suspend CoroutineScope.() -> Unit
|
||||
state: State<AuthenticationStateUio>,
|
||||
onSignIn: suspend CoroutineScope.() -> Unit,
|
||||
onSignInError: suspend CoroutineScope.(exception: Exception?) -> Unit,
|
||||
) {
|
||||
if (state.value == AuthenticationViewModel.Authentication.Success) {
|
||||
when (val dummy = state.value) {
|
||||
AuthenticationStateUio.Initial -> Unit
|
||||
is AuthenticationStateUio.Success -> {
|
||||
LaunchedEffect(key1 = "Authentication.Success", block = onSignIn)
|
||||
}
|
||||
|
||||
is AuthenticationStateUio.Failure -> {
|
||||
LaunchedEffect(key1 = "Authentication.Error") {
|
||||
onSignInError(dummy.exception)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
|
|
|
|||
|
|
@ -10,7 +10,6 @@ import androidx.activity.result.ActivityResult
|
|||
import androidx.activity.result.IntentSenderRequest
|
||||
import androidx.activity.result.contract.ActivityResultContracts
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.Stable
|
||||
import androidx.compose.runtime.State
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.lifecycle.AndroidViewModel
|
||||
|
|
@ -33,13 +32,13 @@ class AuthenticationViewModel @Inject constructor(
|
|||
|
||||
private val state = mutableStateOf(
|
||||
when (repository.isAuthenticated.value) {
|
||||
true -> Authentication.Success
|
||||
else -> Authentication.Initial
|
||||
true -> AuthenticationStateUio.Success
|
||||
else -> AuthenticationStateUio.Initial
|
||||
}
|
||||
)
|
||||
|
||||
@Composable
|
||||
fun rememberAuthenticationState(): State<Authentication> {
|
||||
fun rememberAuthenticationState(): State<AuthenticationStateUio> {
|
||||
launcher = rememberLauncherForActivityResult(
|
||||
contract = ActivityResultContracts.StartIntentSenderForResult(),
|
||||
onResult = {
|
||||
|
|
@ -48,11 +47,10 @@ class AuthenticationViewModel @Inject constructor(
|
|||
.getSignInClient(context)
|
||||
.getSignInCredentialFromIntent(it.data)
|
||||
|
||||
state.value = Authentication.Success
|
||||
repository.updateAuthenticationState(credential)
|
||||
state.value = AuthenticationStateUio.Success
|
||||
repository.updateAuthenticationState(credential = credential)
|
||||
} else {
|
||||
state.value = Authentication.Failure
|
||||
repository.updateAuthenticationState()
|
||||
repository.updateAuthenticationState(credential = null)
|
||||
}
|
||||
},
|
||||
)
|
||||
|
|
@ -60,7 +58,7 @@ class AuthenticationViewModel @Inject constructor(
|
|||
}
|
||||
|
||||
fun signIn(activity: Activity) {
|
||||
state.value = Authentication.Initial
|
||||
state.value = AuthenticationStateUio.Initial
|
||||
|
||||
val request: GetSignInIntentRequest = GetSignInIntentRequest.builder()
|
||||
.setServerClientId(context.getString(R.string.google_sign_in_id))
|
||||
|
|
@ -72,21 +70,14 @@ class AuthenticationViewModel @Inject constructor(
|
|||
launcher?.launch(
|
||||
IntentSenderRequest.Builder(result.intentSender).build()
|
||||
)
|
||||
} catch (e: SendIntentException) {
|
||||
state.value = Authentication.Failure
|
||||
} catch (exception: SendIntentException) {
|
||||
state.value = AuthenticationStateUio.Failure(exception = exception)
|
||||
repository.updateAuthenticationState()
|
||||
}
|
||||
}
|
||||
.addOnFailureListener {
|
||||
state.value = Authentication.Failure
|
||||
.addOnFailureListener { exception ->
|
||||
state.value = AuthenticationStateUio.Failure(exception = exception)
|
||||
repository.updateAuthenticationState()
|
||||
}
|
||||
}
|
||||
|
||||
@Stable
|
||||
sealed class Authentication {
|
||||
object Initial : Authentication()
|
||||
object Success : Authentication()
|
||||
object Failure : Authentication()
|
||||
}
|
||||
}
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
package com.pixelized.rplexicon.utilitary.exceptions
|
||||
|
||||
class ServiceNotReady : Exception()
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
<resources>
|
||||
<string name="app_name">Rp-Compagnon</string>
|
||||
|
||||
<string name="error_generic">Ah !? y\'a un truc qui foire quelque part.</string>
|
||||
<string name="error_generic">Une erreur s\'est produite.</string>
|
||||
<string name="error_structure">La structure du fichier semble avoir changé et n\'est plus compatible avec cette application.</string>
|
||||
|
||||
<string name="gender_male">Mâle</string>
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="google_spreadsheet_api_key">AIzaSyBmagVOEyB68tTJ5QMFMzMQZIHG_4XVCOo</string>
|
||||
<string name="google_sign_in_id" translatable="false">62913404482-ergqkjiuvint49q8lm555j21vvb6af7s.apps.googleusercontent.com</string>
|
||||
</resources>
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
<resources>
|
||||
<string name="app_name">Rp-Companion</string>
|
||||
|
||||
<string name="error_generic">Oups, it should not be rocket science.</string>
|
||||
<string name="error_generic">An error occur.</string>
|
||||
<string name="error_structure">The file structure appears to have changed and is no longer compatible with this application</string>
|
||||
|
||||
<string name="gender_male">Male</string>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue