Skip to content

Commit 5368728

Browse files
author
Tiago Araujo de Souza
committed
Added Nstack
1 parent ed293d0 commit 5368728

File tree

12 files changed

+285
-8
lines changed

12 files changed

+285
-8
lines changed

app/build.gradle

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,14 @@ plugins {
22
id 'com.android.application'
33
id 'kotlin-android'
44
id 'kotlin-kapt'
5-
id 'org.jetbrains.kotlin.plugin.serialization' version '1.4.20'
5+
id 'org.jetbrains.kotlin.plugin.serialization' version '1.4.21'
6+
id 'dk.nstack.translation.plugin'
7+
}
8+
9+
translation {
10+
appId = keys.appId
11+
apiKey = keys.apiKey
12+
acceptHeader = keys.acceptHeader
613
}
714

815
android {
@@ -17,6 +24,11 @@ android {
1724
versionCode 1
1825
versionName "1.0"
1926

27+
manifestPlaceholders = [
28+
appId : keys.appId,
29+
apiKey: keys.apiKey
30+
]
31+
2032
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
2133
}
2234
buildFeatures {
@@ -34,7 +46,8 @@ android {
3446
dimension "default"
3547
applicationIdSuffix ".dev"
3648
manifestPlaceholders = [
37-
APP_NAME: "MonstarlabDev"
49+
APP_NAME: "MonstarlabDev",
50+
env : "staging"
3851
]
3952
buildConfigField "String", "API_URL", "\"https://reqres.in/api/\""
4053
}
@@ -43,7 +56,8 @@ android {
4356
applicationIdSuffix ".staging"
4457
//signingConfig signingConfigs.staging
4558
manifestPlaceholders = [
46-
APP_NAME: "MonstarlabStaging"
59+
APP_NAME: "MonstarlabStaging",
60+
env : "staging"
4761
]
4862
buildConfigField "String", "API_URL", "\"https://reqres.in/api/\""
4963
}
@@ -52,6 +66,7 @@ android {
5266
//signingConfig signingConfigs.production
5367
manifestPlaceholders = [
5468
APP_NAME: "Monstarlab",
69+
env : "production"
5570
]
5671
buildConfigField "String", "API_URL", "\"https://reqres.in/api/\""
5772
}
@@ -93,7 +108,7 @@ dependencies {
93108

94109
implementation("androidx.navigation:navigation-fragment-ktx:2.3.2")
95110
implementation("androidx.navigation:navigation-ui-ktx:2.3.2")
96-
111+
97112
implementation("androidx.lifecycle:lifecycle-livedata-core-ktx:${versions.lifecycle}")
98113
implementation("androidx.lifecycle:lifecycle-runtime-ktx:${versions.lifecycle}")
99114
implementation("androidx.lifecycle:lifecycle-common-java8:${versions.lifecycle}")

app/src/main/AndroidManifest.xml

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,15 @@
11
<?xml version="1.0" encoding="utf-8"?>
22
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
3+
xmlns:tools="http://schemas.android.com/tools"
34
package="com.monstarlab">
45

56
<uses-permission android:name="android.permission.INTERNET" />
67

78
<application
9+
android:name=".App"
810
android:allowBackup="true"
911
android:icon="@mipmap/ic_launcher"
1012
android:label="@string/app_name"
11-
android:name=".App"
1213
android:roundIcon="@mipmap/ic_launcher_round"
1314
android:supportsRtl="true"
1415
android:theme="@style/Theme.Androidtemplate">
@@ -19,6 +20,22 @@
1920
<category android:name="android.intent.category.LAUNCHER" />
2021
</intent-filter>
2122
</activity>
23+
24+
<!-- nstack app id and key from build.gradle manifest placeholder -->
25+
<meta-data
26+
android:name="dk.nodes.nstack.appId"
27+
android:value="${appId}"
28+
tools:replace="android:value" />
29+
<meta-data
30+
android:name="dk.nodes.nstack.apiKey"
31+
android:value="${apiKey}"
32+
tools:replace="android:value" />
33+
34+
<meta-data
35+
android:name="dk.nodes.nstack.env"
36+
android:value="${env}"
37+
tools:replace="android:value" />
38+
2239
</application>
2340

2441
</manifest>
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{"default":{"cancel":"Cancel","ok":"Ok","no":"No","yes":"Yes","retry":"Retry","edit":"Edit","save":"Save","back":"Back","settings":"Settings","later":"Later","next":"Next","previous":"Previous","skip":"Skip","testtest":"__testtest"},"donate":{"donateButton":"Donate!","donateAgainButton":"Donate again!","title":"Help the victims now!"},"error":{"authenticationError":"Login expired, please login again.","connectionError":"No or bad connection, please try again!!!!","errorTitle":"Error","unknownError":"Unknown error, please try again.","errorRandom":"Random"}}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{"default":{"cancel":"Annuller","ok":"Ok","no":"Nej","yes":"Ja","retry":"Pr\u00f8v igen","edit":"Rediger","save":"Gem","back":"Tilbage","settings":"Indstillinger","later":"Senere","next":"N\u00e6ste","previous":"Forrige","skip":"Spring over","testtest":"__testtest"},"donate":{"donateButton":"Don\u00e9r","donateAgainButton":"Don\u00e9r igen","title":"App"},"error":{"authenticationError":"Login er udl\u00f8bet, login venligst ind igen.","connectionError":"Ingen eller d\u00e5rlig forbindelse, pr\u00f8v igen.","errorTitle":"Fejl","unknownError":"Ukendt fejl, pr\u00f8v igen.","errorRandom":"Random"}}

app/src/main/java/com/monstarlab/App.kt

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,21 @@
11
package com.monstarlab
22

3+
import com.monstarlab.features.nstack.Translation
34
import com.monstarlab.injection.components.DaggerAppComponent
45
import dagger.android.AndroidInjector
56
import dagger.android.DaggerApplication
6-
import javax.inject.Inject
7+
import dk.nodes.nstack.kotlin.NStack
8+
import timber.log.Timber
79

810
class App : DaggerApplication() {
911

1012
override fun onCreate() {
1113
super.onCreate()
12-
14+
NStack.translationClass = Translation::class.java
15+
NStack.init(this, BuildConfig.DEBUG)
16+
if (BuildConfig.DEBUG) {
17+
Timber.plant(Timber.DebugTree())
18+
}
1319
}
1420

1521
override fun applicationInjector(): AndroidInjector<out DaggerApplication> {

app/src/main/java/com/monstarlab/arch/base/BaseActivity.kt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package com.monstarlab.arch.base
22

3+
import android.content.Context
34
import android.os.Bundle
45
import androidx.annotation.LayoutRes
56
import androidx.appcompat.app.AppCompatActivity
@@ -10,6 +11,7 @@ import com.monstarlab.arch.extensions.lifecycleAwareLazy
1011
import dagger.android.AndroidInjection
1112
import dagger.android.DispatchingAndroidInjector
1213
import dagger.android.HasAndroidInjector
14+
import dk.nodes.nstack.kotlin.inflater.NStackBaseContext
1315
import javax.inject.Inject
1416

1517
abstract class BaseActivity : AppCompatActivity, HasAndroidInjector {
@@ -28,6 +30,10 @@ abstract class BaseActivity : AppCompatActivity, HasAndroidInjector {
2830
super.onCreate(savedInstanceState)
2931
}
3032

33+
override fun attachBaseContext(newBase: Context) {
34+
super.attachBaseContext(NStackBaseContext(newBase))
35+
}
36+
3137
protected inline fun <reified VM : ViewModel> getViewModel(): VM =
3238
getViewModel(viewModelFactory)
3339

app/src/main/java/com/monstarlab/features/main/MainActivity.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,6 @@ import com.monstarlab.arch.base.BaseActivity
77
class MainActivity : BaseActivity(R.layout.activity_main) {
88
override fun onCreate(savedInstanceState: Bundle?) {
99
super.onCreate(savedInstanceState)
10+
setupNStack()
1011
}
1112
}
Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
package com.monstarlab.features.main
2+
3+
import android.content.Intent
4+
import android.net.Uri
5+
import androidx.appcompat.app.AlertDialog
6+
import androidx.lifecycle.lifecycleScope
7+
import dk.nodes.nstack.kotlin.NStack
8+
import dk.nodes.nstack.kotlin.models.AppUpdate
9+
import dk.nodes.nstack.kotlin.models.AppUpdateState
10+
import dk.nodes.nstack.kotlin.models.Message
11+
import dk.nodes.nstack.kotlin.models.RateReminder
12+
import dk.nodes.nstack.kotlin.models.Result
13+
import dk.nodes.nstack.kotlin.models.state
14+
import dk.nodes.nstack.kotlin.models.update
15+
import kotlinx.coroutines.Dispatchers
16+
import kotlinx.coroutines.launch
17+
import kotlinx.coroutines.withContext
18+
19+
fun MainActivity.setupNStack() = lifecycleScope.launch(Dispatchers.IO) {
20+
when (val result = NStack.appOpen()) {
21+
is Result.Success -> {
22+
withContext(Dispatchers.Main) {
23+
when (result.value.data.update.state) {
24+
AppUpdateState.NONE -> {
25+
/* Nothing to do */
26+
}
27+
AppUpdateState.UPDATE -> showUpdateDialog(result.value.data.update)
28+
AppUpdateState.FORCE -> showForceDialog(result.value.data.update)
29+
AppUpdateState.CHANGELOG -> showChangelogDialog(result.value.data.update)
30+
}
31+
32+
result.value.data.message?.let { showMessageDialog(it) }
33+
result.value.data.rateReminder?.let { showRateReminderDialog(it) }
34+
}
35+
}
36+
is Result.Error -> {
37+
}
38+
}
39+
// if (withContext(Dispatchers.IO) { NStack.RateReminder.shouldShow() }) {
40+
// val answer = NStack.RateReminder.apply {
41+
// title = Translation.rate.title
42+
// message = Translation.rate.message
43+
// yesButton = Translation.rate.yesButton
44+
// noButton = Translation.rate.noButton
45+
// skipButton = Translation.rate.skipButton
46+
// }.show(ContextThemeWrapper(context, R.style.customDialog))
47+
48+
// when (answer) {
49+
// RateReminderAnswer.POSITIVE -> // take user to the playstore page
50+
// RateReminderAnswer.NEGATIVE -> // take user to the feedback screen
51+
// RateReminderAnswer.SKIP -> // do nothing?
52+
// }
53+
// }
54+
}
55+
56+
fun MainActivity.showRateReminderDialog(rateReminder: RateReminder) {
57+
AlertDialog.Builder(this)
58+
.setMessage(rateReminder.body)
59+
.setTitle(rateReminder.title)
60+
.setCancelable(false)
61+
.setPositiveButton(rateReminder.yesButton) { dialog, _ ->
62+
startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(rateReminder.link)))
63+
dialog.dismiss()
64+
}
65+
.setNegativeButton(rateReminder.noButton) { dialog, _ ->
66+
dialog.dismiss()
67+
}
68+
.setNeutralButton(rateReminder.laterButton) { dialog, _ ->
69+
dialog.dismiss()
70+
}
71+
.show()
72+
}
73+
74+
fun MainActivity.showMessageDialog(message: Message) {
75+
AlertDialog.Builder(this)
76+
.setMessage(message.message)
77+
.setCancelable(false)
78+
.setPositiveButton("Translation.defaultSection.ok") { dialog, _ ->
79+
NStack.messageSeen(message)
80+
dialog.dismiss()
81+
}
82+
.show()
83+
}
84+
85+
fun MainActivity.showUpdateDialog(appUpdate: AppUpdate) {
86+
AlertDialog.Builder(this)
87+
.setTitle(appUpdate.update?.translate?.title ?: return)
88+
.setMessage(appUpdate.update?.translate?.message ?: return)
89+
.setPositiveButton(appUpdate.update?.translate?.positiveButton) { dialog, _ ->
90+
dialog.dismiss()
91+
}
92+
.show()
93+
}
94+
95+
fun MainActivity.showChangelogDialog(appUpdate: AppUpdate) {
96+
AlertDialog.Builder(this)
97+
.setTitle(appUpdate.update?.translate?.title ?: return)
98+
.setMessage(appUpdate.update?.translate?.message ?: return)
99+
.setNegativeButton(appUpdate.update?.translate?.negativeButton ?: return) { dialog, _ ->
100+
dialog.dismiss()
101+
}
102+
.show()
103+
}
104+
105+
fun MainActivity.startPlayStore() {
106+
try {
107+
startActivity(
108+
Intent(
109+
Intent.ACTION_VIEW,
110+
Uri.parse("market://details?id=$packageName")
111+
)
112+
)
113+
} catch (anfe: android.content.ActivityNotFoundException) {
114+
startActivity(
115+
Intent(
116+
Intent.ACTION_VIEW,
117+
Uri.parse("https://play.google.com/store/apps/details?id=$packageName")
118+
)
119+
)
120+
}
121+
}
122+
123+
fun MainActivity.showForceDialog(appUpdate: AppUpdate) {
124+
val dialog = AlertDialog.Builder(this)
125+
.setTitle(appUpdate.update?.translate?.title ?: return)
126+
.setMessage(appUpdate.update?.translate?.message ?: return)
127+
.setCancelable(false)
128+
.setPositiveButton(appUpdate.update?.translate?.positiveButton, null)
129+
.create()
130+
131+
dialog.setOnShowListener {
132+
val b = dialog.getButton(AlertDialog.BUTTON_POSITIVE)
133+
b.setOnClickListener {
134+
startPlayStore()
135+
}
136+
}
137+
138+
dialog.show()
139+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package com.monstarlab.features.nstack
2+
3+
import dk.nodes.nstack.kotlin.NStack
4+
5+
/**
6+
* Generated by the NStack gradle plugin
7+
*/
8+
object RateReminderActions {
9+
10+
private const val CRASH = "crash"
11+
private const val DONATED = "donated"
12+
13+
suspend fun crash() {
14+
send(CRASH)
15+
}
16+
17+
suspend fun donated() {
18+
send(DONATED)
19+
}
20+
21+
private suspend fun send(action: String) {
22+
NStack.RateReminder.action(action)
23+
}
24+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
package com.monstarlab.features.nstack;
2+
3+
/**
4+
* Created by nstack.io gradle translation plugin
5+
* Built from Accept Header: en-GB
6+
*/
7+
8+
public class Translation {
9+
public final static class defaultSection {
10+
public static String cancel = "Cancel";
11+
public static String ok = "Ok";
12+
public static String no = "No";
13+
public static String yes = "Yes";
14+
public static String retry = "Retry";
15+
public static String edit = "Edit";
16+
public static String save = "Save";
17+
public static String back = "Back";
18+
public static String settings = "Settings";
19+
public static String later = "Later";
20+
public static String next = "Next";
21+
public static String previous = "Previous";
22+
public static String skip = "Skip";
23+
public static String testtest = "__testtest";
24+
}
25+
public final static class donate {
26+
public static String donateButton = "Donate!";
27+
public static String donateAgainButton = "Donate again!";
28+
public static String title = "Help the victims now!";
29+
}
30+
public final static class error {
31+
public static String authenticationError = "Login expired, please login again.";
32+
public static String connectionError = "No or bad connection, please try again!!!!";
33+
public static String errorTitle = "Error";
34+
public static String unknownError = "Unknown error, please try again.";
35+
public static String errorRandom = "Random";
36+
}
37+
}

0 commit comments

Comments
 (0)