Add Tips
This commit is contained in:
parent
3f2844d730
commit
98f9cd94db
33 changed files with 415 additions and 60 deletions
|
@ -8,6 +8,7 @@ import android.text.format.DateUtils
|
|||
import android.view.View
|
||||
import android.view.WindowManager
|
||||
import android.widget.FrameLayout
|
||||
import android.widget.Toast
|
||||
import androidx.appcompat.app.ActionBarDrawerToggle
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.appcompat.widget.TooltipCompat
|
||||
|
@ -58,7 +59,6 @@ import kotlinx.coroutines.flow.collect
|
|||
import kotlinx.coroutines.launch
|
||||
import org.koin.android.ext.android.inject
|
||||
import org.koin.androidx.viewmodel.ext.android.viewModel
|
||||
import java.util.Locale
|
||||
|
||||
class GameActivity : ThematicActivity(R.layout.activity_game), DialogInterface.OnDismissListener {
|
||||
private val billingManager: IBillingManager by inject()
|
||||
|
@ -188,6 +188,13 @@ class GameActivity : ThematicActivity(R.layout.activity_game), DialogInterface.O
|
|||
currentSaveId = it
|
||||
}
|
||||
)
|
||||
|
||||
tips.observe(
|
||||
this@GameActivity,
|
||||
{
|
||||
tipsCounter.text = it.toString()
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
override fun onBackPressed() {
|
||||
|
@ -248,8 +255,47 @@ class GameActivity : ThematicActivity(R.layout.activity_game), DialogInterface.O
|
|||
)
|
||||
}
|
||||
|
||||
private fun refreshShortcutIcon(isEndGame: Boolean = false) {
|
||||
if (isEndGame || instantAppManager.isEnabled(this)) {
|
||||
private fun disableShortcutIcon(hide: Boolean = false) {
|
||||
tipsCounter.visibility = View.GONE
|
||||
shortcutIcon.apply {
|
||||
visibility = if (hide) View.GONE else View.VISIBLE
|
||||
isClickable = false
|
||||
animate().alpha(0.3f).start()
|
||||
}
|
||||
}
|
||||
|
||||
private fun refreshTipShortcutIcon() {
|
||||
val tipsAmount = gameViewModel.getTips()
|
||||
|
||||
tipsCounter.apply {
|
||||
visibility = View.VISIBLE
|
||||
text = tipsAmount.toString()
|
||||
}
|
||||
|
||||
shortcutIcon.apply {
|
||||
TooltipCompat.setTooltipText(this, getString(R.string.help))
|
||||
setImageResource(R.drawable.tip)
|
||||
setColorFilter(minesCount.currentTextColor)
|
||||
visibility = View.VISIBLE
|
||||
animate().alpha(1.0f).start()
|
||||
setOnClickListener {
|
||||
lifecycleScope.launch {
|
||||
analyticsManager.sentEvent(Analytics.UseTip)
|
||||
|
||||
if (tipsAmount > 0) {
|
||||
if (!gameViewModel.revealRandomMine()) {
|
||||
Toast.makeText(applicationContext, R.string.cant_do_it_now, Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
} else {
|
||||
Toast.makeText(applicationContext, R.string.cant_do_it_now, Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun refreshEndGameShortcutIcon(victory: Boolean = false, isOldGame: Boolean) {
|
||||
if ((isOldGame || !victory) && !instantAppManager.isEnabled(this)) {
|
||||
shortcutIcon.apply {
|
||||
TooltipCompat.setTooltipText(this, getString(R.string.new_game))
|
||||
setImageResource(R.drawable.retry)
|
||||
|
@ -284,6 +330,7 @@ class GameActivity : ThematicActivity(R.layout.activity_game), DialogInterface.O
|
|||
}
|
||||
}
|
||||
|
||||
tipsCounter.visibility = View.GONE
|
||||
shortcutIcon.apply {
|
||||
when (status) {
|
||||
is Status.Over, is Status.Running -> {
|
||||
|
@ -324,7 +371,7 @@ class GameActivity : ThematicActivity(R.layout.activity_game), DialogInterface.O
|
|||
}
|
||||
|
||||
override fun onDrawerClosed(drawerView: View) {
|
||||
if (hasNoOtherFocusedDialog()) {
|
||||
if (hasNoOtherFocusedDialog() && hasActiveGameFragment()) {
|
||||
gameViewModel.resumeGame()
|
||||
}
|
||||
|
||||
|
@ -435,13 +482,6 @@ class GameActivity : ThematicActivity(R.layout.activity_game), DialogInterface.O
|
|||
|
||||
private fun loadGameFragment() {
|
||||
supportFragmentManager.apply {
|
||||
findFragmentByTag(LevelFragment.TAG)?.let { it ->
|
||||
beginTransaction().apply {
|
||||
remove(it)
|
||||
commitAllowingStateLoss()
|
||||
}
|
||||
}
|
||||
|
||||
findFragmentByTag(TutorialLevelFragment.TAG)?.let { it ->
|
||||
beginTransaction().apply {
|
||||
remove(it)
|
||||
|
@ -451,7 +491,7 @@ class GameActivity : ThematicActivity(R.layout.activity_game), DialogInterface.O
|
|||
|
||||
if (findFragmentByTag(LevelFragment.TAG) == null) {
|
||||
beginTransaction().apply {
|
||||
replace(R.id.levelContainer, LevelFragment())
|
||||
replace(R.id.levelContainer, LevelFragment(), LevelFragment.TAG)
|
||||
setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN)
|
||||
commitAllowingStateLoss()
|
||||
}
|
||||
|
@ -460,6 +500,8 @@ class GameActivity : ThematicActivity(R.layout.activity_game), DialogInterface.O
|
|||
}
|
||||
|
||||
private fun loadGameTutorial() {
|
||||
disableShortcutIcon(true)
|
||||
|
||||
supportFragmentManager.apply {
|
||||
findFragmentById(R.id.levelContainer)?.let { it ->
|
||||
beginTransaction().apply {
|
||||
|
@ -556,7 +598,8 @@ class GameActivity : ThematicActivity(R.layout.activity_game), DialogInterface.O
|
|||
victory,
|
||||
score?.rightMines ?: 0,
|
||||
score?.totalMines ?: 0,
|
||||
currentGameStatus.time
|
||||
currentGameStatus.time,
|
||||
if (victory) 1 else 0
|
||||
).apply {
|
||||
showAllowingStateLoss(supportFragmentManager, EndGameDialogFragment.TAG)
|
||||
}
|
||||
|
@ -597,25 +640,28 @@ class GameActivity : ThematicActivity(R.layout.activity_game), DialogInterface.O
|
|||
when (event) {
|
||||
Event.ResumeGame -> {
|
||||
status = Status.Running
|
||||
refreshShortcutIcon()
|
||||
refreshTipShortcutIcon()
|
||||
}
|
||||
Event.StartNewGame -> {
|
||||
status = Status.PreGame
|
||||
refreshShortcutIcon()
|
||||
disableShortcutIcon()
|
||||
refreshAds()
|
||||
}
|
||||
Event.Resume, Event.Running -> {
|
||||
status = Status.Running
|
||||
gameViewModel.runClock()
|
||||
refreshShortcutIcon()
|
||||
refreshTipShortcutIcon()
|
||||
keepScreenOn(true)
|
||||
}
|
||||
Event.StartTutorial -> {
|
||||
status = Status.PreGame
|
||||
gameViewModel.stopClock()
|
||||
disableShortcutIcon(true)
|
||||
loadGameTutorial()
|
||||
}
|
||||
Event.FinishTutorial -> {
|
||||
gameViewModel.startNewGame(Difficulty.Beginner)
|
||||
disableShortcutIcon()
|
||||
loadGameFragment()
|
||||
status = Status.Over(0, Score(4, 4, 25))
|
||||
analyticsManager.sentEvent(Analytics.TutorialCompleted)
|
||||
|
@ -631,12 +677,14 @@ class GameActivity : ThematicActivity(R.layout.activity_game), DialogInterface.O
|
|||
)
|
||||
status = Status.Over(currentTime, score)
|
||||
gameViewModel.stopClock()
|
||||
gameViewModel.revealAllEmptyAreas()
|
||||
gameViewModel.showAllEmptyAreas()
|
||||
gameViewModel.victory()
|
||||
refreshShortcutIcon(true)
|
||||
refreshEndGameShortcutIcon(true, isResuming)
|
||||
keepScreenOn(false)
|
||||
|
||||
if (!isResuming) {
|
||||
gameViewModel.addNewTip()
|
||||
|
||||
waitAndShowEndGameDialog(
|
||||
victory = true,
|
||||
await = false
|
||||
|
@ -651,7 +699,7 @@ class GameActivity : ThematicActivity(R.layout.activity_game), DialogInterface.O
|
|||
totalArea
|
||||
)
|
||||
status = Status.Over(currentTime, score)
|
||||
refreshShortcutIcon(true)
|
||||
refreshEndGameShortcutIcon(false, isResuming)
|
||||
keepScreenOn(false)
|
||||
gameViewModel.stopClock()
|
||||
|
||||
|
@ -711,6 +759,10 @@ class GameActivity : ThematicActivity(R.layout.activity_game), DialogInterface.O
|
|||
} == 0
|
||||
}
|
||||
|
||||
private fun hasActiveGameFragment(): Boolean {
|
||||
return supportFragmentManager.findFragmentByTag(LevelFragment.TAG) != null
|
||||
}
|
||||
|
||||
override fun onDismiss(dialog: DialogInterface?) {
|
||||
gameViewModel.run {
|
||||
refreshUserPreferences()
|
||||
|
|
|
@ -5,6 +5,7 @@ import dev.lucasnlm.antimine.common.level.di.LevelModule
|
|||
import dev.lucasnlm.antimine.core.analytics.IAnalyticsManager
|
||||
import dev.lucasnlm.antimine.core.analytics.models.Analytics
|
||||
import dev.lucasnlm.antimine.core.di.CommonModule
|
||||
import dev.lucasnlm.antimine.core.preferences.IPreferencesRepository
|
||||
import dev.lucasnlm.antimine.di.AppModule
|
||||
import dev.lucasnlm.antimine.di.ViewModelModule
|
||||
import dev.lucasnlm.external.IAdsManager
|
||||
|
@ -14,6 +15,7 @@ import org.koin.core.context.startKoin
|
|||
|
||||
open class MainApplication : MultiDexApplication() {
|
||||
private val analyticsManager: IAnalyticsManager by inject()
|
||||
private val preferencesRepository: IPreferencesRepository by inject()
|
||||
|
||||
private val adsManager: IAdsManager by inject()
|
||||
|
||||
|
@ -29,6 +31,10 @@ open class MainApplication : MultiDexApplication() {
|
|||
sentEvent(Analytics.Open)
|
||||
}
|
||||
|
||||
if (BuildConfig.FLAVOR == "foss") {
|
||||
preferencesRepository.setPremiumFeatures(true)
|
||||
}
|
||||
|
||||
adsManager.start(applicationContext)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,9 +25,9 @@ val ViewModelModule = module {
|
|||
viewModel { TextViewModel(get()) }
|
||||
viewModel { ThemeViewModel(get(), get(), get(), get()) }
|
||||
viewModel {
|
||||
GameViewModel(get(), get(), get(), get(), get(), get(), get(), get(), get(), get(), get())
|
||||
GameViewModel(get(), get(), get(), get(), get(), get(), get(), get(), get(), get(), get(), get())
|
||||
}
|
||||
viewModel {
|
||||
TutorialViewModel(get(), get(), get(), get(), get(), get(), get(), get(), get(), get(), get(), get())
|
||||
TutorialViewModel(get(), get(), get(), get(), get(), get(), get(), get(), get(), get(), get(), get(), get())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ import android.annotation.SuppressLint
|
|||
import android.app.Dialog
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.widget.ImageView
|
||||
import android.widget.TextView
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
|
@ -12,11 +13,8 @@ import androidx.fragment.app.FragmentManager
|
|||
import androidx.lifecycle.lifecycleScope
|
||||
import dev.lucasnlm.antimine.R
|
||||
import dev.lucasnlm.antimine.common.level.viewmodel.GameViewModel
|
||||
import dev.lucasnlm.antimine.core.preferences.IPreferencesRepository
|
||||
import dev.lucasnlm.antimine.level.viewmodel.EndGameDialogEvent
|
||||
import dev.lucasnlm.antimine.level.viewmodel.EndGameDialogViewModel
|
||||
import dev.lucasnlm.external.Ads
|
||||
import dev.lucasnlm.external.IAdsManager
|
||||
import dev.lucasnlm.external.IInstantAppManager
|
||||
import kotlinx.coroutines.flow.collect
|
||||
import org.koin.android.ext.android.inject
|
||||
|
@ -25,9 +23,6 @@ import org.koin.androidx.viewmodel.ext.android.viewModel
|
|||
|
||||
class EndGameDialogFragment : AppCompatDialogFragment() {
|
||||
private val instantAppManager: IInstantAppManager by inject()
|
||||
private val adsManager: IAdsManager by inject()
|
||||
private val preferencesRepository: IPreferencesRepository by inject()
|
||||
|
||||
private val endGameViewModel by viewModel<EndGameDialogViewModel>()
|
||||
private val gameViewModel by sharedViewModel<GameViewModel>()
|
||||
|
||||
|
@ -40,7 +35,8 @@ class EndGameDialogFragment : AppCompatDialogFragment() {
|
|||
isVictory = if (getInt(DIALOG_TOTAL_MINES, 0) > 0) getBoolean(DIALOG_IS_VICTORY) else null,
|
||||
time = getLong(DIALOG_TIME, 0L),
|
||||
rightMines = getInt(DIALOG_RIGHT_MINES, 0),
|
||||
totalMines = getInt(DIALOG_TOTAL_MINES, 0)
|
||||
totalMines = getInt(DIALOG_TOTAL_MINES, 0),
|
||||
received = getInt(DIALOG_RECEIVED, -1)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
@ -72,6 +68,15 @@ class EndGameDialogFragment : AppCompatDialogFragment() {
|
|||
}
|
||||
}
|
||||
|
||||
findViewById<TextView>(R.id.received_message).apply {
|
||||
if (state.received > 0 && state.isVictory == true) {
|
||||
visibility = View.VISIBLE
|
||||
text = getString(R.string.you_have_received, state.received)
|
||||
} else {
|
||||
visibility = View.GONE
|
||||
}
|
||||
}
|
||||
|
||||
if (state.isVictory == true) {
|
||||
if (!instantAppManager.isEnabled(context)) {
|
||||
setNeutralButton(R.string.share) { _, _ ->
|
||||
|
@ -95,20 +100,27 @@ class EndGameDialogFragment : AppCompatDialogFragment() {
|
|||
}.create()
|
||||
|
||||
companion object {
|
||||
fun newInstance(victory: Boolean, rightMines: Int, totalMines: Int, time: Long) =
|
||||
EndGameDialogFragment().apply {
|
||||
arguments = Bundle().apply {
|
||||
putBoolean(DIALOG_IS_VICTORY, victory)
|
||||
putInt(DIALOG_RIGHT_MINES, rightMines)
|
||||
putInt(DIALOG_TOTAL_MINES, totalMines)
|
||||
putLong(DIALOG_TIME, time)
|
||||
}
|
||||
fun newInstance(
|
||||
victory: Boolean,
|
||||
rightMines: Int,
|
||||
totalMines: Int,
|
||||
time: Long,
|
||||
received: Int,
|
||||
) = EndGameDialogFragment().apply {
|
||||
arguments = Bundle().apply {
|
||||
putBoolean(DIALOG_IS_VICTORY, victory)
|
||||
putInt(DIALOG_RIGHT_MINES, rightMines)
|
||||
putInt(DIALOG_TOTAL_MINES, totalMines)
|
||||
putInt(DIALOG_RECEIVED, received)
|
||||
putLong(DIALOG_TIME, time)
|
||||
}
|
||||
}
|
||||
|
||||
const val DIALOG_IS_VICTORY = "dialog_state"
|
||||
private const val DIALOG_TIME = "dialog_time"
|
||||
private const val DIALOG_RIGHT_MINES = "dialog_right_mines"
|
||||
private const val DIALOG_TOTAL_MINES = "dialog_total_mines"
|
||||
private const val DIALOG_RECEIVED = "dialog_received"
|
||||
|
||||
val TAG = EndGameDialogFragment::class.simpleName!!
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@ sealed class EndGameDialogEvent {
|
|||
val time: Long,
|
||||
val rightMines: Int,
|
||||
val totalMines: Int,
|
||||
val received: Int,
|
||||
) : EndGameDialogEvent()
|
||||
|
||||
data class ChangeEmoji(
|
||||
|
|
|
@ -7,4 +7,5 @@ data class EndGameDialogState(
|
|||
val title: String,
|
||||
val message: String,
|
||||
val isVictory: Boolean?,
|
||||
val received: Int
|
||||
)
|
||||
|
|
|
@ -70,6 +70,7 @@ class EndGameDialogViewModel(
|
|||
"",
|
||||
"",
|
||||
false,
|
||||
0
|
||||
)
|
||||
|
||||
override suspend fun mapEventToState(event: EndGameDialogEvent) = flow {
|
||||
|
@ -80,7 +81,8 @@ class EndGameDialogViewModel(
|
|||
titleEmoji = randomVictoryEmoji(),
|
||||
title = context.getString(R.string.you_won),
|
||||
message = messageTo(event.time, event.isVictory),
|
||||
isVictory = true
|
||||
isVictory = true,
|
||||
received = event.received
|
||||
)
|
||||
}
|
||||
false -> {
|
||||
|
@ -88,7 +90,8 @@ class EndGameDialogViewModel(
|
|||
titleEmoji = randomGameOverEmoji(),
|
||||
title = context.getString(R.string.you_lost),
|
||||
message = messageTo(event.time, event.isVictory),
|
||||
isVictory = false
|
||||
isVictory = false,
|
||||
received = event.received
|
||||
)
|
||||
}
|
||||
null -> {
|
||||
|
@ -96,7 +99,8 @@ class EndGameDialogViewModel(
|
|||
titleEmoji = randomNeutralEmoji(),
|
||||
title = context.getString(R.string.new_game),
|
||||
message = context.getString(R.string.new_game_request),
|
||||
isVictory = false
|
||||
isVictory = false,
|
||||
received = event.received
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,15 +27,42 @@ class ThemeAdapter(
|
|||
private val themes: List<AppTheme> = themeViewModel.singleState().themes
|
||||
|
||||
private val minefield = listOf(
|
||||
Area(0, 0, 0, 1, hasMine = false, mistake = false, mark = Mark.None, isCovered = false),
|
||||
Area(1, 1, 0, 0, hasMine = true, mistake = false, mark = Mark.None, isCovered = false),
|
||||
Area(2, 2, 0, 0, hasMine = true, mistake = false, mark = Mark.None, isCovered = true),
|
||||
Area(3, 0, 1, 2, hasMine = false, mistake = false, mark = Mark.None, isCovered = false),
|
||||
Area(4, 1, 1, 3, hasMine = false, mistake = false, mark = Mark.None, isCovered = false),
|
||||
Area(5, 2, 1, 3, hasMine = true, mistake = false, mark = Mark.Flag, isCovered = true),
|
||||
Area(6, 0, 2, 0, hasMine = true, mistake = false, mark = Mark.Question, isCovered = true),
|
||||
Area(7, 1, 2, 4, hasMine = false, mistake = false, mark = Mark.None, isCovered = false),
|
||||
Area(8, 2, 2, 0, hasMine = false, mistake = false, mark = Mark.None, isCovered = true),
|
||||
Area(
|
||||
0, 0, 0, 1,
|
||||
hasMine = false, mistake = false, mark = Mark.None, isCovered = false
|
||||
),
|
||||
Area(
|
||||
1, 1, 0, 0,
|
||||
hasMine = true, mistake = false, mark = Mark.None, isCovered = false
|
||||
),
|
||||
Area(
|
||||
2, 2, 0, 0,
|
||||
hasMine = true, mistake = false, mark = Mark.None, isCovered = true
|
||||
),
|
||||
Area(
|
||||
3, 0, 1, 2,
|
||||
hasMine = false, mistake = false, mark = Mark.None, isCovered = false
|
||||
),
|
||||
Area(
|
||||
4, 1, 1, 3,
|
||||
hasMine = false, mistake = false, mark = Mark.None, isCovered = false
|
||||
),
|
||||
Area(
|
||||
5, 2, 1, 3,
|
||||
hasMine = true, mistake = false, mark = Mark.Flag, isCovered = true
|
||||
),
|
||||
Area(
|
||||
6, 0, 2, 0,
|
||||
hasMine = true, mistake = false, mark = Mark.Question, isCovered = true
|
||||
),
|
||||
Area(
|
||||
7, 1, 2, 4,
|
||||
hasMine = false, mistake = false, mark = Mark.None, isCovered = false
|
||||
),
|
||||
Area(
|
||||
8, 2, 2, 0,
|
||||
hasMine = false, mistake = false, mark = Mark.None, isCovered = true, revealed = true
|
||||
),
|
||||
)
|
||||
|
||||
init {
|
||||
|
|
|
@ -7,6 +7,7 @@ import dev.lucasnlm.antimine.common.level.repository.IDimensionRepository
|
|||
import dev.lucasnlm.antimine.common.level.repository.IMinefieldRepository
|
||||
import dev.lucasnlm.antimine.common.level.repository.ISavesRepository
|
||||
import dev.lucasnlm.antimine.common.level.repository.IStatsRepository
|
||||
import dev.lucasnlm.antimine.common.level.repository.ITipRepository
|
||||
import dev.lucasnlm.antimine.common.level.utils.Clock
|
||||
import dev.lucasnlm.antimine.common.level.utils.IHapticFeedbackManager
|
||||
import dev.lucasnlm.antimine.common.level.viewmodel.GameViewModel
|
||||
|
@ -29,6 +30,7 @@ class TutorialViewModel(
|
|||
minefieldRepository: IMinefieldRepository,
|
||||
analyticsManager: IAnalyticsManager,
|
||||
playGamesManager: IPlayGamesManager,
|
||||
tipRepository: ITipRepository,
|
||||
private val clock: Clock,
|
||||
private val context: Context,
|
||||
private val hapticFeedbackManager: IHapticFeedbackManager,
|
||||
|
@ -44,6 +46,7 @@ class TutorialViewModel(
|
|||
minefieldRepository,
|
||||
analyticsManager,
|
||||
playGamesManager,
|
||||
tipRepository,
|
||||
clock,
|
||||
) {
|
||||
val tutorialState = MutableStateFlow(
|
||||
|
|
10
app/src/main/res/drawable/tip.xml
Normal file
10
app/src/main/res/drawable/tip.xml
Normal file
|
@ -0,0 +1,10 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24"
|
||||
android:tint="?attr/colorControlNormal">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M12,3c-0.46,0 -0.93,0.04 -1.4,0.14C7.84,3.67 5.64,5.9 5.12,8.66c-0.48,2.61 0.48,5.01 2.22,6.56C7.77,15.6 8,16.13 8,16.69V19c0,1.1 0.9,2 2,2h0.28c0.35,0.6 0.98,1 1.72,1s1.38,-0.4 1.72,-1H14c1.1,0 2,-0.9 2,-2v-2.31c0,-0.55 0.22,-1.09 0.64,-1.46C18.09,13.95 19,12.08 19,10C19,6.13 15.87,3 12,3zM12.5,14h-1v-2.59L9.67,9.59l0.71,-0.71L12,10.5l1.62,-1.62l0.71,0.71l-1.83,1.83V14zM13.5,19c-0.01,0 -0.02,-0.01 -0.03,-0.01V19h-2.94v-0.01c-0.01,0 -0.02,0.01 -0.03,0.01c-0.28,0 -0.5,-0.22 -0.5,-0.5c0,-0.28 0.22,-0.5 0.5,-0.5c0.01,0 0.02,0.01 0.03,0.01V18h2.94v0.01c0.01,0 0.02,-0.01 0.03,-0.01c0.28,0 0.5,0.22 0.5,0.5C14,18.78 13.78,19 13.5,19zM13.5,17h-3c-0.28,0 -0.5,-0.22 -0.5,-0.5c0,-0.28 0.22,-0.5 0.5,-0.5h3c0.28,0 0.5,0.22 0.5,0.5C14,16.78 13.78,17 13.5,17z" />
|
||||
</vector>
|
|
@ -90,6 +90,20 @@
|
|||
app:srcCompat="@drawable/retry"
|
||||
tools:alpha="1.0"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tipsCounter"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="41dp"
|
||||
android:textSize="12sp"
|
||||
android:textStyle="bold"
|
||||
android:visibility="gone"
|
||||
tools:text="100"
|
||||
tools:visibility="visible"
|
||||
ads:layout_constraintBottom_toBottomOf="@+id/shortcutIcon"
|
||||
ads:layout_constraintEnd_toEndOf="@+id/shortcutIcon"
|
||||
ads:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/levelContainer"
|
||||
android:layout_width="0dp"
|
||||
|
|
|
@ -50,4 +50,19 @@
|
|||
app:layout_constraintTop_toBottomOf="@+id/title"
|
||||
tools:text="You did 5/12 in 34 seconds." />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/received_message"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/you_have_received"
|
||||
android:layout_marginTop="4dp"
|
||||
android:textSize="14sp"
|
||||
android:textAlignment="center"
|
||||
android:gravity="center"
|
||||
app:drawableEndCompat="@drawable/tip"
|
||||
app:drawableTint="@color/accent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/subtitle"/>
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
|
|
@ -61,6 +61,14 @@ class MockPreferencesRepository : IPreferencesRepository {
|
|||
|
||||
override fun showSupport(): Boolean = true
|
||||
|
||||
override fun getTips(): Int = 0
|
||||
|
||||
override fun setTips(tips: Int) { }
|
||||
|
||||
override fun getExtraTips(): Int = 5
|
||||
|
||||
override fun setExtraTips(tips: Int) { }
|
||||
|
||||
override fun useFlagAssistant(): Boolean = false
|
||||
|
||||
override fun useHapticFeedback(): Boolean = true
|
||||
|
|
|
@ -48,7 +48,8 @@ class ThemeViewModelTest : IntentViewModelTest() {
|
|||
toolbarMine = R.drawable.mine,
|
||||
mine = R.drawable.mine,
|
||||
mineExploded = R.drawable.mine_exploded_red,
|
||||
mineLow = R.drawable.mine_low
|
||||
mineLow = R.drawable.mine_low,
|
||||
revealed = R.drawable.mine_revealed,
|
||||
)
|
||||
)
|
||||
|
||||
|
@ -81,7 +82,8 @@ class ThemeViewModelTest : IntentViewModelTest() {
|
|||
toolbarMine = R.drawable.mine_low,
|
||||
mine = R.drawable.mine,
|
||||
mineExploded = R.drawable.mine_exploded_white,
|
||||
mineLow = R.drawable.mine_low
|
||||
mineLow = R.drawable.mine_low,
|
||||
revealed = R.drawable.mine_revealed,
|
||||
)
|
||||
)
|
||||
|
||||
|
@ -114,7 +116,8 @@ class ThemeViewModelTest : IntentViewModelTest() {
|
|||
toolbarMine = R.drawable.mine_low,
|
||||
mine = R.drawable.mine,
|
||||
mineExploded = R.drawable.mine_exploded_white,
|
||||
mineLow = R.drawable.mine_low
|
||||
mineLow = R.drawable.mine_low,
|
||||
revealed = R.drawable.mine_revealed,
|
||||
)
|
||||
)
|
||||
|
||||
|
|
|
@ -212,6 +212,15 @@ class GameController {
|
|||
}
|
||||
}
|
||||
|
||||
fun revealRandomMine(): Boolean {
|
||||
val result: Boolean
|
||||
field = MinefieldHandler(field.toMutableList(), false).run {
|
||||
result = revealRandomMine()
|
||||
result()
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
fun hasAnyMineExploded(): Boolean = mines().firstOrNull { it.mistake } != null
|
||||
|
||||
fun hasFlaggedAllMines(): Boolean = rightFlags() == minefield.mines
|
||||
|
|
|
@ -18,7 +18,7 @@ import dev.lucasnlm.antimine.common.level.database.models.Stats
|
|||
Save::class,
|
||||
Stats::class
|
||||
],
|
||||
version = 6,
|
||||
version = 7,
|
||||
exportSchema = false
|
||||
)
|
||||
@TypeConverters(
|
||||
|
|
|
@ -5,9 +5,11 @@ import dev.lucasnlm.antimine.common.level.database.AppDataBase
|
|||
import dev.lucasnlm.antimine.common.level.repository.IMinefieldRepository
|
||||
import dev.lucasnlm.antimine.common.level.repository.ISavesRepository
|
||||
import dev.lucasnlm.antimine.common.level.repository.IStatsRepository
|
||||
import dev.lucasnlm.antimine.common.level.repository.ITipRepository
|
||||
import dev.lucasnlm.antimine.common.level.repository.MinefieldRepository
|
||||
import dev.lucasnlm.antimine.common.level.repository.SavesRepository
|
||||
import dev.lucasnlm.antimine.common.level.repository.StatsRepository
|
||||
import dev.lucasnlm.antimine.common.level.repository.TipRepository
|
||||
import dev.lucasnlm.antimine.common.level.utils.Clock
|
||||
import dev.lucasnlm.antimine.common.level.utils.HapticFeedbackManager
|
||||
import dev.lucasnlm.antimine.common.level.utils.IHapticFeedbackManager
|
||||
|
@ -48,4 +50,8 @@ val LevelModule = module {
|
|||
single {
|
||||
HapticFeedbackManager(get())
|
||||
} bind IHapticFeedbackManager::class
|
||||
|
||||
single {
|
||||
TipRepository(get())
|
||||
} bind ITipRepository::class
|
||||
}
|
||||
|
|
|
@ -22,6 +22,13 @@ class MinefieldHandler(
|
|||
.forEach { field[it.id] = it.copy(isCovered = false) }
|
||||
}
|
||||
|
||||
fun revealRandomMine(): Boolean {
|
||||
return field.filter { it.hasMine && it.mark.isNone() && !it.revealed }.shuffled().firstOrNull()?.run {
|
||||
field[this.id] = this.copy(revealed = true)
|
||||
true
|
||||
} ?: false
|
||||
}
|
||||
|
||||
fun turnOffAllHighlighted() {
|
||||
field.filter { it.highlighted }
|
||||
.forEach { field[it.id] = it.copy(highlighted = false) }
|
||||
|
|
|
@ -10,4 +10,5 @@ data class Area(
|
|||
val isCovered: Boolean = true,
|
||||
val mark: Mark = Mark.None,
|
||||
val highlighted: Boolean = false,
|
||||
val revealed: Boolean = false,
|
||||
)
|
||||
|
|
|
@ -0,0 +1,50 @@
|
|||
package dev.lucasnlm.antimine.common.level.repository
|
||||
|
||||
import dev.lucasnlm.antimine.core.preferences.IPreferencesRepository
|
||||
|
||||
interface ITipRepository {
|
||||
fun setExtraTips(amount: Int)
|
||||
fun removeTip(): Boolean
|
||||
fun increaseTip()
|
||||
fun getTotalTips(): Int
|
||||
}
|
||||
|
||||
class TipRepository(
|
||||
private val preferencesRepository: IPreferencesRepository
|
||||
) : ITipRepository {
|
||||
override fun setExtraTips(amount: Int) {
|
||||
preferencesRepository.setExtraTips(amount)
|
||||
}
|
||||
|
||||
override fun removeTip(): Boolean {
|
||||
val tips = preferencesRepository.getTips()
|
||||
val extra = preferencesRepository.getExtraTips()
|
||||
|
||||
return when {
|
||||
tips >= 1 -> {
|
||||
preferencesRepository.setTips(tips - 1)
|
||||
true
|
||||
}
|
||||
preferencesRepository.getExtraTips() >= 1 -> {
|
||||
preferencesRepository.setExtraTips(extra - 1)
|
||||
true
|
||||
}
|
||||
else -> {
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun increaseTip() {
|
||||
val newValue = (preferencesRepository.getTips() + 1).coerceAtMost(MAX_TIPS).coerceAtLeast(0)
|
||||
preferencesRepository.setTips(newValue)
|
||||
}
|
||||
|
||||
override fun getTotalTips(): Int {
|
||||
return preferencesRepository.getExtraTips() + preferencesRepository.getTips()
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val MAX_TIPS = 5
|
||||
}
|
||||
}
|
|
@ -79,7 +79,21 @@ fun Area.paintOnCanvas(
|
|||
)
|
||||
question?.draw(canvas)
|
||||
}
|
||||
else -> {}
|
||||
else -> {
|
||||
if (revealed) {
|
||||
val padding = minePadding ?: context.resources.getDimension(R.dimen.mine_padding).toInt()
|
||||
|
||||
val revealedDrawable = ContextCompat.getDrawable(context, theme.assets.revealed)
|
||||
|
||||
revealedDrawable?.setBounds(
|
||||
rectF.left.toInt() + padding,
|
||||
rectF.top.toInt() + padding,
|
||||
rectF.right.toInt() - padding,
|
||||
rectF.bottom.toInt() - padding
|
||||
)
|
||||
revealedDrawable?.draw(canvas)
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (isAmbientMode) {
|
||||
|
|
|
@ -15,6 +15,7 @@ import dev.lucasnlm.antimine.common.level.repository.IDimensionRepository
|
|||
import dev.lucasnlm.antimine.common.level.repository.IMinefieldRepository
|
||||
import dev.lucasnlm.antimine.common.level.repository.ISavesRepository
|
||||
import dev.lucasnlm.antimine.common.level.repository.IStatsRepository
|
||||
import dev.lucasnlm.antimine.common.level.repository.ITipRepository
|
||||
import dev.lucasnlm.antimine.common.level.utils.Clock
|
||||
import dev.lucasnlm.antimine.common.level.utils.IHapticFeedbackManager
|
||||
import dev.lucasnlm.antimine.core.analytics.IAnalyticsManager
|
||||
|
@ -46,6 +47,7 @@ open class GameViewModel(
|
|||
private val minefieldRepository: IMinefieldRepository,
|
||||
private val analyticsManager: IAnalyticsManager,
|
||||
private val playGamesManager: IPlayGamesManager,
|
||||
private val tipRepository: ITipRepository,
|
||||
private val clock: Clock,
|
||||
) : ViewModel() {
|
||||
val eventObserver = MutableLiveData<Event>()
|
||||
|
@ -62,6 +64,7 @@ open class GameViewModel(
|
|||
val difficulty = MutableLiveData<Difficulty>()
|
||||
val levelSetup = MutableLiveData<Minefield>()
|
||||
val saveId = MutableLiveData<Long>()
|
||||
val tips = MutableLiveData(tipRepository.getTotalTips())
|
||||
|
||||
fun startNewGame(newDifficulty: Difficulty = currentDifficulty): Minefield {
|
||||
clock.reset()
|
||||
|
@ -359,7 +362,22 @@ open class GameViewModel(
|
|||
clock.stop()
|
||||
}
|
||||
|
||||
fun revealAllEmptyAreas() = gameController.revealAllEmptyAreas()
|
||||
fun showAllEmptyAreas() {
|
||||
gameController.revealAllEmptyAreas()
|
||||
}
|
||||
|
||||
fun revealRandomMine(): Boolean {
|
||||
return if (gameController.revealRandomMine()) {
|
||||
if (tipRepository.removeTip()) {
|
||||
refreshField()
|
||||
}
|
||||
|
||||
tips.postValue(tipRepository.getTotalTips())
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
fun explosionDelay() = if (preferencesRepository.useAnimations()) 750L else 0L
|
||||
|
||||
|
@ -408,6 +426,14 @@ open class GameViewModel(
|
|||
}
|
||||
}
|
||||
|
||||
fun addNewTip() {
|
||||
tipRepository.increaseTip()
|
||||
}
|
||||
|
||||
fun getTips(): Int {
|
||||
return tipRepository.getTotalTips()
|
||||
}
|
||||
|
||||
fun victory() {
|
||||
gameController.run {
|
||||
analyticsManager.sentEvent(
|
||||
|
|
|
@ -119,5 +119,7 @@ sealed class Analytics(
|
|||
|
||||
object TapRatingRequest : Analytics("Rating Request")
|
||||
|
||||
object UseTip : Analytics("Use Tip")
|
||||
|
||||
class TapGameReset(resign: Boolean) : Analytics("Game reset", mapOf("Resign" to resign.toString()))
|
||||
}
|
||||
|
|
|
@ -43,6 +43,11 @@ interface IPreferencesRepository {
|
|||
fun setShowSupport(show: Boolean)
|
||||
fun showSupport(): Boolean
|
||||
|
||||
fun getTips(): Int
|
||||
fun setTips(tips: Int)
|
||||
fun getExtraTips(): Int
|
||||
fun setExtraTips(tips: Int)
|
||||
|
||||
fun useFlagAssistant(): Boolean
|
||||
fun useHapticFeedback(): Boolean
|
||||
fun areaSizeMultiplier(): Int
|
||||
|
|
|
@ -186,6 +186,22 @@ class PreferencesRepository(
|
|||
return preferencesManager.getBoolean(PREFERENCE_SHOW_SUPPORT, true)
|
||||
}
|
||||
|
||||
override fun getTips(): Int {
|
||||
return preferencesManager.getInt(PREFERENCE_TIPS, 5)
|
||||
}
|
||||
|
||||
override fun setTips(tips: Int) {
|
||||
preferencesManager.putInt(PREFERENCE_TIPS, tips)
|
||||
}
|
||||
|
||||
override fun getExtraTips(): Int {
|
||||
return preferencesManager.getInt(PREFERENCE_EXTRA_TIPS, 0)
|
||||
}
|
||||
|
||||
override fun setExtraTips(tips: Int) {
|
||||
preferencesManager.putInt(PREFERENCE_EXTRA_TIPS, tips)
|
||||
}
|
||||
|
||||
private companion object {
|
||||
private const val PREFERENCE_VIBRATION = "preference_vibration"
|
||||
private const val PREFERENCE_ASSISTANT = "preference_assistant"
|
||||
|
@ -209,5 +225,7 @@ class PreferencesRepository(
|
|||
private const val PREFERENCE_REQUEST_RATING = "preference_request_rating"
|
||||
private const val PREFERENCE_PREMIUM_FEATURES = "preference_premium_features"
|
||||
private const val PREFERENCE_SHOW_SUPPORT = "preference_show_support"
|
||||
private const val PREFERENCE_TIPS = "preference_current_tips"
|
||||
private const val PREFERENCE_EXTRA_TIPS = "preference_extra_tips"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,4 +10,5 @@ data class Assets(
|
|||
@DrawableRes val mine: Int,
|
||||
@DrawableRes val mineExploded: Int,
|
||||
@DrawableRes val mineLow: Int,
|
||||
@DrawableRes val revealed: Int,
|
||||
)
|
||||
|
|
|
@ -58,7 +58,8 @@ class ThemeRepository(
|
|||
toolbarMine = R.drawable.mine,
|
||||
mine = R.drawable.mine,
|
||||
mineExploded = R.drawable.mine_exploded_red,
|
||||
mineLow = R.drawable.mine_low
|
||||
mineLow = R.drawable.mine_low,
|
||||
revealed = R.drawable.mine_revealed
|
||||
)
|
||||
|
||||
private fun fromDefaultPalette(context: Context) =
|
||||
|
|
|
@ -36,6 +36,7 @@ object Themes {
|
|||
mine = R.drawable.mine,
|
||||
mineExploded = R.drawable.mine_exploded_red,
|
||||
mineLow = R.drawable.mine_low,
|
||||
revealed = R.drawable.mine_revealed_white,
|
||||
)
|
||||
)
|
||||
|
||||
|
@ -69,6 +70,7 @@ object Themes {
|
|||
mine = R.drawable.mine,
|
||||
mineExploded = R.drawable.mine_exploded_white,
|
||||
mineLow = R.drawable.mine_low,
|
||||
revealed = R.drawable.mine_revealed_white,
|
||||
)
|
||||
)
|
||||
|
||||
|
@ -102,6 +104,7 @@ object Themes {
|
|||
mine = R.drawable.mine_low,
|
||||
mineExploded = R.drawable.mine_low,
|
||||
mineLow = R.drawable.mine_low,
|
||||
revealed = R.drawable.mine_revealed_white,
|
||||
)
|
||||
)
|
||||
|
||||
|
@ -139,6 +142,7 @@ object Themes {
|
|||
mine = R.drawable.mine,
|
||||
mineExploded = R.drawable.mine_exploded_white,
|
||||
mineLow = R.drawable.mine_low,
|
||||
revealed = R.drawable.mine_revealed_white,
|
||||
)
|
||||
),
|
||||
AppTheme(
|
||||
|
@ -171,6 +175,7 @@ object Themes {
|
|||
mine = R.drawable.mine,
|
||||
mineExploded = R.drawable.mine_exploded_red,
|
||||
mineLow = R.drawable.mine_low,
|
||||
revealed = R.drawable.mine_revealed_white,
|
||||
)
|
||||
),
|
||||
AppTheme(
|
||||
|
@ -203,6 +208,7 @@ object Themes {
|
|||
mine = R.drawable.mine,
|
||||
mineExploded = R.drawable.mine_exploded_red,
|
||||
mineLow = R.drawable.mine_low,
|
||||
revealed = R.drawable.mine_revealed_white,
|
||||
)
|
||||
),
|
||||
AppTheme(
|
||||
|
@ -235,6 +241,7 @@ object Themes {
|
|||
mine = R.drawable.mine,
|
||||
mineExploded = R.drawable.mine_exploded_red,
|
||||
mineLow = R.drawable.mine_low,
|
||||
revealed = R.drawable.mine_revealed_white,
|
||||
)
|
||||
),
|
||||
AppTheme(
|
||||
|
@ -267,6 +274,7 @@ object Themes {
|
|||
mine = R.drawable.mine_white,
|
||||
mineExploded = R.drawable.mine_white,
|
||||
mineLow = R.drawable.mine_low,
|
||||
revealed = R.drawable.mine_revealed_black,
|
||||
)
|
||||
),
|
||||
AppTheme(
|
||||
|
@ -299,6 +307,7 @@ object Themes {
|
|||
mine = R.drawable.mine_pink,
|
||||
mineExploded = R.drawable.mine_pink_exploded,
|
||||
mineLow = R.drawable.mine_low,
|
||||
revealed = R.drawable.mine_revealed_white,
|
||||
)
|
||||
),
|
||||
AppTheme(
|
||||
|
@ -331,6 +340,7 @@ object Themes {
|
|||
mine = R.drawable.mine_pink,
|
||||
mineExploded = R.drawable.mine_pink_exploded,
|
||||
mineLow = R.drawable.mine_low,
|
||||
revealed = R.drawable.mine_revealed_white,
|
||||
)
|
||||
),
|
||||
AppTheme(
|
||||
|
@ -362,7 +372,8 @@ object Themes {
|
|||
toolbarMine = R.drawable.mine_low,
|
||||
mine = R.drawable.mine,
|
||||
mineExploded = R.drawable.mine_pink_exploded,
|
||||
mineLow = R.drawable.mine_low
|
||||
mineLow = R.drawable.mine_low,
|
||||
revealed = R.drawable.mine_revealed_white,
|
||||
)
|
||||
),
|
||||
AppTheme(
|
||||
|
@ -394,7 +405,8 @@ object Themes {
|
|||
toolbarMine = R.drawable.mine_low,
|
||||
mine = R.drawable.mine,
|
||||
mineExploded = R.drawable.mine_pink_exploded,
|
||||
mineLow = R.drawable.mine_low
|
||||
mineLow = R.drawable.mine_low,
|
||||
revealed = R.drawable.mine_revealed_white,
|
||||
)
|
||||
),
|
||||
AppTheme(
|
||||
|
@ -427,6 +439,7 @@ object Themes {
|
|||
mine = R.drawable.mine,
|
||||
mineExploded = R.drawable.mine_pink_exploded,
|
||||
mineLow = R.drawable.mine_low,
|
||||
revealed = R.drawable.mine_revealed_white,
|
||||
)
|
||||
),
|
||||
AppTheme(
|
||||
|
@ -458,7 +471,8 @@ object Themes {
|
|||
toolbarMine = R.drawable.mine_low,
|
||||
mine = R.drawable.mine,
|
||||
mineExploded = R.drawable.mine_pink_exploded,
|
||||
mineLow = R.drawable.mine_low
|
||||
mineLow = R.drawable.mine_low,
|
||||
revealed = R.drawable.mine_revealed_white,
|
||||
)
|
||||
),
|
||||
AppTheme(
|
||||
|
@ -491,6 +505,7 @@ object Themes {
|
|||
mine = R.drawable.mine_white,
|
||||
mineExploded = R.drawable.mine_white,
|
||||
mineLow = R.drawable.mine_low,
|
||||
revealed = R.drawable.mine_revealed_black,
|
||||
)
|
||||
),
|
||||
AppTheme(
|
||||
|
@ -522,7 +537,8 @@ object Themes {
|
|||
toolbarMine = R.drawable.mine_low,
|
||||
mine = R.drawable.mine_white,
|
||||
mineExploded = R.drawable.mine_white,
|
||||
mineLow = R.drawable.mine_low
|
||||
mineLow = R.drawable.mine_low,
|
||||
revealed = R.drawable.mine_revealed_black,
|
||||
)
|
||||
),
|
||||
AppTheme(
|
||||
|
@ -555,6 +571,7 @@ object Themes {
|
|||
mine = R.drawable.mine_white,
|
||||
mineExploded = R.drawable.mine_white,
|
||||
mineLow = R.drawable.mine_low,
|
||||
revealed = R.drawable.mine_revealed_black,
|
||||
)
|
||||
),
|
||||
AppTheme(
|
||||
|
@ -587,6 +604,7 @@ object Themes {
|
|||
mine = R.drawable.mine,
|
||||
mineExploded = R.drawable.mine_exploded_red,
|
||||
mineLow = R.drawable.mine_low,
|
||||
revealed = R.drawable.mine_revealed_black,
|
||||
)
|
||||
),
|
||||
AppTheme(
|
||||
|
@ -619,6 +637,7 @@ object Themes {
|
|||
mine = R.drawable.mine,
|
||||
mineExploded = R.drawable.mine_exploded_red,
|
||||
mineLow = R.drawable.mine_low,
|
||||
revealed = R.drawable.mine_revealed_black,
|
||||
)
|
||||
),
|
||||
AppTheme(
|
||||
|
@ -645,12 +664,13 @@ object Themes {
|
|||
),
|
||||
assets = Assets(
|
||||
wrongFlag = R.drawable.red_flag,
|
||||
flag = R.drawable.flag,
|
||||
flag = R.drawable.flag_black,
|
||||
questionMark = R.drawable.question,
|
||||
toolbarMine = R.drawable.mine,
|
||||
mine = R.drawable.mine,
|
||||
mineExploded = R.drawable.mine_exploded_red,
|
||||
mineLow = R.drawable.mine_low,
|
||||
revealed = R.drawable.mine_revealed_black,
|
||||
)
|
||||
)
|
||||
)
|
||||
|
|
9
common/src/main/res/drawable-night/mine_revealed.xml
Executable file
9
common/src/main/res/drawable-night/mine_revealed.xml
Executable file
|
@ -0,0 +1,9 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="512"
|
||||
android:viewportHeight="512">
|
||||
<path
|
||||
android:fillColor="#33000000"
|
||||
android:pathData="M331.722,124.091l-33.743,-67.204l-83.901,0l-33.84,65.28l-80.22,0l-37.443,65.714l37.443,67.649l-37.443,66.12l37.42,67.746l80.243,0l39.239,65.717l75.084,0l37.161,-66.643l79.759,-0.019l37.942,-66.801l-40.501,-65.64l40.501,-68.129l-38.02,-63.79z" />
|
||||
</vector>
|
9
common/src/main/res/drawable/mine_revealed.xml
Executable file
9
common/src/main/res/drawable/mine_revealed.xml
Executable file
|
@ -0,0 +1,9 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="512"
|
||||
android:viewportHeight="512">
|
||||
<path
|
||||
android:fillColor="#33ffffff"
|
||||
android:pathData="M331.722,124.091l-33.743,-67.204l-83.901,0l-33.84,65.28l-80.22,0l-37.443,65.714l37.443,67.649l-37.443,66.12l37.42,67.746l80.243,0l39.239,65.717l75.084,0l37.161,-66.643l79.759,-0.019l37.942,-66.801l-40.501,-65.64l40.501,-68.129l-38.02,-63.79z" />
|
||||
</vector>
|
9
common/src/main/res/drawable/mine_revealed_black.xml
Executable file
9
common/src/main/res/drawable/mine_revealed_black.xml
Executable file
|
@ -0,0 +1,9 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="512"
|
||||
android:viewportHeight="512">
|
||||
<path
|
||||
android:fillColor="#33000000"
|
||||
android:pathData="M331.722,124.091l-33.743,-67.204l-83.901,0l-33.84,65.28l-80.22,0l-37.443,65.714l37.443,67.649l-37.443,66.12l37.42,67.746l80.243,0l39.239,65.717l75.084,0l37.161,-66.643l79.759,-0.019l37.942,-66.801l-40.501,-65.64l40.501,-68.129l-38.02,-63.79z" />
|
||||
</vector>
|
9
common/src/main/res/drawable/mine_revealed_white.xml
Executable file
9
common/src/main/res/drawable/mine_revealed_white.xml
Executable file
|
@ -0,0 +1,9 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="512"
|
||||
android:viewportHeight="512">
|
||||
<path
|
||||
android:fillColor="#33ffffff"
|
||||
android:pathData="M331.722,124.091l-33.743,-67.204l-83.901,0l-33.84,65.28l-80.22,0l-37.443,65.714l37.443,67.649l-37.443,66.12l37.42,67.746l80.243,0l39.239,65.717l75.084,0l37.161,-66.643l79.759,-0.019l37.942,-66.801l-40.501,-65.64l40.501,-68.129l-38.02,-63.79z" />
|
||||
</vector>
|
|
@ -78,6 +78,8 @@
|
|||
<string name="flag_tile">Flag</string>
|
||||
<string name="retry">Retry</string>
|
||||
<string name="empty">Empty</string>
|
||||
<string name="cant_do_it_now">Impossible to do that now</string>
|
||||
<string name="you_have_received">You have received: +%1$d</string>
|
||||
<string name="unknown_error">Unknown error.</string>
|
||||
<string name="leaderboards">Leaderboards</string>
|
||||
<string name="cancel">Cancel</string>
|
||||
|
@ -116,4 +118,5 @@
|
|||
<string name="flag_placed">Flag placed!</string>
|
||||
<string name="flag_removed">Flag removed!</string>
|
||||
<string name="remove_ad">Remove Ads</string>
|
||||
<string name="help">Help</string>
|
||||
</resources>
|
||||
|
|
Loading…
Reference in a new issue