diff --git a/.idea/.name b/.idea/.name
deleted file mode 100644
index a60e598..0000000
--- a/.idea/.name
+++ /dev/null
@@ -1 +0,0 @@
-Audiofy
\ No newline at end of file
diff --git a/.idea/kotlinc.xml b/.idea/kotlinc.xml
index fdf8d99..f8467b4 100644
--- a/.idea/kotlinc.xml
+++ b/.idea/kotlinc.xml
@@ -1,6 +1,6 @@
-
+
\ No newline at end of file
diff --git a/app/build.gradle.kts b/app/build.gradle.kts
index 17eabad..431935d 100644
--- a/app/build.gradle.kts
+++ b/app/build.gradle.kts
@@ -9,6 +9,19 @@ plugins {
kotlin("kapt")
}
+/**
+ * The secrets that needs to be added to BuildConfig at runtime.
+ */
+val secrets = arrayOf(
+ "IAP_BUY_ME_COFFEE",
+ "IAP_NO_ADS",
+ "PLACEMENT_BANNER_1",
+ "PLACEMENT_BANNER_2",
+ "PLACEMENT_INTERSTITIAL",
+ "UNITY_APP_ID",
+ "PLAY_CONSOLE_APP_RSA_KEY",
+)
+
android {
compileSdk = 34
namespace = "com.prime.media"
@@ -16,14 +29,15 @@ android {
applicationId = "com.prime.player"
minSdk = 21
targetSdk = 34
- versionCode = 47
+ versionCode = 48
versionName = "2.3.0"
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
vectorDrawables { useSupportLibrary = true }
- // Add necessary const to BuildConfig
- // These filed will be provided in github
- // secrets when released else defualt value will be used
- secrets()
+ //Load secrets into BuildConfig
+ secrets.forEach { secret ->
+ val value = "\"" + (System.getenv(secret) ?: "no_value") + "\""
+ buildConfigField("String", secret, value)
+ }
}
buildTypes {
@@ -55,7 +69,7 @@ android {
freeCompilerArgs = listOf("-Xopt-in=kotlin.RequiresOptIn", "-Xcontext-receivers")
}
buildFeatures { compose = true }
- composeOptions { kotlinCompilerExtensionVersion = "1.5.1" }
+ composeOptions { kotlinCompilerExtensionVersion = "1.5.3" }
packaging { resources { excludes += "/META-INF/{AL2.0,LGPL2.1}" } }
}
@@ -74,11 +88,11 @@ dependencies {
implementation("androidx.compose.material:material-icons-extended:$compose_version")
// The Accompanist Libraries
implementation("io.coil-kt:coil-compose:2.4.0")
- implementation("com.google.accompanist:accompanist-permissions:0.31.5-beta")
+ implementation("com.google.accompanist:accompanist-permissions:0.32.0")
//Lottie
implementation("com.airbnb.android:lottie-compose:6.1.0")
// Preferences and other widgets
- val toolkit_version = "1.0.9-beta"
+ val toolkit_version = "1.1.1"
implementation("com.github.prime-zs.toolkit:preferences:$toolkit_version")
implementation("com.github.prime-zs.toolkit:core-ktx:$toolkit_version")
implementation("com.github.prime-zs.toolkit:material2:$toolkit_version")
@@ -89,7 +103,7 @@ dependencies {
implementation("com.google.firebase:firebase-analytics-ktx")
implementation("com.google.firebase:firebase-crashlytics-ktx")
// WindowSizeClasses
- implementation("androidx.compose.material3:material3-window-size-class:1.2.0-alpha05")
+ implementation("androidx.compose.material3:material3-window-size-class:1.1.1")
// Google Play InAppUpdate
val in_app_update_version = "2.1.0"
implementation("com.google.android.play:app-update:$in_app_update_version")
@@ -105,15 +119,15 @@ dependencies {
// Unity Ads
implementation("com.unity3d.ads:unity-ads:4.8.0")
// Compose navigation
- implementation("androidx.navigation:navigation-compose:2.7.0")
+ implementation("androidx.navigation:navigation-compose:2.7.1")
// Compose Downloadable fonts
implementation("androidx.compose.ui:ui-text-google-fonts:1.5.0")
// Hilt
- implementation("com.google.dagger:hilt-android:2.47")
- kapt("com.google.dagger:hilt-android-compiler:2.47")
+ implementation("com.google.dagger:hilt-android:2.48")
+ kapt("com.google.dagger:hilt-android-compiler:2.48")
implementation("androidx.hilt:hilt-navigation-compose:1.0.0")
// Room Database
- val room_version = "2.6.0-alpha03"
+ val room_version = "2.6.0-beta01"
implementation("androidx.room:room-runtime:$room_version")
kapt("androidx.room:room-compiler:$room_version")
implementation("androidx.room:room-ktx:$room_version")
@@ -129,30 +143,4 @@ dependencies {
implementation("androidx.media3:media3-exoplayer:$media3_version")
// For exposing and controlling media sessions
implementation("androidx.media3:media3-session:$media3_version")
-}
-
-/**
- * Init adn add git secrets to BuildConfig
- */
-fun ApplicationDefaultConfig.secrets() {
- var value = "\"" + (System.getenv("IAP_BUY_ME_COFFEE") ?: "empty") + "\""
- buildConfigField("String", "IAP_BUY_ME_COFFEE", value)
-
- value = "\"" + (System.getenv("IAP_NO_ADS") ?: "empty") + "\""
- buildConfigField("String", "IAP_NO_ADS", value)
-
- value = "\"" + (System.getenv("PLACEMENT_BANNER_1") ?: "empty") + "\""
- buildConfigField("String", "PLACEMENT_BANNER_1", value)
-
- value = "\"" + (System.getenv("PLACEMENT_BANNER_2") ?: "empty") + "\""
- buildConfigField("String", "PLACEMENT_BANNER_2", value)
-
- value = "\"" + (System.getenv("PLACEMENT_INTERSTITIAL") ?: "empty") + "\""
- buildConfigField("String", "PLACEMENT_INTERSTITIAL", value)
-
- value = "\"" + (System.getenv("UNITY_APP_ID") ?: "empty") + "\""
- buildConfigField("String", "UNITY_APP_ID", value)
-
- value = "\"" + (System.getenv("PLAY_CONSOLE_APP_RSA_KEY") ?: "empty") + "\""
- buildConfigField("String", "PLAY_CONSOLE_APP_RSA_KEY", value)
}
\ No newline at end of file
diff --git a/app/src/main/java/com/prime/media/Home.kt b/app/src/main/java/com/prime/media/Home.kt
index 00733d8..cd1c936 100644
--- a/app/src/main/java/com/prime/media/Home.kt
+++ b/app/src/main/java/com/prime/media/Home.kt
@@ -236,8 +236,8 @@ private fun Permission() {
}
Placeholder(
iconResId = R.raw.lt_permission,
- title = stringResource(R.string.storage_permission),
- message = stringResource(R.string.storage_permission_message),
+ title = stringResource(R.string.permission_screen_title),
+ message = stringResource(R.string.permission_screen_desc),
) {
OutlinedButton(
onClick = { permission.launchPermissionRequest() },
@@ -251,8 +251,8 @@ private fun Permission() {
}
}
-private val LightPrimaryColor = Color(0xFF17618D)
-private val LightPrimaryVariantColor = Color(0xFF14547B)
+private val LightPrimaryColor = Color(0xFF244285)
+private val LightPrimaryVariantColor = Color(0xFF305EA5)
private val LightSecondaryColor = Color(0xFF8B008B)
private val LightSecondaryVariantColor = Color(0xFF7B0084)
private val DarkPrimaryColor = Color(0xFFff8f00)
@@ -297,7 +297,7 @@ fun Material(
MaterialTheme(
colors = colors,
content = content,
- typography = Typography(Settings.LatoFontFamily)
+ typography = Typography(Settings.DefaultFontFamily)
)
}
diff --git a/app/src/main/java/com/prime/media/MainActivity.kt b/app/src/main/java/com/prime/media/MainActivity.kt
index fa9febd..38dafc6 100644
--- a/app/src/main/java/com/prime/media/MainActivity.kt
+++ b/app/src/main/java/com/prime/media/MainActivity.kt
@@ -1,7 +1,6 @@
package com.prime.media
import android.animation.ObjectAnimator
-import android.content.ActivityNotFoundException
import android.content.Intent
import android.content.pm.PackageManager
import android.media.audiofx.AudioEffect
@@ -10,7 +9,6 @@ import android.os.Build
import android.os.Bundle
import android.view.View
import android.view.animation.AnticipateInterpolator
-import android.widget.Toast
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.material.icons.Icons
@@ -241,7 +239,7 @@ class MainActivity : ComponentActivity(), SystemFacade {
manager.requestUpdateFlow().collect { result ->
when (result) {
AppUpdateResult.NotAvailable ->
- if (report) channel.show("The app is already updated to the latest version.")
+ if (report) channel.show(R.string.msg_no_new_update_available)
is AppUpdateResult.InProgress -> {
val state = result.installState
@@ -270,9 +268,8 @@ class MainActivity : ComponentActivity(), SystemFacade {
}
// else show the toast.
val res = channel.show(
- title = "Update",
- message = "An update has just been downloaded.",
- action = "RESTART",
+ message = R.string.msg_new_update_downloaded,
+ action = R.string.update,
duration = Duration.Indefinite,
accent = Color.MetroGreen
)
@@ -301,7 +298,7 @@ class MainActivity : ComponentActivity(), SystemFacade {
override fun shareApp() {
ShareCompat.IntentBuilder(this).setType("text/plain")
.setChooserTitle(getString(R.string.app_name))
- .setText("Let me recommend you this application ${Audiofy.GOOGLE_STORE}").startChooser()
+ .setText(getString(R.string.share_app_desc_s, Audiofy.GOOGLE_STORE)).startChooser()
}
override fun onNewIntent(intent: Intent?) {
@@ -317,8 +314,8 @@ class MainActivity : ComponentActivity(), SystemFacade {
) == PackageManager.PERMISSION_GRANTED
if (!isPermitted) {
show(
- R.string.storage_permission_message,
- R.string.storage_permission,
+ R.string.permission_screen_desc,
+ R.string.permission_screen_title,
icon = Icons.TwoTone.Memory
)
return
@@ -327,7 +324,7 @@ class MainActivity : ComponentActivity(), SystemFacade {
lifecycleScope.launch {
val audio = runCatching { findAudio(data) }.getOrNull()
if (audio == null) {
- show(R.string.error_msg, R.string.error)
+ show(R.string.msg_unknown_error, R.string.error)
return@launch
}
remote.set(listOf(audio.toMediaItem))
@@ -338,7 +335,7 @@ class MainActivity : ComponentActivity(), SystemFacade {
override fun launchEqualizer(id: Int) {
lifecycleScope.launch {
if (id == AudioEffect.ERROR_BAD_VALUE)
- return@launch show(R.string.error_msg, R.string.error)
+ return@launch show(R.string.msg_unknown_error, R.string.error)
val result = kotlin.runCatching {
startActivity(
Intent(AudioEffect.ACTION_DISPLAY_AUDIO_EFFECT_CONTROL_PANEL).apply {
@@ -351,7 +348,7 @@ class MainActivity : ComponentActivity(), SystemFacade {
if (!result.isFailure)
return@launch
val res = channel.show(
- message = R.string.equalizer_3rd_party_not_found_msg,
+ message = R.string.msg_3rd_party_equalizer_not_found,
action = R.string.launch,
accent = Color.OrientRed,
duration = Duration.Short
diff --git a/app/src/main/java/com/prime/media/console/Console.kt b/app/src/main/java/com/prime/media/console/Console.kt
index 7a018db..bc71674 100644
--- a/app/src/main/java/com/prime/media/console/Console.kt
+++ b/app/src/main/java/com/prime/media/console/Console.kt
@@ -83,15 +83,17 @@ import androidx.media3.common.Player
import com.prime.media.Material
import com.prime.media.R
import com.prime.media.caption2
+import com.prime.media.core.Anim
import com.prime.media.core.ContentElevation
import com.prime.media.core.ContentPadding
-import com.prime.media.core.compose.AVDIconButton
+import com.prime.media.core.LongDurationMills
+import com.prime.media.core.MediumDurationMills
+import com.prime.media.core.compose.AnimatedIconButton
import com.prime.media.core.compose.Image
import com.prime.media.core.compose.LocalSystemFacade
import com.prime.media.core.compose.LottieAnimButton
import com.prime.media.core.compose.LottieAnimation
import com.prime.media.core.compose.marque
-import com.prime.media.core.compose.rememberAnimatedVectorResource
import com.prime.media.core.compose.shape.CompactDisk
import com.prime.media.core.util.DateUtils
import com.prime.media.darkShadowColor
@@ -152,8 +154,9 @@ private fun PlayButton(
id = R.raw.lt_play_pause,
atEnd = !isPlaying,
scale = 1.5f,
- progressRange = 0.0f..0.5f,
- duration = 1200
+ progressRange = 0.0f..0.29f,
+ duration = Anim.MediumDurationMills,
+ easing = LinearEasing
)
}
}
@@ -295,7 +298,7 @@ private fun Vertical(
// Signature
Text(
text = stringResource(id = R.string.app_name),
- fontFamily = FontFamily.Cursive,
+ fontFamily = Settings.DancingScriptFontFamily,
fontWeight = FontWeight.Bold,
fontSize = 70.sp,
modifier = Modifier
@@ -491,7 +494,7 @@ private fun Vertical(
)
val mode = state.repeatMode
- AVDIconButton(
+ AnimatedIconButton(
id = R.drawable.avd_repeat_more_one_all,
onClick = { state.cycleRepeatMode();facade.launchReviewFlow(); },
atEnd = mode == Player.REPEAT_MODE_ALL,
diff --git a/app/src/main/java/com/prime/media/core/compose/Delegates.kt b/app/src/main/java/com/prime/media/core/compose/Delegates.kt
index 4c8f113..b80f3b0 100644
--- a/app/src/main/java/com/prime/media/core/compose/Delegates.kt
+++ b/app/src/main/java/com/prime/media/core/compose/Delegates.kt
@@ -10,6 +10,8 @@ import androidx.compose.animation.EnterTransition
import androidx.compose.animation.ExitTransition
import androidx.compose.animation.ExperimentalAnimationApi
import androidx.compose.animation.core.AnimationConstants
+import androidx.compose.animation.core.Easing
+import androidx.compose.animation.core.FastOutSlowInEasing
import androidx.compose.animation.core.MutableTransitionState
import androidx.compose.animation.core.animateFloatAsState
import androidx.compose.animation.core.tween
@@ -149,14 +151,15 @@ inline fun LottieAnimation(
atEnd: Boolean = false,
scale: Float = 1f,
progressRange: ClosedFloatingPointRange = 0f..1f,
- duration: Int = -1
+ duration: Int = -1,
+ easing: Easing = FastOutSlowInEasing
) {
val composition by rememberLottieComposition(spec = LottieCompositionSpec.RawRes(id))
val duration2 = composition?.duration?.roundToLong() ?: AnimationConstants.LongDurationMills
val progress by animateFloatAsState(
targetValue = if (atEnd) progressRange.start else progressRange.endInclusive,
label = "Lottie $id",
- animationSpec = tween(if (duration == -1) duration2.toInt() else duration)
+ animationSpec = tween(if (duration == -1) duration2.toInt() else duration, easing = easing)
)
LottieAnimation(
composition = composition,
@@ -285,7 +288,7 @@ inline fun LottieAnimButton(
*/
@OptIn(ExperimentalAnimationGraphicsApi::class)
@Composable
-inline fun AVDIconButton(
+inline fun AnimatedIconButton(
@DrawableRes id: Int,
noinline onClick: () -> Unit,
modifier: Modifier = Modifier,
diff --git a/app/src/main/java/com/prime/media/core/compose/Snackbar.kt b/app/src/main/java/com/prime/media/core/compose/Snackbar.kt
index 4c7286a..a3d374d 100644
--- a/app/src/main/java/com/prime/media/core/compose/Snackbar.kt
+++ b/app/src/main/java/com/prime/media/core/compose/Snackbar.kt
@@ -411,9 +411,9 @@ private fun Snackbar2(
text = {
Label(
text = data.message.value,
- color = LocalContentColor.current.copy(ContentAlpha.medium),
+ color = LocalContentColor.current,
style = MaterialTheme.typography.body2,
- maxLines = 4,
+ maxLines = 5,
)
},
overlineText = composableOrNull(data.title != null) {
diff --git a/app/src/main/java/com/prime/media/core/compose/core-ktx.kt b/app/src/main/java/com/prime/media/core/compose/core-ktx.kt
index 42376db..cc3e996 100644
--- a/app/src/main/java/com/prime/media/core/compose/core-ktx.kt
+++ b/app/src/main/java/com/prime/media/core/compose/core-ktx.kt
@@ -25,7 +25,6 @@ import androidx.compose.ui.unit.dp
import androidx.navigation.NavHostController
import androidx.navigation.compose.currentBackStackEntryAsState
import com.primex.core.Text
-import com.primex.core.resolve
private const val TAG = "ComposeUtil"
@@ -76,11 +75,6 @@ val LocalWindowSizeClass = staticCompositionLocalOf {
val NavHostController.current
@Composable inline get() = currentBackStackEntryAsState().value?.destination?.route
-inline fun Resources.stringResource(res: Text) = resolve(res)
-
-@JvmName("stringResource1")
-inline fun Resources.stringResource(res: Text?) = resolve(res)
-
/**
* @return [content] if [condition] is true else null
*/
diff --git a/app/src/main/java/com/prime/media/core/playback/Playback.kt b/app/src/main/java/com/prime/media/core/playback/Playback.kt
index 4ea9e22..0e237b4 100644
--- a/app/src/main/java/com/prime/media/core/playback/Playback.kt
+++ b/app/src/main/java/com/prime/media/core/playback/Playback.kt
@@ -336,7 +336,7 @@ class Playback : MediaLibraryService(), Callback, Player.Listener {
override fun onPlayerError(error: PlaybackException) {
// make a simple toast
- Toast.makeText(this, getString(R.string.unplayable_file), Toast.LENGTH_SHORT).show()
+ Toast.makeText(this, getString(R.string.msg_unplayable_file), Toast.LENGTH_SHORT).show()
//player.seekToNextMediaItem()
}
}
\ No newline at end of file
diff --git a/app/src/main/java/com/prime/media/directory/Action.kt b/app/src/main/java/com/prime/media/directory/Action.kt
index 9f6a80f..a373864 100644
--- a/app/src/main/java/com/prime/media/directory/Action.kt
+++ b/app/src/main/java/com/prime/media/directory/Action.kt
@@ -1,9 +1,11 @@
package com.prime.media.directory
+import androidx.annotation.StringRes
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.outlined.*
import androidx.compose.runtime.Stable
import androidx.compose.ui.graphics.vector.ImageVector
+import com.prime.media.R
import com.primex.core.Text
/**
@@ -25,21 +27,23 @@ sealed class Action(val id: String, val title: Text, val icon: ImageVector) {
*/
constructor(id: String, title: String, icon: ImageVector) : this(id, Text(title), icon)
- object Play : Action("action_play", "Play", Icons.Outlined.PlayArrow)
- object Shuffle : Action("action_shuffle", "Shuffle", Icons.Outlined.Shuffle)
- object Share : Action("action_share", "Share", Icons.Outlined.Share)
- object Delete : Action("action_delete", "Delete", Icons.Outlined.Delete)
+ constructor(id: String, @StringRes title: Int, icon: ImageVector):this(id, Text(title), icon)
+
+ object Play : Action("action_play", R.string.play, Icons.Outlined.PlayArrow)
+ object Shuffle : Action("action_shuffle", R.string.shuffle, Icons.Outlined.Shuffle)
+ object Share : Action("action_share", R.string.share, Icons.Outlined.Share)
+ object Delete : Action("action_delete", R.string.delete, Icons.Outlined.Delete)
object PlaylistAdd :
- Action("action_add_to_playlist", "Add to Playlist", Icons.Outlined.PlaylistAdd)
+ Action("action_add_to_playlist", R.string.add_to_playlist, Icons.Outlined.PlaylistAdd)
- object Make : Action("action_create", "Create", Icons.Outlined.AddCircle)
- object Edit : Action("action_edit", "Edit", Icons.Outlined.Edit)
- object GoToArtist : Action("action_go_to_artist", "Go to Artist", Icons.Outlined.Person)
- object GoToAlbum : Action("action_go_to_album", "Go to Album", Icons.Outlined.Album)
- object Properties : Action("action_properties", "Properties", Icons.Outlined.Info)
- object SelectAll : Action("action_select_all", "Select All", Icons.Outlined.SelectAll)
- object AddToQueue : Action("action_add_to_queue", "Add to Queue", Icons.Outlined.AddToQueue)
- object PlayNext : Action("action_play_next", "Play Next", Icons.Outlined.QueuePlayNext)
+ object Make : Action("action_create", R.string.create, Icons.Outlined.AddCircle)
+ object Edit : Action("action_edit", R.string.edit, Icons.Outlined.Edit)
+ object GoToArtist : Action("action_go_to_artist", R.string.go_to_artist, Icons.Outlined.Person)
+ object GoToAlbum : Action("action_go_to_album", R.string.go_to_album, Icons.Outlined.Album)
+ object Properties : Action("action_properties", R.string.properties, Icons.Outlined.Info)
+ object SelectAll : Action("action_select_all", R.string.select_all, Icons.Outlined.SelectAll)
+ object AddToQueue : Action("action_add_to_queue", R.string.add_to_queue, Icons.Outlined.AddToQueue)
+ object PlayNext : Action("action_play_next", R.string.play_next, Icons.Outlined.QueuePlayNext)
/**
* Check if this `Action` instance is equal to another object.
@@ -84,20 +88,20 @@ sealed class Action(val id: String, val title: Text, val icon: ImageVector) {
@Stable
sealed class GroupBy(id: String, title: Text, icon: ImageVector) : Action(id, title, icon) {
private constructor(id: String, title: String, icon: ImageVector) : this(id, Text(title), icon)
-
+ private constructor(id: String, @StringRes title: Int, icon: ImageVector):this(id, Text(title), icon)
/**
* GroupBy the title/Name of the item.
*/
- object None : GroupBy(ORDER_BY_NONE, "None", Icons.Outlined.FilterNone)
- object Name : GroupBy(ORDER_BY_NAME, "Name", Icons.Outlined.Title)
+ object None : GroupBy(ORDER_BY_NONE, R.string.none, Icons.Outlined.FilterNone)
+ object Name : GroupBy(ORDER_BY_NAME, R.string.name, Icons.Outlined.Title)
object DateModified :
- GroupBy(ORDER_BY_DATE_MODIFIED, "Date Modified", Icons.Outlined.AccessTime)
+ GroupBy(ORDER_BY_DATE_MODIFIED, R.string.date_modified, Icons.Outlined.AccessTime)
- object DateAdded : GroupBy(ORDER_BY_DATE_ADDED, "Date Added", Icons.Outlined.CalendarMonth)
- object Artist : GroupBy(ORDER_BY_ARTIST, "Artist", Icons.Outlined.Person)
- object Album : GroupBy(ORDER_BY_ALBUM, "Album", Icons.Outlined.Album)
- object Folder : GroupBy(ORDER_BY_FOLDER, "Folder", Icons.Outlined.Folder)
- object Length : GroupBy(ORDER_BY_LENGTH, "Length", Icons.Outlined.AvTimer)
+ object DateAdded : GroupBy(ORDER_BY_DATE_ADDED, R.string.date_added, Icons.Outlined.CalendarMonth)
+ object Artist : GroupBy(ORDER_BY_ARTIST, R.string.artist, Icons.Outlined.Person)
+ object Album : GroupBy(ORDER_BY_ALBUM, R.string.album, Icons.Outlined.Album)
+ object Folder : GroupBy(ORDER_BY_FOLDER, R.string.folder, Icons.Outlined.Folder)
+ object Length : GroupBy(ORDER_BY_LENGTH, R.string.length, Icons.Outlined.AvTimer)
companion object {
private const val ORDER_BY_NONE = "order_by_none"
@@ -145,9 +149,10 @@ sealed class GroupBy(id: String, title: Text, icon: ImageVector) : Action(id, ti
@Stable
sealed class ViewType(id: String, title: Text, icon: ImageVector) : Action(id, title, icon) {
private constructor(id: String, title: String, icon: ImageVector) : this(id, Text(title), icon)
+ private constructor(id: String, @StringRes title: Int, icon: ImageVector):this(id, Text(title), icon)
- object List : ViewType(VIEW_TYPE_LIST, "List", Icons.Outlined.List)
- object Grid : ViewType(VIEW_TYPE_GRID, "Grid", Icons.Outlined.GridView)
+ object List : ViewType(VIEW_TYPE_LIST, R.string.list, Icons.Outlined.List)
+ object Grid : ViewType(VIEW_TYPE_GRID, R.string.grid, Icons.Outlined.GridView)
companion object {
val VIEW_TYPE_LIST = "view_type_list"
diff --git a/app/src/main/java/com/prime/media/directory/playlists/Members.kt b/app/src/main/java/com/prime/media/directory/playlists/Members.kt
index 52f70a3..e956d44 100644
--- a/app/src/main/java/com/prime/media/directory/playlists/Members.kt
+++ b/app/src/main/java/com/prime/media/directory/playlists/Members.kt
@@ -33,7 +33,6 @@ import com.prime.media.core.util.addDistinct
import com.prime.media.directory.*
import com.prime.media.directory.dialogs.Playlists
import com.prime.media.impl.Repository
-import com.prime.media.core.db.toMediaItem
import com.prime.media.core.util.toMediaItem
import com.primex.core.*
import com.primex.material2.*
@@ -237,7 +236,7 @@ class MembersViewModel @Inject constructor(
clear()
// show warning
show(
- R.string.warning_queue_add_experimental,
+ R.string.msg_queue_add_experimental_warning,
R.string.warning,
ResourcesCompat.ID_NULL,
Icons.Outlined.Warning,
@@ -254,8 +253,8 @@ class MembersViewModel @Inject constructor(
return@launch
val count = remote.add(*audios.toTypedArray(), index = index)
show(
- buildPluralResource(id = R.plurals.queue_update_msg, count, count, audios.size),
- buildTextResource(if (count == 0) R.string.error_status_uncertain else R.string.success),
+ buildPluralResource(id = R.plurals.msg_queue_updated_dd, count, count, audios.size),
+ buildTextResource(if (count == 0) R.string.msg_error_status_uncertain else R.string.success),
null,
Icons.Outlined.Queue,
if (count == 0) Color.RedViolet else Color.MetroGreen
diff --git a/app/src/main/java/com/prime/media/directory/store/Albums.kt b/app/src/main/java/com/prime/media/directory/store/Albums.kt
index ff25c01..3f3a96b 100644
--- a/app/src/main/java/com/prime/media/directory/store/Albums.kt
+++ b/app/src/main/java/com/prime/media/directory/store/Albums.kt
@@ -1,3 +1,5 @@
+@file:OptIn(ExperimentalTextApi::class)
+
package com.prime.media.directory.store
import android.provider.MediaStore
@@ -13,6 +15,7 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.res.painterResource
+import androidx.compose.ui.text.ExperimentalTextApi
import androidx.compose.ui.unit.dp
import androidx.lifecycle.SavedStateHandle
import androidx.lifecycle.viewModelScope
@@ -30,6 +33,7 @@ import com.prime.media.directory.*
import com.prime.media.small2
import com.primex.core.Rose
import com.primex.core.Text
+import com.primex.core.textResource
import com.primex.material2.Label
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.flow.*
@@ -67,7 +71,7 @@ class AlbumsViewModel @Inject constructor(
init {
// emit the name to meta
//TODO: Add other fields in future versions.
- meta = MetaData(Text("Albums"))
+ meta = MetaData(Text(R.string.albums))
}
override fun toggleViewType() {
@@ -103,8 +107,7 @@ class AlbumsViewModel @Inject constructor(
.catch {
// any exception.
toaster.show(
- "Some unknown error occured!.",
- "Error",
+ R.string.msg_unknown_error,
leading = Icons.Outlined.Error,
accent = Color.Rose,
duration = Channel.Duration.Indefinite
@@ -159,7 +162,7 @@ fun Album(
// Subtitle
Label(
- text = "Year: ${value.firstYear}",
+ text = textResource(R.string.albums_scr_year_d, value.firstYear),
style = Material.typography.caption2
)
}
diff --git a/app/src/main/java/com/prime/media/directory/store/Audios.kt b/app/src/main/java/com/prime/media/directory/store/Audios.kt
index 40bae15..ca07e46 100644
--- a/app/src/main/java/com/prime/media/directory/store/Audios.kt
+++ b/app/src/main/java/com/prime/media/directory/store/Audios.kt
@@ -13,11 +13,9 @@ import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.*
import androidx.compose.material.icons.Icons
-import androidx.compose.material.icons.filled.Favorite
import androidx.compose.material.icons.outlined.*
import androidx.compose.runtime.*
import androidx.compose.runtime.snapshots.SnapshotStateList
-import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.draw.scale
@@ -248,10 +246,10 @@ class AudiosViewModel @Inject constructor(
GroupBy.None -> mapOf(Text("") to list)
GroupBy.Length -> list.groupBy { audio ->
when {
- audio.duration < TimeUnit.MINUTES.toMillis(2) -> Text(R.string.list_title_less_then_2_mins)
- audio.duration < TimeUnit.MINUTES.toMillis(5) -> Text(R.string.list_title_less_than_5_mins)
- audio.duration < TimeUnit.MINUTES.toMillis(10) -> Text(R.string.list_title_less_than_10_mins)
- else -> Text(R.string.list_title_greater_than_10_mins)
+ audio.duration < TimeUnit.MINUTES.toMillis(2) -> Text(R.string.audios_scr_less_then_2_mins)
+ audio.duration < TimeUnit.MINUTES.toMillis(5) -> Text(R.string.audios_scr_less_than_5_mins)
+ audio.duration < TimeUnit.MINUTES.toMillis(10) -> Text(R.string.audios_scr_less_than_10_mins)
+ else -> Text(R.string.audios_scr_greater_than_10_mins)
}
}
@@ -458,7 +456,7 @@ class AudiosViewModel @Inject constructor(
clear()
// show warning
show(
- R.string.warning_queue_add_experimental,
+ R.string.msg_queue_add_experimental_warning,
R.string.warning,
ResourcesCompat.ID_NULL,
Icons.Outlined.Warning,
@@ -475,8 +473,8 @@ class AudiosViewModel @Inject constructor(
return@launch
val count = remote.add(*audios.toTypedArray(), index = index)
show(
- buildPluralResource(id = R.plurals.queue_update_msg, count, count, audios.size),
- buildTextResource(if (count == 0) R.string.error_status_uncertain else R.string.success),
+ buildPluralResource(id = R.plurals.msg_queue_updated_dd, count, count, audios.size),
+ buildTextResource(if (count == 0) R.string.msg_error_status_uncertain else R.string.success),
null,
Icons.Outlined.Queue,
if (count == 0) Color.RedViolet else Color.MetroGreen
@@ -504,8 +502,8 @@ class AudiosViewModel @Inject constructor(
clear()
val isTrashEnabled = preferences.value(Settings.TRASH_CAN_ENABLED)
val res = show(
- buildTextResource(if (isTrashEnabled) R.string.trash_files_warning_msg else R.string.delete_files_warning_msg, list.size),
- buildTextResource(R.string.alert),
+ buildTextResource(if (isTrashEnabled) R.string.msg_trash_files_warning_d else R.string.msg_delete_files_warning_d, list.size),
+ null,
buildTextResource(if (isTrashEnabled) R.string.trash else R.string.delete),
Icons.Outlined.WarningAmber,
accent = Color.Rose,
@@ -528,28 +526,28 @@ class AudiosViewModel @Inject constructor(
// show appropriate message
when (result) {
-2 -> show(
- R.string.delete_dialog_show_msg,
+ R.string.msg_showing_delete_dialog,
R.string.confirm,
leading = Icons.Outlined.DeleteForever,
accent = Color.Rose,
)
-3 -> show(
- R.string.deleting_process_cancelled,
+ R.string.msg_deleting_process_cancelled,
R.string.cancelled,
leading = Icons.Outlined.Cancel,
)
// handle general case
-1 -> show(
- R.string.delete_audio_error,
+ R.string.msg_delete_unknown_error,
R.string.error,
leading = Icons.Outlined.Error,
accent = Color.Rose
)
else -> show(
- buildTextResource(id = R.string.delete_success_msg, result, uris.size),
- buildTextResource(R.string.success),
+ buildTextResource(id = R.string.msg_delete_success_ss, result, uris.size),
+ null,
null,
Icons.Outlined.Delete,
Color.MetroGreen
diff --git a/app/src/main/java/com/prime/media/directory/store/Folders.kt b/app/src/main/java/com/prime/media/directory/store/Folders.kt
index 1d63acc..ebe6119 100644
--- a/app/src/main/java/com/prime/media/directory/store/Folders.kt
+++ b/app/src/main/java/com/prime/media/directory/store/Folders.kt
@@ -2,7 +2,6 @@ package com.prime.media.directory.store
import android.provider.MediaStore
import androidx.compose.foundation.ExperimentalFoundationApi
-import androidx.compose.foundation.clickable
import androidx.compose.foundation.combinedClickable
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.grid.GridCells
@@ -115,7 +114,7 @@ class FoldersViewModel @Inject constructor(
val list = preferences.value(Settings.BLACKLISTED_FILES)
val name = PathUtils.name(path)
val response = show(
- Text(R.string.block_folder_warning_msg, name),
+ Text(R.string.msg_block_folder_warning_s, name),
Text(id = R.string.warning),
Text(id = R.string.add),
Icons.Outlined.Block,
@@ -127,14 +126,14 @@ class FoldersViewModel @Inject constructor(
val result = preferences.block(path)
if (result > 0)
show(
- Text(R.string.block_success_msg, name),
- Text(R.string.blacklist),
+ Text(R.string.msg_block_success_s, name),
+ Text(R.string.pref_blacklist),
leading = Icons.Outlined.Block,
accent = Color.Rose,
duration = Channel.Duration.Short,
)
else
- show(R.string.error_msg, R.string.error)
+ show(R.string.msg_unknown_error, R.string.error)
}
}
}
diff --git a/app/src/main/java/com/prime/media/impl/ConsoleViewModel.kt b/app/src/main/java/com/prime/media/impl/ConsoleViewModel.kt
index c2ec619..2c8244b 100644
--- a/app/src/main/java/com/prime/media/impl/ConsoleViewModel.kt
+++ b/app/src/main/java/com/prime/media/impl/ConsoleViewModel.kt
@@ -23,10 +23,8 @@ import com.prime.media.core.db.Playlist
import com.prime.media.core.playback.Playback
import com.prime.media.core.playback.Remote
import com.prime.media.core.util.MainHandler
-import com.primex.core.Amber
-import com.primex.core.Text
+import com.primex.core.OrientRed
import dagger.hilt.android.lifecycle.HiltViewModel
-import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.onStart
import kotlinx.coroutines.launch
@@ -91,7 +89,7 @@ class ConsoleViewModel @Inject constructor(
override fun remove(context: Context, key: Uri) {
viewModelScope.launch {
val removed = remote.remove(key)
- val msg = if (removed) R.string.track_remove_msg else R.string.track_remove_error_msg
+ val msg = if (removed) R.string.msg_track_will_be_removed else R.string.msg_track_remove_error
Toast.makeText(context, msg, Toast.LENGTH_SHORT).show()
}
}
@@ -104,8 +102,7 @@ class ConsoleViewModel @Inject constructor(
override fun clear(context: Context) {
viewModelScope.launch {
- val msg = "The playing queue will be cleared shortly."
- Toast.makeText(context, msg, Toast.LENGTH_SHORT).show()
+ Toast.makeText(context, R.string.msg_clearing_playing_queue, Toast.LENGTH_SHORT).show()
remote.clear()
}
}
@@ -125,8 +122,7 @@ class ConsoleViewModel @Inject constructor(
viewModelScope.launch {
// currently not available.
toaster.show(
- title = R.string.coming_soon,
- message = R.string.coming_soon_msg,
+ message = R.string.msg_feature_coming_soon,
leading = Icons.Outlined.MoreTime
)
}
@@ -149,9 +145,9 @@ class ConsoleViewModel @Inject constructor(
this@ConsoleViewModel.favourite = !favourite && res
if (!res)
toaster.show(
- message = Text("An error occurred while adding/removing the item to favourite playlist"),
- title = Text("Favourites"),
- leading = R.drawable.ic_heart
+ message = R.string.msg_error_fav_playlist_update,
+ leading = R.drawable.ic_heart,
+ accent = Color.OrientRed
)
}
}
diff --git a/app/src/main/java/com/prime/media/impl/LibraryViewModel.kt b/app/src/main/java/com/prime/media/impl/LibraryViewModel.kt
index e7ba14b..4db9f59 100644
--- a/app/src/main/java/com/prime/media/impl/LibraryViewModel.kt
+++ b/app/src/main/java/com/prime/media/impl/LibraryViewModel.kt
@@ -90,7 +90,7 @@ class LibraryViewModel @Inject constructor(
// item will be added to the playlist, initiating playback from this item's index.
// If the user decides otherwise, the item will be added to the queue following the current queue order.
val res = channel.show(
- R.string.library_recent_click_msg,
+ R.string.msg_library_recent_click,
action = R.string.reset,
leading = Icons.Outlined.Message,
accent = Color.MetroGreen
@@ -99,8 +99,7 @@ class LibraryViewModel @Inject constructor(
val file = files?.find { it.uri == uri }
if (files == null || file == null) {
channel.show(
- R.string.error_msg,
- R.string.error,
+ R.string.msg_unknown_error,
leading = Icons.Outlined.Error,
accent = Color.Rose
)
@@ -126,7 +125,7 @@ class LibraryViewModel @Inject constructor(
val item = files?.find { it.id == id }
if (files == null || item == null) {
channel.show(
- R.string.error_msg,
+ R.string.msg_unknown_error,
R.string.error,
leading = Icons.Outlined.Error,
accent = Color.Rose
@@ -139,7 +138,7 @@ class LibraryViewModel @Inject constructor(
if (isAlreadyInPlaylist)
return@launch
val res = channel.show(
- R.string.library_msg_recently_added_click,
+ R.string.msg_library_recently_added_click,
action = R.string.reset,
leading = Icons.Outlined.ClearAll,
accent = Color.DahliaYellow
diff --git a/app/src/main/java/com/prime/media/impl/SettingsViewModel.kt b/app/src/main/java/com/prime/media/impl/SettingsViewModel.kt
index 07b67e8..b0a424b 100644
--- a/app/src/main/java/com/prime/media/impl/SettingsViewModel.kt
+++ b/app/src/main/java/com/prime/media/impl/SettingsViewModel.kt
@@ -39,8 +39,8 @@ class SettingsViewModel @Inject constructor(
preferences[Settings.NIGHT_MODE].map {
Preference(
value = it,
- title = Text(R.string.app_theme),
- summery = Text(R.string.app_theme_summery),
+ title = Text(R.string.pref_app_theme),
+ summery = Text(R.string.pref_app_theme_summery),
vector = Icons.Outlined.Lightbulb
)
}.asComposeState()
@@ -51,8 +51,8 @@ class SettingsViewModel @Inject constructor(
preferences[Settings.COLOR_STATUS_BAR].map {
Preference(
vector = null,
- title = Text(R.string.color_status_bar),
- summery = Text(R.string.color_stutus_bar_summery),
+ title = Text(R.string.pref_color_system_bars),
+ summery = Text(R.string.pref_color_system_bars_summery),
value = it
)
}.asComposeState()
@@ -62,8 +62,8 @@ class SettingsViewModel @Inject constructor(
preferences[Settings.HIDE_STATUS_BAR].map {
Preference(
value = it,
- title = Text(R.string.immersive_view),
- summery = Text(R.string.immersive_view_summery),
+ title = Text(R.string.pref_hide_status_bar),
+ summery = Text(R.string.pref_hide_status_bar_summery),
vector = Icons.Outlined.HideImage
)
}.asComposeState()
@@ -73,8 +73,8 @@ class SettingsViewModel @Inject constructor(
preferences[Settings.FORCE_COLORIZE].map {
Preference(
value = it,
- title = Text(R.string.force_accent_color),
- summery = Text(R.string.force_aacent_color_summery)
+ title = Text(R.string.pref_force_accent_color),
+ summery = Text(R.string.pref_force_accent_color_summery)
)
}.asComposeState()
}
@@ -82,8 +82,8 @@ class SettingsViewModel @Inject constructor(
override val minTrackLength: Preference by with(preferences) {
preferences[Settings.MIN_TRACK_LENGTH_SECS].map {
Preference(
- title = Text(R.string.minimum_track_length),
- summery = Text(R.string.minimum_track_length_summery),
+ title = Text(R.string.pref_minimum_track_length),
+ summery = Text(R.string.pref_minimum_track_length_summery),
value = it
)
}.asComposeState()
@@ -92,8 +92,8 @@ class SettingsViewModel @Inject constructor(
override val recentPlaylistLimit: Preference by with(preferences) {
preferences[Settings.RECENT_PLAYLIST_LIMIT].map {
Preference(
- title = Text(R.string.recent_playlist_size),
- summery = Text(R.string.recent_playlist_size_summery),
+ title = Text(R.string.pref_recent_playlist_size),
+ summery = Text(R.string.pref_recent_playlist_size_summery),
value = it
)
}.asComposeState()
@@ -102,8 +102,8 @@ class SettingsViewModel @Inject constructor(
override val fetchArtworkFromMS: Preference by with(preferences) {
preferences[Settings.USE_LEGACY_ARTWORK_METHOD].map {
Preference(
- title = Text(R.string.fetch_artwork_from_mediastore),
- summery = Text(R.string.fetch_artwork_from_mediastore_summery),
+ title = Text(R.string.pref_fetch_artwork_from_mediastore),
+ summery = Text(R.string.pref_fetch_artwork_from_mediastore_summery),
value = it
)
}.asComposeState()
@@ -112,8 +112,8 @@ class SettingsViewModel @Inject constructor(
override val enableTrashCan: Preference by with(preferences) {
preferences[Settings.TRASH_CAN_ENABLED].map {
Preference(
- title = Text(R.string.enable_trash_can),
- summery = Text(R.string.enable_trash_can_summery, isHtml = true),
+ title = Text(R.string.pref_enable_trash_can),
+ summery = Text(R.string.pref_enable_trash_can_summery, isHtml = true),
value = it
)
}.asComposeState()
@@ -121,8 +121,8 @@ class SettingsViewModel @Inject constructor(
override val excludedFiles: Preference?> by with(preferences) {
preferences[Settings.BLACKLISTED_FILES].map {
Preference(
- title = Text(R.string.blacklist),
- summery = Text(R.string.blacklist_summery),
+ title = Text(R.string.pref_blacklist),
+ summery = Text(R.string.pref_blacklist_summery),
value = it
)
}.asComposeState()
@@ -130,8 +130,8 @@ class SettingsViewModel @Inject constructor(
override val gaplessPlayback: Preference by with(preferences) {
preferences[Settings.TRASH_CAN_ENABLED].map {
Preference(
- title = Text(R.string.enable_gapless_playback),
- summery = Text(R.string.enable_gapless_playback_summery),
+ title = Text(R.string.pref_enable_gapless_playback),
+ summery = Text(R.string.pref_enable_gapless_playback_summery),
value = it
)
}.asComposeState()
@@ -139,8 +139,8 @@ class SettingsViewModel @Inject constructor(
override val crossfadeTime: Preference by with(preferences) {
preferences[Settings.RECENT_PLAYLIST_LIMIT].map {
Preference(
- title = Text(R.string.crossfade_time),
- summery = Text(R.string.crossfade_time_summery),
+ title = Text(R.string.pref_crossfade_time),
+ summery = Text(R.string.pref_crossfade_time_summery),
value = it
)
}.asComposeState()
@@ -162,7 +162,7 @@ class SettingsViewModel @Inject constructor(
val res = blacklist.remove(path)
val name = PathUtils.name(path)
if (res)
- Toast.makeText(context, "$name has been successfully removed from blacklist", Toast.LENGTH_SHORT).show()
+ Toast.makeText(context, context.getString(R.string.msg_blacklist_item_remove_success_s, name), Toast.LENGTH_SHORT).show()
else
Toast.makeText(context, R.string.error, Toast.LENGTH_SHORT).show()
preferences[Settings.BLACKLISTED_FILES] = blacklist
diff --git a/app/src/main/java/com/prime/media/library/Library.kt b/app/src/main/java/com/prime/media/library/Library.kt
index b93ee35..ad94ff7 100644
--- a/app/src/main/java/com/prime/media/library/Library.kt
+++ b/app/src/main/java/com/prime/media/library/Library.kt
@@ -1,4 +1,5 @@
@file:Suppress("CrossfadeLabel", "FunctionName")
+@file:OptIn(ExperimentalTextApi::class, ExperimentalTextApi::class)
package com.prime.media.library
@@ -28,14 +29,11 @@ import androidx.compose.material.TopAppBar
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Folder
import androidx.compose.material.icons.outlined.Album
-import androidx.compose.material.icons.outlined.Audiotrack
import androidx.compose.material.icons.outlined.FavoriteBorder
-import androidx.compose.material.icons.outlined.Folder
import androidx.compose.material.icons.outlined.Grain
import androidx.compose.material.icons.outlined.GraphicEq
import androidx.compose.material.icons.outlined.NavigateNext
import androidx.compose.material.icons.outlined.Person
-import androidx.compose.material.icons.outlined.PlaylistAdd
import androidx.compose.material.icons.outlined.PlaylistPlay
import androidx.compose.material.icons.twotone.Settings
import androidx.compose.runtime.Composable
@@ -49,8 +47,10 @@ import androidx.compose.ui.draw.scale
import androidx.compose.ui.draw.shadow
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.vector.ImageVector
+import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
+import androidx.compose.ui.text.ExperimentalTextApi
import androidx.compose.ui.text.buildAnnotatedString
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.BaselineShift
@@ -64,6 +64,7 @@ import com.prime.media.R
import com.prime.media.caption2
import com.prime.media.core.ContentElevation
import com.prime.media.core.ContentPadding
+import com.prime.media.core.billing.Banner
import com.prime.media.core.billing.purchased
import com.prime.media.core.compose.Image
import com.prime.media.core.compose.KenBurns
@@ -91,12 +92,13 @@ import com.prime.media.small2
import com.primex.core.gradient
import com.primex.core.padding
import com.primex.core.rememberState
-import com.primex.core.stringHtmlResource
+import com.primex.core.textResource
import com.primex.core.withSpanStyle
import com.primex.material2.IconButton
import com.primex.material2.Label
import com.primex.material2.OutlinedButton2
import com.primex.material2.Search
+import com.primex.material2.Text
private const val TAG = "Library"
@@ -210,7 +212,7 @@ private fun TopBar(modifier: Modifier = Modifier) {
// Formatted as html resource.
title = {
Text(
- text = stringHtmlResource(id = R.string.title_audio_library_html),
+ text = textResource(id = R.string.library_title),
style = Material.typography.h5,
fontWeight = FontWeight.Light
)
@@ -316,34 +318,34 @@ private fun Shortcuts(
Shortcut(
onAction = { navigator.navigate(Folders.direction()) },
icon = Icons.Default.Folder,
- label = "Folders"
+ label = textResource(id = R.string.folders)
)
Shortcut(
onAction = { navigator.navigate(Genres.direction()) },
icon = Icons.Outlined.Grain,
- label = "Genres"
+ label = textResource(id = R.string.genres)
)
Shortcut(
onAction = { navigator.navigate(Audios.direction(Audios.GET_EVERY)) },
icon = Icons.Outlined.GraphicEq,
- label = "Audios"
+ label = textResource(id =R.string.audios)
)
Shortcut(
onAction = { navigator.navigate(Artists.direction()) },
icon = Icons.Outlined.Person,
- label = "Artists"
+ label = textResource(id =R.string.artists)
)
Shortcut(
onAction = { navigator.navigate(Members.direction(Playback.PLAYLIST_FAVOURITE)) },
icon = Icons.Outlined.FavoriteBorder,
- label = "Favourite"
+ label = textResource(id =R.string.favourite)
)
Shortcut(
onAction = { navigator.navigate(Playlists.direction()) },
icon = Icons.Outlined.PlaylistPlay,
- label = "Playlists"
+ label = textResource(id = R.string.playlists)
)
}
)
@@ -401,7 +403,7 @@ private fun Tile(
)
Text(
- text = "Albums".uppercase(),
+ text = textResource(id = R.string.albums).toString().uppercase(),
fontWeight = FontWeight.SemiBold,
modifier = Modifier.padding(start = ContentPadding.normal),
letterSpacing = 6.sp,
@@ -539,12 +541,14 @@ private val OFFSET_Y_SEARCH = (-32).dp
fun Library(
viewModel: Library
) {
+ val res = LocalContext.current.resources
+ val purchase by purchase(id = BuildConfig.IAP_NO_ADS)
Surface(
modifier = Modifier.fillMaxSize(),
color = Material.colors.background,
content = {
val navigator = LocalNavController.current
- LazyColumn() {
+ LazyColumn(horizontalAlignment = Alignment.CenterHorizontally) {
// The TopBar.
// TODO: Maybe make it collapsable.
TopBar(Modifier.statusBarsPadding())
@@ -562,8 +566,8 @@ fun Library(
.fillMaxWidth()
.offset(y = OFFSET_Y_SEARCH)
.padding(horizontal = ContentPadding.medium),
- title = "Shortcuts",
- subtitle = "The faster way to get things done.",
+ title = res.getString(R.string.library_shortcuts),
+ subtitle = res.getString(R.string.library_shortcuts_tag_line),
)
Shortcuts(
@@ -575,14 +579,23 @@ fun Library(
vertical = ContentPadding.small
)
)
+
+ if (!purchase.purchased)
+ item {
+ Banner(
+ placementID = BuildConfig.PLACEMENT_BANNER_1,
+ modifier = Modifier.padding(ContentPadding.medium).offset(y = OFFSET_Y_SEARCH)
+ )
+ }
+
// Recents.
Header(
modifier = Modifier
.fillMaxWidth()
.offset(y = OFFSET_Y_SEARCH)
.padding(horizontal = ContentPadding.medium),
- title = "Recent",
- subtitle = "The recently played tracks.",
+ title = res.getString(R.string.library_recent),
+ subtitle = res.getString(R.string.library_recent_tag_line),
onClick = { navigator.navigate(Members.direction(Playback.PLAYLIST_RECENT)) }
)
@@ -608,8 +621,8 @@ fun Library(
.fillMaxWidth()
.offset(y = OFFSET_Y_SEARCH)
.padding(horizontal = ContentPadding.medium),
- title = "Recently Added",
- subtitle = "The tracks that have been recently added",
+ title = res.getString(R.string.library_recently_added),
+ subtitle = res.getString(R.string.library_recently_added_tag_line),
onClick = {
navigator.navigate(
Audios.direction(
diff --git a/app/src/main/java/com/prime/media/settings/Blacklist.kt b/app/src/main/java/com/prime/media/settings/Blacklist.kt
index 4540fab..7f19e49 100644
--- a/app/src/main/java/com/prime/media/settings/Blacklist.kt
+++ b/app/src/main/java/com/prime/media/settings/Blacklist.kt
@@ -73,7 +73,7 @@ private fun Blacklist(
true -> Placeholder(
title = "Empty",
iconResId = R.raw.lt_empty_box,
- message = stringResource(R.string.blacklist_empty_msg)
+ message = stringResource(R.string.blacklist_empty_desc)
)
// Show actual list
else -> LazyColumn() {
@@ -96,7 +96,7 @@ fun Toolbar(
modifier: Modifier = Modifier
) {
TopAppBar(
- title = { Label(text = stringResource(id = R.string.blacklist)) },
+ title = { Label(text = stringResource(id = R.string.pref_blacklist)) },
modifier = modifier,
actions = { IconButton(imageVector = Icons.Outlined.Close, onClick = onDismissRequest) },
navigationIcon = {
diff --git a/app/src/main/java/com/prime/media/settings/Settings.kt b/app/src/main/java/com/prime/media/settings/Settings.kt
index b02aa57..4d8610f 100644
--- a/app/src/main/java/com/prime/media/settings/Settings.kt
+++ b/app/src/main/java/com/prime/media/settings/Settings.kt
@@ -1,3 +1,5 @@
+@file:OptIn(ExperimentalTextApi::class)
+
package com.prime.media.settings
import android.content.Intent
@@ -51,6 +53,7 @@ import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
+import androidx.compose.ui.text.ExperimentalTextApi
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
import com.prime.media.BuildConfig
@@ -73,6 +76,7 @@ import com.primex.core.drawHorizontalDivider
import com.primex.core.rememberState
import com.primex.core.stringHtmlResource
import com.primex.core.stringResource
+import com.primex.core.textResource
import com.primex.core.value
import com.primex.material2.DropDownPreference
import com.primex.material2.IconButton
@@ -80,6 +84,7 @@ import com.primex.material2.Label
import com.primex.material2.ListTile
import com.primex.material2.Preference
import com.primex.material2.SwitchPreference
+import com.primex.material2.Text
import com.primex.material2.neumorphic.NeumorphicTopAppBar
private const val TAG = "Settings"
@@ -115,7 +120,7 @@ private fun TopAppBar(
private val RESERVE_PADDING = 56.dp
@Composable
-private inline fun PrefHeader(text: String) {
+private inline fun PrefHeader(text: CharSequence) {
val primary = MaterialTheme.colors.secondary
Label(
text = text,
@@ -209,22 +214,22 @@ private inline fun ColumnScope.Body(
private inline fun ColumnScope.FeedBack() {
val facade = LocalSystemFacade.current
Preference(
- title = stringResource(R.string.feedback),
- summery = stringResource(id = R.string.feedback_dialog_placeholder) + "\nTap to open feedback dialog.",
+ title = stringResource(R.string.pref_feedback),
+ summery = stringResource(id = R.string.pref_feedback_summery) + "\nTap to open feedback dialog.",
icon = Icons.Outlined.Feedback,
modifier = Modifier.clickable { facade.launchAppStore() }
)
Preference(
- title = stringResource(R.string.rate_us),
- summery = stringResource(id = R.string.review_msg),
+ title = stringResource(R.string.pref_rate_us),
+ summery = stringResource(id = R.string.pref_review_summery),
icon = Icons.Outlined.Star,
modifier = Modifier.clickable { facade.launchAppStore() }
)
Preference(
- title = stringResource(R.string.spread_the_word),
- summery = stringResource(R.string.spread_the_word_summery),
+ title = stringResource(R.string.pref_spread_the_word),
+ summery = stringResource(R.string.pref_spread_the_word_summery),
icon = Icons.Outlined.Share,
modifier = Modifier.clickable { facade.shareApp() }
)
@@ -234,7 +239,7 @@ private inline fun ColumnScope.FeedBack() {
private inline fun ColumnScope.AboutUs() {
val provider = LocalSystemFacade.current
Text(
- text = stringHtmlResource(R.string.about_us_desc),
+ text = stringHtmlResource(R.string.pref_about_us_summery),
style = MaterialTheme.typography.body2,
modifier = Modifier
.padding(start = RESERVE_PADDING, end = ContentPadding.xLarge)
@@ -350,18 +355,20 @@ private fun GetToKnowUs(modifier: Modifier = Modifier) {
modifier = modifier.offset(x = ContentPadding.normal),
color = Color.Transparent,
overline = {
- com.primex.material2.Text(
- text = "Audiofy",
- style = Material.typography.h4,
- fontWeight = FontWeight.Bold
+ Text(
+ text = textResource(id = R.string.app_name),
+ style = Material.typography.h3,
+ fontWeight = FontWeight.Bold,
+ fontFamily = Settings.DancingScriptFontFamily
)
},
headline = {
Text(
- text = "v" + BuildConfig.VERSION_NAME + " by Zakir Sheikh",
+ text = textResource(R.string.pref_get_to_know_us_subttile_s, BuildConfig.VERSION_NAME),
style = Material.typography.caption
)
},
+ centerAlign = true,
leading = {
Icon(
painter = painterResource(id = R.drawable.ic_launcher_foreground),
@@ -384,28 +391,28 @@ private fun GetToKnowUs(modifier: Modifier = Modifier) {
imageVector = Icons.Outlined.AlternateEmail,
onClick = { ctx.startActivity(FeedbackIntent) },
modifier = Modifier
- .scale(0.7f)
+ .scale(0.85f)
.border(ButtonDefaults.outlinedBorder, CircleShape)
)
IconButton(
imageVector = Icons.Outlined.DataObject,
onClick = { ctx.startActivity(GithubIntent) },
modifier = Modifier
- .scale(0.7f)
+ .scale(0.85f)
.border(ButtonDefaults.outlinedBorder, CircleShape)
)
IconButton(
imageVector = Icons.Outlined.BugReport,
onClick = { ctx.startActivity(GitHubIssuesPage) },
modifier = Modifier
- .scale(0.7f)
+ .scale(0.85f)
.border(ButtonDefaults.outlinedBorder, CircleShape)
)
IconButton(
imageVector = Icons.Outlined.SupportAgent,
onClick = { ctx.startActivity(TelegramIntent) },
modifier = Modifier
- .scale(0.7f)
+ .scale(0.85f)
.border(ButtonDefaults.outlinedBorder, CircleShape)
)
}
@@ -422,14 +429,14 @@ private fun Compact(state: Settings) {
.padding(it)
.verticalScroll(rememberScrollState())
) {
- PrefHeader(text = "Get to Know Us")
+ PrefHeader(text = textResource(R.string.pref_get_to_know_us))
GetToKnowUs(modifier = Modifier.padding(start = ContentPadding.normal))
Body(state)
- PrefHeader(text = "General")
+ PrefHeader(text = textResource(R.string.general))
General(state = state)
- PrefHeader(text = "Feedback")
+ PrefHeader(text = textResource(R.string.feedback))
FeedBack()
- PrefHeader(text = stringResource(R.string.about_us))
+ PrefHeader(text = textResource(R.string.about_us))
AboutUs()
// Add the necessary padding.
val padding = LocalWindowPadding.current
diff --git a/app/src/main/java/com/prime/media/settings/ViewState.kt b/app/src/main/java/com/prime/media/settings/ViewState.kt
index b3dd0df..81ac1e3 100644
--- a/app/src/main/java/com/prime/media/settings/ViewState.kt
+++ b/app/src/main/java/com/prime/media/settings/ViewState.kt
@@ -78,7 +78,8 @@ interface Settings : Blacklist {
*/
val MINI_PLAYER_HEIGHT = 68.dp
- val LatoFontFamily = FontFamily("Roboto")
+ val DefaultFontFamily = FontFamily("Roboto")
+ val DancingScriptFontFamily = FontFamily("Dancing Script")
/**
* Retrieves/Sets The [NightMode] Strategy
diff --git a/app/src/main/res/values-night/theme.xml b/app/src/main/res/values-night/theme.xml
index 22ab607..0aba940 100644
--- a/app/src/main/res/values-night/theme.xml
+++ b/app/src/main/res/values-night/theme.xml
@@ -1,10 +1,10 @@
-
+