progress bar + material you title bar
This commit is contained in:
parent
04159344d7
commit
d440ed33f3
@ -77,7 +77,6 @@ dependencies {
|
|||||||
testImplementation("androidx.test.ext:junit:1.1.5")
|
testImplementation("androidx.test.ext:junit:1.1.5")
|
||||||
testImplementation("androidx.test.espresso:espresso-core:3.5.1")
|
testImplementation("androidx.test.espresso:espresso-core:3.5.1")
|
||||||
implementation("com.google.code.gson:gson:2.10.1")
|
implementation("com.google.code.gson:gson:2.10.1")
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ktlint {
|
ktlint {
|
||||||
|
@ -16,6 +16,7 @@ import androidx.appcompat.app.AppCompatActivity
|
|||||||
import androidx.lifecycle.lifecycleScope
|
import androidx.lifecycle.lifecycleScope
|
||||||
import androidx.preference.PreferenceManager
|
import androidx.preference.PreferenceManager
|
||||||
import com.fredhappyface.ewesticker.utilities.Toaster
|
import com.fredhappyface.ewesticker.utilities.Toaster
|
||||||
|
import com.google.android.material.progressindicator.LinearProgressIndicator
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
@ -120,11 +121,13 @@ class MainActivity : AppCompatActivity() {
|
|||||||
toaster.toast(getString(R.string.imported_010))
|
toaster.toast(getString(R.string.imported_010))
|
||||||
val button = findViewById<Button>(R.id.updateStickerPackInfoBtn)
|
val button = findViewById<Button>(R.id.updateStickerPackInfoBtn)
|
||||||
val button2 = findViewById<Button>(R.id.reloadStickerPackInfoBtn)
|
val button2 = findViewById<Button>(R.id.reloadStickerPackInfoBtn)
|
||||||
|
val progressBar = findViewById<LinearProgressIndicator>(R.id.linearProgressIndicator)
|
||||||
button.isEnabled = false
|
button.isEnabled = false
|
||||||
button2.isEnabled = false
|
button2.isEnabled = false
|
||||||
|
|
||||||
lifecycleScope.launch(Dispatchers.IO) {
|
lifecycleScope.launch(Dispatchers.IO) {
|
||||||
val totalStickers = StickerImporter(baseContext, toaster).importStickers(stickerDirPath)
|
val totalStickers =
|
||||||
|
StickerImporter(baseContext, toaster, progressBar).importStickers(stickerDirPath)
|
||||||
|
|
||||||
withContext(Dispatchers.Main) {
|
withContext(Dispatchers.Main) {
|
||||||
toaster.toastOnState(
|
toaster.toastOnState(
|
||||||
|
@ -2,9 +2,13 @@ package com.fredhappyface.ewesticker
|
|||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
|
import android.os.Handler
|
||||||
|
import android.os.Looper
|
||||||
|
import android.view.View
|
||||||
import androidx.documentfile.provider.DocumentFile
|
import androidx.documentfile.provider.DocumentFile
|
||||||
import com.fredhappyface.ewesticker.utilities.Toaster
|
import com.fredhappyface.ewesticker.utilities.Toaster
|
||||||
import com.fredhappyface.ewesticker.utilities.Utils
|
import com.fredhappyface.ewesticker.utilities.Utils
|
||||||
|
import com.google.android.material.progressindicator.LinearProgressIndicator
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.async
|
import kotlinx.coroutines.async
|
||||||
import kotlinx.coroutines.awaitAll
|
import kotlinx.coroutines.awaitAll
|
||||||
@ -28,11 +32,19 @@ private const val BUFFER_SIZE = 64 * 1024 // 64 KB
|
|||||||
class StickerImporter(
|
class StickerImporter(
|
||||||
private val context: Context,
|
private val context: Context,
|
||||||
private val toaster: Toaster,
|
private val toaster: Toaster,
|
||||||
|
private val progressBar: LinearProgressIndicator,
|
||||||
) {
|
) {
|
||||||
private val supportedMimes = Utils.getSupportedMimes()
|
private val supportedMimes = Utils.getSupportedMimes()
|
||||||
private val packSizes: MutableMap<String, Int> = mutableMapOf()
|
private val packSizes: MutableMap<String, Int> = mutableMapOf()
|
||||||
private var totalStickers = 0
|
private var totalStickers = 0
|
||||||
|
|
||||||
|
private val mainHandler = Handler(Looper.getMainLooper())
|
||||||
|
|
||||||
|
private fun updateProgressBar(currentProgress: Int, totalStickers: Int) {
|
||||||
|
val progressPercentage = (currentProgress.toFloat() / totalStickers.toFloat()) * 100
|
||||||
|
progressBar.progress = progressPercentage.toInt()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Used by the ACTION_OPEN_DOCUMENT_TREE handler function to copy stickers from a
|
* Used by the ACTION_OPEN_DOCUMENT_TREE handler function to copy stickers from a
|
||||||
@ -43,18 +55,37 @@ class StickerImporter(
|
|||||||
*/
|
*/
|
||||||
suspend fun importStickers(stickerDirPath: String): Int {
|
suspend fun importStickers(stickerDirPath: String): Int {
|
||||||
File(context.filesDir, "stickers").deleteRecursively()
|
File(context.filesDir, "stickers").deleteRecursively()
|
||||||
|
withContext(Dispatchers.Main) {
|
||||||
|
progressBar.visibility = View.VISIBLE
|
||||||
|
progressBar.isIndeterminate = true
|
||||||
|
}
|
||||||
|
|
||||||
val leafNodes = fileWalk(DocumentFile.fromTreeUri(context, Uri.parse(stickerDirPath)))
|
val leafNodes = fileWalk(DocumentFile.fromTreeUri(context, Uri.parse(stickerDirPath)))
|
||||||
if (leafNodes.size > MAX_FILES) {
|
if (leafNodes.size > MAX_FILES) {
|
||||||
toaster.setState(1)
|
toaster.setState(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
withContext(Dispatchers.Main) {
|
||||||
|
progressBar.isIndeterminate = false
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Perform concurrent file copy operations
|
// Perform concurrent file copy operations
|
||||||
withContext(Dispatchers.IO) {
|
withContext(Dispatchers.IO) {
|
||||||
leafNodes.take(MAX_FILES).map { file ->
|
leafNodes.take(MAX_FILES).mapIndexed { index, file ->
|
||||||
async { importSticker(file) }
|
async {
|
||||||
|
importSticker(file)
|
||||||
|
mainHandler.post {
|
||||||
|
updateProgressBar(index + 1, leafNodes.size)
|
||||||
|
}
|
||||||
|
}
|
||||||
}.awaitAll()
|
}.awaitAll()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
withContext(Dispatchers.Main) {
|
||||||
|
progressBar.visibility = View.GONE
|
||||||
|
}
|
||||||
|
|
||||||
return leafNodes.size
|
return leafNodes.size
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -107,18 +138,24 @@ class StickerImporter(
|
|||||||
*/
|
*/
|
||||||
private fun fileWalk(rootNode: DocumentFile?): Set<DocumentFile> {
|
private fun fileWalk(rootNode: DocumentFile?): Set<DocumentFile> {
|
||||||
val leafNodes = mutableSetOf<DocumentFile>()
|
val leafNodes = mutableSetOf<DocumentFile>()
|
||||||
if (rootNode == null || totalStickers >= MAX_FILES) {
|
val stack = ArrayDeque<DocumentFile?>()
|
||||||
return leafNodes
|
|
||||||
}
|
rootNode?.let { stack.addLast(it) }
|
||||||
rootNode.listFiles().forEach { file ->
|
|
||||||
if (file.isFile) {
|
while (stack.isNotEmpty() && leafNodes.size < MAX_FILES) {
|
||||||
leafNodes.add(file)
|
val currentFile = stack.removeLast()
|
||||||
totalStickers++
|
|
||||||
} else if (file.isDirectory) {
|
currentFile?.listFiles()?.forEach { file ->
|
||||||
leafNodes.addAll(fileWalk(file))
|
if (file.isFile) {
|
||||||
}
|
leafNodes.add(file)
|
||||||
if (totalStickers >= MAX_FILES) {
|
totalStickers++
|
||||||
return@forEach
|
|
||||||
|
if (leafNodes.size >= MAX_FILES) {
|
||||||
|
return leafNodes
|
||||||
|
}
|
||||||
|
} else if (file.isDirectory) {
|
||||||
|
stack.addLast(file)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return leafNodes
|
return leafNodes
|
||||||
|
@ -1,15 +1,48 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<com.google.android.material.circularreveal.coordinatorlayout.CircularRevealCoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
android:id="@+id/activityMainRoot"
|
android:id="@+id/activityMainRoot"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:background="@color/bg">
|
android:background="@color/bg">
|
||||||
|
|
||||||
<ScrollView
|
<com.google.android.material.appbar.AppBarLayout
|
||||||
|
android:id="@+id/appBarLayout"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:background="@color/accent">
|
||||||
|
|
||||||
|
<com.google.android.material.appbar.CollapsingToolbarLayout
|
||||||
|
android:id="@+id/collapsingToolbarLayout"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
app:layout_scrollFlags="scroll|exitUntilCollapsed"
|
||||||
|
android:background="@color/accent"
|
||||||
|
app:collapsedTitleTextAppearance="@style/ToolbarTitleTextAppearance"
|
||||||
|
app:expandedTitleTextAppearance="@style/ToolbarTitleTextAppearance"
|
||||||
|
app:title=" EweSticker">
|
||||||
|
|
||||||
|
<View
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="@dimen/appbar_padding"
|
||||||
|
android:background="@color/accent" />
|
||||||
|
|
||||||
|
<androidx.appcompat.widget.Toolbar
|
||||||
|
android:id="@+id/toolbar"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="?attr/actionBarSize"
|
||||||
|
app:layout_collapseMode="none"
|
||||||
|
app:layout_collapseParallaxMultiplier="0.7"
|
||||||
|
android:background="@color/accent" />
|
||||||
|
|
||||||
|
|
||||||
|
</com.google.android.material.appbar.CollapsingToolbarLayout>
|
||||||
|
</com.google.android.material.appbar.AppBarLayout>
|
||||||
|
|
||||||
|
<androidx.core.widget.NestedScrollView
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:orientation="vertical">
|
app:layout_behavior="@string/appbar_scrolling_view_behavior">
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
style="@style/widthMatchHeightWrap"
|
style="@style/widthMatchHeightWrap"
|
||||||
@ -111,6 +144,13 @@
|
|||||||
android:onClick="reloadStickers"
|
android:onClick="reloadStickers"
|
||||||
android:text="@string/reload_sticker_pack_button"
|
android:text="@string/reload_sticker_pack_button"
|
||||||
app:shapeAppearance="?attr/shapeAppearanceSmallComponent" />
|
app:shapeAppearance="?attr/shapeAppearanceSmallComponent" />
|
||||||
|
|
||||||
|
<com.google.android.material.progressindicator.LinearProgressIndicator
|
||||||
|
android:id="@+id/linearProgressIndicator"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:visibility="gone" />
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
</com.google.android.material.card.MaterialCardView>
|
</com.google.android.material.card.MaterialCardView>
|
||||||
<!-- Options -->
|
<!-- Options -->
|
||||||
@ -292,5 +332,5 @@
|
|||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
</com.google.android.material.card.MaterialCardView>
|
</com.google.android.material.card.MaterialCardView>
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
</ScrollView>
|
</androidx.core.widget.NestedScrollView>
|
||||||
</com.google.android.material.circularreveal.coordinatorlayout.CircularRevealCoordinatorLayout>
|
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<resources>
|
<resources>
|
||||||
|
|
||||||
<style name="AppTheme" parent="Theme.Material3.DayNight">
|
<style name="AppTheme" parent="Theme.Material3.DayNight.NoActionBar">
|
||||||
<!-- Primary brand color. -->
|
<!-- Primary brand color. -->
|
||||||
<item name="colorPrimaryVariant">@color/accent</item>
|
<item name="colorPrimaryVariant">@color/accent</item>
|
||||||
<item name="colorOnPrimary">@color/onAccent</item>
|
<item name="colorOnPrimary">@color/onAccent</item>
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<resources>
|
<resources>
|
||||||
<dimen name="r_btn">32sp</dimen>
|
<dimen name="r_btn">32sp</dimen>
|
||||||
|
<dimen name="appbar_padding">160dp</dimen>
|
||||||
|
<dimen name="text_size_title">36sp</dimen>
|
||||||
<dimen name="text_size_heading">24sp</dimen>
|
<dimen name="text_size_heading">24sp</dimen>
|
||||||
<dimen name="text_size_body">16sp</dimen>
|
<dimen name="text_size_body">16sp</dimen>
|
||||||
<dimen name="content_margin">10dp</dimen>
|
<dimen name="content_margin">10dp</dimen>
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
<resources>
|
<resources>
|
||||||
<!-- Base application theme. -->
|
<!-- Base application theme. -->
|
||||||
<style name="AppTheme" parent="Theme.Material3.DayNight">
|
<style name="AppTheme" parent="Theme.Material3.DayNight.NoActionBar">
|
||||||
<!-- Primary brand color. -->
|
<!-- Primary brand color. -->
|
||||||
<item name="colorPrimaryVariant">@color/accent</item>
|
<item name="colorPrimaryVariant">@color/accent</item>
|
||||||
<item name="colorOnPrimary">@color/onAccent</item>
|
<item name="colorOnPrimary">@color/onAccent</item>
|
||||||
@ -23,6 +23,11 @@
|
|||||||
<item name="shapeAppearanceSmallComponent">@style/ShapeAppearance.App.SmallComponent</item>
|
<item name="shapeAppearanceSmallComponent">@style/ShapeAppearance.App.SmallComponent</item>
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
<style name="ToolbarTitleTextAppearance" parent="@style/TextAppearance.Widget.AppCompat.Toolbar.Title">
|
||||||
|
<item name="android:textSize">@dimen/text_size_title</item>
|
||||||
|
</style>
|
||||||
|
|
||||||
|
|
||||||
<style name="ShapeAppearance.App.MediumComponent" parent="ShapeAppearance.MaterialComponents.MediumComponent">
|
<style name="ShapeAppearance.App.MediumComponent" parent="ShapeAppearance.MaterialComponents.MediumComponent">
|
||||||
<item name="cornerSize">@dimen/corner</item>
|
<item name="cornerSize">@dimen/corner</item>
|
||||||
</style>
|
</style>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user