Skip to content

Commit f386b19

Browse files
committed
chore: move share tweet to tip behind beta flag
Signed-off-by: Brandon McAnsh <git@bmcreations.dev>
1 parent 90e7223 commit f386b19

14 files changed

Lines changed: 111 additions & 74 deletions

File tree

api/src/main/java/com/getcode/analytics/AnalyticsManager.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -323,7 +323,7 @@ class AnalyticsManager @Inject constructor(
323323
//Bill
324324
Bill("Bill"),
325325
Request("Request Card"),
326-
TipCard("TIp Card"),
326+
TipCard("Tip Card"),
327327

328328
//Transfer
329329
Transfer("Transfer"),

api/src/main/java/com/getcode/model/PrefBool.kt

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,14 +43,13 @@ sealed class PrefsBool(val value: String) {
4343
data object SHOW_CONNECTIVITY_STATUS: PrefsBool("debug_no_network"), BetaFlag
4444
data object GIVE_REQUESTS_ENABLED: PrefsBool("give_requests_enabled"), BetaFlag
4545
data object BUY_MODULE_ENABLED : PrefsBool("buy_kin_enabled"), BetaFlag
46-
47-
4846
data object CHAT_UNSUB_ENABLED: PrefsBool("chat_unsub_enabled"), BetaFlag
4947
data object TIPS_ENABLED : PrefsBool("tips_enabled"), BetaFlag
5048
data object TIPS_CHAT_ENABLED: PrefsBool("tips_chat_enabled"), BetaFlag
5149
data object TIPS_CHAT_CASH_ENABLED: PrefsBool("tips_chat_cash_enabled"), BetaFlag
5250
data object BALANCE_CURRENCY_SELECTION_ENABLED: PrefsBool("balance_currency_enabled"), BetaFlag
5351
data object KADO_WEBVIEW_ENABLED : PrefsBool("kado_inapp_enabled"), BetaFlag
52+
data object SHARE_TWEET_TO_TIP : PrefsBool("share_tweet_to_tip"), BetaFlag
5453
}
5554

5655
val APP_SETTINGS: List<AppSetting> = listOf(PrefsBool.CAMERA_START_BY_DEFAULT, PrefsBool.REQUIRE_BIOMETRICS)

api/src/main/java/com/getcode/network/repository/BetaFlagsRepository.kt

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ data class BetaOptions(
1919
val tipsChatCashEnabled: Boolean,
2020
val balanceCurrencySelectionEnabled: Boolean,
2121
val kadoWebViewEnabled: Boolean,
22+
val shareTweetToTip: Boolean,
2223
) {
2324
companion object {
2425
// Default states for various beta flags in app.
@@ -36,6 +37,7 @@ data class BetaOptions(
3637
tipsChatCashEnabled = false,
3738
balanceCurrencySelectionEnabled = true,
3839
kadoWebViewEnabled = false,
40+
shareTweetToTip = false
3941
)
4042
}
4143
}
@@ -70,7 +72,8 @@ class BetaFlagsRepository @Inject constructor(
7072
observeBetaFlag(PrefsBool.TIPS_CHAT_CASH_ENABLED, default = defaults.tipsChatCashEnabled),
7173
observeBetaFlag(PrefsBool.BALANCE_CURRENCY_SELECTION_ENABLED, defaults.balanceCurrencySelectionEnabled),
7274
observeBetaFlag(PrefsBool.DISPLAY_ERRORS, default = defaults.displayErrors),
73-
observeBetaFlag(PrefsBool.KADO_WEBVIEW_ENABLED, default = defaults.kadoWebViewEnabled)
75+
observeBetaFlag(PrefsBool.KADO_WEBVIEW_ENABLED, default = defaults.kadoWebViewEnabled),
76+
observeBetaFlag(PrefsBool.SHARE_TWEET_TO_TIP, default = defaults.shareTweetToTip)
7477
) {
7578
BetaOptions(
7679
showNetworkDropOff = it[0],
@@ -86,6 +89,7 @@ class BetaFlagsRepository @Inject constructor(
8689
balanceCurrencySelectionEnabled = it[10],
8790
displayErrors = it[11],
8891
kadoWebViewEnabled = it[12],
92+
shareTweetToTip = it[13]
8993
)
9094
}
9195
}
@@ -98,4 +102,8 @@ class BetaFlagsRepository @Inject constructor(
98102
b.takeIf { a } ?: default
99103
}
100104
}
105+
106+
suspend fun isEnabled(flag: PrefsBool): Boolean {
107+
return prefRepository.get(flag, false)
108+
}
101109
}

app/build.gradle.kts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -223,5 +223,5 @@ dependencies {
223223
implementation(Libs.timber)
224224
implementation(Libs.bugsnag)
225225

226-
implementation("dev.chrisbanes.haze:haze:0.7.3")
226+
implementation(Libs.haze)
227227
}

app/src/main/AndroidManifest.xml

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -150,13 +150,19 @@
150150
android:scheme="https" />
151151
</intent-filter>
152152

153+
</activity>
154+
155+
<activity-alias
156+
android:name="com.getcode.view.TweetShareHandler"
157+
android:exported="true"
158+
android:targetActivity="com.getcode.view.MainActivity"
159+
android:enabled="false">
153160
<intent-filter>
154161
<action android:name="android.intent.action.SEND"/>
155162
<category android:name="android.intent.category.DEFAULT"/>
156163
<data android:mimeType="text/plain"/>
157164
</intent-filter>
158-
159-
</activity>
165+
</activity-alias>
160166

161167
<service
162168
android:name="com.getcode.util.AuthenticatorService"

app/src/main/java/com/getcode/models/PaymentRequest.kt

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ import com.getcode.utils.ErrorUtils
1010
import com.getcode.vendor.Base58
1111
import kotlinx.serialization.SerialName
1212
import kotlinx.serialization.Serializable
13-
import kotlinx.serialization.encodeToString
1413
import kotlinx.serialization.json.Json
1514
import kotlinx.serialization.json.JsonObject
1615
import kotlinx.serialization.json.decodeFromJsonElement
@@ -58,16 +57,20 @@ data class DeepLinkRequest(
5857

5958
val mode = container.decode<Mode>("mode") ?: return null
6059
Timber.d("mode=$mode")
61-
val secret = container.decode<String>("clientSecret")
62-
val clientSecret = secret?.let { Base58.decode(it) }
60+
val secret = container.decode<String>("clientSecret") ?: return null
61+
val clientSecret = Base58.decode(secret)
62+
if (clientSecret.size != 11) {
63+
Timber.e("Invalid client secret")
64+
return null
65+
}
6366

6467
val (successUrl, cancelUrl) = container.decode<ConfirmParams>("confirmParams")
6568
?: ConfirmParams(null, null)
6669

6770

6871
val baseRequest = DeepLinkRequest(
6972
mode = mode,
70-
clientSecret = clientSecret?.toList().orEmpty(),
73+
clientSecret = clientSecret.toList(),
7174
successUrl = successUrl?.url,
7275
cancelUrl = cancelUrl?.url,
7376
)
@@ -164,10 +167,6 @@ private inline fun <reified T> JsonObject.decode(key: String): T? {
164167
}
165168
}
166169

167-
inline fun <reified T> encode(data: T): String {
168-
return runCatching { Json.encodeToString<T>(data) }.getOrNull().orEmpty()
169-
}
170-
171170
private inline fun <reified T, R> JsonObject.decode(key: String, map: (T) -> R): R? {
172171
return decode<T>(key)?.let { map(it) }
173172
}
@@ -180,7 +179,7 @@ private data class LoginKeys(
180179
)
181180

182181
@Serializable
183-
data class PlatformKeys(
182+
private data class PlatformKeys(
184183
val name: String,
185184
val username: String,
186185
)

app/src/main/java/com/getcode/util/Context.kt

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,8 @@
11
package com.getcode.util
22

33
import android.content.Context
4-
import androidx.biometric.BiometricManager
5-
import androidx.biometric.BiometricPrompt
6-
import androidx.biometric.BiometricPrompt.AuthenticationError
74
import androidx.core.content.ContextCompat
8-
import androidx.fragment.app.FragmentActivity
95
import com.getcode.R
10-
import com.getcode.network.repository.TransactionRepository.ErrorSubmitIntent
11-
import timber.log.Timber
12-
import java.util.concurrent.Executors
136

147
fun Context.launchAppSettings() {
158
val intent = IntentUtils.appSettings()

app/src/main/java/com/getcode/util/DeeplinkHandler.kt

Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,24 @@
11
package com.getcode.util
22

3+
import android.content.Context
34
import android.content.Intent
45
import android.net.Uri
56
import androidx.core.net.toUri
67
import cafe.adriel.voyager.core.screen.Screen
8+
import com.getcode.model.BetaFlag
9+
import com.getcode.model.PrefsBool
710
import com.getcode.models.DeepLinkRequest
811
import com.getcode.models.encode
912
import com.getcode.navigation.screens.HomeScreen
1013
import com.getcode.navigation.screens.LoginScreen
14+
import com.getcode.network.repository.BetaFlagsRepository
1115
import com.getcode.network.repository.encodeBase64
1216
import com.getcode.network.repository.urlDecode
17+
import com.getcode.ui.utils.getActivity
1318
import com.getcode.utils.TraceType
1419
import com.getcode.utils.base64EncodedData
1520
import com.getcode.utils.trace
21+
import dagger.hilt.android.qualifiers.ApplicationContext
1622
import kotlinx.coroutines.flow.MutableStateFlow
1723
import kotlinx.serialization.json.buildJsonObject
1824
import kotlinx.serialization.json.put
@@ -39,7 +45,10 @@ data class DeeplinkResult(
3945
* in favour of the latest request in the navigation graph.
4046
*/
4147
@Singleton
42-
class DeeplinkHandler @Inject constructor() {
48+
class DeeplinkHandler @Inject constructor(
49+
@ApplicationContext private val context: Context,
50+
private val betaFlags: BetaFlagsRepository
51+
) {
4352
var debounceIntent: Intent? = null
4453
set(value) {
4554
intent.value = value
@@ -49,12 +58,13 @@ class DeeplinkHandler @Inject constructor() {
4958

5059
val intent = MutableStateFlow(debounceIntent)
5160

52-
fun handle(intent: Intent? = debounceIntent): DeeplinkResult? {
61+
suspend fun handle(intent: Intent? = debounceIntent): DeeplinkResult? {
62+
println(intent)
5363
val uri = when {
5464
intent?.data != null -> intent.data
5565
intent?.getStringExtra(Intent.EXTRA_TEXT) != null -> {
5666
val sharedLink = intent.getStringExtra(Intent.EXTRA_TEXT)?.toUri() ?: return null
57-
sharedLink.resolveSharedEntity
67+
sharedLink.resolveSharedEntity()
5868
}
5969

6070
else -> null
@@ -108,19 +118,19 @@ class DeeplinkHandler @Inject constructor() {
108118
* Handles converting inbound shared content with possible deeplinks
109119
* e.g sharing a tweet to trigger a tipcard flow
110120
*/
111-
private val Uri.resolveSharedEntity: Uri
112-
get() {
113-
// https://x.com/<username>/status/<tweetId>
114-
return when {
115-
this.host == "x.com" || this.host == "twitter.com" -> {
121+
private suspend fun Uri.resolveSharedEntity(): Uri {
122+
when {
123+
this.host == "x.com" || this.host == "twitter.com" -> {
124+
// https://x.com/<username>/status/<tweetId>
125+
if (betaFlags.isEnabled(PrefsBool.SHARE_TWEET_TO_TIP)) {
116126
// convert shared tweets to owner's tip card
117127
val username = pathSegments.firstOrNull() ?: return this
118-
Uri.parse(Linkify.tipCard(username, "x"))
128+
return Uri.parse(Linkify.tipCard(username, "x"))
119129
}
120-
121-
else -> this
122130
}
123131
}
132+
return this
133+
}
124134

125135
private val Uri.deeplinkType: Type
126136
get() {

app/src/main/java/com/getcode/util/IntentUtils.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
package com.getcode.util
22

3+
import android.content.Context
34
import android.content.Intent
45
import android.net.Uri
56
import android.provider.Settings
67
import com.getcode.BuildConfig
78
import com.getcode.utils.makeE164
89

10+
911
object IntentUtils {
1012

1113
fun appSettings() = Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS).apply {
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
package com.getcode.util
2+
3+
import android.content.ComponentName
4+
import android.content.Context
5+
import android.content.pm.PackageManager
6+
import dagger.hilt.android.qualifiers.ApplicationContext
7+
import javax.inject.Inject
8+
9+
10+
class Pacman @Inject constructor(
11+
@ApplicationContext private val context: Context
12+
) {
13+
private val packageManager = context.packageManager
14+
15+
fun enableTweetShare(enable: Boolean) {
16+
val component = ComponentName(context.packageName, "com.getcode.view.TweetShareHandler")
17+
if (enable) {
18+
packageManager.setComponentEnabledSetting(
19+
component,
20+
PackageManager.COMPONENT_ENABLED_STATE_ENABLED, PackageManager.DONT_KILL_APP
21+
)
22+
} else {
23+
packageManager.setComponentEnabledSetting(
24+
component,
25+
PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP
26+
)
27+
}
28+
}
29+
30+
}

0 commit comments

Comments
 (0)