mirror of
https://github.com/Shabinder/SpotiFlyer.git
synced 2024-11-22 09:04:32 +01:00
Revert Back to old/gold java.io.File!
- SAF is painfully slow. - SAF brings nothing but more issues and hacks. - External SdCard write Access wont be fixed (NO SAF).
This commit is contained in:
parent
a3e9b7c3c1
commit
d9ba60dbbf
@ -120,12 +120,6 @@ dependencies {
|
|||||||
implementation(MVIKotlin.mvikotlinLogging)
|
implementation(MVIKotlin.mvikotlinLogging)
|
||||||
implementation(MVIKotlin.mvikotlinTimeTravel)
|
implementation(MVIKotlin.mvikotlinTimeTravel)
|
||||||
|
|
||||||
// Firebase
|
|
||||||
implementation(platform("com.google.firebase:firebase-bom:27.1.0"))
|
|
||||||
implementation("com.google.firebase:firebase-analytics-ktx")
|
|
||||||
implementation("com.google.firebase:firebase-crashlytics-ktx")
|
|
||||||
implementation("com.google.firebase:firebase-perf-ktx")
|
|
||||||
|
|
||||||
// Extras
|
// Extras
|
||||||
Extras.Android.apply {
|
Extras.Android.apply {
|
||||||
implementation(Acra.notification)
|
implementation(Acra.notification)
|
||||||
@ -134,6 +128,7 @@ dependencies {
|
|||||||
implementation(matomo)
|
implementation(matomo)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//implementation("com.jakewharton.timber:timber:4.7.1")
|
||||||
implementation("dev.icerock.moko:parcelize:0.6.1")
|
implementation("dev.icerock.moko:parcelize:0.6.1")
|
||||||
implementation("com.github.shabinder:storage-chooser:2.0.4.45")
|
implementation("com.github.shabinder:storage-chooser:2.0.4.45")
|
||||||
implementation("com.google.accompanist:accompanist-insets:0.9.1")
|
implementation("com.google.accompanist:accompanist-insets:0.9.1")
|
||||||
|
@ -29,8 +29,26 @@ import org.koin.android.ext.koin.androidContext
|
|||||||
import org.koin.android.ext.koin.androidLogger
|
import org.koin.android.ext.koin.androidLogger
|
||||||
import org.koin.core.component.KoinComponent
|
import org.koin.core.component.KoinComponent
|
||||||
import org.koin.core.logger.Level
|
import org.koin.core.logger.Level
|
||||||
|
import org.matomo.sdk.Matomo
|
||||||
|
import org.matomo.sdk.Tracker
|
||||||
|
import org.matomo.sdk.TrackerBuilder
|
||||||
|
|
||||||
class App: Application(), KoinComponent {
|
class App: Application(), KoinComponent {
|
||||||
|
|
||||||
|
val tracker: Tracker by lazy {
|
||||||
|
TrackerBuilder.createDefault(
|
||||||
|
"https://kind-grasshopper-73.telebit.io/matomo/matomo.php", 1)
|
||||||
|
.build(Matomo.getInstance(this)).apply {
|
||||||
|
if (BuildConfig.DEBUG) {
|
||||||
|
/*Timber.plant(DebugTree())
|
||||||
|
addTrackingCallback {
|
||||||
|
Timber.d(it.toMap().toString())
|
||||||
|
it
|
||||||
|
}*/
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun onCreate() {
|
override fun onCreate() {
|
||||||
super.onCreate()
|
super.onCreate()
|
||||||
|
|
||||||
|
@ -56,22 +56,22 @@ import com.shabinder.common.models.Actions
|
|||||||
import com.shabinder.common.models.DownloadStatus
|
import com.shabinder.common.models.DownloadStatus
|
||||||
import com.shabinder.common.models.PlatformActions
|
import com.shabinder.common.models.PlatformActions
|
||||||
import com.shabinder.common.models.PlatformActions.Companion.SharedPreferencesKey
|
import com.shabinder.common.models.PlatformActions.Companion.SharedPreferencesKey
|
||||||
|
import com.shabinder.common.models.Status
|
||||||
import com.shabinder.common.models.TrackDetails
|
import com.shabinder.common.models.TrackDetails
|
||||||
|
import com.shabinder.common.models.methods
|
||||||
import com.shabinder.common.root.SpotiFlyerRoot
|
import com.shabinder.common.root.SpotiFlyerRoot
|
||||||
|
import com.shabinder.common.root.SpotiFlyerRoot.Analytics
|
||||||
import com.shabinder.common.root.callbacks.SpotiFlyerRootCallBacks
|
import com.shabinder.common.root.callbacks.SpotiFlyerRootCallBacks
|
||||||
import com.shabinder.common.uikit.*
|
import com.shabinder.common.uikit.*
|
||||||
import com.shabinder.spotiflyer.utils.*
|
|
||||||
import com.shabinder.common.models.Status
|
|
||||||
import com.shabinder.common.models.methods
|
|
||||||
import com.shabinder.spotiflyer.ui.NetworkDialog
|
import com.shabinder.spotiflyer.ui.NetworkDialog
|
||||||
import com.shabinder.spotiflyer.ui.PermissionDialog
|
import com.shabinder.spotiflyer.ui.PermissionDialog
|
||||||
|
import com.shabinder.spotiflyer.utils.*
|
||||||
import kotlinx.coroutines.*
|
import kotlinx.coroutines.*
|
||||||
import kotlinx.coroutines.flow.*
|
import kotlinx.coroutines.flow.*
|
||||||
import org.koin.android.ext.android.inject
|
import org.koin.android.ext.android.inject
|
||||||
|
import org.matomo.sdk.extra.TrackHelper
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
const val disableDozeCode = 1223
|
|
||||||
|
|
||||||
@ExperimentalAnimationApi
|
@ExperimentalAnimationApi
|
||||||
class MainActivity : ComponentActivity() {
|
class MainActivity : ComponentActivity() {
|
||||||
|
|
||||||
@ -85,6 +85,7 @@ class MainActivity : ComponentActivity() {
|
|||||||
private lateinit var updateUIReceiver: BroadcastReceiver
|
private lateinit var updateUIReceiver: BroadcastReceiver
|
||||||
private lateinit var queryReceiver: BroadcastReceiver
|
private lateinit var queryReceiver: BroadcastReceiver
|
||||||
private val internetAvailability by lazy { ConnectionLiveData(applicationContext) }
|
private val internetAvailability by lazy { ConnectionLiveData(applicationContext) }
|
||||||
|
private val tracker get() = (application as App).tracker
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
@ -118,7 +119,8 @@ class MainActivity : ComponentActivity() {
|
|||||||
PermissionDialog(
|
PermissionDialog(
|
||||||
permissionGranted.value,
|
permissionGranted.value,
|
||||||
{ requestStoragePermission() },
|
{ requestStoragePermission() },
|
||||||
{ disableDozeMode(disableDozeCode) }
|
{ disableDozeMode(disableDozeCode) },
|
||||||
|
dir::enableAnalytics
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -130,6 +132,10 @@ class MainActivity : ComponentActivity() {
|
|||||||
private fun initialise() {
|
private fun initialise() {
|
||||||
checkIfLatestVersion()
|
checkIfLatestVersion()
|
||||||
handleIntentFromExternalActivity()
|
handleIntentFromExternalActivity()
|
||||||
|
if(dir.isAnalyticsEnabled){
|
||||||
|
// Download/App Install Event
|
||||||
|
TrackHelper.track().download().with(tracker)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
@ -380,4 +386,8 @@ class MainActivity : ComponentActivity() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
const val disableDozeCode = 1223
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,11 +8,13 @@ import androidx.compose.foundation.layout.Row
|
|||||||
import androidx.compose.foundation.layout.Spacer
|
import androidx.compose.foundation.layout.Spacer
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.foundation.layout.size
|
||||||
import androidx.compose.material.AlertDialog
|
import androidx.compose.material.AlertDialog
|
||||||
import androidx.compose.material.Icon
|
import androidx.compose.material.Icon
|
||||||
import androidx.compose.material.Text
|
import androidx.compose.material.Text
|
||||||
import androidx.compose.material.TextButton
|
import androidx.compose.material.TextButton
|
||||||
import androidx.compose.material.icons.Icons
|
import androidx.compose.material.icons.Icons
|
||||||
|
import androidx.compose.material.icons.rounded.Insights
|
||||||
import androidx.compose.material.icons.rounded.SdStorage
|
import androidx.compose.material.icons.rounded.SdStorage
|
||||||
import androidx.compose.material.icons.rounded.SystemSecurityUpdate
|
import androidx.compose.material.icons.rounded.SystemSecurityUpdate
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
@ -28,6 +30,7 @@ import androidx.compose.ui.text.font.FontWeight
|
|||||||
import androidx.compose.ui.text.style.TextAlign
|
import androidx.compose.ui.text.style.TextAlign
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.compose.ui.unit.sp
|
import androidx.compose.ui.unit.sp
|
||||||
|
import androidx.compose.ui.window.DialogProperties
|
||||||
import com.shabinder.common.uikit.SpotiFlyerShapes
|
import com.shabinder.common.uikit.SpotiFlyerShapes
|
||||||
import com.shabinder.common.uikit.SpotiFlyerTypography
|
import com.shabinder.common.uikit.SpotiFlyerTypography
|
||||||
import com.shabinder.common.uikit.colorPrimary
|
import com.shabinder.common.uikit.colorPrimary
|
||||||
@ -38,13 +41,50 @@ import kotlinx.coroutines.delay
|
|||||||
fun PermissionDialog(
|
fun PermissionDialog(
|
||||||
permissionGranted: Boolean,
|
permissionGranted: Boolean,
|
||||||
requestStoragePermission:() -> Unit,
|
requestStoragePermission:() -> Unit,
|
||||||
disableDozeMode:() -> Unit
|
disableDozeMode:() -> Unit,
|
||||||
|
enableAnalytics:() -> Unit
|
||||||
){
|
){
|
||||||
var askForPermission by remember { mutableStateOf(false) }
|
var askForPermission by remember { mutableStateOf(false) }
|
||||||
LaunchedEffect(Unit) {
|
LaunchedEffect(Unit) {
|
||||||
delay(2000)
|
delay(2000)
|
||||||
askForPermission = true
|
askForPermission = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Analytics Permission Dialog
|
||||||
|
var askForAnalyticsPermission by remember { mutableStateOf(false) }
|
||||||
|
AnimatedVisibility(askForAnalyticsPermission) {
|
||||||
|
AlertDialog(
|
||||||
|
onDismissRequest = {
|
||||||
|
askForAnalyticsPermission = false
|
||||||
|
},
|
||||||
|
title = {
|
||||||
|
Row(verticalAlignment = Alignment.CenterVertically) {
|
||||||
|
Icon(Icons.Rounded.Insights,"Analytics",Modifier.size(52.dp))
|
||||||
|
Spacer(Modifier.padding(horizontal = 4.dp))
|
||||||
|
Text("Grant Analytics Access",style = SpotiFlyerTypography.h5,textAlign = TextAlign.Center)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
backgroundColor = Color.DarkGray,
|
||||||
|
buttons = {
|
||||||
|
TextButton(
|
||||||
|
{
|
||||||
|
askForAnalyticsPermission = false
|
||||||
|
enableAnalytics()
|
||||||
|
},
|
||||||
|
Modifier.padding(bottom = 16.dp, start = 16.dp, end = 16.dp).fillMaxWidth()
|
||||||
|
.background(colorPrimary, shape = SpotiFlyerShapes.medium)
|
||||||
|
.padding(horizontal = 8.dp),
|
||||||
|
) {
|
||||||
|
Text("Sure!",color = Color.Black,fontSize = 18.sp,textAlign = TextAlign.Center)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
text = {
|
||||||
|
Text("Your Data is Anonymized and will never be shared with any 3rd party service",style = SpotiFlyerTypography.body2,textAlign = TextAlign.Center)
|
||||||
|
},
|
||||||
|
properties = DialogProperties(dismissOnBackPress = true,dismissOnClickOutside = false)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
AnimatedVisibility(
|
AnimatedVisibility(
|
||||||
askForPermission && !permissionGranted
|
askForPermission && !permissionGranted
|
||||||
) {
|
) {
|
||||||
@ -55,6 +95,7 @@ fun PermissionDialog(
|
|||||||
{
|
{
|
||||||
requestStoragePermission()
|
requestStoragePermission()
|
||||||
disableDozeMode()
|
disableDozeMode()
|
||||||
|
askForAnalyticsPermission = true
|
||||||
},
|
},
|
||||||
Modifier.padding(bottom = 16.dp, start = 16.dp, end = 16.dp).fillMaxWidth()
|
Modifier.padding(bottom = 16.dp, start = 16.dp, end = 16.dp).fillMaxWidth()
|
||||||
.background(colorPrimary, shape = SpotiFlyerShapes.medium)
|
.background(colorPrimary, shape = SpotiFlyerShapes.medium)
|
||||||
@ -100,6 +141,23 @@ fun PermissionDialog(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Row(
|
||||||
|
modifier = Modifier.fillMaxWidth().padding(top = 6.dp),
|
||||||
|
verticalAlignment = Alignment.CenterVertically
|
||||||
|
) {
|
||||||
|
Icon(Icons.Rounded.Insights,"Analytics")
|
||||||
|
Spacer(modifier = Modifier.padding(start = 16.dp))
|
||||||
|
Column {
|
||||||
|
Text(
|
||||||
|
text = "Analytics",
|
||||||
|
style = SpotiFlyerTypography.h6.copy(fontWeight = FontWeight.SemiBold)
|
||||||
|
)
|
||||||
|
Text(
|
||||||
|
text = "Share Analytics Data (optional) with App Devs (Self-Hosted), It will never be used/shared/sold to any third party service.",
|
||||||
|
style = SpotiFlyerTypography.subtitle2,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
@ -102,7 +102,7 @@ fun SpotiFlyerMainContent(component: SpotiFlyerMain) {
|
|||||||
)
|
)
|
||||||
|
|
||||||
when (model.selectedCategory) {
|
when (model.selectedCategory) {
|
||||||
HomeCategory.About -> AboutColumn()
|
HomeCategory.About -> AboutColumn { component.analytics.donationDialogVisit() }
|
||||||
HomeCategory.History -> HistoryColumn(
|
HomeCategory.History -> HistoryColumn(
|
||||||
model.records.sortedByDescending { it.id },
|
model.records.sortedByDescending { it.id },
|
||||||
component::loadImage,
|
component::loadImage,
|
||||||
@ -221,7 +221,10 @@ fun SearchPanel(
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun AboutColumn(modifier: Modifier = Modifier) {
|
fun AboutColumn(
|
||||||
|
modifier: Modifier = Modifier,
|
||||||
|
donationDialogOpenEvent:() -> Unit
|
||||||
|
) {
|
||||||
|
|
||||||
Box {
|
Box {
|
||||||
val stateVertical = rememberScrollState(0)
|
val stateVertical = rememberScrollState(0)
|
||||||
@ -331,14 +334,18 @@ fun AboutColumn(modifier: Modifier = Modifier) {
|
|||||||
var isDonationDialogVisible by remember { mutableStateOf(false) }
|
var isDonationDialogVisible by remember { mutableStateOf(false) }
|
||||||
|
|
||||||
DonationDialog(
|
DonationDialog(
|
||||||
isDonationDialogVisible
|
isDonationDialogVisible,
|
||||||
) {
|
onDismiss = {
|
||||||
isDonationDialogVisible = false
|
isDonationDialogVisible = false
|
||||||
}
|
}
|
||||||
|
)
|
||||||
|
|
||||||
Row(
|
Row(
|
||||||
modifier = modifier.fillMaxWidth().padding(vertical = 6.dp)
|
modifier = modifier.fillMaxWidth().padding(vertical = 6.dp)
|
||||||
.clickable(onClick = { isDonationDialogVisible = true }),
|
.clickable(onClick = {
|
||||||
|
isDonationDialogVisible = true
|
||||||
|
donationDialogOpenEvent()
|
||||||
|
}),
|
||||||
verticalAlignment = Alignment.CenterVertically
|
verticalAlignment = Alignment.CenterVertically
|
||||||
) {
|
) {
|
||||||
Icon(Icons.Rounded.CardGiftcard, "Support Developer")
|
Icon(Icons.Rounded.CardGiftcard, "Support Developer")
|
||||||
|
@ -41,7 +41,7 @@ import java.net.URL
|
|||||||
actual class Dir actual constructor(
|
actual class Dir actual constructor(
|
||||||
private val logger: Kermit,
|
private val logger: Kermit,
|
||||||
private val settings: Settings,
|
private val settings: Settings,
|
||||||
private val spotiFlyerDatabase: SpotiFlyerDatabase,
|
spotiFlyerDatabase: SpotiFlyerDatabase,
|
||||||
) {
|
) {
|
||||||
companion object {
|
companion object {
|
||||||
const val DirKey = "downloadDir"
|
const val DirKey = "downloadDir"
|
||||||
@ -91,7 +91,7 @@ actual class Dir actual constructor(
|
|||||||
* */
|
* */
|
||||||
if(!songFile.exists()) {
|
if(!songFile.exists()) {
|
||||||
/*Make intermediate Dirs if they don't exist yet*/
|
/*Make intermediate Dirs if they don't exist yet*/
|
||||||
songFile.parentFile.mkdirs()
|
songFile.parentFile?.mkdirs()
|
||||||
}
|
}
|
||||||
|
|
||||||
if(mp3ByteArray.isNotEmpty()) songFile.writeBytes(mp3ByteArray)
|
if(mp3ByteArray.isNotEmpty()) songFile.writeBytes(mp3ByteArray)
|
||||||
|
@ -17,7 +17,6 @@
|
|||||||
package com.shabinder.common.di
|
package com.shabinder.common.di
|
||||||
|
|
||||||
import co.touchlab.kermit.Kermit
|
import co.touchlab.kermit.Kermit
|
||||||
import co.touchlab.stately.ensureNeverFrozen
|
|
||||||
import com.russhwolf.settings.Settings
|
import com.russhwolf.settings.Settings
|
||||||
import com.shabinder.common.database.databaseModule
|
import com.shabinder.common.database.databaseModule
|
||||||
import com.shabinder.common.database.getLogger
|
import com.shabinder.common.database.getLogger
|
||||||
@ -25,15 +24,10 @@ import com.shabinder.common.di.providers.GaanaProvider
|
|||||||
import com.shabinder.common.di.providers.SpotifyProvider
|
import com.shabinder.common.di.providers.SpotifyProvider
|
||||||
import com.shabinder.common.di.providers.YoutubeMp3
|
import com.shabinder.common.di.providers.YoutubeMp3
|
||||||
import com.shabinder.common.di.providers.YoutubeMusic
|
import com.shabinder.common.di.providers.YoutubeMusic
|
||||||
import com.shabinder.common.models.NativeAtomicReference
|
import io.ktor.client.*
|
||||||
import io.ktor.client.HttpClient
|
import io.ktor.client.features.json.*
|
||||||
import io.ktor.client.features.HttpTimeout
|
import io.ktor.client.features.json.serializer.*
|
||||||
import io.ktor.client.features.json.JsonFeature
|
import io.ktor.client.features.logging.*
|
||||||
import io.ktor.client.features.json.serializer.KotlinxSerializer
|
|
||||||
import io.ktor.client.features.logging.DEFAULT
|
|
||||||
import io.ktor.client.features.logging.LogLevel
|
|
||||||
import io.ktor.client.features.logging.Logger
|
|
||||||
import io.ktor.client.features.logging.Logging
|
|
||||||
import kotlinx.serialization.json.Json
|
import kotlinx.serialization.json.Json
|
||||||
import org.koin.core.context.startKoin
|
import org.koin.core.context.startKoin
|
||||||
import org.koin.dsl.KoinAppDeclaration
|
import org.koin.dsl.KoinAppDeclaration
|
||||||
@ -87,12 +81,6 @@ fun createHttpClient(enableNetworkLogs: Boolean = false) = HttpClient {
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
}*/
|
}*/
|
||||||
// Timeout
|
|
||||||
install(HttpTimeout) {
|
|
||||||
// requestTimeoutMillis = 20000L
|
|
||||||
connectTimeoutMillis = 15000L
|
|
||||||
socketTimeoutMillis = 15000L
|
|
||||||
}
|
|
||||||
if (enableNetworkLogs) {
|
if (enableNetworkLogs) {
|
||||||
install(Logging) {
|
install(Logging) {
|
||||||
logger = Logger.DEFAULT
|
logger = Logger.DEFAULT
|
||||||
|
@ -18,7 +18,6 @@ package com.shabinder.common.di
|
|||||||
|
|
||||||
import co.touchlab.kermit.Kermit
|
import co.touchlab.kermit.Kermit
|
||||||
import com.russhwolf.settings.Settings
|
import com.russhwolf.settings.Settings
|
||||||
import com.russhwolf.settings.SettingsListener
|
|
||||||
import com.shabinder.common.database.SpotiFlyerDatabase
|
import com.shabinder.common.database.SpotiFlyerDatabase
|
||||||
import com.shabinder.common.di.utils.removeIllegalChars
|
import com.shabinder.common.di.utils.removeIllegalChars
|
||||||
import com.shabinder.common.models.DownloadResult
|
import com.shabinder.common.models.DownloadResult
|
||||||
|
@ -45,6 +45,13 @@ actual class Dir actual constructor(
|
|||||||
) {
|
) {
|
||||||
companion object {
|
companion object {
|
||||||
const val DirKey = "downloadDir"
|
const val DirKey = "downloadDir"
|
||||||
|
const val AnalyticsKey = "analytics"
|
||||||
|
}
|
||||||
|
|
||||||
|
actual val isAnalyticsEnabled get() = settings.getBooleanOrNull(AnalyticsKey) ?: false
|
||||||
|
|
||||||
|
actual fun enableAnalytics() {
|
||||||
|
settings.putBoolean(AnalyticsKey,true)
|
||||||
}
|
}
|
||||||
|
|
||||||
init {
|
init {
|
||||||
|
@ -21,7 +21,6 @@ import platform.Foundation.sendSynchronousRequest
|
|||||||
import platform.Foundation.writeToFile
|
import platform.Foundation.writeToFile
|
||||||
import platform.UIKit.UIImage
|
import platform.UIKit.UIImage
|
||||||
import platform.UIKit.UIImageJPEGRepresentation
|
import platform.UIKit.UIImageJPEGRepresentation
|
||||||
import java.lang.System
|
|
||||||
|
|
||||||
actual class Dir actual constructor(
|
actual class Dir actual constructor(
|
||||||
val logger: Kermit,
|
val logger: Kermit,
|
||||||
@ -30,6 +29,13 @@ actual class Dir actual constructor(
|
|||||||
) {
|
) {
|
||||||
companion object {
|
companion object {
|
||||||
const val DirKey = "downloadDir"
|
const val DirKey = "downloadDir"
|
||||||
|
const val AnalyticsKey = "analytics"
|
||||||
|
}
|
||||||
|
|
||||||
|
actual val isAnalyticsEnabled get() = settings.getBooleanOrNull(AnalyticsKey) ?: false
|
||||||
|
|
||||||
|
actual fun enableAnalytics() {
|
||||||
|
settings.putBoolean(AnalyticsKey,true)
|
||||||
}
|
}
|
||||||
|
|
||||||
actual fun isPresent(path: String): Boolean = NSFileManager.defaultManager.fileExistsAtPath(path)
|
actual fun isPresent(path: String): Boolean = NSFileManager.defaultManager.fileExistsAtPath(path)
|
||||||
|
@ -39,8 +39,17 @@ actual class Dir actual constructor(
|
|||||||
) {
|
) {
|
||||||
companion object {
|
companion object {
|
||||||
const val DirKey = "downloadDir"
|
const val DirKey = "downloadDir"
|
||||||
|
const val AnalyticsKey = "analytics"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
actual val isAnalyticsEnabled get() = settings.getBooleanOrNull(AnalyticsKey) ?: false
|
||||||
|
|
||||||
|
actual fun enableAnalytics() {
|
||||||
|
settings.putBoolean(AnalyticsKey,true)
|
||||||
|
}
|
||||||
|
|
||||||
|
actual fun setDownloadDirectory(newBasePath:String) = settings.putString(DirKey,newBasePath)
|
||||||
|
|
||||||
/*init {
|
/*init {
|
||||||
createDirectories()
|
createDirectories()
|
||||||
}*/
|
}*/
|
||||||
|
@ -65,6 +65,11 @@ interface SpotiFlyerList {
|
|||||||
val link: String
|
val link: String
|
||||||
val listOutput: Consumer<Output>
|
val listOutput: Consumer<Output>
|
||||||
val downloadProgressFlow: MutableSharedFlow<HashMap<String, DownloadStatus>>
|
val downloadProgressFlow: MutableSharedFlow<HashMap<String, DownloadStatus>>
|
||||||
|
val listAnalytics: Analytics
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Analytics {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sealed class Output {
|
sealed class Output {
|
||||||
|
@ -31,6 +31,8 @@ interface SpotiFlyerMain {
|
|||||||
|
|
||||||
val models: Value<State>
|
val models: Value<State>
|
||||||
|
|
||||||
|
val analytics: Analytics
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We Intend to Move to List Screen
|
* We Intend to Move to List Screen
|
||||||
* Note: Implementation in Root
|
* Note: Implementation in Root
|
||||||
@ -57,6 +59,11 @@ interface SpotiFlyerMain {
|
|||||||
val storeFactory: StoreFactory
|
val storeFactory: StoreFactory
|
||||||
val database: Database?
|
val database: Database?
|
||||||
val dir: Dir
|
val dir: Dir
|
||||||
|
val mainAnalytics: Analytics
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Analytics {
|
||||||
|
fun donationDialogVisit()
|
||||||
}
|
}
|
||||||
|
|
||||||
sealed class Output {
|
sealed class Output {
|
||||||
|
@ -40,9 +40,6 @@ internal class SpotiFlyerMainImpl(
|
|||||||
|
|
||||||
init {
|
init {
|
||||||
instanceKeeper.ensureNeverFrozen()
|
instanceKeeper.ensureNeverFrozen()
|
||||||
lifecycle.doOnDestroy {
|
|
||||||
cache.invalidateAll()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private val store =
|
private val store =
|
||||||
@ -55,11 +52,13 @@ internal class SpotiFlyerMainImpl(
|
|||||||
|
|
||||||
private val cache = Cache.Builder
|
private val cache = Cache.Builder
|
||||||
.newBuilder()
|
.newBuilder()
|
||||||
.maximumCacheSize(20)
|
.maximumCacheSize(25)
|
||||||
.build<String, Picture>()
|
.build<String, Picture>()
|
||||||
|
|
||||||
override val models: Value<State> = store.asValue()
|
override val models: Value<State> = store.asValue()
|
||||||
|
|
||||||
|
override val analytics = mainAnalytics
|
||||||
|
|
||||||
override fun onLinkSearch(link: String) {
|
override fun onLinkSearch(link: String) {
|
||||||
if (methods.value.isInternetAvailable) mainOutput.callback(Output.Search(link = link))
|
if (methods.value.isInternetAvailable) mainOutput.callback(Output.Search(link = link))
|
||||||
else methods.value.showPopUpMessage("Check Network Connection Please")
|
else methods.value.showPopUpMessage("Check Network Connection Please")
|
||||||
|
@ -54,6 +54,14 @@ interface SpotiFlyerRoot {
|
|||||||
val directories: Dir
|
val directories: Dir
|
||||||
val downloadProgressReport: MutableSharedFlow<HashMap<String, DownloadStatus>>
|
val downloadProgressReport: MutableSharedFlow<HashMap<String, DownloadStatus>>
|
||||||
val actions:Actions
|
val actions:Actions
|
||||||
|
val analytics: Analytics
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Analytics {
|
||||||
|
fun appLaunchEvent()
|
||||||
|
fun homeScreenVisit()
|
||||||
|
fun listScreenVisit()
|
||||||
|
fun donationDialogVisit()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,6 +37,7 @@ import com.shabinder.common.models.AllPlatforms
|
|||||||
import com.shabinder.common.models.Consumer
|
import com.shabinder.common.models.Consumer
|
||||||
import com.shabinder.common.models.methods
|
import com.shabinder.common.models.methods
|
||||||
import com.shabinder.common.root.SpotiFlyerRoot
|
import com.shabinder.common.root.SpotiFlyerRoot
|
||||||
|
import com.shabinder.common.root.SpotiFlyerRoot.Analytics
|
||||||
import com.shabinder.common.root.SpotiFlyerRoot.Child
|
import com.shabinder.common.root.SpotiFlyerRoot.Child
|
||||||
import com.shabinder.common.root.SpotiFlyerRoot.Dependencies
|
import com.shabinder.common.root.SpotiFlyerRoot.Dependencies
|
||||||
import com.shabinder.common.root.callbacks.SpotiFlyerRootCallBacks
|
import com.shabinder.common.root.callbacks.SpotiFlyerRootCallBacks
|
||||||
@ -49,7 +50,8 @@ internal class SpotiFlyerRootImpl(
|
|||||||
componentContext: ComponentContext,
|
componentContext: ComponentContext,
|
||||||
private val main: (ComponentContext, output:Consumer<SpotiFlyerMain.Output>)->SpotiFlyerMain,
|
private val main: (ComponentContext, output:Consumer<SpotiFlyerMain.Output>)->SpotiFlyerMain,
|
||||||
private val list: (ComponentContext, link:String, output:Consumer<SpotiFlyerList.Output>)->SpotiFlyerList,
|
private val list: (ComponentContext, link:String, output:Consumer<SpotiFlyerList.Output>)->SpotiFlyerList,
|
||||||
private val actions: Actions
|
private val actions: Actions,
|
||||||
|
private val analytics: Analytics
|
||||||
) : SpotiFlyerRoot, ComponentContext by componentContext {
|
) : SpotiFlyerRoot, ComponentContext by componentContext {
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
@ -72,7 +74,8 @@ internal class SpotiFlyerRootImpl(
|
|||||||
dependencies
|
dependencies
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
actions = dependencies.actions.freeze()
|
actions = dependencies.actions.freeze(),
|
||||||
|
analytics = dependencies.analytics
|
||||||
) {
|
) {
|
||||||
instanceKeeper.ensureNeverFrozen()
|
instanceKeeper.ensureNeverFrozen()
|
||||||
methods.value = dependencies.actions.freeze()
|
methods.value = dependencies.actions.freeze()
|
||||||
@ -113,16 +116,23 @@ internal class SpotiFlyerRootImpl(
|
|||||||
|
|
||||||
private fun onMainOutput(output: SpotiFlyerMain.Output) =
|
private fun onMainOutput(output: SpotiFlyerMain.Output) =
|
||||||
when (output) {
|
when (output) {
|
||||||
is SpotiFlyerMain.Output.Search -> router.push(Configuration.List(link = output.link))
|
is SpotiFlyerMain.Output.Search -> {
|
||||||
|
router.push(Configuration.List(link = output.link))
|
||||||
|
analytics.listScreenVisit()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun onListOutput(output: SpotiFlyerList.Output): Unit =
|
private fun onListOutput(output: SpotiFlyerList.Output): Unit =
|
||||||
when (output) {
|
when (output) {
|
||||||
is SpotiFlyerList.Output.Finished -> router.pop()
|
is SpotiFlyerList.Output.Finished -> {
|
||||||
|
router.pop()
|
||||||
|
analytics.homeScreenVisit()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun authenticateSpotify(spotifyProvider: SpotifyProvider, override:Boolean){
|
private fun authenticateSpotify(spotifyProvider: SpotifyProvider, override:Boolean){
|
||||||
GlobalScope.launch(Dispatchers.Default) {
|
GlobalScope.launch(Dispatchers.Default) {
|
||||||
|
analytics.appLaunchEvent()
|
||||||
/*Authenticate Spotify Client*/
|
/*Authenticate Spotify Client*/
|
||||||
spotifyProvider.authenticateSpotifyClient(override)
|
spotifyProvider.authenticateSpotifyClient(override)
|
||||||
}
|
}
|
||||||
@ -143,6 +153,9 @@ private fun spotiFlyerMain(componentContext: ComponentContext, output: Consumer<
|
|||||||
dependencies = object : SpotiFlyerMain.Dependencies, Dependencies by dependencies {
|
dependencies = object : SpotiFlyerMain.Dependencies, Dependencies by dependencies {
|
||||||
override val mainOutput: Consumer<SpotiFlyerMain.Output> = output
|
override val mainOutput: Consumer<SpotiFlyerMain.Output> = output
|
||||||
override val dir: Dir = directories
|
override val dir: Dir = directories
|
||||||
|
override val mainAnalytics = object : SpotiFlyerMain.Analytics {
|
||||||
|
override fun donationDialogVisit() = analytics.donationDialogVisit()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -155,5 +168,6 @@ private fun spotiFlyerList(componentContext: ComponentContext, link: String, out
|
|||||||
override val link: String = link
|
override val link: String = link
|
||||||
override val listOutput: Consumer<SpotiFlyerList.Output> = output
|
override val listOutput: Consumer<SpotiFlyerList.Output> = output
|
||||||
override val downloadProgressFlow = downloadProgressReport
|
override val downloadProgressFlow = downloadProgressReport
|
||||||
|
override val listAnalytics = object : SpotiFlyerList.Analytics {}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
Loading…
Reference in New Issue
Block a user