Skip to content

Commit

Permalink
Fixed a few code comments (#54)
Browse files Browse the repository at this point in the history
* Fixed a few code comments

* Removed Konbini refresh state stuff

* Closable KomojuApi Client
  • Loading branch information
AmniX authored Oct 21, 2024
1 parent f55d386 commit 617f670
Show file tree
Hide file tree
Showing 13 changed files with 165 additions and 64 deletions.
Original file line number Diff line number Diff line change
@@ -1,22 +1,28 @@
package com.komoju.android.sdk

/**
* This annotation means that this option is experimental and subject to change in Future.
* Please test your behaviour overall once you update the komoju SDK Version
* Annotation used to mark APIs in the Komoju SDK as experimental.
* This indicates that the annotated feature or API is subject to change in future releases.
* Users should be cautious and thoroughly test their code after updating the SDK version.
*
* - The annotation requires explicit opt-in to use the marked elements.
* - A warning will be shown when using experimental APIs.
*
* @see [RequiresOptIn] to learn more about Kotlin's opt-in mechanism.
*/
@RequiresOptIn(level = RequiresOptIn.Level.WARNING)
@Retention(AnnotationRetention.BINARY)
@Target(
AnnotationTarget.CLASS,
AnnotationTarget.ANNOTATION_CLASS,
AnnotationTarget.PROPERTY,
AnnotationTarget.FIELD,
AnnotationTarget.LOCAL_VARIABLE,
AnnotationTarget.VALUE_PARAMETER,
AnnotationTarget.CONSTRUCTOR,
AnnotationTarget.FUNCTION,
AnnotationTarget.PROPERTY_GETTER,
AnnotationTarget.PROPERTY_SETTER,
AnnotationTarget.TYPEALIAS,
AnnotationTarget.CLASS, // Can annotate classes
AnnotationTarget.ANNOTATION_CLASS, // Can annotate other annotations
AnnotationTarget.PROPERTY, // Can annotate properties
AnnotationTarget.FIELD, // Can annotate fields
AnnotationTarget.LOCAL_VARIABLE, // Can annotate local variables
AnnotationTarget.VALUE_PARAMETER, // Can annotate function parameters
AnnotationTarget.CONSTRUCTOR, // Can annotate constructors
AnnotationTarget.FUNCTION, // Can annotate functions
AnnotationTarget.PROPERTY_GETTER, // Can annotate property getters
AnnotationTarget.PROPERTY_SETTER, // Can annotate property setters
AnnotationTarget.TYPEALIAS, // Can annotate type aliases
)
annotation class ExperimentalKomojuPaymentApi
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ internal class KomojuPaymentActivity : ComponentActivity() {
}

@Composable
fun NewIntentEffect(context: Context, onNewDeeplink: (String) -> Unit) {
private fun NewIntentEffect(context: Context, onNewDeeplink: (String) -> Unit) {
LaunchedEffect(Unit) {
callbackFlow {
val componentActivity = context as ComponentActivity
Expand Down
3 changes: 2 additions & 1 deletion android/src/main/java/com/komoju/android/sdk/KomojuSDK.kt
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import androidx.activity.result.contract.ActivityResultContract
import com.komoju.android.sdk.types.Currency
import com.komoju.android.sdk.types.Language
import com.komoju.android.sdk.ui.theme.ConfigurableTheme
import com.komoju.android.sdk.utils.empty
import kotlin.contracts.ExperimentalContracts
import kotlin.contracts.contract
import kotlinx.parcelize.Parcelize
Expand All @@ -29,7 +30,7 @@ object KomojuSDK {
internal val publishableKey: String?, // Public API key for Komoju integration.
internal val isDebugMode: Boolean, // Debug mode flag for logging and testing.
internal val sessionId: String?, // Unique session ID for payment transaction.
internal val redirectURL: String = "", // URL to redirect after payment completion.
internal val redirectURL: String = String.empty, // URL to redirect after payment completion.
internal val configurableTheme: ConfigurableTheme, // Custom theme for UI elements.
internal val inlinedProcessing: Boolean, // Flag to enable inlined processing.
) : Parcelable {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ internal class PaymentResultScreenModel : ScreenModel {
}

@Composable
internal fun Navigator.paymentResultScreenModel() = rememberNavigatorScreenModel(PaymentResultScreenModel::class.simpleName) {
PaymentResultScreenModel()
}
internal fun Navigator.paymentResultScreenModel() = rememberNavigatorScreenModel(
tag = PaymentResultScreenModel::class.simpleName,
factory = ::PaymentResultScreenModel,
)
26 changes: 26 additions & 0 deletions android/src/main/java/com/komoju/android/sdk/types/Currency.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,43 @@ package com.komoju.android.sdk.types

import java.util.Locale

/**
* Enum class representing supported currencies with corresponding ISO 4217 currency codes.
* Each currency is associated with a specific locale.
*/
enum class Currency(val currencyCode: String) {

/**
* Japanese Yen currency with code "JPY".
*/
JPY(currencyCode = "JPY"),

/**
* United States Dollar currency with code "USD".
*/
USD(currencyCode = "USD"),
;

/**
* Converts the current currency to its corresponding locale.
*
* @return [Locale] for the currency.
* - JPY returns [Locale.JAPAN]
* - USD returns [Locale.US]
*/
fun toLocale(): Locale = when (this) {
JPY -> Locale.JAPAN
USD -> Locale.US
}

companion object {
/**
* Parses the given language code and returns the corresponding [Currency] enum constant.
* If the code does not match any currency, USD is returned as the default.
*
* @param languageCode A string representing the currency code (e.g., "JPY", "USD").
* @return The matching [Currency] enum constant or [USD] if no match is found.
*/
fun parse(languageCode: String): Currency = entries.firstOrNull { it.currencyCode == languageCode } ?: USD
}
}
27 changes: 27 additions & 0 deletions android/src/main/java/com/komoju/android/sdk/types/Language.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,43 @@ package com.komoju.android.sdk.types

import java.util.Locale

/**
* Enum class representing supported languages with their respective language codes.
* Each language is associated with a specific locale.
*/
enum class Language(val languageCode: String) {

/**
* English language with code "en".
*/
ENGLISH(languageCode = "en"),

/**
* Japanese language with code "ja".
*/
JAPANESE(languageCode = "ja"),
;

/**
* Converts the current language to its corresponding locale.
*
* @return [Locale] for the language.
* - ENGLISH returns [Locale.ENGLISH]
* - JAPANESE returns [Locale.JAPANESE]
*/
internal fun toLocale(): Locale = when (this) {
ENGLISH -> Locale.ENGLISH
JAPANESE -> Locale.JAPANESE
}

companion object {
/**
* Provides the default [Language] based on the system's default locale.
*
* @return The corresponding [Language] based on the system's default language:
* - Returns [JAPANESE] if the default language is Japanese.
* - Returns [ENGLISH] for all other cases.
*/
val default
get() = when (Locale.getDefault().language) {
Locale.JAPANESE.language -> JAPANESE
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,15 +85,15 @@ internal fun InlinedPaymentPrimaryButton(
}
}

enum class InlinedPaymentPrimaryButtonState {
internal enum class InlinedPaymentPrimaryButtonState {
LOADING,
IDLE,
SUCCESS,
ERROR,
}

@Composable
fun rememberInlinedPaymentPrimaryButtonState(
internal fun rememberInlinedPaymentPrimaryButtonState(
default: InlinedPaymentPrimaryButtonState = InlinedPaymentPrimaryButtonState.IDLE,
): MutableState<InlinedPaymentPrimaryButtonState> = rememberSaveable { mutableStateOf(default) }

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ import com.komoju.mobile.sdk.entities.PaymentStatus
internal data class KonbiniAwaitingPaymentScreen(val route: KomojuPaymentRoute.KonbiniAwaitingPayment) : Screen {
@Composable
override fun Content() {
val screenModel = rememberScreenModel { KonbiniAwaitingPaymentScreenModel(route.configuration, route.payment) }
val screenModel = rememberScreenModel { KonbiniAwaitingPaymentScreenModel(route.payment) }
val uiState by screenModel.state.collectAsStateWithLifecycle()
RouterEffect(screenModel.router.collectAsStateWithLifecycle(), screenModel::onRouteConsumed)
uiState.payment?.let {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,18 +1,14 @@
package com.komoju.android.sdk.ui.screens.awating

import cafe.adriel.voyager.core.model.screenModelScope
import com.komoju.android.sdk.KomojuSDK
import com.komoju.android.sdk.navigation.RouterStateScreenModel
import com.komoju.android.sdk.ui.screens.KomojuPaymentRoute
import com.komoju.android.sdk.ui.screens.Router
import com.komoju.mobile.sdk.entities.Payment
import com.komoju.mobile.sdk.remote.apis.KomojuRemoteApi
import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch

internal class KonbiniAwaitingPaymentScreenModel(private val config: KomojuSDK.Configuration, private val payment: Payment? = null) :
RouterStateScreenModel<KonbiniAwaitingPaymentUiState>(KonbiniAwaitingPaymentUiState(payment)) {
private val komojuApi = KomojuRemoteApi(config.publishableKey, config.language.languageCode)
internal class KonbiniAwaitingPaymentScreenModel(payment: Payment? = null) :
RouterStateScreenModel<KonbiniAwaitingPaymentUiState>(
KonbiniAwaitingPaymentUiState(payment),
) {

fun onPrimaryButtonClicked() {
when (val payment = state.value.payment) {
Expand All @@ -22,28 +18,6 @@ internal class KonbiniAwaitingPaymentScreenModel(private val config: KomojuSDK.C
}

fun onSecondaryButtonClicked() {
// when (state.value.payment) {
// is Payment.Konbini -> refreshPayment()
// else -> Unit
// }
mutableRouter.value = Router.Pop
}

fun refreshPayment() {
screenModelScope.launch {
val sessionId = config.sessionId ?: return@launch
mutableState.update {
it.copy(isLoading = true)
}
komojuApi.sessions.verifyPaymentBySessionID(sessionId).onSuccess { payment ->
mutableState.update {
it.copy(payment = payment, isLoading = false)
}
}.onFailure {
mutableState.update {
it.copy(isLoading = false)
}
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ import kotlinx.coroutines.launch

internal class KomojuPaymentScreenModel(private val config: KomojuSDK.Configuration) :
RouterStateScreenModel<KomojuPaymentUIState>(KomojuPaymentUIState()) {
private val komojuApi: KomojuRemoteApi = KomojuRemoteApi(config.publishableKey, config.language.languageCode)
private val komojuApi: KomojuRemoteApi = KomojuRemoteApi.create(config.publishableKey, config.language.languageCode)
private val _offSitePaymentURL = MutableStateFlow<String?>(null)
val offSitePaymentURL = _offSitePaymentURL.asStateFlow()

Expand Down Expand Up @@ -467,4 +467,9 @@ internal class KomojuPaymentScreenModel(private val config: KomojuSDK.Configurat
fun onOffSitePaymentURLConsumed() {
_offSitePaymentURL.value = null
}

override fun onDispose() {
komojuApi.close()
super.onDispose()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import kotlinx.coroutines.launch

internal class VerifyPaymentScreenModel(private val config: KomojuSDK.Configuration) : RouterStateScreenModel<Unit>(Unit) {

private val komojuApi: KomojuRemoteApi = KomojuRemoteApi(config.publishableKey, config.language.languageCode)
private val komojuApi: KomojuRemoteApi = KomojuRemoteApi.create(config.publishableKey, config.language.languageCode)

fun process(type: KomojuPaymentRoute.ProcessPayment.ProcessType) {
screenModelScope.launch {
Expand Down Expand Up @@ -70,4 +70,9 @@ internal class VerifyPaymentScreenModel(private val config: KomojuSDK.Configurat
mutableRouter.value = Router.ReplaceAll(KomojuPaymentRoute.PaymentFailed(Reason.CREDIT_CARD_ERROR))
}
}

override fun onDispose() {
komojuApi.close()
super.onDispose()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,24 +5,66 @@ import android.os.Parcelable
import androidx.annotation.ColorInt
import kotlinx.parcelize.Parcelize

/**
* Interface representing a configurable theme with customizable UI properties.
* This interface extends [Parcelable], allowing themes to be passed between Android components.
*/
interface ConfigurableTheme : Parcelable {
@get:ColorInt val primaryButtonColor: Int

@get:ColorInt val primaryButtonContentColor: Int
/**
* Color value for the primary button background.
*
* @return An integer representing a color value annotated with [ColorInt].
*/
@get:ColorInt
val primaryButtonColor: Int

@get:ColorInt val primaryButtonCornerRadiusInDP: Int
/**
* Color value for the content (e.g., text or icon) inside the primary button.
*
* @return An integer representing a color value annotated with [ColorInt].
*/
@get:ColorInt
val primaryButtonContentColor: Int

@get:ColorInt val loaderColor: Int
/**
* Corner radius for the primary button in density-independent pixels (DP).
*
* @return An integer representing the corner radius in DP annotated with [ColorInt].
*/
@get:ColorInt
val primaryButtonCornerRadiusInDP: Int

/**
* Color value for the loader/spinner.
*
* @return An integer representing a color value annotated with [ColorInt].
*/
@get:ColorInt
val loaderColor: Int

companion object {
/**
* Provides a default implementation of the [ConfigurableTheme].
*/
val default = DefaultConfigurableTheme()
}
}

/**
* Data class representing the default implementation of [ConfigurableTheme].
* This class uses default values for UI elements such as buttons and loaders.
* It is annotated with [Parcelize] to allow it to be passed between Android components.
*
* @param primaryButtonColor The background color of the primary button.
* @param primaryButtonContentColor The color of the content inside the primary button.
* @param primaryButtonCornerRadiusInDP The corner radius of the primary button in DP.
* @param loaderColor The color of the loader/spinner.
*/
@Parcelize
data class DefaultConfigurableTheme(
override val primaryButtonColor: Int = Color.parseColor("#FF297FE7"),
override val primaryButtonContentColor: Int = Color.WHITE,
override val primaryButtonCornerRadiusInDP: Int = 8,
override val loaderColor: Int = Color.parseColor("#FF3CC239"),
override val primaryButtonColor: Int = Color.parseColor("#FF297FE7"), // Default blue color for primary button.
override val primaryButtonContentColor: Int = Color.WHITE, // Default white color for primary button content.
override val primaryButtonCornerRadiusInDP: Int = 8, // Default corner radius of 8 DP for primary button.
override val loaderColor: Int = Color.parseColor("#FF3CC239"), // Default green color for loader.
) : ConfigurableTheme
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,25 @@ package com.komoju.mobile.sdk.remote.apis
import com.komoju.mobile.sdk.i18n.I18nTexts
import com.komoju.mobile.sdk.remote.createNetworkClient

class KomojuRemoteApi(publishableKey: String?, language: String) {
interface KomojuRemoteApi : AutoCloseable {
val sessions: SessionApi
val tokens: TokensApi

companion object {
fun create(publishableKey: String?, language: String): KomojuRemoteApi = KomojuRemoteApiImpl(publishableKey, language)
}
}

internal class KomojuRemoteApiImpl(publishableKey: String?, language: String) : KomojuRemoteApi {
private val networkClient by lazy { createNetworkClient(publishableKey) }

private val i18nTexts by lazy { I18nTexts(language) }

val sessions: SessionApi by lazy { SessionApiImpl(i18nTexts, networkClient) }
val tokens: TokensApi by lazy { TokenApiImpl(networkClient) }
override val sessions: SessionApi by lazy { SessionApiImpl(i18nTexts, networkClient) }

override val tokens: TokensApi by lazy { TokenApiImpl(networkClient) }

override fun close() {
networkClient.close()
}
}

0 comments on commit 617f670

Please sign in to comment.