@@ -2,9 +2,13 @@ package com.fredhappyface.ewesticker
22
33import android.content.Context
44import android.net.Uri
5+ import android.os.Handler
6+ import android.os.Looper
7+ import android.view.View
58import androidx.documentfile.provider.DocumentFile
69import com.fredhappyface.ewesticker.utilities.Toaster
710import com.fredhappyface.ewesticker.utilities.Utils
11+ import com.google.android.material.progressindicator.LinearProgressIndicator
812import kotlinx.coroutines.Dispatchers
913import kotlinx.coroutines.async
1014import kotlinx.coroutines.awaitAll
@@ -28,11 +32,19 @@ private const val BUFFER_SIZE = 64 * 1024 // 64 KB
2832class StickerImporter (
2933 private val context : Context ,
3034 private val toaster : Toaster ,
35+ private val progressBar : LinearProgressIndicator ,
3136) {
3237 private val supportedMimes = Utils .getSupportedMimes()
3338 private val packSizes: MutableMap <String , Int > = mutableMapOf ()
3439 private var totalStickers = 0
3540
41+ private val mainHandler = Handler (Looper .getMainLooper())
42+
43+ private fun updateProgressBar (currentProgress : Int , totalStickers : Int ) {
44+ val progressPercentage = (currentProgress.toFloat() / totalStickers.toFloat()) * 100
45+ progressBar.progress = progressPercentage.toInt()
46+ }
47+
3648
3749 /* *
3850 * Used by the ACTION_OPEN_DOCUMENT_TREE handler function to copy stickers from a
@@ -43,18 +55,37 @@ class StickerImporter(
4355 */
4456 suspend fun importStickers (stickerDirPath : String ): Int {
4557 File (context.filesDir, " stickers" ).deleteRecursively()
58+ withContext(Dispatchers .Main ) {
59+ progressBar.visibility = View .VISIBLE
60+ progressBar.isIndeterminate = true
61+ }
62+
4663 val leafNodes = fileWalk(DocumentFile .fromTreeUri(context, Uri .parse(stickerDirPath)))
4764 if (leafNodes.size > MAX_FILES ) {
4865 toaster.setState(1 )
4966 }
5067
68+ withContext(Dispatchers .Main ) {
69+ progressBar.isIndeterminate = false
70+ }
71+
72+
5173 // Perform concurrent file copy operations
5274 withContext(Dispatchers .IO ) {
53- leafNodes.take(MAX_FILES ).map { file ->
54- async { importSticker(file) }
75+ leafNodes.take(MAX_FILES ).mapIndexed { index, file ->
76+ async {
77+ importSticker(file)
78+ mainHandler.post {
79+ updateProgressBar(index + 1 , leafNodes.size)
80+ }
81+ }
5582 }.awaitAll()
5683 }
5784
85+ withContext(Dispatchers .Main ) {
86+ progressBar.visibility = View .GONE
87+ }
88+
5889 return leafNodes.size
5990 }
6091
@@ -107,18 +138,24 @@ class StickerImporter(
107138 */
108139 private fun fileWalk (rootNode : DocumentFile ? ): Set <DocumentFile > {
109140 val leafNodes = mutableSetOf<DocumentFile >()
110- if (rootNode == null || totalStickers >= MAX_FILES ) {
111- return leafNodes
112- }
113- rootNode.listFiles().forEach { file ->
114- if (file.isFile) {
115- leafNodes.add(file)
116- totalStickers++
117- } else if (file.isDirectory) {
118- leafNodes.addAll(fileWalk(file))
119- }
120- if (totalStickers >= MAX_FILES ) {
121- return @forEach
141+ val stack = ArrayDeque <DocumentFile ?>()
142+
143+ rootNode?.let { stack.addLast(it) }
144+
145+ while (stack.isNotEmpty() && leafNodes.size < MAX_FILES ) {
146+ val currentFile = stack.removeLast()
147+
148+ currentFile?.listFiles()?.forEach { file ->
149+ if (file.isFile) {
150+ leafNodes.add(file)
151+ totalStickers++
152+
153+ if (leafNodes.size >= MAX_FILES ) {
154+ return leafNodes
155+ }
156+ } else if (file.isDirectory) {
157+ stack.addLast(file)
158+ }
122159 }
123160 }
124161 return leafNodes
0 commit comments