Navigation Implemented.

This commit is contained in:
shabinder 2020-12-29 18:48:23 +05:30
parent d734c82bf9
commit 38618bd2b1
10 changed files with 313 additions and 40 deletions

View File

@ -80,6 +80,9 @@ dependencies {
implementation "androidx.compose.material:material:$compose_version" implementation "androidx.compose.material:material:$compose_version"
implementation "androidx.compose.material:material-icons-extended:$compose_version" implementation "androidx.compose.material:material-icons-extended:$compose_version"
//Compose-Navigation
implementation "androidx.navigation:navigation-compose:1.0.0-alpha04"
//Lifecycle //Lifecycle
implementation "androidx.lifecycle:lifecycle-runtime-ktx:$lifecycle_version" implementation "androidx.lifecycle:lifecycle-runtime-ktx:$lifecycle_version"
implementation "androidx.lifecycle:lifecycle-livedata-ktx:$lifecycle_version" implementation "androidx.lifecycle:lifecycle-livedata-ktx:$lifecycle_version"

View File

@ -1,24 +1,57 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" <manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.shabinder.spotiflyer"> package="com.shabinder.spotiflyer">
<queries>
<package android:name="com.gaana" />
<package android:name="com.spotify.music" />
<package android:name="com.google.android.youtube" />
</queries>
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"
android:maxSdkVersion="28"
tools:ignore="ScopedStorage" />
<uses-permission android:name="android.permission.READ_STORAGE_PERMISSION" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" />
<application <application
android:allowBackup="true" android:allowBackup="true"
android:icon="@mipmap/ic_launcher" android:icon="@mipmap/ic_launcher"
android:label="@string/app_name" android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round" android:roundIcon="@mipmap/ic_launcher_round"
android:forceDarkAllowed="true"
android:supportsRtl="true" android:supportsRtl="true"
android:theme="@style/Theme.SpotiFlyer"> android:theme="@style/Theme.SpotiFlyer"
tools:targetApi="q"
tools:ignore="AllowBackup">
<activity <activity
android:name=".MainActivity" android:name=".MainActivity"
android:label="@string/app_name" android:label="@string/app_name"
android:theme="@style/Theme.SpotiFlyer"> android:hardwareAccelerated="true"
android:theme="@style/Theme.SpotiFlyer"
android:launchMode="singleTask">
<intent-filter> <intent-filter>
<action android:name="android.intent.action.MAIN" /> <action android:name="android.intent.action.MAIN" />
<data android:mimeType="text/plain" />
<action android:name="android.intent.action.SEND" />
<category android:name="android.intent.category.LAUNCHER" /> <category android:name="android.intent.category.LAUNCHER" />
</intent-filter> </intent-filter>
</activity> </activity>
<!-- Add your API key here -->
<meta-data
android:name="com.razorpay.ApiKey"
android:value="rzp_live_3ZQeoFYOxjmXye"
/>
</application> </application>
</manifest> </manifest>

View File

@ -17,8 +17,10 @@ import androidx.compose.ui.platform.setContent
import androidx.compose.ui.res.vectorResource import androidx.compose.ui.res.vectorResource
import androidx.core.view.WindowCompat import androidx.core.view.WindowCompat
import com.shabinder.spotiflyer.home.Home import com.shabinder.spotiflyer.home.Home
import com.shabinder.spotiflyer.navigation.ComposeNavigation
import com.shabinder.spotiflyer.ui.ComposeLearnTheme import com.shabinder.spotiflyer.ui.ComposeLearnTheme
import com.shabinder.spotiflyer.ui.appNameStyle import com.shabinder.spotiflyer.ui.appNameStyle
import com.shabinder.spotiflyer.utils.requestStoragePermission
import dev.chrisbanes.accompanist.insets.ProvideWindowInsets import dev.chrisbanes.accompanist.insets.ProvideWindowInsets
import dev.chrisbanes.accompanist.insets.statusBarsHeight import dev.chrisbanes.accompanist.insets.statusBarsHeight
@ -43,11 +45,22 @@ class MainActivity : AppCompatActivity() {
modifier = Modifier.fillMaxWidth() modifier = Modifier.fillMaxWidth()
) )
Home() ComposeNavigation()
} }
} }
} }
} }
requestStoragePermission()
}
companion object{
private lateinit var instance: MainActivity
fun getInstance():MainActivity = this.instance
}
init {
instance = this
} }
} }
@ -72,7 +85,7 @@ fun AppBar(
actions = { actions = {
Providers(AmbientContentAlpha provides ContentAlpha.medium) { Providers(AmbientContentAlpha provides ContentAlpha.medium) {
IconButton( IconButton(
onClick = { /* TODO: Open Settings */ } onClick = { /* TODO: Open Preferences*/ }
) { ) {
Icon(Icons.Filled.Settings, tint = Color.Gray) Icon(Icons.Filled.Settings, tint = Color.Gray)
} }

View File

@ -1,20 +1,18 @@
package com.shabinder.spotiflyer.home package com.shabinder.spotiflyer.home
import androidx.compose.foundation.BorderStroke import androidx.compose.foundation.*
import androidx.compose.foundation.Image
import androidx.compose.foundation.background
import androidx.compose.foundation.border
import androidx.compose.foundation.layout.* import androidx.compose.foundation.layout.*
import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.text.KeyboardOptions import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.material.* import androidx.compose.material.*
import androidx.compose.material.AmbientTextStyle
import androidx.compose.material.Icon
import androidx.compose.material.TabDefaults.tabIndicatorOffset import androidx.compose.material.TabDefaults.tabIndicatorOffset
import androidx.compose.material.Text
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.outlined.History import androidx.compose.material.icons.outlined.History
import androidx.compose.material.icons.outlined.Info import androidx.compose.material.icons.outlined.Info
import androidx.compose.material.icons.rounded.History import androidx.compose.material.icons.rounded.*
import androidx.compose.material.icons.rounded.Info
import androidx.compose.material.icons.rounded.InsertLink
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
@ -23,20 +21,22 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Brush import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import androidx.compose.ui.res.imageResource
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import androidx.compose.ui.res.vectorResource import androidx.compose.ui.res.vectorResource
import androidx.compose.ui.text.TextStyle import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.input.KeyboardType import androidx.compose.ui.text.input.KeyboardType
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.navigation.NavController
import androidx.navigation.compose.navigate
import com.shabinder.spotiflyer.R import com.shabinder.spotiflyer.R
import com.shabinder.spotiflyer.ui.SpotiFlyerTypography import com.shabinder.spotiflyer.ui.SpotiFlyerTypography
import com.shabinder.spotiflyer.ui.colorAccent import com.shabinder.spotiflyer.ui.colorAccent
import com.shabinder.spotiflyer.ui.colorPrimary import com.shabinder.spotiflyer.ui.colorPrimary
import com.shabinder.spotiflyer.utils.openPlatform
@Composable @Composable
fun Home(modifier: Modifier = Modifier) { fun Home(navController: NavController, modifier: Modifier = Modifier) {
val viewModel: HomeViewModel = viewModel() val viewModel: HomeViewModel = viewModel()
Column(modifier = modifier) { Column(modifier = modifier) {
@ -46,9 +46,10 @@ fun Home(modifier: Modifier = Modifier) {
AuthenticationBanner(viewModel,modifier) AuthenticationBanner(viewModel,modifier)
SearchBar( SearchPanel(
link, link,
viewModel::updateLink, viewModel::updateLink,
navController,
modifier modifier
) )
@ -61,7 +62,7 @@ fun Home(modifier: Modifier = Modifier) {
) )
when(selectedCategory){ when(selectedCategory){
HomeCategory.About -> AboutColumn(viewModel,modifier) HomeCategory.About -> AboutColumn()
HomeCategory.History -> HistoryColumn() HomeCategory.History -> HistoryColumn()
} }
@ -70,26 +71,131 @@ fun Home(modifier: Modifier = Modifier) {
@Composable @Composable
fun AboutColumn(viewModel: HomeViewModel, modifier: Modifier) { fun AboutColumn(modifier: Modifier = Modifier) {
ScrollableColumn(modifier.fillMaxSize(),contentPadding = PaddingValues(16.dp)) {
Card( Card(
modifier = modifier.padding(8.dp).fillMaxWidth(), modifier = modifier.fillMaxWidth(),
border = BorderStroke(1.dp,Color.Gray) border = BorderStroke(1.dp,Color.Gray)
) { ) {
Column(modifier.padding(8.dp)) { Column(modifier.padding(12.dp)) {
Text( Text(
text = stringResource(R.string.supported_platform), text = stringResource(R.string.supported_platform),
style = SpotiFlyerTypography.body1 style = SpotiFlyerTypography.body1
) )
Spacer(modifier = Modifier.padding(top = 8.dp)) Spacer(modifier = Modifier.padding(top = 12.dp))
Row(horizontalArrangement = Arrangement.Center,modifier = modifier.fillMaxWidth()) { Row(horizontalArrangement = Arrangement.Center,modifier = modifier.fillMaxWidth()) {
Icon(imageVector = vectorResource(id = R.drawable.ic_spotify_logo ),tint = Color.Unspecified) Icon(
imageVector = vectorResource(id = R.drawable.ic_spotify_logo), tint = Color.Unspecified,
modifier = Modifier.clickable(
onClick = { openPlatform("com.spotify.music","http://open.spotify.com") })
)
Spacer(modifier = modifier.padding(start = 24.dp)) Spacer(modifier = modifier.padding(start = 24.dp))
Icon(imageVector = vectorResource(id = R.drawable.ic_gaana ),tint = Color.Unspecified) Icon(imageVector = vectorResource(id = R.drawable.ic_gaana ),tint = Color.Unspecified,
modifier = Modifier.clickable(
onClick = { openPlatform("com.gaana","http://gaana.com") })
)
Spacer(modifier = modifier.padding(start = 24.dp)) Spacer(modifier = modifier.padding(start = 24.dp))
Icon(imageVector = vectorResource(id = R.drawable.ic_youtube),tint = Color.Unspecified) Icon(imageVector = vectorResource(id = R.drawable.ic_youtube),tint = Color.Unspecified,
modifier = Modifier.clickable(
onClick = { openPlatform("com.google.android.youtube","http://m.youtube.com") })
)
} }
} }
} }
Spacer(modifier = Modifier.padding(top = 8.dp))
Card(
modifier = modifier.fillMaxWidth(),
border = BorderStroke(1.dp,Color.Gray)
) {
Column(modifier.padding(12.dp)) {
Text(
text = stringResource(R.string.support_development),
style = SpotiFlyerTypography.body1
)
Spacer(modifier = Modifier.padding(top = 6.dp))
Row(verticalAlignment = Alignment.CenterVertically,
modifier = Modifier.fillMaxWidth().clickable(
onClick = { openPlatform("http://github.com/Shabinder/SpotiFlyer") })
.padding(vertical = 6.dp)
) {
Icon(imageVector = vectorResource(id = R.drawable.ic_github ),tint = Color.LightGray)
Spacer(modifier = Modifier.padding(start = 16.dp))
Column {
Text(
text = stringResource(R.string.github),
style = SpotiFlyerTypography.h6
)
Text(
text = stringResource(R.string.github_star),
style = SpotiFlyerTypography.subtitle2
)
}
}
Row(modifier = modifier.fillMaxWidth().padding(vertical = 6.dp),verticalAlignment = Alignment.CenterVertically) {
Icon(Icons.Rounded.Flag.copy(defaultHeight = 32.dp,defaultWidth = 32.dp))
Spacer(modifier = Modifier.padding(start = 16.dp))
Column {
Text(
text = stringResource(R.string.translate),
style = SpotiFlyerTypography.h6
)
Text(
text = stringResource(R.string.help_us_translate),
style = SpotiFlyerTypography.subtitle2
)
}
}
Row(modifier = modifier.fillMaxWidth().padding(vertical = 6.dp),verticalAlignment = Alignment.CenterVertically) {
Icon(Icons.Rounded.CardGiftcard.copy(defaultHeight = 32.dp,defaultWidth = 32.dp))
Spacer(modifier = Modifier.padding(start = 16.dp))
Column {
Text(
text = stringResource(R.string.donate),
style = SpotiFlyerTypography.h6
)
Text(
text = stringResource(R.string.donate_subtitle),
style = SpotiFlyerTypography.subtitle2
)
}
}
Row(modifier = modifier.fillMaxWidth().padding(vertical = 6.dp),verticalAlignment = Alignment.CenterVertically) {
Icon(Icons.Rounded.Share.copy(defaultHeight = 32.dp,defaultWidth = 32.dp))
Spacer(modifier = Modifier.padding(start = 16.dp))
Column {
Text(
text = stringResource(R.string.share),
style = SpotiFlyerTypography.h6
)
Text(
text = stringResource(R.string.share_subtitle),
style = SpotiFlyerTypography.subtitle2
)
}
}
}
}
Row(
horizontalArrangement = Arrangement.Center,
verticalAlignment = Alignment.CenterVertically,
modifier = modifier.fillMaxWidth().padding(8.dp)
) {
Text(
text = stringResource(id = R.string.made_with_love),
color = colorPrimary,
fontSize = 22.sp
)
Spacer(modifier = Modifier.padding(start = 4.dp))
Icon(vectorResource(id = R.drawable.ic_heart),tint = Color.Unspecified)
Spacer(modifier = Modifier.padding(start = 4.dp))
Text(
text = stringResource(id = R.string.in_india),
color = colorPrimary,
fontSize = 22.sp
)
}
}
} }
@Composable @Composable
@ -150,15 +256,16 @@ fun HomeTabBar(
} }
@Composable @Composable
fun SearchBar( fun SearchPanel(
link:String, link:String,
updateLink:(s:String) -> Unit, updateLink:(s:String) -> Unit,
navController: NavController,
modifier: Modifier = Modifier modifier: Modifier = Modifier
){ ){
Column( Column(
horizontalAlignment = Alignment.CenterHorizontally, horizontalAlignment = Alignment.CenterHorizontally,
modifier = modifier.padding(top = 16.dp,bottom = 16.dp) modifier = modifier.padding(top = 16.dp,)
){ ){
TextField( TextField(
leadingIcon = { leadingIcon = {
@ -182,7 +289,7 @@ fun SearchBar(
) )
OutlinedButton( OutlinedButton(
modifier = Modifier.padding(12.dp).wrapContentWidth(), modifier = Modifier.padding(12.dp).wrapContentWidth(),
onClick = {/*TODO*/}, onClick = {navController.navigate("track_list/$link") },
border = BorderStroke(1.dp, Brush.horizontalGradient(listOf(colorPrimary, colorAccent))) border = BorderStroke(1.dp, Brush.horizontalGradient(listOf(colorPrimary, colorAccent)))
){ ){
Text(text = "Search",style = SpotiFlyerTypography.h6,modifier = Modifier.padding(4.dp)) Text(text = "Search",style = SpotiFlyerTypography.h6,modifier = Modifier.padding(4.dp))

View File

@ -0,0 +1,37 @@
package com.shabinder.spotiflyer.navigation
import androidx.compose.runtime.Composable
import androidx.navigation.NavType
import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable
import androidx.navigation.compose.navArgument
import androidx.navigation.compose.rememberNavController
import com.shabinder.spotiflyer.home.Home
import com.shabinder.spotiflyer.tracklist.TrackList
@Composable
fun ComposeNavigation() {
val navController = rememberNavController()
NavHost(
navController = navController,
startDestination = "home"
) {
//HomeScreen - Starting Point
composable("home") {
Home(navController = navController)
}
//Track list Screen
//Argument `link` = Link of Track/Album/Playlist
composable(
"track_list/{link}",
arguments = listOf(navArgument("link") { type = NavType.StringType })
) {
TrackList(
link = it.arguments?.getString("link") ?: "error",
navController = navController
)
}
}
}

View File

@ -0,0 +1,10 @@
package com.shabinder.spotiflyer.tracklist
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.navigation.NavController
@Composable
fun TrackList(link: String,navController: NavController, modifier: Modifier = Modifier){
}

View File

@ -1,5 +1,6 @@
package com.shabinder.spotiflyer.ui package com.shabinder.spotiflyer.ui
import androidx.compose.material.MaterialTheme
import androidx.compose.material.Typography import androidx.compose.material.Typography
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.TextStyle import androidx.compose.ui.text.TextStyle
@ -53,9 +54,11 @@ val SpotiFlyerTypography = Typography(
), ),
h6 = TextStyle( h6 = TextStyle(
fontFamily = Montserrat, fontFamily = Montserrat,
fontSize = 20.sp, fontSize = 18.sp,
fontWeight = FontWeight.SemiBold, fontWeight = FontWeight.Medium,
lineHeight = 24.sp lineHeight = 26.sp,
letterSpacing = 0.5.sp
), ),
subtitle1 = TextStyle( subtitle1 = TextStyle(
fontFamily = Montserrat, fontFamily = Montserrat,
@ -76,7 +79,8 @@ val SpotiFlyerTypography = Typography(
fontSize = 16.sp, fontSize = 16.sp,
fontWeight = FontWeight.Medium, fontWeight = FontWeight.Medium,
lineHeight = 20.sp, lineHeight = 20.sp,
letterSpacing = 0.15.sp letterSpacing = 0.15.sp,
color = colorAccent
), ),
body2 = TextStyle( body2 = TextStyle(
fontFamily = Montserrat, fontFamily = Montserrat,

View File

@ -0,0 +1,49 @@
package com.shabinder.spotiflyer.utils
import android.Manifest
import android.content.Intent
import android.content.pm.PackageManager
import android.net.Uri
import android.os.Build
import android.util.Log
import com.shabinder.spotiflyer.BuildConfig
import com.shabinder.spotiflyer.MainActivity
/*
* Only Log in Debug Mode
**/
fun log(tag:String? = "SpotiFlyer",message:String? = "null"){
if (BuildConfig.DEBUG) {
Log.d(tag ?: "spotiflyer", message ?: "null")
}
}
fun MainActivity.requestStoragePermission() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
this.requestPermissions(
arrayOf(Manifest.permission.WRITE_EXTERNAL_STORAGE),
786
)
}
}
fun openPlatform(packageName:String, websiteAddress:String){
val manager: PackageManager = mainActivity.packageManager
try {
val intent = manager.getLaunchIntentForPackage(packageName)
?: throw PackageManager.NameNotFoundException()
intent.addCategory(Intent.CATEGORY_LAUNCHER)
mainActivity.startActivity(intent)
} catch (e: PackageManager.NameNotFoundException) {
val uri: Uri =
Uri.parse(websiteAddress)
val intent = Intent(Intent.ACTION_VIEW, uri)
mainActivity.startActivity(intent)
}
}
fun openPlatform(websiteAddress:String){
val uri = Uri.parse(websiteAddress)
val intent = Intent(Intent.ACTION_VIEW, uri)
mainActivity.startActivity(intent)
}

View File

@ -0,0 +1,6 @@
package com.shabinder.spotiflyer.utils
import com.shabinder.spotiflyer.MainActivity
val mainActivity
get() = MainActivity.getInstance()

View File

@ -3,4 +3,15 @@
<string name="home_about">About</string> <string name="home_about">About</string>
<string name="home_history">History</string> <string name="home_history">History</string>
<string name="supported_platform">Supported Platforms</string> <string name="supported_platform">Supported Platforms</string>
<string name="support_development">Support Development</string>
<string name="github_star">Star / Fork the project on Github.</string>
<string name="github">GitHub</string>
<string name="translate">Translate</string>
<string name="help_us_translate">Help us translate this app in your local language.</string>
<string name="donate">Donate</string>
<string name="donate_subtitle">If you think I deserve to get paid for my work, you can leave me some money here.</string>
<string name="share">Share</string>
<string name="share_subtitle">Share this app with your friends and family.</string>
<string name="made_with_love">Made with</string>
<string name="in_india">in India</string>
</resources> </resources>