Repository: skyline-emu/skyline
File: app/src/main/java/emu/skyline/AppDialog.kt (Kotlin)

Code before:

            val fragment = AppDialog()
            fragment.arguments = args
            return fragment
        }
    }

    private lateinit var binding : AppDialogBinding

    private val item by lazy { requireArguments().serializable<AppItem>(AppItemTag)!! }

    private val savesFolderRoot by lazy { "${requireContext().getPublicFilesDir().canonicalPath}/switch/nand/user/save/0000000000000000/00000000000000000000000000000001/" }
    private var lastZipCreated : File? = null
    private val documentPicker = registerForActivityResult(ActivityResultContracts.OpenDocument()) {
        it?.let { uri ->
            try {
                val savesFolder = File(savesFolderRoot)
                var inputZip = requireContext().contentResolver.openInputStream(uri)
                var validZip = false
                // A TitleID must be the first folder name inside the zip in order to be considered valid.
                if (inputZip != null) {
                    ZipInputStream(BufferedInputStream(inputZip)).use { zis ->
                        validZip = Regex("^0100[0-9A-Fa-f]{12}/").containsMatchIn(zis.nextEntry.name)
                    }
                }
                inputZip = requireContext().contentResolver.openInputStream(uri)
                if (inputZip != null && validZip){
                    CoroutineScope(Dispatchers.IO).launch {
                        ZipUtils.unzip(inputZip, savesFolder)
                        withContext(Dispatchers.Main){
                            val isSaveFileOfThisGame = File("$savesFolderRoot${item.titleId}").exists()
                            binding.deleteSave.isEnabled = isSaveFileOfThisGame
                            binding.exportSave.isEnabled = isSaveFileOfThisGame
                            Snackbar.make(binding.root, R.string.save_file_imported_ok, Snackbar.LENGTH_LONG).show()
                        }
                    }
                } else {
                    Snackbar.make(binding.root, getString(R.string.save_file_invalid_zip_structure), Snackbar.LENGTH_LONG).show()
                }
            } catch (e: Exception) {
                Snackbar.make(binding.root, getString(R.string.error), Snackbar.LENGTH_LONG).show()
            }
        }
    }

    /**
     * This inflates the layout of the dialog after initial view creation
     */
    override fun onCreateView(inflater : LayoutInflater, container : ViewGroup?, savedInstanceState : Bundle?) = AppDialogBinding.inflate(inflater).also { binding = it }.root

    override fun onViewCreated(view : View, savedInstanceState : Bundle?) {

Review comment (performance):
Why are you opening the stream again here? Overall this code could be simplified a lot:
- Extract the Zip to the cache dir
- Check if it's valid:
  - Valid: copy to the correct dir inside `files/switch/nand/...`
  - Invalid: tell the user
 - Clean up the extracted filed from the temporary cache

Code after:

            val fragment = AppDialog()
            fragment.arguments = args
            return fragment
        }
    }

    private lateinit var binding : AppDialogBinding

    private val item by lazy { requireArguments().serializable<AppItem>(AppItemTag)!! }

    private val savesFolderRoot by lazy { "${requireContext().getPublicFilesDir().canonicalPath}/switch/nand/user/save/0000000000000000/00000000000000000000000000000001/" }
    private var lastZipCreated : File? = null
    private val documentPicker = registerForActivityResult(ActivityResultContracts.OpenDocument()) {
        it?.let { uri -> importSave(uri) }
    }

    /**
     * This inflates the layout of the dialog after initial view creation
     */
    override fun onCreateView(inflater : LayoutInflater, container : ViewGroup?, savedInstanceState : Bundle?) = AppDialogBinding.inflate(inflater).also { binding = it }.root

    override fun onViewCreated(view : View, savedInstanceState : Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        // Set the peek height after the root view has been laid out
        view.apply {
            post {
                val behavior = BottomSheetBehavior.from(parent as View)
                behavior.peekHeight = height
            }
        }

        binding.gameIcon.setImageBitmap(item.bitmapIcon)
        binding.gameTitle.text = item.title
        binding.gameVersion.text = item.version ?: item.loaderResultString(requireContext())
        binding.gameTitleId.text = item.titleId
        binding.gameAuthor.text = item.author

        binding.gamePlay.isEnabled = item.loaderResult == LoaderResult.Success
        binding.gamePlay.setOnClickListener {
            startActivity(Intent(activity, EmulationActivity::class.java).apply {
                putExtras(requireArguments())
            })
        }

        binding.gameSettings.isEnabled = item.loaderResult == LoaderResult.Success
        binding.gameSettings.setOnClickListener {
            startActivity(Intent(activity, SettingsActivity::class.java).apply {
                putExtras(requireArguments())
            })