= 0L..3000L,
27 | steps: Int = 5
28 | ) {
29 | SettingsSlider(
30 | title = title,
31 | value = value.toFloat(),
32 | onValueChange = { onValueChange(it.roundToLong()) },
33 | valueRange = valueRange.start.toFloat()..valueRange.endInclusive.toFloat(),
34 | steps = steps,
35 | valueFormatter = { "${it / 1000}s" }
36 | )
37 | }
38 |
--------------------------------------------------------------------------------
/app/src/main/java/com/uravgcode/chooser/tutorial/domain/PageData.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2025 UrAvgCode
3 | *
4 | * This program is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU General Public License as published by
6 | * the Free Software Foundation, either version 3 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * You should have received a copy of the GNU General Public License
10 | * along with this program. If not, see .
11 | *
12 | * @author UrAvgCode
13 | * @description Data class that defines the content structure for a single tutorial page.
14 | */
15 |
16 | package com.uravgcode.chooser.tutorial.domain
17 |
18 | import androidx.annotation.DrawableRes
19 |
20 | data class PageData(
21 | @DrawableRes val iconId: Int? = null,
22 | @DrawableRes val previewId: Int,
23 | val title: String,
24 | val description: String,
25 | )
26 |
--------------------------------------------------------------------------------
/app/src/main/java/com/uravgcode/chooser/tutorial/domain/PagerContent.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2025 UrAvgCode
3 | *
4 | * This program is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU General Public License as published by
6 | * the Free Software Foundation, either version 3 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * You should have received a copy of the GNU General Public License
10 | * along with this program. If not, see .
11 | *
12 | * @author UrAvgCode
13 | * @description A list of page data for the tutorial pager.
14 | */
15 |
16 | package com.uravgcode.chooser.tutorial.domain
17 |
18 | import com.uravgcode.chooser.R
19 |
20 | val pagerContent = listOf(
21 | PageData(
22 | previewId = R.drawable.chooser_preview_animated,
23 | title = "Welcome to Chooser",
24 | description = "Make quick, unbiased decisions with a touch. " +
25 | "Place multiple fingers on screen, wait a brief moment, and Chooser will do the rest.",
26 | ),
27 | PageData(
28 | previewId = R.drawable.button_preview_animated,
29 | title = "How to Use",
30 | description = """
31 |
32 | Mode Button
33 | Switch between Single, Group, and Order modes.
34 | Long press to access additional settings.
35 |
36 |
37 |
38 | Number Button
39 | Adjust how many fingers to select or groups to create.
40 |
41 | """,
42 | ),
43 | PageData(
44 | iconId = R.drawable.single_icon,
45 | previewId = R.drawable.single_preview_animated,
46 | title = "Single Mode",
47 | description = "Selects a random finger from all touching the screen.",
48 | ),
49 | PageData(
50 | iconId = R.drawable.group_icon,
51 | previewId = R.drawable.group_preview_animated,
52 | title = "Group Mode",
53 | description = "Divides all fingers into balanced teams or groups.",
54 | ),
55 | PageData(
56 | iconId = R.drawable.order_icon,
57 | previewId = R.drawable.order_preview_animated,
58 | title = "Order Mode",
59 | description = "Creates a random sequence of all fingers on screen.",
60 | ),
61 | )
62 |
--------------------------------------------------------------------------------
/app/src/main/java/com/uravgcode/chooser/tutorial/presentation/TutorialScreen.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2025 UrAvgCode
3 | *
4 | * This program is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU General Public License as published by
6 | * the Free Software Foundation, either version 3 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * You should have received a copy of the GNU General Public License
10 | * along with this program. If not, see .
11 | *
12 | * @author UrAvgCode
13 | * @description TutorialScreen displays tutorial content on first app start.
14 | */
15 |
16 | package com.uravgcode.chooser.tutorial.presentation
17 |
18 | import androidx.compose.foundation.layout.Arrangement
19 | import androidx.compose.foundation.layout.Box
20 | import androidx.compose.foundation.layout.Column
21 | import androidx.compose.foundation.layout.WindowInsets
22 | import androidx.compose.foundation.layout.fillMaxWidth
23 | import androidx.compose.foundation.layout.padding
24 | import androidx.compose.foundation.layout.safeDrawing
25 | import androidx.compose.foundation.pager.HorizontalPager
26 | import androidx.compose.foundation.pager.rememberPagerState
27 | import androidx.compose.material.icons.Icons
28 | import androidx.compose.material.icons.automirrored.filled.ArrowBack
29 | import androidx.compose.material.icons.automirrored.filled.ArrowForward
30 | import androidx.compose.material.icons.filled.Check
31 | import androidx.compose.material3.Icon
32 | import androidx.compose.material3.IconButton
33 | import androidx.compose.material3.MaterialTheme
34 | import androidx.compose.material3.Scaffold
35 | import androidx.compose.material3.Text
36 | import androidx.compose.material3.TextButton
37 | import androidx.compose.runtime.Composable
38 | import androidx.compose.runtime.derivedStateOf
39 | import androidx.compose.runtime.getValue
40 | import androidx.compose.runtime.remember
41 | import androidx.compose.runtime.rememberCoroutineScope
42 | import androidx.compose.ui.Alignment
43 | import androidx.compose.ui.Modifier
44 | import androidx.compose.ui.unit.dp
45 | import com.uravgcode.chooser.tutorial.domain.pagerContent
46 | import com.uravgcode.chooser.tutorial.presentation.component.PageIndicator
47 | import com.uravgcode.chooser.tutorial.presentation.component.TutorialPage
48 | import kotlinx.coroutines.launch
49 | import kotlin.math.absoluteValue
50 |
51 | @Composable
52 | fun TutorialScreen(onComplete: () -> Unit) {
53 | val coroutineScope = rememberCoroutineScope()
54 | val pagerState = rememberPagerState(pageCount = { pagerContent.size })
55 |
56 | Scaffold(
57 | contentWindowInsets = WindowInsets.safeDrawing,
58 | ) { padding ->
59 | Column(
60 | modifier = Modifier.padding(padding),
61 | verticalArrangement = Arrangement.Center
62 | ) {
63 | Box(
64 | modifier = Modifier
65 | .fillMaxWidth()
66 | .padding(horizontal = 16.dp),
67 | ) {
68 | TextButton(
69 | onClick = { onComplete() },
70 | modifier = Modifier.align(Alignment.TopEnd)
71 | ) {
72 | Text(
73 | text = "Skip",
74 | style = MaterialTheme.typography.bodyLarge,
75 | )
76 | }
77 | }
78 |
79 | HorizontalPager(
80 | state = pagerState,
81 | modifier = Modifier.weight(1f),
82 | ) { page ->
83 | val isPageFullyVisible by remember {
84 | derivedStateOf {
85 | pagerState.currentPage == page &&
86 | pagerState.currentPageOffsetFraction.absoluteValue < 0.1f
87 | }
88 | }
89 |
90 | TutorialPage(
91 | iconId = pagerContent[page].iconId,
92 | previewId = pagerContent[page].previewId,
93 | title = pagerContent[page].title,
94 | description = pagerContent[page].description,
95 | isVisible = isPageFullyVisible,
96 | )
97 | }
98 |
99 | Box(
100 | modifier = Modifier
101 | .fillMaxWidth()
102 | .padding(horizontal = 16.dp),
103 | ) {
104 | IconButton(
105 | onClick = {
106 | coroutineScope.launch {
107 | pagerState.animateScrollToPage(pagerState.currentPage - 1)
108 | }
109 | },
110 | modifier = Modifier.align(Alignment.CenterStart)
111 | ) {
112 | Icon(
113 | imageVector = Icons.AutoMirrored.Filled.ArrowBack,
114 | contentDescription = "Back"
115 | )
116 | }
117 |
118 | PageIndicator(
119 | modifier = Modifier.align(Alignment.Center),
120 | pagerState = pagerState
121 | )
122 |
123 | IconButton(
124 | onClick = {
125 | if (pagerState.currentPage < pagerState.pageCount - 1) {
126 | coroutineScope.launch {
127 | pagerState.animateScrollToPage(pagerState.currentPage + 1)
128 | }
129 | } else {
130 | onComplete()
131 | }
132 | },
133 | modifier = Modifier.align(Alignment.CenterEnd)
134 | ) {
135 | Icon(
136 | imageVector = if (pagerState.currentPage < pagerState.pageCount - 1)
137 | Icons.AutoMirrored.Filled.ArrowForward
138 | else
139 | Icons.Default.Check,
140 | contentDescription = "Next"
141 | )
142 | }
143 | }
144 | }
145 | }
146 | }
147 |
--------------------------------------------------------------------------------
/app/src/main/java/com/uravgcode/chooser/tutorial/presentation/component/PageIndicator.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2025 UrAvgCode
3 | *
4 | * This program is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU General Public License as published by
6 | * the Free Software Foundation, either version 3 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * You should have received a copy of the GNU General Public License
10 | * along with this program. If not, see .
11 | *
12 | * @author UrAvgCode
13 | * @description PageIndicator shows the current page position with animated indicators.
14 | */
15 |
16 | package com.uravgcode.chooser.tutorial.presentation.component
17 |
18 | import androidx.compose.foundation.background
19 | import androidx.compose.foundation.layout.Arrangement
20 | import androidx.compose.foundation.layout.Box
21 | import androidx.compose.foundation.layout.Row
22 | import androidx.compose.foundation.layout.height
23 | import androidx.compose.foundation.layout.width
24 | import androidx.compose.foundation.pager.PagerState
25 | import androidx.compose.foundation.shape.CircleShape
26 | import androidx.compose.material3.MaterialTheme
27 | import androidx.compose.runtime.Composable
28 | import androidx.compose.ui.Modifier
29 | import androidx.compose.ui.unit.dp
30 | import kotlin.math.absoluteValue
31 |
32 | @Composable
33 | fun PageIndicator(
34 | modifier: Modifier = Modifier,
35 | pagerState: PagerState
36 | ) {
37 | Row(
38 | modifier = modifier,
39 | horizontalArrangement = Arrangement.spacedBy(8.dp)
40 | ) {
41 | val page = pagerState.currentPage
42 | val offset = pagerState.currentPageOffsetFraction
43 |
44 | repeat(pagerState.pageCount) { index ->
45 | val distance = (index - (page + offset)).absoluteValue
46 | val percentage = (1f - distance).coerceAtLeast(0f)
47 |
48 | val width = 8.dp + (10.dp * percentage)
49 | val alpha = 0.5f + (0.5f * percentage)
50 |
51 | Box(
52 | modifier = Modifier
53 | .width(width)
54 | .height(8.dp)
55 | .background(
56 | color = MaterialTheme.colorScheme.primary.copy(alpha = alpha),
57 | shape = CircleShape
58 | )
59 | )
60 | }
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/app/src/main/java/com/uravgcode/chooser/tutorial/presentation/component/TutorialPage.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2025 UrAvgCode
3 | *
4 | * This program is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU General Public License as published by
6 | * the Free Software Foundation, either version 3 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * You should have received a copy of the GNU General Public License
10 | * along with this program. If not, see .
11 | *
12 | * @author UrAvgCode
13 | * @description TutorialPage displays a tutorial page with an animated preview.
14 | */
15 |
16 | package com.uravgcode.chooser.tutorial.presentation.component
17 |
18 | import androidx.annotation.DrawableRes
19 | import androidx.compose.animation.graphics.ExperimentalAnimationGraphicsApi
20 | import androidx.compose.animation.graphics.res.animatedVectorResource
21 | import androidx.compose.animation.graphics.res.rememberAnimatedVectorPainter
22 | import androidx.compose.animation.graphics.vector.AnimatedImageVector
23 | import androidx.compose.foundation.Image
24 | import androidx.compose.foundation.layout.Arrangement
25 | import androidx.compose.foundation.layout.Column
26 | import androidx.compose.foundation.layout.Row
27 | import androidx.compose.foundation.layout.aspectRatio
28 | import androidx.compose.foundation.layout.fillMaxSize
29 | import androidx.compose.foundation.layout.padding
30 | import androidx.compose.foundation.layout.size
31 | import androidx.compose.foundation.shape.CircleShape
32 | import androidx.compose.material3.Icon
33 | import androidx.compose.material3.MaterialTheme
34 | import androidx.compose.material3.Surface
35 | import androidx.compose.material3.Text
36 | import androidx.compose.runtime.Composable
37 | import androidx.compose.runtime.LaunchedEffect
38 | import androidx.compose.runtime.getValue
39 | import androidx.compose.runtime.mutableStateOf
40 | import androidx.compose.runtime.remember
41 | import androidx.compose.runtime.setValue
42 | import androidx.compose.ui.Alignment
43 | import androidx.compose.ui.Modifier
44 | import androidx.compose.ui.layout.ContentScale
45 | import androidx.compose.ui.res.painterResource
46 | import androidx.compose.ui.text.AnnotatedString
47 | import androidx.compose.ui.text.font.FontWeight
48 | import androidx.compose.ui.text.fromHtml
49 | import androidx.compose.ui.text.style.TextAlign
50 | import androidx.compose.ui.unit.dp
51 | import kotlinx.coroutines.delay
52 |
53 | @Composable
54 | @OptIn(ExperimentalAnimationGraphicsApi::class)
55 | fun TutorialPage(
56 | @DrawableRes iconId: Int? = null,
57 | @DrawableRes previewId: Int,
58 | title: String,
59 | description: String,
60 | isVisible: Boolean = true,
61 | ) {
62 | val image = AnimatedImageVector.animatedVectorResource(previewId)
63 | var atEnd by remember { mutableStateOf(false) }
64 |
65 | LaunchedEffect(isVisible) {
66 | if (isVisible) {
67 | delay(600)
68 | atEnd = true
69 | }
70 | }
71 |
72 | Column(
73 | modifier = Modifier
74 | .fillMaxSize()
75 | .padding(horizontal = 16.dp),
76 | horizontalAlignment = Alignment.CenterHorizontally,
77 | verticalArrangement = Arrangement.Center
78 | ) {
79 | Surface(
80 | shape = CircleShape,
81 | color = MaterialTheme.colorScheme.surfaceContainerLowest,
82 | modifier = Modifier
83 | .aspectRatio(1f)
84 | .weight(weight = 1f, fill = false),
85 | ) {
86 | Image(
87 | painter = rememberAnimatedVectorPainter(image, atEnd),
88 | contentDescription = null,
89 | modifier = Modifier.fillMaxSize(),
90 | contentScale = ContentScale.Fit,
91 | )
92 | }
93 |
94 | Row(
95 | modifier = Modifier.padding(top = 16.dp),
96 | verticalAlignment = Alignment.CenterVertically,
97 | ) {
98 | iconId?.let {
99 | Icon(
100 | painter = painterResource(it),
101 | contentDescription = null,
102 | modifier = Modifier
103 | .size(42.dp)
104 | .padding(end = 8.dp),
105 | )
106 | }
107 | Text(
108 | text = title,
109 | fontWeight = FontWeight.Bold,
110 | style = MaterialTheme.typography.headlineLarge,
111 | )
112 | }
113 | Text(
114 | text = AnnotatedString.fromHtml(description),
115 | textAlign = TextAlign.Center,
116 | modifier = Modifier.padding(top = 8.dp)
117 | )
118 | }
119 | }
120 |
--------------------------------------------------------------------------------
/app/src/main/java/com/uravgcode/chooser/ui/theme/Color.kt:
--------------------------------------------------------------------------------
1 | package com.uravgcode.chooser.ui.theme
2 |
3 | import androidx.compose.ui.graphics.Color
4 |
5 | val primaryDark = Color(0xFFC7C6C7)
6 | val onPrimaryDark = Color(0xFF303031)
7 | val primaryContainerDark = Color(0xFF252627)
8 | val onPrimaryContainerDark = Color(0xFF8D8D8E)
9 |
10 | val secondaryDark = Color(0xFFC8C6C6)
11 | val onSecondaryDark = Color(0xFF303031)
12 | val secondaryContainerDark = Color(0xFF474747)
13 | val onSecondaryContainerDark = Color(0xFFB7B5B5)
14 |
15 | val tertiaryDark = Color(0xFFCBC5C7)
16 | val onTertiaryDark = Color(0xFF332F31)
17 | val tertiaryContainerDark = Color(0xFF282527)
18 | val onTertiaryContainerDark = Color(0xFF918C8E)
19 |
20 | val errorDark = Color(0xFFFFB4AB)
21 | val onErrorDark = Color(0xFF690005)
22 | val errorContainerDark = Color(0xFF93000A)
23 | val onErrorContainerDark = Color(0xFFFFDAD6)
24 |
25 | val backgroundDark = Color(0xFF141313)
26 | val onBackgroundDark = Color(0xFFE5E2E1)
27 |
28 | val surfaceDark = Color(0xFF141313)
29 | val onSurfaceDark = Color(0xFFE5E2E1)
30 | val surfaceVariantDark = Color(0xFF444749)
31 | val onSurfaceVariantDark = Color(0xFFC5C7C9)
32 |
33 | val outlineDark = Color(0xFF8F9193)
34 | val outlineVariantDark = Color(0xFF444749)
35 | val scrimDark = Color(0xFF000000)
36 |
37 | val inverseSurfaceDark = Color(0xFFE5E2E1)
38 | val inverseOnSurfaceDark = Color(0xFF313030)
39 | val inversePrimaryDark = Color(0xFF5E5E5F)
40 |
41 | val surfaceDimDark = Color(0xFF141313)
42 | val surfaceBrightDark = Color(0xFF3A3939)
43 | val surfaceContainerLowestDark = Color(0xFF0E0E0E)
44 | val surfaceContainerLowDark = Color(0xFF1C1B1B)
45 | val surfaceContainerDark = Color(0xFF201F1F)
46 | val surfaceContainerHighDark = Color(0xFF2A2A2A)
47 | val surfaceContainerHighestDark = Color(0xFF353434)
48 |
--------------------------------------------------------------------------------
/app/src/main/java/com/uravgcode/chooser/ui/theme/Theme.kt:
--------------------------------------------------------------------------------
1 | package com.uravgcode.chooser.ui.theme
2 |
3 | import androidx.compose.material3.MaterialTheme
4 | import androidx.compose.material3.darkColorScheme
5 | import androidx.compose.runtime.Composable
6 |
7 | private val darkScheme = darkColorScheme(
8 | primary = primaryDark,
9 | onPrimary = onPrimaryDark,
10 | primaryContainer = primaryContainerDark,
11 | onPrimaryContainer = onPrimaryContainerDark,
12 |
13 | secondary = secondaryDark,
14 | onSecondary = onSecondaryDark,
15 | secondaryContainer = secondaryContainerDark,
16 | onSecondaryContainer = onSecondaryContainerDark,
17 |
18 | tertiary = tertiaryDark,
19 | onTertiary = onTertiaryDark,
20 | tertiaryContainer = tertiaryContainerDark,
21 | onTertiaryContainer = onTertiaryContainerDark,
22 |
23 | error = errorDark,
24 | onError = onErrorDark,
25 | errorContainer = errorContainerDark,
26 | onErrorContainer = onErrorContainerDark,
27 |
28 | background = backgroundDark,
29 | onBackground = onBackgroundDark,
30 |
31 | surface = surfaceDark,
32 | onSurface = onSurfaceDark,
33 | surfaceVariant = surfaceVariantDark,
34 | onSurfaceVariant = onSurfaceVariantDark,
35 |
36 | outline = outlineDark,
37 | outlineVariant = outlineVariantDark,
38 | scrim = scrimDark,
39 |
40 | inverseSurface = inverseSurfaceDark,
41 | inverseOnSurface = inverseOnSurfaceDark,
42 | inversePrimary = inversePrimaryDark,
43 |
44 | surfaceDim = surfaceDimDark,
45 | surfaceBright = surfaceBrightDark,
46 | surfaceContainerLowest = surfaceContainerLowestDark,
47 | surfaceContainerLow = surfaceContainerLowDark,
48 | surfaceContainer = surfaceContainerDark,
49 | surfaceContainerHigh = surfaceContainerHighDark,
50 | surfaceContainerHighest = surfaceContainerHighestDark,
51 | )
52 |
53 | @Composable
54 | fun ChooserTheme(
55 | content: @Composable () -> Unit
56 | ) {
57 | MaterialTheme(
58 | colorScheme = darkScheme,
59 | typography = Typography,
60 | content = content
61 | )
62 | }
63 |
--------------------------------------------------------------------------------
/app/src/main/java/com/uravgcode/chooser/ui/theme/Type.kt:
--------------------------------------------------------------------------------
1 | package com.uravgcode.chooser.ui.theme
2 |
3 | import androidx.compose.material3.Typography
4 |
5 | val Typography = Typography()
6 |
--------------------------------------------------------------------------------
/app/src/main/res/animator/fade_in_full_1.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
10 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/animator/fade_in_full_2.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
11 |
12 |
--------------------------------------------------------------------------------
/app/src/main/res/animator/fade_in_full_3.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
11 |
12 |
--------------------------------------------------------------------------------
/app/src/main/res/animator/fade_in_full_4.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
11 |
12 |
--------------------------------------------------------------------------------
/app/src/main/res/animator/fade_in_growing_1.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
10 |
17 |
18 |
--------------------------------------------------------------------------------
/app/src/main/res/animator/fade_in_growing_2.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
11 |
19 |
20 |
--------------------------------------------------------------------------------
/app/src/main/res/animator/fade_in_growing_3.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
11 |
19 |
20 |
--------------------------------------------------------------------------------
/app/src/main/res/animator/fade_in_growing_4.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
11 |
19 |
20 |
--------------------------------------------------------------------------------
/app/src/main/res/animator/fade_in_partial_1.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
10 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/animator/fade_in_partial_2.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
11 |
12 |
--------------------------------------------------------------------------------
/app/src/main/res/animator/fade_in_partial_3.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
11 |
12 |
--------------------------------------------------------------------------------
/app/src/main/res/animator/fade_in_partial_4.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
11 |
12 |
--------------------------------------------------------------------------------
/app/src/main/res/animator/fade_in_shrinking.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
10 |
17 |
18 |
--------------------------------------------------------------------------------
/app/src/main/res/animator/fade_out_shrinking.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
10 |
17 |
18 |
--------------------------------------------------------------------------------
/app/src/main/res/animator/fill_color_white_to_blue.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/animator/fill_color_white_to_orange.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/animator/infinite_rotation.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
11 |
12 |
--------------------------------------------------------------------------------
/app/src/main/res/animator/stroke_color_black_to_white.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/animator/stroke_color_white_to_blue.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/animator/stroke_color_white_to_orange.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/button_preview.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
12 |
15 |
18 |
19 |
22 |
25 |
28 |
29 |
30 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/button_preview_animated.xml:
--------------------------------------------------------------------------------
1 |
3 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/chooser_preview.xml:
--------------------------------------------------------------------------------
1 |
6 |
13 |
16 |
20 |
27 |
34 |
35 |
41 |
44 |
48 |
55 |
62 |
63 |
70 |
73 |
77 |
84 |
91 |
92 |
99 |
102 |
106 |
113 |
120 |
121 |
122 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/chooser_preview_animated.xml:
--------------------------------------------------------------------------------
1 |
3 |
6 |
9 |
12 |
15 |
16 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/group_icon.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
12 |
15 |
18 |
21 |
24 |
25 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/group_preview.xml:
--------------------------------------------------------------------------------
1 |
6 |
12 |
16 |
21 |
29 |
37 |
38 |
43 |
47 |
52 |
60 |
68 |
69 |
75 |
79 |
84 |
92 |
100 |
101 |
107 |
111 |
116 |
124 |
132 |
133 |
134 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/group_preview_animated.xml:
--------------------------------------------------------------------------------
1 |
3 |
6 |
9 |
12 |
15 |
18 |
19 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_launcher_animated.xml:
--------------------------------------------------------------------------------
1 |
3 |
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_launcher_foreground.xml:
--------------------------------------------------------------------------------
1 |
6 |
10 |
13 |
19 |
26 |
33 |
34 |
35 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_launcher_monochrome.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
12 |
18 |
24 |
25 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/order_icon.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
12 |
15 |
16 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/order_preview.xml:
--------------------------------------------------------------------------------
1 |
6 |
12 |
15 |
19 |
26 |
33 |
34 |
37 |
42 |
46 |
47 |
52 |
55 |
59 |
66 |
73 |
74 |
77 |
82 |
86 |
87 |
93 |
96 |
100 |
107 |
114 |
115 |
118 |
123 |
127 |
128 |
134 |
137 |
141 |
148 |
155 |
156 |
159 |
164 |
168 |
169 |
170 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/order_preview_animated.xml:
--------------------------------------------------------------------------------
1 |
3 |
6 |
9 |
12 |
15 |
18 |
21 |
24 |
27 |
28 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/single_icon.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
12 |
13 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/single_preview.xml:
--------------------------------------------------------------------------------
1 |
6 |
12 |
15 |
16 |
23 |
26 |
30 |
37 |
44 |
45 |
51 |
54 |
58 |
65 |
72 |
73 |
80 |
83 |
87 |
94 |
101 |
102 |
109 |
112 |
116 |
123 |
130 |
131 |
132 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/single_preview_animated.xml:
--------------------------------------------------------------------------------
1 |
3 |
6 |
9 |
12 |
15 |
16 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-anydpi/ic_launcher.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/raw/finger_chosen.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/UrAvgCode/Chooser/0ba2cbac77c152260c3b909eed64c4c94fc73f38/app/src/main/res/raw/finger_chosen.mp3
--------------------------------------------------------------------------------
/app/src/main/res/raw/finger_down.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/UrAvgCode/Chooser/0ba2cbac77c152260c3b909eed64c4c94fc73f38/app/src/main/res/raw/finger_down.mp3
--------------------------------------------------------------------------------
/app/src/main/res/raw/finger_up.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/UrAvgCode/Chooser/0ba2cbac77c152260c3b909eed64c4c94fc73f38/app/src/main/res/raw/finger_up.mp3
--------------------------------------------------------------------------------
/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #000
4 | #474747
5 | #fff
6 | #2196f3
7 | #4caf50
8 | #ffeb3b
9 | #ce6d29
10 | #ce2949
11 |
12 |
--------------------------------------------------------------------------------
/app/src/main/res/values/ic_launcher_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #141414
4 |
--------------------------------------------------------------------------------
/app/src/main/res/values/themes.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
13 |
14 |
--------------------------------------------------------------------------------
/build.gradle.kts:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 | plugins {
3 | alias(libs.plugins.android.application) apply false
4 | alias(libs.plugins.kotlin.android) apply false
5 | alias(libs.plugins.kotlin.compose) apply false
6 | }
7 |
--------------------------------------------------------------------------------
/fastlane/metadata/android/de/changelogs/1.txt:
--------------------------------------------------------------------------------
1 | Erste Veröffentlichung
2 |
--------------------------------------------------------------------------------
/fastlane/metadata/android/de/changelogs/10.txt:
--------------------------------------------------------------------------------
1 | Verbesserungen
2 | - Unterstützung für Edge-to-Edge Display
3 |
4 | Entwicklung
5 | - SDK 35
6 | - Code Verbesserungen
7 | - Abhängigkeiten aktualisiert
8 |
--------------------------------------------------------------------------------
/fastlane/metadata/android/de/changelogs/11.txt:
--------------------------------------------------------------------------------
1 | Funktionen
2 | - Einstellungsmenü hinzugefügt, zugänglich durch langes Drücken der Modus-Taste:
3 | - Ton und Vibration ein-/ausschalten
4 | - Edge-to-Edge Display ein-/ausschalten
5 | - Kreisgröße und Lebensdauer ändern
6 |
7 | Verbesserungen
8 | - Monochromes Icon hinzugefügt
9 |
10 | Entwicklung
11 | - Umstellung auf Jetpack Compose
12 | - Abhängigkeiten aktualisiert
13 |
--------------------------------------------------------------------------------
/fastlane/metadata/android/de/changelogs/12.txt:
--------------------------------------------------------------------------------
1 | Funktionen
2 | - Neue Einstellungen:
3 | - Kreisgröße im Gruppen-Modus unabhängig änderbar
4 | - Einstellungsabschnitte mit Titeln hinzugefügt
5 |
6 | Verbesserungen
7 | - Schwarzer Radius skaliert jetzt mit der Kreisgröße
8 | - Schwebende Zahlen skalieren mit der Kreisgröße
9 |
10 | Entwicklung
11 | - Kotlin-Version aktualisiert
12 | - Abhängigkeiten aktualisiert
13 |
--------------------------------------------------------------------------------
/fastlane/metadata/android/de/changelogs/13.txt:
--------------------------------------------------------------------------------
1 | Funktionen
2 | - Einstellungsmenü hinzugefügt, zugänglich durch langes Drücken der Modus-Taste:
3 | - Ton und Vibration ein-/ausschalten
4 | - Edge-to-Edge Display ein-/ausschalten
5 | - Position der Buttons mit Abstand von oben anpassen
6 | - Kreisgröße und Lebensdauer ändern
7 | - Setze alle Einstellungen zurück
8 |
9 | Verbesserungen
10 | - Monochromes Icon hinzugefügt
11 |
12 | Entwicklung
13 | - Umstellung auf Jetpack Compose
14 | - Abhängigkeiten aktualisiert
15 |
--------------------------------------------------------------------------------
/fastlane/metadata/android/de/changelogs/14.txt:
--------------------------------------------------------------------------------
1 | Verbesserungen
2 | - verbesserte Einstellungsnamen für Button-Padding
3 | - Übergangsanimationen zwischen Bildschirmen hinzugefügt
4 | - Unterstützung für vorausschauende Zurück-Touch-Geste aktiviert
5 |
6 | Behobene Fehler
7 | - unbeabsichtigte Navigation bei Orientierungsänderung behoben
8 |
9 | Entwicklung
10 | - Umstellung auf Compose Navigation
11 | - Abhängigkeiten aktualisiert
12 |
--------------------------------------------------------------------------------
/fastlane/metadata/android/de/changelogs/15.txt:
--------------------------------------------------------------------------------
1 | Funktionen
2 | - Beim ersten Start der App öffnet sich ein Tutorial, das die wichtigsten Funktionen vorstellt
3 |
4 | Entwicklung
5 | - Einstellungen auf DataStore umgestellt
6 | - Abhängigkeiten aktualisiert
7 |
--------------------------------------------------------------------------------
/fastlane/metadata/android/de/changelogs/16.txt:
--------------------------------------------------------------------------------
1 | Funktionen
2 | - Auswahlzeit Einstellungen für verschiedene Modi hinzugefügt
3 | - Import/Export von Einstellungen
4 |
5 | Verbesserungen
6 | - Animierter Splash Screen hinzugefügt
7 |
8 | Entwicklung
9 | - Einstellungen-Migration entfernt
10 | - Abhängigkeiten aktualisiert
11 |
--------------------------------------------------------------------------------
/fastlane/metadata/android/de/changelogs/2.txt:
--------------------------------------------------------------------------------
1 | Behobene Fehler
2 | - Probleme mit der Bildschirmaktualisierungsrate
3 | - Textausrichtung der Tasten
4 | - Geschwindigkeit der Tastenanimation
5 | - Durchschnittlicher Farbwert von mehr als zwei Farben
6 |
7 | Entwicklung
8 | - sdk 34
9 | - material 1.10
10 | - application version 8.1.2
11 |
--------------------------------------------------------------------------------
/fastlane/metadata/android/de/changelogs/3.txt:
--------------------------------------------------------------------------------
1 | Entwicklung
2 | - Code Vereinfachungen
3 | - material 1.11
4 | - com.android.application 8.2.1
5 |
--------------------------------------------------------------------------------
/fastlane/metadata/android/de/changelogs/4.txt:
--------------------------------------------------------------------------------
1 | Verbesserungen
2 | - Neues Symbol für den Durchzählmodus
3 | - Geringerer App Speicherplatzverbrauch
4 |
5 | Entwicklung
6 | - Ressourcen verkleinern
7 | - material dependency entfernt
8 | - appcompat dependency entfernt
9 | - dependencies info entfernt
10 |
--------------------------------------------------------------------------------
/fastlane/metadata/android/de/changelogs/5.txt:
--------------------------------------------------------------------------------
1 | Funktionen
2 | - Einige Testsounds hinzugefügt
3 | - Die Sounds lassen sich durch langes Drücken der Modustaste ein und ausschalten
4 |
5 | (Die Sounds werden sich höchstwahrscheinlich bis zur fertigen nächsten Version noch ändern)
6 |
--------------------------------------------------------------------------------
/fastlane/metadata/android/de/changelogs/6.txt:
--------------------------------------------------------------------------------
1 | Verbesserungen
2 | - Kreise im Durchzählmodus bleiben auf dem Bildschirm
3 | - Kreise im Durchzählmodus zeigen ihre jeweilige Nummer
4 |
--------------------------------------------------------------------------------
/fastlane/metadata/android/de/changelogs/7.txt:
--------------------------------------------------------------------------------
1 | Verbesserungen
2 | - Die App startet im Modus, in dem man sie verlassen hat
3 | - Kreise im Durchzählmodus bleiben länger auf dem Bildschirm
4 | - Nummern sind leichter zu lesen
5 |
6 | Behobene Fehler
7 | - Parallele Soundwiedergabe
8 | - Den Bildschirm zu drehen, setzt die App nicht mehr zurück
9 |
--------------------------------------------------------------------------------
/fastlane/metadata/android/de/changelogs/8.txt:
--------------------------------------------------------------------------------
1 | Funktionen
2 | - Sounds wurden hinzugefügt
3 | - Die Sounds lassen sich durch langes Drücken der Modustaste ein und ausschalten
4 | - Überarbeitung des Durchzählmodus
5 | - Die App startet im Modus, in dem man sie verlassen hat
6 |
7 | Behobene Fehler
8 | - Den Bildschirm zu drehen, setzt die App nicht mehr zurück
9 |
--------------------------------------------------------------------------------
/fastlane/metadata/android/de/changelogs/9.txt:
--------------------------------------------------------------------------------
1 | Entwicklung
2 | - kleinere Code-Verbesserungen
3 | - aktualisierte Abhängigkeiten
4 |
--------------------------------------------------------------------------------
/fastlane/metadata/android/de/full_description.txt:
--------------------------------------------------------------------------------
1 | Chooser ist eine Android-App, die dabei hilft, eine zufällige Auswahl unter Freunden oder anderen Gruppen zu treffen.
2 | Egal ob zu entscheiden, wer an der Kasse zahlen soll, wer ein Spiel beginnen soll oder in welchen Teams man spielt.
3 |
4 | Jeder berührt einfach den Bildschirm, um die zufällig ausgewählten Personen zu bestimmen.
5 | Das macht die Entscheidungsfindung nicht nur fair, sondern auch unterhaltsam.
6 |
7 | Funktionen
8 |
9 | - Wähle eine zufällige Person aus
10 | - Wähle mehrere Personen aus
11 | - Teile Personen in Gruppen ein
12 | - Zähle durch eine Gruppe durch
13 |
--------------------------------------------------------------------------------
/fastlane/metadata/android/de/short_description.txt:
--------------------------------------------------------------------------------
1 | Wähle zufällige Finger auf dem Bildschirm aus
2 |
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/changelogs/1.txt:
--------------------------------------------------------------------------------
1 | initial release
2 |
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/changelogs/10.txt:
--------------------------------------------------------------------------------
1 | Improvements
2 | - enhanced display cutout handling
3 | - added support for edge-to-edge display without black bars
4 |
5 | Development
6 | - target SDK 35
7 | - minor code improvements
8 | - update dependencies
9 |
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/changelogs/11.txt:
--------------------------------------------------------------------------------
1 | Features
2 | - added settings menu accessible by long pressing the mode button:
3 | - enable/disable sound and vibrations
4 | - enable/disable edge-to-edge display
5 | - change circle size and lifetime
6 |
7 | Improvements
8 | - added a monochrome icon
9 |
10 | Development
11 | - switched to Jetpack Compose
12 | - updated dependencies
13 |
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/changelogs/12.txt:
--------------------------------------------------------------------------------
1 | Features
2 | - new settings:
3 | - change group circle lifetime independently
4 | - added section separators with titles
5 |
6 | Improvements
7 | - black radius now scales with circle size
8 | - floating numbers scale with circle size
9 |
10 | Development
11 | - updated kotlin version
12 | - updated dependencies
13 |
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/changelogs/13.txt:
--------------------------------------------------------------------------------
1 | Features
2 | - added settings menu accessible by long pressing the mode button:
3 | - enable/disable sound and vibrations
4 | - enable/disable edge-to-edge display
5 | - change button position with top padding
6 | - change circle size and lifetime
7 | - reset all settings
8 |
9 | Improvements
10 | - added a monochrome icon
11 |
12 | Development
13 | - switched to Jetpack Compose
14 | - updated dependencies
15 |
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/changelogs/14.txt:
--------------------------------------------------------------------------------
1 | Improvements
2 | - improved settings names for button padding
3 | - added transition animations between screens
4 | - enabled predictive back gesture support
5 |
6 | Fixed
7 | - fixed unintended navigation on orientation change
8 |
9 | Development
10 | - migrated to compose navigation
11 | - updated dependencies
12 |
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/changelogs/15.txt:
--------------------------------------------------------------------------------
1 | Features
2 | - added a tutorial that automatically launches on first app start to introduce core features
3 |
4 | Development
5 | - migrated settings to datastore
6 | - updated dependencies
7 |
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/changelogs/16.txt:
--------------------------------------------------------------------------------
1 | Features
2 | - added selection delay settings for different modes
3 | - import/export settings
4 |
5 | Improvements
6 | - added animated splash screen
7 |
8 | Development
9 | - removed settings migration
10 | - updated dependencies
11 |
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/changelogs/2.txt:
--------------------------------------------------------------------------------
1 | Fixed
2 | - screen refresh rate problems
3 | - button text alignment
4 | - button animation speed
5 | - average color of more than two colors
6 |
7 | Development
8 | - sdk 34
9 | - material 1.10
10 | - application version 8.1.2
11 |
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/changelogs/3.txt:
--------------------------------------------------------------------------------
1 | Development
2 | - code cleanup
3 | - material 1.11
4 | - com.android.application 8.2.1
5 |
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/changelogs/4.txt:
--------------------------------------------------------------------------------
1 | Improved
2 | - new order icon
3 | - smaller app size
4 |
5 | Development
6 | - shrink resources
7 | - removed material dependency
8 | - removed appcompat dependency
9 | - removed dependencies info
10 |
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/changelogs/5.txt:
--------------------------------------------------------------------------------
1 | Features
2 | - added some test sounds for proof of concept
3 | - turn sounds on and off by long pressing the mode button
4 |
5 | (the sounds will most likely change until full release)
6 |
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/changelogs/6.txt:
--------------------------------------------------------------------------------
1 | Improved
2 | - circles in order mode no longer disappear
3 | - circles in order mode display their respective number
4 |
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/changelogs/7.txt:
--------------------------------------------------------------------------------
1 | Improved
2 | - return to the app as you left it
3 | - circles in order mode stay on screen for longer
4 | - numbers are easier to read
5 |
6 | Fixed
7 | - parallel sound playback
8 | - turning the screen doesn't reset the app
9 |
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/changelogs/8.txt:
--------------------------------------------------------------------------------
1 | Features
2 | - added sounds
3 | - turn sounds on and off by long pressing the mode button
4 | - overhauled order mode
5 | - return to the app as you left it
6 |
7 | Fixed
8 | - turning the screen doesn't reset the app
9 |
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/changelogs/9.txt:
--------------------------------------------------------------------------------
1 | Development
2 | - minor code improvements
3 | - update dependencies
4 |
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/full_description.txt:
--------------------------------------------------------------------------------
1 | Chooser is an Android app designed to help you make random selections among friends or groups.
2 | Whether you're deciding who should pay at the checkout, who should start a game, or which teams to play in, Chooser has you covered.
3 |
4 | With Chooser, everyone simply touches the screen to select random fingers, ensuring fair and unbiased decisions every time.
5 | It adds an exciting twist to decision-making, making it not only fair but also entertaining.
6 |
7 | Features
8 |
9 | - Choose a random person from the group
10 | - Select multiple people at once
11 | - Divide people into customizable groups
12 | - Easily count through a group
13 |
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/images/featureGraphic.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/UrAvgCode/Chooser/0ba2cbac77c152260c3b909eed64c4c94fc73f38/fastlane/metadata/android/en-US/images/featureGraphic.png
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/images/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/UrAvgCode/Chooser/0ba2cbac77c152260c3b909eed64c4c94fc73f38/fastlane/metadata/android/en-US/images/icon.png
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/images/phoneScreenshots/1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/UrAvgCode/Chooser/0ba2cbac77c152260c3b909eed64c4c94fc73f38/fastlane/metadata/android/en-US/images/phoneScreenshots/1.png
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/images/phoneScreenshots/2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/UrAvgCode/Chooser/0ba2cbac77c152260c3b909eed64c4c94fc73f38/fastlane/metadata/android/en-US/images/phoneScreenshots/2.png
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/images/phoneScreenshots/3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/UrAvgCode/Chooser/0ba2cbac77c152260c3b909eed64c4c94fc73f38/fastlane/metadata/android/en-US/images/phoneScreenshots/3.png
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/images/phoneScreenshots/4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/UrAvgCode/Chooser/0ba2cbac77c152260c3b909eed64c4c94fc73f38/fastlane/metadata/android/en-US/images/phoneScreenshots/4.png
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/images/phoneScreenshots/5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/UrAvgCode/Chooser/0ba2cbac77c152260c3b909eed64c4c94fc73f38/fastlane/metadata/android/en-US/images/phoneScreenshots/5.png
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/short_description.txt:
--------------------------------------------------------------------------------
1 | Select random fingers on the screen
2 |
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/title.txt:
--------------------------------------------------------------------------------
1 | Chooser
2 |
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 | # IDE (e.g. Android Studio) users:
3 | # Gradle settings configured through the IDE *will override*
4 | # any settings specified in this file.
5 | # For more details on how to configure your build environment visit
6 | # http://www.gradle.org/docs/current/userguide/build_environment.html
7 | # Specifies the JVM arguments used for the daemon process.
8 | # The setting is particularly useful for tweaking memory settings.
9 | org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
10 | # When configured, Gradle will run in incubating parallel mode.
11 | # This option should only be used with decoupled projects. For more details, visit
12 | # https://developer.android.com/r/tools/gradle-multi-project-decoupled-projects
13 | # org.gradle.parallel=true
14 | # AndroidX package structure to make it clearer which packages are bundled with the
15 | # Android operating system, and which are packaged with your app's APK
16 | # https://developer.android.com/topic/libraries/support-library/androidx-rn
17 | android.useAndroidX=true
18 | # Kotlin code style for this project: "official" or "obsolete":
19 | kotlin.code.style=official
20 | # Enables namespacing of each library's R class so that its R class includes only the
21 | # resources declared in the library itself and none from the library's dependencies,
22 | # thereby reducing the size of the R class for that library
23 | android.nonTransitiveRClass=true
--------------------------------------------------------------------------------
/gradle/libs.versions.toml:
--------------------------------------------------------------------------------
1 | [versions]
2 | agp = "8.10.0"
3 | kotlin = "2.1.10"
4 | coreKtx = "1.16.0"
5 | lifecycleRuntimeKtx = "2.9.0"
6 |
7 | datastore = "1.1.6"
8 | kotlinSerialization = "1.7.3"
9 |
10 | activityCompose = "1.10.1"
11 | composeBom = "2025.05.00"
12 | navigationCompose = "2.9.0"
13 |
14 | splashscreen = "1.0.1"
15 |
16 |
17 | [libraries]
18 | androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" }
19 | androidx-lifecycle-runtime-ktx = { group = "androidx.lifecycle", name = "lifecycle-runtime-ktx", version.ref = "lifecycleRuntimeKtx" }
20 |
21 | androidx-datastore = { module = "androidx.datastore:datastore", version.ref = "datastore" }
22 | kotlinx-serialization-json = { group = "org.jetbrains.kotlinx", name = "kotlinx-serialization-json", version.ref = "kotlinSerialization" }
23 |
24 | androidx-activity-compose = { group = "androidx.activity", name = "activity-compose", version.ref = "activityCompose" }
25 | androidx-compose-bom = { group = "androidx.compose", name = "compose-bom", version.ref = "composeBom" }
26 |
27 | androidx-material3 = { group = "androidx.compose.material3", name = "material3" }
28 | androidx-material-icons-extended = { module = "androidx.compose.material:material-icons-extended" }
29 |
30 | androidx-ui = { group = "androidx.compose.ui", name = "ui" }
31 | androidx-ui-graphics = { group = "androidx.compose.ui", name = "ui-graphics" }
32 | androidx-ui-tooling = { group = "androidx.compose.ui", name = "ui-tooling" }
33 | androidx-ui-tooling-preview = { group = "androidx.compose.ui", name = "ui-tooling-preview" }
34 | androidx-ui-test-manifest = { group = "androidx.compose.ui", name = "ui-test-manifest" }
35 |
36 | androidx-animation-graphics = { module = "androidx.compose.animation:animation-graphics" }
37 |
38 | androidx-navigation-compose = { group = "androidx.navigation", name = "navigation-compose", version.ref = "navigationCompose" }
39 |
40 | androidx-core-splashscreen = { module = "androidx.core:core-splashscreen", version.ref = "splashscreen" }
41 |
42 |
43 | [plugins]
44 | android-application = { id = "com.android.application", version.ref = "agp" }
45 | kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }
46 | kotlin-compose = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "kotlin" }
47 | kotlin-serialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "kotlin" }
48 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/UrAvgCode/Chooser/0ba2cbac77c152260c3b909eed64c4c94fc73f38/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionBase=GRADLE_USER_HOME
2 | distributionPath=wrapper/dists
3 | distributionSha256Sum=61ad310d3c7d3e5da131b76bbf22b5a4c0786e9d892dae8c1658d4b484de3caa
4 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.14-bin.zip
5 | networkTimeout=10000
6 | validateDistributionUrl=true
7 | zipStoreBase=GRADLE_USER_HOME
8 | zipStorePath=wrapper/dists
9 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | #
4 | # Copyright © 2015-2021 the original authors.
5 | #
6 | # Licensed under the Apache License, Version 2.0 (the "License");
7 | # you may not use this file except in compliance with the License.
8 | # You may obtain a copy of the License at
9 | #
10 | # https://www.apache.org/licenses/LICENSE-2.0
11 | #
12 | # Unless required by applicable law or agreed to in writing, software
13 | # distributed under the License is distributed on an "AS IS" BASIS,
14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | # See the License for the specific language governing permissions and
16 | # limitations under the License.
17 | #
18 | # SPDX-License-Identifier: Apache-2.0
19 | #
20 |
21 | ##############################################################################
22 | #
23 | # Gradle start up script for POSIX generated by Gradle.
24 | #
25 | # Important for running:
26 | #
27 | # (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
28 | # noncompliant, but you have some other compliant shell such as ksh or
29 | # bash, then to run this script, type that shell name before the whole
30 | # command line, like:
31 | #
32 | # ksh Gradle
33 | #
34 | # Busybox and similar reduced shells will NOT work, because this script
35 | # requires all of these POSIX shell features:
36 | # * functions;
37 | # * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
38 | # «${var#prefix}», «${var%suffix}», and «$( cmd )»;
39 | # * compound commands having a testable exit status, especially «case»;
40 | # * various built-in commands including «command», «set», and «ulimit».
41 | #
42 | # Important for patching:
43 | #
44 | # (2) This script targets any POSIX shell, so it avoids extensions provided
45 | # by Bash, Ksh, etc; in particular arrays are avoided.
46 | #
47 | # The "traditional" practice of packing multiple parameters into a
48 | # space-separated string is a well documented source of bugs and security
49 | # problems, so this is (mostly) avoided, by progressively accumulating
50 | # options in "$@", and eventually passing that to Java.
51 | #
52 | # Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
53 | # and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
54 | # see the in-line comments for details.
55 | #
56 | # There are tweaks for specific operating systems such as AIX, CygWin,
57 | # Darwin, MinGW, and NonStop.
58 | #
59 | # (3) This script is generated from the Groovy template
60 | # https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
61 | # within the Gradle project.
62 | #
63 | # You can find Gradle at https://github.com/gradle/gradle/.
64 | #
65 | ##############################################################################
66 |
67 | # Attempt to set APP_HOME
68 |
69 | # Resolve links: $0 may be a link
70 | app_path=$0
71 |
72 | # Need this for daisy-chained symlinks.
73 | while
74 | APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
75 | [ -h "$app_path" ]
76 | do
77 | ls=$( ls -ld "$app_path" )
78 | link=${ls#*' -> '}
79 | case $link in #(
80 | /*) app_path=$link ;; #(
81 | *) app_path=$APP_HOME$link ;;
82 | esac
83 | done
84 |
85 | # This is normally unused
86 | # shellcheck disable=SC2034
87 | APP_BASE_NAME=${0##*/}
88 | # Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
89 | APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit
90 |
91 | # Use the maximum available, or set MAX_FD != -1 to use that value.
92 | MAX_FD=maximum
93 |
94 | warn () {
95 | echo "$*"
96 | } >&2
97 |
98 | die () {
99 | echo
100 | echo "$*"
101 | echo
102 | exit 1
103 | } >&2
104 |
105 | # OS specific support (must be 'true' or 'false').
106 | cygwin=false
107 | msys=false
108 | darwin=false
109 | nonstop=false
110 | case "$( uname )" in #(
111 | CYGWIN* ) cygwin=true ;; #(
112 | Darwin* ) darwin=true ;; #(
113 | MSYS* | MINGW* ) msys=true ;; #(
114 | NONSTOP* ) nonstop=true ;;
115 | esac
116 |
117 | CLASSPATH="\\\"\\\""
118 |
119 |
120 | # Determine the Java command to use to start the JVM.
121 | if [ -n "$JAVA_HOME" ] ; then
122 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
123 | # IBM's JDK on AIX uses strange locations for the executables
124 | JAVACMD=$JAVA_HOME/jre/sh/java
125 | else
126 | JAVACMD=$JAVA_HOME/bin/java
127 | fi
128 | if [ ! -x "$JAVACMD" ] ; then
129 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
130 |
131 | Please set the JAVA_HOME variable in your environment to match the
132 | location of your Java installation."
133 | fi
134 | else
135 | JAVACMD=java
136 | if ! command -v java >/dev/null 2>&1
137 | then
138 | die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
139 |
140 | Please set the JAVA_HOME variable in your environment to match the
141 | location of your Java installation."
142 | fi
143 | fi
144 |
145 | # Increase the maximum file descriptors if we can.
146 | if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
147 | case $MAX_FD in #(
148 | max*)
149 | # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
150 | # shellcheck disable=SC2039,SC3045
151 | MAX_FD=$( ulimit -H -n ) ||
152 | warn "Could not query maximum file descriptor limit"
153 | esac
154 | case $MAX_FD in #(
155 | '' | soft) :;; #(
156 | *)
157 | # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
158 | # shellcheck disable=SC2039,SC3045
159 | ulimit -n "$MAX_FD" ||
160 | warn "Could not set maximum file descriptor limit to $MAX_FD"
161 | esac
162 | fi
163 |
164 | # Collect all arguments for the java command, stacking in reverse order:
165 | # * args from the command line
166 | # * the main class name
167 | # * -classpath
168 | # * -D...appname settings
169 | # * --module-path (only if needed)
170 | # * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
171 |
172 | # For Cygwin or MSYS, switch paths to Windows format before running java
173 | if "$cygwin" || "$msys" ; then
174 | APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
175 | CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
176 |
177 | JAVACMD=$( cygpath --unix "$JAVACMD" )
178 |
179 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
180 | for arg do
181 | if
182 | case $arg in #(
183 | -*) false ;; # don't mess with options #(
184 | /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
185 | [ -e "$t" ] ;; #(
186 | *) false ;;
187 | esac
188 | then
189 | arg=$( cygpath --path --ignore --mixed "$arg" )
190 | fi
191 | # Roll the args list around exactly as many times as the number of
192 | # args, so each arg winds up back in the position where it started, but
193 | # possibly modified.
194 | #
195 | # NB: a `for` loop captures its iteration list before it begins, so
196 | # changing the positional parameters here affects neither the number of
197 | # iterations, nor the values presented in `arg`.
198 | shift # remove old arg
199 | set -- "$@" "$arg" # push replacement arg
200 | done
201 | fi
202 |
203 |
204 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
205 | DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
206 |
207 | # Collect all arguments for the java command:
208 | # * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
209 | # and any embedded shellness will be escaped.
210 | # * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
211 | # treated as '${Hostname}' itself on the command line.
212 |
213 | set -- \
214 | "-Dorg.gradle.appname=$APP_BASE_NAME" \
215 | -classpath "$CLASSPATH" \
216 | -jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \
217 | "$@"
218 |
219 | # Stop when "xargs" is not available.
220 | if ! command -v xargs >/dev/null 2>&1
221 | then
222 | die "xargs is not available"
223 | fi
224 |
225 | # Use "xargs" to parse quoted args.
226 | #
227 | # With -n1 it outputs one arg per line, with the quotes and backslashes removed.
228 | #
229 | # In Bash we could simply go:
230 | #
231 | # readarray ARGS < <( xargs -n1 <<<"$var" ) &&
232 | # set -- "${ARGS[@]}" "$@"
233 | #
234 | # but POSIX shell has neither arrays nor command substitution, so instead we
235 | # post-process each arg (as a line of input to sed) to backslash-escape any
236 | # character that might be a shell metacharacter, then use eval to reverse
237 | # that process (while maintaining the separation between arguments), and wrap
238 | # the whole thing up as a single "set" statement.
239 | #
240 | # This will of course break if any of these variables contains a newline or
241 | # an unmatched quote.
242 | #
243 |
244 | eval "set -- $(
245 | printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
246 | xargs -n1 |
247 | sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
248 | tr '\n' ' '
249 | )" '"$@"'
250 |
251 | exec "$JAVACMD" "$@"
252 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @rem
2 | @rem Copyright 2015 the original author or authors.
3 | @rem
4 | @rem Licensed under the Apache License, Version 2.0 (the "License");
5 | @rem you may not use this file except in compliance with the License.
6 | @rem You may obtain a copy of the License at
7 | @rem
8 | @rem https://www.apache.org/licenses/LICENSE-2.0
9 | @rem
10 | @rem Unless required by applicable law or agreed to in writing, software
11 | @rem distributed under the License is distributed on an "AS IS" BASIS,
12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | @rem See the License for the specific language governing permissions and
14 | @rem limitations under the License.
15 | @rem
16 | @rem SPDX-License-Identifier: Apache-2.0
17 | @rem
18 |
19 | @if "%DEBUG%"=="" @echo off
20 | @rem ##########################################################################
21 | @rem
22 | @rem Gradle startup script for Windows
23 | @rem
24 | @rem ##########################################################################
25 |
26 | @rem Set local scope for the variables with windows NT shell
27 | if "%OS%"=="Windows_NT" setlocal
28 |
29 | set DIRNAME=%~dp0
30 | if "%DIRNAME%"=="" set DIRNAME=.
31 | @rem This is normally unused
32 | set APP_BASE_NAME=%~n0
33 | set APP_HOME=%DIRNAME%
34 |
35 | @rem Resolve any "." and ".." in APP_HOME to make it shorter.
36 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
37 |
38 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
39 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
40 |
41 | @rem Find java.exe
42 | if defined JAVA_HOME goto findJavaFromJavaHome
43 |
44 | set JAVA_EXE=java.exe
45 | %JAVA_EXE% -version >NUL 2>&1
46 | if %ERRORLEVEL% equ 0 goto execute
47 |
48 | echo. 1>&2
49 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2
50 | echo. 1>&2
51 | echo Please set the JAVA_HOME variable in your environment to match the 1>&2
52 | echo location of your Java installation. 1>&2
53 |
54 | goto fail
55 |
56 | :findJavaFromJavaHome
57 | set JAVA_HOME=%JAVA_HOME:"=%
58 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
59 |
60 | if exist "%JAVA_EXE%" goto execute
61 |
62 | echo. 1>&2
63 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2
64 | echo. 1>&2
65 | echo Please set the JAVA_HOME variable in your environment to match the 1>&2
66 | echo location of your Java installation. 1>&2
67 |
68 | goto fail
69 |
70 | :execute
71 | @rem Setup the command line
72 |
73 | set CLASSPATH=
74 |
75 |
76 | @rem Execute Gradle
77 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %*
78 |
79 | :end
80 | @rem End local scope for the variables with windows NT shell
81 | if %ERRORLEVEL% equ 0 goto mainEnd
82 |
83 | :fail
84 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
85 | rem the _cmd.exe /c_ return code!
86 | set EXIT_CODE=%ERRORLEVEL%
87 | if %EXIT_CODE% equ 0 set EXIT_CODE=1
88 | if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
89 | exit /b %EXIT_CODE%
90 |
91 | :mainEnd
92 | if "%OS%"=="Windows_NT" endlocal
93 |
94 | :omega
95 |
--------------------------------------------------------------------------------
/readme/chooser-icon.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/readme/get-it-on-github.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/UrAvgCode/Chooser/0ba2cbac77c152260c3b909eed64c4c94fc73f38/readme/get-it-on-github.png
--------------------------------------------------------------------------------
/readme/group-mode.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/UrAvgCode/Chooser/0ba2cbac77c152260c3b909eed64c4c94fc73f38/readme/group-mode.gif
--------------------------------------------------------------------------------
/readme/order-mode.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/UrAvgCode/Chooser/0ba2cbac77c152260c3b909eed64c4c94fc73f38/readme/order-mode.gif
--------------------------------------------------------------------------------
/readme/single-mode.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/UrAvgCode/Chooser/0ba2cbac77c152260c3b909eed64c4c94fc73f38/readme/single-mode.gif
--------------------------------------------------------------------------------
/settings.gradle.kts:
--------------------------------------------------------------------------------
1 | pluginManagement {
2 | repositories {
3 | google {
4 | content {
5 | includeGroupByRegex("com\\.android.*")
6 | includeGroupByRegex("com\\.google.*")
7 | includeGroupByRegex("androidx.*")
8 | }
9 | }
10 | mavenCentral()
11 | gradlePluginPortal()
12 | }
13 | }
14 |
15 | @Suppress("UnstableApiUsage")
16 | dependencyResolutionManagement {
17 | repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
18 | repositories {
19 | google()
20 | mavenCentral()
21 | }
22 | }
23 |
24 | rootProject.name = "Chooser"
25 | include(":app")
26 |
--------------------------------------------------------------------------------