Skip to content

Commit

Permalink
Merge pull request #495 from gini/IPC-283-custom-localization-manager
Browse files Browse the repository at this point in the history
Ipc 283 custom localization manager
  • Loading branch information
a-szotyori authored Aug 6, 2024
2 parents 26be54c + 755b716 commit 9b0b8cd
Show file tree
Hide file tree
Showing 30 changed files with 615 additions and 93 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import ch.qos.logback.classic.LoggerContext
import ch.qos.logback.classic.android.LogcatAppender
import ch.qos.logback.classic.encoder.PatternLayoutEncoder
import com.google.android.material.tabs.TabLayoutMediator
import kotlinx.coroutines.launch
import net.gini.android.health.sdk.exampleapp.configuration.ConfigurationFragment
import net.gini.android.health.sdk.exampleapp.databinding.ActivityMainBinding
import net.gini.android.health.sdk.exampleapp.invoices.ui.AppCompatThemeInvoicesActivity
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import kotlinx.coroutines.launch
import net.gini.android.health.sdk.GiniHealth
import net.gini.android.health.sdk.exampleapp.pager.PagerAdapter
import net.gini.android.health.sdk.paymentcomponent.PaymentComponentConfiguration
import net.gini.android.health.sdk.util.GiniLocalization
import java.io.File

class MainViewModel(
Expand Down Expand Up @@ -51,4 +52,10 @@ class MainViewModel(
}

fun getPaymentComponentConfiguration() = paymentComponentConfiguration

fun setGiniHealthLanguage(localization: GiniLocalization, context: Context) {
giniHealth.setSDKLanguage(localization, context)
}

fun getGiniHealthLanguage(context: Context) = GiniHealth.getSDKLanguage(context)
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,15 @@ import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.AdapterView
import android.widget.ArrayAdapter
import androidx.fragment.app.activityViewModels
import net.gini.android.health.sdk.exampleapp.MainViewModel
import net.gini.android.health.sdk.exampleapp.databinding.FragmentConfigurationBinding
import net.gini.android.health.sdk.exampleapp.review.ReviewViewModel
import net.gini.android.health.sdk.paymentcomponent.PaymentComponentConfiguration
import net.gini.android.health.sdk.util.GiniLocalization
import org.koin.android.ext.android.bind

class ConfigurationFragment: Fragment() {

Expand All @@ -25,6 +29,26 @@ class ConfigurationFragment: Fragment() {
with(binding) {
setupSwitchListeners()
}

val languages = arrayOf(GiniLocalization.GERMAN, GiniLocalization.ENGLISH)
context?.let {
val languageAdapter = ArrayAdapter(it, android.R.layout.simple_spinner_dropdown_item, languages)
binding.languageSpinner.apply {
adapter = languageAdapter
onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
override fun onItemSelected(p0: AdapterView<*>?, p1: View?, p2: Int, p3: Long) {
languageAdapter.getItem(p2)?.let {
viewModel.setGiniHealthLanguage(it, context)
}
}

override fun onNothingSelected(p0: AdapterView<*>?) {
}
}
setSelection(languageAdapter.getPosition(viewModel.getGiniHealthLanguage(context)))
}
}

return binding.root
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import android.content.DialogInterface
import android.content.Intent
import android.net.Uri
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatActivity
Expand Down Expand Up @@ -89,11 +90,11 @@ class ReviewActivity : AppCompatActivity() {

supportActionBar?.hide()

val binding = ActivityReviewBinding.inflate(LayoutInflater.from(baseContext))
IntentCompat.getParcelableExtra(intent, MainActivity.PAYMENT_COMPONENT_CONFIG, PaymentComponentConfiguration::class.java)?.let {
viewModel.setPaymentComponentConfig(it)
}

val binding = ActivityReviewBinding.inflate(layoutInflater)
setContentView(binding.root)

binding.toolbar.isGone = showCloseButton
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,34 @@
android:layout_height="wrap_content"
android:checked="false"
android:text="@string/hide_powered_by_gini"/>
</LinearLayout>

<com.google.android.material.divider.MaterialDivider
android:id="@+id/divider3"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/ghs_medium" />

<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">

<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/sdk_language"/>

<View
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="1dp"/>


<Spinner
android:id="@+id/languageSpinner"
android:layout_width="wrap_content"
android:gravity="end"
android:layout_height="wrap_content"/>

</LinearLayout>
</LinearLayout>
1 change: 1 addition & 0 deletions health-sdk/example-app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
<string name="close_screen_for_configurations_to_take_place">The configuration changes will take effect after closing this screen.</string>
<string name="hide_powered_by_gini">Hide powered by Gini on payment component</string>
<string name="gini_health_version">Gini Health SDK v: </string>
<string name="sdk_language">SDK language: </string>

<string name="ghs_privacy_policy_link_url">https://www.google.com</string>
<!-- TODO: Remove or change this placeholder text -->
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package net.gini.android.health.sdk

import android.content.Context
import android.content.SharedPreferences
import android.os.Bundle
import android.os.Parcelable
import androidx.lifecycle.Lifecycle
Expand All @@ -21,11 +23,12 @@ import net.gini.android.health.sdk.review.ReviewFragment
import net.gini.android.health.sdk.review.model.PaymentDetails
import net.gini.android.health.sdk.review.model.PaymentRequest
import net.gini.android.health.sdk.review.model.ResultWrapper
import net.gini.android.health.sdk.review.model.getPaymentExtraction
import net.gini.android.health.sdk.review.model.toPaymentDetails
import net.gini.android.health.sdk.review.model.wrapToResult
import net.gini.android.health.sdk.util.GiniLocalization
import org.slf4j.LoggerFactory
import java.lang.ref.WeakReference
import java.util.Locale

/**
* [GiniHealth] is one of the main classes for interacting with the Gini Health SDK. It manages interaction with the Gini Health API.
Expand Down Expand Up @@ -76,6 +79,17 @@ class GiniHealth(
*/
val openBankState: StateFlow<PaymentState> = _openBankState

/**
* Sets the app language to the desired one from the languages the SDK is supporting. If not set then defaults to the system's language locale.
*
* @param language enum value for the desired language or null for default system language
* @param context Context object to save the configuration.
*/
fun setSDKLanguage(language: GiniLocalization?, context: Context) {
localizedContext = null
GiniHealthPreferences(context).saveSDKLanguage(language)
}

/**
* Sets a [Document] for review. Results can be collected from [documentFlow] and [paymentFlow].
*
Expand Down Expand Up @@ -232,6 +246,23 @@ class GiniHealth(
class Error(val throwable: Throwable) : PaymentState()
}

internal class GiniHealthPreferences(context: Context) {
private val sharedPreferences = context.getSharedPreferences("GiniHealthPreferences", Context.MODE_PRIVATE)

fun saveSDKLanguage(value: GiniLocalization?) {
val editor: SharedPreferences.Editor = sharedPreferences.edit()
editor.putString(SDK_LANGUAGE_PREFS_KEY, value?.readableName?.uppercase())
editor.apply()
}

fun getSDKLanguage(): GiniLocalization? {
val enumValue = sharedPreferences.getString(SDK_LANGUAGE_PREFS_KEY, null)
return if (enumValue.isNullOrEmpty()) null else GiniLocalization.valueOf(enumValue)
}
}

internal var localizedContext: Context? = null

companion object {
private val LOG = LoggerFactory.getLogger(GiniHealth::class.java)

Expand All @@ -242,5 +273,10 @@ class GiniHealth(
private const val PROVIDER = "net.gini.android.health.sdk.GiniHealth"
private const val CAPTURED_ARGUMENTS = "CAPTURED_ARGUMENTS"
private const val PAYABLE = "Payable"
private const val SDK_LANGUAGE_PREFS_KEY = "SDK_LANGUAGE_PREFS_KEY"

fun getSDKLanguage(context: Context): GiniLocalization? {
return GiniHealthPreferences(context).getSDKLanguage()
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,11 @@ import net.gini.android.health.sdk.paymentcomponent.PaymentComponent
import net.gini.android.health.sdk.paymentprovider.PaymentProviderApp
import net.gini.android.health.sdk.util.GhsBottomSheetDialogFragment
import net.gini.android.health.sdk.util.autoCleared
import net.gini.android.health.sdk.util.getLayoutInflaterWithGiniHealthTheme
import net.gini.android.health.sdk.util.getLayoutInflaterWithGiniHealthThemeAndLocale
import net.gini.android.health.sdk.util.setIntervalClickListener
import net.gini.android.health.sdk.util.wrappedWithGiniHealthTheme
import net.gini.android.health.sdk.util.wrappedWithGiniHealthThemeAndLocale
import org.slf4j.LoggerFactory
import java.util.Locale

/**
* The [BankSelectionBottomSheet] displays a list of available banks for the user to choose from. If a banking app is not
Expand All @@ -39,12 +40,17 @@ class BankSelectionBottomSheet private constructor(private val paymentComponent:
private var binding: GhsBottomSheetBankSelectionBinding by autoCleared()
private val viewModel: BankSelectionViewModel by viewModels { BankSelectionViewModel.Factory(paymentComponent) }

override fun onGetLayoutInflater(savedInstanceState: Bundle?): LayoutInflater {
val inflater = super.onGetLayoutInflater(savedInstanceState)
return this.getLayoutInflaterWithGiniHealthThemeAndLocale(inflater, viewModel.paymentComponent?.giniHealthLanguage)
}

override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
binding = GhsBottomSheetBankSelectionBinding.inflate(inflater, container, false)

binding.ghsPaymentProviderAppsList.layoutManager = LinearLayoutManager(requireContext())
binding.ghsPaymentProviderAppsList.adapter =
PaymentProviderAppsAdapter(emptyList(), object : PaymentProviderAppsAdapter.OnItemClickListener {
PaymentProviderAppsAdapter(emptyList(), viewModel.paymentComponent?.giniHealthLanguage, object : PaymentProviderAppsAdapter.OnItemClickListener {
override fun onItemClick(paymentProviderApp: PaymentProviderApp) {
LOG.debug("Selected payment provider app: {}", paymentProviderApp.name)

Expand Down Expand Up @@ -116,6 +122,7 @@ class BankSelectionBottomSheet private constructor(private val paymentComponent:

internal class PaymentProviderAppsAdapter(
var dataSet: List<PaymentProviderAppListItem>,
val locale: Locale?,
val onItemClickListener: OnItemClickListener
) : RecyclerView.Adapter<PaymentProviderAppsAdapter.ViewHolder>() {

Expand All @@ -135,7 +142,7 @@ internal class PaymentProviderAppsAdapter(
}

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val view = GhsItemPaymentProviderAppBinding.inflate(parent.getLayoutInflaterWithGiniHealthTheme(), parent, false)
val view = GhsItemPaymentProviderAppBinding.inflate(parent.getLayoutInflaterWithGiniHealthThemeAndLocale(locale), parent, false)
val viewHolder = ViewHolder(view, object : ViewHolder.OnClickListener {
override fun onClick(adapterPosition: Int) {
onItemClickListener.onItemClick(dataSet[adapterPosition].paymentProviderApp)
Expand All @@ -146,7 +153,7 @@ internal class PaymentProviderAppsAdapter(

override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val paymentProviderAppListItem = dataSet[position]
holder.itemView.context.wrappedWithGiniHealthTheme().let { context ->
holder.itemView.context.wrappedWithGiniHealthThemeAndLocale(locale).let { context ->
holder.button.text = paymentProviderAppListItem.paymentProviderApp.name
holder.iconView.setImageDrawable(paymentProviderAppListItem.paymentProviderApp.icon)
holder.itemView.isSelected = paymentProviderAppListItem.isSelected
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,23 @@ package net.gini.android.health.sdk.moreinformation

import android.text.SpannedString
import android.text.method.LinkMovementMethod
import android.util.Log
import android.view.View
import android.view.ViewGroup
import android.widget.BaseExpandableListAdapter
import android.widget.TextView
import net.gini.android.health.sdk.databinding.GhsItemFaqAnswerBinding
import net.gini.android.health.sdk.databinding.GhsItemFaqLabelBinding
import net.gini.android.health.sdk.util.getLayoutInflaterWithGiniHealthTheme
import net.gini.android.health.sdk.paymentcomponent.PaymentComponent
import net.gini.android.health.sdk.util.getLayoutInflaterWithGiniHealthThemeAndLocale
import java.util.Locale

/**
* Created by dani on 26/02/2024.
*/

internal class FaqExpandableListAdapter(val dataSet: List<Pair<String, CharSequence>>) : BaseExpandableListAdapter() {
internal class FaqExpandableListAdapter(
val dataSet: List<Pair<String, CharSequence>>,
private val locale: Locale?
) : BaseExpandableListAdapter() {
override fun getGroupCount(): Int = dataSet.size
override fun getChildrenCount(listPosition: Int): Int = 1
override fun getGroup(listPosition: Int): Any = dataSet[listPosition].first
Expand All @@ -29,13 +32,13 @@ internal class FaqExpandableListAdapter(val dataSet: List<Pair<String, CharSeque
override fun hasStableIds(): Boolean = true

override fun getGroupView(position: Int, isExpanded: Boolean, p2: View?, parent: ViewGroup): View {
val groupView = GhsItemFaqLabelBinding.inflate(parent.getLayoutInflaterWithGiniHealthTheme(), parent, false)
val groupView = GhsItemFaqLabelBinding.inflate(parent.getLayoutInflaterWithGiniHealthThemeAndLocale(locale), parent, false)
groupView.ghsFaqLabel.text = dataSet[position].first
return groupView.root
}

override fun getChildView(p0: Int, p1: Int, isLastChild: Boolean, convertView: View?, parent: ViewGroup): View {
val groupView = GhsItemFaqAnswerBinding.inflate(parent.getLayoutInflaterWithGiniHealthTheme(), parent, false)
val groupView = GhsItemFaqAnswerBinding.inflate(parent.getLayoutInflaterWithGiniHealthThemeAndLocale(locale), parent, false)
val text = getChild(p0, p1)
if (text is SpannedString) {
groupView.ghsFaqAnswerLabel.movementMethod = LinkMovementMethod.getInstance()
Expand Down
Loading

0 comments on commit 9b0b8cd

Please sign in to comment.