☁️
Züs
  • About Züs
  • Concepts
    • Architecture
      • Mining on the Züs Blockchain
        • Onboarding a New Miner or Sharder
        • Block Production Protocol
        • Block Finalization
        • Merkle Patricia Trees(MPT) and Recovery
        • View Change and Distributed Key Generation(DKG)
      • Payment
      • Storage
      • Token Bridge Protocol
      • Resources
    • Tokenomics
      • Staking Process
      • Block Rewards
      • Delegation
    • Store
    • Earn
    • Build
    • NFT
  • Resources
    • Whitepapers
      • Tokenomics Paper
      • Architecture Paper
      • Storage Paper
    • Patents
      • NON-FUNGIBLE TOKEN BLOCKCHAIN PROCESSING
      • FREE STORAGE PROTOCOL FOR BLOCKCHAIN PLATFORM
      • TRANSFERRING CONTENT VIA PROXY RE-ENCRYPTION
      • STREAMING CONTENT VIA BLOCKCHAIN TECHNOLOGY
      • SPLIT-KEY WALLET ACCESS BETWEEN BLOCKCHAINS
      • ENFORCING SECURITY PARAMETERS SPECIFIED BY AN OWNER ON A BLOCKCHAIN PLATFORM
      • CLIENT AUTHENTICATION USING SPLIT KEY SIGNING ON A BLOCKCHAIN PLATFORM
      • BLOCKCHAIN CONTENT PURCHASING PROTOCOL
      • BLOCKCHAIN BASED PRIVACY COMPLIANCE PLATFORM
      • SYSTEMS AND METHODS OF SELF-ADMINISTERED PROTOCOLS ON A BLOCKCHAIN PLATFORM
      • SYSTEMS AND METHODS OF AGGREGATE SIGNING OF DIGITAL SIGNATURES ON MULTIPLE MESSAGES SIMULTANEOUSLY U
      • SYSTEMS AND METHODS OF BLOCKCHAIN PLATFORM FOR AUTOMATED ASSET BASED PROVISIONING OF RESOURCES
      • SYSTEMS AND METHODS OF SELF-FORKING BLOCKCHAIN PROTOCOL
      • SYSTEMS AND METHODS OF SUSTAINABILITY PROTOCOL USING DISTRIBUTED BLOCKCHAIN APPLICATION WITH IoT SEN
      • SYSTEMS AND METHODS OF BLOCKCHAIN PLATFORM FOR DISTRIBUTED APPLICATIONS
  • API Reference
    • Endpoints
      • Block
      • Client
      • Connection
      • DNS
      • File
      • Smart Contracts
      • Blobber Stats
      • Transactions
      • Miners and Sharders
        • Stats
        • State
        • Diagnostics
        • Configuration
        • Smart Contract State
        • Smart Contract Stats
        • Chain Stats
  • Hackathon
    • Register to Hackathon
      • How to Add Members to Hackathon Team
    • Repos
    • Documentation
  • Products
    • Bolt
      • Get Started
      • Stake
      • Activity
      • Buy ZCN
      • Sell ZCN
      • Send Tokens
      • Receive Tokens
      • Settings
        • Manage Profile
        • Wallet
        • Read Pool
      • Troubleshooting
    • Vult
      • Sign Up
      • Upload File
      • Upload an Encrypted File
      • Upload a File to a Folder
      • Share a Uploaded File
      • Move a Uploaded File
      • Delete a File
      • Make File Available Offline
      • Troubleshooting
    • Atlus
      • Dashboard Overview
      • Service Providers
      • Charts
        • Market Charts
        • Network Charts
        • Storage Charts
        • Züs Explainer
      • Blockchain
      • Server Map
    • Blimp
      • Sign Up
        • Buy ZCN for Storage
      • Use Blimp as Direct Storage
      • Use Blimp as S3 Server
        • S3 Operations
      • Use Blimp for Cloud Migration
      • Manage Allocations
        • Extend Size
        • Extend Duration
        • Add Blobber
        • Replace Blobber
        • Make allocation Immutable
        • Freeze Allocation
        • Cancel Allocation
    • Chimney
      • Get Started
      • Deploy Blobber on Own Server
      • Deploy Blobber on Rented Server
      • Stake Blobber
      • Add Blobber
      • Monitor Blobbers
      • Visualize Blobber Logs
      • View Blobber Rank
    • Chalk
      • Sign Up
      • Create NFT Collection
        • Buy ZCN for NFT via ERC token
        • Buy ZCN for NFT via Credit card
      • Explore NFT Collections
      • My NFTs
      • Profile
        • Withdraw Earnings
        • Manage Collections
  • Guides
    • Zus GO SDK
    • Zus JS SDK
    • Zbox CLI
      • Repo
      • Get Started
      • Creating and Managing Allocations
      • Uploading and Managing Files
      • Lock and Unlock Tokens
      • Tips and Troubleshooting
    • Zwallet CLI
      • Repo
      • Get Started
      • Zwallet Operations
      • Staking on miners and sharders
      • Burn and Mint Tokens using Zwallet
      • Troubleshooting
    • Add a Blobber
      • Repo
      • Getting Started
    • Add a Miner/Sharder
      • Repo
      • Getting Started
    • Setup a Blockchain
      • Repo
      • Quickstart
        • Understand the Script
      • Step 1: Set up the project
      • Step 2: Setup the network for Züs components
      • Step 3: Initialize and Build the Züs components
      • Step 4: Start Sharder and Miner Containers
      • Step 5 : Create a wallet using zwalletcli
      • Step 6: Starting the blobber containers
      • Step 7: Validate Züs deployment
      • Step 8: Creating an Allocation on Blobber
      • Restarting Sharder and Miner Containers with CleanDB.
      • Additional Tips and Troubleshooting
    • Glossary
  • Support
    • Help Center
      • Community
      • Issues on Github
      • Contact Us
Powered by GitBook
On this page
  • Select App Directory
  1. Guides
  2. Züs GoSDK
  3. GoSDK for mobile builds (iOS and Android)
  4. Android GoSDK Sample App

Select App Fragments

The page provides instructions on how to add dialog box functionalities to the sample app.

Last updated 1 year ago

Select App Directory

The following directories lie inside the android studio project:

├── ui
│   ├── selectapp
│      ├── AllocationDetailsBottomScreenFragment.kt (Bottom sheet fragment for displaying allocation details)
│      ├── DetailsListAdapter.kt (Adapter for generalised list view)
│      ├── NetworkDetailsBottomScreenFragment.kt (Bottom Sheet fragment for displaying network details)
│      ├── SelectAppFragment.kt  (Navigates to bolt or vult app.)
│      └── WalletDetailsBottomScreenFragment.kt (wallet details bottom sheet fragment in SelectAppFragment.)
       └── DetailsBottomSheetFragment.kt(Bottom sheet fragment for displaying all details )    
ui/selectapp/AllocationDetailsBottomScreenFragment.kt
package org.zus.bolt.helloworld.ui.selectapp

import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.lifecycle.ViewModelProvider
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import org.zus.bolt.helloworld.R
import org.zus.bolt.helloworld.databinding.GenericBottomSheetDetailsFragmentBinding
import org.zus.bolt.helloworld.models.vult.AllocationModel
import org.zus.bolt.helloworld.utils.Utils
import org.zus.bolt.helloworld.databinding.RowDetailsListItemBinding
import org.zus.bolt.helloworld.models.selectapp.DetailsListModel
import org.zus.bolt.helloworld.models.selectapp.DetailsModel
import org.zus.bolt.helloworld.ui.vult.VultViewModel
import org.zus.bolt.helloworld.utils.Utils.Companion.getConvertedDateTime
import org.zus.bolt.helloworld.utils.Utils.Companion.getConvertedSize

class AllocationDetailsBottomScreenFragment(
    private val allocationModel: Allocation,
) : BottomSheetDialogFragment() {
      
    private lateinit var binding: GenericBottomSheetDetailsFragmentBinding
    private lateinit var vultViewModel: VultViewModel
    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View {
        binding = GenericBottomSheetDetailsFragmentBinding.inflate(inflater, container, false)
        vultViewModel = ViewModelProvider(requireActivity())[VultViewModel::class.java]
        binding.tvPageTitle.text = getString(R.string.allocation_details_title)

        CoroutineScope(Dispatchers.Main).launch {

            val statsModel = vultViewModel.getAllocation()?.let { vultViewModel.getStats(it.stats) }

            val allocationDetailsModel = DetailsListModel(
                title = getString(R.string.details),
                detailsList = listOf(
                    DetailsModel(
                        title = "Allocation ID: ${allocationModel.id}",
                        value = allocationModel.id,
                        showArrowButton = false
                    ),
                    DetailsModel(
                        title = "Name: ${allocationModel.name}",
                        value = allocationModel.name,
                        showArrowButton = false
                    ),
                    DetailsModel(
                        title = "Expiration: ${allocationModel.expiration.getConvertedDateTime()}",
                        value = allocationModel.expiration.getConvertedDateTime(),
                        showArrowButton = false
                    ),
                    DetailsModel(
                        title = "Size: ${allocationModel.size.getConvertedSize()}",
                        value = allocationModel.size.getConvertedSize(),
                        showArrowButton = false
                    ),
                    DetailsModel(
                        title = "Used Size: ${statsModel?.used_size?.getConvertedSize() ?: "0"}",
                        value = statsModel?.used_size?.getConvertedSize() ?: "0",
                        showArrowButton = false
                    )
                )
            )

            val shardsAndChallengesDetails = DetailsListModel(
                title = getString(R.string.shards_and_challenges_details_title),
                detailsList = listOf(
                    DetailsModel(
                        title = "Data Shards: ${allocationModel.dataShards}",
                        value = allocationModel.dataShards.toString(),
                        showArrowButton = false
                    ),
                    DetailsModel(
                        title = "Parity Shards: ${allocationModel.parityShards}",
                        value = allocationModel.parityShards.toString(),
                        showArrowButton = false
                    ),
                    DetailsModel(
                        title = "Number of Writes: ${statsModel?.num_of_writes ?: 0}",
                        value = statsModel?.num_of_writes.toString(),
                        showArrowButton = false
                    ),
                    DetailsModel(
                        title = "Number of Reads: ${statsModel?.num_of_reads ?: 0}",
                        value = statsModel?.num_of_reads.toString(),
                        showArrowButton = false
                    ),
                    DetailsModel(
                        title = "Number of Challenges: ${statsModel?.num_success_challenges ?: 0}",
                        value = statsModel?.num_success_challenges.toString(),
                        showArrowButton = false
                    ),
                    DetailsModel(
                        title = "Latest Closed Challenge: ${statsModel?.latest_closed_challenge ?: "No value provided"}",
                        value = statsModel?.latest_closed_challenge ?: "No value provided",
                        showArrowButton = false
                    )
                )
            )
               val allocationDetails = listOf(
                allocationDetailsModel,
                shardsAndChallengesDetails
            )

            binding.detailsListView.removeAllViews()

            for (detailsModel in allocationDetails) {
                val rowDetailsListItemBindings = RowDetailsListItemBinding.inflate(
                    LayoutInflater.from(requireActivity()),
                    binding.detailsListView,
                    false
                )
                rowDetailsListItemBindings.tvDetails.text = detailsModel.title
                rowDetailsListItemBindings.detailsListView.adapter = DetailsListAdapter(
                    requireActivity(),
                    detailsModel.detailsList
                )

                binding.detailsListView.addView(rowDetailsListItemBindings.root)
            }

        }
        return binding.root
    }
}

Describing Code

  • Line 3 to 20 import packages to create view/UI for Allocation Details in the sample app.

  • Line 22 defines a class AllocationDetailsBottomScreenFragment which has following fields:

  • Line 25 defines a private late initialized binding variable that holds Bottom Sheet Dialog object instance

  • Line 28 overrides the onCreateView function which creates and returns the view hierarchy associated with the AllocationDetailsBottomScreen.

  • Line 38 to 71 defines a coroutine allocationDetailsModel that awaits execution of AllocationDetails and sharders/challenges details in the defined format by Details Model instance.

  • Line 73 to 107 defines how sharders and challenges information should be displayed. The display format is similar to Details Model instance.

  • Line 109 to 132 takes all the allocation and sharder information and binds it to the entire view to outermost container in layout.

ui/selectapp/DetailsListAdapter.kt
package org.zus.bolt.helloworld.ui.selectapp

import android.annotation.SuppressLint
import android.content.ClipboardManager
import android.content.Context.CLIPBOARD_SERVICE
import android.text.SpannableString
import android.text.SpannedString
import android.text.style.ForegroundColorSpan
import android.text.style.StyleSpan
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.BaseAdapter
import android.widget.Toast
import androidx.appcompat.app.AlertDialog
import androidx.core.content.ContextCompat
import androidx.fragment.app.FragmentActivity
import androidx.navigation.findNavController
import org.zus.bolt.helloworld.R
import org.zus.bolt.helloworld.databinding.DialogItemViewBinding
import org.zus.bolt.helloworld.databinding.RowDetailsBinding
import org.zus.bolt.helloworld.models.selectapp.DetailsModel
import org.zus.bolt.helloworld.ui.TAG_CREATE_WALLET
import org.zus.bolt.helloworld.utils.Utils.Companion.isValidJson
import org.zus.bolt.helloworld.utils.Utils.Companion.isValidUrl
import org.zus.bolt.helloworld.utils.Utils.Companion.prettyJsonFormat

class DetailsListAdapter(
    private val fragmentActivity: FragmentActivity,
    private val detailsList: List<DetailsModel>,
) : BaseAdapter() {

    override fun getCount(): Int = detailsList.size

    override fun getItem(position: Int): Any {
        return detailsList[position]
    }

    override fun getItemId(position: Int): Long {
        return 0
    }

    @SuppressLint("RestrictedApi")
    override fun getView(position: Int, convertView: View?, parent: ViewGroup?): View {
        val rowDetailsBinding = RowDetailsBinding.inflate(LayoutInflater.from(parent?.context))
        rowDetailsBinding.tvDetailTitle.text = detailsList[position].title

        rowDetailsBinding.rowDetailsRoot.setOnLongClickListener {
            val clipboard =
                fragmentActivity.getSystemService(CLIPBOARD_SERVICE) as ClipboardManager
            clipboard.setPrimaryClip(
                android.content.ClipData.newPlainText(
                    detailsList[position].title,
                    detailsList[position].value
                )
            )
            Toast.makeText(
                fragmentActivity,
                "${detailsList[position].title} Copied to clipboard",
                Toast.LENGTH_SHORT
            ).show()
            true
        }

        if (detailsList[position].value.isValidUrl()) {
            val text = SpannableString(detailsList[position].title).apply {
                if (detailsList[position].title.isValidUrl()) {
                    rowDetailsBinding.tvDetailTitle.setTextColor(
                        ContextCompat.getColor(
                            fragmentActivity,
                            R.color.color_url
                        )
                    )
                } else {
                    val colonIndex = detailsList[position].title.indexOf(":")
                    setSpan(
                        ForegroundColorSpan(
                            ContextCompat.getColor(
                                fragmentActivity,
                                R.color.color_url
                            )
                        ),
                        colonIndex,
                        detailsList[position].title.length,
                        SpannedString.SPAN_EXCLUSIVE_EXCLUSIVE
                    )
                }
            }

            rowDetailsBinding.tvDetailTitle.text = text

            rowDetailsBinding.rowDetailsRoot.setOnClickListener {
                val openUrl = android.content.Intent(android.content.Intent.ACTION_VIEW)
                openUrl.data = android.net.Uri.parse(detailsList[position].value)
                fragmentActivity.startActivity(openUrl)
            }
        }

        if (detailsList[position].showArrowButton) {
            rowDetailsBinding.ibnArrowDetails.visibility = View.VISIBLE

            rowDetailsBinding.rowDetailsRoot.setOnClickListener {
                val detailsBottomSheetDialogFragment =
                    DetailsBottomSheetFragment(detailsList[position])
                detailsBottomSheetDialogFragment.show(
                    fragmentActivity.supportFragmentManager,
                    "detailsBottomSheetDialogFragment"
                )
            }
        } else {
            rowDetailsBinding.ibnArrowDetails.visibility = View.GONE
        }

        return rowDetailsBinding.root
    }
}

Describing Code

  • DetailsListAdapter class defines fields and functions that handles functionality of addition and removal of data in a list without the need to redraw the entire view.

ui/selectapp/NetworkDetailsBottomScreenFragment.kt
package org.zus.bolt.helloworld.ui.selectapp

import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ArrayAdapter
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
import com.google.gson.Gson
import org.zus.bolt.helloworld.R
import org.zus.bolt.helloworld.databinding.GenericBottomSheetDetailsFragmentBinding
import org.zus.bolt.helloworld.databinding.RowDetailsListItemBinding
import org.zus.bolt.helloworld.models.NetworkModel
import org.zus.bolt.helloworld.models.selectapp.DetailsListModel
import org.zus.bolt.helloworld.models.selectapp.DetailsModel
import org.zus.bolt.helloworld.utils.Utils

class NetworkDetailsBottomScreenFragment : BottomSheetDialogFragment() {
    lateinit var binding: GenericBottomSheetDetailsFragmentBinding
    lateinit var networkModel: NetworkModel
    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?,
    ): View {
        binding =
            GenericBottomSheetDetailsFragmentBinding.inflate(inflater, container, false)

        binding.tvPageTitle.text = getString(R.string.network_details_title)

        networkModel = Gson().fromJson(
            Utils(requireContext()).getConfigFromAssets("config.json"),
            NetworkModel::class.java
        )

        val networkDetailsModel = DetailsListModel(
            title = getString(R.string.details),
            detailsList = listOf(
                DetailsModel(
                    title = "Name: ${networkModel.domainUrl}",
                    value = networkModel.domainUrl,
                    showArrowButton = false
                ),
                DetailsModel(
                    title = "Url: ${networkModel.config.blockWorker}",
                    value = networkModel.config.blockWorker,
                    showArrowButton = false
                ),
                DetailsModel(
                    title = "0box Url: ${networkModel.zboxUrl}",
                    value = networkModel.zboxUrl,
                    showArrowButton = false
                )
            )
        )

        val url = DetailsListModel(
            title = "",
            detailsList = listOf(
                DetailsModel(
                    title = networkModel.config.blockWorker,
                    value = networkModel.config.blockWorker,
                    showArrowButton = false
                )
            )
        )


        val networkDetails = listOf(
            networkDetailsModel,
            url
        )

        binding.detailsListView.removeAllViews()

        for (detailsModel in networkDetails) {
            val rowDetailsListItemBindings = RowDetailsListItemBinding.inflate(
                LayoutInflater.from(requireActivity()),
                binding.detailsListView,
                false
            )
            rowDetailsListItemBindings.tvDetails.text = detailsModel.title
            rowDetailsListItemBindings.detailsListView.adapter = DetailsListAdapter(
                requireActivity(),
                detailsModel.detailsList
            )

            binding.detailsListView.addView(rowDetailsListItemBindings.root)
        }

        return binding.root
    }
}

Describing Code:

  • Line 3 to 16 import packages required to create UI for Network Details in App.See here

  • Line 18 defines a class NetworkDetailsBottomScreenFragment which has following fields:

  • (Line 20) A private variable that holds access to NetworkModel instance.

  • Line 21 overrides the onCreateView function which creates and returns the view hierarchy associated with the NetworkDetailsBottomScreenFragment.

  • (Line 27) A private late initialized binding variable that holds Bottom Sheet Dialog object instance.

  • Line 31 to 33 retrieves network configuration from

  • Line 36 to 66 defines how network details should be displayed in UI of the app. The format is defined by DetailsModel

  • Line 69 to 90 defines view binding that help interact code with views defined in line 36 to 66.

  • Line 91 binding.root ties the entire view to outermost container in layout of the app.

ui/selectapp/SelectAppFragment.kt
package org.zus.bolt.helloworld.ui.selectapp

import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import androidx.lifecycle.ViewModelProvider
import androidx.navigation.fragment.findNavController
import com.google.android.material.snackbar.Snackbar
import com.google.gson.Gson
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import org.zus.bolt.helloworld.R
import org.zus.bolt.helloworld.databinding.SelectAppFragmentBinding
import org.zus.bolt.helloworld.models.bolt.WalletModel
import org.zus.bolt.helloworld.ui.mainactivity.MainViewModel
import org.zus.bolt.helloworld.ui.vult.VultViewModel
import org.zus.bolt.helloworld.utils.Utils

class SelectAppFragment : Fragment() {
    lateinit var binding: SelectAppFragmentBinding
    lateinit var mainViewModel: MainViewModel
    lateinit var vultViewModel: VultViewModel

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?,
    ): View? {
        // Inflate the layout for this fragment
        binding = SelectAppFragmentBinding.inflate(inflater, container, false)
        mainViewModel = ViewModelProvider(requireActivity())[MainViewModel::class.java]
        vultViewModel = ViewModelProvider(requireActivity())[VultViewModel::class.java]

        binding.cvWalletDetails.setOnClickListener {
            val walletDetailsBottomScreenFragment =
                WalletDetailsBottomScreenFragment(mainViewModel.wallet!!)
            walletDetailsBottomScreenFragment.show(
                parentFragmentManager,
                "WalletDetailsBottomScreenFragment"
            )
        }
        binding.cvAllocationDetails.setOnClickListener {
            CoroutineScope(Dispatchers.IO).launch {
                try {
                    val allocationModel = vultViewModel.getAllocation()
                    requireActivity().runOnUiThread {
                        if (allocationModel != null)
                            AllocationDetailsBottomScreenFragment(allocationModel).show(
                                parentFragmentManager,
                                "AllocationDetailsBottomScreenFragment")
                        else
                            Snackbar.make(
                                binding.root,
                                "Error: Allocation not found",
                                Snackbar.LENGTH_LONG
                            ).show()
                    }
                } catch (e: Exception) {
                    requireActivity().runOnUiThread {
                        Snackbar.make(
                            binding.root,
                            "Error: ${e.message}",
                            Snackbar.LENGTH_LONG
                        ).show()
                    }
                }
            }

        }
        binding.cvNetworkDetails.setOnClickListener {
            val networkDetailsBottomScreenFragment =
                NetworkDetailsBottomScreenFragment()
            networkDetailsBottomScreenFragment.show(
                parentFragmentManager,
                "NetworkDetailsBottomScreenFragment"
            )
        }

        binding.cvBolt.setOnClickListener {
            if (!Utils(requireContext()).isWalletExist()) {
                findNavController().navigate(R.id.action_selectAppFragment_to_boltFragment)
            } else {
                mainViewModel.wallet =
                    Gson().fromJson(
                        Utils(requireContext()).readWalletFromFileJSON(),
                        WalletModel::class.java
                    )
                mainViewModel.setWalletJson(Utils(requireContext()).readWalletFromFileJSON())
                findNavController().navigate(R.id.action_selectAppFragment_to_boltFragment)
            }
        }
        binding.cvVult.setOnClickListener {
            if (!Utils(requireContext()).isWalletExist()) {
                findNavController().navigate(R.id.action_selectAppFragment_to_vultFragment)
            } else {
                mainViewModel.wallet =
                    Gson().fromJson(
                        Utils(requireContext()).readWalletFromFileJSON(),
                        WalletModel::class.java
                    )
                mainViewModel.setWalletJson(Utils(requireContext()).readWalletFromFileJSON())
                findNavController().navigate(R.id.action_selectAppFragment_to_vultFragment)
            }
        }
        return binding.root
    }
}

Describing Code:

  • Line 3 to 16 import packages that are required to create views for the selected app parts in the app.

  • Line 22 defines a class SelectAppFragment which has following fields

    • A late intialized variable binding that holds SelectAppFragment Binding instance.

    • A late initialized variable mainViewModel that holds MainViewModel instance.

    • A late initialized variable vultViewModel that holds VultViewModel instance

  • Line 27 overrides the onCreateView function which creates and returns the view hierarchy associated with the SelectAppFragment.

    • Line 32 selected app fragment binding is called via inflate which will uncompress all the binding data and provide the container with the uncompressed data

    • Line 33 mainViewModel variable get assigned with a ViewModelProvider instance which provides Models to produce Views for MainViewModel.

    • Line 34 VultViewModel variable gets assigned with a ViewModelProvider instance which provides Models to produce Views for VultViewModel.

  • Line 36 to 42 defines view for for data related to Wallet Details. On button click present the recyclable view in WalletDetailsBottomScreenFragment

  • Line 44 to 71 defines view for the data related to Allocation Details. On button click present the recyclable view in AllocationDetailsBottomScreenFragment

  • Line 72 to 79 defines view for the data related to Network Details.On button click present the view in NetworkDetailsBottomScreenFragment

  • Line 81 to 93 defines view for Bolt selected part. It sets the wallet via WalletModel on and navigates the user to Bolt UI on button click.

  • Line 94 to 105 defines view for Vult selected part. It sets the wallet via WalletModel and navigates the user to VultUI on button click.

  • Line 107 binding.root binds the entire view to outermost container in layout.

ui/selectapp/WalletDetailsBottomScreenFragment.kt
package org.zus.bolt.helloworld.ui.selectapp

import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
import org.zus.bolt.helloworld.R
import org.zus.bolt.helloworld.databinding.GenericBottomSheetDetailsFragmentBinding
import org.zus.bolt.helloworld.databinding.RowDetailsListItemBinding
import org.zus.bolt.helloworld.models.bolt.WalletModel
import org.zus.bolt.helloworld.models.selectapp.DetailsListModel
import org.zus.bolt.helloworld.models.selectapp.DetailsModel
import org.zus.bolt.helloworld.utils.Utils.Companion.prettyJsonFormat

class WalletDetailsBottomScreenFragment(
    private val walletModel: WalletModel,
) : BottomSheetDialogFragment() {
    private lateinit var binding: GenericBottomSheetDetailsFragmentBinding
    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?,
    ): View {
        binding = GenericBottomSheetDetailsFragmentBinding.inflate(inflater, container, false)

        binding.tvPageTitle.text = getString(R.string.wallet_details_title)

        val walletDetailsListModel = DetailsListModel(
            title = getString(R.string.details),
            detailsList = listOf(
                DetailsModel(
                    title = "ClientID",
                    value = walletModel.mClientId,
                    showArrowButton = true
                ),
                DetailsModel(
                    title = "Private Encryption Key",
                    value = walletModel.mKeys[0].mPrivateKey,
                    showArrowButton = true
                ),
                DetailsModel(
                    title = "Public Encryption Key",
                    value = walletModel.mKeys[0].mPublicKey,
                    showArrowButton = true
                ),
                DetailsModel(
                    title = "Mnemonics",
                    value = walletModel.mMnemonics,
                    showArrowButton = true
                )
            )
        )
        val walletJsonModel = DetailsListModel(
            title = getString(R.string.wallet_json_title),
            detailsList = listOf(
                DetailsModel(
                    title = walletModel.walletJson.prettyJsonFormat(),
                    value = walletModel.walletJson,
                    showArrowButton = false
                )
            )
        )

        val detailsListModel = listOf(walletDetailsListModel, walletJsonModel)
        //linear layout adapter

        binding.detailsListView.removeAllViews()

        for (detailsModel in detailsListModel) {
            val rowDetailsListItemBindings = RowDetailsListItemBinding.inflate(
                LayoutInflater.from(requireActivity()),
                binding.detailsListView,
                false
            )
            rowDetailsListItemBindings.tvDetails.text = detailsModel.title
            rowDetailsListItemBindings.detailsListView.adapter = DetailsListAdapter(
                requireActivity(),
                detailsModel.detailsList
            )

            binding.detailsListView.addView(rowDetailsListItemBindings.root)
        }

        return binding.root
    }
}
  • Line 3 to 12 import packages required to create UI for Network Details in App.

  • Line 15 defines a class NetworkDetailsBottomScreenFragment which has following fields:

    • (Line 16) A private variable that holds access to NetworkModel instance.

    • (Line 15) A private late initialized binding variable that holds Bottom Sheet Dialog object instance

  • Line 17 overrides the onCreateView function which creates and returns the view hierarchy associated with the NetworkDetailsBottomScreenFragment.

    • The Network Details are fetched via [Utils.kt] method and from config.json stored in assets.

  • Line 41 and 43 defines a variable linearArrayAdapter that holds Network details in DetailListAdaptertype. DetailsListView handles addition and removal without the need to redraw the entire view

  • Line 43 binding.root binds the entire view to outermost container in layout.

ui/selectapp/DetailsBottomSheetFragment.kt
package org.zus.bolt.helloworld.ui.selectapp

import android.content.ClipData
import android.content.ClipboardManager
import android.content.Context.CLIPBOARD_SERVICE
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Toast
import androidx.navigation.fragment.findNavController
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
import org.zus.bolt.helloworld.databinding.DetailsFragmentBinding
import org.zus.bolt.helloworld.models.selectapp.DetailsModel

class DetailsBottomSheetFragment(
    private val detailsModel: DetailsModel,
) : BottomSheetDialogFragment() {
    private lateinit var binding: DetailsFragmentBinding

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

        /* Header title. */
        binding.tvHeaderTitle.text = detailsModel.title
        binding.btnBack.setOnClickListener {
            findNavController().popBackStack()
        }

        binding.tvDetails.text = detailsModel.value
        binding.tvDetails.setOnLongClickListener {
            val clipboard =
                requireActivity().getSystemService(CLIPBOARD_SERVICE) as ClipboardManager
            val clip = ClipData.newPlainText("label", detailsModel.value)
            clipboard.setPrimaryClip(clip)
            Toast.makeText(requireContext(), "Copied to clipboard", Toast.LENGTH_SHORT).show()
            true
        }

        return binding.root
    }
}

Describing Code :

  • Line 3 to 14 import packages to create fragment for viewing details in the sample app.

  • Line 16 defines a class DetailsBottomScreenFragment which has following fields

  • Line 19 defines a private late initialized binding variable that holds DetailsFragmentBinding object.

  • Line 21 to 42 overrides the onCreateView function which creates and returns the view for the details reusable portion of the sample app.

  • Line 44 binds the entire view to outermost container in layout.

The view hierarchy as follows:(Line 25 to 35) in a BottomSheetDialog Network Name ,URL,0box URL and Domain are list as list pairs. See for reference

gif
config.json
gif