Merge pull request #192 from lucasnlm/move-instant-app-data
Move instant app data
This commit is contained in:
commit
425c8b494b
75 changed files with 645 additions and 82 deletions
|
@ -12,8 +12,8 @@ android {
|
|||
|
||||
defaultConfig {
|
||||
// versionCode and versionName must be hardcoded to support F-droid
|
||||
versionCode 802031
|
||||
versionName '8.2.3'
|
||||
versionCode 803001
|
||||
versionName '8.3.0'
|
||||
minSdkVersion 21
|
||||
targetSdkVersion 30
|
||||
multiDexEnabled true
|
||||
|
|
|
@ -38,7 +38,6 @@
|
|||
android:roundIcon="@mipmap/ic_launcher_round"
|
||||
android:supportsRtl="true"
|
||||
android:theme="@style/AppTheme"
|
||||
android:targetSandboxVersion="2"
|
||||
tools:targetApi="lollipop">
|
||||
|
||||
<activity
|
||||
|
|
|
@ -5,6 +5,7 @@ import android.content.Intent
|
|||
import android.net.Uri
|
||||
import android.os.Bundle
|
||||
import android.text.format.DateUtils
|
||||
import android.util.Log
|
||||
import android.view.Gravity
|
||||
import android.view.View
|
||||
import android.view.WindowManager
|
||||
|
@ -23,6 +24,7 @@ import androidx.lifecycle.Transformations
|
|||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.preference.PreferenceManager
|
||||
import dev.lucasnlm.antimine.about.AboutActivity
|
||||
import dev.lucasnlm.antimine.cloud.CloudSaveManager
|
||||
import dev.lucasnlm.antimine.common.level.models.Difficulty
|
||||
import dev.lucasnlm.antimine.common.level.models.Event
|
||||
import dev.lucasnlm.antimine.common.level.models.Score
|
||||
|
@ -58,10 +60,12 @@ import kotlinx.android.synthetic.main.activity_tv_game.*
|
|||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.GlobalScope
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.flow.collect
|
||||
import kotlinx.coroutines.withContext
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.flow.collect
|
||||
import org.koin.android.ext.android.inject
|
||||
import org.koin.androidx.viewmodel.ext.android.viewModel
|
||||
import java.lang.Exception
|
||||
|
||||
class GameActivity : ThematicActivity(R.layout.activity_game), DialogInterface.OnDismissListener {
|
||||
private val billingManager: IBillingManager by inject()
|
||||
|
@ -82,6 +86,8 @@ class GameActivity : ThematicActivity(R.layout.activity_game), DialogInterface.O
|
|||
|
||||
val gameViewModel by viewModel<GameViewModel>()
|
||||
|
||||
private val cloudSaveManager by inject<CloudSaveManager>()
|
||||
|
||||
override val noActionBar: Boolean = true
|
||||
|
||||
private var status: Status = Status.PreGame
|
||||
|
@ -91,7 +97,7 @@ class GameActivity : ThematicActivity(R.layout.activity_game), DialogInterface.O
|
|||
private var currentTime: Long = 0
|
||||
private var currentSaveId: Long = 0
|
||||
|
||||
private val areaSizeMultiplier by lazy { preferencesRepository.areaSizeMultiplier() }
|
||||
private val areaSizeMultiplier by lazy { preferencesRepository.squareSizeMultiplier() }
|
||||
private val currentRadius by lazy { preferencesRepository.squareRadius() }
|
||||
private val useHelp by lazy { preferencesRepository.useHelp() }
|
||||
|
||||
|
@ -102,6 +108,7 @@ class GameActivity : ThematicActivity(R.layout.activity_game), DialogInterface.O
|
|||
PreferenceManager.setDefaultValues(this, R.xml.preferences, false)
|
||||
|
||||
bindViewModel()
|
||||
bindPlayGames()
|
||||
bindToolbar()
|
||||
bindDrawer()
|
||||
bindNavigationMenu()
|
||||
|
@ -121,6 +128,22 @@ class GameActivity : ThematicActivity(R.layout.activity_game), DialogInterface.O
|
|||
onOpenAppActions()
|
||||
}
|
||||
|
||||
private fun bindPlayGames() {
|
||||
lifecycleScope.launch {
|
||||
withContext(Dispatchers.IO) {
|
||||
silentGooglePlayLogin()
|
||||
}
|
||||
|
||||
withContext(Dispatchers.Main) {
|
||||
if (!isFinishing) {
|
||||
invalidateOptionsMenu()
|
||||
}
|
||||
}
|
||||
|
||||
playGamesManager.showPlayPopUp(this@GameActivity)
|
||||
}
|
||||
}
|
||||
|
||||
private fun bindViewModel() = gameViewModel.apply {
|
||||
Transformations
|
||||
.distinctUntilChanged(eventObserver)
|
||||
|
@ -222,7 +245,6 @@ class GameActivity : ThematicActivity(R.layout.activity_game), DialogInterface.O
|
|||
analyticsManager.sentEvent(Analytics.Resume)
|
||||
}
|
||||
|
||||
silentGooglePlayLogin()
|
||||
refreshAds()
|
||||
}
|
||||
}
|
||||
|
@ -711,6 +733,7 @@ class GameActivity : ThematicActivity(R.layout.activity_game), DialogInterface.O
|
|||
analyticsManager.sentEvent(Analytics.TutorialCompleted)
|
||||
preferencesRepository.completeTutorial()
|
||||
showCompletedTutorialDialog()
|
||||
cloudSaveManager.uploadSave()
|
||||
}
|
||||
Event.Victory -> {
|
||||
val isResuming = (status == Status.PreGame)
|
||||
|
@ -727,6 +750,7 @@ class GameActivity : ThematicActivity(R.layout.activity_game), DialogInterface.O
|
|||
keepScreenOn(false)
|
||||
|
||||
if (!isResuming) {
|
||||
cloudSaveManager.uploadSave()
|
||||
gameViewModel.addNewTip()
|
||||
|
||||
waitAndShowEndGameAlert(
|
||||
|
@ -748,6 +772,7 @@ class GameActivity : ThematicActivity(R.layout.activity_game), DialogInterface.O
|
|||
gameViewModel.stopClock()
|
||||
|
||||
if (!isResuming) {
|
||||
cloudSaveManager.uploadSave()
|
||||
GlobalScope.launch(context = Dispatchers.Main) {
|
||||
gameViewModel.gameOver(isResuming)
|
||||
waitAndShowEndGameAlert(
|
||||
|
@ -767,7 +792,7 @@ class GameActivity : ThematicActivity(R.layout.activity_game), DialogInterface.O
|
|||
*/
|
||||
private fun restartIfNeed(): Boolean {
|
||||
return (
|
||||
areaSizeMultiplier != preferencesRepository.areaSizeMultiplier() ||
|
||||
areaSizeMultiplier != preferencesRepository.squareSizeMultiplier() ||
|
||||
currentRadius != preferencesRepository.squareRadius() ||
|
||||
useHelp != preferencesRepository.useHelp()
|
||||
).also {
|
||||
|
@ -853,8 +878,11 @@ class GameActivity : ThematicActivity(R.layout.activity_game), DialogInterface.O
|
|||
|
||||
private fun silentGooglePlayLogin() {
|
||||
if (playGamesManager.hasGooglePlayGames()) {
|
||||
playGamesManager.silentLogin(this)
|
||||
invalidateOptionsMenu()
|
||||
try {
|
||||
playGamesManager.silentLogin()
|
||||
} catch (e: Exception) {
|
||||
Log.e(TAG, "User not logged in Play Games")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -871,9 +899,7 @@ class GameActivity : ThematicActivity(R.layout.activity_game), DialogInterface.O
|
|||
}
|
||||
|
||||
private fun openCrowdIn() {
|
||||
Intent(Intent.ACTION_VIEW, Uri.parse("https://crowdin.com/project/antimine-android")).let {
|
||||
startActivity(it)
|
||||
}
|
||||
startActivity(Intent(Intent.ACTION_VIEW, Uri.parse("https://crowdin.com/project/antimine-android")))
|
||||
}
|
||||
|
||||
private fun showSupportAppDialog() {
|
||||
|
@ -900,6 +926,7 @@ class GameActivity : ThematicActivity(R.layout.activity_game), DialogInterface.O
|
|||
}
|
||||
|
||||
companion object {
|
||||
val TAG = GameActivity::class.simpleName
|
||||
const val GOOGLE_PLAY_REQUEST_CODE = 6
|
||||
|
||||
const val MIN_USAGES_TO_IAP = 5
|
||||
|
|
|
@ -0,0 +1,52 @@
|
|||
package dev.lucasnlm.antimine.cloud
|
||||
|
||||
import dev.lucasnlm.antimine.common.level.database.models.toHashMap
|
||||
import dev.lucasnlm.antimine.common.level.repository.IStatsRepository
|
||||
import dev.lucasnlm.antimine.core.preferences.IPreferencesRepository
|
||||
import dev.lucasnlm.external.ICloudStorageManager
|
||||
import dev.lucasnlm.external.IPlayGamesManager
|
||||
import dev.lucasnlm.external.model.CloudSave
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.GlobalScope
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
|
||||
class CloudSaveManager(
|
||||
private val playGamesManager: IPlayGamesManager,
|
||||
private val preferencesRepository: IPreferencesRepository,
|
||||
private val statsRepository: IStatsRepository,
|
||||
private val cloudStorageManager: ICloudStorageManager,
|
||||
) {
|
||||
fun uploadSave() {
|
||||
GlobalScope.launch {
|
||||
withContext(Dispatchers.IO) {
|
||||
getCloudSave()?.let {
|
||||
cloudStorageManager.uploadSave(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun getCloudSave(): CloudSave? {
|
||||
val minId = preferencesRepository.getStatsBase()
|
||||
|
||||
return playGamesManager.playerId()?.let { playerId ->
|
||||
CloudSave(
|
||||
playId = playerId,
|
||||
completeTutorial = if (preferencesRepository.isTutorialCompleted()) 1 else 0,
|
||||
selectedTheme = preferencesRepository.themeId().toInt(),
|
||||
squareRadius = preferencesRepository.squareRadius(),
|
||||
squareSize = preferencesRepository.squareSizeMultiplier(),
|
||||
touchTiming = preferencesRepository.customLongPressTimeout().toInt(),
|
||||
questionMark = if (preferencesRepository.useQuestionMark()) 1 else 0,
|
||||
gameAssistance = if (preferencesRepository.useFlagAssistant()) 1 else 0,
|
||||
help = if (preferencesRepository.useHelp()) 1 else 0,
|
||||
hapticFeedback = if (preferencesRepository.useHapticFeedback()) 1 else 0,
|
||||
soundEffects = if (preferencesRepository.isSoundEffectsEnabled()) 1 else 0,
|
||||
stats = statsRepository.getAllStats(minId).map { it.toHashMap() },
|
||||
premiumFeatures = if (preferencesRepository.isPremiumEnabled()) 1 else 0,
|
||||
controlStyle = preferencesRepository.controlStyle().ordinal,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -9,14 +9,17 @@ import android.widget.BaseAdapter
|
|||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.appcompat.app.AppCompatDialogFragment
|
||||
import dev.lucasnlm.antimine.R
|
||||
import dev.lucasnlm.antimine.cloud.CloudSaveManager
|
||||
import dev.lucasnlm.antimine.control.view.ControlItemView
|
||||
import dev.lucasnlm.antimine.control.view.SimpleControlItemView
|
||||
import dev.lucasnlm.antimine.control.viewmodel.ControlEvent
|
||||
import dev.lucasnlm.antimine.control.viewmodel.ControlViewModel
|
||||
import dev.lucasnlm.antimine.core.control.ControlStyle
|
||||
import org.koin.android.ext.android.inject
|
||||
import org.koin.androidx.viewmodel.ext.android.viewModel
|
||||
|
||||
class ControlDialogFragment : AppCompatDialogFragment() {
|
||||
private val cloudSaveManager by inject<CloudSaveManager>()
|
||||
private val controlViewModel by viewModel<ControlViewModel>()
|
||||
private val adapter by lazy { ControlListAdapter(controlViewModel) }
|
||||
|
||||
|
@ -33,6 +36,7 @@ class ControlDialogFragment : AppCompatDialogFragment() {
|
|||
if (activity is DialogInterface.OnDismissListener) {
|
||||
(activity as DialogInterface.OnDismissListener).onDismiss(dialog)
|
||||
}
|
||||
cloudSaveManager.uploadSave()
|
||||
super.onDismiss(dialog)
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package dev.lucasnlm.antimine.di
|
||||
|
||||
import dev.lucasnlm.antimine.cloud.CloudSaveManager
|
||||
import dev.lucasnlm.antimine.support.IapHandler
|
||||
import dev.lucasnlm.antimine.common.BuildConfig
|
||||
import dev.lucasnlm.antimine.core.analytics.DebugAnalyticsManager
|
||||
|
@ -8,9 +9,11 @@ import dev.lucasnlm.antimine.core.analytics.ProdAnalyticsManager
|
|||
import dev.lucasnlm.antimine.share.ShareManager
|
||||
import dev.lucasnlm.external.AdsManager
|
||||
import dev.lucasnlm.external.BillingManager
|
||||
import dev.lucasnlm.external.CloudStorageManager
|
||||
import dev.lucasnlm.external.ExternalAnalyticsWrapper
|
||||
import dev.lucasnlm.external.IAdsManager
|
||||
import dev.lucasnlm.external.IBillingManager
|
||||
import dev.lucasnlm.external.ICloudStorageManager
|
||||
import dev.lucasnlm.external.IInstantAppManager
|
||||
import dev.lucasnlm.external.IPlayGamesManager
|
||||
import dev.lucasnlm.external.IReviewWrapper
|
||||
|
@ -31,10 +34,14 @@ val AppModule = module {
|
|||
|
||||
single { ReviewWrapper() } bind IReviewWrapper::class
|
||||
|
||||
single { CloudStorageManager() } bind ICloudStorageManager::class
|
||||
|
||||
single { ShareManager(get(), get()) }
|
||||
|
||||
single { IapHandler(get(), get(), get()) }
|
||||
|
||||
single { CloudSaveManager(get(), get(), get(), get()) }
|
||||
|
||||
single {
|
||||
if (BuildConfig.DEBUG) {
|
||||
DebugAnalyticsManager()
|
||||
|
|
|
@ -7,6 +7,7 @@ import dev.lucasnlm.antimine.custom.viewmodel.CreateGameViewModel
|
|||
import dev.lucasnlm.antimine.history.viewmodel.HistoryViewModel
|
||||
import dev.lucasnlm.antimine.level.viewmodel.EndGameDialogViewModel
|
||||
import dev.lucasnlm.antimine.playgames.viewmodel.PlayGamesViewModel
|
||||
import dev.lucasnlm.antimine.splash.viewmodel.SplashViewModel
|
||||
import dev.lucasnlm.antimine.stats.viewmodel.StatsViewModel
|
||||
import dev.lucasnlm.antimine.text.viewmodel.TextViewModel
|
||||
import dev.lucasnlm.antimine.theme.viewmodel.ThemeViewModel
|
||||
|
@ -24,6 +25,7 @@ val ViewModelModule = module {
|
|||
viewModel { StatsViewModel(get(), get(), get(), get()) }
|
||||
viewModel { TextViewModel(get()) }
|
||||
viewModel { ThemeViewModel(get(), get(), get(), get()) }
|
||||
viewModel { SplashViewModel(get(), get(), get(), get(), get(), get(), get()) }
|
||||
viewModel {
|
||||
GameViewModel(get(), get(), get(), get(), get(), get(), get(), get(), get(), get(), get(), get())
|
||||
}
|
||||
|
|
|
@ -28,8 +28,10 @@ class HistoryFragment : Fragment(R.layout.fragment_history) {
|
|||
historyViewModel.sendEvent(HistoryEvent.LoadAllSaves)
|
||||
|
||||
historyViewModel.observeState().collect {
|
||||
if (it.saveList.isEmpty()) {
|
||||
empty.visibility = View.GONE
|
||||
empty.visibility = if (it.saveList.isEmpty()) {
|
||||
View.VISIBLE
|
||||
} else {
|
||||
View.GONE
|
||||
}
|
||||
|
||||
saveHistory.apply {
|
||||
|
|
|
@ -8,6 +8,7 @@ import androidx.preference.PreferenceFragmentCompat
|
|||
import androidx.preference.PreferenceManager
|
||||
import dev.lucasnlm.antimine.R
|
||||
import dev.lucasnlm.antimine.ThematicActivity
|
||||
import dev.lucasnlm.antimine.cloud.CloudSaveManager
|
||||
import dev.lucasnlm.antimine.core.preferences.IPreferencesRepository
|
||||
import org.koin.android.ext.android.inject
|
||||
|
||||
|
@ -17,6 +18,8 @@ class PreferencesActivity :
|
|||
|
||||
private val preferenceRepository: IPreferencesRepository by inject()
|
||||
|
||||
private val cloudSaveManager by inject<CloudSaveManager>()
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
PreferenceManager.setDefaultValues(this, R.xml.preferences, false)
|
||||
|
@ -30,6 +33,8 @@ class PreferencesActivity :
|
|||
override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
|
||||
cloudSaveManager.uploadSave()
|
||||
|
||||
PreferenceManager.getDefaultSharedPreferences(this)
|
||||
.unregisterOnSharedPreferenceChangeListener(this)
|
||||
}
|
||||
|
|
|
@ -2,20 +2,75 @@ package dev.lucasnlm.antimine.splash
|
|||
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.util.Log
|
||||
import android.view.Gravity
|
||||
import android.widget.LinearLayout
|
||||
import android.widget.TextView
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import dev.lucasnlm.antimine.GameActivity
|
||||
import dev.lucasnlm.antimine.support.IapHandler
|
||||
import dev.lucasnlm.antimine.R
|
||||
import dev.lucasnlm.antimine.splash.viewmodel.SplashViewModel
|
||||
import dev.lucasnlm.external.IPlayGamesManager
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.withContext
|
||||
import org.koin.android.ext.android.inject
|
||||
import org.koin.androidx.viewmodel.ext.android.viewModel
|
||||
|
||||
class SplashActivity : AppCompatActivity() {
|
||||
private val iapHandler: IapHandler by inject()
|
||||
private val playGamesManager: IPlayGamesManager by inject()
|
||||
|
||||
private val splashViewMode: SplashViewModel by viewModel()
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
iapHandler.start()
|
||||
val layout = LinearLayout(this).apply {
|
||||
fitsSystemWindows = true
|
||||
gravity = Gravity.BOTTOM or Gravity.CENTER_HORIZONTAL
|
||||
orientation = LinearLayout.VERTICAL
|
||||
|
||||
Intent(this, GameActivity::class.java).run { startActivity(this) }
|
||||
finish()
|
||||
val params = LinearLayout.LayoutParams(
|
||||
LinearLayout.LayoutParams.WRAP_CONTENT,
|
||||
LinearLayout.LayoutParams.WRAP_CONTENT
|
||||
).apply { setMargins(0, 0, 0, 200) }
|
||||
|
||||
val loadingMessage = TextView(context).apply {
|
||||
text = context.getString(R.string.loading)
|
||||
setTextColor(ContextCompat.getColor(context, R.color.splash_text_color))
|
||||
}
|
||||
|
||||
addView(loadingMessage, params)
|
||||
}
|
||||
setContentView(layout)
|
||||
|
||||
splashViewMode.startIap()
|
||||
|
||||
lifecycleScope.launchWhenCreated {
|
||||
if (playGamesManager.hasGooglePlayGames()) {
|
||||
withContext(Dispatchers.IO) {
|
||||
try {
|
||||
playGamesManager.silentLogin()
|
||||
splashViewMode.migrateCloudSave()
|
||||
} catch (e: Exception) {
|
||||
Log.e(TAG, "User not logged in Play Games")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
withContext(Dispatchers.Main) {
|
||||
if (!isFinishing) {
|
||||
overridePendingTransition(android.R.anim.fade_in, android.R.anim.fade_out)
|
||||
Intent(this@SplashActivity, GameActivity::class.java)
|
||||
.run { startActivity(this) }
|
||||
finish()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
val TAG = SplashActivity::class.simpleName
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,82 @@
|
|||
package dev.lucasnlm.antimine.splash.viewmodel
|
||||
|
||||
import android.content.Context
|
||||
import androidx.lifecycle.ViewModel
|
||||
import dev.lucasnlm.antimine.common.level.database.models.Stats
|
||||
import dev.lucasnlm.antimine.common.level.repository.IStatsRepository
|
||||
import dev.lucasnlm.antimine.core.control.ControlStyle
|
||||
import dev.lucasnlm.antimine.core.preferences.IPreferencesRepository
|
||||
import dev.lucasnlm.antimine.support.IapHandler
|
||||
import dev.lucasnlm.external.ICloudStorageManager
|
||||
import dev.lucasnlm.external.IInstantAppManager
|
||||
import dev.lucasnlm.external.IPlayGamesManager
|
||||
import dev.lucasnlm.external.model.CloudSave
|
||||
|
||||
class SplashViewModel(
|
||||
private val context: Context,
|
||||
private val preferencesRepository: IPreferencesRepository,
|
||||
private val statsRepository: IStatsRepository,
|
||||
private val saveCloudStorageManager: ICloudStorageManager,
|
||||
private val playGamesManager: IPlayGamesManager,
|
||||
private val instantAppManager: IInstantAppManager,
|
||||
private val iapHandler: IapHandler,
|
||||
) : ViewModel() {
|
||||
fun startIap() {
|
||||
iapHandler.start()
|
||||
}
|
||||
|
||||
suspend fun migrateCloudSave() {
|
||||
if (instantAppManager.isEnabled(context) || preferencesRepository.shouldMigrateFromCloud()) {
|
||||
val userId = playGamesManager.playerId()
|
||||
|
||||
userId?.let {
|
||||
saveCloudStorageManager.getSave(it)?.let { cloudSave ->
|
||||
loadCloudSave(cloudSave)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (instantAppManager.isEnabled(context)) {
|
||||
preferencesRepository.setMigrateFromCloud(true)
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun loadCloudSave(cloudSave: CloudSave) = with(cloudSave) {
|
||||
if (cloudSave.completeTutorial == 1) {
|
||||
preferencesRepository.completeTutorial()
|
||||
}
|
||||
|
||||
preferencesRepository.completeFirstUse()
|
||||
preferencesRepository.useTheme(cloudSave.selectedTheme.toLong())
|
||||
preferencesRepository.setSquareRadius(cloudSave.squareRadius)
|
||||
preferencesRepository.setSquareMultiplier(cloudSave.squareSize)
|
||||
preferencesRepository.setCustomLongPressTimeout(cloudSave.touchTiming.toLong())
|
||||
preferencesRepository.setQuestionMark(cloudSave.questionMark != 0)
|
||||
preferencesRepository.setFlagAssistant(gameAssistance != 0)
|
||||
preferencesRepository.setHapticFeedback(hapticFeedback != 0)
|
||||
preferencesRepository.setHelp(help != 0)
|
||||
preferencesRepository.setSoundEffectsEnabled(soundEffects != 0)
|
||||
preferencesRepository.setPremiumFeatures(cloudSave.premiumFeatures != 0)
|
||||
preferencesRepository.useControlStyle(ControlStyle.values()[cloudSave.controlStyle])
|
||||
|
||||
cloudSave.stats.mapNotNull {
|
||||
try {
|
||||
Stats(
|
||||
uid = it["uid"]!!.toInt(),
|
||||
duration = it["duration"]!!.toLong(),
|
||||
mines = it["mines"]!!.toInt(),
|
||||
victory = it["victory"]!!.toInt(),
|
||||
width = it["width"]!!.toInt(),
|
||||
height = it["height"]!!.toInt(),
|
||||
openArea = it["openArea"]!!.toInt(),
|
||||
)
|
||||
} catch (e: Exception) {
|
||||
null
|
||||
}
|
||||
}.forEach {
|
||||
statsRepository.addStats(it)
|
||||
}
|
||||
|
||||
preferencesRepository.setMigrateFromCloud(false)
|
||||
}
|
||||
}
|
|
@ -7,6 +7,7 @@ import androidx.lifecycle.lifecycleScope
|
|||
import androidx.recyclerview.widget.GridLayoutManager
|
||||
import dev.lucasnlm.antimine.R
|
||||
import dev.lucasnlm.antimine.ThematicActivity
|
||||
import dev.lucasnlm.antimine.cloud.CloudSaveManager
|
||||
import dev.lucasnlm.antimine.common.level.repository.IDimensionRepository
|
||||
import dev.lucasnlm.antimine.common.level.view.SpaceItemDecoration
|
||||
import dev.lucasnlm.antimine.core.preferences.IPreferencesRepository
|
||||
|
@ -25,6 +26,8 @@ class ThemeActivity : ThematicActivity(R.layout.activity_theme) {
|
|||
|
||||
private val themeViewModel by viewModel<ThemeViewModel>()
|
||||
|
||||
private val cloudSaveManager by inject<CloudSaveManager>()
|
||||
|
||||
private val preferencesRepository: IPreferencesRepository by inject()
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
|
@ -62,6 +65,7 @@ class ThemeActivity : ThematicActivity(R.layout.activity_theme) {
|
|||
themeViewModel.observeState().collect {
|
||||
if (usingTheme.id != it.current.id) {
|
||||
recreate()
|
||||
cloudSaveManager.uploadSave()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,10 +4,8 @@ import android.graphics.Color
|
|||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import android.view.animation.AnimationUtils
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.text.bold
|
||||
import androidx.core.text.buildSpannedString
|
||||
import androidx.core.text.color
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.recyclerview.widget.GridLayoutManager
|
||||
|
@ -87,7 +85,7 @@ class TutorialLevelFragment : Fragment(R.layout.fragment_tutorial_level) {
|
|||
.forEach {
|
||||
when (it) {
|
||||
flagAction, openAction -> {
|
||||
bold { color(ContextCompat.getColor(context, R.color.accent)) { append(it) } }
|
||||
bold { append(it) }
|
||||
}
|
||||
else -> append(it)
|
||||
}
|
||||
|
@ -109,7 +107,7 @@ class TutorialLevelFragment : Fragment(R.layout.fragment_tutorial_level) {
|
|||
.forEach {
|
||||
when (it) {
|
||||
flagAction, openAction -> {
|
||||
bold { color(ContextCompat.getColor(context, R.color.accent)) { append(it) } }
|
||||
bold { append(it) }
|
||||
}
|
||||
else -> append(it)
|
||||
}
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/recyclerView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_height="0dp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintRight_toRightOf="parent"
|
||||
|
|
|
@ -38,9 +38,13 @@ val AppModule = module {
|
|||
|
||||
single {
|
||||
object : IPlayGamesManager {
|
||||
override fun playerId(): String? = null
|
||||
|
||||
override fun hasGooglePlayGames(): Boolean = false
|
||||
|
||||
override fun silentLogin(activity: Activity) { }
|
||||
override fun silentLogin() { }
|
||||
|
||||
override fun showPlayPopUp(activity: Activity) { }
|
||||
|
||||
override fun getLoginIntent(): Intent? = null
|
||||
|
||||
|
|
|
@ -31,6 +31,8 @@ class MockPreferencesRepository : IPreferencesRepository {
|
|||
|
||||
override fun customLongPressTimeout(): Long = 400L
|
||||
|
||||
override fun setCustomLongPressTimeout(value: Long) { }
|
||||
|
||||
override fun themeId(): Long = 1L
|
||||
|
||||
override fun useTheme(themeId: Long) { }
|
||||
|
@ -63,8 +65,12 @@ class MockPreferencesRepository : IPreferencesRepository {
|
|||
|
||||
override fun useHelp(): Boolean = false
|
||||
|
||||
override fun setHelp(value: Boolean) { }
|
||||
|
||||
override fun squareRadius(): Int = 2
|
||||
|
||||
override fun setSquareRadius(value: Int) { }
|
||||
|
||||
override fun getTips(): Int = 0
|
||||
|
||||
override fun setTips(tips: Int) { }
|
||||
|
@ -79,15 +85,29 @@ class MockPreferencesRepository : IPreferencesRepository {
|
|||
|
||||
override fun useFlagAssistant(): Boolean = false
|
||||
|
||||
override fun setFlagAssistant(value: Boolean) { }
|
||||
|
||||
override fun useHapticFeedback(): Boolean = true
|
||||
|
||||
override fun areaSizeMultiplier(): Int = 50
|
||||
override fun setHapticFeedback(value: Boolean) { }
|
||||
|
||||
override fun squareSizeMultiplier(): Int = 50
|
||||
|
||||
override fun setSquareMultiplier(value: Int) { }
|
||||
|
||||
override fun useAnimations(): Boolean = false
|
||||
|
||||
override fun useQuestionMark(): Boolean = false
|
||||
|
||||
override fun setQuestionMark(value: Boolean) { }
|
||||
|
||||
override fun isSoundEffectsEnabled(): Boolean = false
|
||||
|
||||
override fun setSoundEffectsEnabled(value: Boolean) { }
|
||||
|
||||
override fun shouldMigrateFromCloud(): Boolean = false
|
||||
|
||||
override fun setMigrateFromCloud(value: Boolean) { }
|
||||
|
||||
override fun showWindowsWhenFinishGame(): Boolean = true
|
||||
}
|
||||
|
|
|
@ -8,8 +8,8 @@ android {
|
|||
|
||||
defaultConfig {
|
||||
// versionCode and versionName must be hardcoded to support F-droid
|
||||
versionCode 802031
|
||||
versionName '8.2.3'
|
||||
versionCode 803001
|
||||
versionName '8.3.0'
|
||||
minSdkVersion 21
|
||||
targetSdkVersion 30
|
||||
testInstrumentationRunner 'androidx.test.runner.AndroidJUnitRunner'
|
||||
|
|
|
@ -27,3 +27,13 @@ data class Stats(
|
|||
@ColumnInfo(name = "openArea")
|
||||
val openArea: Int,
|
||||
)
|
||||
|
||||
fun Stats.toHashMap(): HashMap<String, String> = hashMapOf(
|
||||
"uid" to uid.toString(),
|
||||
"duration" to duration.toString(),
|
||||
"mines" to mines.toString(),
|
||||
"victory" to victory.toString(),
|
||||
"width" to width.toString(),
|
||||
"height" to height.toString(),
|
||||
"openArea" to openArea.toString(),
|
||||
)
|
||||
|
|
|
@ -27,9 +27,9 @@ class DimensionRepository(
|
|||
) : IDimensionRepository {
|
||||
|
||||
override fun areaSize(): Float {
|
||||
val multiplier = preferencesRepository.areaSizeMultiplier() / 100.0f
|
||||
val regularSize = context.resources.getDimension(R.dimen.field_size)
|
||||
return regularSize * multiplier
|
||||
val multiplier = preferencesRepository.squareSizeMultiplier() / 100.0f
|
||||
val maxArea = context.resources.getDimension(R.dimen.field_size)
|
||||
return maxArea * multiplier
|
||||
}
|
||||
|
||||
override fun areaSeparator(): Float {
|
||||
|
|
|
@ -313,6 +313,9 @@ open class GameViewModel(
|
|||
ActionResponse.OpenNeighbors -> {
|
||||
analyticsManager.sentEvent(Analytics.OpenNeighbors(index))
|
||||
}
|
||||
ActionResponse.OpenOrMark -> {
|
||||
analyticsManager.sentEvent(Analytics.OpenOrFlagTile(index))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -535,7 +538,7 @@ open class GameViewModel(
|
|||
|
||||
fun getAppTheme(): AppTheme = themeRepository.getTheme()
|
||||
|
||||
private fun getAreaSizeMultiplier() = preferencesRepository.areaSizeMultiplier()
|
||||
private fun getAreaSizeMultiplier() = preferencesRepository.squareSizeMultiplier()
|
||||
|
||||
private fun refreshField() {
|
||||
field.postValue(gameController.field())
|
||||
|
|
|
@ -50,6 +50,8 @@ sealed class Analytics(
|
|||
|
||||
class OpenTile(index: Int) : Analytics("Open Tile", mapOf("Index" to index.toString()))
|
||||
|
||||
class OpenOrFlagTile(index: Int) : Analytics("Open or Flag Tile", mapOf("Index" to index.toString()))
|
||||
|
||||
class SwitchMark(index: Int) : Analytics("Switch Mark", mapOf("Index" to index.toString()))
|
||||
|
||||
class HighlightNeighbors(index: Int) : Analytics("Highlight Neighbors", mapOf("Index" to index.toString()))
|
||||
|
|
|
@ -20,6 +20,7 @@ interface IPreferencesRepository {
|
|||
fun completeTutorial()
|
||||
|
||||
fun customLongPressTimeout(): Long
|
||||
fun setCustomLongPressTimeout(value: Long)
|
||||
|
||||
fun themeId(): Long
|
||||
fun useTheme(themeId: Long)
|
||||
|
@ -44,7 +45,10 @@ interface IPreferencesRepository {
|
|||
fun showSupport(): Boolean
|
||||
|
||||
fun useHelp(): Boolean
|
||||
fun setHelp(value: Boolean)
|
||||
|
||||
fun squareRadius(): Int
|
||||
fun setSquareRadius(value: Int)
|
||||
|
||||
fun getTips(): Int
|
||||
fun setTips(tips: Int)
|
||||
|
@ -55,10 +59,24 @@ interface IPreferencesRepository {
|
|||
fun setSwitchControl(useOpen: Boolean)
|
||||
|
||||
fun useFlagAssistant(): Boolean
|
||||
fun setFlagAssistant(value: Boolean)
|
||||
|
||||
fun useHapticFeedback(): Boolean
|
||||
fun areaSizeMultiplier(): Int
|
||||
fun setHapticFeedback(value: Boolean)
|
||||
|
||||
fun squareSizeMultiplier(): Int
|
||||
fun setSquareMultiplier(value: Int)
|
||||
|
||||
fun useAnimations(): Boolean
|
||||
|
||||
fun useQuestionMark(): Boolean
|
||||
fun setQuestionMark(value: Boolean)
|
||||
|
||||
fun isSoundEffectsEnabled(): Boolean
|
||||
fun setSoundEffectsEnabled(value: Boolean)
|
||||
|
||||
fun shouldMigrateFromCloud(): Boolean
|
||||
fun setMigrateFromCloud(value: Boolean)
|
||||
|
||||
fun showWindowsWhenFinishGame(): Boolean
|
||||
}
|
||||
|
|
|
@ -48,21 +48,48 @@ class PreferencesRepository(
|
|||
override fun useFlagAssistant(): Boolean =
|
||||
preferencesManager.getBoolean(PREFERENCE_ASSISTANT, true)
|
||||
|
||||
override fun setFlagAssistant(value: Boolean) {
|
||||
preferencesManager.putBoolean(PREFERENCE_ASSISTANT, value)
|
||||
}
|
||||
|
||||
override fun useHapticFeedback(): Boolean =
|
||||
preferencesManager.getBoolean(PREFERENCE_VIBRATION, true)
|
||||
|
||||
override fun areaSizeMultiplier(): Int =
|
||||
override fun setHapticFeedback(value: Boolean) {
|
||||
preferencesManager.putBoolean(PREFERENCE_VIBRATION, value)
|
||||
}
|
||||
|
||||
override fun squareSizeMultiplier(): Int =
|
||||
preferencesManager.getInt(PREFERENCE_AREA_SIZE, 50)
|
||||
|
||||
override fun setSquareMultiplier(value: Int) {
|
||||
preferencesManager.putInt(PREFERENCE_AREA_SIZE, value)
|
||||
}
|
||||
|
||||
override fun useAnimations(): Boolean =
|
||||
preferencesManager.getBoolean(PREFERENCE_ANIMATION, true)
|
||||
|
||||
override fun useQuestionMark(): Boolean =
|
||||
preferencesManager.getBoolean(PREFERENCE_QUESTION_MARK, false)
|
||||
|
||||
override fun setQuestionMark(value: Boolean) {
|
||||
preferencesManager.putBoolean(PREFERENCE_QUESTION_MARK, value)
|
||||
}
|
||||
|
||||
override fun isSoundEffectsEnabled(): Boolean =
|
||||
preferencesManager.getBoolean(PREFERENCE_SOUND_EFFECTS, false)
|
||||
|
||||
override fun setSoundEffectsEnabled(value: Boolean) {
|
||||
preferencesManager.putBoolean(PREFERENCE_SOUND_EFFECTS, value)
|
||||
}
|
||||
|
||||
override fun shouldMigrateFromCloud(): Boolean =
|
||||
preferencesManager.getBoolean(PREFERENCE_SHOULD_MIGRATE_FROM_CLOUD, true)
|
||||
|
||||
override fun setMigrateFromCloud(value: Boolean) {
|
||||
preferencesManager.putBoolean(PREFERENCE_SHOULD_MIGRATE_FROM_CLOUD, value)
|
||||
}
|
||||
|
||||
override fun showWindowsWhenFinishGame(): Boolean =
|
||||
preferencesManager.getBoolean(PREFERENCE_SHOW_WINDOWS, true)
|
||||
|
||||
|
@ -93,6 +120,10 @@ class PreferencesRepository(
|
|||
override fun customLongPressTimeout(): Long =
|
||||
preferencesManager.getInt(PREFERENCE_LONG_PRESS_TIMEOUT, ViewConfiguration.getLongPressTimeout()).toLong()
|
||||
|
||||
override fun setCustomLongPressTimeout(value: Long) {
|
||||
preferencesManager.putInt(PREFERENCE_LONG_PRESS_TIMEOUT, value.toInt())
|
||||
}
|
||||
|
||||
override fun themeId(): Long =
|
||||
preferencesManager.getInt(PREFERENCE_CUSTOM_THEME, 0).toLong()
|
||||
|
||||
|
@ -195,10 +226,18 @@ class PreferencesRepository(
|
|||
return preferencesManager.getBoolean(PREFERENCE_USE_HELP, false)
|
||||
}
|
||||
|
||||
override fun setHelp(value: Boolean) {
|
||||
preferencesManager.putBoolean(PREFERENCE_USE_HELP, value)
|
||||
}
|
||||
|
||||
override fun squareRadius(): Int {
|
||||
return preferencesManager.getInt(PREFERENCE_SQUARE_RADIUS, 2)
|
||||
}
|
||||
|
||||
override fun setSquareRadius(value: Int) {
|
||||
preferencesManager.putInt(PREFERENCE_SQUARE_RADIUS, value)
|
||||
}
|
||||
|
||||
override fun getTips(): Int {
|
||||
return preferencesManager.getInt(PREFERENCE_TIPS, 5)
|
||||
}
|
||||
|
@ -252,5 +291,6 @@ class PreferencesRepository(
|
|||
private const val PREFERENCE_EXTRA_TIPS = "preference_extra_tips"
|
||||
private const val PREFERENCE_SHOW_WINDOWS = "preference_show_windows"
|
||||
private const val PREFERENCE_USE_OPEN_SWITCH_CONTROL = "preference_use_open_switch_control"
|
||||
private const val PREFERENCE_SHOULD_MIGRATE_FROM_CLOUD = "preference_should_migrate_from_cloud"
|
||||
}
|
||||
}
|
||||
|
|
22
common/src/main/res/drawable-night/new_splash.xml
Normal file
22
common/src/main/res/drawable-night/new_splash.xml
Normal file
|
@ -0,0 +1,22 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="200dp"
|
||||
android:height="200dp"
|
||||
android:viewportWidth="187.5"
|
||||
android:viewportHeight="187.5">
|
||||
<path
|
||||
android:pathData="m88.569,20.255a73.602,73.602 0,0 0,-17.187 3.4l-2.311,27.252 -26.94,-9.324a73.602,73.602 90,0 0,-10.276 12.877L48.552,78.169 20.719,88.803a73.602,73.602 0,0 0,-0.159 4.84,73.602 73.602,90 0,0 0.814,10.917l28.983,7.683 -14.584,26.212a73.602,73.602 90,0 0,10.879 11.404l26.989,-12.674 5.495,28.51a73.602,73.602 90,0 0,15.024 1.55,73.602 73.602,90 0,0 1.354,-0.013L107.511,141.325 128.774,158.598a73.602,73.602 90,0 0,14.35 -10.002l-7.007,-25.871 25.831,-0.41a73.602,73.602 90,0 0,4.992 -17.699l-20.865,-14.527 18.93,-16.403a73.602,73.602 0,0 0,-7.339 -17.248l-24.941,2.249 4.013,-25.08a73.602,73.602 90,0 0,-16.228 -8.687l-18.195,18.294z"
|
||||
android:strokeAlpha="0.698615"
|
||||
android:strokeLineJoin="round"
|
||||
android:strokeWidth="95.1572"
|
||||
android:fillColor="#ffffff"
|
||||
android:strokeColor="#00000000"
|
||||
android:strokeLineCap="round"/>
|
||||
<path
|
||||
android:pathData="M93.75,93.75m-60.612,0a60.612,60.612 45,1 1,121.224 0a60.612,60.612 135,1 1,-121.224 0"
|
||||
android:strokeAlpha="0.698615"
|
||||
android:strokeLineJoin="round"
|
||||
android:strokeWidth="42.2765"
|
||||
android:fillColor="#ffffff"
|
||||
android:strokeColor="#00000000"
|
||||
android:strokeLineCap="round"/>
|
||||
</vector>
|
|
@ -2,12 +2,8 @@
|
|||
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item>
|
||||
<shape android:shape="rectangle">
|
||||
<solid android:color="#ff212121" />
|
||||
<solid android:color="@color/launcher_background_night" />
|
||||
</shape>
|
||||
</item>
|
||||
<item>
|
||||
<bitmap
|
||||
android:gravity="center"
|
||||
android:src="@drawable/splash_image" />
|
||||
</item>
|
||||
<item android:gravity="center" android:drawable="@drawable/new_splash"/>
|
||||
</layer-list>
|
||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 6.1 KiB |
22
common/src/main/res/drawable/new_splash.xml
Normal file
22
common/src/main/res/drawable/new_splash.xml
Normal file
|
@ -0,0 +1,22 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="200dp"
|
||||
android:height="200dp"
|
||||
android:viewportWidth="187.5"
|
||||
android:viewportHeight="187.5">
|
||||
<path
|
||||
android:pathData="m88.569,20.255a73.602,73.602 0,0 0,-17.187 3.4l-2.311,27.252 -26.94,-9.324a73.602,73.602 90,0 0,-10.276 12.877L48.552,78.169 20.719,88.803a73.602,73.602 0,0 0,-0.159 4.84,73.602 73.602,90 0,0 0.814,10.917l28.983,7.683 -14.584,26.212a73.602,73.602 90,0 0,10.879 11.404l26.989,-12.674 5.495,28.51a73.602,73.602 90,0 0,15.024 1.55,73.602 73.602,90 0,0 1.354,-0.013L107.511,141.325 128.774,158.598a73.602,73.602 90,0 0,14.35 -10.002l-7.007,-25.871 25.831,-0.41a73.602,73.602 90,0 0,4.992 -17.699l-20.865,-14.527 18.93,-16.403a73.602,73.602 0,0 0,-7.339 -17.248l-24.941,2.249 4.013,-25.08a73.602,73.602 90,0 0,-16.228 -8.687l-18.195,18.294z"
|
||||
android:strokeAlpha="0.698615"
|
||||
android:strokeLineJoin="round"
|
||||
android:strokeWidth="95.1572"
|
||||
android:fillColor="#1a1a1a"
|
||||
android:strokeColor="#00000000"
|
||||
android:strokeLineCap="round"/>
|
||||
<path
|
||||
android:pathData="M93.75,93.75m-60.612,0a60.612,60.612 45,1 1,121.224 0a60.612,60.612 135,1 1,-121.224 0"
|
||||
android:strokeAlpha="0.698615"
|
||||
android:strokeLineJoin="round"
|
||||
android:strokeWidth="42.2765"
|
||||
android:fillColor="#1a1a1a"
|
||||
android:strokeColor="#00000000"
|
||||
android:strokeLineCap="round"/>
|
||||
</vector>
|
|
@ -2,12 +2,8 @@
|
|||
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item>
|
||||
<shape android:shape="rectangle">
|
||||
<solid android:color="@android:color/white" />
|
||||
<solid android:color="@color/launcher_background_start" />
|
||||
</shape>
|
||||
</item>
|
||||
<item>
|
||||
<bitmap
|
||||
android:gravity="center"
|
||||
android:src="@drawable/splash_image" />
|
||||
</item>
|
||||
<item android:gravity="center" android:drawable="@drawable/new_splash"/>
|
||||
</layer-list>
|
||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 9.1 KiB |
|
@ -95,6 +95,7 @@
|
|||
<string name="translation">Vertalings</string>
|
||||
<string name="licenses">Licenses</string>
|
||||
<string name="google_play_games">Google Play Games</string>
|
||||
<string name="loading">Laai…</string>
|
||||
<string name="connect">Konnekteer</string>
|
||||
<string name="connecting">Besig om aanlyn te koppel…</string>
|
||||
<string name="disconnect">Ontkoppel</string>
|
||||
|
|
|
@ -95,6 +95,7 @@
|
|||
<string name="translation">الترجمة</string>
|
||||
<string name="licenses">التراخيص</string>
|
||||
<string name="google_play_games">ألعاب Google Play</string>
|
||||
<string name="loading">جاري التحميل…</string>
|
||||
<string name="connect">الاتصال</string>
|
||||
<string name="connecting">جاري الاتصال…</string>
|
||||
<string name="disconnect">قطع الاتصال</string>
|
||||
|
|
|
@ -95,6 +95,7 @@
|
|||
<string name="translation">Превод</string>
|
||||
<string name="licenses">Лицензи</string>
|
||||
<string name="google_play_games">Google Play Games</string>
|
||||
<string name="loading">Зареждане…</string>
|
||||
<string name="connect">Свързване</string>
|
||||
<string name="connecting">Свързване…</string>
|
||||
<string name="disconnect">Прекъсване</string>
|
||||
|
|
|
@ -95,6 +95,7 @@
|
|||
<string name="translation">Traduccions</string>
|
||||
<string name="licenses">Llicències</string>
|
||||
<string name="google_play_games">Google Play Jocs</string>
|
||||
<string name="loading">Carregant…</string>
|
||||
<string name="connect">Connectar</string>
|
||||
<string name="connecting">Connectant…</string>
|
||||
<string name="disconnect">Desconnectar</string>
|
||||
|
|
|
@ -95,6 +95,7 @@
|
|||
<string name="translation">Překlad</string>
|
||||
<string name="licenses">Licence</string>
|
||||
<string name="google_play_games">Google Play Games</string>
|
||||
<string name="loading">Načítání…</string>
|
||||
<string name="connect">Připojit</string>
|
||||
<string name="connecting">Připojování…</string>
|
||||
<string name="disconnect">Odpojit</string>
|
||||
|
|
|
@ -95,6 +95,7 @@
|
|||
<string name="translation">Oversættelser</string>
|
||||
<string name="licenses">Licenser</string>
|
||||
<string name="google_play_games">Google Play Spil</string>
|
||||
<string name="loading">Indlæser…</string>
|
||||
<string name="connect">Tilslut</string>
|
||||
<string name="connecting">Tilslutter…</string>
|
||||
<string name="disconnect">Afbryd</string>
|
||||
|
|
|
@ -46,7 +46,7 @@
|
|||
<string name="system">System</string>
|
||||
<string name="rating">Rückmeldung</string>
|
||||
<string name="support_title">Unterstütze uns!</string>
|
||||
<string name="support_action">Hilfestellung</string>
|
||||
<string name="support_action">Unterstützung</string>
|
||||
<string name="rating_message">Wenn dir dieses Spiel gefällt, gib uns bitte eine Rückmeldung. Es wird uns sehr helfen.</string>
|
||||
<string name="used_software_text">Dieses Spiel benutzt folgende Software von Drittanbietern:</string>
|
||||
<string name="translators_text">Dieses Spiel wurde von den folgenden Personen übersetzt:</string>
|
||||
|
@ -95,6 +95,7 @@
|
|||
<string name="translation">Übersetzung</string>
|
||||
<string name="licenses">Lizenzen</string>
|
||||
<string name="google_play_games">Google Play Games</string>
|
||||
<string name="loading">Wird geladen...</string>
|
||||
<string name="connect">Verbinden</string>
|
||||
<string name="connecting">Verbindung wird hergestellt…</string>
|
||||
<string name="disconnect">Trennen</string>
|
||||
|
@ -121,9 +122,9 @@
|
|||
<string name="flag_removed">Markierung entfernt!</string>
|
||||
<string name="remove_ad">Werbung entfernen</string>
|
||||
<string name="help">Hilfe</string>
|
||||
<string name="show_windows">Show windows</string>
|
||||
<string name="switch_control">Switch: Flag and Open</string>
|
||||
<string name="switch_control_desc">Use button to switch between Flag and Open</string>
|
||||
<string name="show_windows">Fenster anzeigen</string>
|
||||
<string name="switch_control">Umschalter: Markieren und Öffnen</string>
|
||||
<string name="switch_control_desc">Benutze den Knopf, um zwischen Markierung und Öffnen zu wechseln</string>
|
||||
<string name="app_description">Du musst ein rechteckiges Spielfeld, das versteckte Minen enthält, räumen, ohne irgendeine davon zur Explosion zu bringen.</string>
|
||||
<string name="app_name">Antimine</string>
|
||||
</resources>
|
||||
|
|
|
@ -95,6 +95,7 @@
|
|||
<string name="translation">Μετάφραση</string>
|
||||
<string name="licenses">Άδειες</string>
|
||||
<string name="google_play_games">Google Play Games</string>
|
||||
<string name="loading">Φόρτωση…</string>
|
||||
<string name="connect">Σύνδεση</string>
|
||||
<string name="connecting">Σύνδεση…</string>
|
||||
<string name="disconnect">Αποσύνδεση</string>
|
||||
|
|
|
@ -95,6 +95,7 @@
|
|||
<string name="translation">Translation</string>
|
||||
<string name="licenses">Licenses</string>
|
||||
<string name="google_play_games">Google Play Games</string>
|
||||
<string name="loading">Loading…</string>
|
||||
<string name="connect">Connect</string>
|
||||
<string name="connecting">Connecting…</string>
|
||||
<string name="disconnect">Disconnect</string>
|
||||
|
|
|
@ -95,6 +95,7 @@
|
|||
<string name="translation">Traducción</string>
|
||||
<string name="licenses">Licencias</string>
|
||||
<string name="google_play_games">Google Play Games</string>
|
||||
<string name="loading">Cargando…</string>
|
||||
<string name="connect">Conectar</string>
|
||||
<string name="connecting">Conectando…</string>
|
||||
<string name="disconnect">Desconectar</string>
|
||||
|
|
|
@ -95,6 +95,7 @@
|
|||
<string name="translation">Käännökset</string>
|
||||
<string name="licenses">Lisenssit</string>
|
||||
<string name="google_play_games">Google Play Pelit</string>
|
||||
<string name="loading">Ladataan…</string>
|
||||
<string name="connect">Yhdistä</string>
|
||||
<string name="connecting">Yhdistetään…</string>
|
||||
<string name="disconnect">Katkaise yhteys</string>
|
||||
|
|
|
@ -95,6 +95,7 @@
|
|||
<string name="translation">Traduction</string>
|
||||
<string name="licenses">Licences</string>
|
||||
<string name="google_play_games">Google Play Games</string>
|
||||
<string name="loading">Chargement…</string>
|
||||
<string name="connect">Connexion</string>
|
||||
<string name="connecting">Connexion en cours…</string>
|
||||
<string name="disconnect">Déconnexion</string>
|
||||
|
|
|
@ -95,6 +95,7 @@
|
|||
<string name="translation">अनुवाद</string>
|
||||
<string name="licenses">लाइसेंस</string>
|
||||
<string name="google_play_games">Google Play Games</string>
|
||||
<string name="loading">लोड हो रहा है…</string>
|
||||
<string name="connect">कनेक्ट करें</string>
|
||||
<string name="connecting">संपर्क बना रहा है...</string>
|
||||
<string name="disconnect">संपर्क तोड़ें</string>
|
||||
|
|
|
@ -95,6 +95,7 @@
|
|||
<string name="translation">Fordítás</string>
|
||||
<string name="licenses">Licencek</string>
|
||||
<string name="google_play_games">Google Play Játékok</string>
|
||||
<string name="loading">Betöltés…</string>
|
||||
<string name="connect">Csatlakozás</string>
|
||||
<string name="connecting">Csatlakozás…</string>
|
||||
<string name="disconnect">Lecsatlakozás</string>
|
||||
|
|
|
@ -95,6 +95,7 @@
|
|||
<string name="translation">Terjemahan</string>
|
||||
<string name="licenses">Lisensi</string>
|
||||
<string name="google_play_games">Google Play Games</string>
|
||||
<string name="loading">Memuat…</string>
|
||||
<string name="connect">Menyambungkan</string>
|
||||
<string name="connecting">Menghubungkan…</string>
|
||||
<string name="disconnect">Terputus</string>
|
||||
|
|
|
@ -95,6 +95,7 @@
|
|||
<string name="translation">Traduzione</string>
|
||||
<string name="licenses">Licenze</string>
|
||||
<string name="google_play_games">Google Play Games</string>
|
||||
<string name="loading">Caricamento…</string>
|
||||
<string name="connect">Connetti</string>
|
||||
<string name="connecting">Connessione in corso…</string>
|
||||
<string name="disconnect">Disconnetti</string>
|
||||
|
|
|
@ -95,6 +95,7 @@
|
|||
<string name="translation">תרגומים</string>
|
||||
<string name="licenses">רשיונות</string>
|
||||
<string name="google_play_games">Google Play Games</string>
|
||||
<string name="loading">טוען…</string>
|
||||
<string name="connect">התחבר</string>
|
||||
<string name="connecting">מתחבר…</string>
|
||||
<string name="disconnect">נתק</string>
|
||||
|
|
|
@ -95,6 +95,7 @@
|
|||
<string name="translation">翻訳</string>
|
||||
<string name="licenses">ライセンス</string>
|
||||
<string name="google_play_games">Google Play ゲーム</string>
|
||||
<string name="loading">読み込み中…</string>
|
||||
<string name="connect">接続</string>
|
||||
<string name="connecting">接続しています...</string>
|
||||
<string name="disconnect">切断</string>
|
||||
|
|
|
@ -95,6 +95,7 @@
|
|||
<string name="translation">번역</string>
|
||||
<string name="licenses">라이선스</string>
|
||||
<string name="google_play_games">Google Play 게임</string>
|
||||
<string name="loading">시작중…</string>
|
||||
<string name="connect">연결하기</string>
|
||||
<string name="connecting">연결중…</string>
|
||||
<string name="disconnect">연결 해제</string>
|
||||
|
|
|
@ -21,4 +21,6 @@
|
|||
|
||||
<color name="view_cover">#171717</color>
|
||||
<color name="view_clean">#ff424242</color>
|
||||
|
||||
<color name="splash_text_color">#FFFFFF</color>
|
||||
</resources>
|
||||
|
|
|
@ -95,6 +95,7 @@
|
|||
<string name="translation">Vertaling</string>
|
||||
<string name="licenses">Licenties</string>
|
||||
<string name="google_play_games">Google Play Games</string>
|
||||
<string name="loading">Bezig met laden…</string>
|
||||
<string name="connect">Verbinden</string>
|
||||
<string name="connecting">Verbinden…</string>
|
||||
<string name="disconnect">Verbinding verbreken</string>
|
||||
|
|
|
@ -95,6 +95,7 @@
|
|||
<string name="translation">Oversettelse</string>
|
||||
<string name="licenses">Lisenser</string>
|
||||
<string name="google_play_games">Google Play Spill</string>
|
||||
<string name="loading">Laster…</string>
|
||||
<string name="connect">Koble til</string>
|
||||
<string name="connecting">Kobler til…</string>
|
||||
<string name="disconnect">Koble fra</string>
|
||||
|
|
|
@ -65,7 +65,7 @@
|
|||
<string name="open_areas">Odkryte pola</string>
|
||||
<string name="total_time">Całkowity czas gry</string>
|
||||
<string name="average_time">Średni czas gry</string>
|
||||
<string name="shortest_time">Najkrótszy czas gry</string>
|
||||
<string name="shortest_time">Najlepszy czas gry</string>
|
||||
<string name="performance">Skuteczność</string>
|
||||
<string name="ok">OK</string>
|
||||
<string name="use_question_mark">Używaj Znaku zapytania</string>
|
||||
|
@ -95,6 +95,7 @@
|
|||
<string name="translation">Tłumaczenie</string>
|
||||
<string name="licenses">Licencje</string>
|
||||
<string name="google_play_games">Gry Google Play</string>
|
||||
<string name="loading">Wczytywanie…</string>
|
||||
<string name="connect">Połącz</string>
|
||||
<string name="connecting">Łączenie…</string>
|
||||
<string name="disconnect">Rozłącz</string>
|
||||
|
|
|
@ -95,6 +95,7 @@
|
|||
<string name="translation">Tradução</string>
|
||||
<string name="licenses">Licenças</string>
|
||||
<string name="google_play_games">Google Play Jogos</string>
|
||||
<string name="loading">Carregando…</string>
|
||||
<string name="connect">Conectar</string>
|
||||
<string name="connecting">Conectando…</string>
|
||||
<string name="disconnect">Desconectar</string>
|
||||
|
|
|
@ -95,6 +95,7 @@
|
|||
<string name="translation">Tradução</string>
|
||||
<string name="licenses">Licenças</string>
|
||||
<string name="google_play_games">Google Play Jogos</string>
|
||||
<string name="loading">A carregar…</string>
|
||||
<string name="connect">Conectar</string>
|
||||
<string name="connecting">Conectando…</string>
|
||||
<string name="disconnect">Desconectar</string>
|
||||
|
|
|
@ -95,6 +95,7 @@
|
|||
<string name="translation">Translare</string>
|
||||
<string name="licenses">Licenţe</string>
|
||||
<string name="google_play_games">Jocurile Google Play</string>
|
||||
<string name="loading">Încărcare…</string>
|
||||
<string name="connect">Conectează-te</string>
|
||||
<string name="connecting">Se conectează…</string>
|
||||
<string name="disconnect">Deconectează</string>
|
||||
|
|
|
@ -95,6 +95,7 @@
|
|||
<string name="translation">Перевод</string>
|
||||
<string name="licenses">Лицензии</string>
|
||||
<string name="google_play_games">Google Play Games</string>
|
||||
<string name="loading">Загрузка…</string>
|
||||
<string name="connect">Подключиться</string>
|
||||
<string name="connecting">Подключение…</string>
|
||||
<string name="disconnect">Отключиться</string>
|
||||
|
|
|
@ -95,6 +95,7 @@
|
|||
<string name="translation">Translation</string>
|
||||
<string name="licenses">Licenses</string>
|
||||
<string name="google_play_games">Google Play Games</string>
|
||||
<string name="loading">Loading…</string>
|
||||
<string name="connect">Connect</string>
|
||||
<string name="connecting">Connecting…</string>
|
||||
<string name="disconnect">Disconnect</string>
|
||||
|
|
|
@ -95,6 +95,7 @@
|
|||
<string name="translation">แปลภาษา</string>
|
||||
<string name="licenses">ใบอนุญาต</string>
|
||||
<string name="google_play_games">Google Play Games</string>
|
||||
<string name="loading">กำลังโหลด...</string>
|
||||
<string name="connect">เชื่อมต่อ</string>
|
||||
<string name="connecting">กำลังเชื่อมต่อ…</string>
|
||||
<string name="disconnect">ตัดการเชื่อมต่อ</string>
|
||||
|
|
|
@ -95,6 +95,7 @@
|
|||
<string name="translation">Çeviri</string>
|
||||
<string name="licenses">Lisanslar</string>
|
||||
<string name="google_play_games">Google Play Oyunlar</string>
|
||||
<string name="loading">Yükleniyor…</string>
|
||||
<string name="connect">Bağlan</string>
|
||||
<string name="connecting">Bağlanıyor…</string>
|
||||
<string name="disconnect">Bağlantıyı kes</string>
|
||||
|
|
|
@ -95,6 +95,7 @@
|
|||
<string name="translation">Переклад</string>
|
||||
<string name="licenses">Ліцензії</string>
|
||||
<string name="google_play_games">Google Play Games</string>
|
||||
<string name="loading">Завантаження…</string>
|
||||
<string name="connect">Під’єднатись</string>
|
||||
<string name="connecting">Підключення…</string>
|
||||
<string name="disconnect">Відключитись</string>
|
||||
|
|
|
@ -95,6 +95,7 @@
|
|||
<string name="translation">Dịch thuật</string>
|
||||
<string name="licenses">Giấy phép</string>
|
||||
<string name="google_play_games">Google Play Trò chơi</string>
|
||||
<string name="loading">Đang tải…</string>
|
||||
<string name="connect">Kết nối</string>
|
||||
<string name="connecting">Đang kết nối…</string>
|
||||
<string name="disconnect">Ngừng kết nối</string>
|
||||
|
|
|
@ -95,6 +95,7 @@
|
|||
<string name="translation">翻译</string>
|
||||
<string name="licenses">许可证</string>
|
||||
<string name="google_play_games">Google Play 游戏</string>
|
||||
<string name="loading">启动中…</string>
|
||||
<string name="connect">连接</string>
|
||||
<string name="connecting">正在连接…</string>
|
||||
<string name="disconnect">断开</string>
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
|
||||
<color name="launcher_background_start">#FCC216</color>
|
||||
<color name="launcher_background_end">#FF8C3A</color>
|
||||
<color name="launcher_background_night">#212121</color>
|
||||
|
||||
<color name="accent">#FFD32F2F</color>
|
||||
<color name="install_button">#00C853</color>
|
||||
|
@ -29,4 +30,6 @@
|
|||
|
||||
<color name="view_cover">#424242</color>
|
||||
<color name="view_clean">#d5d2cc</color>
|
||||
|
||||
<color name="splash_text_color">#000000</color>
|
||||
</resources>
|
||||
|
|
|
@ -95,6 +95,7 @@
|
|||
<string name="translation">Translation</string>
|
||||
<string name="licenses">Licenses</string>
|
||||
<string name="google_play_games">Google Play Games</string>
|
||||
<string name="loading">Loading…</string>
|
||||
<string name="connect">Connect</string>
|
||||
<string name="connecting">Connecting…</string>
|
||||
<string name="disconnect">Disconnect</string>
|
||||
|
|
|
@ -19,10 +19,8 @@
|
|||
<item name="android:windowTranslucentNavigation">true</item>
|
||||
</style>
|
||||
|
||||
<style name="Theme.Splash" parent="Theme.AppCompat.NoActionBar">
|
||||
<style name="Theme.Splash" parent="Theme.AppCompat.DayNight.NoActionBar">
|
||||
<item name="android:windowBackground">@drawable/splash</item>
|
||||
<item name="windowActionBar">false</item>
|
||||
<item name="windowNoTitle">true</item>
|
||||
<item name="android:windowDrawsSystemBarBackgrounds">true</item>
|
||||
<item name="android:statusBarColor">@android:color/transparent</item>
|
||||
<item name="android:windowTranslucentStatus">true</item>
|
||||
|
|
9
external/src/main/java/dev/lucasnlm/external/ICloudStorageManager.kt
vendored
Normal file
9
external/src/main/java/dev/lucasnlm/external/ICloudStorageManager.kt
vendored
Normal file
|
@ -0,0 +1,9 @@
|
|||
package dev.lucasnlm.external
|
||||
|
||||
import dev.lucasnlm.external.model.CloudSave
|
||||
|
||||
interface ICloudStorageManager {
|
||||
fun uploadSave(cloudSave: CloudSave)
|
||||
|
||||
suspend fun getSave(playId: String): CloudSave?
|
||||
}
|
|
@ -25,8 +25,10 @@ enum class Leaderboard(
|
|||
}
|
||||
|
||||
interface IPlayGamesManager {
|
||||
fun playerId(): String?
|
||||
fun hasGooglePlayGames(): Boolean
|
||||
fun silentLogin(activity: Activity)
|
||||
fun silentLogin()
|
||||
fun showPlayPopUp(activity: Activity)
|
||||
fun getLoginIntent(): Intent?
|
||||
fun handleLoginResult(data: Intent?)
|
||||
fun isLogged(): Boolean
|
||||
|
|
53
external/src/main/java/dev/lucasnlm/external/model/CloudSave.kt
vendored
Normal file
53
external/src/main/java/dev/lucasnlm/external/model/CloudSave.kt
vendored
Normal file
|
@ -0,0 +1,53 @@
|
|||
package dev.lucasnlm.external.model
|
||||
|
||||
data class CloudSave(
|
||||
val playId: String,
|
||||
val completeTutorial: Int,
|
||||
val selectedTheme: Int,
|
||||
val squareRadius: Int,
|
||||
val squareSize: Int,
|
||||
val touchTiming: Int,
|
||||
val questionMark: Int,
|
||||
val gameAssistance: Int,
|
||||
val help: Int,
|
||||
val hapticFeedback: Int,
|
||||
val soundEffects: Int,
|
||||
val stats: List<HashMap<String, String>>,
|
||||
val premiumFeatures: Int,
|
||||
val controlStyle: Int,
|
||||
)
|
||||
|
||||
fun CloudSave.toHashMap(): HashMap<String, Any> = hashMapOf(
|
||||
"completeTutorial" to completeTutorial,
|
||||
"selectedTheme" to selectedTheme,
|
||||
"squareRadius" to squareRadius,
|
||||
"squareSize" to squareSize,
|
||||
"touchTiming" to touchTiming,
|
||||
"questionMark" to questionMark,
|
||||
"gameAssistance" to gameAssistance,
|
||||
"help" to help,
|
||||
"hapticFeedback" to hapticFeedback,
|
||||
"soundEffects" to soundEffects,
|
||||
"stats" to stats,
|
||||
"premiumFeatures" to premiumFeatures,
|
||||
"controlStyle" to controlStyle,
|
||||
)
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
fun cloudSaveOf(id: String, data: Map<String, Any>) =
|
||||
CloudSave(
|
||||
id,
|
||||
data["completeTutorial"].toString().toInt(),
|
||||
data["selectedTheme"].toString().toInt(),
|
||||
data["squareRadius"].toString().toInt(),
|
||||
data["squareSize"].toString().toInt(),
|
||||
data["touchTiming"].toString().toInt(),
|
||||
data["questionMark"].toString().toInt(),
|
||||
data["gameAssistance"].toString().toInt(),
|
||||
data["help"].toString().toInt(),
|
||||
data["hapticFeedback"].toString().toInt(),
|
||||
data["soundEffects"].toString().toInt(),
|
||||
data["stats"] as List<HashMap<String, String>>,
|
||||
data["premiumFeatures"].toString().toInt(),
|
||||
data["controlStyle"].toString().toInt(),
|
||||
)
|
|
@ -6,8 +6,8 @@ android {
|
|||
compileSdkVersion 30
|
||||
|
||||
defaultConfig {
|
||||
versionCode 802031
|
||||
versionName '8.2.3'
|
||||
versionCode 803001
|
||||
versionName '8.3.0'
|
||||
minSdkVersion 21
|
||||
targetSdkVersion 30
|
||||
}
|
||||
|
|
14
foss/src/main/java/dev/lucasnlm/external/CloudStorageManager.kt
vendored
Normal file
14
foss/src/main/java/dev/lucasnlm/external/CloudStorageManager.kt
vendored
Normal file
|
@ -0,0 +1,14 @@
|
|||
package dev.lucasnlm.external
|
||||
|
||||
import dev.lucasnlm.external.model.CloudSave
|
||||
|
||||
class CloudStorageManager : ICloudStorageManager {
|
||||
override fun uploadSave(cloudSave: CloudSave) {
|
||||
// FOSS build doesn't support cloud save.
|
||||
}
|
||||
|
||||
override suspend fun getSave(playId: String): CloudSave? {
|
||||
// FOSS build doesn't support cloud save.
|
||||
return null
|
||||
}
|
||||
}
|
|
@ -7,9 +7,15 @@ import android.content.Intent
|
|||
class PlayGamesManager(
|
||||
context: Context,
|
||||
) : IPlayGamesManager {
|
||||
override fun playerId(): String? = null
|
||||
|
||||
override fun hasGooglePlayGames(): Boolean = false
|
||||
|
||||
override fun silentLogin(activity: Activity) {
|
||||
override fun silentLogin() {
|
||||
// F-droid build doesn't have Google Play Games
|
||||
}
|
||||
|
||||
override fun showPlayPopUp(activity: Activity) {
|
||||
// F-droid build doesn't have Google Play Games
|
||||
}
|
||||
|
||||
|
|
|
@ -10,8 +10,8 @@ android {
|
|||
compileSdkVersion 30
|
||||
|
||||
defaultConfig {
|
||||
versionCode 802031
|
||||
versionName '8.2.3'
|
||||
versionCode 803001
|
||||
versionName '8.3.0'
|
||||
minSdkVersion 21
|
||||
targetSdkVersion 30
|
||||
}
|
||||
|
@ -38,16 +38,17 @@ dependencies {
|
|||
implementation project(':external')
|
||||
|
||||
// Google
|
||||
implementation 'com.android.billingclient:billing-ktx:3.0.0'
|
||||
implementation 'com.android.billingclient:billing-ktx:3.0.1'
|
||||
implementation 'com.google.android.gms:play-services-instantapps:17.0.0'
|
||||
implementation 'com.google.android.gms:play-services-games:20.0.0'
|
||||
implementation 'com.google.android.gms:play-services-games:20.0.1'
|
||||
implementation 'com.google.android.gms:play-services-auth:18.1.0'
|
||||
implementation 'com.google.android.gms:play-services-ads:19.3.0'
|
||||
implementation 'com.google.android.gms:play-services-ads:19.4.0'
|
||||
implementation 'com.google.android.play:core-ktx:1.8.1'
|
||||
|
||||
// Firebase
|
||||
implementation 'com.google.firebase:firebase-analytics-ktx:17.5.0'
|
||||
implementation 'com.google.firebase:firebase-crashlytics:17.2.1'
|
||||
implementation 'com.google.firebase:firebase-analytics-ktx:17.6.0'
|
||||
implementation 'com.google.firebase:firebase-crashlytics:17.2.2'
|
||||
implementation 'com.google.firebase:firebase-firestore-ktx:21.7.1'
|
||||
|
||||
// Kotlin
|
||||
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.9'
|
||||
|
|
66
proprietary/src/main/java/dev/lucasnlm/external/CloudStorageManager.kt
vendored
Normal file
66
proprietary/src/main/java/dev/lucasnlm/external/CloudStorageManager.kt
vendored
Normal file
|
@ -0,0 +1,66 @@
|
|||
package dev.lucasnlm.external
|
||||
|
||||
import android.util.Log
|
||||
import com.google.android.gms.tasks.Tasks
|
||||
import com.google.firebase.firestore.FirebaseFirestore
|
||||
import com.google.firebase.firestore.ktx.firestore
|
||||
import com.google.firebase.ktx.Firebase
|
||||
import dev.lucasnlm.external.model.CloudSave
|
||||
import dev.lucasnlm.external.model.cloudSaveOf
|
||||
import dev.lucasnlm.external.model.toHashMap
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import kotlinx.coroutines.withContext
|
||||
|
||||
class CloudStorageManager : ICloudStorageManager {
|
||||
private val db by lazy { Firebase.firestore }
|
||||
|
||||
override fun uploadSave(cloudSave: CloudSave) {
|
||||
FirebaseFirestore.setLoggingEnabled(true)
|
||||
val data = cloudSave.toHashMap()
|
||||
Tasks.await(
|
||||
db.collection(SAVES)
|
||||
.document(cloudSave.playId)
|
||||
.set(data)
|
||||
.addOnCompleteListener {
|
||||
Log.v(TAG, "Cloud storage complete")
|
||||
}
|
||||
.addOnCanceledListener {
|
||||
Log.v(TAG, "Cloud storage canceled")
|
||||
}
|
||||
.addOnFailureListener {
|
||||
Log.e(TAG, "Cloud storage error", it)
|
||||
}
|
||||
.addOnSuccessListener {
|
||||
Log.v(TAG, "Cloud storage success")
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
@Suppress("BlockingMethodInNonBlockingContext")
|
||||
override suspend fun getSave(playId: String): CloudSave? {
|
||||
return runBlocking {
|
||||
try {
|
||||
withContext(Dispatchers.IO) {
|
||||
val result = Tasks.await(
|
||||
db.collection(SAVES)
|
||||
.document(playId)
|
||||
.get()
|
||||
)
|
||||
|
||||
result.data?.let {
|
||||
cloudSaveOf(playId, it.toMap())
|
||||
}
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
Log.e(TAG, "Fail to load save on cloud", e)
|
||||
null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
val TAG = CloudStorageManager::class.simpleName
|
||||
const val SAVES = "saves"
|
||||
}
|
||||
}
|
|
@ -10,6 +10,7 @@ import com.google.android.gms.auth.api.signin.GoogleSignIn
|
|||
import com.google.android.gms.auth.api.signin.GoogleSignInAccount
|
||||
import com.google.android.gms.auth.api.signin.GoogleSignInOptions
|
||||
import com.google.android.gms.games.Games
|
||||
import com.google.android.gms.tasks.Tasks
|
||||
|
||||
class PlayGamesManager(
|
||||
private val context: Context,
|
||||
|
@ -17,28 +18,33 @@ class PlayGamesManager(
|
|||
private var account: GoogleSignInAccount? = null
|
||||
|
||||
private fun setupPopUp(activity: Activity, account: GoogleSignInAccount) {
|
||||
Games.getGamesClient(context, account).setViewForPopups(activity.findViewById(android.R.id.content))
|
||||
Games.getGamesClient(context, account).setGravityForPopups(Gravity.TOP or Gravity.END)
|
||||
Games.getGamesClient(context, account)
|
||||
.setViewForPopups(activity.findViewById(android.R.id.content))
|
||||
Games.getGamesClient(context, account)
|
||||
.setGravityForPopups(Gravity.TOP or Gravity.END)
|
||||
}
|
||||
|
||||
override fun playerId(): String? {
|
||||
return account?.let {
|
||||
Tasks.await(Games.getPlayersClient(context, it).currentPlayerId)
|
||||
}
|
||||
}
|
||||
|
||||
override fun showPlayPopUp(activity: Activity) {
|
||||
if (!activity.isFinishing) {
|
||||
account?.let {
|
||||
setupPopUp(activity, it)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun hasGooglePlayGames(): Boolean = true
|
||||
|
||||
override fun silentLogin(activity: Activity) {
|
||||
override fun silentLogin() {
|
||||
val signInOptions = GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_GAMES_SIGN_IN).build()
|
||||
val lastAccount: GoogleSignInAccount? = GoogleSignIn.getLastSignedInAccount(context)
|
||||
|
||||
if (lastAccount != null) {
|
||||
account = lastAccount.also { setupPopUp(activity, it) }
|
||||
} else {
|
||||
GoogleSignIn
|
||||
.getClient(context, signInOptions)
|
||||
.silentSignIn()
|
||||
.addOnCompleteListener { task ->
|
||||
if (task.isSuccessful) {
|
||||
account = task.result?.also { setupPopUp(activity, it) }
|
||||
}
|
||||
}
|
||||
}
|
||||
account = lastAccount ?: Tasks.await(GoogleSignIn.getClient(context, signInOptions).silentSignIn())
|
||||
}
|
||||
|
||||
override fun getLoginIntent(): Intent? {
|
||||
|
|
|
@ -8,8 +8,8 @@ android {
|
|||
|
||||
defaultConfig {
|
||||
// versionCode and versionName must be hardcoded to support F-droid
|
||||
versionCode 802031
|
||||
versionName '8.2.3'
|
||||
versionCode 803001
|
||||
versionName '8.3.0'
|
||||
applicationId 'dev.lucasnlm.antimine'
|
||||
minSdkVersion 23
|
||||
targetSdkVersion 30
|
||||
|
|
Loading…
Reference in a new issue