Skip to content

Commit 39c3a52

Browse files
authored
Merge pull request #540 from code-payments/feat/gallery-support
feat: add gallery support and share image to code
2 parents fff2b62 + 80ba960 commit 39c3a52

25 files changed

Lines changed: 411 additions & 123 deletions

File tree

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,4 +51,9 @@ data class CameraGesturesFeature(
5151
data class FlippableTipCardFeature(
5252
override val enabled: Boolean = BetaOptions.Defaults.canFlipTipCard,
5353
override val available: Boolean = true, // always available
54+
): Feature
55+
56+
data class GalleryFeature(
57+
override val enabled: Boolean = BetaOptions.Defaults.galleryEnabled,
58+
override val available: Boolean = true, // always available
5459
): Feature

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ sealed class PrefsBool(val value: String) {
6262
data object TIP_CARD_ON_HOMESCREEN: PrefsBool("tip_card_on_home_screen"), BetaFlag, Immutable
6363
data object TIP_CARD_FLIPPABLE: PrefsBool("tipcard_flippable"), BetaFlag
6464
data object CAMERA_GESTURES_ENABLED: PrefsBool("camera_gestures_enabled"), BetaFlag
65+
data object GALLERY_ENABLED: PrefsBool("gallery_enabled"), BetaFlag
6566
}
6667

6768
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: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ data class BetaOptions(
2323
val tipCardOnHomeScreen: Boolean,
2424
val cameraGesturesEnabled: Boolean,
2525
val canFlipTipCard: Boolean,
26+
val galleryEnabled: Boolean,
2627
) {
2728
companion object {
2829
// Default states for various beta flags in app.
@@ -43,7 +44,8 @@ data class BetaOptions(
4344
shareTweetToTip = true,
4445
tipCardOnHomeScreen = true,
4546
cameraGesturesEnabled = true,
46-
canFlipTipCard = false
47+
canFlipTipCard = false,
48+
galleryEnabled = false
4749
)
4850
}
4951
}
@@ -82,7 +84,8 @@ class BetaFlagsRepository @Inject constructor(
8284
observeBetaFlag(PrefsBool.SHARE_TWEET_TO_TIP, default = defaults.shareTweetToTip),
8385
observeBetaFlag(PrefsBool.TIP_CARD_ON_HOMESCREEN, defaults.tipCardOnHomeScreen),
8486
observeBetaFlag(PrefsBool.CAMERA_GESTURES_ENABLED, defaults.cameraGesturesEnabled),
85-
observeBetaFlag(PrefsBool.TIP_CARD_FLIPPABLE, defaults.canFlipTipCard)
87+
observeBetaFlag(PrefsBool.TIP_CARD_FLIPPABLE, defaults.canFlipTipCard),
88+
observeBetaFlag(PrefsBool.GALLERY_ENABLED, defaults.galleryEnabled),
8689
) {
8790
BetaOptions(
8891
showNetworkDropOff = it[0],
@@ -102,6 +105,8 @@ class BetaFlagsRepository @Inject constructor(
102105
tipCardOnHomeScreen = it[14],
103106
cameraGesturesEnabled = it[15],
104107
canFlipTipCard = it[16],
108+
galleryEnabled = it[17],
109+
105110
)
106111
}
107112
}
@@ -125,19 +130,33 @@ class BetaFlagsRepository @Inject constructor(
125130
PrefsBool.BALANCE_CURRENCY_SELECTION_ENABLED -> balanceCurrencySelectionEnabled
126131
PrefsBool.BUCKET_DEBUGGER_ENABLED -> canViewBuckets
127132
PrefsBool.BUY_MODULE_ENABLED -> buyModuleEnabled
133+
PrefsBool.CAMERA_GESTURES_ENABLED -> cameraGesturesEnabled
128134
PrefsBool.CHAT_UNSUB_ENABLED -> chatUnsubEnabled
129135
PrefsBool.CONVERSATIONS_ENABLED -> conversationsEnabled
130136
PrefsBool.CONVERSATION_CASH_ENABLED -> conversationCashEnabled
131137
PrefsBool.DISPLAY_ERRORS -> displayErrors
138+
PrefsBool.GALLERY_ENABLED -> galleryEnabled
132139
PrefsBool.GIVE_REQUESTS_ENABLED -> giveRequestsEnabled
133140
PrefsBool.KADO_WEBVIEW_ENABLED -> kadoWebViewEnabled
134141
PrefsBool.LOG_SCAN_TIMES -> debugScanTimesEnabled
135142
PrefsBool.SHARE_TWEET_TO_TIP -> shareTweetToTip
136143
PrefsBool.SHOW_CONNECTIVITY_STATUS -> showNetworkDropOff
137144
PrefsBool.TIPS_ENABLED -> tipsEnabled
145+
PrefsBool.TIP_CARD_FLIPPABLE -> canFlipTipCard
138146
PrefsBool.TIP_CARD_ON_HOMESCREEN -> tipCardOnHomeScreen
139147
PrefsBool.VIBRATE_ON_SCAN -> tickOnScan
140-
else -> false
148+
PrefsBool.BUY_MODULE_AVAILABLE -> false
149+
PrefsBool.CAMERA_START_BY_DEFAULT -> false
150+
PrefsBool.DISMISSED_TIP_CARD_BANNER -> false
151+
PrefsBool.ESTABLISH_CODE_RELATIONSHIP -> false
152+
PrefsBool.HAS_REMOVED_LOCAL_CURRENCY -> false
153+
PrefsBool.IS_DEBUG_ACTIVE -> false
154+
PrefsBool.IS_DEBUG_ALLOWED -> false
155+
PrefsBool.IS_ELIGIBLE_GET_FIRST_KIN_AIRDROP -> false
156+
PrefsBool.IS_ELIGIBLE_GIVE_FIRST_KIN_AIRDROP -> false
157+
PrefsBool.REQUIRE_BIOMETRICS -> false
158+
PrefsBool.SEEN_TIP_CARD -> false
159+
PrefsBool.STARTED_TIP_CONNECT -> false
141160
}
142161
}
143162
}

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

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import com.getcode.model.TipCardOnHomeScreenFeature
1010
import com.getcode.model.ConversationCashFeature
1111
import com.getcode.model.ConversationsFeature
1212
import com.getcode.model.FlippableTipCardFeature
13+
import com.getcode.model.GalleryFeature
1314
import kotlinx.coroutines.flow.combine
1415
import kotlinx.coroutines.flow.map
1516
import javax.inject.Inject
@@ -24,7 +25,7 @@ class FeatureRepository @Inject constructor(
2425
val buyModule = combine(
2526
betaFlags.observe().map { it.buyModuleEnabled },
2627
prefRepository.observeOrDefault(PrefsBool.BUY_MODULE_AVAILABLE, false)
27-
) { enabled, available -> BuyModuleFeature(enabled, available) }
28+
) { enabled, available -> BuyModuleFeature(enabled, available) }
2829

2930
val tipCards = betaFlags.observe().map { TipCardFeature(it.tipsEnabled) }
3031
val tipCardOnHomeScreen = betaFlags.observe().map { TipCardOnHomeScreenFeature(it.tipCardOnHomeScreen) }
@@ -34,6 +35,8 @@ class FeatureRepository @Inject constructor(
3435

3536
val cameraGestures = betaFlags.observe().map { CameraGesturesFeature(it.cameraGesturesEnabled) }
3637

38+
val galleryEnabled = betaFlags.observe().map { GalleryFeature(it.galleryEnabled) }
39+
3740
val requestKin = betaFlags.observe().map { RequestKinFeature(it.giveRequestsEnabled) }
3841

3942
val balanceCurrencySelection = betaFlags.observe().map { BalanceCurrencyFeature(it.balanceCurrencySelectionEnabled) }

app/build.gradle.kts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,8 @@ dependencies {
168168

169169
implementation(Libs.androidx_biometrics)
170170

171+
implementation(Libs.androidx_activity)
172+
171173
// cameraX
172174
implementation(Libs.androidx_camerax_core)
173175
implementation(Libs.androidx_camerax_camera2)

app/src/main/AndroidManifest.xml

Lines changed: 26 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
<?xml version="1.0" encoding="utf-8"?>
2-
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
2+
<manifest xmlns:tools="http://schemas.android.com/tools"
3+
xmlns:android="http://schemas.android.com/apk/res/android">
34

45
<uses-feature
56
android:name="android.hardware.camera"
@@ -54,6 +55,18 @@
5455
<category android:name="android.intent.category.LAUNCHER" />
5556
</intent-filter>
5657

58+
<intent-filter>
59+
<action android:name="android.intent.action.SEND"/>
60+
<category android:name="android.intent.category.DEFAULT"/>
61+
<data android:mimeType="text/plain"/>
62+
</intent-filter>
63+
64+
<intent-filter>
65+
<action android:name="android.intent.action.SEND"/>
66+
<category android:name="android.intent.category.DEFAULT"/>
67+
<data android:mimeType="image/*"/>
68+
</intent-filter>
69+
5770
<intent-filter android:autoVerify="true">
5871
<action android:name="android.intent.action.VIEW" />
5972

@@ -151,17 +164,20 @@
151164
</intent-filter>
152165
</activity>
153166

154-
<activity-alias
155-
android:name="com.getcode.view.TweetShareHandler"
156-
android:exported="true"
157-
android:targetActivity="com.getcode.view.MainActivity"
158-
android:enabled="true">
167+
<!--
168+
Prompt Google Play services to install the backported photo picker module
169+
https://developer.android.com/training/data-storage/shared/photopicker#device-availability
170+
-->
171+
<!--suppress AndroidDomInspection -->
172+
<service android:name="com.google.android.gms.metadata.ModuleDependencies"
173+
android:enabled="false"
174+
android:exported="false"
175+
tools:ignore="MissingClass">
159176
<intent-filter>
160-
<action android:name="android.intent.action.SEND"/>
161-
<category android:name="android.intent.category.DEFAULT"/>
162-
<data android:mimeType="text/plain"/>
177+
<action android:name="com.google.android.gms.metadata.MODULE_DEPENDENCIES" />
163178
</intent-filter>
164-
</activity-alias>
179+
<meta-data android:name="photopicker_activity:0:required" android:value="" />
180+
</service>
165181

166182
<service
167183
android:name="com.getcode.util.AuthenticatorService"

app/src/main/java/com/getcode/inject/AppModule.kt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ import com.getcode.util.vibration.Vibrator
2626
import com.getcode.utils.network.Api24NetworkObserver
2727
import com.getcode.utils.network.Api29NetworkObserver
2828
import com.getcode.utils.network.NetworkConnectivityListener
29+
import com.kik.kikx.kikcodes.KikCodeScanner
30+
import com.kik.kikx.kikcodes.implementation.KikCodeScannerImpl
2931
import com.mixpanel.android.mpmetrics.MixpanelAPI
3032
import dagger.Module
3133
import dagger.Provides
@@ -120,4 +122,8 @@ object AppModule {
120122
fun providesBiometricsManager(
121123
@ApplicationContext context: Context
122124
): BiometricManager = BiometricManager.from(context)
125+
126+
@Provides
127+
@Singleton
128+
fun providesCodeScanner(): KikCodeScanner = KikCodeScannerImpl()
123129
}

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

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

3+
import android.net.Uri
34
import com.getcode.model.CurrencyCode
45
import com.getcode.model.Domain
56
import com.getcode.model.Fee
@@ -22,6 +23,7 @@ data class DeepLinkRequest(
2223
val paymentRequest: PaymentRequest? = null,
2324
val loginRequest: LoginRequest? = null,
2425
val tipRequest: TipRequest? = null,
26+
val imageRequest: ImageRequest? = null,
2527
val successUrl: String?,
2628
val cancelUrl: String?,
2729

@@ -32,9 +34,20 @@ data class DeepLinkRequest(
3234
@SerialName("donation") Donation,
3335
@SerialName("login") Login,
3436
@SerialName("tip") Tip,
37+
@SerialName("internal:image") Image,
3538
}
3639

3740
companion object {
41+
fun fromImage(uri: Uri): DeepLinkRequest {
42+
return DeepLinkRequest(
43+
mode = Mode.Image,
44+
clientSecret = emptyList(),
45+
imageRequest = ImageRequest(uri),
46+
cancelUrl = null,
47+
successUrl = null,
48+
)
49+
}
50+
3851
fun fromTipCardUsername(platform: String, username: String): DeepLinkRequest {
3952
return DeepLinkRequest(
4053
mode = Mode.Tip,
@@ -138,6 +151,10 @@ data class DeepLinkRequest(
138151
tipRequest = TipRequest(platform.name, platform.username)
139152
)
140153
}
154+
155+
Mode.Image -> {
156+
return baseRequest
157+
}
141158
}
142159
}
143160
}
@@ -158,6 +175,10 @@ data class TipRequest(
158175
val username: String,
159176
)
160177

178+
data class ImageRequest(
179+
val uri: Uri
180+
)
181+
161182
private inline fun <reified T> JsonObject.decode(key: String): T? {
162183
return runCatching { Json.decodeFromJsonElement<T>(getValue(key)) }
163184
.onFailure { Timber.e("failed to decode $key from result") }

app/src/main/java/com/getcode/ui/components/AuthCheck.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ fun AuthCheck(
8686
is DeeplinkHandler.Type.Login -> true
8787
is DeeplinkHandler.Type.Cash,
8888
is DeeplinkHandler.Type.Tip,
89+
is DeeplinkHandler.Type.Image,
8990
is DeeplinkHandler.Type.Sdk -> {
9091
val hasAuth = state.isAuthenticated == true
9192
if (!hasAuth) {

0 commit comments

Comments
 (0)